diff --git a/src/render_tree.js b/src/render_tree.js index 88dc7296..38bc73bf 100644 --- a/src/render_tree.js +++ b/src/render_tree.js @@ -25,7 +25,7 @@ define(['./core', './markdown_helpers'], function(Markdown, MarkdownHelpers) { var content = []; if ( options.root ) { - content.push( render_tree( jsonml ) ); + content.push( render_tree( jsonml, options ) ); } else { jsonml.shift(); // get rid of the tag @@ -33,7 +33,7 @@ define(['./core', './markdown_helpers'], function(Markdown, MarkdownHelpers) { jsonml.shift(); // get rid of the attributes while ( jsonml.length ) - content.push( render_tree( jsonml.shift() ) ); + content.push( render_tree( jsonml.shift(), options ) ); } return content.join( "\n\n" ); @@ -83,7 +83,7 @@ define(['./core', './markdown_helpers'], function(Markdown, MarkdownHelpers) { Markdown.toHTML = function toHTML( source , dialect , options ) { var input = this.toHTMLTree( source , dialect , options ); - return this.renderJsonML( input ); + return this.renderJsonML( input, options ); }; @@ -95,10 +95,15 @@ define(['./core', './markdown_helpers'], function(Markdown, MarkdownHelpers) { .replace( /'/g, "'" ); } - function render_tree( jsonml ) { + function K(input) { return input; } + + function render_tree( jsonml, options ) { // basic case + + var sanitize = (options.sanitize !== false) ? escapeHTML : K; + if ( typeof jsonml === "string" ) - return escapeHTML( jsonml ); + return sanitize( jsonml ); var tag = jsonml.shift(), attributes = {}, @@ -108,11 +113,16 @@ define(['./core', './markdown_helpers'], function(Markdown, MarkdownHelpers) { attributes = jsonml.shift(); while ( jsonml.length ) - content.push( render_tree( jsonml.shift() ) ); + content.push( render_tree( jsonml.shift(), options ) ); var tag_attrs = ""; + if (typeof attributes.src !== 'undefined') { + tag_attrs += ' src="' + sanitize( attributes.src ) + '"'; + delete attributes.src; + } + for ( var a in attributes ) - tag_attrs += " " + a + '="' + escapeHTML( attributes[ a ] ) + '"'; + tag_attrs += " " + a + '="' + sanitize( attributes[ a ] ) + '"'; // be careful about adding whitespace here for inline elements if ( tag === "img" || tag === "br" || tag === "hr" ) diff --git a/test/features.t.js b/test/features.t.js index 48ec6664..4d80fe7f 100644 --- a/test/features.t.js +++ b/test/features.t.js @@ -1,4 +1,5 @@ -var markdown = require("../src/markdown"); +var markdown = require("../src/markdown"), + tap = require("tap"); function test_dialect( dialect, features ) { var fs = require("fs"), @@ -80,3 +81,10 @@ dialects.Maruku.push( "meta", "definition_lists", "tables" ); for ( var d in dialects ) { test_dialect( d, dialects[ d ] ); } + + +tap.test("src attribute order", function(t) { + var tree = markdown.toHTML("![photo](/images/photo.jpg)"); + t.equivalent( tree, '

photo

' ); + t.end(); +}); \ No newline at end of file diff --git a/test/html_renderer.t.js b/test/html_renderer.t.js new file mode 100644 index 00000000..d0d6d6ab --- /dev/null +++ b/test/html_renderer.t.js @@ -0,0 +1,22 @@ +var markdown = require("../src/markdown"), + tap = require("tap"); + +tap.test("src attribute order", function(t) { + var tree = markdown.toHTML("![photo](/images/photo.jpg)"); + t.equivalent( tree, '

photo

' ); + t.end(); +}); + +tap.test("HTML Sanitizing", function(t) { + var input = "hello "; + + t.equivalent( markdown.toHTML(input, 'Gruber'), + '

hello <world>

', + "escapes by default" ); + + t.equivalent( markdown.toHTML(input, 'Gruber', {sanitize: false}), + '

hello

', + "sanitization can be disabled" ); + + t.end(); +});