rapier-html 1.2.51 → 1.2.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BUILD.json +4 -4
- package/README.md +10 -15
- package/dist/ledger/math/delimiters.mjs +56 -17
- package/dist/ledger/math/markdown-rules.mjs +22 -6
- package/dist/ledger/md-assets.mjs +39 -80
- package/dist/ledger/md-engine.mjs +650 -26
- package/dist/ledger/md-marks.mjs +15 -12
- package/dist/ledger/md-parser-config.mjs +175 -25
- package/dist/rapier.html +72 -61
- package/package.json +1 -1
|
@@ -2,6 +2,57 @@
|
|
|
2
2
|
|
|
3
3
|
const NEWLINES = /\r\n?/g, NULLS = /\0/g;
|
|
4
4
|
|
|
5
|
+
const BLOCK_STARTER = new Uint8Array(128);
|
|
6
|
+
for (const c of [35, 36, 42, 43, 45, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 62, 91, 92, 95, 96, 126]) BLOCK_STARTER[c] = 1;
|
|
7
|
+
|
|
8
|
+
const INLINE_TERM = new Uint8Array(128);
|
|
9
|
+
for (const c of [10, 33, 36, 38, 42, 43, 58, 60, 61, 91, 92, 93, 94, 95, 96, 126]) INLINE_TERM[c] = 1;
|
|
10
|
+
|
|
11
|
+
const LABEL_SPECIAL = new Uint8Array(128);
|
|
12
|
+
for (const c of [10, 33, 36, 60, 91, 92, 93, 94, 96]) LABEL_SPECIAL[c] = 1;
|
|
13
|
+
|
|
14
|
+
const ASCII_PUNCT = new Uint8Array(128);
|
|
15
|
+
for (const c of [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 58, 59, 60, 61, 62, 63, 64, 91, 92, 93, 94, 95, 96, 123, 124, 125, 126]) ASCII_PUNCT[c] = 1;
|
|
16
|
+
|
|
17
|
+
const RULE_STARTERS = {
|
|
18
|
+
text: null,
|
|
19
|
+
linkify: [58],
|
|
20
|
+
newline: [10],
|
|
21
|
+
rapier_semantic_probe: [33, 91],
|
|
22
|
+
temml_math_block: [36, 92],
|
|
23
|
+
escape: [92],
|
|
24
|
+
backticks: [96],
|
|
25
|
+
strikethrough: [126],
|
|
26
|
+
mark: [61],
|
|
27
|
+
ins: [43],
|
|
28
|
+
emphasis: [42, 95],
|
|
29
|
+
sup: [94],
|
|
30
|
+
link: [91],
|
|
31
|
+
rapier_wiki: [33, 91],
|
|
32
|
+
image: [33],
|
|
33
|
+
footnote_inline: [94],
|
|
34
|
+
footnote_ref: [91],
|
|
35
|
+
autolink: [60],
|
|
36
|
+
html_inline: [60],
|
|
37
|
+
entity: [38]
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
function isAsciiTrimmable(c) {
|
|
41
|
+
return c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function asciiTrim(str) {
|
|
45
|
+
const len = str.length;
|
|
46
|
+
if (len === 0) return '';
|
|
47
|
+
const first = str.charCodeAt(0), last = str.charCodeAt(len - 1);
|
|
48
|
+
if (!isAsciiTrimmable(first) && !isAsciiTrimmable(last)) return str;
|
|
49
|
+
let start = 0;
|
|
50
|
+
while (start < len && isAsciiTrimmable(str.charCodeAt(start))) start++;
|
|
51
|
+
let end = len - 1;
|
|
52
|
+
while (end >= start && isAsciiTrimmable(str.charCodeAt(end))) end--;
|
|
53
|
+
return str.slice(start, end + 1);
|
|
54
|
+
}
|
|
55
|
+
|
|
5
56
|
function lineScanner(Base, Token) {
|
|
6
57
|
function StateBlock(src, md, env, tokens) {
|
|
7
58
|
this.bMarks = []; this.eMarks = []; this.tShift = []; this.sCount = []; this.bsCount = [];
|
|
@@ -19,7 +70,7 @@ function lineScanner(Base, Token) {
|
|
|
19
70
|
indent++;
|
|
20
71
|
}
|
|
21
72
|
if (at === length) break;
|
|
22
|
-
let end = src.indexOf('\n', at);
|
|
73
|
+
let end = src.charCodeAt(at) === 0x0a ? at : src.indexOf('\n', at + 1);
|
|
23
74
|
if (end < 0) end = length;
|
|
24
75
|
this.bMarks.push(start); this.eMarks.push(end); this.tShift.push(indent); this.sCount.push(offset); this.bsCount.push(0);
|
|
25
76
|
start = end + 1;
|
|
@@ -28,16 +79,533 @@ function lineScanner(Base, Token) {
|
|
|
28
79
|
this.lineMax = this.bMarks.length - 1;
|
|
29
80
|
}
|
|
30
81
|
StateBlock.prototype = Base.prototype;
|
|
82
|
+
Base.prototype.getLines = function getLines(begin, end, indent, keepLastLF) {
|
|
83
|
+
if (begin >= end) return '';
|
|
84
|
+
const src = this.src, bMarks = this.bMarks, eMarks = this.eMarks, tShift = this.tShift, bsCount = this.bsCount;
|
|
85
|
+
if (begin + 1 === end) {
|
|
86
|
+
const lineStart = bMarks[begin], last = keepLastLF ? eMarks[begin] + 1 : eMarks[begin];
|
|
87
|
+
if (indent === 0) return src.slice(lineStart, last);
|
|
88
|
+
const shift = tShift[begin];
|
|
89
|
+
if (shift === 0) return src.slice(lineStart, last);
|
|
90
|
+
let lineIndent = 0, first = lineStart;
|
|
91
|
+
const bs = bsCount[begin];
|
|
92
|
+
while (first < last && lineIndent < indent) {
|
|
93
|
+
const ch = src.charCodeAt(first);
|
|
94
|
+
if (ch === 0x20) lineIndent++;
|
|
95
|
+
else if (ch === 0x09) lineIndent += 4 - (lineIndent + bs) % 4;
|
|
96
|
+
else if (first - lineStart < shift) lineIndent++;
|
|
97
|
+
else break;
|
|
98
|
+
first++;
|
|
99
|
+
}
|
|
100
|
+
if (lineIndent > indent) return ' '.repeat(lineIndent - indent) + src.slice(first, last);
|
|
101
|
+
return src.slice(first, last);
|
|
102
|
+
}
|
|
103
|
+
const queue = new Array(end - begin);
|
|
104
|
+
for (let i = 0, line = begin; line < end; line++, i++) {
|
|
105
|
+
const lineStart = bMarks[line];
|
|
106
|
+
const last = line + 1 < end || keepLastLF ? eMarks[line] + 1 : eMarks[line];
|
|
107
|
+
if (indent === 0 || tShift[line] === 0 && bsCount[line] === 0 && src.charCodeAt(lineStart) !== 0x20 && src.charCodeAt(lineStart) !== 0x09) {
|
|
108
|
+
queue[i] = src.slice(lineStart, last);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
let lineIndent = 0, first = lineStart;
|
|
112
|
+
const shift = tShift[line], bs = bsCount[line];
|
|
113
|
+
while (first < last && lineIndent < indent) {
|
|
114
|
+
const ch = src.charCodeAt(first);
|
|
115
|
+
if (ch === 0x20) lineIndent++;
|
|
116
|
+
else if (ch === 0x09) lineIndent += 4 - (lineIndent + bs) % 4;
|
|
117
|
+
else if (first - lineStart < shift) lineIndent++;
|
|
118
|
+
else break;
|
|
119
|
+
first++;
|
|
120
|
+
}
|
|
121
|
+
queue[i] = lineIndent > indent ? ' '.repeat(lineIndent - indent) + src.slice(first, last) : src.slice(first, last);
|
|
122
|
+
}
|
|
123
|
+
return queue.join('');
|
|
124
|
+
};
|
|
31
125
|
return StateBlock;
|
|
32
126
|
}
|
|
33
127
|
|
|
128
|
+
function lineCanTerminateParagraph(state, nextLine, endLine) {
|
|
129
|
+
const pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
|
130
|
+
if (pos >= state.eMarks[nextLine]) return false;
|
|
131
|
+
const ch = state.src.charCodeAt(pos);
|
|
132
|
+
if (ch < 128 && BLOCK_STARTER[ch] === 1) return true;
|
|
133
|
+
const n2 = nextLine + 1;
|
|
134
|
+
if (n2 < endLine) {
|
|
135
|
+
const p2 = state.bMarks[n2] + state.tShift[n2];
|
|
136
|
+
if (p2 < state.eMarks[n2]) {
|
|
137
|
+
const c2 = state.src.charCodeAt(p2);
|
|
138
|
+
if (c2 === 0x7c || c2 === 0x2d || c2 === 0x3a) return true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function lheading(state, startLine, endLine) {
|
|
145
|
+
const blkIndent = state.blkIndent;
|
|
146
|
+
if (state.sCount[startLine] - blkIndent >= 4) return false;
|
|
147
|
+
let nextLine = startLine + 1;
|
|
148
|
+
if (nextLine >= endLine || state.isEmpty(nextLine)) {
|
|
149
|
+
state._pLine = startLine;
|
|
150
|
+
state._pEnd = endLine;
|
|
151
|
+
state._pNext = nextLine;
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
const terminatorRules = state.md.block.ruler.getRules('paragraph'), len = terminatorRules.length;
|
|
155
|
+
const oldParentType = state.parentType;
|
|
156
|
+
state.parentType = 'paragraph';
|
|
157
|
+
const src = state.src, bMarks = state.bMarks, eMarks = state.eMarks, tShift = state.tShift, sCount = state.sCount;
|
|
158
|
+
let level = 0, marker = 0;
|
|
159
|
+
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
|
|
160
|
+
const sc = sCount[nextLine];
|
|
161
|
+
if (sc - blkIndent > 3) continue;
|
|
162
|
+
if (sc >= blkIndent) {
|
|
163
|
+
let pos = bMarks[nextLine] + tShift[nextLine];
|
|
164
|
+
const max = eMarks[nextLine];
|
|
165
|
+
if (pos < max) {
|
|
166
|
+
marker = src.charCodeAt(pos);
|
|
167
|
+
if (marker === 0x2d || marker === 0x3d) {
|
|
168
|
+
pos = state.skipChars(pos, marker);
|
|
169
|
+
pos = state.skipSpaces(pos);
|
|
170
|
+
if (pos >= max) {
|
|
171
|
+
level = marker === 0x3d ? 1 : 2;
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (sc < 0) continue;
|
|
178
|
+
if (!lineCanTerminateParagraph(state, nextLine, endLine)) continue;
|
|
179
|
+
let terminate = false;
|
|
180
|
+
for (let i = 0; i < len; i++) {
|
|
181
|
+
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
|
182
|
+
terminate = true;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (terminate) break;
|
|
187
|
+
}
|
|
188
|
+
if (!level) {
|
|
189
|
+
state.parentType = oldParentType;
|
|
190
|
+
state._pLine = startLine;
|
|
191
|
+
state._pEnd = endLine;
|
|
192
|
+
state._pNext = nextLine;
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
const content = asciiTrim(state.getLines(startLine, nextLine, blkIndent, false));
|
|
196
|
+
state.line = nextLine + 1;
|
|
197
|
+
const token_o = state.push('heading_open', `h${level}`, 1);
|
|
198
|
+
token_o.markup = marker === 0x3d ? '=' : '-';
|
|
199
|
+
token_o.map = [startLine, state.line];
|
|
200
|
+
const token_i = state.push('inline', '', 0);
|
|
201
|
+
token_i.content = content;
|
|
202
|
+
token_i.map = [startLine, state.line - 1];
|
|
203
|
+
token_i.children = [];
|
|
204
|
+
const token_c = state.push('heading_close', `h${level}`, -1);
|
|
205
|
+
token_c.markup = marker === 0x3d ? '=' : '-';
|
|
206
|
+
state.parentType = oldParentType;
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function paragraph(state, startLine, endLine) {
|
|
211
|
+
let nextLine = startLine + 1;
|
|
212
|
+
if (state._pLine === startLine && state._pEnd === endLine) {
|
|
213
|
+
nextLine = state._pNext;
|
|
214
|
+
} else if (nextLine < endLine && !state.isEmpty(nextLine)) {
|
|
215
|
+
const terminatorRules = state.md.block.ruler.getRules('paragraph'), len = terminatorRules.length;
|
|
216
|
+
const oldParentType = state.parentType, blkIndent = state.blkIndent, sCount = state.sCount;
|
|
217
|
+
state.parentType = 'paragraph';
|
|
218
|
+
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
|
|
219
|
+
const sc = sCount[nextLine];
|
|
220
|
+
if (sc - blkIndent > 3 || sc < 0) continue;
|
|
221
|
+
if (!lineCanTerminateParagraph(state, nextLine, endLine)) continue;
|
|
222
|
+
let terminate = false;
|
|
223
|
+
for (let i = 0; i < len; i++) {
|
|
224
|
+
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
|
225
|
+
terminate = true;
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (terminate) break;
|
|
230
|
+
}
|
|
231
|
+
state.parentType = oldParentType;
|
|
232
|
+
}
|
|
233
|
+
const content = asciiTrim(state.getLines(startLine, nextLine, state.blkIndent, false));
|
|
234
|
+
state.line = nextLine;
|
|
235
|
+
const token_o = state.push('paragraph_open', 'p', 1);
|
|
236
|
+
token_o.map = [startLine, nextLine];
|
|
237
|
+
const token_i = state.push('inline', '', 0);
|
|
238
|
+
token_i.content = content;
|
|
239
|
+
token_i.map = [startLine, nextLine];
|
|
240
|
+
token_i.children = [];
|
|
241
|
+
state.push('paragraph_close', 'p', -1);
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function textRule(state, silent) {
|
|
246
|
+
let pos = state.pos;
|
|
247
|
+
const src = state.src, max = state.posMax;
|
|
248
|
+
while (pos < max) {
|
|
249
|
+
const ch = src.charCodeAt(pos);
|
|
250
|
+
if (ch < 128 && INLINE_TERM[ch] === 1) break;
|
|
251
|
+
pos++;
|
|
252
|
+
}
|
|
253
|
+
if (pos === state.pos) return false;
|
|
254
|
+
if (!silent) state.pending += src.slice(state.pos, pos);
|
|
255
|
+
state.pos = pos;
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function compileInlineDispatch(ruler) {
|
|
260
|
+
const rules = ruler.getRules('');
|
|
261
|
+
if (ruler._compiledRules === rules && ruler._dispatchTable) return ruler._dispatchTable;
|
|
262
|
+
const entries = ruler.__rules__;
|
|
263
|
+
for (let i = 0; i < entries.length; i++) {
|
|
264
|
+
const entry = entries[i];
|
|
265
|
+
if (!entry.enabled) continue;
|
|
266
|
+
if (!(entry.name in RULE_STARTERS)) {
|
|
267
|
+
ruler._compiledRules = rules;
|
|
268
|
+
ruler._dispatchTable = null;
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const table = new Array(128);
|
|
273
|
+
for (let c = 0; c < 128; c++) table[c] = [];
|
|
274
|
+
for (let i = 0; i < entries.length; i++) {
|
|
275
|
+
const entry = entries[i];
|
|
276
|
+
if (!entry.enabled) continue;
|
|
277
|
+
const starters = RULE_STARTERS[entry.name];
|
|
278
|
+
if (starters === null) {
|
|
279
|
+
for (let c = 0; c < 128; c++) {
|
|
280
|
+
if (INLINE_TERM[c] === 0) table[c].push(entry.fn);
|
|
281
|
+
}
|
|
282
|
+
} else {
|
|
283
|
+
for (let j = 0; j < starters.length; j++) table[starters[j]].push(entry.fn);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
ruler._compiledRules = rules;
|
|
287
|
+
ruler._dispatchTable = table;
|
|
288
|
+
return table;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function tuneInlineTokenizer(md) {
|
|
292
|
+
const inline = md.inline;
|
|
293
|
+
inline.tokenize = function tokenize(state) {
|
|
294
|
+
const rules = this.ruler.getRules('');
|
|
295
|
+
const end = state.posMax;
|
|
296
|
+
const maxNesting = state.md.options.maxNesting;
|
|
297
|
+
const src = state.src;
|
|
298
|
+
const table = this.ruler.__cache__?.[''] === rules ? compileInlineDispatch(this.ruler) : null;
|
|
299
|
+
if (table) {
|
|
300
|
+
while (state.pos < end) {
|
|
301
|
+
const prevPos = state.pos;
|
|
302
|
+
const ch = src.charCodeAt(prevPos);
|
|
303
|
+
if (ch >= 128 || INLINE_TERM[ch] === 0) {
|
|
304
|
+
let pos = prevPos + 1;
|
|
305
|
+
while (pos < end) {
|
|
306
|
+
const c = src.charCodeAt(pos);
|
|
307
|
+
if (c < 128 && INLINE_TERM[c] === 1) break;
|
|
308
|
+
pos++;
|
|
309
|
+
}
|
|
310
|
+
state.pending += src.slice(prevPos, pos);
|
|
311
|
+
state.pos = pos;
|
|
312
|
+
if (pos >= end) break;
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
let ok = false;
|
|
316
|
+
if (state.level < maxNesting) {
|
|
317
|
+
const bucket = table[ch], bLen = bucket.length;
|
|
318
|
+
for (let i = 0; i < bLen; i++) {
|
|
319
|
+
ok = bucket[i](state, false);
|
|
320
|
+
if (ok) {
|
|
321
|
+
if (prevPos >= state.pos) throw new Error("inline rule didn't increment state.pos");
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (ok) {
|
|
327
|
+
if (state.pos >= end) break;
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
state.pending += src[state.pos++];
|
|
331
|
+
}
|
|
332
|
+
if (state.pending) state.pushPending();
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const len = rules.length;
|
|
336
|
+
while (state.pos < end) {
|
|
337
|
+
const prevPos = state.pos;
|
|
338
|
+
let ok = false;
|
|
339
|
+
if (state.level < maxNesting) {
|
|
340
|
+
for (let i = 0; i < len; i++) {
|
|
341
|
+
ok = rules[i](state, false);
|
|
342
|
+
if (ok) {
|
|
343
|
+
if (prevPos >= state.pos) throw new Error("inline rule didn't increment state.pos");
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (ok) {
|
|
349
|
+
if (state.pos >= end) break;
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
state.pending += src[state.pos++];
|
|
353
|
+
}
|
|
354
|
+
if (state.pending) state.pushPending();
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
inline.skipToken = function skipToken(state) {
|
|
358
|
+
const pos = state.pos;
|
|
359
|
+
const cache = state.cache;
|
|
360
|
+
if (cache[pos] !== undefined) {
|
|
361
|
+
state.pos = cache[pos];
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const rules = this.ruler.getRules('');
|
|
365
|
+
const maxNesting = state.md.options.maxNesting;
|
|
366
|
+
let ok = false;
|
|
367
|
+
if (state.level < maxNesting) {
|
|
368
|
+
const table = this.ruler.__cache__?.[''] === rules ? compileInlineDispatch(this.ruler) : null;
|
|
369
|
+
if (table) {
|
|
370
|
+
const ch = state.src.charCodeAt(pos);
|
|
371
|
+
if (ch >= 128 || INLINE_TERM[ch] === 0) {
|
|
372
|
+
let end = pos + 1;
|
|
373
|
+
const max = state.posMax, src = state.src;
|
|
374
|
+
while (end < max) {
|
|
375
|
+
const c = src.charCodeAt(end);
|
|
376
|
+
if (c < 128 && INLINE_TERM[c] === 1) break;
|
|
377
|
+
end++;
|
|
378
|
+
}
|
|
379
|
+
state.pos = end;
|
|
380
|
+
cache[pos] = end;
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
const bucket = table[ch], bLen = bucket.length;
|
|
384
|
+
for (let i = 0; i < bLen; i++) {
|
|
385
|
+
state.level++;
|
|
386
|
+
ok = bucket[i](state, true);
|
|
387
|
+
state.level--;
|
|
388
|
+
if (ok) {
|
|
389
|
+
if (pos >= state.pos) throw new Error("inline rule didn't increment state.pos");
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
} else {
|
|
394
|
+
const len = rules.length;
|
|
395
|
+
for (let i = 0; i < len; i++) {
|
|
396
|
+
state.level++;
|
|
397
|
+
ok = rules[i](state, true);
|
|
398
|
+
state.level--;
|
|
399
|
+
if (ok) {
|
|
400
|
+
if (pos >= state.pos) throw new Error("inline rule didn't increment state.pos");
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
} else {
|
|
406
|
+
state.pos = state.posMax;
|
|
407
|
+
}
|
|
408
|
+
if (!ok) state.pos++;
|
|
409
|
+
cache[pos] = state.pos;
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function fastParseLinkLabel(state, start, disableNested) {
|
|
414
|
+
const max = state.posMax, src = state.src;
|
|
415
|
+
if (state._labelPos === start && state._labelMax === max) {
|
|
416
|
+
if (disableNested && state._labelNested) return -1;
|
|
417
|
+
return state._labelEnd;
|
|
418
|
+
}
|
|
419
|
+
let pos = start + 1;
|
|
420
|
+
let simple = true;
|
|
421
|
+
while (pos < max) {
|
|
422
|
+
const ch = src.charCodeAt(pos);
|
|
423
|
+
if (ch === 0x5d) {
|
|
424
|
+
state._labelPos = start;
|
|
425
|
+
state._labelMax = max;
|
|
426
|
+
state._labelEnd = pos;
|
|
427
|
+
state._labelNested = false;
|
|
428
|
+
return pos;
|
|
429
|
+
}
|
|
430
|
+
if (ch < 128 && LABEL_SPECIAL[ch] === 1) {
|
|
431
|
+
simple = false;
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
pos++;
|
|
435
|
+
}
|
|
436
|
+
if (simple) {
|
|
437
|
+
state._labelPos = start;
|
|
438
|
+
state._labelMax = max;
|
|
439
|
+
state._labelEnd = -1;
|
|
440
|
+
state._labelNested = false;
|
|
441
|
+
return -1;
|
|
442
|
+
}
|
|
443
|
+
const oldPos = state.pos;
|
|
444
|
+
state.pos = start + 1;
|
|
445
|
+
let level = 1, found = false, hasNested = false;
|
|
446
|
+
while (state.pos < max) {
|
|
447
|
+
const marker = src.charCodeAt(state.pos);
|
|
448
|
+
if (marker === 0x5d) {
|
|
449
|
+
level--;
|
|
450
|
+
if (level === 0) {
|
|
451
|
+
found = true;
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
const prevPos = state.pos;
|
|
456
|
+
state.md.inline.skipToken(state);
|
|
457
|
+
if (marker === 0x5b) {
|
|
458
|
+
if (prevPos === state.pos - 1) {
|
|
459
|
+
level++;
|
|
460
|
+
} else {
|
|
461
|
+
hasNested = true;
|
|
462
|
+
if (disableNested) {
|
|
463
|
+
state.pos = oldPos;
|
|
464
|
+
state._labelPos = start;
|
|
465
|
+
state._labelMax = max;
|
|
466
|
+
state._labelEnd = -2;
|
|
467
|
+
state._labelNested = true;
|
|
468
|
+
return -1;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
const labelEnd = found ? state.pos : -1;
|
|
474
|
+
state.pos = oldPos;
|
|
475
|
+
if (state._labelPos !== start || state._labelMax !== max || state._labelEnd !== -2) {
|
|
476
|
+
state._labelPos = start;
|
|
477
|
+
state._labelMax = max;
|
|
478
|
+
state._labelEnd = labelEnd;
|
|
479
|
+
state._labelNested = hasNested;
|
|
480
|
+
}
|
|
481
|
+
return disableNested && hasNested ? -1 : labelEnd;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
const DELIM_RESULT = {can_open: false, can_close: false, length: 0};
|
|
485
|
+
|
|
486
|
+
function tuneScanDelims(md) {
|
|
487
|
+
const isPunctCharCode = md.utils.isPunctCharCode;
|
|
488
|
+
const isWhiteSpace = md.utils.isWhiteSpace;
|
|
489
|
+
md.inline.State.prototype.scanDelims = function scanDelims(start, canSplitWord) {
|
|
490
|
+
const max = this.posMax, src = this.src;
|
|
491
|
+
const marker = src.charCodeAt(start);
|
|
492
|
+
let lastChar;
|
|
493
|
+
if (start === 0) {
|
|
494
|
+
lastChar = 0x20;
|
|
495
|
+
} else if (start === 1) {
|
|
496
|
+
lastChar = src.charCodeAt(0);
|
|
497
|
+
if ((lastChar & 0xf800) === 0xd800) lastChar = 0xfffd;
|
|
498
|
+
} else {
|
|
499
|
+
lastChar = src.charCodeAt(start - 1);
|
|
500
|
+
if ((lastChar & 0xfc00) === 0xdc00) {
|
|
501
|
+
const highSurr = src.charCodeAt(start - 2);
|
|
502
|
+
lastChar = (highSurr & 0xfc00) === 0xd800 ? 0x10000 + ((highSurr - 0xd800) << 10) + (lastChar - 0xdc00) : 0xfffd;
|
|
503
|
+
} else if ((lastChar & 0xfc00) === 0xd800) {
|
|
504
|
+
lastChar = 0xfffd;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
let pos = start + 1;
|
|
508
|
+
while (pos < max && src.charCodeAt(pos) === marker) pos++;
|
|
509
|
+
const count = pos - start;
|
|
510
|
+
let nextChar = pos < max ? src.charCodeAt(pos) : 0x20;
|
|
511
|
+
if ((nextChar & 0xfc00) === 0xd800) {
|
|
512
|
+
const lowSurr = src.charCodeAt(pos + 1);
|
|
513
|
+
nextChar = (lowSurr & 0xfc00) === 0xdc00 ? 0x10000 + ((nextChar - 0xd800) << 10) + (lowSurr - 0xdc00) : 0xfffd;
|
|
514
|
+
} else if ((nextChar & 0xfc00) === 0xdc00) {
|
|
515
|
+
nextChar = 0xfffd;
|
|
516
|
+
}
|
|
517
|
+
const isLastWhiteSpace = lastChar < 128 ? (lastChar === 0x20 || (lastChar >= 0x09 && lastChar <= 0x0d)) : isWhiteSpace(lastChar);
|
|
518
|
+
const isNextWhiteSpace = nextChar < 128 ? (nextChar === 0x20 || (nextChar >= 0x09 && nextChar <= 0x0d)) : isWhiteSpace(nextChar);
|
|
519
|
+
const isLastPunctChar = !isLastWhiteSpace && (lastChar < 128 ? ASCII_PUNCT[lastChar] === 1 : isPunctCharCode(lastChar));
|
|
520
|
+
const isNextPunctChar = !isNextWhiteSpace && (nextChar < 128 ? ASCII_PUNCT[nextChar] === 1 : isPunctCharCode(nextChar));
|
|
521
|
+
const left_flanking = !isNextWhiteSpace && (!isNextPunctChar || isLastWhiteSpace || isLastPunctChar);
|
|
522
|
+
const right_flanking = !isLastWhiteSpace && (!isLastPunctChar || isNextWhiteSpace || isNextPunctChar);
|
|
523
|
+
DELIM_RESULT.can_open = left_flanking && (canSplitWord || !right_flanking || isLastPunctChar);
|
|
524
|
+
DELIM_RESULT.can_close = right_flanking && (canSplitWord || !left_flanking || isNextPunctChar);
|
|
525
|
+
DELIM_RESULT.length = count;
|
|
526
|
+
return DELIM_RESULT;
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function fragmentsJoin(state) {
|
|
531
|
+
const tokens = state.tokens, max = tokens.length;
|
|
532
|
+
if (max === 0) return;
|
|
533
|
+
let level = 0, last = 0;
|
|
534
|
+
for (let curr = 0; curr < max; curr++) {
|
|
535
|
+
const tok = tokens[curr], nesting = tok.nesting;
|
|
536
|
+
if (nesting < 0) level--;
|
|
537
|
+
tok.level = level;
|
|
538
|
+
if (nesting > 0) level++;
|
|
539
|
+
if (tok.type === 'text' && curr + 1 < max && tokens[curr + 1].type === 'text') {
|
|
540
|
+
tokens[curr + 1].content = tok.content + tokens[curr + 1].content;
|
|
541
|
+
} else {
|
|
542
|
+
if (curr !== last) tokens[last] = tok;
|
|
543
|
+
last++;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
if (last !== max) tokens.length = last;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function joinAlt(tokens) {
|
|
550
|
+
const max = tokens.length;
|
|
551
|
+
if (max === 0) return;
|
|
552
|
+
let last = 0;
|
|
553
|
+
for (let curr = 0; curr < max; curr++) {
|
|
554
|
+
const tok = tokens[curr];
|
|
555
|
+
if (tok.type === 'text_special') tok.type = 'text';
|
|
556
|
+
}
|
|
557
|
+
for (let curr = 0; curr < max; curr++) {
|
|
558
|
+
const tok = tokens[curr];
|
|
559
|
+
if (tok.type === 'text' && curr + 1 < max && tokens[curr + 1].type === 'text') {
|
|
560
|
+
tokens[curr + 1].content = tok.content + tokens[curr + 1].content;
|
|
561
|
+
} else {
|
|
562
|
+
if (curr !== last) tokens[last] = tok;
|
|
563
|
+
last++;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
if (last !== max) tokens.length = last;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function textJoin(state) {
|
|
570
|
+
const blockTokens = state.tokens, l = blockTokens.length;
|
|
571
|
+
for (let j = 0; j < l; j++) {
|
|
572
|
+
if (blockTokens[j].type !== 'inline') continue;
|
|
573
|
+
const tokens = blockTokens[j].children, max = tokens.length;
|
|
574
|
+
if (max === 0) continue;
|
|
575
|
+
let hasSpecialOrMerge = false;
|
|
576
|
+
for (let curr = 0; curr < max; curr++) {
|
|
577
|
+
const tok = tokens[curr];
|
|
578
|
+
if (tok.type === 'text_special') {
|
|
579
|
+
tok.type = 'text';
|
|
580
|
+
hasSpecialOrMerge = true;
|
|
581
|
+
}
|
|
582
|
+
if (tok.children) joinAlt(tok.children);
|
|
583
|
+
if (!hasSpecialOrMerge && tok.type === 'text' && curr + 1 < max && (tokens[curr + 1].type === 'text' || tokens[curr + 1].type === 'text_special')) {
|
|
584
|
+
hasSpecialOrMerge = true;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
if (!hasSpecialOrMerge) continue;
|
|
588
|
+
let last = 0;
|
|
589
|
+
for (let curr = 0; curr < max; curr++) {
|
|
590
|
+
const tok = tokens[curr];
|
|
591
|
+
if (tok.type === 'text' && curr + 1 < max && tokens[curr + 1].type === 'text') {
|
|
592
|
+
tokens[curr + 1].content = tok.content + tokens[curr + 1].content;
|
|
593
|
+
} else {
|
|
594
|
+
if (curr !== last) tokens[last] = tok;
|
|
595
|
+
last++;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
if (last !== max) tokens.length = last;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
34
602
|
function backticks(state, silent) {
|
|
35
603
|
const start = state.pos, src = state.src;
|
|
36
604
|
if (src.charCodeAt(start) !== 0x60) return false;
|
|
37
605
|
const max = state.posMax;
|
|
38
606
|
let pos = start + 1;
|
|
39
607
|
while (pos < max && src.charCodeAt(pos) === 0x60) pos++;
|
|
40
|
-
const marker = src.slice(start, pos), length = marker.length, runs = state.backticks;
|
|
608
|
+
const marker = pos - start === 1 ? '`' : src.slice(start, pos), length = marker.length, runs = state.backticks;
|
|
41
609
|
const scanned = state.backticksScanned;
|
|
42
610
|
if (!scanned || pos < scanned || (runs[length] ?? -1) >= pos) {
|
|
43
611
|
let matchStart, matchEnd = pos;
|
|
@@ -50,8 +618,11 @@ function backticks(state, silent) {
|
|
|
50
618
|
if (!silent) {
|
|
51
619
|
const token = state.push('code_inline', 'code', 0);
|
|
52
620
|
token.markup = marker;
|
|
53
|
-
let content = src.slice(pos, matchStart)
|
|
54
|
-
if (content.
|
|
621
|
+
let content = src.slice(pos, matchStart);
|
|
622
|
+
if (content.indexOf('\n') >= 0) content = content.replace(/\n/g, ' ');
|
|
623
|
+
if (content.length >= 2 && content.charCodeAt(0) === 0x20 && content.charCodeAt(content.length - 1) === 0x20 && /[^ ]/.test(content)) {
|
|
624
|
+
content = content.slice(1, -1);
|
|
625
|
+
}
|
|
55
626
|
token.content = content;
|
|
56
627
|
}
|
|
57
628
|
state.pos = matchEnd;
|
|
@@ -72,37 +643,78 @@ function cleanWebLink(url) {
|
|
|
72
643
|
return match !== null && match[1].length <= 255;
|
|
73
644
|
}
|
|
74
645
|
|
|
75
|
-
function
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
646
|
+
function releaseCoreState(state) {
|
|
647
|
+
state.src = '';
|
|
648
|
+
state.env = {};
|
|
649
|
+
state.tokens = [];
|
|
650
|
+
return state;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
function releaseBlockState(state) {
|
|
654
|
+
state.src = '';
|
|
655
|
+
state.env = {};
|
|
656
|
+
state.tokens = [];
|
|
657
|
+
state.bMarks = [];
|
|
658
|
+
state.eMarks = [];
|
|
659
|
+
state.tShift = [];
|
|
660
|
+
state.sCount = [];
|
|
661
|
+
state.bsCount = [];
|
|
662
|
+
return state;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function releaseInlineState(state) {
|
|
666
|
+
state.src = '';
|
|
667
|
+
state.env = {};
|
|
668
|
+
state.tokens = [];
|
|
669
|
+
state.tokens_meta = [];
|
|
670
|
+
state.pending = '';
|
|
671
|
+
state.delimiters = [];
|
|
672
|
+
state._prev_delimiters = [];
|
|
673
|
+
state.backticks = {};
|
|
82
674
|
return state;
|
|
83
675
|
}
|
|
84
|
-
|
|
85
|
-
function
|
|
86
|
-
const
|
|
87
|
-
|
|
676
|
+
|
|
677
|
+
function detachTokenSample(token) {
|
|
678
|
+
const copy = Object.assign(Object.create(Object.getPrototypeOf(token)), token);
|
|
679
|
+
copy.content = '';
|
|
680
|
+
copy.markup = '';
|
|
681
|
+
copy.info = '';
|
|
682
|
+
copy.children = token.children ? [] : null;
|
|
683
|
+
copy.meta = token.meta ? {} : null;
|
|
684
|
+
copy.attrs = token.attrs ? [] : null;
|
|
685
|
+
return copy;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
function sampleTokensOnce(kept, tokens) {
|
|
689
|
+
const limit = Math.min(tokens.length, 256);
|
|
690
|
+
for (let index = 0; index < limit; index++) {
|
|
88
691
|
const token = tokens[index];
|
|
89
|
-
if (!kept.has(token.type)) kept.set(token.type, token);
|
|
692
|
+
if (!kept.has(token.type)) kept.set(token.type, detachTokenSample(token));
|
|
90
693
|
const children = token.children;
|
|
91
694
|
if (children) for (let at = 0; at < children.length; at++) {
|
|
92
695
|
const child = children[at];
|
|
93
|
-
if (!kept.has(child.type)) kept.set(child.type, child);
|
|
696
|
+
if (!kept.has(child.type)) kept.set(child.type, detachTokenSample(child));
|
|
94
697
|
}
|
|
95
698
|
}
|
|
96
|
-
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
function hasAnyDelimiters(state) {
|
|
702
|
+
if (state.delimiters.length > 0) return true;
|
|
703
|
+
const meta = state.tokens_meta, len = meta.length;
|
|
704
|
+
for (let i = 0; i < len; i++) {
|
|
705
|
+
const m = meta[i];
|
|
706
|
+
if (m && m.delimiters && m.delimiters.length > 0) return true;
|
|
707
|
+
}
|
|
708
|
+
return false;
|
|
97
709
|
}
|
|
98
710
|
|
|
99
711
|
function keepClasses(md) {
|
|
100
|
-
const anchors = {core: null, block: null, inline: null, tokens:
|
|
712
|
+
const anchors = {core: null, block: null, inline: null, tokens: new Map()};
|
|
101
713
|
const finish = (state, tokens) => {
|
|
102
|
-
anchors.core =
|
|
103
|
-
if (anchors.block)
|
|
104
|
-
if (anchors.inline)
|
|
105
|
-
anchors.tokens
|
|
714
|
+
anchors.core = releaseCoreState(state);
|
|
715
|
+
if (anchors.block) releaseBlockState(anchors.block);
|
|
716
|
+
if (anchors.inline) releaseInlineState(anchors.inline);
|
|
717
|
+
if (anchors.tokens.size < 24 && tokens.length > 0) sampleTokensOnce(anchors.tokens, tokens);
|
|
106
718
|
};
|
|
107
719
|
const release = (owner, key) => Object.getPrototypeOf(owner)[key] === owner[key];
|
|
108
720
|
if (release(md, 'parse') && release(md, 'parseInline')) {
|
|
@@ -132,8 +744,12 @@ function keepClasses(md) {
|
|
|
132
744
|
if (release(md.inline, 'parse')) md.inline.parse = function (str, md, env, outTokens) {
|
|
133
745
|
const state = new this.State(str, md, env, outTokens);
|
|
134
746
|
this.tokenize(state);
|
|
135
|
-
|
|
136
|
-
|
|
747
|
+
if (hasAnyDelimiters(state)) {
|
|
748
|
+
const rules = this.ruler2.getRules(''), length = rules.length;
|
|
749
|
+
for (let index = 0; index < length; index++) rules[index](state);
|
|
750
|
+
} else {
|
|
751
|
+
fragmentsJoin(state);
|
|
752
|
+
}
|
|
137
753
|
anchors.inline = state;
|
|
138
754
|
};
|
|
139
755
|
}
|
|
@@ -144,12 +760,20 @@ export function tuneMarkdownEngine(md) {
|
|
|
144
760
|
md.core.ruler.at('normalize', state => {
|
|
145
761
|
let src = state.src;
|
|
146
762
|
if (src.indexOf('\r') >= 0) src = src.replace(NEWLINES, '\n');
|
|
147
|
-
if (src.indexOf('\0') >= 0) src = src.replace(NULLS, '
|
|
763
|
+
if (src.indexOf('\0') >= 0) src = src.replace(NULLS, '\ufffd');
|
|
148
764
|
state.src = src;
|
|
149
765
|
});
|
|
766
|
+
md.core.ruler.at('text_join', textJoin);
|
|
150
767
|
const BaseBlock = md.block.State;
|
|
151
768
|
md.block.State = lineScanner(BaseBlock, new BaseBlock('', md, {}, []).Token);
|
|
769
|
+
md.block.ruler.at('lheading', lheading);
|
|
770
|
+
md.block.ruler.at('paragraph', paragraph);
|
|
771
|
+
md.inline.ruler.at('text', textRule);
|
|
152
772
|
md.inline.ruler.at('backticks', backticks);
|
|
773
|
+
md.inline.ruler2.at('fragments_join', fragmentsJoin);
|
|
774
|
+
md.helpers.parseLinkLabel = fastParseLinkLabel;
|
|
775
|
+
tuneScanDelims(md);
|
|
776
|
+
tuneInlineTokenizer(md);
|
|
153
777
|
const normalizeLink = md.normalizeLink;
|
|
154
778
|
md.normalizeLink = url => cleanWebLink(url) ? url : normalizeLink.call(md, url);
|
|
155
779
|
keepClasses(md);
|