QString HoedownMarkdownConverter::renderAsHtml(MarkdownDocument *document) { QString html; if (document) { HoedownMarkdownDocument *doc = dynamic_cast<HoedownMarkdownDocument*>(document); if (doc->document()) { hoedown_buffer *in = doc->document(); hoedown_buffer *out = hoedown_buffer_new(64); hoedown_renderer *renderer = hoedown_html_renderer_new(0, 16); hoedown_markdown *markdown = hoedown_markdown_new(doc->options(), 16, renderer); hoedown_markdown_render(out, in->data, in->size, markdown); hoedown_markdown_free(markdown); hoedown_html_renderer_free(renderer); html = QString::fromUtf8(hoedown_buffer_cstr(out)); hoedown_buffer_free(out); } } return html; }
char* OxMarkDownToHtml(char* sMarkDown) { hoedown_renderer *renderer; hoedown_document *document; hoedown_buffer *buffer; unsigned int extensions = 0, render_flags = 0; const uint8_t *sHtml; renderer = hoedown_html_renderer_new(render_flags, 0); document = hoedown_document_new(renderer, extensions, 16); buffer = hoedown_buffer_new(16); hoedown_document_render(document, buffer, (const uint8_t *)sMarkDown, strlen(sMarkDown)); sHtml = (char*)OxAllocate(buffer->size + 1); StringCchCopyA(sHtml, buffer->size + 1, buffer->data); hoedown_buffer_reset(buffer); hoedown_html_smartypants(buffer, sHtml, buffer->size); hoedown_buffer_free(buffer); hoedown_document_free(document); hoedown_html_renderer_free(renderer); return sHtml; }
void mdRenderer::render(const QString markdownText) { if(markdownText.isEmpty()) { html =""; return; } QByteArray utf8Data = markdownText.toUtf8(); hoedown_buffer *doc = hoedown_buffer_new(utf8Data.length()); hoedown_buffer_puts(doc, utf8Data.data()); hoedown_buffer *out = hoedown_buffer_new(64); hoedown_renderer *renderer = hoedown_html_renderer_new(0, 16); hoedown_markdown *markdown = hoedown_markdown_new(0, 16, renderer); hoedown_markdown_render(out, doc->data, doc->size, markdown); hoedown_markdown_free(markdown); hoedown_html_renderer_free(renderer); html = QString::fromUtf8(hoedown_buffer_cstr(out)); hoedown_buffer_free(out); html="<!DOCTYPE html> <html> <head> <style type=\"text/css\">"+ style+ "</style>"+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"+ "</head> <body>"+ html+ "</body> </html>"; }
// Converts markdown to html QString Markdown::convert2html(const QString& markdown) { QString html; if ( !markdown.isEmpty() ) { QString markdownClean = parseCustomLinksForHTML(markdown); hoedown_html_flags flags = HOEDOWN_HTML_USE_XHTML; hoedown_extensions extensions = (hoedown_extensions)(HOEDOWN_EXT_BLOCK|HOEDOWN_EXT_SPAN|HOEDOWN_EXT_FLAGS); size_t max_nesting = 16; hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); hoedown_document *document = hoedown_document_new(renderer, extensions, max_nesting); hoedown_buffer *result = hoedown_buffer_new(max_nesting); std::string markdownStr = markdownClean.toStdString(); hoedown_document_render( document, result, reinterpret_cast<const uint8_t*>(&markdownStr[0]), markdownStr.size() ); std::ostringstream convert; for (size_t x = 0; x < result->size; x++) { convert << result->data[x]; } html = QString::fromStdString( convert.str() ); hoedown_buffer_free(result); hoedown_document_free(document); hoedown_html_renderer_free(renderer); } return html; }
// // return html rendered markdown of note text // QString Note::toMarkdownHtml() { hoedown_renderer *renderer = hoedown_html_renderer_new( HOEDOWN_HTML_USE_XHTML, 16 ); hoedown_document *document = hoedown_document_new(renderer, (hoedown_extensions) HOEDOWN_EXT_SPAN, 16); QString str = this->noteText; unsigned char *sequence = (unsigned char*)qstrdup( str.toUtf8().constData() ); int length = strlen( (char*) sequence ); // return an empty string if the note is empty if ( length == 0 ) { return ""; } hoedown_buffer *html = hoedown_buffer_new( length ); // render markdown html hoedown_document_render( document, html, sequence, length ); // get markdown html QString result = QString::fromUtf8( (char*) html->data, html->size ); /* Cleanup */ free(sequence); hoedown_buffer_free(html); hoedown_document_free(document); hoedown_html_renderer_free(renderer); return result; }
QByteArray HoedownMarkdownConverterPrivate::markdown2Html(const QByteArray &markdownText) const { int markdownLength = markdownText.size(); if(markdownLength == 0) { return QByteArray(""); } hoedown_buffer *ib, *ob; hoedown_renderer *renderer = NULL; hoedown_document *document; // malloc ob = hoedown_buffer_new(markdownLength); ib = hoedown_buffer_new(markdownLength); renderer = hoedown_html_renderer_new(HOEDOWN_HTML_USE_XHTML, 0); /* typedef enum hoedown_extensions { // block-level extensions HOEDOWN_EXT_TABLES = (1 << 0), HOEDOWN_EXT_FENCED_CODE = (1 << 1), HOEDOWN_EXT_FOOTNOTES = (1 << 2), // span-level extensions HOEDOWN_EXT_AUTOLINK = (1 << 3), HOEDOWN_EXT_STRIKETHROUGH = (1 << 4), HOEDOWN_EXT_UNDERLINE = (1 << 5), HOEDOWN_EXT_HIGHLIGHT = (1 << 6), HOEDOWN_EXT_QUOTE = (1 << 7), HOEDOWN_EXT_SUPERSCRIPT = (1 << 8), HOEDOWN_EXT_MATH = (1 << 9), // other flags HOEDOWN_EXT_NO_INTRA_EMPHASIS = (1 << 11), HOEDOWN_EXT_SPACE_HEADERS = (1 << 12), HOEDOWN_EXT_MATH_EXPLICIT = (1 << 13), // negative flags HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 14) } hoedown_extensions; */ // 尽可能的指定 document = hoedown_document_new(renderer, HOEDOWN_EXT_TABLES, 16); // put data hoedown_buffer_put(ib, (const uint8_t *) markdownText.toStdString().c_str(), markdownText.size()); // render markdown to html hoedown_document_render(document, ob, ib->data, ib->size); QByteArray html((const char*)ob->data, ob->size); // free hoedown_buffer_free(ib); hoedown_document_free(document); hoedown_html_renderer_free(renderer); hoedown_buffer_free(ob); return html; }
/** * @brief Returns html rendered markdown of the note text * @param notesPath for transforming relative local urls to absolute ones * @param maxImageWidth defined maximum image width (ignored if forExport is true) * @param forExport defines whether the export or preview stylesheet * @return */ QString Note::toMarkdownHtml(QString notesPath, int maxImageWidth, bool forExport) { hoedown_renderer *renderer = hoedown_html_renderer_new(HOEDOWN_HTML_USE_XHTML, 16); hoedown_extensions extensions = (hoedown_extensions) (HOEDOWN_EXT_BLOCK | HOEDOWN_EXT_SPAN); hoedown_document *document = hoedown_document_new(renderer, extensions, 16); // get the decrypted note text (or the normal note text if there isn't any) QString str = getDecryptedNoteText(); QString windowsSlash = ""; #ifdef Q_OS_WIN32 // we need an other slash for Windows windowsSlash = "/"; #endif // parse for relative file urls and make them absolute // (for example to show images under the note path) str.replace( QRegularExpression("\\(file:\\/\\/([^\\/].+)\\)"), "(file://" + windowsSlash + notesPath + "/\\1)"); unsigned char *sequence = (unsigned char *) qstrdup( str.toUtf8().constData()); qint64 length = strlen((char *) sequence); // return an empty string if the note is empty if (length == 0) { return ""; } hoedown_buffer *html = hoedown_buffer_new(length); // render markdown html hoedown_document_render(document, html, sequence, length); // get markdown html QString result = QString::fromUtf8((char *) html->data, html->size); /* Cleanup */ free(sequence); hoedown_buffer_free(html); hoedown_document_free(document); hoedown_html_renderer_free(renderer); QSettings(settings); QString fontString = settings.value("MainWindow/noteTextView.code.font") .toString(); // set the stylesheet for the <code> blocks QString codeStyleSheet = ""; if (fontString != "") { // set the note text view font QFont font; font.fromString(fontString); // add the font for the code block codeStyleSheet = QString( "pre, code { %1; }").arg(encodeCssFont(font)); } bool darkModeColors = settings.value("darkModeColors").toBool(); QString codeBackgroundColor = darkModeColors ? "#444444" : "#f1f1f1"; // do some more code formatting codeStyleSheet += QString( "pre, code { padding: 16px; overflow: auto;" " line-height: 1.45em; background-color: %1;" " border-radius: 3px; }").arg(codeBackgroundColor); // remove double code blocks result.replace("<pre><code>", "<pre>") .replace("</code></pre>", "</pre>"); if (forExport) { // get defined body font from settings QString bodyfontString = settings.value("MainWindow/noteTextView.font") .toString(); // create export stylesheet QString exportStyleSheet = ""; if (bodyfontString != "") { QFont bodyFont; bodyFont.fromString(bodyfontString); exportStyleSheet = QString( "body { %1; }").arg(encodeCssFont(bodyFont)); } result = QString("<html><head><meta charset=\"utf-8\"/><style>" "h1 { margin: 5px 0 20px 0; }" "h2, h3 { margin: 10px 0 15px 0; }" "img { max-width: 100%; }" "a { color: #FF9137; text-decoration: none; } %1 %2" "</style></head><body>%3</body></html>") .arg(codeStyleSheet, exportStyleSheet, result); } else { // for preview result = QString("<html><head><style>" "h1 { margin: 5px 0 20px 0; }" "h2, h3 { margin: 10px 0 15px 0; }" "a { color: #FF9137; text-decoration: none; } %1" "</style></head><body>%2</body></html>") .arg(codeStyleSheet, result); } // check if width of embedded local images is too high QRegularExpression re("<img src=\"file:\\/\\/([^\"]+)\""); QRegularExpressionMatchIterator i = re.globalMatch(result); while (i.hasNext()) { QRegularExpressionMatch match = i.next(); QString fileName = match.captured(1); #ifdef Q_OS_WIN // remove the leading slash under Windows to get a more correct filename QImage image(Utils::Misc::removeIfStartsWith(fileName, "/")); #else QImage image(fileName); #endif if (forExport) { result.replace( QRegularExpression("<img src=\"file:\\/\\/" + QRegularExpression::escape(fileName) + "\""), QString("<img src=\"file://%2\"").arg(fileName)); } else { // for preview // cap the image width at 980px or the note text view width if (image.width() > maxImageWidth) { result.replace( QRegularExpression("<img src=\"file:\\/\\/" + QRegularExpression::escape(fileName) + "\""), QString("<img width=\"%1\" src=\"file://%2\"").arg( QString::number(maxImageWidth), fileName)); } } } // check if there is a script that wants to modify the content QString scriptResult = ScriptingService::instance() ->callNoteToMarkdownHtmlHook(this, result); if (!scriptResult.isEmpty()) { result = scriptResult; } return result; }
/** * @brief Returns html rendered markdown of the note text * @param notesPath for transforming relative local urls to absolute ones * @return */ QString Note::toMarkdownHtml(QString notesPath) { hoedown_renderer *renderer = hoedown_html_renderer_new(HOEDOWN_HTML_USE_XHTML, 16); hoedown_extensions extensions = (hoedown_extensions) (HOEDOWN_EXT_BLOCK | HOEDOWN_EXT_SPAN); hoedown_document *document = hoedown_document_new(renderer, extensions, 16); // get the decrypted note text (or the normal note text if there isn't any) QString str = getDecryptedNoteText(); QString windowsSlash = ""; #ifdef Q_OS_WIN32 // we need an other slash for Windows windowsSlash = "/"; #endif // parse for relative file urls and make them absolute // (for example to show images under the note path) str.replace( QRegularExpression("\\(file:\\/\\/([^\\/].+)\\)"), "(file://" + windowsSlash + notesPath + "/\\1)"); unsigned char *sequence = (unsigned char *) qstrdup( str.toUtf8().constData()); qint64 length = strlen((char *) sequence); // return an empty string if the note is empty if (length == 0) { return ""; } hoedown_buffer *html = hoedown_buffer_new(length); // render markdown html hoedown_document_render(document, html, sequence, length); // get markdown html QString result = QString::fromUtf8((char *) html->data, html->size); /* Cleanup */ free(sequence); hoedown_buffer_free(html); hoedown_document_free(document); hoedown_html_renderer_free(renderer); QSettings(settings); QString fontString = settings.value("MainWindow/noteTextView.code.font") .toString(); // set the stylesheet for the <code> blocks QString codeStyleSheet = ""; if (fontString != "") { // set the note text view font QFont font; font.fromString(fontString); codeStyleSheet = "pre, code {" + encodeCssFont(font) + "}"; } result = "<html><head>" "<style>h1, h2, h3 { margin: 5pt 0 10pt 0; }" "a { color: #FF9137; text-decoration: none; }" + codeStyleSheet + "</style></head><body>" + result + "</body></html>"; // check if width of embedded local images is too high QRegularExpression re("<img src=\"file:\\/\\/([^\"]+)\""); QRegularExpressionMatchIterator i = re.globalMatch(result); while (i.hasNext()) { QRegularExpressionMatch match = i.next(); QString fileName = match.captured(1); QImage image(fileName); // cap the image width at 980px if (image.width() > 980) { result.replace( QRegularExpression("<img src=\"file:\\/\\/" + QRegularExpression::escape(fileName) + "\""), "<img width=\"980\" src=\"file://" + fileName + "\""); } } return result; }
/** * @brief Returns html rendered markdown of the note text * @param notesPath for transforming relative local urls to absolute ones * @return */ QString Note::toMarkdownHtml(QString notesPath) { hoedown_renderer *renderer = hoedown_html_renderer_new(HOEDOWN_HTML_USE_XHTML, 16); hoedown_extensions extensions = (hoedown_extensions) (HOEDOWN_EXT_BLOCK | HOEDOWN_EXT_SPAN); hoedown_document *document = hoedown_document_new(renderer, extensions, 16); // get the decrypted note text (or the normal note text if there isn't any) QString str = getDecryptedNoteText(); // parse for relative file urls and make them absolute // (for example to show images under the note path) str.replace( QRegularExpression("\\(file:\\/\\/([^\\/].+)\\)"), "(file://" + notesPath + "/\\1)"); unsigned char *sequence = (unsigned char *) qstrdup(str.toUtf8().constData()); int length = strlen((char *) sequence); // return an empty string if the note is empty if (length == 0) { return ""; } hoedown_buffer *html = hoedown_buffer_new(length); // render markdown html hoedown_document_render(document, html, sequence, length); // get markdown html QString result = QString::fromUtf8((char *) html->data, html->size); /* Cleanup */ free(sequence); hoedown_buffer_free(html); hoedown_document_free(document); hoedown_html_renderer_free(renderer); result = "<html><head><style>h1, h2, h3 { margin: 5pt 0 10pt 0; }" "a { color: #FF9137; text-decoration: none; }</style></head><body>" + result + "</body></html>"; // check if width of embedded local images is too high QRegularExpression re("<img src=\"file:\\/\\/([^\"]+)\""); QRegularExpressionMatchIterator i = re.globalMatch(result); while (i.hasNext()) { QRegularExpressionMatch match = i.next(); QString fileName = match.captured(1); QImage image(fileName); // cap the image width at 980px if (image.width() > 980) { result.replace( QRegularExpression("<img src=\"file:\\/\\/" + QRegularExpression::escape(fileName) + "\""), "<img width=\"980\" src=\"file://" + fileName + "\""); } } return result; }