add Hoedown for markdown convertion

Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
Le Tan 2016-10-23 10:35:31 +08:00
parent 5fa07864a1
commit a983026552
14 changed files with 191 additions and 14 deletions

3
.gitmodules vendored
View File

@ -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

View File

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

1
hoedown Submodule

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

View File

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

View File

@ -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">

View File

@ -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

View File

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

View File

@ -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

View File

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

View File

@ -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

View File

@ -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
src/vmarkdownconverter.h Normal file
View File

@ -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

View File

@ -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()

View File

@ -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);