diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js
index d0e2f505..98c1942b 100644
--- a/browser/components/MarkdownEditor.js
+++ b/browser/components/MarkdownEditor.js
@@ -280,6 +280,7 @@ class MarkdownEditor extends React.Component {
indentSize={editorIndentSize}
scrollPastEnd={config.preview.scrollPastEnd}
smartQuotes={config.preview.smartQuotes}
+ sanitize={config.preview.sanitize}
ref='preview'
onContextMenu={(e) => this.handleContextMenu(e)}
onDoubleClick={(e) => this.handleDoubleClick(e)}
diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js
index e4298a71..bd5d3939 100755
--- a/browser/components/MarkdownPreview.js
+++ b/browser/components/MarkdownPreview.js
@@ -135,8 +135,11 @@ export default class MarkdownPreview extends React.Component {
}
initMarkdown () {
- const { smartQuotes } = this.props
- this.markdown = new Markdown({ typographer: smartQuotes })
+ const { smartQuotes, sanitize } = this.props
+ this.markdown = new Markdown({
+ typographer: smartQuotes,
+ sanitize
+ })
}
handlePreviewAnchorClick (e) {
@@ -318,7 +321,7 @@ export default class MarkdownPreview extends React.Component {
componentDidUpdate (prevProps) {
if (prevProps.value !== this.props.value) this.rewriteIframe()
- if (prevProps.smartQuotes !== this.props.smartQuotes) {
+ if (prevProps.smartQuotes !== this.props.smartQuotes || prevProps.sanitize !== this.props.sanitize) {
this.initMarkdown()
this.rewriteIframe()
}
diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js
index 0aa2d16c..945f5d62 100644
--- a/browser/components/MarkdownSplitEditor.js
+++ b/browser/components/MarkdownSplitEditor.js
@@ -128,6 +128,7 @@ class MarkdownSplitEditor extends React.Component {
lineNumber={config.preview.lineNumber}
scrollPastEnd={config.preview.scrollPastEnd}
smartQuotes={config.preview.smartQuotes}
+ sanitize={config.preview.sanitize}
ref='preview'
tabInde='0'
value={value}
diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js
index ee38c27d..6f1f2f00 100644
--- a/browser/lib/markdown.js
+++ b/browser/lib/markdown.js
@@ -45,52 +45,62 @@ class Markdown {
'' +
str +
''
- }
+ },
+ sanitize: 'STRICT'
}
const updatedOptions = Object.assign(defaultOptions, options)
this.md = markdownit(updatedOptions)
- // Sanitize use rinput before other plugins
- this.md.use(sanitize, {
- allowedTags: ['iframe', 'input', 'b',
+ if (updatedOptions.sanitize !== 'NONE') {
+ const allowedTags = ['iframe', 'input', 'b',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'br', 'b', 'i', 'strong', 'em', 'a', 'pre', 'code', 'img', 'tt',
'div', 'ins', 'del', 'sup', 'sub', 'p', 'ol', 'ul', 'table', 'thead', 'tbody', 'tfoot', 'blockquote',
'dl', 'dt', 'dd', 'kbd', 'q', 'samp', 'var', 'hr', 'ruby', 'rt', 'rp', 'li', 'tr', 'td', 'th', 's', 'strike', 'summary', 'details'
- ],
- allowedAttributes: {
- '*': [
- 'style',
- 'abbr', 'accept', 'accept-charset',
- 'accesskey', 'action', 'align', 'alt', 'axis',
- 'border', 'cellpadding', 'cellspacing', 'char',
- 'charoff', 'charset', 'checked',
- 'clear', 'cols', 'colspan', 'color',
- 'compact', 'coords', 'datetime', 'dir',
- 'disabled', 'enctype', 'for', 'frame',
- 'headers', 'height', 'hreflang',
- 'hspace', 'ismap', 'label', 'lang',
- 'maxlength', 'media', 'method',
- 'multiple', 'name', 'nohref', 'noshade',
- 'nowrap', 'open', 'prompt', 'readonly', 'rel', 'rev',
- 'rows', 'rowspan', 'rules', 'scope',
- 'selected', 'shape', 'size', 'span',
- 'start', 'summary', 'tabindex', 'target',
- 'title', 'type', 'usemap', 'valign', 'value',
- 'vspace', 'width', 'itemprop'
- ],
- 'a': ['href'],
- 'div': ['itemscope', 'itemtype'],
- 'blockquote': ['cite'],
- 'del': ['cite'],
- 'ins': ['cite'],
- 'q': ['cite'],
- 'img': ['src', 'width', 'height'],
- 'iframe': ['src', 'width', 'height', 'frameborder', 'allowfullscreen'],
- 'input': ['type', 'id', 'checked']
- },
- allowedIframeHostnames: ['www.youtube.com']
- })
+ ]
+ const allowedAttributes = [
+ 'abbr', 'accept', 'accept-charset',
+ 'accesskey', 'action', 'align', 'alt', 'axis',
+ 'border', 'cellpadding', 'cellspacing', 'char',
+ 'charoff', 'charset', 'checked',
+ 'clear', 'cols', 'colspan', 'color',
+ 'compact', 'coords', 'datetime', 'dir',
+ 'disabled', 'enctype', 'for', 'frame',
+ 'headers', 'height', 'hreflang',
+ 'hspace', 'ismap', 'label', 'lang',
+ 'maxlength', 'media', 'method',
+ 'multiple', 'name', 'nohref', 'noshade',
+ 'nowrap', 'open', 'prompt', 'readonly', 'rel', 'rev',
+ 'rows', 'rowspan', 'rules', 'scope',
+ 'selected', 'shape', 'size', 'span',
+ 'start', 'summary', 'tabindex', 'target',
+ 'title', 'type', 'usemap', 'valign', 'value',
+ 'vspace', 'width', 'itemprop'
+ ]
+
+ if (updatedOptions.sanitize === 'ALLOW_STYLES') {
+ allowedTags.push('style')
+ allowedAttributes.push('style')
+ }
+
+ // Sanitize use rinput before other plugins
+ this.md.use(sanitize, {
+ allowedTags,
+ allowedAttributes: {
+ '*': allowedAttributes,
+ 'a': ['href'],
+ 'div': ['itemscope', 'itemtype'],
+ 'blockquote': ['cite'],
+ 'del': ['cite'],
+ 'ins': ['cite'],
+ 'q': ['cite'],
+ 'img': ['src', 'width', 'height'],
+ 'iframe': ['src', 'width', 'height', 'frameborder', 'allowfullscreen'],
+ 'input': ['type', 'id', 'checked']
+ },
+ allowedIframeHostnames: ['www.youtube.com']
+ })
+ }
this.md.use(emoji, {
shortcuts: {}
diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js
index 40b89198..ff220348 100644
--- a/browser/main/lib/ConfigManager.js
+++ b/browser/main/lib/ConfigManager.js
@@ -51,7 +51,8 @@ export const DEFAULT_CONFIG = {
latexBlockOpen: '$$',
latexBlockClose: '$$',
scrollPastEnd: false,
- smartQuotes: true
+ smartQuotes: true,
+ sanitize: 'STRICT' // 'STRICT', 'ALLOW_STYLES', 'NONE'
},
blog: {
type: 'wordpress', // Available value: wordpress, add more types in the future plz
diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js
index 81e29746..708dd82a 100644
--- a/browser/main/modals/PreferencesModal/UiTab.js
+++ b/browser/main/modals/PreferencesModal/UiTab.js
@@ -91,7 +91,8 @@ class UiTab extends React.Component {
latexBlockOpen: this.refs.previewLatexBlockOpen.value,
latexBlockClose: this.refs.previewLatexBlockClose.value,
scrollPastEnd: this.refs.previewScrollPastEnd.checked,
- smartQuotes: this.refs.previewSmartQuotes.checked
+ smartQuotes: this.refs.previewSmartQuotes.checked,
+ sanitize: this.refs.previewSanitize.value
}
}
@@ -441,6 +442,23 @@ class UiTab extends React.Component {
Enable smart quotes
+
+