diff --git a/Gruntfile.js b/Gruntfile.js
index cbf70f4dc..7f7e80f32 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -193,7 +193,8 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-migrate-3.0.1.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-ui.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery.ui.touch-punch.min.js",
- "packages/node_modules/@node-red/editor-client/src/vendor/marked/marked.min.js",
+ "node_modules/marked/marked.min.js",
+ "node_modules/dompurify/dist/purify.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/d3/d3.v3.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/i18next/i18next.min.js",
"node_modules/jsonata/jsonata-es5.min.js",
diff --git a/package.json b/package.json
index a6c4c5091..3db93d8c6 100644
--- a/package.json
+++ b/package.json
@@ -75,6 +75,8 @@
"bcrypt": "3.0.6"
},
"devDependencies": {
+ "marked": "0.8.0",
+ "dompurify": "2.0.8",
"grunt": "~1.0.4",
"grunt-chmod": "~1.1.1",
"grunt-cli": "~1.3.2",
diff --git a/packages/node_modules/@node-red/editor-client/src/js/red.js b/packages/node_modules/@node-red/editor-client/src/js/red.js
index a742577d7..f0c11cdd9 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/red.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/red.js
@@ -431,7 +431,7 @@ var RED = (function() {
''+
'';
- RED.sidebar.info.set(aboutHeader+marked(data));
+ RED.sidebar.info.set(aboutHeader+RED.utils.renderMarkdown(data));
RED.sidebar.info.show();
});
}
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js
index c8a93964d..9a9765c35 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js
@@ -102,7 +102,7 @@
var f = $(this).val();
var args = RED._('jsonata:'+f+".args",{defaultValue:''});
var title = "
"+body+"
"); }) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js index 97957eadf..f89c8f3a7 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js @@ -107,7 +107,7 @@ clearTimeout(changeTimer); changeTimer = setTimeout(function() { var currentScrollTop = $(".red-ui-editor-type-markdown-panel-preview").scrollTop(); - $(".red-ui-editor-type-markdown-panel-preview").html(marked(expressionEditor.getValue())); + $(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue())); $(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop); },200); }) @@ -116,7 +116,7 @@ } if (value) { - $(".red-ui-editor-type-markdown-panel-preview").html(marked(expressionEditor.getValue())); + $(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue())); } panels = RED.panels.create({ id:"red-ui-editor-type-markdown-panels", diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js b/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js index 967a61f51..b70854bfa 100755 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js @@ -269,7 +269,7 @@ RED.palette = (function() { RED.view.focus(); var helpText; if (nt.indexOf("subflow:") === 0) { - helpText = marked(RED.nodes.subflow(nt.substring(8)).info||"")||(''+RED._("sidebar.info.none")+''); + helpText = RED.utils.renderMarkdown(RED.nodes.subflow(nt.substring(8)).info||"")||(''+RED._("sidebar.info.none")+''); } else { helpText = $("script[data-help-name='"+d.attr("data-palette-type")+"']").html()||(''+RED._("sidebar.info.none")+''); } @@ -370,7 +370,7 @@ RED.palette = (function() { RED.workspaces.show(nt.substring(8)); e.preventDefault(); }); - nodeInfo = marked(def.info||""); + nodeInfo = RED.utils.renderMarkdown(def.info||""); } setLabel(nt,d,label,nodeInfo); @@ -440,7 +440,7 @@ RED.palette = (function() { } else if (portOutput.length !== 0 && sf.out.length === 0) { portOutput.remove(); } - setLabel(sf.type+":"+sf.id,paletteNode,sf.name,marked(sf.info||"")); + setLabel(sf.type+":"+sf.id,paletteNode,sf.name,RED.utils.renderMarkdown(sf.info||"")); setIcon(paletteNode,sf); var currentCategory = paletteNode.data('category'); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js b/packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js index 2d377ba54..f0944c879 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js @@ -158,7 +158,7 @@ RED.projects.settings = (function() { container.empty(); var desc; if (activeProject.description) { - desc = marked(activeProject.description); + desc = RED.utils.renderMarkdown(activeProject.description); } else { desc = '' + RED._("sidebar.project.noDescriptionAvailable") + ''; } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js index b8e3b150b..bfa4e4b23 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js @@ -15,17 +15,6 @@ **/ RED.sidebar.info = (function() { - marked.setOptions({ - renderer: new marked.Renderer(), - gfm: true, - tables: true, - breaks: false, - pedantic: false, - sanitize: true, - smartLists: true, - smartypants: false - }); - var content; var sections; var propertiesSection; @@ -314,7 +303,7 @@ RED.sidebar.info = (function() { if (subflowNode && node.type !== "subflow") { // Selected a subflow instance node. // - The subflow template info goes into help - helpText = (marked(subflowNode.info||"")||(''+RED._("sidebar.info.none")+'')); + helpText = (RED.utils.renderMarkdown(subflowNode.info||"")||(''+RED._("sidebar.info.none")+'')); } else { helpText = $("script[data-help-name='"+node.type+"']").html()||(''+RED._("sidebar.info.none")+''); } @@ -326,10 +315,10 @@ RED.sidebar.info = (function() { if (node._def && node._def.info) { var info = node._def.info; var textInfo = (typeof info === "function" ? info.call(node) : info); - infoText = infoText + marked(textInfo); + infoText = infoText + RED.utils.renderMarkdown(textInfo); } if (node.info) { - infoText = infoText + marked(node.info || "") + infoText = infoText + RED.utils.renderMarkdown(node.info || "") } setInfoText(infoText, infoSection.content); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js index d35d1f1ba..a9c1c9500 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js @@ -16,6 +16,28 @@ RED.utils = (function() { + window._marked = window.marked; + window.marked = function(txt) { + console.warn("Use of 'marked()' is deprecated. Use RED.utils.renderMarkdown() instead"); + return renderMarkdown(txt); + } + + _marked.setOptions({ + renderer: new _marked.Renderer(), + gfm: true, + tables: true, + breaks: false, + pedantic: false, + smartLists: true, + smartypants: false + }); + + function renderMarkdown(txt) { + var rendered = _marked(txt); + var cleaned = DOMPurify.sanitize(rendered, {SAFE_FOR_JQUERY: true}) + return cleaned; + } + function formatString(str) { return str.replace(/\r?\n/g,"↵").replace(/\t/g,"→"); } @@ -1053,6 +1075,7 @@ RED.utils = (function() { decodeObject: decodeObject, parseContextKey: parseContextKey, createIconElement: createIconElement, - sanitize: sanitize + sanitize: sanitize, + renderMarkdown: renderMarkdown } })(); diff --git a/packages/node_modules/@node-red/editor-client/src/vendor/marked/marked.min.js b/packages/node_modules/@node-red/editor-client/src/vendor/marked/marked.min.js deleted file mode 100644 index 555c1dc1d..000000000 --- a/packages/node_modules/@node-red/editor-client/src/vendor/marked/marked.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * marked - a markdown parser - * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) - * https://github.com/chjj/marked - */ -(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/"+(escaped?code:escape(code,true))+"\n
"}return''+(escaped?code:escape(code,true))+"\n
\n"};Renderer.prototype.blockquote=function(quote){return"\n"+quote+"\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"
"+text+"
\n"};Renderer.prototype.table=function(header,body){return""+text+"
"};Renderer.prototype.br=function(){return this.options.xhtml?""+escape(e.message+"",true)+""}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); \ No newline at end of file