Ver código fonte

add Hoedown for markdown convertion

Signed-off-by: Le Tan <[email protected]>
Le Tan 9 anos atrás
pai
commit
a983026552

+ 3 - 0
.gitmodules

@@ -1,3 +1,6 @@
 [submodule "src/utils/marked"]
 	path = src/utils/marked
 	url = https://github.com/chjj/marked.git
+[submodule "hoedown"]
+	path = hoedown
+	url = https://github.com/tamlok/hoedown.git

+ 4 - 1
VNote.pro

@@ -8,4 +8,7 @@ TEMPLATE = subdirs
 
 CONFIG += c++11
 
-SUBDIRS = src
+SUBDIRS = hoedown \
+    src
+
+src.depends = hoedown

+ 1 - 0
hoedown

@@ -0,0 +1 @@
+Subproject commit 845cdbc3588129e4c1ddf8397a3ab742c6e3d9c4

+ 0 - 1
src/resources/post_template.html

@@ -1,3 +1,2 @@
-</div>
 </body>
 </html>

+ 4 - 2
src/resources/pre_template.html

@@ -2,7 +2,9 @@
 <html lang="en">
 <meta charset="utf-8">
 <head>
-  <link rel="stylesheet" type="text/css" href=":/resources/markdown.css">
+  <link rel="stylesheet" type="text/css" href="CSS_PLACE_HOLDER">
+  <link rel="stylesheet" type="text/css" href="qrc:/utils/highlightjs/styles/default.css">
+  <script src="qrc:/utils/highlightjs/highlight.pack.js"></script>
+  <script>hljs.initHighlightingOnLoad();</script>
 </head>
 <body>
-  <div id="placeholder">

+ 11 - 2
src/src.pro

@@ -32,7 +32,8 @@ SOURCES += main.cpp\
     hgmarkdownhighlighter.cpp \
     vstyleparser.cpp \
     utils/peg-highlight/pmh_styleparser.c \
-    dialog/vnewnotebookdialog.cpp
+    dialog/vnewnotebookdialog.cpp \
+    vmarkdownconverter.cpp
 
 HEADERS  += vmainwindow.h \
     vdirectorytree.h \
@@ -55,7 +56,15 @@ HEADERS  += vmainwindow.h \
     utils/peg-highlight/pmh_definitions.h \
     vstyleparser.h \
     utils/peg-highlight/pmh_styleparser.h \
-    dialog/vnewnotebookdialog.h
+    dialog/vnewnotebookdialog.h \
+    vmarkdownconverter.h
 
 RESOURCES += \
     vnote.qrc
+
+win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../hoedown/release/ -lhoedown
+else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../hoedown/debug/ -lhoedown
+else:unix: LIBS += -L$$OUT_PWD/../hoedown/ -lhoedown
+
+INCLUDEPATH += $$PWD/../hoedown
+DEPENDPATH += $$PWD/../hoedown

+ 5 - 0
src/vconfigmanager.cpp

@@ -45,6 +45,11 @@ void VConfigManager::initialize()
     templateCssUrl = getConfigFromSettings("global", "template_css_url").toString();
     curNotebookIndex = getConfigFromSettings("global", "current_notebook").toInt();
 
+    markdownExtensions = hoedown_extensions(HOEDOWN_EXT_TABLES | HOEDOWN_EXT_FENCED_CODE |
+                                            HOEDOWN_EXT_HIGHLIGHT | HOEDOWN_EXT_AUTOLINK |
+                                            HOEDOWN_EXT_QUOTE | HOEDOWN_EXT_MATH);
+    mdConverterType = (MarkdownConverterType)getConfigFromSettings("global", "markdown_converter").toInt();
+
     // Update notebooks
     readNotebookFromSettings();
 

+ 36 - 0
src/vconfigmanager.h

@@ -8,10 +8,16 @@
 #include "vnotebook.h"
 
 #include "hgmarkdownhighlighter.h"
+#include "vmarkdownconverter.h"
 
 class QJsonObject;
 class QString;
 
+enum MarkdownConverterType {
+    Hoedown = 0,
+    Marked
+};
+
 class VConfigManager
 {
 public:
@@ -49,6 +55,12 @@ public:
     inline const QVector<VNotebook>& getNotebooks() const;
     inline void setNotebooks(const QVector<VNotebook> &notebooks);
 
+    inline hoedown_extensions getMarkdownExtensions() const;
+    inline MarkdownConverterType getMdConverterType() const;
+
+    inline QString getPreTemplatePath() const;
+    inline QString getPostTemplatePath() const;
+
 private:
     void updateMarkdownEditStyle();
     QVariant getConfigFromSettings(const QString &section, const QString &key);
@@ -69,6 +81,10 @@ private:
     int curNotebookIndex;
     QVector<VNotebook> notebooks;
 
+    // Markdown Converter
+    hoedown_extensions markdownExtensions;
+    MarkdownConverterType mdConverterType;
+
     // The name of the config file in each directory
     static const QString dirConfigFileName;
     // The name of the default configuration file
@@ -140,4 +156,24 @@ inline void VConfigManager::setNotebooks(const QVector<VNotebook> &notebooks)
     writeNotebookToSettings();
 }
 
+inline hoedown_extensions VConfigManager::getMarkdownExtensions() const
+{
+    return markdownExtensions;
+}
+
+inline MarkdownConverterType VConfigManager::getMdConverterType() const
+{
+    return mdConverterType;
+}
+
+inline QString VConfigManager::getPreTemplatePath() const
+{
+    return preTemplatePath;
+}
+
+inline QString VConfigManager::getPostTemplatePath() const
+{
+    return postTemplatePath;
+}
+
 #endif // VCONFIGMANAGER_H

+ 25 - 6
src/veditor.cpp

@@ -10,12 +10,13 @@
 #include "vpreviewpage.h"
 #include "hgmarkdownhighlighter.h"
 #include "vconfigmanager.h"
+#include "vmarkdownconverter.h"
 
 extern VConfigManager vconfig;
 
 VEditor::VEditor(const QString &path, const QString &name, bool modifiable,
                  QWidget *parent)
-    : QStackedWidget(parent)
+    : QStackedWidget(parent), mdConverterType(vconfig.getMdConverterType())
 {
     DocType docType = isMarkdown(name) ? DocType::Markdown : DocType::Html;
     QString fileText = VUtils::readFileFromDisk(QDir(path).filePath(name));
@@ -83,7 +84,11 @@ void VEditor::showFileReadMode()
         setCurrentWidget(textBrowser);
         break;
     case DocType::Markdown:
-        document.setText(noteFile->content);
+        if (mdConverterType == MarkdownConverterType::Marked) {
+            document.setText(noteFile->content);
+        } else {
+            previewByConverter();
+        }
         setCurrentWidget(webPreviewer);
         break;
     default:
@@ -91,6 +96,18 @@ void VEditor::showFileReadMode()
     }
 }
 
+void VEditor::previewByConverter()
+{
+    VMarkdownConverter mdConverter;
+    QString content = noteFile->content;
+    QString html = mdConverter.generateHtml(content, vconfig.getMarkdownExtensions());
+    QRegularExpression tocExp("<p>\\[TOC\\]<\\/p>", QRegularExpression::CaseInsensitiveOption);
+    QString toc = mdConverter.generateToc(content, vconfig.getMarkdownExtensions());
+    html.replace(tocExp, toc);
+    QString completeHtml = VNote::preTemplateHtml + html + VNote::postTemplateHtml;
+    webPreviewer->setHtml(completeHtml, QUrl::fromLocalFile(noteFile->path + QDir::separator()));
+}
+
 void VEditor::showFileEditMode()
 {
     isEditMode = true;
@@ -175,10 +192,12 @@ void VEditor::setupMarkdownPreview()
     VPreviewPage *page = new VPreviewPage(this);
     webPreviewer->setPage(page);
 
-    QWebChannel *channel = new QWebChannel(this);
-    channel->registerObject(QStringLiteral("content"), &document);
-    page->setWebChannel(channel);
-    webPreviewer->setHtml(VNote::templateHtml, QUrl::fromLocalFile(noteFile->path + QDir::separator()));
+    if (mdConverterType == MarkdownConverterType::Marked) {
+        QWebChannel *channel = new QWebChannel(this);
+        channel->registerObject(QStringLiteral("content"), &document);
+        page->setWebChannel(channel);
+        webPreviewer->setHtml(VNote::templateHtml, QUrl::fromLocalFile(noteFile->path + QDir::separator()));
+    }
 
     addWidget(webPreviewer);
 }

+ 4 - 0
src/veditor.h

@@ -6,6 +6,8 @@
 #include "vconstants.h"
 #include "vnotefile.h"
 #include "vdocument.h"
+#include "vmarkdownconverter.h"
+#include "vconfigmanager.h"
 
 class QTextBrowser;
 class VEdit;
@@ -31,6 +33,7 @@ private:
     void showFileReadMode();
     void showFileEditMode();
     void setupMarkdownPreview();
+    void previewByConverter();
 
     VNoteFile *noteFile;
     bool isEditMode;
@@ -38,6 +41,7 @@ private:
     VEdit *textEditor;
     QWebEngineView *webPreviewer;
     VDocument document;
+    MarkdownConverterType mdConverterType;
 };
 
 #endif // VEDITOR_H

+ 52 - 0
src/vmarkdownconverter.cpp

@@ -0,0 +1,52 @@
+#include "vmarkdownconverter.h"
+
+VMarkdownConverter::VMarkdownConverter()   
+{
+    hoedownHtmlFlags = (hoedown_html_flags)0;
+    nestingLevel = 16;
+
+    htmlRenderer = hoedown_html_renderer_new(hoedownHtmlFlags, nestingLevel);
+    tocRenderer = hoedown_html_toc_renderer_new(nestingLevel);
+}
+
+VMarkdownConverter::~VMarkdownConverter()
+{
+    if (htmlRenderer) {
+        hoedown_html_renderer_free(htmlRenderer);
+    }
+    if (tocRenderer) {
+        hoedown_html_renderer_free(tocRenderer);
+    }
+}
+
+QString VMarkdownConverter::generateHtml(const QString &markdown, hoedown_extensions options)
+{
+    if (markdown.isEmpty()) {
+        return QString();
+    }
+    hoedown_document *document = hoedown_document_new(htmlRenderer, options,
+                                                      nestingLevel);
+    QByteArray data = markdown.toUtf8();
+    hoedown_buffer *outBuf = hoedown_buffer_new(data.size());
+    hoedown_document_render(document, outBuf, (const uint8_t *)data.constData(), data.size());
+    hoedown_document_free(document);
+    QString html = QString::fromUtf8(hoedown_buffer_cstr(outBuf));
+    hoedown_buffer_free(outBuf);
+
+    return html;
+}
+
+QString VMarkdownConverter::generateToc(const QString &markdown, hoedown_extensions options)
+{
+    if (markdown.isEmpty()) {
+        return QString();
+    }
+    hoedown_document *document = hoedown_document_new(tocRenderer, options, nestingLevel);
+    QByteArray data = markdown.toUtf8();
+    hoedown_buffer *outBuf = hoedown_buffer_new(16);
+    hoedown_document_render(document, outBuf, (const uint8_t *)data.constData(), data.size());
+    hoedown_document_free(document);
+    QString toc = QString::fromUtf8(hoedown_buffer_cstr(outBuf));
+    hoedown_buffer_free(outBuf);
+    return toc;
+}

+ 28 - 0
src/vmarkdownconverter.h

@@ -0,0 +1,28 @@
+#ifndef VMARKDOWNCONVERTER_H
+#define VMARKDOWNCONVERTER_H
+
+#include <QString>
+
+extern "C" {
+#include <src/html.h>
+#include <src/document.h>
+}
+
+class VMarkdownConverter
+{
+public:
+    VMarkdownConverter();
+    ~VMarkdownConverter();
+
+    QString generateHtml(const QString &markdown, hoedown_extensions options);
+    QString generateToc(const QString &markdown, hoedown_extensions options);
+
+private:
+    // VMarkdownDocument *generateDocument(const QString &markdown);
+    hoedown_html_flags hoedownHtmlFlags;
+    int nestingLevel;
+    hoedown_renderer *htmlRenderer;
+    hoedown_renderer *tocRenderer;
+};
+
+#endif // VMARKDOWNCONVERTER_H

+ 13 - 2
src/vnote.cpp

@@ -10,6 +10,8 @@
 VConfigManager vconfig;
 
 QString VNote::templateHtml;
+QString VNote::preTemplateHtml;
+QString VNote::postTemplateHtml;
 
 VNote::VNote() : QObject()
 {
@@ -21,8 +23,17 @@ VNote::VNote() : QObject()
 
 void VNote::decorateTemplate()
 {
-    templateHtml = VUtils::readFileFromDisk(vconfig.getTemplatePath());
-    templateHtml.replace("CSS_PLACE_HOLDER", vconfig.getTemplateCssUrl());
+    if (templateHtml.isEmpty()) {
+        templateHtml = VUtils::readFileFromDisk(vconfig.getTemplatePath());
+        templateHtml.replace("CSS_PLACE_HOLDER", vconfig.getTemplateCssUrl());
+    }
+    if (preTemplateHtml.isEmpty()) {
+        preTemplateHtml = VUtils::readFileFromDisk(vconfig.getPreTemplatePath());
+        preTemplateHtml.replace("CSS_PLACE_HOLDER", vconfig.getTemplateCssUrl());
+    }
+    if (postTemplateHtml.isEmpty()) {
+        postTemplateHtml = VUtils::readFileFromDisk(vconfig.getPostTemplatePath());
+    }
 }
 
 const QVector<VNotebook>& VNote::getNotebooks()

+ 5 - 0
src/vnote.h

@@ -20,8 +20,13 @@ public:
 
     static void decorateTemplate();
 
+    // Used by Marked
     static QString templateHtml;
 
+    // Used by other markdown converter
+    static QString preTemplateHtml;
+    static QString postTemplateHtml;
+
     void createNotebook(const QString &name, const QString &path);
     void removeNotebook(const QString &name);