build(aio): throw an error if a code-example tag is not closed

This commit is contained in:
Peter Bacon Darwin 2017-05-04 22:02:26 +01:00 committed by Matias Niemelä
parent 9449eff6fd
commit 5057e16874
2 changed files with 46 additions and 29 deletions

View File

@ -91,15 +91,19 @@ module.exports = function renderMarkdown() {
const openMatch = anyBlockMatcher.exec(value); const openMatch = anyBlockMatcher.exec(value);
if (openMatch) { if (openMatch) {
const blockName = openMatch[1]; const blockName = openMatch[1];
const fullMatch = matchRecursiveRegExp(value, createOpenMatcher(blockName), createCloseMatcher(blockName))[0]; try {
if (silent || !fullMatch) { const fullMatch = matchRecursiveRegExp(value, createOpenMatcher(blockName), createCloseMatcher(blockName))[0];
// either we are not eating (silent) or the match failed if (silent || !fullMatch) {
return !!fullMatch; // either we are not eating (silent) or the match failed
return !!fullMatch;
}
return eat(fullMatch[0])({
type: 'html',
value: fullMatch[0]
});
} catch(e) {
this.file.fail('Unmatched plain HTML block tag ' + e.message);
} }
return eat(fullMatch[0])({
type: 'html',
value: fullMatch[0]
});
} }
} }
} }
@ -161,30 +165,32 @@ function rgxFindMatchPos(str, left, right, flags) {
let index, match, start, end; let index, match, start, end;
let count = 0; let count = 0;
do { while ((match = bothMatcher.exec(str))) {
while ((match = bothMatcher.exec(str))) { if (leftMatcher.test(match[0])) {
if (leftMatcher.test(match[0])) { if (!(count++)) {
if (!(count++)) { index = bothMatcher.lastIndex;
index = bothMatcher.lastIndex; start = index - match[0].length;
start = index - match[0].length; }
} } else if (count) {
} else if (count) { if (!--count) {
if (!--count) { end = match.index + match[0].length;
end = match.index + match[0].length; var obj = {
var obj = { left: {start: start, end: index},
left: {start: start, end: index}, match: {start: index, end: match.index},
match: {start: index, end: match.index}, right: {start: match.index, end: end},
right: {start: match.index, end: end}, wholeMatch: {start: start, end: end}
wholeMatch: {start: start, end: end} };
}; pos.push(obj);
pos.push(obj); if (!global) {
if (!global) { return pos;
return pos;
}
} }
} }
} }
} while (count && (bothMatcher.lastIndex = index)); }
if (count) {
throw new Error(str.slice(start, index));
}
return pos; return pos;
} }

View File

@ -49,6 +49,17 @@ describe('remark: renderMarkdown service', () => {
expect(output).toEqual('<code-example>\n\n **abc**\n\n def\n</code-example>\n<code-tabs><code-pane>\n\n **abc**\n\n def\n</code-pane></code-tabs>\n'); expect(output).toEqual('<code-example>\n\n **abc**\n\n def\n</code-example>\n<code-tabs><code-pane>\n\n **abc**\n\n def\n</code-pane></code-tabs>\n');
}); });
it('should handle recursive tags marked as unformatted', () => {
const content = '<code-example>\n\n <code-example>\n\n **abc**\n\n def\n\n</code-example>\n\n</code-example>\n\nhij\n\n<code-example>\n\nklm</code-example>';
const output = renderMarkdown(content);
expect(output).toEqual('<code-example>\n\n <code-example>\n\n **abc**\n\n def\n\n</code-example>\n\n</code-example>\n<p>hij</p>\n<code-example>\n\nklm</code-example>\n');
});
it('should raise an error if a tag marked as unformatted is not closed', () => {
const content = '<code-example path="xxx">\n\n **abc**\n\n def\n<code-example>\n\n\n\n **abc**\n\n def\n</code-example>';
expect(() => renderMarkdown(content)).toThrowError('Unmatched plain HTML block tag <code-example path="xxx">');
});
it('should not remove spaces after anchor tags', () => { it('should not remove spaces after anchor tags', () => {
var input = var input =
'A aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa aaaaaaaaa aaaaaaaaaa aaaaaaaaaaa\n' + 'A aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa aaaaaaaaa aaaaaaaaaa aaaaaaaaaaa\n' +