6#ifndef MD4QT_MD_HTML_HPP_INCLUDED
7#define MD4QT_MD_HTML_HPP_INCLUDED
38 const typename Trait::String &hrefForRefBackImage,
39 bool wrappedInArticle =
true)
57 for (
const auto &s : styles) {
60 m_html.push_back(Trait::latin1ToString(
"<strong>"));
64 m_html.push_back(Trait::latin1ToString(
"<em>"));
68 m_html.push_back(Trait::latin1ToString(
"<del>"));
80 for (
const auto &s : styles) {
83 m_html.push_back(Trait::latin1ToString(
"</strong>"));
87 m_html.push_back(Trait::latin1ToString(
"</em>"));
91 m_html.push_back(Trait::latin1ToString(
"</del>"));
104 m_html.push_back(Trait::latin1ToString(
"\n"));
129 m_html.push_back(m->
isInline() ? Trait::latin1ToString(
"$") : Trait::latin1ToString(
"$$"));
131 m_html.push_back(m->
isInline() ? Trait::latin1ToString(
"$") : Trait::latin1ToString(
"$$"));
143 m_html.push_back(Trait::latin1ToString(
"<br />"));
156 m_html.push_back(Trait::latin1ToString(
"<p dir=\"auto\">"));
162 m_html.push_back(Trait::latin1ToString(
"</p>"));
172 m_html.push_back(Trait::latin1ToString(
"\n"));
175 switch (h->
level()) {
182 onHeading(h, Trait::latin1ToString(
"h") + Trait::latin1ToString(std::to_string(h->
level()).c_str()));
190 m_html.push_back(Trait::latin1ToString(
"\n"));
200 m_html.push_back(Trait::latin1ToString(
"\n"));
201 m_html.push_back(Trait::latin1ToString(
"<pre><code"));
203 if (!c->
syntax().isEmpty()) {
204 m_html.push_back(Trait::latin1ToString(
" class=\"language-"));
206 m_html.push_back(Trait::latin1ToString(
"\""));
209 m_html.push_back(Trait::latin1ToString(
">"));
211 m_html.push_back(Trait::latin1ToString(
"</code></pre>"));
212 m_html.push_back(Trait::latin1ToString(
"\n"));
224 m_html.push_back(Trait::latin1ToString(
"<code>"));
228 m_html.push_back(Trait::latin1ToString(
"</code>"));
240 m_html.push_back(Trait::latin1ToString(
"\n<blockquote>"));
246 m_html.push_back(Trait::latin1ToString(
"</blockquote>\n"));
256 m_html.push_back(Trait::latin1ToString(
"\n"));
262 for (
auto it = l->
items().cbegin(), last = l->
items().cend(); it != last; ++it) {
267 type = item->listType();
271 m_html.push_back(Trait::latin1ToString(
"<ol"));
273 if (item->isTaskList()) {
274 m_html.push_back(Trait::latin1ToString(
" class=\"contains-task-list\""));
277 m_html.push_back(Trait::latin1ToString(
" dir=\"auto\">\n"));
281 m_html.push_back(Trait::latin1ToString(
"<ul"));
283 if (item->isTaskList()) {
284 m_html.push_back(Trait::latin1ToString(
" class=\"contains-task-list\""));
287 m_html.push_back(Trait::latin1ToString(
" dir=\"auto\">\n"));
301 m_html.push_back(Trait::latin1ToString(
"</ol>\n"));
303 m_html.push_back(Trait::latin1ToString(
"</ul>\n"));
315 m_html.push_back(Trait::latin1ToString(
"\n"));
320 m_html.push_back(Trait::latin1ToString(
"<table><thead><tr>\n"));
325 for (
auto th = (*t->
rows().cbegin())->cells().cbegin(), last = (*t->
rows().cbegin())->cells().cend(); th != last; ++th) {
327 m_html.push_back(Trait::latin1ToString(
"<th"));
329 m_html.push_back(Trait::latin1ToString(
" dir=\"auto\">\n"));
335 m_html.push_back(Trait::latin1ToString(
"\n</th>\n"));
342 m_html.push_back(Trait::latin1ToString(
"</tr></thead><tbody>\n"));
345 for (
auto r = std::next(t->
rows().cbegin()), rlast = t->
rows().cend(); r != rlast; ++r) {
347 m_html.push_back(Trait::latin1ToString(
"<tr>\n"));
352 for (
auto c = (*r)->cells().cbegin(), clast = (*r)->cells().cend(); c != clast; ++c) {
354 m_html.push_back(Trait::latin1ToString(
"\n<td"));
356 m_html.push_back(Trait::latin1ToString(
" dir=\"auto\">\n"));
362 m_html.push_back(Trait::latin1ToString(
"\n</td>\n"));
373 for (; i < columns; ++i) {
374 m_html.push_back(Trait::latin1ToString(
"<td dir=\"auto\"></td>"));
377 m_html.push_back(Trait::latin1ToString(
"\n</tr>\n"));
382 m_html.push_back(Trait::latin1ToString(
"</tbody></table>"));
387 m_html.push_back(Trait::latin1ToString(
"\n"));
397 m_html.push_back(Trait::latin1ToString(
"\n<div id=\""));
399 m_html.push_back(Trait::latin1ToString(
"\"></div>\n"));
423 m_html.push_back(Trait::latin1ToString(
"<hr />"));
432 typename Trait::String url = l->
url();
434 const auto lit = this->
m_doc->labeledLinks().find(url);
436 if (lit != this->
m_doc->labeledLinks().cend()) {
437 url = lit->second->url();
440 if (std::find(this->
m_anchors.cbegin(), this->m_anchors.cend(), url) != this->m_anchors.cend()) {
441 url = Trait::latin1ToString(
"#") + url;
442 }
else if (url.startsWith(Trait::latin1ToString(
"#")) &&
443 this->m_doc->labeledHeadings().find(url) == this->m_doc->labeledHeadings().cend()) {
445 const auto sp = path.
lastIndexOf(Trait::latin1ToString(
"/"));
447 const auto p = url.
indexOf(path) - 1;
448 url.remove(p, url.length() - p);
454 m_html.push_back(Trait::latin1ToString(
"<a href=\""));
456 m_html.push_back(Trait::latin1ToString(
"\">"));
459 if (l->
p() && !l->
p()->isEmpty()) {
461 }
else if (!l->
img()->isEmpty()) {
465 }
else if (!l->
text().isEmpty()) {
476 m_html.push_back(Trait::latin1ToString(
"</a>"));
490 m_html.push_back(Trait::latin1ToString(
"<img src=\""));
492 m_html.push_back(Trait::latin1ToString(
"\" alt=\""));
494 m_html.push_back(Trait::latin1ToString(
"\" style=\"max-width:100%;\" />"));
505 const auto fit = this->
m_doc->footnotesMap().find(ref->
id());
507 if (fit != this->
m_doc->footnotesMap().cend()) {
508 const auto r = std::find_if(
m_fns.begin(),
m_fns.end(), [&ref](
const auto &stuff) {
509 return ref->id() == stuff.m_id;
515 m_html.push_back(Trait::latin1ToString(
"<sup>"));
516 m_html.push_back(Trait::latin1ToString(
"<a href=\"#"));
518 m_html.push_back(Trait::latin1ToString(
"\" id=\"ref-"));
520 m_html.push_back(Trait::latin1ToString(
"-"));
523 if (r ==
m_fns.end()) {
525 m_html.push_back(Trait::latin1ToString(
"1"));
529 m_html.push_back(Trait::latin1ToString(std::to_string(++(r->m_current)).c_str()));
538 m_html.push_back(Trait::latin1ToString(
"\">"));
541 if (r ==
m_fns.end()) {
543 m_html.push_back(Trait::latin1ToString(std::to_string(
m_fns.size() + 1).c_str()));
546 m_fns.push_back({ref->
id(), 1, 0});
548 m_html.push_back(Trait::latin1ToString(std::to_string(std::distance(
m_fns.begin(), r) + 1).c_str()));
551 m_html.push_back(Trait::latin1ToString(
"</a></sup>"));
567 m_html.push_back(Trait::latin1ToString(
"<li"));
571 Trait::latin1ToString(
" class=\"task-list-item\"><input "
572 "type=\"checkbox\" id=\"\" disabled=\"\" class=\"task-list-item-checkbox\""));
575 m_html.push_back(Trait::latin1ToString(
" checked=\"\""));
580 m_html.push_back(Trait::latin1ToString(
" value=\""));
581 m_html.push_back(Trait::latin1ToString(std::to_string(i->
startNumber()).c_str()));
582 m_html.push_back(Trait::latin1ToString(
"\""));
585 m_html.push_back(Trait::latin1ToString(
">\n"));
591 m_html.push_back(Trait::latin1ToString(
"</li>\n"));
600 const typename Trait::String &ht)
603 m_html.push_back(Trait::latin1ToString(
"<"));
606 m_html.push_back(Trait::latin1ToString(
" dir=\"auto\">"));
609 if (h->
text().get()) {
614 m_html.push_back(Trait::latin1ToString(
"</"));
616 m_html.push_back(Trait::latin1ToString(
">"));
621 virtual void onFootnotes(
const typename Trait::String &hrefForRefBackImage)
623 if (!
m_fns.empty()) {
624 m_html.push_back(Trait::latin1ToString(
"<section class=\"footnotes\"><ol dir=\"auto\">"));
629 const auto tmpm_fns =
m_fns;
632 for (
const auto &
id : tmpm_fns) {
633 const auto fit = this->
m_doc->footnotesMap().find(
id.m_id);
635 if (fit != this->
m_doc->footnotesMap().cend()) {
643 for (
const auto &
id :
m_fns) {
644 m_html.push_back(Trait::latin1ToString(
"<li id=\""));
645 m_html.push_back(
id.m_id);
646 m_html.push_back(Trait::latin1ToString(
"\">"));
649 const auto fit = this->
m_doc->footnotesMap().find(
id.m_id);
651 if (fit != this->
m_doc->footnotesMap().cend()) {
654 if (!hrefForRefBackImage.isEmpty()) {
655 typename Trait::String backRef;
656 long long int backRefPos =
m_html.endsWith(Trait::latin1ToString(
"</p>")) ? 4 : 0;
658 for (
long long int i = 1; i <=
id.m_count; ++i) {
659 backRef.push_back(Trait::latin1ToString(
"<a href=\"#ref-"));
660 backRef.push_back(
id.m_id);
661 backRef.push_back(Trait::latin1ToString(
"-"));
662 backRef.push_back(Trait::latin1ToString(std::to_string(i).c_str()));
663 backRef.push_back(Trait::latin1ToString(
"\"><img src=\""));
664 backRef.push_back(hrefForRefBackImage);
665 backRef.push_back(Trait::latin1ToString(
"\" /></a>"));
671 m_html.push_back(Trait::latin1ToString(
"</li>"));
675 if (!
m_fns.empty()) {
676 m_html.push_back(Trait::latin1ToString(
"</ol></section>\n"));
683 typename Trait::String html;
686 html.push_back(Trait::latin1ToString(
" id=\""));
687 auto label = h->
label();
688 if (label.
startsWith(Trait::latin1ToString(
"#"))) {
691 html.push_back(label);
692 html.push_back(Trait::latin1ToString(
"\""));
702 tmp.replace(Trait::latin1ToChar(
'&'), Trait::latin1ToString(
"&"));
703 tmp.replace(Trait::latin1ToChar(
'<'), Trait::latin1ToString(
"<"));
704 tmp.replace(Trait::latin1ToChar(
'>'), Trait::latin1ToString(
">"));
712 typename Trait::String html;
716 html.push_back(Trait::latin1ToString(
" align=\"left\""));
720 html.push_back(Trait::latin1ToString(
" align=\"center\""));
724 html.push_back(Trait::latin1ToString(
" align=\"right\""));
755 typename Trait::template Vector<FootnoteRefStuff>
m_fns;
761template<
class Trait,
class HtmlVisitor = details::HtmlVisitor<Trait>>
762typename Trait::String
767 bool wrapInBodyTag =
true,
769 const typename Trait::String &hrefForRefBackImage = {},
771 bool wrapInArticle =
true)
773 typename Trait::String html;
776 html.push_back(Trait::latin1ToString(
"<!DOCTYPE html>\n<html><head></head><body>\n"));
780 html.push_back(Trait::latin1ToString(
"<article class=\"markdown-body\">"));
785 html.push_back(visitor.toHtml(doc, hrefForRefBackImage, wrapInArticle));
788 html.push_back(Trait::latin1ToString(
"</article>\n"));
792 html.push_back(Trait::latin1ToString(
"</body></html>\n"));
const Trait::String & label() const
const Items & items() const
const Trait::String & syntax() const
const Trait::String & text() const
ParagraphSharedPointer text() const
const Trait::String & label() const
const Styles & closeStyles() const
const Styles & openStyles() const
typename Trait::template Vector< StyleDelim > Styles
Type of list of emphasis.
const Trait::String & text() const
Not parsed text of link's description.
ParagraphSharedPointer p() const
const Trait::String & url() const
ImageSharedPointer img() const
ListType listType() const
ListType
Type of the list.
const Trait::String & expr() const
const Trait::String & text() const
const Rows & rows() const
Alignment columnAlignment(int idx) const
const Trait::String & text() const
Visitor interface to walk through Document.
virtual void onFootnote(Footnote< Trait > *f)
Handle footnote.
virtual void onListItem(ListItem< Trait > *i, bool first)
Handle list item.
virtual void onBlockquote(Blockquote< Trait > *b)
Handle blockquote.
virtual void onTableCell(TableCell< Trait > *c)
Handle table cell.
Trait::template Vector< typename Trait::String > m_anchors
All available m_anchors in the document.
std::shared_ptr< Document< Trait > > m_doc
Document.
virtual void onParagraph(Paragraph< Trait > *p, bool wrap)
Handle paragraph.
void process(std::shared_ptr< Document< Trait > > d)
Walk through the document.
HTML visitor interface to walk through Document.
void onList(List< Trait > *l) override
Handle list.
void onAddLineEnding() override
Handle new line in HTML.
virtual void openStyle(const typename ItemWithOpts< Trait >::Styles &styles)
Insert into HTML tags for opening styles.
Trait::template Vector< FootnoteRefStuff > m_fns
Vector of processed footnotes references.
virtual Trait::String tableAlignmentToHtml(typename Table< Trait >::Alignment a)
void onListItem(ListItem< Trait > *i, bool first) override
Handle list item.
void onLineBreak(LineBreak< Trait > *) override
Handle line break.
void onLink(Link< Trait > *l) override
Handle link.
void onAnchor(Anchor< Trait > *a) override
Handle anchor.
bool m_dontIncrementFootnoteCount
Just process footnote references and don't increment count number.
Trait::String m_html
HTML content.
void onBlockquote(Blockquote< Trait > *b) override
Handle blockquote.
virtual void closeStyle(const typename ItemWithOpts< Trait >::Styles &styles)
Insert into HTML tags for closing styles.
virtual Trait::String toHtml(std::shared_ptr< Document< Trait > > doc, const typename Trait::String &hrefForRefBackImage, bool wrappedInArticle=true)
Walk through the document.
void onInlineCode(Code< Trait > *c) override
Handle inline code.
void onImage(Image< Trait > *i) override
Handle image.
bool m_justCollectFootnoteRefs
Just collect footnote references?
void onText(Text< Trait > *t) override
Handle text item.
virtual Trait::String prepareTextForHtml(const typename Trait::String &t)
Prepare text to insert into HTML content.
virtual void onFootnotes(const typename Trait::String &hrefForRefBackImage)
Handle footnotes.
void onTable(Table< Trait > *t) override
Handle table.
bool m_isWrappedInArticle
Is this HTML wrapped in artcile tag?
void onMath(Math< Trait > *m) override
Handle LaTeX math expression.
~HtmlVisitor() override=default
void onCode(Code< Trait > *c) override
Handle code block.
virtual Trait::String headingIdToHtml(Heading< Trait > *h)
virtual void onHeading(Heading< Trait > *h, const typename Trait::String &ht)
Handle heading.
void onRawHtml(RawHtml< Trait > *h) override
Handle raw HTML.
void onFootnoteRef(FootnoteRef< Trait > *ref) override
Handle footnote reference.
void onHeading(Heading< Trait > *h) override
Handle heading.
void onParagraph(Paragraph< Trait > *p, bool wrap) override
Handle paragraph.
void onHorizontalLine(HorizontalLine< Trait > *) override
Handle horizontal line.
@ StrikethroughText
Strikethrough.
Trait::String toHtml(std::shared_ptr< Document< Trait > > doc, bool wrapInBodyTag=true, const typename Trait::String &hrefForRefBackImage={}, bool wrapInArticle=true)
Convert Document to HTML.
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
qsizetype length() const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const