FIX: urls in BBCode tags weren't working

This commit is contained in:
Régis Hanol 2013-06-27 00:41:48 +02:00
parent b47f6e80b8
commit 689b296204
3 changed files with 70 additions and 18 deletions

View File

@ -10,6 +10,9 @@
Discourse.BBCode = { Discourse.BBCode = {
QUOTE_REGEXP: /\[quote=([^\]]*)\]((?:[\s\S](?!\[quote=[^\]]*\]))*?)\[\/quote\]/im, 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 // Define our replacers
replacers: { replacers: {
@ -145,6 +148,41 @@ Discourse.BBCode = {
return result; 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 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 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 @returns {Object} object containing the new string and template function
**/ **/
extractQuotes: function(text) { extractQuotes: function(text) {
var result = {text: "" + text, replacements: []}; var result = { text: "" + text, replacements: [] };
var replacements = []; var replacements = [];
var matches, key;
var matches;
while (matches = Discourse.BBCode.QUOTE_REGEXP.exec(result.text)) { while (matches = Discourse.BBCode.QUOTE_REGEXP.exec(result.text)) {
var key = md5(matches[0]); key = md5(matches[0]);
replacements.push({ replacements.push({
key: key, key: key,
value: matches[0], value: matches[0],
@ -180,7 +217,7 @@ Discourse.BBCode = {
return input; return input;
}; };
return(result); return (result);
}, },
/** /**

View File

@ -99,7 +99,7 @@ Discourse.Markdown = {
var converter = new Markdown.Converter(); var converter = new Markdown.Converter();
var mentionLookup = opts.mentionLookup || Discourse.Mention.lookupCache; var mentionLookup = opts.mentionLookup || Discourse.Mention.lookupCache;
var quoteTemplate = null; var quoteTemplate = null, urlsTemplate = null;
// Before cooking callbacks // Before cooking callbacks
converter.hooks.chain("preConversion", function(text) { converter.hooks.chain("preConversion", function(text) {
@ -114,6 +114,13 @@ Discourse.Markdown = {
return extracted.text; 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 // Support autolinking of www.something.com
converter.hooks.chain("preConversion", function(text) { converter.hooks.chain("preConversion", function(text) {
return text.replace(/(^|[\s\n])(www\.[a-z\.\-\_\(\)\/\?\=\%0-9]+)/gim, function(full, _, rest) { 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) { converter.hooks.chain("postConversion", function(text) {
// reapply quotes // reapply quotes
if (quoteTemplate) { if (quoteTemplate) { text = quoteTemplate(text); }
text = quoteTemplate(text); // reapply urls
} if (urlsTemplate) { text = urlsTemplate(text); }
// format with BBCode
return Discourse.BBCode.format(text, opts); return Discourse.BBCode.format(text, opts);
}); });

View File

@ -120,9 +120,18 @@ test("SanitizeHTML", function() {
}); });
// TODO test("URLs in BBCode tags", function() {
// test("with BBCode", function() {
// cooked("[img]http://eviltrout.com/eviltrout.png[/img]", cooked("[img]http://eviltrout.com/eviltrout.png[/img][img]http://samsaffron.com/samsaffron.png[/img]",
// "<p><img src=\"http://eviltrout.com/eviltrout.png\"></p>", "<p><img src=\"http://eviltrout.com/eviltrout.png\"><img src=\"http://samsaffron.com/samsaffron.png\"></p>",
// "BBCode is parsed first"); "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");
});