Merge pull request #2650 from Elberet/fix-parser
Fix: block parser uses regexes for stop tags, allows stricter matching
This commit is contained in:
commit
49f0eaea13
|
@ -120,7 +120,7 @@ Discourse.Markdown.whiteListTag('span', 'class', /^bbcode-size-\d+$/);
|
|||
// Handles `[code] ... [/code]` blocks
|
||||
Discourse.Dialect.replaceBlock({
|
||||
start: /(\[code\])([\s\S]*)/igm,
|
||||
stop: '[/code]',
|
||||
stop: /\[\/code\]/igm,
|
||||
rawContents: true,
|
||||
|
||||
emitter: function(blockContents) {
|
||||
|
|
|
@ -21,7 +21,7 @@ function flattenBlocks(blocks) {
|
|||
|
||||
Discourse.Dialect.replaceBlock({
|
||||
start: /^`{3}([^\n\[\]]+)?\n?([\s\S]*)?/gm,
|
||||
stop: '```',
|
||||
stop: /^```$/gm,
|
||||
emitter: function(blockContents, matches) {
|
||||
|
||||
var klass = Discourse.SiteSettings.default_code_lang;
|
||||
|
@ -54,7 +54,7 @@ Discourse.Dialect.on('parseNode', function (event) {
|
|||
|
||||
Discourse.Dialect.replaceBlock({
|
||||
start: /(<pre[^\>]*\>)([\s\S]*)/igm,
|
||||
stop: '</pre>',
|
||||
stop: /<\/pre>/igm,
|
||||
rawContents: true,
|
||||
skipIfTradtionalLinebreaks: true,
|
||||
|
||||
|
|
|
@ -379,7 +379,7 @@ Discourse.Dialect = {
|
|||
if (!match) { return; }
|
||||
|
||||
var lastChance = function() {
|
||||
return !next.some(function(e) { return e.indexOf(args.stop) !== -1; });
|
||||
return !next.some(function(blk) { return blk.match(args.stop); });
|
||||
};
|
||||
|
||||
// shave off start tag and leading text, if any.
|
||||
|
@ -387,7 +387,8 @@ Discourse.Dialect = {
|
|||
leading = block.slice(0, pos),
|
||||
trailing = match[2] ? match[2].replace(/^\n*/, "") : "";
|
||||
// just give up if there's no stop tag in this or any next block
|
||||
if (block.indexOf(args.stop, pos + args.stop.length) === -1 && lastChance()) { return; }
|
||||
args.stop.lastIndex = block.length - trailing.length;
|
||||
if (!args.stop.exec(block) && lastChance()) { return; }
|
||||
if (leading.length > 0) { result.push(['p'].concat(this.processInline(leading))); }
|
||||
if (trailing.length > 0) {
|
||||
next.unshift(MD.mk_block(trailing, block.trailing,
|
||||
|
@ -405,10 +406,10 @@ Discourse.Dialect = {
|
|||
startPos.push(args.start.lastIndex - m[0].length);
|
||||
args.start.lastIndex = args.start.lastIndex - (m[2] ? m[2].length : 0);
|
||||
}
|
||||
var endPos = [], offset = 0;
|
||||
while ((pos = currentBlock.indexOf(args.stop, offset)) !== -1) {
|
||||
endPos.push(pos);
|
||||
offset += (pos + args.stop.length);
|
||||
args.stop.lastIndex = 0;
|
||||
var endPos = [];
|
||||
while (m = (args.stop).exec(currentBlock)) {
|
||||
endPos.push(args.stop.lastIndex - m[0].length);
|
||||
}
|
||||
|
||||
// go through the available end tags:
|
||||
|
@ -421,7 +422,8 @@ Discourse.Dialect = {
|
|||
// found an end tag, but we must go up a level first.
|
||||
ep++; nesting--;
|
||||
} else {
|
||||
// found an end tag and we're at the top: done!
|
||||
// found an end tag and we're at the top: done! -- or: start tag and end tag are
|
||||
// identical, (i.e. startPos[sp] == endPos[ep]), so we don't do nesting at all.
|
||||
actualEndPos = endPos[ep];
|
||||
break blockloop;
|
||||
}
|
||||
|
@ -442,8 +444,9 @@ Discourse.Dialect = {
|
|||
contentBlocks.push(currentBlock);
|
||||
}
|
||||
|
||||
var before = currentBlock.slice(0, actualEndPos).replace(/\n*$/, ""),
|
||||
after = currentBlock.slice(actualEndPos + args.stop.length).replace(/^\n*/, "");
|
||||
var stopLen = currentBlock.match(args.stop)[0].length,
|
||||
before = currentBlock.slice(0, actualEndPos).replace(/\n*$/, ""),
|
||||
after = currentBlock.slice(actualEndPos + stopLen).replace(/^\n*/, "");
|
||||
if (before.length > 0) contentBlocks.push(MD.mk_block(before, "", currentBlock.lineNumber));
|
||||
if (after.length > 0) next.unshift(MD.mk_block(after, "", currentBlock.lineNumber + countLines(before)));
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ var esc = Handlebars.Utils.escapeExpression;
|
|||
|
||||
Discourse.Dialect.replaceBlock({
|
||||
start: new RegExp("\\[quote(=[^\\[\\]]+)?\\]([\\s\\S]*)", "igm"),
|
||||
stop: '[/quote]',
|
||||
stop: /\[\/quote\]/igm,
|
||||
emitter: function(blockContents, matches, options) {
|
||||
|
||||
var params = {'class': 'quote'},
|
||||
|
|
|
@ -365,13 +365,17 @@ test("Code Blocks", function() {
|
|||
"<p><pre><code class=\"lang-auto\">hello</code></pre></p>",
|
||||
"it doesn't not whitelist all classes");
|
||||
|
||||
cooked("```[quote=\"sam, post:1, topic:9441, full:true\"]This is `<not>` a bug.[/quote]```",
|
||||
cooked("```\n[quote=\"sam, post:1, topic:9441, full:true\"]This is `<not>` a bug.[/quote]\n```",
|
||||
"<p><pre><code class=\"lang-auto\">[quote="sam, post:1, topic:9441, full:true"]This is `<not>` a bug.[/quote]</code></pre></p>",
|
||||
"it allows code with backticks in it");
|
||||
|
||||
cooked(" hello\n<blockquote>test</blockquote>",
|
||||
"<pre><code>hello</code></pre>\n\n<blockquote>test</blockquote>",
|
||||
"it allows an indented code block to by followed by a `<blockquote>`");
|
||||
|
||||
cooked("``` foo bar ```",
|
||||
"<p><code>foo bar</code></p>",
|
||||
"it tolerates misuse of code block tags as inline code");
|
||||
});
|
||||
|
||||
test("sanitize", function() {
|
||||
|
|
Loading…
Reference in New Issue