diff --git a/app/assets/javascripts/discourse/components/bbcode.js b/app/assets/javascripts/discourse/components/bbcode.js index ac39819c74b..4dbc9506d5a 100644 --- a/app/assets/javascripts/discourse/components/bbcode.js +++ b/app/assets/javascripts/discourse/components/bbcode.js @@ -10,6 +10,9 @@ Discourse.BBCode = { QUOTE_REGEXP: /\[quote=([^\]]*)\]((?:[\s\S](?!\[quote=[^\]]*\]))*?)\[\/quote\]/im, + IMG_REGEXP: /\[img\]([\s\S]*?)\[\/img\]/i, + URL_REGEXP: /\[url\]([\s\S]*?)\[\/url\]/i, + URL_WITH_TITLE_REGEXP: /\[url=(.+?)\]([\s\S]*?)\[\/url\]/i, // Define our replacers replacers: { @@ -145,6 +148,41 @@ Discourse.BBCode = { return result; }, + /** + We want to remove urls in BBCode tags from a string before applying markdown + to prevent them from being modified by markdown. + This will return an object that contains: + - a new version of the text with the urls replaced with unique ids + - a `template()` function for reapplying them later. + + @method extractUrls + @param {String} text The text inside which we want to replace urls + @returns {Object} object containing the new string and template function + **/ + extractUrls: function(text) { + var result = { text: "" + text, replacements: [] }; + var replacements = []; + var matches, key; + + _.each([Discourse.BBCode.IMG_REGEXP, Discourse.BBCode.URL_REGEXP, Discourse.BBCode.URL_WITH_TITLE_REGEXP], function(r) { + while (matches = r.exec(result.text)) { + key = md5(matches[0]); + replacements.push({ key: key, value: matches[0] }); + result.text = result.text.replace(matches[0], key); + } + }); + + result.template = function(input) { + _.each(replacements, function(r) { + input = input.replace(r.key, r.value); + }); + return input; + }; + + return (result); + }, + + /** We want to remove quotes from a string before applying markdown to avoid weird stuff with newlines and such. This will return an object that @@ -156,13 +194,12 @@ Discourse.BBCode = { @returns {Object} object containing the new string and template function **/ extractQuotes: function(text) { - var result = {text: "" + text, replacements: []}; - + var result = { text: "" + text, replacements: [] }; var replacements = []; + var matches, key; - var matches; while (matches = Discourse.BBCode.QUOTE_REGEXP.exec(result.text)) { - var key = md5(matches[0]); + key = md5(matches[0]); replacements.push({ key: key, value: matches[0], @@ -180,7 +217,7 @@ Discourse.BBCode = { return input; }; - return(result); + return (result); }, /** diff --git a/app/assets/javascripts/discourse/components/markdown.js b/app/assets/javascripts/discourse/components/markdown.js index 8f67853f53f..373df516ca4 100644 --- a/app/assets/javascripts/discourse/components/markdown.js +++ b/app/assets/javascripts/discourse/components/markdown.js @@ -99,7 +99,7 @@ Discourse.Markdown = { var converter = new Markdown.Converter(); var mentionLookup = opts.mentionLookup || Discourse.Mention.lookupCache; - var quoteTemplate = null; + var quoteTemplate = null, urlsTemplate = null; // Before cooking callbacks converter.hooks.chain("preConversion", function(text) { @@ -114,6 +114,13 @@ Discourse.Markdown = { return extracted.text; }); + // Extract urls in BBCode tags so they are not passed through markdown. + converter.hooks.chain("preConversion", function(text) { + var extracted = Discourse.BBCode.extractUrls(text); + urlsTemplate = extracted.template; + return extracted.text; + }); + // Support autolinking of www.something.com converter.hooks.chain("preConversion", function(text) { return text.replace(/(^|[\s\n])(www\.[a-z\.\-\_\(\)\/\?\=\%0-9]+)/gim, function(full, _, rest) { @@ -178,12 +185,11 @@ Discourse.Markdown = { }); converter.hooks.chain("postConversion", function(text) { - // reapply quotes - if (quoteTemplate) { - text = quoteTemplate(text); - } - + if (quoteTemplate) { text = quoteTemplate(text); } + // reapply urls + if (urlsTemplate) { text = urlsTemplate(text); } + // format with BBCode return Discourse.BBCode.format(text, opts); }); diff --git a/test/javascripts/components/markdown_test.js b/test/javascripts/components/markdown_test.js index 6ee020e73eb..2b6d7c9f832 100644 --- a/test/javascripts/components/markdown_test.js +++ b/test/javascripts/components/markdown_test.js @@ -77,7 +77,7 @@ test("Quotes", function() { "
1
\n
\n2