corrected a parsing edge cases for bbcode blocks
This commit is contained in:
parent
38950cdc10
commit
0e0092d738
|
@ -1,6 +1,19 @@
|
||||||
|
let isWhiteSpace;
|
||||||
|
|
||||||
|
function trailingSpaceOnly(src, start, max) {
|
||||||
|
let i;
|
||||||
|
for(i=start;i<max;i++) {
|
||||||
|
let code = src.charCodeAt(i);
|
||||||
|
if (code === 0x0A) { return true; }
|
||||||
|
if (!isWhiteSpace(code)) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// parse a tag [test a=1 b=2] to a data structure
|
// parse a tag [test a=1 b=2] to a data structure
|
||||||
// {tag: "test", attrs={a: "1", b: "2"}
|
// {tag: "test", attrs={a: "1", b: "2"}
|
||||||
export function parseBBCodeTag(src, start, max) {
|
export function parseBBCodeTag(src, start, max, multiline) {
|
||||||
|
|
||||||
let i;
|
let i;
|
||||||
let tag;
|
let tag;
|
||||||
|
@ -31,6 +44,11 @@ export function parseBBCodeTag(src, start, max) {
|
||||||
|
|
||||||
if (closingTag) {
|
if (closingTag) {
|
||||||
if (src[i] === ']') {
|
if (src[i] === ']') {
|
||||||
|
|
||||||
|
if (multiline && !trailingSpaceOnly(src, i+1, max)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return {tag, length: tag.length+3, closing: true};
|
return {tag, length: tag.length+3, closing: true};
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -81,6 +99,10 @@ export function parseBBCodeTag(src, start, max) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (multiline && !trailingSpaceOnly(src, start+length, max)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tag = tag.toLowerCase();
|
tag = tag.toLowerCase();
|
||||||
|
|
||||||
return {tag, attrs, length};
|
return {tag, attrs, length};
|
||||||
|
@ -89,9 +111,8 @@ export function parseBBCodeTag(src, start, max) {
|
||||||
|
|
||||||
function applyBBCode(state, startLine, endLine, silent, md) {
|
function applyBBCode(state, startLine, endLine, silent, md) {
|
||||||
|
|
||||||
var i, pos, nextLine,
|
var i, nextLine,
|
||||||
old_parent, old_line_max, rule,
|
old_parent, old_line_max, rule,
|
||||||
auto_closed = false,
|
|
||||||
start = state.bMarks[startLine] + state.tShift[startLine],
|
start = state.bMarks[startLine] + state.tShift[startLine],
|
||||||
initial = start,
|
initial = start,
|
||||||
max = state.eMarks[startLine];
|
max = state.eMarks[startLine];
|
||||||
|
@ -99,9 +120,9 @@ function applyBBCode(state, startLine, endLine, silent, md) {
|
||||||
// [ === 91
|
// [ === 91
|
||||||
if (91 !== state.src.charCodeAt(start)) { return false; }
|
if (91 !== state.src.charCodeAt(start)) { return false; }
|
||||||
|
|
||||||
let info = parseBBCodeTag(state.src, start, max);
|
let info = parseBBCodeTag(state.src, start, max, true);
|
||||||
|
|
||||||
if (!info) {
|
if (!info || info.closing) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +145,9 @@ function applyBBCode(state, startLine, endLine, silent, md) {
|
||||||
// Search for the end of the block
|
// Search for the end of the block
|
||||||
nextLine = startLine;
|
nextLine = startLine;
|
||||||
|
|
||||||
|
let closeTag;
|
||||||
|
let nesting = 0;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
nextLine++;
|
nextLine++;
|
||||||
if (nextLine >= endLine) {
|
if (nextLine >= endLine) {
|
||||||
|
@ -150,14 +174,24 @@ function applyBBCode(state, startLine, endLine, silent, md) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeTag = parseBBCodeTag(state.src, start, max, true);
|
||||||
|
|
||||||
if (state.src.slice(start+2, max-1) !== rule.tag) { continue; }
|
if (closeTag && closeTag.closing && closeTag.tag === info.tag) {
|
||||||
|
if (nesting === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nesting--;
|
||||||
|
}
|
||||||
|
|
||||||
if (pos < max) { continue; }
|
if (closeTag && !closeTag.closing && closeTag.tag === info.tag) {
|
||||||
|
nesting++;
|
||||||
|
}
|
||||||
|
|
||||||
// found!
|
closeTag = null;
|
||||||
auto_closed = true;
|
}
|
||||||
break;
|
|
||||||
|
if (!closeTag) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_parent = state.parentType;
|
old_parent = state.parentType;
|
||||||
|
@ -199,9 +233,8 @@ function applyBBCode(state, startLine, endLine, silent, md) {
|
||||||
lastToken = state.tokens[state.tokens.length-1];
|
lastToken = state.tokens[state.tokens.length-1];
|
||||||
|
|
||||||
state.parentType = old_parent;
|
state.parentType = old_parent;
|
||||||
|
|
||||||
state.lineMax = old_line_max;
|
state.lineMax = old_line_max;
|
||||||
state.line = nextLine + (auto_closed ? 1 : 0);
|
state.line = nextLine+1;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -210,8 +243,9 @@ export function setup(helper) {
|
||||||
if (!helper.markdownIt) { return; }
|
if (!helper.markdownIt) { return; }
|
||||||
|
|
||||||
helper.registerPlugin(md => {
|
helper.registerPlugin(md => {
|
||||||
|
isWhiteSpace = md.utils.isWhiteSpace;
|
||||||
md.block.ruler.after('fence', 'bbcode', (state, startLine, endLine, silent)=> {
|
md.block.ruler.after('fence', 'bbcode', (state, startLine, endLine, silent)=> {
|
||||||
return applyBBCode(state, startLine, endLine, silent, md);
|
return applyBBCode(state, startLine, endLine, silent, md);
|
||||||
});
|
}, { alt: ['paragraph', 'reference', 'blockquote', 'list'] });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -637,9 +637,25 @@ HTML
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can handle quote edge cases" do
|
it "can handle quote edge cases" do
|
||||||
# expect(cook("a\n[quote]\ntest\n[quote]")).to include('aside')
|
expect(PrettyText.cook("a\n[quote]\ntest\n[/quote]\n\n\na")).to include('aside')
|
||||||
expect(cook("[quote]\ntest")).not_to include('aside')
|
expect(PrettyText.cook("- a\n[quote]\ntest\n[/quote]\n\n\na")).to include('aside')
|
||||||
# expect(cook("[quote]abc\ntest\n[quote]")).not_to include('aside')
|
expect(PrettyText.cook("[quote]\ntest")).not_to include('aside')
|
||||||
|
expect(PrettyText.cook("[quote]abc\ntest\n[/quote]")).not_to include('aside')
|
||||||
|
expect(PrettyText.cook("[quote]\ntest\n[/quote]z")).not_to include('aside')
|
||||||
|
|
||||||
|
nested = <<~QUOTE
|
||||||
|
[quote]
|
||||||
|
a
|
||||||
|
[quote]
|
||||||
|
b
|
||||||
|
[/quote]
|
||||||
|
c
|
||||||
|
[/quote]
|
||||||
|
QUOTE
|
||||||
|
|
||||||
|
cooked = PrettyText.cook(nested)
|
||||||
|
expect(cooked.scan('aside').length).to eq(4)
|
||||||
|
expect(cooked.scan('quote]').length).to eq(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "do off topic quoting with emoji unescape" do
|
it "do off topic quoting with emoji unescape" do
|
||||||
|
|
Loading…
Reference in New Issue