diff options
| author | Felix (xq) Queißner <git@mq32.de> | 2020-06-23 00:35:41 +0200 |
|---|---|---|
| committer | Felix (xq) Queißner <git@mq32.de> | 2020-06-23 00:35:41 +0200 |
| commit | 0860a8ec32fd01b6fdea92e1e6a80de096e2e694 (patch) | |
| tree | b858ca1d88bad6050f51d9a413b48f74b1a21545 /src/renderers/markdownrenderer.cpp | |
| parent | 75ec461eeaa851cb5c53f4cfffc434e3e529ed1d (diff) | |
| download | kristall-0860a8ec32fd01b6fdea92e1e6a80de096e2e694.tar.gz | |
Starts to implement new markdown rendering
Diffstat (limited to 'src/renderers/markdownrenderer.cpp')
| -rw-r--r-- | src/renderers/markdownrenderer.cpp | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/src/renderers/markdownrenderer.cpp b/src/renderers/markdownrenderer.cpp new file mode 100644 index 0000000..1c53a2f --- /dev/null +++ b/src/renderers/markdownrenderer.cpp @@ -0,0 +1,267 @@ +#include "markdownrenderer.hpp" + +#include "textstyleinstance.hpp" + +#include <cmark.h> +#include <node.h> +#include <cassert> + +#include <QDebug> +#include <QTextCursor> + +//static char const *nodeToStr(cmark_node_type type) +//{ +// switch (type) +// { +// case CMARK_NODE_DOCUMENT: +// return "CMARK_NODE_DOCUMENT"; +// case CMARK_NODE_BLOCK_QUOTE: +// return "CMARK_NODE_BLOCK_QUOTE"; +// case CMARK_NODE_LIST: +// return "CMARK_NODE_LIST"; +// case CMARK_NODE_ITEM: +// return "CMARK_NODE_ITEM"; +// case CMARK_NODE_CODE_BLOCK: +// return "CMARK_NODE_CODE_BLOCK"; +// case CMARK_NODE_HTML_BLOCK: +// return "CMARK_NODE_HTML_BLOCK"; +// case CMARK_NODE_CUSTOM_BLOCK: +// return "CMARK_NODE_CUSTOM_BLOCK"; +// case CMARK_NODE_PARAGRAPH: +// return "CMARK_NODE_PARAGRAPH"; +// case CMARK_NODE_HEADING: +// return "CMARK_NODE_HEADING"; +// case CMARK_NODE_THEMATIC_BREAK: +// return "CMARK_NODE_THEMATIC_BREAK"; +// case CMARK_NODE_TEXT: +// return "CMARK_NODE_TEXT"; +// case CMARK_NODE_SOFTBREAK: +// return "CMARK_NODE_SOFTBREAK"; +// case CMARK_NODE_LINEBREAK: +// return "CMARK_NODE_LINEBREAK"; +// case CMARK_NODE_CODE: +// return "CMARK_NODE_CODE"; +// case CMARK_NODE_HTML_INLINE: +// return "CMARK_NODE_HTML_INLINE"; +// case CMARK_NODE_CUSTOM_INLINE: +// return "CMARK_NODE_CUSTOM_INLINE"; +// case CMARK_NODE_EMPH: +// return "CMARK_NODE_EMPH"; +// case CMARK_NODE_STRONG: +// return "CMARK_NODE_STRONG"; +// case CMARK_NODE_LINK: +// return "CMARK_NODE_LINK"; +// case CMARK_NODE_IMAGE: +// return "CMARK_NODE_IMAGE"; +// } +// return "UNKNOWN"; +//}; + +struct RenderState +{ + QTextCursor cursor; + + QUrl root_url; + DocumentStyle const *style; + DocumentOutlineModel *outline; + TextStyleInstance text_style; +}; + +static void renderNode(RenderState &state, cmark_node const &node); + +static void renderChildren(RenderState &state, cmark_node const & node) +{ + for (auto child = node.first_child; child != nullptr; child = child->next) + { + renderNode(state, *child); + } +} + +/* Leaf Nodes +* * CMARK_NODE_HTML_BLOCK +* * CMARK_NODE_THEMATIC_BREAK +* * CMARK_NODE_CODE_BLOCK +* * CMARK_NODE_TEXT +* * CMARK_NODE_SOFTBREAK +* * CMARK_NODE_LINEBREAK +* * CMARK_NODE_CODE +* * CMARK_NODE_HTML_INLINE +*/ + +static QString extractNodeText(cmark_node const &node) +{ + return QString::fromUtf8((char const*)node.data, node.len); +} + +static void renderNode(RenderState &state, cmark_node const & node) +{ + auto & cursor = state.cursor; + + switch (node.type) + { + case CMARK_NODE_DOCUMENT: + { + renderChildren(state, node); + break; + } + + case CMARK_NODE_BLOCK_QUOTE: + { + qDebug() << "CMARK_NODE_BLOCK_QUOTE"; + break; + } + case CMARK_NODE_LIST: + { + auto fmt = cursor.blockFormat(); + cursor.insertList(QTextListFormat::ListDisc); + renderChildren(state, node); + cursor.setBlockFormat(fmt); + break; + } + case CMARK_NODE_ITEM: + { + renderChildren(state, node); + break; + } + case CMARK_NODE_CODE_BLOCK: + { + qDebug() << "CMARK_NODE_CODE_BLOCK"; + break; + } + case CMARK_NODE_HTML_BLOCK: + { + qDebug() << "CMARK_NODE_HTML_BLOCK"; + break; + } + case CMARK_NODE_CUSTOM_BLOCK: + { + qDebug() << "CMARK_NODE_CUSTOM_BLOCK"; + break; + } + case CMARK_NODE_PARAGRAPH: + { + cursor.insertBlock(); + renderChildren(state, node); + break; + } + case CMARK_NODE_HEADING: + { + cursor.insertBlock(); + switch(node.as.heading.level) { + case 1: cursor.setCharFormat(state.text_style.standard_h1); break; + case 2: cursor.setCharFormat(state.text_style.standard_h2); break; + case 3: cursor.setCharFormat(state.text_style.standard_h3); break; + case 4: cursor.setCharFormat(state.text_style.standard_h3); break; + case 5: cursor.setCharFormat(state.text_style.standard_h3); break; + case 6: cursor.setCharFormat(state.text_style.standard_h3); break; + + default: qDebug() << "heading" << node.as.heading.level; break; + } + + switch(node.as.heading.level) { + case 1: state.outline->appendH1("Unknown H1", QString { }); break; + case 2: state.outline->appendH2("Unknown H2", QString { }); break; + case 3: state.outline->appendH3("Unknown H3", QString { }); break; + } + + renderChildren(state, node); + cursor.setCharFormat(state.text_style.standard); + break; + } + case CMARK_NODE_THEMATIC_BREAK: + { + qDebug() << "CMARK_NODE_THEMATIC_BREAK"; + break; + } + case CMARK_NODE_TEXT: + { + cursor.insertText(extractNodeText(node)); + break; + } + case CMARK_NODE_SOFTBREAK: + { + qDebug() << "CMARK_NODE_SOFTBREAK"; + break; + } + case CMARK_NODE_LINEBREAK: + { + qDebug() << "CMARK_NODE_LINEBREAK"; + break; + } + case CMARK_NODE_CODE: + { + qDebug() << "CMARK_NODE_CODE"; + break; + } + case CMARK_NODE_HTML_INLINE: + { + qDebug() << "CMARK_NODE_HTML_INLINE"; + break; + } + case CMARK_NODE_CUSTOM_INLINE: + { + qDebug() << "CMARK_NODE_CUSTOM_INLINE"; + break; + } + case CMARK_NODE_EMPH: + { + qDebug() << "CMARK_NODE_EMPH"; + break; + } + case CMARK_NODE_STRONG: + { + qDebug() << "CMARK_NODE_STRONG"; + break; + } + case CMARK_NODE_LINK: + { + // TODO: Implementing linking + // cursor.insertText(QString::fromUtf8((char*)node.as.link.title)); + // qDebug() << "CMARK_NODE_LINK" << (char*)node.as.link.url; + renderChildren(state, node); + break; + } + case CMARK_NODE_IMAGE: + { + qDebug() << "CMARK_NODE_IMAGE"; + break; + } + } +} + +std::unique_ptr<QTextDocument> MarkdownRenderer::render( + QByteArray const &input, + QUrl const &root_url, + DocumentStyle const &style, + DocumentOutlineModel &outline) +{ + + std::unique_ptr<cmark_node, decltype(&cmark_node_free)> md_root{ + cmark_parse_document(input.data(), input.size(), 0), + &cmark_node_free, + }; + if (not md_root) + return nullptr; + + qDebug() << md_root.get(); + + auto doc = std::make_unique<QTextDocument>(); + doc->setDocumentMargin(style.margin); + doc->setIndentWidth(20); + + outline.beginBuild(); + + RenderState state = { + QTextCursor { doc.get() }, + root_url, + &style, + &outline, + TextStyleInstance { style }, + }; + + renderNode(state, *md_root); + + outline.endBuild(); + + return doc; +} |
