diff --git a/aio/tools/transforms/remark-package/services/renderMarkdown.js b/aio/tools/transforms/remark-package/services/renderMarkdown.js index bb0defe5f2..c68701e119 100644 --- a/aio/tools/transforms/remark-package/services/renderMarkdown.js +++ b/aio/tools/transforms/remark-package/services/renderMarkdown.js @@ -91,15 +91,19 @@ module.exports = function renderMarkdown() { const openMatch = anyBlockMatcher.exec(value); if (openMatch) { const blockName = openMatch[1]; - const fullMatch = matchRecursiveRegExp(value, createOpenMatcher(blockName), createCloseMatcher(blockName))[0]; - if (silent || !fullMatch) { - // either we are not eating (silent) or the match failed - return !!fullMatch; + try { + const fullMatch = matchRecursiveRegExp(value, createOpenMatcher(blockName), createCloseMatcher(blockName))[0]; + if (silent || !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 count = 0; - do { - while ((match = bothMatcher.exec(str))) { - if (leftMatcher.test(match[0])) { - if (!(count++)) { - index = bothMatcher.lastIndex; - start = index - match[0].length; - } - } else if (count) { - if (!--count) { - end = match.index + match[0].length; - var obj = { - left: {start: start, end: index}, - match: {start: index, end: match.index}, - right: {start: match.index, end: end}, - wholeMatch: {start: start, end: end} - }; - pos.push(obj); - if (!global) { - return pos; - } + while ((match = bothMatcher.exec(str))) { + if (leftMatcher.test(match[0])) { + if (!(count++)) { + index = bothMatcher.lastIndex; + start = index - match[0].length; + } + } else if (count) { + if (!--count) { + end = match.index + match[0].length; + var obj = { + left: {start: start, end: index}, + match: {start: index, end: match.index}, + right: {start: match.index, end: end}, + wholeMatch: {start: start, end: end} + }; + pos.push(obj); + if (!global) { + return pos; } } } - } while (count && (bothMatcher.lastIndex = index)); + } + + if (count) { + throw new Error(str.slice(start, index)); + } return pos; } diff --git a/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js b/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js index ea4409ac5f..d9afc6c762 100644 --- a/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js +++ b/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js @@ -49,6 +49,17 @@ describe('remark: renderMarkdown service', () => { expect(output).toEqual('\n\n **abc**\n\n def\n\n\n\n **abc**\n\n def\n\n'); }); + it('should handle recursive tags marked as unformatted', () => { + const content = '\n\n \n\n **abc**\n\n def\n\n\n\n\n\nhij\n\n\n\nklm'; + const output = renderMarkdown(content); + expect(output).toEqual('\n\n \n\n **abc**\n\n def\n\n\n\n\n

hij

\n\n\nklm\n'); + }); + + it('should raise an error if a tag marked as unformatted is not closed', () => { + const content = '\n\n **abc**\n\n def\n\n\n\n\n **abc**\n\n def\n'; + expect(() => renderMarkdown(content)).toThrowError('Unmatched plain HTML block tag '); + }); + it('should not remove spaces after anchor tags', () => { var input = 'A aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa aaaaaaaaa aaaaaaaaaa aaaaaaaaaaa\n' +