Merge pull request #1098 from ZogStriP/FIX-urls-in-BBCode-tags

FIX: urls in BBCode tags weren't working
This commit is contained in:
Jeff Atwood 2013-06-26 16:24:35 -07:00
commit 0d8bda2aa5
3 changed files with 70 additions and 18 deletions

View File

@ -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);
},
/**

View File

@ -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);
});

View File

@ -120,9 +120,18 @@ test("SanitizeHTML", function() {
});
// TODO
// test("with BBCode", function() {
// cooked("[img]http://eviltrout.com/eviltrout.png[/img]",
// "<p><img src=\"http://eviltrout.com/eviltrout.png\"></p>",
// "BBCode is parsed first");
// });
test("URLs in BBCode tags", function() {
cooked("[img]http://eviltrout.com/eviltrout.png[/img][img]http://samsaffron.com/samsaffron.png[/img]",
"<p><img src=\"http://eviltrout.com/eviltrout.png\"><img src=\"http://samsaffron.com/samsaffron.png\"></p>",
"images are properly parsed");
cooked("[url]http://discourse.org[/url]",
"<p><a href=\"http://discourse.org\">http://discourse.org</a></p>",
"links are properly parsed");
cooked("[url=http://discourse.org]discourse[/url]",
"<p><a href=\"http://discourse.org\">discourse</a></p>",
"named links are properly parsed");
});