UNPKG

2.46 kBJavaScriptView Raw
1// Replacing the default htmlBlock rule to allow using custom components at
2// root level
3
4const blockNames = require('markdown-it/lib/common/html_blocks')
5const HTML_OPEN_CLOSE_TAG_RE = require('markdown-it/lib/common/html_re').HTML_OPEN_CLOSE_TAG_RE
6
7// An array of opening and corresponding closing sequences for html tags,
8// last argument defines whether it can terminate a paragraph or not
9const HTML_SEQUENCES = [
10 [/^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true],
11 [/^<!--/, /-->/, true],
12 [/^<\?/, /\?>/, true],
13 [/^<![A-Z]/, />/, true],
14 [/^<!\[CDATA\[/, /\]\]>/, true],
15 // PascalCase Components
16 [/^<[A-Z]/, />/, true],
17 // custom elements with hyphens
18 [/^<\w+\-/, />/, true],
19 [new RegExp('^</?(' + blockNames.join('|') + ')(?=(\\s|/?>|$))', 'i'), /^$/, true],
20 [new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\s*$'), /^$/, false]
21]
22
23module.exports = md => {
24 md.block.ruler.at('html_block', htmlBlock)
25}
26
27function htmlBlock (state, startLine, endLine, silent) {
28 let i, nextLine, lineText
29 let pos = state.bMarks[startLine] + state.tShift[startLine]
30 let max = state.eMarks[startLine]
31
32 // if it's indented more than 3 spaces, it should be a code block
33 if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
34
35 if (!state.md.options.html) { return false }
36
37 if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false }
38
39 lineText = state.src.slice(pos, max)
40
41 for (i = 0; i < HTML_SEQUENCES.length; i++) {
42 if (HTML_SEQUENCES[i][0].test(lineText)) { break }
43 }
44
45 if (i === HTML_SEQUENCES.length) {
46 return false
47 }
48
49 if (silent) {
50 // true if this sequence can be a terminator, false otherwise
51 return HTML_SEQUENCES[i][2]
52 }
53
54 nextLine = startLine + 1
55
56 // If we are here - we detected HTML block.
57 // Let's roll down till block end.
58 if (!HTML_SEQUENCES[i][1].test(lineText)) {
59 for (; nextLine < endLine; nextLine++) {
60 if (state.sCount[nextLine] < state.blkIndent) { break }
61
62 pos = state.bMarks[nextLine] + state.tShift[nextLine]
63 max = state.eMarks[nextLine]
64 lineText = state.src.slice(pos, max)
65
66 if (HTML_SEQUENCES[i][1].test(lineText)) {
67 if (lineText.length !== 0) { nextLine++ }
68 break
69 }
70 }
71 }
72
73 state.line = nextLine
74
75 const token = state.push('html_block', '', 0)
76 token.map = [startLine, nextLine]
77 token.content = state.getLines(startLine, nextLine, state.blkIndent, true)
78
79 return true
80}