From d0fdda69045bb280dbf39e035f1f8474247196a6 Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Fri, 27 May 2022 20:09:12 +0530 Subject: [PATCH] fix: more than 4 indented html tags cause error (#638) (#665) fix #638 Co-authored-by: Kia King Ishii --- src/node/markdown/plugins/component.ts | 122 +++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 9 deletions(-) diff --git a/src/node/markdown/plugins/component.ts b/src/node/markdown/plugins/component.ts index accacb8d..6ca6b463 100644 --- a/src/node/markdown/plugins/component.ts +++ b/src/node/markdown/plugins/component.ts @@ -3,10 +3,101 @@ import { RuleBlock } from 'markdown-it/lib/parser_block' import blockNames from 'markdown-it/lib/common/html_blocks' import { HTML_OPEN_CLOSE_TAG_RE } from 'markdown-it/lib/common/html_re' -// Replacing the default htmlBlock rule to allow using custom components at -// root level +/** + * Vue reserved tags + * + * @see https://vuejs.org/api/built-in-components.html + */ +const vueReservedTags = [ + 'template', + 'component', + 'transition', + 'transition-group', + 'keep-alive', + 'slot', + 'teleport' +] + +/** + * According to markdown spec, all non-block html tags are treated as "inline" + * tags (wrapped with

), including those "unknown" tags. + * + * Therefore, markdown-it processes "inline" tags and "unknown" tags in the + * same way, and does not care if a tag is "inline" or "unknown". + * + * As we want to take those "unknown" tags as custom components, we should + * treat them as "block" tags. + * + * So we have to distinguish between "inline" and "unknown" tags ourselves. + * + * The inline tags list comes from MDN. + * + * @see https://spec.commonmark.org/0.29/#raw-html + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements + */ +const inlineTags = [ + 'a', + 'abbr', + 'acronym', + 'audio', + 'b', + 'bdi', + 'bdo', + 'big', + 'br', + 'button', + 'canvas', + 'cite', + 'code', + 'data', + 'datalist', + 'del', + 'dfn', + 'em', + 'embed', + 'i', + // iframe is treated as HTML blocks in markdown spec + // 'iframe', + 'img', + 'input', + 'ins', + 'kbd', + 'label', + 'map', + 'mark', + 'meter', + 'noscript', + 'object', + 'output', + 'picture', + 'progress', + 'q', + 'ruby', + 's', + 'samp', + 'script', + 'select', + 'slot', + 'small', + 'span', + 'strong', + 'sub', + 'sup', + 'svg', + 'template', + 'textarea', + 'time', + 'u', + 'tt', + 'var', + 'video', + 'wbr' +] -// An array of opening and corresponding closing sequences for html tags, +// replacing the default htmlBlock rule to allow using custom components at +// root level +// +// an array of opening and corresponding closing sequences for html tags, // last argument defines whether it can terminate a paragraph or not const HTML_SEQUENCES: [RegExp, RegExp, boolean][] = [ [/^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true], @@ -14,10 +105,24 @@ const HTML_SEQUENCES: [RegExp, RegExp, boolean][] = [ [/^<\?/, /\?>/, true], [/^/, true], [/^/, true], - // PascalCase Components - [/^<[A-Z]/, />/, true], - // custom elements with hyphens - [/^<\w+\-/, />/, true], + + // MODIFIED HERE: treat vue reserved tags as block tags + [ + new RegExp('^|$))', 'i'), + /^$/, + true + ], + + // MODIFIED HERE: treat unknown tags as block tags (custom components), + // excluding known inline tags + [ + new RegExp( + '^]' + ), + /^$/, + true + ], + [ new RegExp('^|$))', 'i'), /^$/, @@ -67,8 +172,7 @@ const htmlBlock: RuleBlock = (state, startLine, endLine, silent): boolean => { nextLine = startLine + 1 - // If we are here - we detected HTML block. - // Let's roll down till block end. + // if we are here - we detected HTML block. let's roll down till block end if (!HTML_SEQUENCES[i][1].test(lineText)) { for (; nextLine < endLine; nextLine++) { if (state.sCount[nextLine] < state.blkIndent) {