6#ifndef MD4QT_MD_HTML_HPP_INCLUDED
7#define MD4QT_MD_HTML_HPP_INCLUDED
28 typename Trait::String html;
31 html.push_back(Trait::latin1ToString(
" id=\""));
32 auto label = h->
label();
33 if (label.
startsWith(Trait::latin1ToString(
"#"))) {
36 html.push_back(label);
37 html.push_back(Trait::latin1ToString(
"\""));
48 tmp.replace(Trait::latin1ToChar(
'&'), Trait::latin1ToString(
"&"));
49 tmp.replace(Trait::latin1ToChar(
'<'), Trait::latin1ToString(
"<"));
50 tmp.replace(Trait::latin1ToChar(
'>'), Trait::latin1ToString(
">"));
59 typename Trait::String html;
63 html.push_back(Trait::latin1ToString(
" align=\"left\""));
67 html.push_back(Trait::latin1ToString(
" align=\"center\""));
71 html.push_back(Trait::latin1ToString(
" align=\"right\""));
95 const typename Trait::String &hrefForRefBackImage,
96 bool wrappedInArticle =
true)
114 for (
const auto &s : styles) {
117 m_html.push_back(Trait::latin1ToString(
"<strong>"));
121 m_html.push_back(Trait::latin1ToString(
"<em>"));
125 m_html.push_back(Trait::latin1ToString(
"<del>"));
137 for (
const auto &s : styles) {
140 m_html.push_back(Trait::latin1ToString(
"</strong>"));
144 m_html.push_back(Trait::latin1ToString(
"</em>"));
148 m_html.push_back(Trait::latin1ToString(
"</del>"));
161 m_html.push_back(Trait::latin1ToString(
"\n"));
186 m_html.push_back(m->
isInline() ? Trait::latin1ToString(
"$") : Trait::latin1ToString(
"$$"));
188 m_html.push_back(m->
isInline() ? Trait::latin1ToString(
"$") : Trait::latin1ToString(
"$$"));
200 m_html.push_back(Trait::latin1ToString(
"<br />"));
213 m_html.push_back(Trait::latin1ToString(
"<p dir=\"auto\">"));
219 m_html.push_back(Trait::latin1ToString(
"</p>"));
229 m_html.push_back(Trait::latin1ToString(
"\n"));
232 switch (h->
level()) {
239 onHeading(h, Trait::latin1ToString(
"h") + Trait::latin1ToString(std::to_string(h->
level()).c_str()));
247 m_html.push_back(Trait::latin1ToString(
"\n"));
257 m_html.push_back(Trait::latin1ToString(
"\n"));
258 m_html.push_back(Trait::latin1ToString(
"<pre><code"));
260 if (!c->
syntax().isEmpty()) {
261 m_html.push_back(Trait::latin1ToString(
" class=\"language-"));
263 m_html.push_back(Trait::latin1ToString(
"\""));
266 m_html.push_back(Trait::latin1ToString(
">"));
268 m_html.push_back(Trait::latin1ToString(
"</code></pre>"));
269 m_html.push_back(Trait::latin1ToString(
"\n"));
281 m_html.push_back(Trait::latin1ToString(
"<code>"));
285 m_html.push_back(Trait::latin1ToString(
"</code>"));
297 m_html.push_back(Trait::latin1ToString(
"\n<blockquote>"));
303 m_html.push_back(Trait::latin1ToString(
"</blockquote>\n"));
313 m_html.push_back(Trait::latin1ToString(
"\n"));
319 for (
auto it = l->
items().cbegin(), last = l->
items().cend(); it != last; ++it) {
324 type = item->listType();
328 m_html.push_back(Trait::latin1ToString(
"<ol"));
330 if (item->isTaskList()) {
331 m_html.push_back(Trait::latin1ToString(
" class=\"contains-task-list\""));
334 m_html.push_back(Trait::latin1ToString(
" dir=\"auto\">\n"));
338 m_html.push_back(Trait::latin1ToString(
"<ul"));
340 if (item->isTaskList()) {
341 m_html.push_back(Trait::latin1ToString(
" class=\"contains-task-list\""));
344 m_html.push_back(Trait::latin1ToString(
" dir=\"auto\">\n"));
358 m_html.push_back(Trait::latin1ToString(
"</ol>\n"));
360 m_html.push_back(Trait::latin1ToString(
"</ul>\n"));
372 m_html.push_back(Trait::latin1ToString(
"\n"));
377 m_html.push_back(Trait::latin1ToString(
"<table><thead><tr>\n"));
382 for (
auto th = (*t->
rows().cbegin())->cells().cbegin(), last = (*t->
rows().cbegin())->cells().cend(); th != last; ++th) {
384 m_html.push_back(Trait::latin1ToString(
"<th"));
386 m_html.push_back(Trait::latin1ToString(
" dir=\"auto\">\n"));
392 m_html.push_back(Trait::latin1ToString(
"\n</th>\n"));
399 m_html.push_back(Trait::latin1ToString(
"</tr></thead><tbody>\n"));
402 for (
auto r = std::next(t->
rows().cbegin()), rlast = t->
rows().cend(); r != rlast; ++r) {
404 m_html.push_back(Trait::latin1ToString(
"<tr>\n"));
409 for (
auto c = (*r)->cells().cbegin(), clast = (*r)->cells().cend(); c != clast; ++c) {
411 m_html.push_back(Trait::latin1ToString(
"\n<td"));
413 m_html.push_back(Trait::latin1ToString(
" dir=\"auto\">\n"));
419 m_html.push_back(Trait::latin1ToString(
"\n</td>\n"));
430 for (; i < columns; ++i) {
431 m_html.push_back(Trait::latin1ToString(
"<td dir=\"auto\"></td>"));
434 m_html.push_back(Trait::latin1ToString(
"\n</tr>\n"));
439 m_html.push_back(Trait::latin1ToString(
"</tbody></table>"));
444 m_html.push_back(Trait::latin1ToString(
"\n"));
454 m_html.push_back(Trait::latin1ToString(
"\n<div id=\""));
456 m_html.push_back(Trait::latin1ToString(
"\"></div>\n"));
480 m_html.push_back(Trait::latin1ToString(
"<hr />"));
489 typename Trait::String url = l->
url();
491 const auto lit = this->
m_doc->labeledLinks().find(url);
493 if (lit != this->
m_doc->labeledLinks().cend()) {
494 url = lit->second->url();
497 if (std::find(this->
m_anchors.cbegin(), this->m_anchors.cend(), url) != this->m_anchors.cend()) {
498 url = Trait::latin1ToString(
"#") + url;
499 }
else if (url.startsWith(Trait::latin1ToString(
"#")) &&
500 this->m_doc->labeledHeadings().find(url) == this->m_doc->labeledHeadings().cend()) {
502 const auto sp = path.
lastIndexOf(Trait::latin1ToString(
"/"));
504 const auto p = url.
indexOf(path) - 1;
505 url.remove(p, url.length() - p);
511 m_html.push_back(Trait::latin1ToString(
"<a href=\""));
513 m_html.push_back(Trait::latin1ToString(
"\">"));
516 if (l->
p() && !l->
p()->isEmpty()) {
518 }
else if (!l->
img()->isEmpty()) {
522 }
else if (!l->
text().isEmpty()) {
533 m_html.push_back(Trait::latin1ToString(
"</a>"));
547 m_html.push_back(Trait::latin1ToString(
"<img src=\""));
549 m_html.push_back(Trait::latin1ToString(
"\" alt=\""));
551 m_html.push_back(Trait::latin1ToString(
"\" style=\"max-width:100%;\" />"));
562 const auto fit = this->
m_doc->footnotesMap().find(ref->
id());
564 if (fit != this->
m_doc->footnotesMap().cend()) {
565 const auto r = std::find_if(
m_fns.begin(),
m_fns.end(), [&ref](
const auto &stuff) {
566 return ref->id() == stuff.m_id;
572 m_html.push_back(Trait::latin1ToString(
"<sup>"));
573 m_html.push_back(Trait::latin1ToString(
"<a href=\"#"));
575 m_html.push_back(Trait::latin1ToString(
"\" id=\"ref-"));
577 m_html.push_back(Trait::latin1ToString(
"-"));
580 if (r ==
m_fns.end()) {
582 m_html.push_back(Trait::latin1ToString(
"1"));
586 m_html.push_back(Trait::latin1ToString(std::to_string(++(r->m_current)).c_str()));
595 m_html.push_back(Trait::latin1ToString(
"\">"));
598 if (r ==
m_fns.end()) {
600 m_html.push_back(Trait::latin1ToString(std::to_string(
m_fns.size() + 1).c_str()));
603 m_fns.push_back({ref->
id(), 1, 0});
605 m_html.push_back(Trait::latin1ToString(std::to_string(std::distance(
m_fns.begin(), r) + 1).c_str()));
608 m_html.push_back(Trait::latin1ToString(
"</a></sup>"));
624 m_html.push_back(Trait::latin1ToString(
"<li"));
628 Trait::latin1ToString(
" class=\"task-list-item\"><input "
629 "type=\"checkbox\" id=\"\" disabled=\"\" class=\"task-list-item-checkbox\""));
632 m_html.push_back(Trait::latin1ToString(
" checked=\"\""));
637 m_html.push_back(Trait::latin1ToString(
" value=\""));
638 m_html.push_back(Trait::latin1ToString(std::to_string(i->
startNumber()).c_str()));
639 m_html.push_back(Trait::latin1ToString(
"\""));
642 m_html.push_back(Trait::latin1ToString(
">\n"));
648 m_html.push_back(Trait::latin1ToString(
"</li>\n"));
657 const typename Trait::String &ht)
660 m_html.push_back(Trait::latin1ToString(
"<"));
663 m_html.push_back(Trait::latin1ToString(
" dir=\"auto\">"));
666 if (h->
text().get()) {
671 m_html.push_back(Trait::latin1ToString(
"</"));
673 m_html.push_back(Trait::latin1ToString(
">"));
678 virtual void onFootnotes(
const typename Trait::String &hrefForRefBackImage)
680 if (!
m_fns.empty()) {
681 m_html.push_back(Trait::latin1ToString(
"<section class=\"footnotes\"><ol dir=\"auto\">"));
686 const auto tmpm_fns =
m_fns;
689 for (
const auto &
id : tmpm_fns) {
690 const auto fit = this->
m_doc->footnotesMap().find(
id.m_id);
692 if (fit != this->
m_doc->footnotesMap().cend()) {
700 for (
const auto &
id :
m_fns) {
701 m_html.push_back(Trait::latin1ToString(
"<li id=\""));
702 m_html.push_back(
id.m_id);
703 m_html.push_back(Trait::latin1ToString(
"\">"));
706 const auto fit = this->
m_doc->footnotesMap().find(
id.m_id);
708 if (fit != this->
m_doc->footnotesMap().cend()) {
711 if (!hrefForRefBackImage.isEmpty()) {
712 typename Trait::String backRef;
713 long long int backRefPos =
m_html.endsWith(Trait::latin1ToString(
"</p>")) ? 4 : 0;
715 for (
long long int i = 1; i <=
id.m_count; ++i) {
716 backRef.push_back(Trait::latin1ToString(
"<a href=\"#ref-"));
717 backRef.push_back(
id.m_id);
718 backRef.push_back(Trait::latin1ToString(
"-"));
719 backRef.push_back(Trait::latin1ToString(std::to_string(i).c_str()));
720 backRef.push_back(Trait::latin1ToString(
"\"><img src=\""));
721 backRef.push_back(hrefForRefBackImage);
722 backRef.push_back(Trait::latin1ToString(
"\" /></a>"));
728 m_html.push_back(Trait::latin1ToString(
"</li>"));
732 if (!
m_fns.empty()) {
733 m_html.push_back(Trait::latin1ToString(
"</ol></section>\n"));
758 typename Trait::template Vector<FootnoteRefStuff>
m_fns;
765typename Trait::String
770 bool wrapInBodyTag =
true,
772 const typename Trait::String &hrefForRefBackImage = {},
774 bool wrapInArticle =
true)
776 typename Trait::String html;
779 html.push_back(Trait::latin1ToString(
"<!DOCTYPE html>\n<html><head></head><body>\n"));
783 html.push_back(Trait::latin1ToString(
"<article class=\"markdown-body\">"));
786 details::HtmlVisitor<Trait> visitor;
788 html.push_back(visitor.toHtml(doc, hrefForRefBackImage, wrapInArticle));
791 html.push_back(Trait::latin1ToString(
"</article>\n"));
795 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.
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 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 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.
Trait::String tableAlignmentToHtml(typename Table< Trait >::Alignment a)
Trait::String headingIdToHtml(Heading< Trait > *h)
Trait::String prepareTextForHtml(const typename Trait::String &t)
Prepare text to insert into HTML content.
@ 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