From e411ed68899e3d1f357ca899b7f66b0cb7876071 Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Fri, 27 Sep 2013 11:35:44 +0100 Subject: [PATCH] No autolinking inside of code blocks closes #865 - rejigged markdown to have some functionality before showdown runs, and other functionality before. - autolinking now happens last, so it can be smarter --- .../vendor/showdown/extensions/github.js | 54 ++++++++++++------- core/test/unit/client_showdown_int_spec.js | 26 ++++++++- 2 files changed, 59 insertions(+), 21 deletions(-) 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 '' + alt + '';
-                        }
-
-                        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(/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\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 '' + alt + '';
+                        }
+
+                        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 = [ {