forked from markdown-it/markdown-it
/
parser_block.js
134 lines (106 loc) · 3.64 KB
/
parser_block.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/** internal
* class ParserBlock
*
* Block-level tokenizer.
**/
import Ruler from './ruler.js';
import table from './rules_block/table.js';
import code from './rules_block/code.js';
import fence from './rules_block/fence.js';
import blockquote from './rules_block/blockquote.js';
import hr from './rules_block/hr.js';
import list from './rules_block/list.js';
import reference from './rules_block/reference.js';
import htmlBlock from './rules_block/html_block.js';
import heading from './rules_block/heading.js';
import lheading from './rules_block/lheading.js';
import paragraph from './rules_block/paragraph.js';
import stateBlock from './rules_block/state_block.js';
const _rules = [
// First 2 params - rule name & source. Secondary array - list of rules,
// which can be terminated by this one.
[ 'table', table, [ 'paragraph', 'reference' ] ],
[ 'code', code ],
[ 'fence', fence, [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
[ 'blockquote', blockquote, [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
[ 'hr', hr, [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
[ 'list', list, [ 'paragraph', 'reference', 'blockquote', 'table' ] ],
[ 'reference', reference ],
[ 'html_block', htmlBlock, [ 'paragraph', 'reference', 'blockquote' ] ],
[ 'heading', heading, [ 'paragraph', 'reference', 'blockquote' ] ],
[ 'lheading', lheading ],
[ 'paragraph', paragraph ]
];
/**
* new ParserBlock()
**/
function ParserBlock() {
/**
* ParserBlock#ruler -> Ruler
*
* [[Ruler]] instance. Keep configuration of block rules.
**/
this.ruler = new Ruler();
for (let i = 0; i < _rules.length; i++) {
this.ruler.push(_rules[i][0], _rules[i][1], { alt: (_rules[i][2] || []).slice() });
}
}
// Generate tokens for input range
//
ParserBlock.prototype.tokenize = function (state, startLine, endLine) {
let ok, i,
rules = this.ruler.getRules(''),
len = rules.length,
line = startLine,
hasEmptyLines = false,
maxNesting = state.md.options.maxNesting;
while (line < endLine) {
state.line = line = state.skipEmptyLines(line);
if (line >= endLine) { break; }
// Termination condition for nested calls.
// Nested calls currently used for blockquotes & lists
if (state.sCount[line] < state.blkIndent) { break; }
// If nesting level exceeded - skip tail to the end. That's not ordinary
// situation and we should not care about content.
if (state.level >= maxNesting) {
state.line = endLine;
break;
}
// Try all possible rules.
// On success, rule should:
//
// - update `state.line`
// - update `state.tokens`
// - return true
for (i = 0; i < len; i++) {
ok = rules[i](state, line, endLine, false);
if (ok) { break; }
}
// set state.tight if we had an empty line before current tag
// i.e. latest empty line should not count
state.tight = !hasEmptyLines;
// paragraph might "eat" one newline after it in nested lists
if (state.isEmpty(state.line - 1)) {
hasEmptyLines = true;
}
line = state.line;
if (line < endLine && state.isEmpty(line)) {
hasEmptyLines = true;
line++;
state.line = line;
}
}
};
/**
* ParserBlock.parse(str, md, env, outTokens)
*
* Process input string and push block tokens into `outTokens`
**/
ParserBlock.prototype.parse = function (src, md, env, outTokens) {
let state;
if (!src) { return; }
state = new this.State(src, md, env, outTokens);
this.tokenize(state, state.line, state.lineMax);
};
ParserBlock.prototype.State = stateBlock;
export default ParserBlock;