diff --git a/src/core/htmltemplatehelper.cpp b/src/core/htmltemplatehelper.cpp index e73f919a..47744b5c 100644 --- a/src/core/htmltemplatehelper.cpp +++ b/src/core/htmltemplatehelper.cpp @@ -21,6 +21,9 @@ QString WebGlobalOptions::toJavascriptObject() const + QString("webGraphviz: %1,\n").arg(Utils::boolToString(m_webGraphviz)) + QString("constrainImageWidthEnabled: %1,\n").arg(Utils::boolToString(m_constrainImageWidthEnabled)) + QString("protectFromXss: %1,\n").arg(Utils::boolToString(m_protectFromXss)) + + QString("htmlTagEnabled: %1,\n").arg(Utils::boolToString(m_htmlTagEnabled)) + + QString("autoBreakEnabled: %1,\n").arg(Utils::boolToString(m_autoBreakEnabled)) + + QString("linkifyEnabled: %1,\n").arg(Utils::boolToString(m_linkifyEnabled)) + QString("sectionNumberEnabled: %1\n").arg(Utils::boolToString(m_sectionNumberEnabled)) + QStringLiteral("}"); } @@ -155,6 +158,9 @@ void HtmlTemplateHelper::updateMarkdownViewerTemplate(const MarkdownEditorConfig opts.m_sectionNumberEnabled = p_config.getSectionNumberEnabled(); opts.m_constrainImageWidthEnabled = p_config.getConstrainImageWidthEnabled(); opts.m_protectFromXss = p_config.getProtectFromXss(); + opts.m_htmlTagEnabled = p_config.getHtmlTagEnabled(); + opts.m_autoBreakEnabled = p_config.getAutoBreakEnabled(); + opts.m_linkifyEnabled = p_config.getLinkifyEnabled(); fillGlobalOptions(s_markdownViewerTemplate.m_template, opts); } diff --git a/src/core/htmltemplatehelper.h b/src/core/htmltemplatehelper.h index f1fc7db0..ded17b4d 100644 --- a/src/core/htmltemplatehelper.h +++ b/src/core/htmltemplatehelper.h @@ -20,6 +20,12 @@ namespace vnotex bool m_protectFromXss = false; + bool m_htmlTagEnabled = true; + + bool m_autoBreakEnabled = false; + + bool m_linkifyEnabled = true; + QString toJavascriptObject() const; }; diff --git a/src/core/markdowneditorconfig.cpp b/src/core/markdowneditorconfig.cpp index 0081b559..fb0590e5 100644 --- a/src/core/markdowneditorconfig.cpp +++ b/src/core/markdowneditorconfig.cpp @@ -39,6 +39,9 @@ void MarkdownEditorConfig::init(const QJsonObject &p_app, const QJsonObject &p_u m_zoomFactorInReadMode = READREAL(QStringLiteral("zoom_factor_in_read_mode")); m_fetchImagesInParseAndPaste = READBOOL(QStringLiteral("fetch_images_in_parse_and_paste")); m_protectFromXss = READBOOL(QStringLiteral("protect_from_xss")); + m_htmlTagEnabled = READBOOL(QStringLiteral("html_tag")); + m_autoBreakEnabled = READBOOL(QStringLiteral("auto_break")); + m_linkifyEnabled = READBOOL(QStringLiteral("linkify")); } QJsonObject MarkdownEditorConfig::toJson() const @@ -56,6 +59,9 @@ QJsonObject MarkdownEditorConfig::toJson() const obj[QStringLiteral("zoom_factor_in_read_mode")] = m_zoomFactorInReadMode; obj[QStringLiteral("fetch_images_in_parse_and_paste")] = m_fetchImagesInParseAndPaste; obj[QStringLiteral("protect_from_xss")] = m_protectFromXss; + obj[QStringLiteral("html_tag")] = m_htmlTagEnabled; + obj[QStringLiteral("auto_break")] = m_autoBreakEnabled; + obj[QStringLiteral("linkify")] = m_linkifyEnabled; return obj; } @@ -195,3 +201,33 @@ bool MarkdownEditorConfig::getProtectFromXss() const { return m_protectFromXss; } + +bool MarkdownEditorConfig::getHtmlTagEnabled() const +{ + return m_htmlTagEnabled; +} + +void MarkdownEditorConfig::setHtmlTagEnabled(bool p_enabled) +{ + updateConfig(m_htmlTagEnabled, p_enabled, this); +} + +bool MarkdownEditorConfig::getAutoBreakEnabled() const +{ + return m_autoBreakEnabled; +} + +void MarkdownEditorConfig::setAutoBreakEnabled(bool p_enabled) +{ + updateConfig(m_autoBreakEnabled, p_enabled, this); +} + +bool MarkdownEditorConfig::getLinkifyEnabled() const +{ + return m_linkifyEnabled; +} + +void MarkdownEditorConfig::setLinkifyEnabled(bool p_enabled) +{ + updateConfig(m_linkifyEnabled, p_enabled, this); +} diff --git a/src/core/markdowneditorconfig.h b/src/core/markdowneditorconfig.h index c2ae0a91..4a4c40ab 100644 --- a/src/core/markdowneditorconfig.h +++ b/src/core/markdowneditorconfig.h @@ -62,6 +62,15 @@ namespace vnotex bool getProtectFromXss() const; + bool getHtmlTagEnabled() const; + void setHtmlTagEnabled(bool p_enabled); + + bool getAutoBreakEnabled() const; + void setAutoBreakEnabled(bool p_enabled); + + bool getLinkifyEnabled() const; + void setLinkifyEnabled(bool p_enabled); + private: QSharedPointer m_textEditorConfig; @@ -97,6 +106,15 @@ namespace vnotex // Whether protect from Cross-Site Scripting. bool m_protectFromXss = false; + + // Whether allow HTML tag in Markdown source. + bool m_htmlTagEnabled = true; + + // Whether auto break a line with `\n`. + bool m_autoBreakEnabled = false; + + // Whether convert URL-like text to links. + bool m_linkifyEnabled = true; }; } diff --git a/src/data/core/vnotex.json b/src/data/core/vnotex.json index 500b3b7e..7ff2dcdd 100644 --- a/src/data/core/vnotex.json +++ b/src/data/core/vnotex.json @@ -237,7 +237,13 @@ "//comment" : "Whether fetch images to local in Parse To Markdown And Paste", "fetch_images_in_parse_and_paste" : true, "//comment" : "Whether protect from Cross-Site Scripting attack", - "protect_from_xss" : false + "protect_from_xss" : false, + "//comment" : "Whether allow HTML tags in source", + "html_tag" : true, + "//comment" : "Whether auto break a line with '\\n'", + "auto_break" : false, + "//comment" : "Whether convert URL-like text to links", + "linkify" : true } }, "widget" : { diff --git a/src/data/extra/web/js/markdownit.js b/src/data/extra/web/js/markdownit.js index 30d11f0a..3b07b546 100644 --- a/src/data/extra/web/js/markdownit.js +++ b/src/data/extra/web/js/markdownit.js @@ -94,6 +94,12 @@ class MarkdownIt extends VxWorker { this.name = 'markdownit'; this.options = p_options; + if (!this.options) { + this.options = new MarkdownItOptions(); + this.options.enableHtmlTag = window.vxOptions.htmlTagEnabled; + this.options.enableAutoBreaks = window.vxOptions.autoBreakEnabled; + this.options.enableLinkify = window.vxOptions.linkifyEnabled; + } // Languages of code blocks that need to skip highlight. this.langsToSkipHighlight = new Set(); @@ -332,4 +338,4 @@ class MarkdownIt extends VxWorker { } } -window.vnotex.registerWorker(new MarkdownIt(new MarkdownItOptions())); +window.vnotex.registerWorker(new MarkdownIt(null)); diff --git a/src/widgets/dialogs/settings/markdowneditorpage.cpp b/src/widgets/dialogs/settings/markdowneditorpage.cpp index 85a15d8e..4363751e 100644 --- a/src/widgets/dialogs/settings/markdowneditorpage.cpp +++ b/src/widgets/dialogs/settings/markdowneditorpage.cpp @@ -1,7 +1,9 @@ #include "markdowneditorpage.h" #include +#include #include +#include #include #include @@ -20,57 +22,13 @@ MarkdownEditorPage::MarkdownEditorPage(QWidget *p_parent) void MarkdownEditorPage::setupUI() { - auto mainLayout = new QFormLayout(this); + auto mainLayout = new QVBoxLayout(this); - { - const QString label(tr("Insert file name as title")); - m_insertFileNameAsTitleCheckBox = WidgetsFactory::createCheckBox(label, this); - m_insertFileNameAsTitleCheckBox->setToolTip(tr("Insert file name as title when creating note")); - mainLayout->addRow(m_insertFileNameAsTitleCheckBox); - addSearchItem(label, m_insertFileNameAsTitleCheckBox->toolTip(), m_insertFileNameAsTitleCheckBox); - connect(m_insertFileNameAsTitleCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } + auto readBox = setupReadGroup(); + mainLayout->addWidget(readBox); - { - const QString label(tr("Section number")); - m_sectionNumberCheckBox = WidgetsFactory::createCheckBox(label, this); - m_sectionNumberCheckBox->setToolTip(tr("Display section number of headings in read mode")); - mainLayout->addRow(m_sectionNumberCheckBox); - addSearchItem(label, m_sectionNumberCheckBox->toolTip(), m_sectionNumberCheckBox); - connect(m_sectionNumberCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } - - { - const QString label(tr("Constrain image width")); - m_constrainImageWidthCheckBox = WidgetsFactory::createCheckBox(label, this); - m_constrainImageWidthCheckBox->setToolTip(tr("Constrain image width to the window")); - mainLayout->addRow(m_constrainImageWidthCheckBox); - addSearchItem(label, m_constrainImageWidthCheckBox->toolTip(), m_constrainImageWidthCheckBox); - connect(m_constrainImageWidthCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } - - { - const QString label(tr("Constrain in-place preview width")); - m_constrainInPlacePreviewWidthCheckBox = WidgetsFactory::createCheckBox(label, this); - m_constrainInPlacePreviewWidthCheckBox->setToolTip(tr("Constrain in-place preview width to the window")); - mainLayout->addRow(m_constrainInPlacePreviewWidthCheckBox); - addSearchItem(label, m_constrainInPlacePreviewWidthCheckBox->toolTip(), m_constrainInPlacePreviewWidthCheckBox); - connect(m_constrainInPlacePreviewWidthCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } - - { - const QString label(tr("Fetch images to local in Parse And Paste")); - m_fetchImagesToLocalCheckBox = WidgetsFactory::createCheckBox(label, this); - m_fetchImagesToLocalCheckBox->setToolTip(tr("Fetch images to local in Parse To Markdown And Paste")); - mainLayout->addRow(m_fetchImagesToLocalCheckBox); - addSearchItem(label, m_fetchImagesToLocalCheckBox->toolTip(), m_fetchImagesToLocalCheckBox); - connect(m_fetchImagesToLocalCheckBox, &QCheckBox::stateChanged, - this, &MarkdownEditorPage::pageIsChanged); - } + auto editBox = setupEditGroup(); + mainLayout->addWidget(editBox); } void MarkdownEditorPage::loadInternal() @@ -86,6 +44,12 @@ void MarkdownEditorPage::loadInternal() m_constrainInPlacePreviewWidthCheckBox->setChecked(markdownConfig.getConstrainInPlacePreviewWidthEnabled()); m_fetchImagesToLocalCheckBox->setChecked(markdownConfig.getFetchImagesInParseAndPaste()); + + m_htmlTagCheckBox->setChecked(markdownConfig.getHtmlTagEnabled()); + + m_autoBreakCheckBox->setChecked(markdownConfig.getAutoBreakEnabled()); + + m_linkifyCheckBox->setChecked(markdownConfig.getLinkifyEnabled()); } void MarkdownEditorPage::saveInternal() @@ -102,6 +66,12 @@ void MarkdownEditorPage::saveInternal() markdownConfig.setFetchImagesInParseAndPaste(m_fetchImagesToLocalCheckBox->isChecked()); + markdownConfig.setHtmlTagEnabled(m_htmlTagCheckBox->isChecked()); + + markdownConfig.setAutoBreakEnabled(m_autoBreakCheckBox->isChecked()); + + markdownConfig.setLinkifyEnabled(m_linkifyCheckBox->isChecked()); + EditorPage::notifyEditorConfigChange(); } @@ -109,3 +79,99 @@ QString MarkdownEditorPage::title() const { return tr("Markdown Editor"); } + +QGroupBox *MarkdownEditorPage::setupReadGroup() +{ + auto box = new QGroupBox(tr("Read"), this); + auto layout = new QFormLayout(box); + + { + const QString label(tr("Section number")); + m_sectionNumberCheckBox = WidgetsFactory::createCheckBox(label, box); + m_sectionNumberCheckBox->setToolTip(tr("Display section number of headings in read mode")); + layout->addRow(m_sectionNumberCheckBox); + addSearchItem(label, m_sectionNumberCheckBox->toolTip(), m_sectionNumberCheckBox); + connect(m_sectionNumberCheckBox, &QCheckBox::stateChanged, + this, &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Constrain image width")); + m_constrainImageWidthCheckBox = WidgetsFactory::createCheckBox(label, box); + m_constrainImageWidthCheckBox->setToolTip(tr("Constrain image width to the window")); + layout->addRow(m_constrainImageWidthCheckBox); + addSearchItem(label, m_constrainImageWidthCheckBox->toolTip(), m_constrainImageWidthCheckBox); + connect(m_constrainImageWidthCheckBox, &QCheckBox::stateChanged, + this, &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("HTML tag")); + m_htmlTagCheckBox = WidgetsFactory::createCheckBox(label, box); + m_htmlTagCheckBox->setToolTip(tr("Allow HTML tags in source")); + layout->addRow(m_htmlTagCheckBox); + addSearchItem(label, m_htmlTagCheckBox->toolTip(), m_htmlTagCheckBox); + connect(m_htmlTagCheckBox, &QCheckBox::stateChanged, + this, &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Auto break")); + m_autoBreakCheckBox = WidgetsFactory::createCheckBox(label, box); + m_autoBreakCheckBox->setToolTip(tr("Automatically break a line with '\\n'")); + layout->addRow(m_autoBreakCheckBox); + addSearchItem(label, m_autoBreakCheckBox->toolTip(), m_autoBreakCheckBox); + connect(m_autoBreakCheckBox, &QCheckBox::stateChanged, + this, &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Linkify")); + m_linkifyCheckBox = WidgetsFactory::createCheckBox(label, box); + m_linkifyCheckBox->setToolTip(tr("Convert URL-like text to links")); + layout->addRow(m_linkifyCheckBox); + addSearchItem(label, m_linkifyCheckBox->toolTip(), m_linkifyCheckBox); + connect(m_linkifyCheckBox, &QCheckBox::stateChanged, + this, &MarkdownEditorPage::pageIsChanged); + } + + return box; +} + +QGroupBox *MarkdownEditorPage::setupEditGroup() +{ + auto box = new QGroupBox(tr("Edit"), this); + auto layout = new QFormLayout(box); + + { + const QString label(tr("Insert file name as title")); + m_insertFileNameAsTitleCheckBox = WidgetsFactory::createCheckBox(label, box); + m_insertFileNameAsTitleCheckBox->setToolTip(tr("Insert file name as title when creating note")); + layout->addRow(m_insertFileNameAsTitleCheckBox); + addSearchItem(label, m_insertFileNameAsTitleCheckBox->toolTip(), m_insertFileNameAsTitleCheckBox); + connect(m_insertFileNameAsTitleCheckBox, &QCheckBox::stateChanged, + this, &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Constrain in-place preview width")); + m_constrainInPlacePreviewWidthCheckBox = WidgetsFactory::createCheckBox(label, box); + m_constrainInPlacePreviewWidthCheckBox->setToolTip(tr("Constrain in-place preview width to the window")); + layout->addRow(m_constrainInPlacePreviewWidthCheckBox); + addSearchItem(label, m_constrainInPlacePreviewWidthCheckBox->toolTip(), m_constrainInPlacePreviewWidthCheckBox); + connect(m_constrainInPlacePreviewWidthCheckBox, &QCheckBox::stateChanged, + this, &MarkdownEditorPage::pageIsChanged); + } + + { + const QString label(tr("Fetch images to local in Parse And Paste")); + m_fetchImagesToLocalCheckBox = WidgetsFactory::createCheckBox(label, box); + m_fetchImagesToLocalCheckBox->setToolTip(tr("Fetch images to local in Parse To Markdown And Paste")); + layout->addRow(m_fetchImagesToLocalCheckBox); + addSearchItem(label, m_fetchImagesToLocalCheckBox->toolTip(), m_fetchImagesToLocalCheckBox); + connect(m_fetchImagesToLocalCheckBox, &QCheckBox::stateChanged, + this, &MarkdownEditorPage::pageIsChanged); + } + + return box; +} diff --git a/src/widgets/dialogs/settings/markdowneditorpage.h b/src/widgets/dialogs/settings/markdowneditorpage.h index a2e797d0..57880257 100644 --- a/src/widgets/dialogs/settings/markdowneditorpage.h +++ b/src/widgets/dialogs/settings/markdowneditorpage.h @@ -4,6 +4,7 @@ #include "settingspage.h" class QCheckBox; +class QGroupBox; namespace vnotex { @@ -23,6 +24,10 @@ namespace vnotex private: void setupUI(); + QGroupBox *setupReadGroup(); + + QGroupBox *setupEditGroup(); + QCheckBox *m_insertFileNameAsTitleCheckBox = nullptr; QCheckBox *m_sectionNumberCheckBox = nullptr; @@ -32,6 +37,12 @@ namespace vnotex QCheckBox *m_constrainInPlacePreviewWidthCheckBox = nullptr; QCheckBox *m_fetchImagesToLocalCheckBox = nullptr; + + QCheckBox *m_htmlTagCheckBox = nullptr; + + QCheckBox *m_autoBreakCheckBox = nullptr; + + QCheckBox *m_linkifyCheckBox = nullptr; }; } diff --git a/src/widgets/dialogs/settings/settingsdialog.cpp b/src/widgets/dialogs/settings/settingsdialog.cpp index 627436ec..6f9ac3f1 100644 --- a/src/widgets/dialogs/settings/settingsdialog.cpp +++ b/src/widgets/dialogs/settings/settingsdialog.cpp @@ -49,7 +49,7 @@ void SettingsDialog::setupPageExplorer(QBoxLayout *p_layout, QWidget *p_parent) auto layout = new QVBoxLayout(); m_searchEdit = WidgetsFactory::createLineEdit(p_parent); - m_searchEdit->setPlaceholderText(tr("Type to search")); + m_searchEdit->setPlaceholderText(tr("Search")); layout->addWidget(m_searchEdit); m_pageExplorer = new TreeWidget(TreeWidget::None, p_parent); diff --git a/src/widgets/findandreplacewidget.cpp b/src/widgets/findandreplacewidget.cpp index 84a12bab..b27f1b3e 100644 --- a/src/widgets/findandreplacewidget.cpp +++ b/src/widgets/findandreplacewidget.cpp @@ -73,7 +73,7 @@ void FindAndReplaceWidget::setupUI() auto label = new QLabel(tr("Find:"), this); m_findLineEdit = WidgetsFactory::createLineEdit(this); - m_findLineEdit->setPlaceholderText(tr("Type to search")); + m_findLineEdit->setPlaceholderText(tr("Search")); connect(m_findLineEdit, &QLineEdit::textChanged, m_findTextTimer, QOverload<>::of(&QTimer::start));