export: add TOC function to built-in PDF export

This commit is contained in:
Le Tan 2018-03-04 20:06:09 +08:00
parent fb73fdad77
commit 9cc193178b
10 changed files with 79 additions and 29 deletions

View File

@ -208,6 +208,10 @@ QWidget *VExportDialog::setupPDFAdvancedSettings()
updatePageLayoutLabel(); updatePageLayoutLabel();
// Enable table of contents.
m_tableOfContentsCB = new QCheckBox(tr("Enable Table Of Contents"));
m_tableOfContentsCB->setToolTip(tr("Add a table of contents to the document"));
// Use wkhtmltopdf. // Use wkhtmltopdf.
m_wkhtmltopdfCB = new QCheckBox(tr("Use wkhtmltopdf")); m_wkhtmltopdfCB = new QCheckBox(tr("Use wkhtmltopdf"));
m_wkhtmltopdfCB->setToolTip(tr("Use wkhtmltopdf tool to generate PDF (wkhtmltopdf needed to be installed)")); m_wkhtmltopdfCB->setToolTip(tr("Use wkhtmltopdf tool to generate PDF (wkhtmltopdf needed to be installed)"));
@ -217,7 +221,6 @@ QWidget *VExportDialog::setupPDFAdvancedSettings()
m_wkPathEdit->setEnabled(checked); m_wkPathEdit->setEnabled(checked);
m_wkPathBrowseBtn->setEnabled(checked); m_wkPathBrowseBtn->setEnabled(checked);
m_wkBackgroundCB->setEnabled(checked); m_wkBackgroundCB->setEnabled(checked);
m_wkTableOfContentsCB->setEnabled(checked);
m_wkPageNumberCB->setEnabled(checked); m_wkPageNumberCB->setEnabled(checked);
m_wkExtraArgsEdit->setEnabled(checked); m_wkExtraArgsEdit->setEnabled(checked);
}); });
@ -257,11 +260,6 @@ QWidget *VExportDialog::setupPDFAdvancedSettings()
m_wkBackgroundCB->setToolTip(tr("Enable background when printing")); m_wkBackgroundCB->setToolTip(tr("Enable background when printing"));
m_wkBackgroundCB->setEnabled(m_wkhtmltopdfCB->isChecked()); m_wkBackgroundCB->setEnabled(m_wkhtmltopdfCB->isChecked());
// wkhtmltopdf enable table of contents.
m_wkTableOfContentsCB = new QCheckBox(tr("Enable Table Of Contents"));
m_wkTableOfContentsCB->setToolTip(tr("Add a table of contents to the document"));
m_wkTableOfContentsCB->setEnabled(m_wkhtmltopdfCB->isChecked());
// wkhtmltopdf page number. // wkhtmltopdf page number.
m_wkPageNumberCB = VUtils::getComboBox(); m_wkPageNumberCB = VUtils::getComboBox();
m_wkPageNumberCB->setToolTip(tr("Append page number as footer")); m_wkPageNumberCB->setToolTip(tr("Append page number as footer"));
@ -277,6 +275,7 @@ QWidget *VExportDialog::setupPDFAdvancedSettings()
advLayout->addWidget(new QLabel(tr("Page layout:")), 0, 0); advLayout->addWidget(new QLabel(tr("Page layout:")), 0, 0);
advLayout->addWidget(m_layoutLabel, 0, 1); advLayout->addWidget(m_layoutLabel, 0, 1);
advLayout->addWidget(layoutBtn, 0, 2); advLayout->addWidget(layoutBtn, 0, 2);
advLayout->addWidget(m_tableOfContentsCB, 0, 4, 1, 2);
advLayout->addWidget(m_wkhtmltopdfCB, 1, 1, 1, 2); advLayout->addWidget(m_wkhtmltopdfCB, 1, 1, 1, 2);
advLayout->addWidget(wkBtn, 1, 4, 1, 2); advLayout->addWidget(wkBtn, 1, 4, 1, 2);
@ -291,14 +290,12 @@ QWidget *VExportDialog::setupPDFAdvancedSettings()
advLayout->addWidget(new QLabel(tr("Output file name:")), 3, 3); advLayout->addWidget(new QLabel(tr("Output file name:")), 3, 3);
advLayout->addWidget(m_wkTargetFileNameEdit, 3, 4, 1, 2); advLayout->addWidget(m_wkTargetFileNameEdit, 3, 4, 1, 2);
advLayout->addWidget(m_wkBackgroundCB, 4, 1, 1, 2); advLayout->addWidget(new QLabel(tr("Page number:")), 4, 0);
advLayout->addWidget(m_wkTableOfContentsCB, 4, 4, 1, 2); advLayout->addWidget(m_wkPageNumberCB, 4, 1, 1, 2);
advLayout->addWidget(m_wkBackgroundCB, 4, 4, 1, 2);
advLayout->addWidget(new QLabel(tr("Page number:")), 5, 0); advLayout->addWidget(new QLabel(tr("Additional options:")), 5, 0);
advLayout->addWidget(m_wkPageNumberCB, 5, 1, 1, 2); advLayout->addWidget(m_wkExtraArgsEdit, 5, 1, 1, 5);
advLayout->addWidget(new QLabel(tr("Additional options:")), 6, 0);
advLayout->addWidget(m_wkExtraArgsEdit, 6, 1, 1, 5);
advLayout->setContentsMargins(0, 0, 0, 0); advLayout->setContentsMargins(0, 0, 0, 0);
@ -437,6 +434,8 @@ void VExportDialog::initUIFields(MarkdownConverterType p_renderer)
m_mimeHTMLCB->setChecked(s_opt.m_htmlOpt.m_mimeHTML); m_mimeHTMLCB->setChecked(s_opt.m_htmlOpt.m_mimeHTML);
m_tableOfContentsCB->setChecked(s_opt.m_pdfOpt.m_enableTableOfContents);
m_wkhtmltopdfCB->setChecked(s_opt.m_pdfOpt.m_wkhtmltopdf); m_wkhtmltopdfCB->setChecked(s_opt.m_pdfOpt.m_wkhtmltopdf);
// wkhtmltopdf path. // wkhtmltopdf path.
@ -444,8 +443,6 @@ void VExportDialog::initUIFields(MarkdownConverterType p_renderer)
m_wkBackgroundCB->setChecked(s_opt.m_pdfOpt.m_wkEnableBackground); m_wkBackgroundCB->setChecked(s_opt.m_pdfOpt.m_wkEnableBackground);
m_wkTableOfContentsCB->setChecked(s_opt.m_pdfOpt.m_wkEnableTableOfContents);
// wkhtmltopdf page number. // wkhtmltopdf page number.
m_wkPageNumberCB->addItem(tr("None"), (int)ExportPageNumber::None); m_wkPageNumberCB->addItem(tr("None"), (int)ExportPageNumber::None);
m_wkPageNumberCB->addItem(tr("Left"), (int)ExportPageNumber::Left); m_wkPageNumberCB->addItem(tr("Left"), (int)ExportPageNumber::Left);
@ -507,7 +504,7 @@ void VExportDialog::startExport()
m_wkhtmltopdfCB->isChecked(), m_wkhtmltopdfCB->isChecked(),
QDir::toNativeSeparators(m_wkPathEdit->text()), QDir::toNativeSeparators(m_wkPathEdit->text()),
m_wkBackgroundCB->isChecked(), m_wkBackgroundCB->isChecked(),
m_wkTableOfContentsCB->isChecked(), m_tableOfContentsCB->isChecked(),
m_wkTitleEdit->text(), m_wkTitleEdit->text(),
m_wkTargetFileNameEdit->text(), m_wkTargetFileNameEdit->text(),
(ExportPageNumber)m_wkPageNumberCB->currentData().toInt(), (ExportPageNumber)m_wkPageNumberCB->currentData().toInt(),

View File

@ -81,7 +81,7 @@ struct ExportPDFOption
: m_layout(NULL), : m_layout(NULL),
m_wkhtmltopdf(false), m_wkhtmltopdf(false),
m_wkEnableBackground(true), m_wkEnableBackground(true),
m_wkEnableTableOfContents(false), m_enableTableOfContents(false),
m_wkPageNumber(ExportPageNumber::None) m_wkPageNumber(ExportPageNumber::None)
{ {
} }
@ -90,7 +90,7 @@ struct ExportPDFOption
bool p_wkhtmltopdf, bool p_wkhtmltopdf,
const QString &p_wkPath, const QString &p_wkPath,
bool p_wkEnableBackground, bool p_wkEnableBackground,
bool p_wkEnableTableOfContents, bool p_enableTableOfContents,
const QString &p_wkTitle, const QString &p_wkTitle,
const QString &p_wkTargetFileName, const QString &p_wkTargetFileName,
ExportPageNumber p_wkPageNumber, ExportPageNumber p_wkPageNumber,
@ -99,7 +99,7 @@ struct ExportPDFOption
m_wkhtmltopdf(p_wkhtmltopdf), m_wkhtmltopdf(p_wkhtmltopdf),
m_wkPath(p_wkPath), m_wkPath(p_wkPath),
m_wkEnableBackground(p_wkEnableBackground), m_wkEnableBackground(p_wkEnableBackground),
m_wkEnableTableOfContents(p_wkEnableTableOfContents), m_enableTableOfContents(p_enableTableOfContents),
m_wkTitle(p_wkTitle), m_wkTitle(p_wkTitle),
m_wkTargetFileName(p_wkTargetFileName), m_wkTargetFileName(p_wkTargetFileName),
m_wkPageNumber(p_wkPageNumber), m_wkPageNumber(p_wkPageNumber),
@ -111,7 +111,7 @@ struct ExportPDFOption
bool m_wkhtmltopdf; bool m_wkhtmltopdf;
QString m_wkPath; QString m_wkPath;
bool m_wkEnableBackground; bool m_wkEnableBackground;
bool m_wkEnableTableOfContents; bool m_enableTableOfContents;;
QString m_wkTitle; QString m_wkTitle;
QString m_wkTargetFileName; QString m_wkTargetFileName;
ExportPageNumber m_wkPageNumber; ExportPageNumber m_wkPageNumber;
@ -315,7 +315,7 @@ private:
QCheckBox *m_wkBackgroundCB; QCheckBox *m_wkBackgroundCB;
QCheckBox *m_wkTableOfContentsCB; QCheckBox *m_tableOfContentsCB;
QComboBox *m_wkPageNumberCB; QComboBox *m_wkPageNumberCB;

View File

@ -149,6 +149,7 @@ int main(int argc, char *argv[])
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
if (!qstrcmp(argv[i], "-d")) { if (!qstrcmp(argv[i], "-d")) {
g_debugLog = true; g_debugLog = true;
break;
} }
} }

View File

@ -100,6 +100,10 @@ var markdownToHtml = function(markdown, needToc) {
}; };
var updateText = function(text) { var updateText = function(text) {
if (VAddTOC) {
text = "[TOC]\n\n" + text;
}
var needToc = mdHasTocSection(text); var needToc = mdHasTocSection(text);
var html = markdownToHtml(text, needToc); var html = markdownToHtml(text, needToc);
placeholder.innerHTML = html; placeholder.innerHTML = html;

View File

@ -48,6 +48,10 @@ if (typeof VRemoveMathjaxScript == 'undefined') {
VRemoveMathjaxScript = false; VRemoveMathjaxScript = false;
} }
if (typeof VAddTOC == 'undefined') {
VAddTOC = false;
}
var getUrlScheme = function(url) { var getUrlScheme = function(url) {
var idx = url.indexOf(':'); var idx = url.indexOf(':');
if (idx > -1) { if (idx > -1) {
@ -805,13 +809,19 @@ var handleToc = function(needToc) {
var tocTree = tocToTree(toPerfectToc(toc, baseLevel), baseLevel); var tocTree = tocToTree(toPerfectToc(toc, baseLevel), baseLevel);
content.setToc(tocTree, baseLevel); content.setToc(tocTree, baseLevel);
var removeToc = toc.length == 0;
// Add it to html // Add it to html
if (needToc) { if (needToc) {
var eles = document.getElementsByClassName('vnote-toc'); var eles = document.getElementsByClassName('vnote-toc');
for (var i = 0; i < eles.length; ++i) { for (var i = 0; i < eles.length; ++i) {
if (removeToc) {
eles[i].parentNode.removeChild(eles[i]);
} else {
eles[i].innerHTML = tocTree; eles[i].innerHTML = tocTree;
} }
} }
}
}; };
// Implement mouse drag with Ctrl and left button pressed to scroll. // Implement mouse drag with Ctrl and left button pressed to scroll.

View File

@ -49,6 +49,10 @@ var mdHasTocSection = function(markdown) {
}; };
var updateText = function(text) { var updateText = function(text) {
if (VAddTOC) {
text = "[TOC]\n\n" + text;
}
var needToc = mdHasTocSection(text); var needToc = mdHasTocSection(text);
var html = markdownToHtml(text, needToc); var html = markdownToHtml(text, needToc);
placeholder.innerHTML = html; placeholder.innerHTML = html;

View File

@ -73,6 +73,10 @@ var highlightCodeBlocks = function(doc, enableMermaid, enableFlowchart, enableMa
}; };
var updateText = function(text) { var updateText = function(text) {
if (VAddTOC) {
text = "[TOC]\n\n" + text;
}
var needToc = mdHasTocSection(text); var needToc = mdHasTocSection(text);
var html = markdownToHtml(text, needToc); var html = markdownToHtml(text, needToc);
placeholder.innerHTML = html; placeholder.innerHTML = html;

View File

@ -602,7 +602,8 @@ QString VUtils::generateHtmlTemplate(MarkdownConverterType p_conType,
const QString &p_renderStyle, const QString &p_renderStyle,
const QString &p_renderCodeBlockStyle, const QString &p_renderCodeBlockStyle,
bool p_isPDF, bool p_isPDF,
bool p_wkhtmltopdf) bool p_wkhtmltopdf,
bool p_addToc)
{ {
Q_ASSERT((p_isPDF && p_wkhtmltopdf) || !p_wkhtmltopdf); Q_ASSERT((p_isPDF && p_wkhtmltopdf) || !p_wkhtmltopdf);
@ -611,12 +612,13 @@ QString VUtils::generateHtmlTemplate(MarkdownConverterType p_conType,
g_config->getCodeBlockCssStyleUrl(p_renderCodeBlockStyle), g_config->getCodeBlockCssStyleUrl(p_renderCodeBlockStyle),
p_isPDF); p_isPDF);
return generateHtmlTemplate(templ, p_conType, p_wkhtmltopdf); return generateHtmlTemplate(templ, p_conType, p_wkhtmltopdf, p_addToc);
} }
QString VUtils::generateHtmlTemplate(const QString &p_template, QString VUtils::generateHtmlTemplate(const QString &p_template,
MarkdownConverterType p_conType, MarkdownConverterType p_conType,
bool p_wkhtmltopdf) bool p_wkhtmltopdf,
bool p_addToc)
{ {
QString jsFile, extraFile; QString jsFile, extraFile;
switch (p_conType) { switch (p_conType) {
@ -715,6 +717,17 @@ QString VUtils::generateHtmlTemplate(const QString &p_template,
extraFile += "<script>var VEnableFlashAnchor = true;</script>\n"; extraFile += "<script>var VEnableFlashAnchor = true;</script>\n";
} }
if (p_addToc) {
extraFile += "<script>var VAddTOC = true;</script>\n";
extraFile += "<style type=\"text/css\">\n"
" @media print {\n"
" .vnote-toc {\n"
" page-break-after: always;\n"
" }\n"
" }\n"
"</style>";
}
extraFile += "<script>var VStylesToInline = '" + g_config->getStylesToInlineWhenCopied() + "';</script>\n"; extraFile += "<script>var VStylesToInline = '" + g_config->getStylesToInlineWhenCopied() + "';</script>\n";
QString htmlTemplate(p_template); QString htmlTemplate(p_template);

View File

@ -177,7 +177,8 @@ public:
const QString &p_renderStyle, const QString &p_renderStyle,
const QString &p_renderCodeBlockStyle, const QString &p_renderCodeBlockStyle,
bool p_isPDF, bool p_isPDF,
bool p_wkhtmltopdf = false); bool p_wkhtmltopdf = false,
bool p_addToc = false);
// @p_renderBg is the background name. // @p_renderBg is the background name.
static QString generateExportHtmlTemplate(const QString &p_renderBg, bool p_includeMathJax); static QString generateExportHtmlTemplate(const QString &p_renderBg, bool p_includeMathJax);
@ -359,7 +360,8 @@ private:
static QString generateHtmlTemplate(const QString &p_template, static QString generateHtmlTemplate(const QString &p_template,
MarkdownConverterType p_conType, MarkdownConverterType p_conType,
bool p_wkhtmltopdf = false); bool p_wkhtmltopdf = false,
bool p_addToc = false);
// <value, name> // <value, name>
static QVector<QPair<QString, QString>> s_availableLanguages; static QVector<QPair<QString, QString>> s_availableLanguages;

View File

@ -41,13 +41,17 @@ void VExporter::prepareExport(const ExportOption &p_opt)
{ {
bool isPdf = p_opt.m_format == ExportFormat::PDF bool isPdf = p_opt.m_format == ExportFormat::PDF
|| p_opt.m_format == ExportFormat::OnePDF; || p_opt.m_format == ExportFormat::OnePDF;
bool extraToc = isPdf
&& !p_opt.m_pdfOpt.m_wkhtmltopdf
&& p_opt.m_pdfOpt.m_enableTableOfContents;
m_htmlTemplate = VUtils::generateHtmlTemplate(p_opt.m_renderer, m_htmlTemplate = VUtils::generateHtmlTemplate(p_opt.m_renderer,
p_opt.m_renderBg, p_opt.m_renderBg,
p_opt.m_renderStyle, p_opt.m_renderStyle,
p_opt.m_renderCodeBlockStyle, p_opt.m_renderCodeBlockStyle,
isPdf, isPdf,
isPdf && p_opt.m_pdfOpt.m_wkhtmltopdf); isPdf && p_opt.m_pdfOpt.m_wkhtmltopdf,
extraToc);
m_exportHtmlTemplate = VUtils::generateExportHtmlTemplate(p_opt.m_renderBg, m_exportHtmlTemplate = VUtils::generateExportHtmlTemplate(p_opt.m_renderBg,
isPdf && p_opt.m_pdfOpt.m_wkhtmltopdf); isPdf && p_opt.m_pdfOpt.m_wkhtmltopdf);
@ -153,7 +157,7 @@ void VExporter::prepareWKArguments(const ExportPDFOption &p_opt)
} }
// TOC option. // TOC option.
if (p_opt.m_wkEnableTableOfContents) { if (p_opt.m_enableTableOfContents) {
m_wkArgs << "toc" << "--toc-text-size-shrink" << "1.0"; m_wkArgs << "toc" << "--toc-text-size-shrink" << "1.0";
} }
} }
@ -203,6 +207,17 @@ void VExporter::initWebViewer(VFile *p_file, const ExportOption &p_opt)
QString html = mdConverter.generateHtml(p_file->getContent(), QString html = mdConverter.generateHtml(p_file->getContent(),
g_config->getMarkdownExtensions(), g_config->getMarkdownExtensions(),
toc); toc);
bool isPdf = p_opt.m_format == ExportFormat::PDF
|| p_opt.m_format == ExportFormat::OnePDF;
bool extraToc = isPdf
&& !p_opt.m_pdfOpt.m_wkhtmltopdf
&& p_opt.m_pdfOpt.m_enableTableOfContents;
if (extraToc && !toc.isEmpty()) {
// Add toc to html.
QString div = "<div class=\"vnote-toc\">" + toc + "</div>\n";
html = div + html;
}
m_webDocument->setHtml(html); m_webDocument->setHtml(html);
} }