/** * @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 * @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(); // 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; }