From 19eab7d1fc0bdd8c9b5ce00532cb183f0cab36b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20H=C3=A4usler?= Date: Thu, 17 Dec 2020 23:19:22 +0100 Subject: [PATCH] Add option to disable HTML rendering (#2414) --- src/main/preferences/schema.json | 5 +++++ src/muya/lib/config/index.js | 5 ++++- src/muya/lib/contentState/pasteCtrl.js | 3 ++- src/muya/lib/parser/marked/options.js | 4 +++- .../render/renderBlock/renderLeafBlock.js | 3 ++- src/muya/lib/utils/exportHtml.js | 8 ++++---- src/muya/lib/utils/index.js | 20 +++++++++++++++++-- .../components/editorWithTabs/editor.vue | 10 ++++++++++ .../prefComponents/markdown/index.vue | 6 ++++++ src/renderer/store/preferences.js | 1 + static/preference.json | 1 + 11 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/main/preferences/schema.json b/src/main/preferences/schema.json index ddf2fff2..f0010599 100644 --- a/src/main/preferences/schema.json +++ b/src/main/preferences/schema.json @@ -289,6 +289,11 @@ "type": "boolean", "default": false }, + "isHtmlEnabled": { + "description": "Markdown-Enable HTML rendering", + "type": "boolean", + "default": true + }, "isGitlabCompatibilityEnabled": { "description": "Markdown-Enable GitLab compatibility mode.", "type": "boolean", diff --git a/src/muya/lib/config/index.js b/src/muya/lib/config/index.js index 18e576fb..ba4a8326 100644 --- a/src/muya/lib/config/index.js +++ b/src/muya/lib/config/index.js @@ -283,7 +283,10 @@ export const MUYA_DEFAULT_OPTION = Object.freeze({ // Markdown extensions superSubScript: false, footnote: false, - isGitlabCompatibilityEnabled: false + isGitlabCompatibilityEnabled: false, + + // Whether HTML rendering is disabled or not. + disableHtml: true }) // export const DIAGRAM_TEMPLATE = Object.freeze({ diff --git a/src/muya/lib/contentState/pasteCtrl.js b/src/muya/lib/contentState/pasteCtrl.js index 5fe883ee..e7753771 100644 --- a/src/muya/lib/contentState/pasteCtrl.js +++ b/src/muya/lib/contentState/pasteCtrl.js @@ -74,7 +74,8 @@ const pasteCtrl = ContentState => { } // Prevent XSS and sanitize HTML. - const sanitizedHtml = sanitize(html, PREVIEW_DOMPURIFY_CONFIG) + const { disableHtml } = this.muya.options + const sanitizedHtml = sanitize(html, PREVIEW_DOMPURIFY_CONFIG, disableHtml) const tempWrapper = document.createElement('div') tempWrapper.innerHTML = sanitizedHtml diff --git a/src/muya/lib/parser/marked/options.js b/src/muya/lib/parser/marked/options.js index 4c1399cd..8a8db848 100644 --- a/src/muya/lib/parser/marked/options.js +++ b/src/muya/lib/parser/marked/options.js @@ -30,5 +30,7 @@ export default { frontMatter: true, superSubScript: false, footnote: false, - isGitlabCompatibilityEnabled: false + isGitlabCompatibilityEnabled: false, + + isHtmlEnabled: true } diff --git a/src/muya/lib/parser/render/renderBlock/renderLeafBlock.js b/src/muya/lib/parser/render/renderBlock/renderLeafBlock.js index 58f51774..4cf27c4d 100644 --- a/src/muya/lib/parser/render/renderBlock/renderLeafBlock.js +++ b/src/muya/lib/parser/render/renderBlock/renderLeafBlock.js @@ -132,7 +132,8 @@ export default function renderLeafBlock (parent, block, activeBlocks, matches, u selector += `.${CLASS_OR_ID.AG_HTML_PREVIEW}` Object.assign(data.attrs, { spellcheck: 'false' }) - const htmlContent = sanitize(code, PREVIEW_DOMPURIFY_CONFIG) + const { disableHtml } = this.muya.options + const htmlContent = sanitize(code, PREVIEW_DOMPURIFY_CONFIG, disableHtml) // handle empty html bock if (/^<([a-z][a-z\d]*)[^>]*?>(\s*)<\/\1>$/.test(htmlContent.trim())) { diff --git a/src/muya/lib/utils/exportHtml.js b/src/muya/lib/utils/exportHtml.js index 02ee4412..a4a91889 100644 --- a/src/muya/lib/utils/exportHtml.js +++ b/src/muya/lib/utils/exportHtml.js @@ -13,7 +13,7 @@ import { validEmoji } from '../ui/emojis' export const getSanitizeHtml = (markdown, options) => { const html = marked(markdown, options) - return sanitize(html, EXPORT_DOMPURIFY_CONFIG) + return sanitize(html, EXPORT_DOMPURIFY_CONFIG, false) } const DIAGRAM_TYPE = [ @@ -143,7 +143,7 @@ class ExportHtml { mathRenderer: this.mathRenderer }) - html = sanitize(html, EXPORT_DOMPURIFY_CONFIG) + html = sanitize(html, EXPORT_DOMPURIFY_CONFIG, false) const exportContainer = this.exportContainer = document.createElement('div') exportContainer.classList.add('ag-render-container') @@ -192,7 +192,7 @@ class ExportHtml { - ${sanitize(title, EXPORT_DOMPURIFY_CONFIG)} + ${sanitize(title, EXPORT_DOMPURIFY_CONFIG, true)} @@ -304,7 +304,7 @@ class ExportHtml { } output = output + createTableBody(html) + HF_TABLE_END - return sanitize(output, EXPORT_DOMPURIFY_CONFIG) + return sanitize(output, EXPORT_DOMPURIFY_CONFIG, false) } } diff --git a/src/muya/lib/utils/index.js b/src/muya/lib/utils/index.js index 98392db2..98ce56a9 100644 --- a/src/muya/lib/utils/index.js +++ b/src/muya/lib/utils/index.js @@ -6,6 +6,14 @@ let id = 0 const TIMEOUT = 1500 +const HTML_TAG_REPLACEMENTS = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' +} + export const getUniqueId = () => `${ID_PREFIX}${id++}` export const getLongUniqueId = () => `${getUniqueId()}-${(+new Date()).toString(32)}` @@ -322,6 +330,10 @@ export const escapeInBlockHtml = html => { }) } +export const escapeHtmlTags = html => { + return html.replace(/[&<>"']/g, x => { return HTML_TAG_REPLACEMENTS[x] }) +} + export const wordCount = markdown => { const paragraph = markdown.split(/\n{2,}/).filter(line => line).length let word = 0 @@ -363,8 +375,12 @@ export const mixins = (constructor, ...object) => { return Object.assign(constructor.prototype, ...object) } -export const sanitize = (html, options) => { - return runSanitize(escapeInBlockHtml(html), options) +export const sanitize = (html, purifyOptions, disableHtml) => { + if (disableHtml) { + return runSanitize(escapeHtmlTags(html), purifyOptions) + } else { + return runSanitize(escapeInBlockHtml(html), purifyOptions) + } } export const getParagraphReference = (ele, id) => { diff --git a/src/renderer/components/editorWithTabs/editor.vue b/src/renderer/components/editorWithTabs/editor.vue index febd64a0..8cc7bc01 100644 --- a/src/renderer/components/editorWithTabs/editor.vue +++ b/src/renderer/components/editorWithTabs/editor.vue @@ -140,6 +140,7 @@ export default { frontmatterType: state => state.preferences.frontmatterType, superSubScript: state => state.preferences.superSubScript, footnote: state => state.preferences.footnote, + isHtmlEnabled: state => state.preferences.isHtmlEnabled, isGitlabCompatibilityEnabled: state => state.preferences.isGitlabCompatibilityEnabled, lineHeight: state => state.preferences.lineHeight, fontSize: state => state.preferences.fontSize, @@ -285,6 +286,13 @@ export default { } }, + isHtmlEnabled: function (value, oldValue) { + const { editor } = this + if (value !== oldValue && editor) { + editor.setOptions({ disableHtml: !value }, true) + } + }, + isGitlabCompatibilityEnabled: function (value, oldValue) { const { editor } = this if (value !== oldValue && editor) { @@ -525,6 +533,7 @@ export default { frontmatterType, superSubScript, footnote, + isHtmlEnabled, isGitlabCompatibilityEnabled, hideQuickInsertHint, editorLineWidth, @@ -573,6 +582,7 @@ export default { frontmatterType, superSubScript, footnote, + disableHtml: !isHtmlEnabled, isGitlabCompatibilityEnabled, hideQuickInsertHint, hideLinkPopup, diff --git a/src/renderer/prefComponents/markdown/index.vue b/src/renderer/prefComponents/markdown/index.vue index e7855e44..dadc74c0 100644 --- a/src/renderer/prefComponents/markdown/index.vue +++ b/src/renderer/prefComponents/markdown/index.vue @@ -62,6 +62,11 @@ >
Compatibility
+ state.preferences.frontmatterType, superSubScript: state => state.preferences.superSubScript, footnote: state => state.preferences.footnote, + isHtmlEnabled: state => state.preferences.isHtmlEnabled, isGitlabCompatibilityEnabled: state => state.preferences.isGitlabCompatibilityEnabled, sequenceTheme: state => state.preferences.sequenceTheme }) diff --git a/src/renderer/store/preferences.js b/src/renderer/store/preferences.js index 2c0e13b6..82489c5d 100644 --- a/src/renderer/store/preferences.js +++ b/src/renderer/store/preferences.js @@ -47,6 +47,7 @@ const state = { frontmatterType: '-', superSubScript: false, footnote: false, + isHtmlEnabled: true, isGitlabCompatibilityEnabled: false, sequenceTheme: 'hand', diff --git a/static/preference.json b/static/preference.json index 5f687534..6e64f7fc 100644 --- a/static/preference.json +++ b/static/preference.json @@ -43,6 +43,7 @@ "frontmatterType": "-", "superSubScript": false, "footnote": false, + "isHtmlEnabled": true, "isGitlabCompatibilityEnabled": false, "sequenceTheme": "hand",