diff --git a/core/shared/vendor/showdown/extensions/github.js b/core/shared/vendor/showdown/extensions/github.js index 367d6eee20..48259bdff3 100644 --- a/core/shared/vendor/showdown/extensions/github.js +++ b/core/shared/vendor/showdown/extensions/github.js @@ -16,11 +16,10 @@ } }, { - // GFM newline and underscore modifications + // GFM newline and underscore modifications, happen BEFORE showdown type : 'lang', filter : function (text) { - var extractions = {}, - imageMarkdownRegex = /^(?:\{(.*?)\})?!(?:\[([^\n\]]*)\])(?:\(([^\n\]]*)\))?$/gim, + var preExtractions = {}, hashID = 0; function hashId() { @@ -30,19 +29,10 @@ // Extract pre blocks text = text.replace(/
[\s\S]*?<\/pre>/gim, function (x) { var hash = hashId(); - extractions[hash] = x; + preExtractions[hash] = x; return "{gfm-js-extract-pre-" + hash + "}"; }, 'm'); - // better URL support, but no title support - text = text.replace(imageMarkdownRegex, function (match, key, alt, src) { - if (src) { - return ''; - } - - return ''; - }); - //prevent foo_bar and foo_bar_baz from ending up with an italic word in the middle text = text.replace(/(^(?! {4}|\t)\w+_\w+_\w[\w_]*)/gm, function (x) { return x.replace(/_/gm, '\\_'); @@ -53,8 +43,9 @@ return x.match(/\n{2}/) ? x : x.trim() + " \n"; }); + text = text.replace(/\{gfm-js-extract-pre-([0-9]+)\}/gm, function (x, y) { - return "\n\n" + extractions[y]; + return "\n\n" + preExtractions[y]; }); @@ -62,25 +53,43 @@ } }, { - // Auto-link URLs and emails - type : 'lang', + // GFM autolinking & custom image handling, happens AFTER showdown + type : 'html', filter : function (text) { - var extractions = {}, + var refExtractions = {}, + preExtractions = {}, + imageMarkdownRegex = /^(?:\{(.*?)\})?!(?:\[([^\n\]]*)\])(?:\(([^\n\]]*)\))?$/gim, hashID = 0; function hashId() { return hashID++; } + // Extract pre blocks + text = text.replace(/<(pre|code)>[\s\S]*?<\/(\1)>/gim, function (x) { + var hash = hashId(); + preExtractions[hash] = x; + return "{gfm-js-extract-pre-" + hash + "}"; + }, 'm'); + // filter out def urls // from Marked https://github.com/chjj/marked/blob/master/lib/marked.js#L24 text = text.replace(/^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/gmi, function (x) { var hash = hashId(); - extractions[hash] = x; + refExtractions[hash] = x; return "{gfm-js-extract-ref-url-" + hash + "}"; }); + // better URL support, but no title support + text = text.replace(imageMarkdownRegex, function (match, key, alt, src) { + if (src) { + return '
'; + } + + return ''; + }); + // match a URL // adapted from https://gist.github.com/jorilallo/1283095#L158 // and http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript @@ -95,13 +104,18 @@ return lookBehind ? wholeMatch : "" + wholeMatch + ""; }); - // match emil + // match email text = text.replace(/[a-z0-9_\-+=.]+@[a-z0-9\-]+(\.[a-z0-9-]+)+/gmi, function (wholeMatch) { return "" + wholeMatch + ""; }); + // replace extractions + text = text.replace(/\{gfm-js-extract-pre-([0-9]+)\}/gm, function (x, y) { + return preExtractions[y]; + }); + text = text.replace(/\{gfm-js-extract-ref-url-([0-9]+)\}/gi, function (x, y) { - return "\n\n" + extractions[y]; + return "\n\n" + refExtractions[y]; }); return text; diff --git a/core/test/unit/client_showdown_int_spec.js b/core/test/unit/client_showdown_int_spec.js index 1b427c2f2b..ff95c524b5 100644 --- a/core/test/unit/client_showdown_int_spec.js +++ b/core/test/unit/client_showdown_int_spec.js @@ -178,7 +178,7 @@ describe("Showdown client side converter", function () { }, { input: "# http://google.co.uk", - output: /^
http:\/\/google.co.uk<\/a><\/h1>$/ + output: /^
http:\/\/google.co.uk<\/a><\/h1>$/ }, { input: "* http://google.co.uk", @@ -279,6 +279,30 @@ describe("Showdown client side converter", function () { }); }); + it("should NOT auto-link URLS inside of code/pre blocks", function () { + var testPhrases = [ + { + input: "```\nurl: http://google.co.uk\n```", + output: /^
url: http:\/\/google.co.uk \n<\/code><\/pre>$/ + }, + { + input: "`url: http://google.co.uk`", + output: /^
url: http:\/\/google.co.uk<\/code><\/p>$/ + }, + { + input: "Hello type some `url: http://google.co.uk` stuff", + output: /^
Hello type some
url: http:\/\/google.co.uk<\/code> stuff<\/p>$/ + } + + ], + processedMarkup; + + testPhrases.forEach(function (testPhrase) { + processedMarkup = converter.makeHtml(testPhrase.input); + processedMarkup.should.match(testPhrase.output); + }); + }); + it("should not display anything for reference URL", function () { var testPhrases = [ {