@morlay/dsh-reference 0.0.1-alpha.2
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/LICENSE +21 -0
- package/README.md +28 -0
- package/dist/index.d.mts +24 -0
- package/dist/index.mjs +4948 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +52 -0
- package/src/file-content.ts +144 -0
- package/src/index.ts +105 -0
- package/src/links.ts +96 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,4948 @@
|
|
|
1
|
+
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
2
|
+
import { isUserInvocable, renderSkillContent } from "@deepseek-ai/dsh-skill";
|
|
3
|
+
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
4
|
+
//#region src/file-content.ts
|
|
5
|
+
const READ_LIMIT = 2e3;
|
|
6
|
+
const READ_MAX_LINE_LENGTH = 2e3;
|
|
7
|
+
const READ_MAX_BYTES = 51200;
|
|
8
|
+
const STREAM_MIN_SIZE = 10485760;
|
|
9
|
+
async function readFileContent(fs, reference, request) {
|
|
10
|
+
const offset = reference.lineStart ?? 1;
|
|
11
|
+
const limit = reference.lineEnd === void 0 ? READ_LIMIT : Math.max(1, reference.lineEnd - offset + 1);
|
|
12
|
+
try {
|
|
13
|
+
const target = await fs.resolve(reference.path, {
|
|
14
|
+
...request.cwd === void 0 ? {} : { cwd: request.cwd },
|
|
15
|
+
signal: request.signal
|
|
16
|
+
});
|
|
17
|
+
const info = await fs.stat(target, request.signal);
|
|
18
|
+
if (info === void 0 || info.type !== "file") return void 0;
|
|
19
|
+
const window = await buildWindow(info.size === void 0 || info.size >= STREAM_MIN_SIZE ? await fs.streamText(target, request.signal) : [await fs.readText(target, request.signal)], {
|
|
20
|
+
offset,
|
|
21
|
+
limit
|
|
22
|
+
});
|
|
23
|
+
if (window === void 0) return void 0;
|
|
24
|
+
return formatFileContent(target.displayPath, {
|
|
25
|
+
offset,
|
|
26
|
+
lines: window.lines,
|
|
27
|
+
totalLines: window.totalLines,
|
|
28
|
+
truncatedByBytes: window.truncatedByBytes
|
|
29
|
+
});
|
|
30
|
+
} catch {
|
|
31
|
+
request.signal.throwIfAborted();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function buildWindow(chunks, window) {
|
|
36
|
+
const lines = [];
|
|
37
|
+
let totalLines = 0;
|
|
38
|
+
let outputBytes = 0;
|
|
39
|
+
let truncatedByBytes = false;
|
|
40
|
+
let lineBuffer = "";
|
|
41
|
+
const lineBufferCap = 2001;
|
|
42
|
+
const append = (segment) => {
|
|
43
|
+
if (lineBuffer.length >= lineBufferCap) return;
|
|
44
|
+
lineBuffer += segment;
|
|
45
|
+
if (lineBuffer.length > lineBufferCap) lineBuffer = lineBuffer.slice(0, lineBufferCap);
|
|
46
|
+
};
|
|
47
|
+
const flush = () => {
|
|
48
|
+
const raw = lineBuffer.endsWith("\r") ? lineBuffer.slice(0, -1) : lineBuffer;
|
|
49
|
+
lineBuffer = "";
|
|
50
|
+
totalLines += 1;
|
|
51
|
+
if (truncatedByBytes || totalLines < window.offset || lines.length >= window.limit) return;
|
|
52
|
+
const text = raw.length > READ_MAX_LINE_LENGTH ? `${raw.slice(0, READ_MAX_LINE_LENGTH)}... (line truncated to ${READ_MAX_LINE_LENGTH} chars)` : raw;
|
|
53
|
+
const bytes = Buffer.byteLength(text, "utf8") + (lines.length > 0 ? 1 : 0);
|
|
54
|
+
if (outputBytes + bytes > READ_MAX_BYTES) {
|
|
55
|
+
truncatedByBytes = true;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
outputBytes += bytes;
|
|
59
|
+
lines.push({
|
|
60
|
+
number: totalLines,
|
|
61
|
+
text
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
for await (const chunk of chunks) {
|
|
65
|
+
let start = 0;
|
|
66
|
+
let newline = chunk.indexOf("\n", start);
|
|
67
|
+
while (newline !== -1) {
|
|
68
|
+
append(chunk.slice(start, newline));
|
|
69
|
+
flush();
|
|
70
|
+
start = newline + 1;
|
|
71
|
+
newline = chunk.indexOf("\n", start);
|
|
72
|
+
}
|
|
73
|
+
append(chunk.slice(start));
|
|
74
|
+
}
|
|
75
|
+
if (lineBuffer.length > 0) flush();
|
|
76
|
+
if (!truncatedByBytes && window.offset > totalLines && !(totalLines === 0 && window.offset === 1)) return void 0;
|
|
77
|
+
return {
|
|
78
|
+
lines,
|
|
79
|
+
totalLines,
|
|
80
|
+
truncatedByBytes
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function formatFileContent(displayPath, outcome) {
|
|
84
|
+
const endLine = outcome.lines.at(-1)?.number ?? Math.max(0, outcome.offset - 1);
|
|
85
|
+
let footer;
|
|
86
|
+
if (outcome.truncatedByBytes) footer = `(Output capped. Showing lines ${outcome.offset}-${endLine}. Use offset=${endLine + 1} to continue.)`;
|
|
87
|
+
else if (endLine < outcome.totalLines) footer = `(Showing lines ${outcome.offset}-${endLine} of ${outcome.totalLines}. Use offset=${endLine + 1} to continue.)`;
|
|
88
|
+
else footer = `(End of file - total ${outcome.totalLines} lines)`;
|
|
89
|
+
const body = outcome.lines.length === 0 ? footer : `${outcome.lines.map((line) => `${line.number}: ${line.text}`).join("\n")}\n\n${footer}`;
|
|
90
|
+
return `<file_content path="${displayPath.replaceAll("\"", """)}">
|
|
91
|
+
${body}
|
|
92
|
+
</file_content>`;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region ../../../node_modules/.pnpm/ccount@2.0.1/node_modules/ccount/index.js
|
|
96
|
+
/**
|
|
97
|
+
* Count how often a character (or substring) is used in a string.
|
|
98
|
+
*
|
|
99
|
+
* @param {string} value
|
|
100
|
+
* Value to search in.
|
|
101
|
+
* @param {string} character
|
|
102
|
+
* Character (or substring) to look for.
|
|
103
|
+
* @return {number}
|
|
104
|
+
* Number of times `character` occurred in `value`.
|
|
105
|
+
*/
|
|
106
|
+
function ccount(value, character) {
|
|
107
|
+
const source = String(value);
|
|
108
|
+
if (typeof character !== "string") throw new TypeError("Expected character");
|
|
109
|
+
let count = 0;
|
|
110
|
+
let index = source.indexOf(character);
|
|
111
|
+
while (index !== -1) {
|
|
112
|
+
count++;
|
|
113
|
+
index = source.indexOf(character, index + character.length);
|
|
114
|
+
}
|
|
115
|
+
return count;
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region ../../../node_modules/.pnpm/micromark-util-character@2.1.1/node_modules/micromark-util-character/index.js
|
|
119
|
+
/**
|
|
120
|
+
* @import {Code} from 'micromark-util-types'
|
|
121
|
+
*/
|
|
122
|
+
/**
|
|
123
|
+
* Check whether the character code represents an ASCII alpha (`a` through `z`,
|
|
124
|
+
* case insensitive).
|
|
125
|
+
*
|
|
126
|
+
* An **ASCII alpha** is an ASCII upper alpha or ASCII lower alpha.
|
|
127
|
+
*
|
|
128
|
+
* An **ASCII upper alpha** is a character in the inclusive range U+0041 (`A`)
|
|
129
|
+
* to U+005A (`Z`).
|
|
130
|
+
*
|
|
131
|
+
* An **ASCII lower alpha** is a character in the inclusive range U+0061 (`a`)
|
|
132
|
+
* to U+007A (`z`).
|
|
133
|
+
*
|
|
134
|
+
* @param code
|
|
135
|
+
* Code.
|
|
136
|
+
* @returns {boolean}
|
|
137
|
+
* Whether it matches.
|
|
138
|
+
*/
|
|
139
|
+
const asciiAlpha = regexCheck(/[A-Za-z]/);
|
|
140
|
+
/**
|
|
141
|
+
* Check whether the character code represents an ASCII alphanumeric (`a`
|
|
142
|
+
* through `z`, case insensitive, or `0` through `9`).
|
|
143
|
+
*
|
|
144
|
+
* An **ASCII alphanumeric** is an ASCII digit (see `asciiDigit`) or ASCII alpha
|
|
145
|
+
* (see `asciiAlpha`).
|
|
146
|
+
*
|
|
147
|
+
* @param code
|
|
148
|
+
* Code.
|
|
149
|
+
* @returns {boolean}
|
|
150
|
+
* Whether it matches.
|
|
151
|
+
*/
|
|
152
|
+
const asciiAlphanumeric = regexCheck(/[\dA-Za-z]/);
|
|
153
|
+
/**
|
|
154
|
+
* Check whether a character code is an ASCII control character.
|
|
155
|
+
*
|
|
156
|
+
* An **ASCII control** is a character in the inclusive range U+0000 NULL (NUL)
|
|
157
|
+
* to U+001F (US), or U+007F (DEL).
|
|
158
|
+
*
|
|
159
|
+
* @param {Code} code
|
|
160
|
+
* Code.
|
|
161
|
+
* @returns {boolean}
|
|
162
|
+
* Whether it matches.
|
|
163
|
+
*/
|
|
164
|
+
function asciiControl(code) {
|
|
165
|
+
return code !== null && (code < 32 || code === 127);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Check whether the character code represents an ASCII digit (`0` through `9`).
|
|
169
|
+
*
|
|
170
|
+
* An **ASCII digit** is a character in the inclusive range U+0030 (`0`) to
|
|
171
|
+
* U+0039 (`9`).
|
|
172
|
+
*
|
|
173
|
+
* @param code
|
|
174
|
+
* Code.
|
|
175
|
+
* @returns {boolean}
|
|
176
|
+
* Whether it matches.
|
|
177
|
+
*/
|
|
178
|
+
const asciiDigit = regexCheck(/\d/);
|
|
179
|
+
/**
|
|
180
|
+
* Check whether a character code is a markdown line ending.
|
|
181
|
+
*
|
|
182
|
+
* A **markdown line ending** is the virtual characters M-0003 CARRIAGE RETURN
|
|
183
|
+
* LINE FEED (CRLF), M-0004 LINE FEED (LF) and M-0005 CARRIAGE RETURN (CR).
|
|
184
|
+
*
|
|
185
|
+
* In micromark, the actual character U+000A LINE FEED (LF) and U+000D CARRIAGE
|
|
186
|
+
* RETURN (CR) are replaced by these virtual characters depending on whether
|
|
187
|
+
* they occurred together.
|
|
188
|
+
*
|
|
189
|
+
* @param {Code} code
|
|
190
|
+
* Code.
|
|
191
|
+
* @returns {boolean}
|
|
192
|
+
* Whether it matches.
|
|
193
|
+
*/
|
|
194
|
+
function markdownLineEnding(code) {
|
|
195
|
+
return code !== null && code < -2;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Check whether a character code is a markdown line ending (see
|
|
199
|
+
* `markdownLineEnding`) or markdown space (see `markdownSpace`).
|
|
200
|
+
*
|
|
201
|
+
* @param {Code} code
|
|
202
|
+
* Code.
|
|
203
|
+
* @returns {boolean}
|
|
204
|
+
* Whether it matches.
|
|
205
|
+
*/
|
|
206
|
+
function markdownLineEndingOrSpace(code) {
|
|
207
|
+
return code !== null && (code < 0 || code === 32);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Check whether a character code is a markdown space.
|
|
211
|
+
*
|
|
212
|
+
* A **markdown space** is the concrete character U+0020 SPACE (SP) and the
|
|
213
|
+
* virtual characters M-0001 VIRTUAL SPACE (VS) and M-0002 HORIZONTAL TAB (HT).
|
|
214
|
+
*
|
|
215
|
+
* In micromark, the actual character U+0009 CHARACTER TABULATION (HT) is
|
|
216
|
+
* replaced by one M-0002 HORIZONTAL TAB (HT) and between 0 and 3 M-0001 VIRTUAL
|
|
217
|
+
* SPACE (VS) characters, depending on the column at which the tab occurred.
|
|
218
|
+
*
|
|
219
|
+
* @param {Code} code
|
|
220
|
+
* Code.
|
|
221
|
+
* @returns {boolean}
|
|
222
|
+
* Whether it matches.
|
|
223
|
+
*/
|
|
224
|
+
function markdownSpace(code) {
|
|
225
|
+
return code === -2 || code === -1 || code === 32;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Check whether the character code represents Unicode punctuation.
|
|
229
|
+
*
|
|
230
|
+
* A **Unicode punctuation** is a character in the Unicode `Pc` (Punctuation,
|
|
231
|
+
* Connector), `Pd` (Punctuation, Dash), `Pe` (Punctuation, Close), `Pf`
|
|
232
|
+
* (Punctuation, Final quote), `Pi` (Punctuation, Initial quote), `Po`
|
|
233
|
+
* (Punctuation, Other), or `Ps` (Punctuation, Open) categories, or an ASCII
|
|
234
|
+
* punctuation (see `asciiPunctuation`).
|
|
235
|
+
*
|
|
236
|
+
* See:
|
|
237
|
+
* **\[UNICODE]**:
|
|
238
|
+
* [The Unicode Standard](https://www.unicode.org/versions/).
|
|
239
|
+
* Unicode Consortium.
|
|
240
|
+
*
|
|
241
|
+
* @param code
|
|
242
|
+
* Code.
|
|
243
|
+
* @returns
|
|
244
|
+
* Whether it matches.
|
|
245
|
+
*/
|
|
246
|
+
const unicodePunctuation = regexCheck(/\p{P}|\p{S}/u);
|
|
247
|
+
/**
|
|
248
|
+
* Check whether the character code represents Unicode whitespace.
|
|
249
|
+
*
|
|
250
|
+
* Note that this does handle micromark specific markdown whitespace characters.
|
|
251
|
+
* See `markdownLineEndingOrSpace` to check that.
|
|
252
|
+
*
|
|
253
|
+
* A **Unicode whitespace** is a character in the Unicode `Zs` (Separator,
|
|
254
|
+
* Space) category, or U+0009 CHARACTER TABULATION (HT), U+000A LINE FEED (LF),
|
|
255
|
+
* U+000C (FF), or U+000D CARRIAGE RETURN (CR) (**\[UNICODE]**).
|
|
256
|
+
*
|
|
257
|
+
* See:
|
|
258
|
+
* **\[UNICODE]**:
|
|
259
|
+
* [The Unicode Standard](https://www.unicode.org/versions/).
|
|
260
|
+
* Unicode Consortium.
|
|
261
|
+
*
|
|
262
|
+
* @param code
|
|
263
|
+
* Code.
|
|
264
|
+
* @returns
|
|
265
|
+
* Whether it matches.
|
|
266
|
+
*/
|
|
267
|
+
const unicodeWhitespace = regexCheck(/\s/);
|
|
268
|
+
/**
|
|
269
|
+
* Create a code check from a regex.
|
|
270
|
+
*
|
|
271
|
+
* @param {RegExp} regex
|
|
272
|
+
* Expression.
|
|
273
|
+
* @returns {(code: Code) => boolean}
|
|
274
|
+
* Check.
|
|
275
|
+
*/
|
|
276
|
+
function regexCheck(regex) {
|
|
277
|
+
return check;
|
|
278
|
+
/**
|
|
279
|
+
* Check whether a code matches the bound regex.
|
|
280
|
+
*
|
|
281
|
+
* @param {Code} code
|
|
282
|
+
* Character code.
|
|
283
|
+
* @returns {boolean}
|
|
284
|
+
* Whether the character code matches the bound regex.
|
|
285
|
+
*/
|
|
286
|
+
function check(code) {
|
|
287
|
+
return code !== null && code > -1 && regex.test(String.fromCharCode(code));
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
//#endregion
|
|
291
|
+
//#region ../../../node_modules/.pnpm/escape-string-regexp@5.0.0/node_modules/escape-string-regexp/index.js
|
|
292
|
+
function escapeStringRegexp(string) {
|
|
293
|
+
if (typeof string !== "string") throw new TypeError("Expected a string");
|
|
294
|
+
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
|
|
295
|
+
}
|
|
296
|
+
//#endregion
|
|
297
|
+
//#region ../../../node_modules/.pnpm/unist-util-is@6.0.1/node_modules/unist-util-is/lib/index.js
|
|
298
|
+
/**
|
|
299
|
+
* Generate an assertion from a test.
|
|
300
|
+
*
|
|
301
|
+
* Useful if you’re going to test many nodes, for example when creating a
|
|
302
|
+
* utility where something else passes a compatible test.
|
|
303
|
+
*
|
|
304
|
+
* The created function is a bit faster because it expects valid input only:
|
|
305
|
+
* a `node`, `index`, and `parent`.
|
|
306
|
+
*
|
|
307
|
+
* @param {Test} test
|
|
308
|
+
* * when nullish, checks if `node` is a `Node`.
|
|
309
|
+
* * when `string`, works like passing `(node) => node.type === test`.
|
|
310
|
+
* * when `function` checks if function passed the node is true.
|
|
311
|
+
* * when `object`, checks that all keys in test are in node, and that they have (strictly) equal values.
|
|
312
|
+
* * when `array`, checks if any one of the subtests pass.
|
|
313
|
+
* @returns {Check}
|
|
314
|
+
* An assertion.
|
|
315
|
+
*/
|
|
316
|
+
const convert = (
|
|
317
|
+
/**
|
|
318
|
+
* @param {Test} [test]
|
|
319
|
+
* @returns {Check}
|
|
320
|
+
*/
|
|
321
|
+
function(test) {
|
|
322
|
+
if (test === null || test === void 0) return ok;
|
|
323
|
+
if (typeof test === "function") return castFactory(test);
|
|
324
|
+
if (typeof test === "object") return Array.isArray(test) ? anyFactory(test) : propertiesFactory(test);
|
|
325
|
+
if (typeof test === "string") return typeFactory(test);
|
|
326
|
+
throw new Error("Expected function, string, or object as test");
|
|
327
|
+
});
|
|
328
|
+
/**
|
|
329
|
+
* @param {Array<Props | TestFunction | string>} tests
|
|
330
|
+
* @returns {Check}
|
|
331
|
+
*/
|
|
332
|
+
function anyFactory(tests) {
|
|
333
|
+
/** @type {Array<Check>} */
|
|
334
|
+
const checks = [];
|
|
335
|
+
let index = -1;
|
|
336
|
+
while (++index < tests.length) checks[index] = convert(tests[index]);
|
|
337
|
+
return castFactory(any);
|
|
338
|
+
/**
|
|
339
|
+
* @this {unknown}
|
|
340
|
+
* @type {TestFunction}
|
|
341
|
+
*/
|
|
342
|
+
function any(...parameters) {
|
|
343
|
+
let index = -1;
|
|
344
|
+
while (++index < checks.length) if (checks[index].apply(this, parameters)) return true;
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Turn an object into a test for a node with a certain fields.
|
|
350
|
+
*
|
|
351
|
+
* @param {Props} check
|
|
352
|
+
* @returns {Check}
|
|
353
|
+
*/
|
|
354
|
+
function propertiesFactory(check) {
|
|
355
|
+
const checkAsRecord = check;
|
|
356
|
+
return castFactory(all);
|
|
357
|
+
/**
|
|
358
|
+
* @param {Node} node
|
|
359
|
+
* @returns {boolean}
|
|
360
|
+
*/
|
|
361
|
+
function all(node) {
|
|
362
|
+
const nodeAsRecord = node;
|
|
363
|
+
/** @type {string} */
|
|
364
|
+
let key;
|
|
365
|
+
for (key in check) if (nodeAsRecord[key] !== checkAsRecord[key]) return false;
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Turn a string into a test for a node with a certain type.
|
|
371
|
+
*
|
|
372
|
+
* @param {string} check
|
|
373
|
+
* @returns {Check}
|
|
374
|
+
*/
|
|
375
|
+
function typeFactory(check) {
|
|
376
|
+
return castFactory(type);
|
|
377
|
+
/**
|
|
378
|
+
* @param {Node} node
|
|
379
|
+
*/
|
|
380
|
+
function type(node) {
|
|
381
|
+
return node && node.type === check;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Turn a custom test into a test for a node that passes that test.
|
|
386
|
+
*
|
|
387
|
+
* @param {TestFunction} testFunction
|
|
388
|
+
* @returns {Check}
|
|
389
|
+
*/
|
|
390
|
+
function castFactory(testFunction) {
|
|
391
|
+
return check;
|
|
392
|
+
/**
|
|
393
|
+
* @this {unknown}
|
|
394
|
+
* @type {Check}
|
|
395
|
+
*/
|
|
396
|
+
function check(value, index, parent) {
|
|
397
|
+
return Boolean(looksLikeANode(value) && testFunction.call(this, value, typeof index === "number" ? index : void 0, parent || void 0));
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
function ok() {
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* @param {unknown} value
|
|
405
|
+
* @returns {value is Node}
|
|
406
|
+
*/
|
|
407
|
+
function looksLikeANode(value) {
|
|
408
|
+
return value !== null && typeof value === "object" && "type" in value;
|
|
409
|
+
}
|
|
410
|
+
//#endregion
|
|
411
|
+
//#region ../../../node_modules/.pnpm/unist-util-visit-parents@6.0.2/node_modules/unist-util-visit-parents/lib/color.node.js
|
|
412
|
+
/**
|
|
413
|
+
* @param {string} d
|
|
414
|
+
* @returns {string}
|
|
415
|
+
*/
|
|
416
|
+
function color(d) {
|
|
417
|
+
return "\x1B[33m" + d + "\x1B[39m";
|
|
418
|
+
}
|
|
419
|
+
//#endregion
|
|
420
|
+
//#region ../../../node_modules/.pnpm/unist-util-visit-parents@6.0.2/node_modules/unist-util-visit-parents/lib/index.js
|
|
421
|
+
/**
|
|
422
|
+
* @import {Node as UnistNode, Parent as UnistParent} from 'unist'
|
|
423
|
+
*/
|
|
424
|
+
/**
|
|
425
|
+
* @typedef {Exclude<import('unist-util-is').Test, undefined> | undefined} Test
|
|
426
|
+
* Test from `unist-util-is`.
|
|
427
|
+
*
|
|
428
|
+
* Note: we have remove and add `undefined`, because otherwise when generating
|
|
429
|
+
* automatic `.d.ts` files, TS tries to flatten paths from a local perspective,
|
|
430
|
+
* which doesn’t work when publishing on npm.
|
|
431
|
+
*/
|
|
432
|
+
/**
|
|
433
|
+
* @typedef {(
|
|
434
|
+
* Fn extends (value: any) => value is infer Thing
|
|
435
|
+
* ? Thing
|
|
436
|
+
* : Fallback
|
|
437
|
+
* )} Predicate
|
|
438
|
+
* Get the value of a type guard `Fn`.
|
|
439
|
+
* @template Fn
|
|
440
|
+
* Value; typically function that is a type guard (such as `(x): x is Y`).
|
|
441
|
+
* @template Fallback
|
|
442
|
+
* Value to yield if `Fn` is not a type guard.
|
|
443
|
+
*/
|
|
444
|
+
/**
|
|
445
|
+
* @typedef {(
|
|
446
|
+
* Check extends null | undefined // No test.
|
|
447
|
+
* ? Value
|
|
448
|
+
* : Value extends {type: Check} // String (type) test.
|
|
449
|
+
* ? Value
|
|
450
|
+
* : Value extends Check // Partial test.
|
|
451
|
+
* ? Value
|
|
452
|
+
* : Check extends Function // Function test.
|
|
453
|
+
* ? Predicate<Check, Value> extends Value
|
|
454
|
+
* ? Predicate<Check, Value>
|
|
455
|
+
* : never
|
|
456
|
+
* : never // Some other test?
|
|
457
|
+
* )} MatchesOne
|
|
458
|
+
* Check whether a node matches a primitive check in the type system.
|
|
459
|
+
* @template Value
|
|
460
|
+
* Value; typically unist `Node`.
|
|
461
|
+
* @template Check
|
|
462
|
+
* Value; typically `unist-util-is`-compatible test, but not arrays.
|
|
463
|
+
*/
|
|
464
|
+
/**
|
|
465
|
+
* @typedef {(
|
|
466
|
+
* Check extends ReadonlyArray<infer T>
|
|
467
|
+
* ? MatchesOne<Value, T>
|
|
468
|
+
* : Check extends Array<infer T>
|
|
469
|
+
* ? MatchesOne<Value, T>
|
|
470
|
+
* : MatchesOne<Value, Check>
|
|
471
|
+
* )} Matches
|
|
472
|
+
* Check whether a node matches a check in the type system.
|
|
473
|
+
* @template Value
|
|
474
|
+
* Value; typically unist `Node`.
|
|
475
|
+
* @template Check
|
|
476
|
+
* Value; typically `unist-util-is`-compatible test.
|
|
477
|
+
*/
|
|
478
|
+
/**
|
|
479
|
+
* @typedef {0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10} Uint
|
|
480
|
+
* Number; capped reasonably.
|
|
481
|
+
*/
|
|
482
|
+
/**
|
|
483
|
+
* @typedef {I extends 0 ? 1 : I extends 1 ? 2 : I extends 2 ? 3 : I extends 3 ? 4 : I extends 4 ? 5 : I extends 5 ? 6 : I extends 6 ? 7 : I extends 7 ? 8 : I extends 8 ? 9 : 10} Increment
|
|
484
|
+
* Increment a number in the type system.
|
|
485
|
+
* @template {Uint} [I=0]
|
|
486
|
+
* Index.
|
|
487
|
+
*/
|
|
488
|
+
/**
|
|
489
|
+
* @typedef {(
|
|
490
|
+
* Node extends UnistParent
|
|
491
|
+
* ? Node extends {children: Array<infer Children>}
|
|
492
|
+
* ? Child extends Children ? Node : never
|
|
493
|
+
* : never
|
|
494
|
+
* : never
|
|
495
|
+
* )} InternalParent
|
|
496
|
+
* Collect nodes that can be parents of `Child`.
|
|
497
|
+
* @template {UnistNode} Node
|
|
498
|
+
* All node types in a tree.
|
|
499
|
+
* @template {UnistNode} Child
|
|
500
|
+
* Node to search for.
|
|
501
|
+
*/
|
|
502
|
+
/**
|
|
503
|
+
* @typedef {InternalParent<InclusiveDescendant<Tree>, Child>} Parent
|
|
504
|
+
* Collect nodes in `Tree` that can be parents of `Child`.
|
|
505
|
+
* @template {UnistNode} Tree
|
|
506
|
+
* All node types in a tree.
|
|
507
|
+
* @template {UnistNode} Child
|
|
508
|
+
* Node to search for.
|
|
509
|
+
*/
|
|
510
|
+
/**
|
|
511
|
+
* @typedef {(
|
|
512
|
+
* Depth extends Max
|
|
513
|
+
* ? never
|
|
514
|
+
* :
|
|
515
|
+
* | InternalParent<Node, Child>
|
|
516
|
+
* | InternalAncestor<Node, InternalParent<Node, Child>, Max, Increment<Depth>>
|
|
517
|
+
* )} InternalAncestor
|
|
518
|
+
* Collect nodes in `Tree` that can be ancestors of `Child`.
|
|
519
|
+
* @template {UnistNode} Node
|
|
520
|
+
* All node types in a tree.
|
|
521
|
+
* @template {UnistNode} Child
|
|
522
|
+
* Node to search for.
|
|
523
|
+
* @template {Uint} [Max=10]
|
|
524
|
+
* Max; searches up to this depth.
|
|
525
|
+
* @template {Uint} [Depth=0]
|
|
526
|
+
* Current depth.
|
|
527
|
+
*/
|
|
528
|
+
/**
|
|
529
|
+
* @typedef {InternalAncestor<InclusiveDescendant<Tree>, Child>} Ancestor
|
|
530
|
+
* Collect nodes in `Tree` that can be ancestors of `Child`.
|
|
531
|
+
* @template {UnistNode} Tree
|
|
532
|
+
* All node types in a tree.
|
|
533
|
+
* @template {UnistNode} Child
|
|
534
|
+
* Node to search for.
|
|
535
|
+
*/
|
|
536
|
+
/**
|
|
537
|
+
* @typedef {(
|
|
538
|
+
* Tree extends UnistParent
|
|
539
|
+
* ? Depth extends Max
|
|
540
|
+
* ? Tree
|
|
541
|
+
* : Tree | InclusiveDescendant<Tree['children'][number], Max, Increment<Depth>>
|
|
542
|
+
* : Tree
|
|
543
|
+
* )} InclusiveDescendant
|
|
544
|
+
* Collect all (inclusive) descendants of `Tree`.
|
|
545
|
+
*
|
|
546
|
+
* > 👉 **Note**: for performance reasons, this seems to be the fastest way to
|
|
547
|
+
* > recurse without actually running into an infinite loop, which the
|
|
548
|
+
* > previous version did.
|
|
549
|
+
* >
|
|
550
|
+
* > Practically, a max of `2` is typically enough assuming a `Root` is
|
|
551
|
+
* > passed, but it doesn’t improve performance.
|
|
552
|
+
* > It gets higher with `List > ListItem > Table > TableRow > TableCell`.
|
|
553
|
+
* > Using up to `10` doesn’t hurt or help either.
|
|
554
|
+
* @template {UnistNode} Tree
|
|
555
|
+
* Tree type.
|
|
556
|
+
* @template {Uint} [Max=10]
|
|
557
|
+
* Max; searches up to this depth.
|
|
558
|
+
* @template {Uint} [Depth=0]
|
|
559
|
+
* Current depth.
|
|
560
|
+
*/
|
|
561
|
+
/**
|
|
562
|
+
* @typedef {'skip' | boolean} Action
|
|
563
|
+
* Union of the action types.
|
|
564
|
+
*
|
|
565
|
+
* @typedef {number} Index
|
|
566
|
+
* Move to the sibling at `index` next (after node itself is completely
|
|
567
|
+
* traversed).
|
|
568
|
+
*
|
|
569
|
+
* Useful if mutating the tree, such as removing the node the visitor is
|
|
570
|
+
* currently on, or any of its previous siblings.
|
|
571
|
+
* Results less than 0 or greater than or equal to `children.length` stop
|
|
572
|
+
* traversing the parent.
|
|
573
|
+
*
|
|
574
|
+
* @typedef {[(Action | null | undefined | void)?, (Index | null | undefined)?]} ActionTuple
|
|
575
|
+
* List with one or two values, the first an action, the second an index.
|
|
576
|
+
*
|
|
577
|
+
* @typedef {Action | ActionTuple | Index | null | undefined | void} VisitorResult
|
|
578
|
+
* Any value that can be returned from a visitor.
|
|
579
|
+
*/
|
|
580
|
+
/**
|
|
581
|
+
* @callback Visitor
|
|
582
|
+
* Handle a node (matching `test`, if given).
|
|
583
|
+
*
|
|
584
|
+
* Visitors are free to transform `node`.
|
|
585
|
+
* They can also transform the parent of node (the last of `ancestors`).
|
|
586
|
+
*
|
|
587
|
+
* Replacing `node` itself, if `SKIP` is not returned, still causes its
|
|
588
|
+
* descendants to be walked (which is a bug).
|
|
589
|
+
*
|
|
590
|
+
* When adding or removing previous siblings of `node` (or next siblings, in
|
|
591
|
+
* case of reverse), the `Visitor` should return a new `Index` to specify the
|
|
592
|
+
* sibling to traverse after `node` is traversed.
|
|
593
|
+
* Adding or removing next siblings of `node` (or previous siblings, in case
|
|
594
|
+
* of reverse) is handled as expected without needing to return a new `Index`.
|
|
595
|
+
*
|
|
596
|
+
* Removing the children property of an ancestor still results in them being
|
|
597
|
+
* traversed.
|
|
598
|
+
* @param {Visited} node
|
|
599
|
+
* Found node.
|
|
600
|
+
* @param {Array<VisitedParents>} ancestors
|
|
601
|
+
* Ancestors of `node`.
|
|
602
|
+
* @returns {VisitorResult}
|
|
603
|
+
* What to do next.
|
|
604
|
+
*
|
|
605
|
+
* An `Index` is treated as a tuple of `[CONTINUE, Index]`.
|
|
606
|
+
* An `Action` is treated as a tuple of `[Action]`.
|
|
607
|
+
*
|
|
608
|
+
* Passing a tuple back only makes sense if the `Action` is `SKIP`.
|
|
609
|
+
* When the `Action` is `EXIT`, that action can be returned.
|
|
610
|
+
* When the `Action` is `CONTINUE`, `Index` can be returned.
|
|
611
|
+
* @template {UnistNode} [Visited=UnistNode]
|
|
612
|
+
* Visited node type.
|
|
613
|
+
* @template {UnistParent} [VisitedParents=UnistParent]
|
|
614
|
+
* Ancestor type.
|
|
615
|
+
*/
|
|
616
|
+
/**
|
|
617
|
+
* @typedef {Visitor<Matches<InclusiveDescendant<Tree>, Check>, Ancestor<Tree, Matches<InclusiveDescendant<Tree>, Check>>>} BuildVisitor
|
|
618
|
+
* Build a typed `Visitor` function from a tree and a test.
|
|
619
|
+
*
|
|
620
|
+
* It will infer which values are passed as `node` and which as `parents`.
|
|
621
|
+
* @template {UnistNode} [Tree=UnistNode]
|
|
622
|
+
* Tree type.
|
|
623
|
+
* @template {Test} [Check=Test]
|
|
624
|
+
* Test type.
|
|
625
|
+
*/
|
|
626
|
+
/** @type {Readonly<ActionTuple>} */
|
|
627
|
+
const empty = [];
|
|
628
|
+
/**
|
|
629
|
+
* Visit nodes, with ancestral information.
|
|
630
|
+
*
|
|
631
|
+
* This algorithm performs *depth-first* *tree traversal* in *preorder*
|
|
632
|
+
* (**NLR**) or if `reverse` is given, in *reverse preorder* (**NRL**).
|
|
633
|
+
*
|
|
634
|
+
* You can choose for which nodes `visitor` is called by passing a `test`.
|
|
635
|
+
* For complex tests, you should test yourself in `visitor`, as it will be
|
|
636
|
+
* faster and will have improved type information.
|
|
637
|
+
*
|
|
638
|
+
* Walking the tree is an intensive task.
|
|
639
|
+
* Make use of the return values of the visitor when possible.
|
|
640
|
+
* Instead of walking a tree multiple times, walk it once, use `unist-util-is`
|
|
641
|
+
* to check if a node matches, and then perform different operations.
|
|
642
|
+
*
|
|
643
|
+
* You can change the tree.
|
|
644
|
+
* See `Visitor` for more info.
|
|
645
|
+
*
|
|
646
|
+
* @overload
|
|
647
|
+
* @param {Tree} tree
|
|
648
|
+
* @param {Check} check
|
|
649
|
+
* @param {BuildVisitor<Tree, Check>} visitor
|
|
650
|
+
* @param {boolean | null | undefined} [reverse]
|
|
651
|
+
* @returns {undefined}
|
|
652
|
+
*
|
|
653
|
+
* @overload
|
|
654
|
+
* @param {Tree} tree
|
|
655
|
+
* @param {BuildVisitor<Tree>} visitor
|
|
656
|
+
* @param {boolean | null | undefined} [reverse]
|
|
657
|
+
* @returns {undefined}
|
|
658
|
+
*
|
|
659
|
+
* @param {UnistNode} tree
|
|
660
|
+
* Tree to traverse.
|
|
661
|
+
* @param {Visitor | Test} test
|
|
662
|
+
* `unist-util-is`-compatible test
|
|
663
|
+
* @param {Visitor | boolean | null | undefined} [visitor]
|
|
664
|
+
* Handle each node.
|
|
665
|
+
* @param {boolean | null | undefined} [reverse]
|
|
666
|
+
* Traverse in reverse preorder (NRL) instead of the default preorder (NLR).
|
|
667
|
+
* @returns {undefined}
|
|
668
|
+
* Nothing.
|
|
669
|
+
*
|
|
670
|
+
* @template {UnistNode} Tree
|
|
671
|
+
* Node type.
|
|
672
|
+
* @template {Test} Check
|
|
673
|
+
* `unist-util-is`-compatible test.
|
|
674
|
+
*/
|
|
675
|
+
function visitParents(tree, test, visitor, reverse) {
|
|
676
|
+
/** @type {Test} */
|
|
677
|
+
let check;
|
|
678
|
+
if (typeof test === "function" && typeof visitor !== "function") {
|
|
679
|
+
reverse = visitor;
|
|
680
|
+
visitor = test;
|
|
681
|
+
} else check = test;
|
|
682
|
+
const is = convert(check);
|
|
683
|
+
const step = reverse ? -1 : 1;
|
|
684
|
+
factory(tree, void 0, [])();
|
|
685
|
+
/**
|
|
686
|
+
* @param {UnistNode} node
|
|
687
|
+
* @param {number | undefined} index
|
|
688
|
+
* @param {Array<UnistParent>} parents
|
|
689
|
+
*/
|
|
690
|
+
function factory(node, index, parents) {
|
|
691
|
+
const value = node && typeof node === "object" ? node : {};
|
|
692
|
+
if (typeof value.type === "string") {
|
|
693
|
+
const name = typeof value.tagName === "string" ? value.tagName : typeof value.name === "string" ? value.name : void 0;
|
|
694
|
+
Object.defineProperty(visit, "name", { value: "node (" + color(node.type + (name ? "<" + name + ">" : "")) + ")" });
|
|
695
|
+
}
|
|
696
|
+
return visit;
|
|
697
|
+
function visit() {
|
|
698
|
+
/** @type {Readonly<ActionTuple>} */
|
|
699
|
+
let result = empty;
|
|
700
|
+
/** @type {Readonly<ActionTuple>} */
|
|
701
|
+
let subresult;
|
|
702
|
+
/** @type {number} */
|
|
703
|
+
let offset;
|
|
704
|
+
/** @type {Array<UnistParent>} */
|
|
705
|
+
let grandparents;
|
|
706
|
+
if (!test || is(node, index, parents[parents.length - 1] || void 0)) {
|
|
707
|
+
result = toResult(visitor(node, parents));
|
|
708
|
+
if (result[0] === false) return result;
|
|
709
|
+
}
|
|
710
|
+
if ("children" in node && node.children) {
|
|
711
|
+
const nodeAsParent = node;
|
|
712
|
+
if (nodeAsParent.children && result[0] !== "skip") {
|
|
713
|
+
offset = (reverse ? nodeAsParent.children.length : -1) + step;
|
|
714
|
+
grandparents = parents.concat(nodeAsParent);
|
|
715
|
+
while (offset > -1 && offset < nodeAsParent.children.length) {
|
|
716
|
+
const child = nodeAsParent.children[offset];
|
|
717
|
+
subresult = factory(child, offset, grandparents)();
|
|
718
|
+
if (subresult[0] === false) return subresult;
|
|
719
|
+
offset = typeof subresult[1] === "number" ? subresult[1] : offset + step;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
return result;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Turn a return value into a clean result.
|
|
729
|
+
*
|
|
730
|
+
* @param {VisitorResult} value
|
|
731
|
+
* Valid return values from visitors.
|
|
732
|
+
* @returns {Readonly<ActionTuple>}
|
|
733
|
+
* Clean result.
|
|
734
|
+
*/
|
|
735
|
+
function toResult(value) {
|
|
736
|
+
if (Array.isArray(value)) return value;
|
|
737
|
+
if (typeof value === "number") return [true, value];
|
|
738
|
+
return value === null || value === void 0 ? empty : [value];
|
|
739
|
+
}
|
|
740
|
+
//#endregion
|
|
741
|
+
//#region ../../../node_modules/.pnpm/mdast-util-find-and-replace@3.0.2/node_modules/mdast-util-find-and-replace/lib/index.js
|
|
742
|
+
/**
|
|
743
|
+
* @import {Nodes, Parents, PhrasingContent, Root, Text} from 'mdast'
|
|
744
|
+
* @import {BuildVisitor, Test, VisitorResult} from 'unist-util-visit-parents'
|
|
745
|
+
*/
|
|
746
|
+
/**
|
|
747
|
+
* @typedef RegExpMatchObject
|
|
748
|
+
* Info on the match.
|
|
749
|
+
* @property {number} index
|
|
750
|
+
* The index of the search at which the result was found.
|
|
751
|
+
* @property {string} input
|
|
752
|
+
* A copy of the search string in the text node.
|
|
753
|
+
* @property {[...Array<Parents>, Text]} stack
|
|
754
|
+
* All ancestors of the text node, where the last node is the text itself.
|
|
755
|
+
*
|
|
756
|
+
* @typedef {RegExp | string} Find
|
|
757
|
+
* Pattern to find.
|
|
758
|
+
*
|
|
759
|
+
* Strings are escaped and then turned into global expressions.
|
|
760
|
+
*
|
|
761
|
+
* @typedef {Array<FindAndReplaceTuple>} FindAndReplaceList
|
|
762
|
+
* Several find and replaces, in array form.
|
|
763
|
+
*
|
|
764
|
+
* @typedef {[Find, Replace?]} FindAndReplaceTuple
|
|
765
|
+
* Find and replace in tuple form.
|
|
766
|
+
*
|
|
767
|
+
* @typedef {ReplaceFunction | string | null | undefined} Replace
|
|
768
|
+
* Thing to replace with.
|
|
769
|
+
*
|
|
770
|
+
* @callback ReplaceFunction
|
|
771
|
+
* Callback called when a search matches.
|
|
772
|
+
* @param {...any} parameters
|
|
773
|
+
* The parameters are the result of corresponding search expression:
|
|
774
|
+
*
|
|
775
|
+
* * `value` (`string`) — whole match
|
|
776
|
+
* * `...capture` (`Array<string>`) — matches from regex capture groups
|
|
777
|
+
* * `match` (`RegExpMatchObject`) — info on the match
|
|
778
|
+
* @returns {Array<PhrasingContent> | PhrasingContent | string | false | null | undefined}
|
|
779
|
+
* Thing to replace with.
|
|
780
|
+
*
|
|
781
|
+
* * when `null`, `undefined`, `''`, remove the match
|
|
782
|
+
* * …or when `false`, do not replace at all
|
|
783
|
+
* * …or when `string`, replace with a text node of that value
|
|
784
|
+
* * …or when `Node` or `Array<Node>`, replace with those nodes
|
|
785
|
+
*
|
|
786
|
+
* @typedef {[RegExp, ReplaceFunction]} Pair
|
|
787
|
+
* Normalized find and replace.
|
|
788
|
+
*
|
|
789
|
+
* @typedef {Array<Pair>} Pairs
|
|
790
|
+
* All find and replaced.
|
|
791
|
+
*
|
|
792
|
+
* @typedef Options
|
|
793
|
+
* Configuration.
|
|
794
|
+
* @property {Test | null | undefined} [ignore]
|
|
795
|
+
* Test for which nodes to ignore (optional).
|
|
796
|
+
*/
|
|
797
|
+
/**
|
|
798
|
+
* Find patterns in a tree and replace them.
|
|
799
|
+
*
|
|
800
|
+
* The algorithm searches the tree in *preorder* for complete values in `Text`
|
|
801
|
+
* nodes.
|
|
802
|
+
* Partial matches are not supported.
|
|
803
|
+
*
|
|
804
|
+
* @param {Nodes} tree
|
|
805
|
+
* Tree to change.
|
|
806
|
+
* @param {FindAndReplaceList | FindAndReplaceTuple} list
|
|
807
|
+
* Patterns to find.
|
|
808
|
+
* @param {Options | null | undefined} [options]
|
|
809
|
+
* Configuration (when `find` is not `Find`).
|
|
810
|
+
* @returns {undefined}
|
|
811
|
+
* Nothing.
|
|
812
|
+
*/
|
|
813
|
+
function findAndReplace(tree, list, options) {
|
|
814
|
+
const ignored = convert((options || {}).ignore || []);
|
|
815
|
+
const pairs = toPairs(list);
|
|
816
|
+
let pairIndex = -1;
|
|
817
|
+
while (++pairIndex < pairs.length) visitParents(tree, "text", visitor);
|
|
818
|
+
/** @type {BuildVisitor<Root, 'text'>} */
|
|
819
|
+
function visitor(node, parents) {
|
|
820
|
+
let index = -1;
|
|
821
|
+
/** @type {Parents | undefined} */
|
|
822
|
+
let grandparent;
|
|
823
|
+
while (++index < parents.length) {
|
|
824
|
+
const parent = parents[index];
|
|
825
|
+
/** @type {Array<Nodes> | undefined} */
|
|
826
|
+
const siblings = grandparent ? grandparent.children : void 0;
|
|
827
|
+
if (ignored(parent, siblings ? siblings.indexOf(parent) : void 0, grandparent)) return;
|
|
828
|
+
grandparent = parent;
|
|
829
|
+
}
|
|
830
|
+
if (grandparent) return handler(node, parents);
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Handle a text node which is not in an ignored parent.
|
|
834
|
+
*
|
|
835
|
+
* @param {Text} node
|
|
836
|
+
* Text node.
|
|
837
|
+
* @param {Array<Parents>} parents
|
|
838
|
+
* Parents.
|
|
839
|
+
* @returns {VisitorResult}
|
|
840
|
+
* Result.
|
|
841
|
+
*/
|
|
842
|
+
function handler(node, parents) {
|
|
843
|
+
const parent = parents[parents.length - 1];
|
|
844
|
+
const find = pairs[pairIndex][0];
|
|
845
|
+
const replace = pairs[pairIndex][1];
|
|
846
|
+
let start = 0;
|
|
847
|
+
const index = parent.children.indexOf(node);
|
|
848
|
+
let change = false;
|
|
849
|
+
/** @type {Array<PhrasingContent>} */
|
|
850
|
+
let nodes = [];
|
|
851
|
+
find.lastIndex = 0;
|
|
852
|
+
let match = find.exec(node.value);
|
|
853
|
+
while (match) {
|
|
854
|
+
const position = match.index;
|
|
855
|
+
/** @type {RegExpMatchObject} */
|
|
856
|
+
const matchObject = {
|
|
857
|
+
index: match.index,
|
|
858
|
+
input: match.input,
|
|
859
|
+
stack: [...parents, node]
|
|
860
|
+
};
|
|
861
|
+
let value = replace(...match, matchObject);
|
|
862
|
+
if (typeof value === "string") value = value.length > 0 ? {
|
|
863
|
+
type: "text",
|
|
864
|
+
value
|
|
865
|
+
} : void 0;
|
|
866
|
+
if (value === false) find.lastIndex = position + 1;
|
|
867
|
+
else {
|
|
868
|
+
if (start !== position) nodes.push({
|
|
869
|
+
type: "text",
|
|
870
|
+
value: node.value.slice(start, position)
|
|
871
|
+
});
|
|
872
|
+
if (Array.isArray(value)) nodes.push(...value);
|
|
873
|
+
else if (value) nodes.push(value);
|
|
874
|
+
start = position + match[0].length;
|
|
875
|
+
change = true;
|
|
876
|
+
}
|
|
877
|
+
if (!find.global) break;
|
|
878
|
+
match = find.exec(node.value);
|
|
879
|
+
}
|
|
880
|
+
if (change) {
|
|
881
|
+
if (start < node.value.length) nodes.push({
|
|
882
|
+
type: "text",
|
|
883
|
+
value: node.value.slice(start)
|
|
884
|
+
});
|
|
885
|
+
parent.children.splice(index, 1, ...nodes);
|
|
886
|
+
} else nodes = [node];
|
|
887
|
+
return index + nodes.length;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Turn a tuple or a list of tuples into pairs.
|
|
892
|
+
*
|
|
893
|
+
* @param {FindAndReplaceList | FindAndReplaceTuple} tupleOrList
|
|
894
|
+
* Schema.
|
|
895
|
+
* @returns {Pairs}
|
|
896
|
+
* Clean pairs.
|
|
897
|
+
*/
|
|
898
|
+
function toPairs(tupleOrList) {
|
|
899
|
+
/** @type {Pairs} */
|
|
900
|
+
const result = [];
|
|
901
|
+
if (!Array.isArray(tupleOrList)) throw new TypeError("Expected find and replace tuple or list of tuples");
|
|
902
|
+
/** @type {FindAndReplaceList} */
|
|
903
|
+
const list = !tupleOrList[0] || Array.isArray(tupleOrList[0]) ? tupleOrList : [tupleOrList];
|
|
904
|
+
let index = -1;
|
|
905
|
+
while (++index < list.length) {
|
|
906
|
+
const tuple = list[index];
|
|
907
|
+
result.push([toExpression(tuple[0]), toFunction(tuple[1])]);
|
|
908
|
+
}
|
|
909
|
+
return result;
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Turn a find into an expression.
|
|
913
|
+
*
|
|
914
|
+
* @param {Find} find
|
|
915
|
+
* Find.
|
|
916
|
+
* @returns {RegExp}
|
|
917
|
+
* Expression.
|
|
918
|
+
*/
|
|
919
|
+
function toExpression(find) {
|
|
920
|
+
return typeof find === "string" ? new RegExp(escapeStringRegexp(find), "g") : find;
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Turn a replace into a function.
|
|
924
|
+
*
|
|
925
|
+
* @param {Replace} replace
|
|
926
|
+
* Replace.
|
|
927
|
+
* @returns {ReplaceFunction}
|
|
928
|
+
* Function.
|
|
929
|
+
*/
|
|
930
|
+
function toFunction(replace) {
|
|
931
|
+
return typeof replace === "function" ? replace : function() {
|
|
932
|
+
return replace;
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
//#endregion
|
|
936
|
+
//#region ../../../node_modules/.pnpm/mdast-util-gfm-autolink-literal@2.0.1/node_modules/mdast-util-gfm-autolink-literal/lib/index.js
|
|
937
|
+
/**
|
|
938
|
+
* @import {RegExpMatchObject, ReplaceFunction} from 'mdast-util-find-and-replace'
|
|
939
|
+
* @import {CompileContext, Extension as FromMarkdownExtension, Handle as FromMarkdownHandle, Transform as FromMarkdownTransform} from 'mdast-util-from-markdown'
|
|
940
|
+
* @import {ConstructName, Options as ToMarkdownExtension} from 'mdast-util-to-markdown'
|
|
941
|
+
* @import {Link, PhrasingContent} from 'mdast'
|
|
942
|
+
*/
|
|
943
|
+
/**
|
|
944
|
+
* Create an extension for `mdast-util-from-markdown` to enable GFM autolink
|
|
945
|
+
* literals in markdown.
|
|
946
|
+
*
|
|
947
|
+
* @returns {FromMarkdownExtension}
|
|
948
|
+
* Extension for `mdast-util-to-markdown` to enable GFM autolink literals.
|
|
949
|
+
*/
|
|
950
|
+
function gfmAutolinkLiteralFromMarkdown() {
|
|
951
|
+
return {
|
|
952
|
+
transforms: [transformGfmAutolinkLiterals],
|
|
953
|
+
enter: {
|
|
954
|
+
literalAutolink: enterLiteralAutolink,
|
|
955
|
+
literalAutolinkEmail: enterLiteralAutolinkValue,
|
|
956
|
+
literalAutolinkHttp: enterLiteralAutolinkValue,
|
|
957
|
+
literalAutolinkWww: enterLiteralAutolinkValue
|
|
958
|
+
},
|
|
959
|
+
exit: {
|
|
960
|
+
literalAutolink: exitLiteralAutolink,
|
|
961
|
+
literalAutolinkEmail: exitLiteralAutolinkEmail,
|
|
962
|
+
literalAutolinkHttp: exitLiteralAutolinkHttp,
|
|
963
|
+
literalAutolinkWww: exitLiteralAutolinkWww
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* @this {CompileContext}
|
|
969
|
+
* @type {FromMarkdownHandle}
|
|
970
|
+
*/
|
|
971
|
+
function enterLiteralAutolink(token) {
|
|
972
|
+
this.enter({
|
|
973
|
+
type: "link",
|
|
974
|
+
title: null,
|
|
975
|
+
url: "",
|
|
976
|
+
children: []
|
|
977
|
+
}, token);
|
|
978
|
+
}
|
|
979
|
+
/**
|
|
980
|
+
* @this {CompileContext}
|
|
981
|
+
* @type {FromMarkdownHandle}
|
|
982
|
+
*/
|
|
983
|
+
function enterLiteralAutolinkValue(token) {
|
|
984
|
+
this.config.enter.autolinkProtocol.call(this, token);
|
|
985
|
+
}
|
|
986
|
+
/**
|
|
987
|
+
* @this {CompileContext}
|
|
988
|
+
* @type {FromMarkdownHandle}
|
|
989
|
+
*/
|
|
990
|
+
function exitLiteralAutolinkHttp(token) {
|
|
991
|
+
this.config.exit.autolinkProtocol.call(this, token);
|
|
992
|
+
}
|
|
993
|
+
/**
|
|
994
|
+
* @this {CompileContext}
|
|
995
|
+
* @type {FromMarkdownHandle}
|
|
996
|
+
*/
|
|
997
|
+
function exitLiteralAutolinkWww(token) {
|
|
998
|
+
this.config.exit.data.call(this, token);
|
|
999
|
+
const node = this.stack[this.stack.length - 1];
|
|
1000
|
+
node.type;
|
|
1001
|
+
node.url = "http://" + this.sliceSerialize(token);
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* @this {CompileContext}
|
|
1005
|
+
* @type {FromMarkdownHandle}
|
|
1006
|
+
*/
|
|
1007
|
+
function exitLiteralAutolinkEmail(token) {
|
|
1008
|
+
this.config.exit.autolinkEmail.call(this, token);
|
|
1009
|
+
}
|
|
1010
|
+
/**
|
|
1011
|
+
* @this {CompileContext}
|
|
1012
|
+
* @type {FromMarkdownHandle}
|
|
1013
|
+
*/
|
|
1014
|
+
function exitLiteralAutolink(token) {
|
|
1015
|
+
this.exit(token);
|
|
1016
|
+
}
|
|
1017
|
+
/** @type {FromMarkdownTransform} */
|
|
1018
|
+
function transformGfmAutolinkLiterals(tree) {
|
|
1019
|
+
findAndReplace(tree, [[/(https?:\/\/|www(?=\.))([-.\w]+)([^ \t\r\n]*)/gi, findUrl], [/(?<=^|\s|\p{P}|\p{S})([-.\w+]+)@([-\w]+(?:\.[-\w]+)+)/gu, findEmail]], { ignore: ["link", "linkReference"] });
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* @type {ReplaceFunction}
|
|
1023
|
+
* @param {string} _
|
|
1024
|
+
* @param {string} protocol
|
|
1025
|
+
* @param {string} domain
|
|
1026
|
+
* @param {string} path
|
|
1027
|
+
* @param {RegExpMatchObject} match
|
|
1028
|
+
* @returns {Array<PhrasingContent> | Link | false}
|
|
1029
|
+
*/
|
|
1030
|
+
function findUrl(_, protocol, domain, path, match) {
|
|
1031
|
+
let prefix = "";
|
|
1032
|
+
if (!previous(match)) return false;
|
|
1033
|
+
if (/^w/i.test(protocol)) {
|
|
1034
|
+
domain = protocol + domain;
|
|
1035
|
+
protocol = "";
|
|
1036
|
+
prefix = "http://";
|
|
1037
|
+
}
|
|
1038
|
+
if (!isCorrectDomain(domain)) return false;
|
|
1039
|
+
const parts = splitUrl(domain + path);
|
|
1040
|
+
if (!parts[0]) return false;
|
|
1041
|
+
/** @type {Link} */
|
|
1042
|
+
const result = {
|
|
1043
|
+
type: "link",
|
|
1044
|
+
title: null,
|
|
1045
|
+
url: prefix + protocol + parts[0],
|
|
1046
|
+
children: [{
|
|
1047
|
+
type: "text",
|
|
1048
|
+
value: protocol + parts[0]
|
|
1049
|
+
}]
|
|
1050
|
+
};
|
|
1051
|
+
if (parts[1]) return [result, {
|
|
1052
|
+
type: "text",
|
|
1053
|
+
value: parts[1]
|
|
1054
|
+
}];
|
|
1055
|
+
return result;
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* @type {ReplaceFunction}
|
|
1059
|
+
* @param {string} _
|
|
1060
|
+
* @param {string} atext
|
|
1061
|
+
* @param {string} label
|
|
1062
|
+
* @param {RegExpMatchObject} match
|
|
1063
|
+
* @returns {Link | false}
|
|
1064
|
+
*/
|
|
1065
|
+
function findEmail(_, atext, label, match) {
|
|
1066
|
+
if (!previous(match, true) || /[-\d_]$/.test(label)) return false;
|
|
1067
|
+
return {
|
|
1068
|
+
type: "link",
|
|
1069
|
+
title: null,
|
|
1070
|
+
url: "mailto:" + atext + "@" + label,
|
|
1071
|
+
children: [{
|
|
1072
|
+
type: "text",
|
|
1073
|
+
value: atext + "@" + label
|
|
1074
|
+
}]
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* @param {string} domain
|
|
1079
|
+
* @returns {boolean}
|
|
1080
|
+
*/
|
|
1081
|
+
function isCorrectDomain(domain) {
|
|
1082
|
+
const parts = domain.split(".");
|
|
1083
|
+
if (parts.length < 2 || parts[parts.length - 1] && (/_/.test(parts[parts.length - 1]) || !/[a-zA-Z\d]/.test(parts[parts.length - 1])) || parts[parts.length - 2] && (/_/.test(parts[parts.length - 2]) || !/[a-zA-Z\d]/.test(parts[parts.length - 2]))) return false;
|
|
1084
|
+
return true;
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* @param {string} url
|
|
1088
|
+
* @returns {[string, string | undefined]}
|
|
1089
|
+
*/
|
|
1090
|
+
function splitUrl(url) {
|
|
1091
|
+
const trailExec = /[!"&'),.:;<>?\]}]+$/.exec(url);
|
|
1092
|
+
if (!trailExec) return [url, void 0];
|
|
1093
|
+
url = url.slice(0, trailExec.index);
|
|
1094
|
+
let trail = trailExec[0];
|
|
1095
|
+
let closingParenIndex = trail.indexOf(")");
|
|
1096
|
+
const openingParens = ccount(url, "(");
|
|
1097
|
+
let closingParens = ccount(url, ")");
|
|
1098
|
+
while (closingParenIndex !== -1 && openingParens > closingParens) {
|
|
1099
|
+
url += trail.slice(0, closingParenIndex + 1);
|
|
1100
|
+
trail = trail.slice(closingParenIndex + 1);
|
|
1101
|
+
closingParenIndex = trail.indexOf(")");
|
|
1102
|
+
closingParens++;
|
|
1103
|
+
}
|
|
1104
|
+
return [url, trail];
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* @param {RegExpMatchObject} match
|
|
1108
|
+
* @param {boolean | null | undefined} [email=false]
|
|
1109
|
+
* @returns {boolean}
|
|
1110
|
+
*/
|
|
1111
|
+
function previous(match, email) {
|
|
1112
|
+
const code = match.input.charCodeAt(match.index - 1);
|
|
1113
|
+
return (match.index === 0 || unicodeWhitespace(code) || unicodePunctuation(code)) && (!email || code !== 47);
|
|
1114
|
+
}
|
|
1115
|
+
//#endregion
|
|
1116
|
+
//#region ../../../node_modules/.pnpm/micromark-util-normalize-identifier@2.0.1/node_modules/micromark-util-normalize-identifier/index.js
|
|
1117
|
+
/**
|
|
1118
|
+
* Normalize an identifier (as found in references, definitions).
|
|
1119
|
+
*
|
|
1120
|
+
* Collapses markdown whitespace, trim, and then lower- and uppercase.
|
|
1121
|
+
*
|
|
1122
|
+
* Some characters are considered “uppercase”, such as U+03F4 (`ϴ`), but if their
|
|
1123
|
+
* lowercase counterpart (U+03B8 (`θ`)) is uppercased will result in a different
|
|
1124
|
+
* uppercase character (U+0398 (`Θ`)).
|
|
1125
|
+
* So, to get a canonical form, we perform both lower- and uppercase.
|
|
1126
|
+
*
|
|
1127
|
+
* Using uppercase last makes sure keys will never interact with default
|
|
1128
|
+
* prototypal values (such as `constructor`): nothing in the prototype of
|
|
1129
|
+
* `Object` is uppercase.
|
|
1130
|
+
*
|
|
1131
|
+
* @param {string} value
|
|
1132
|
+
* Identifier to normalize.
|
|
1133
|
+
* @returns {string}
|
|
1134
|
+
* Normalized identifier.
|
|
1135
|
+
*/
|
|
1136
|
+
function normalizeIdentifier(value) {
|
|
1137
|
+
return value.replace(/[\t\n\r ]+/g, " ").replace(/^ | $/g, "").toLowerCase().toUpperCase();
|
|
1138
|
+
}
|
|
1139
|
+
//#endregion
|
|
1140
|
+
//#region ../../../node_modules/.pnpm/mdast-util-gfm-footnote@2.1.0_supports-color@9.4.0/node_modules/mdast-util-gfm-footnote/lib/index.js
|
|
1141
|
+
/**
|
|
1142
|
+
* @import {
|
|
1143
|
+
* CompileContext,
|
|
1144
|
+
* Extension as FromMarkdownExtension,
|
|
1145
|
+
* Handle as FromMarkdownHandle
|
|
1146
|
+
* } from 'mdast-util-from-markdown'
|
|
1147
|
+
* @import {ToMarkdownOptions} from 'mdast-util-gfm-footnote'
|
|
1148
|
+
* @import {
|
|
1149
|
+
* Handle as ToMarkdownHandle,
|
|
1150
|
+
* Map,
|
|
1151
|
+
* Options as ToMarkdownExtension
|
|
1152
|
+
* } from 'mdast-util-to-markdown'
|
|
1153
|
+
* @import {FootnoteDefinition, FootnoteReference} from 'mdast'
|
|
1154
|
+
*/
|
|
1155
|
+
footnoteReference.peek = footnoteReferencePeek;
|
|
1156
|
+
/**
|
|
1157
|
+
* @this {CompileContext}
|
|
1158
|
+
* @type {FromMarkdownHandle}
|
|
1159
|
+
*/
|
|
1160
|
+
function enterFootnoteCallString() {
|
|
1161
|
+
this.buffer();
|
|
1162
|
+
}
|
|
1163
|
+
/**
|
|
1164
|
+
* @this {CompileContext}
|
|
1165
|
+
* @type {FromMarkdownHandle}
|
|
1166
|
+
*/
|
|
1167
|
+
function enterFootnoteCall(token) {
|
|
1168
|
+
this.enter({
|
|
1169
|
+
type: "footnoteReference",
|
|
1170
|
+
identifier: "",
|
|
1171
|
+
label: ""
|
|
1172
|
+
}, token);
|
|
1173
|
+
}
|
|
1174
|
+
/**
|
|
1175
|
+
* @this {CompileContext}
|
|
1176
|
+
* @type {FromMarkdownHandle}
|
|
1177
|
+
*/
|
|
1178
|
+
function enterFootnoteDefinitionLabelString() {
|
|
1179
|
+
this.buffer();
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1182
|
+
* @this {CompileContext}
|
|
1183
|
+
* @type {FromMarkdownHandle}
|
|
1184
|
+
*/
|
|
1185
|
+
function enterFootnoteDefinition(token) {
|
|
1186
|
+
this.enter({
|
|
1187
|
+
type: "footnoteDefinition",
|
|
1188
|
+
identifier: "",
|
|
1189
|
+
label: "",
|
|
1190
|
+
children: []
|
|
1191
|
+
}, token);
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
* @this {CompileContext}
|
|
1195
|
+
* @type {FromMarkdownHandle}
|
|
1196
|
+
*/
|
|
1197
|
+
function exitFootnoteCallString(token) {
|
|
1198
|
+
const label = this.resume();
|
|
1199
|
+
const node = this.stack[this.stack.length - 1];
|
|
1200
|
+
node.type;
|
|
1201
|
+
node.identifier = normalizeIdentifier(this.sliceSerialize(token)).toLowerCase();
|
|
1202
|
+
node.label = label;
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* @this {CompileContext}
|
|
1206
|
+
* @type {FromMarkdownHandle}
|
|
1207
|
+
*/
|
|
1208
|
+
function exitFootnoteCall(token) {
|
|
1209
|
+
this.exit(token);
|
|
1210
|
+
}
|
|
1211
|
+
/**
|
|
1212
|
+
* @this {CompileContext}
|
|
1213
|
+
* @type {FromMarkdownHandle}
|
|
1214
|
+
*/
|
|
1215
|
+
function exitFootnoteDefinitionLabelString(token) {
|
|
1216
|
+
const label = this.resume();
|
|
1217
|
+
const node = this.stack[this.stack.length - 1];
|
|
1218
|
+
node.type;
|
|
1219
|
+
node.identifier = normalizeIdentifier(this.sliceSerialize(token)).toLowerCase();
|
|
1220
|
+
node.label = label;
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* @this {CompileContext}
|
|
1224
|
+
* @type {FromMarkdownHandle}
|
|
1225
|
+
*/
|
|
1226
|
+
function exitFootnoteDefinition(token) {
|
|
1227
|
+
this.exit(token);
|
|
1228
|
+
}
|
|
1229
|
+
/** @type {ToMarkdownHandle} */
|
|
1230
|
+
function footnoteReferencePeek() {
|
|
1231
|
+
return "[";
|
|
1232
|
+
}
|
|
1233
|
+
/**
|
|
1234
|
+
* @type {ToMarkdownHandle}
|
|
1235
|
+
* @param {FootnoteReference} node
|
|
1236
|
+
*/
|
|
1237
|
+
function footnoteReference(node, _, state, info) {
|
|
1238
|
+
const tracker = state.createTracker(info);
|
|
1239
|
+
let value = tracker.move("[^");
|
|
1240
|
+
const exit = state.enter("footnoteReference");
|
|
1241
|
+
const subexit = state.enter("reference");
|
|
1242
|
+
value += tracker.move(state.safe(state.associationId(node), {
|
|
1243
|
+
after: "]",
|
|
1244
|
+
before: value
|
|
1245
|
+
}));
|
|
1246
|
+
subexit();
|
|
1247
|
+
exit();
|
|
1248
|
+
value += tracker.move("]");
|
|
1249
|
+
return value;
|
|
1250
|
+
}
|
|
1251
|
+
/**
|
|
1252
|
+
* Create an extension for `mdast-util-from-markdown` to enable GFM footnotes
|
|
1253
|
+
* in markdown.
|
|
1254
|
+
*
|
|
1255
|
+
* @returns {FromMarkdownExtension}
|
|
1256
|
+
* Extension for `mdast-util-from-markdown`.
|
|
1257
|
+
*/
|
|
1258
|
+
function gfmFootnoteFromMarkdown() {
|
|
1259
|
+
return {
|
|
1260
|
+
enter: {
|
|
1261
|
+
gfmFootnoteCallString: enterFootnoteCallString,
|
|
1262
|
+
gfmFootnoteCall: enterFootnoteCall,
|
|
1263
|
+
gfmFootnoteDefinitionLabelString: enterFootnoteDefinitionLabelString,
|
|
1264
|
+
gfmFootnoteDefinition: enterFootnoteDefinition
|
|
1265
|
+
},
|
|
1266
|
+
exit: {
|
|
1267
|
+
gfmFootnoteCallString: exitFootnoteCallString,
|
|
1268
|
+
gfmFootnoteCall: exitFootnoteCall,
|
|
1269
|
+
gfmFootnoteDefinitionLabelString: exitFootnoteDefinitionLabelString,
|
|
1270
|
+
gfmFootnoteDefinition: exitFootnoteDefinition
|
|
1271
|
+
}
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
//#endregion
|
|
1275
|
+
//#region ../../../node_modules/.pnpm/mdast-util-gfm-strikethrough@2.0.0_supports-color@9.4.0/node_modules/mdast-util-gfm-strikethrough/lib/index.js
|
|
1276
|
+
handleDelete.peek = peekDelete;
|
|
1277
|
+
/**
|
|
1278
|
+
* Create an extension for `mdast-util-from-markdown` to enable GFM
|
|
1279
|
+
* strikethrough in markdown.
|
|
1280
|
+
*
|
|
1281
|
+
* @returns {FromMarkdownExtension}
|
|
1282
|
+
* Extension for `mdast-util-from-markdown` to enable GFM strikethrough.
|
|
1283
|
+
*/
|
|
1284
|
+
function gfmStrikethroughFromMarkdown() {
|
|
1285
|
+
return {
|
|
1286
|
+
canContainEols: ["delete"],
|
|
1287
|
+
enter: { strikethrough: enterStrikethrough },
|
|
1288
|
+
exit: { strikethrough: exitStrikethrough }
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
/**
|
|
1292
|
+
* @this {CompileContext}
|
|
1293
|
+
* @type {FromMarkdownHandle}
|
|
1294
|
+
*/
|
|
1295
|
+
function enterStrikethrough(token) {
|
|
1296
|
+
this.enter({
|
|
1297
|
+
type: "delete",
|
|
1298
|
+
children: []
|
|
1299
|
+
}, token);
|
|
1300
|
+
}
|
|
1301
|
+
/**
|
|
1302
|
+
* @this {CompileContext}
|
|
1303
|
+
* @type {FromMarkdownHandle}
|
|
1304
|
+
*/
|
|
1305
|
+
function exitStrikethrough(token) {
|
|
1306
|
+
this.exit(token);
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* @type {ToMarkdownHandle}
|
|
1310
|
+
* @param {Delete} node
|
|
1311
|
+
*/
|
|
1312
|
+
function handleDelete(node, _, state, info) {
|
|
1313
|
+
const tracker = state.createTracker(info);
|
|
1314
|
+
const exit = state.enter("strikethrough");
|
|
1315
|
+
let value = tracker.move("~~");
|
|
1316
|
+
value += state.containerPhrasing(node, {
|
|
1317
|
+
...tracker.current(),
|
|
1318
|
+
before: value,
|
|
1319
|
+
after: "~"
|
|
1320
|
+
});
|
|
1321
|
+
value += tracker.move("~~");
|
|
1322
|
+
exit();
|
|
1323
|
+
return value;
|
|
1324
|
+
}
|
|
1325
|
+
/** @type {ToMarkdownHandle} */
|
|
1326
|
+
function peekDelete() {
|
|
1327
|
+
return "~";
|
|
1328
|
+
}
|
|
1329
|
+
//#endregion
|
|
1330
|
+
//#region ../../../node_modules/.pnpm/micromark-util-classify-character@2.0.1/node_modules/micromark-util-classify-character/index.js
|
|
1331
|
+
/**
|
|
1332
|
+
* @import {Code} from 'micromark-util-types'
|
|
1333
|
+
*/
|
|
1334
|
+
/**
|
|
1335
|
+
* Classify whether a code represents whitespace, punctuation, or something
|
|
1336
|
+
* else.
|
|
1337
|
+
*
|
|
1338
|
+
* Used for attention (emphasis, strong), whose sequences can open or close
|
|
1339
|
+
* based on the class of surrounding characters.
|
|
1340
|
+
*
|
|
1341
|
+
* > 👉 **Note**: eof (`null`) is seen as whitespace.
|
|
1342
|
+
*
|
|
1343
|
+
* @param {Code} code
|
|
1344
|
+
* Code.
|
|
1345
|
+
* @returns {typeof constants.characterGroupWhitespace | typeof constants.characterGroupPunctuation | undefined}
|
|
1346
|
+
* Group.
|
|
1347
|
+
*/
|
|
1348
|
+
function classifyCharacter(code) {
|
|
1349
|
+
if (code === null || markdownLineEndingOrSpace(code) || unicodeWhitespace(code)) return 1;
|
|
1350
|
+
if (unicodePunctuation(code)) return 2;
|
|
1351
|
+
}
|
|
1352
|
+
//#endregion
|
|
1353
|
+
//#region ../../../node_modules/.pnpm/mdast-util-gfm-table@2.0.0_supports-color@9.4.0/node_modules/mdast-util-gfm-table/lib/index.js
|
|
1354
|
+
/**
|
|
1355
|
+
* @typedef {import('mdast').InlineCode} InlineCode
|
|
1356
|
+
* @typedef {import('mdast').Table} Table
|
|
1357
|
+
* @typedef {import('mdast').TableCell} TableCell
|
|
1358
|
+
* @typedef {import('mdast').TableRow} TableRow
|
|
1359
|
+
*
|
|
1360
|
+
* @typedef {import('markdown-table').Options} MarkdownTableOptions
|
|
1361
|
+
*
|
|
1362
|
+
* @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext
|
|
1363
|
+
* @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension
|
|
1364
|
+
* @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle
|
|
1365
|
+
*
|
|
1366
|
+
* @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension
|
|
1367
|
+
* @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle
|
|
1368
|
+
* @typedef {import('mdast-util-to-markdown').State} State
|
|
1369
|
+
* @typedef {import('mdast-util-to-markdown').Info} Info
|
|
1370
|
+
*/
|
|
1371
|
+
/**
|
|
1372
|
+
* @typedef Options
|
|
1373
|
+
* Configuration.
|
|
1374
|
+
* @property {boolean | null | undefined} [tableCellPadding=true]
|
|
1375
|
+
* Whether to add a space of padding between delimiters and cells (default:
|
|
1376
|
+
* `true`).
|
|
1377
|
+
* @property {boolean | null | undefined} [tablePipeAlign=true]
|
|
1378
|
+
* Whether to align the delimiters (default: `true`).
|
|
1379
|
+
* @property {MarkdownTableOptions['stringLength'] | null | undefined} [stringLength]
|
|
1380
|
+
* Function to detect the length of table cell content, used when aligning
|
|
1381
|
+
* the delimiters between cells (optional).
|
|
1382
|
+
*/
|
|
1383
|
+
/**
|
|
1384
|
+
* Create an extension for `mdast-util-from-markdown` to enable GFM tables in
|
|
1385
|
+
* markdown.
|
|
1386
|
+
*
|
|
1387
|
+
* @returns {FromMarkdownExtension}
|
|
1388
|
+
* Extension for `mdast-util-from-markdown` to enable GFM tables.
|
|
1389
|
+
*/
|
|
1390
|
+
function gfmTableFromMarkdown() {
|
|
1391
|
+
return {
|
|
1392
|
+
enter: {
|
|
1393
|
+
table: enterTable,
|
|
1394
|
+
tableData: enterCell,
|
|
1395
|
+
tableHeader: enterCell,
|
|
1396
|
+
tableRow: enterRow
|
|
1397
|
+
},
|
|
1398
|
+
exit: {
|
|
1399
|
+
codeText: exitCodeText,
|
|
1400
|
+
table: exitTable,
|
|
1401
|
+
tableData: exit,
|
|
1402
|
+
tableHeader: exit,
|
|
1403
|
+
tableRow: exit
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
/**
|
|
1408
|
+
* @this {CompileContext}
|
|
1409
|
+
* @type {FromMarkdownHandle}
|
|
1410
|
+
*/
|
|
1411
|
+
function enterTable(token) {
|
|
1412
|
+
const align = token._align;
|
|
1413
|
+
this.enter({
|
|
1414
|
+
type: "table",
|
|
1415
|
+
align: align.map(function(d) {
|
|
1416
|
+
return d === "none" ? null : d;
|
|
1417
|
+
}),
|
|
1418
|
+
children: []
|
|
1419
|
+
}, token);
|
|
1420
|
+
this.data.inTable = true;
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
1423
|
+
* @this {CompileContext}
|
|
1424
|
+
* @type {FromMarkdownHandle}
|
|
1425
|
+
*/
|
|
1426
|
+
function exitTable(token) {
|
|
1427
|
+
this.exit(token);
|
|
1428
|
+
this.data.inTable = void 0;
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* @this {CompileContext}
|
|
1432
|
+
* @type {FromMarkdownHandle}
|
|
1433
|
+
*/
|
|
1434
|
+
function enterRow(token) {
|
|
1435
|
+
this.enter({
|
|
1436
|
+
type: "tableRow",
|
|
1437
|
+
children: []
|
|
1438
|
+
}, token);
|
|
1439
|
+
}
|
|
1440
|
+
/**
|
|
1441
|
+
* @this {CompileContext}
|
|
1442
|
+
* @type {FromMarkdownHandle}
|
|
1443
|
+
*/
|
|
1444
|
+
function exit(token) {
|
|
1445
|
+
this.exit(token);
|
|
1446
|
+
}
|
|
1447
|
+
/**
|
|
1448
|
+
* @this {CompileContext}
|
|
1449
|
+
* @type {FromMarkdownHandle}
|
|
1450
|
+
*/
|
|
1451
|
+
function enterCell(token) {
|
|
1452
|
+
this.enter({
|
|
1453
|
+
type: "tableCell",
|
|
1454
|
+
children: []
|
|
1455
|
+
}, token);
|
|
1456
|
+
}
|
|
1457
|
+
/**
|
|
1458
|
+
* @this {CompileContext}
|
|
1459
|
+
* @type {FromMarkdownHandle}
|
|
1460
|
+
*/
|
|
1461
|
+
function exitCodeText(token) {
|
|
1462
|
+
let value = this.resume();
|
|
1463
|
+
if (this.data.inTable) value = value.replace(/\\([\\|])/g, replace);
|
|
1464
|
+
const node = this.stack[this.stack.length - 1];
|
|
1465
|
+
node.type;
|
|
1466
|
+
node.value = value;
|
|
1467
|
+
this.exit(token);
|
|
1468
|
+
}
|
|
1469
|
+
/**
|
|
1470
|
+
* @param {string} $0
|
|
1471
|
+
* @param {string} $1
|
|
1472
|
+
* @returns {string}
|
|
1473
|
+
*/
|
|
1474
|
+
function replace($0, $1) {
|
|
1475
|
+
return $1 === "|" ? $1 : $0;
|
|
1476
|
+
}
|
|
1477
|
+
//#endregion
|
|
1478
|
+
//#region ../../../node_modules/.pnpm/mdast-util-gfm-task-list-item@2.0.0_supports-color@9.4.0/node_modules/mdast-util-gfm-task-list-item/lib/index.js
|
|
1479
|
+
/**
|
|
1480
|
+
* @typedef {import('mdast').ListItem} ListItem
|
|
1481
|
+
* @typedef {import('mdast').Paragraph} Paragraph
|
|
1482
|
+
* @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext
|
|
1483
|
+
* @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension
|
|
1484
|
+
* @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle
|
|
1485
|
+
* @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension
|
|
1486
|
+
* @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle
|
|
1487
|
+
*/
|
|
1488
|
+
/**
|
|
1489
|
+
* Create an extension for `mdast-util-from-markdown` to enable GFM task
|
|
1490
|
+
* list items in markdown.
|
|
1491
|
+
*
|
|
1492
|
+
* @returns {FromMarkdownExtension}
|
|
1493
|
+
* Extension for `mdast-util-from-markdown` to enable GFM task list items.
|
|
1494
|
+
*/
|
|
1495
|
+
function gfmTaskListItemFromMarkdown() {
|
|
1496
|
+
return { exit: {
|
|
1497
|
+
taskListCheckValueChecked: exitCheck,
|
|
1498
|
+
taskListCheckValueUnchecked: exitCheck,
|
|
1499
|
+
paragraph: exitParagraphWithTaskListItem
|
|
1500
|
+
} };
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* @this {CompileContext}
|
|
1504
|
+
* @type {FromMarkdownHandle}
|
|
1505
|
+
*/
|
|
1506
|
+
function exitCheck(token) {
|
|
1507
|
+
const node = this.stack[this.stack.length - 2];
|
|
1508
|
+
node.type;
|
|
1509
|
+
node.checked = token.type === "taskListCheckValueChecked";
|
|
1510
|
+
}
|
|
1511
|
+
/**
|
|
1512
|
+
* @this {CompileContext}
|
|
1513
|
+
* @type {FromMarkdownHandle}
|
|
1514
|
+
*/
|
|
1515
|
+
function exitParagraphWithTaskListItem(token) {
|
|
1516
|
+
const parent = this.stack[this.stack.length - 2];
|
|
1517
|
+
if (parent && parent.type === "listItem" && typeof parent.checked === "boolean") {
|
|
1518
|
+
const node = this.stack[this.stack.length - 1];
|
|
1519
|
+
node.type;
|
|
1520
|
+
const head = node.children[0];
|
|
1521
|
+
if (head && head.type === "text") {
|
|
1522
|
+
const siblings = parent.children;
|
|
1523
|
+
let index = -1;
|
|
1524
|
+
/** @type {Paragraph | undefined} */
|
|
1525
|
+
let firstParaghraph;
|
|
1526
|
+
while (++index < siblings.length) {
|
|
1527
|
+
const sibling = siblings[index];
|
|
1528
|
+
if (sibling.type === "paragraph") {
|
|
1529
|
+
firstParaghraph = sibling;
|
|
1530
|
+
break;
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
if (firstParaghraph === node) {
|
|
1534
|
+
head.value = head.value.slice(1);
|
|
1535
|
+
if (head.value.length === 0) node.children.shift();
|
|
1536
|
+
else if (node.position && head.position && typeof head.position.start.offset === "number") {
|
|
1537
|
+
head.position.start.column++;
|
|
1538
|
+
head.position.start.offset++;
|
|
1539
|
+
node.position.start = Object.assign({}, head.position.start);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
this.exit(token);
|
|
1545
|
+
}
|
|
1546
|
+
//#endregion
|
|
1547
|
+
//#region ../../../node_modules/.pnpm/mdast-util-gfm@3.1.0_supports-color@9.4.0/node_modules/mdast-util-gfm/lib/index.js
|
|
1548
|
+
/**
|
|
1549
|
+
* @import {Extension as FromMarkdownExtension} from 'mdast-util-from-markdown'
|
|
1550
|
+
* @import {Options} from 'mdast-util-gfm'
|
|
1551
|
+
* @import {Options as ToMarkdownExtension} from 'mdast-util-to-markdown'
|
|
1552
|
+
*/
|
|
1553
|
+
/**
|
|
1554
|
+
* Create an extension for `mdast-util-from-markdown` to enable GFM (autolink
|
|
1555
|
+
* literals, footnotes, strikethrough, tables, tasklists).
|
|
1556
|
+
*
|
|
1557
|
+
* @returns {Array<FromMarkdownExtension>}
|
|
1558
|
+
* Extension for `mdast-util-from-markdown` to enable GFM (autolink literals,
|
|
1559
|
+
* footnotes, strikethrough, tables, tasklists).
|
|
1560
|
+
*/
|
|
1561
|
+
function gfmFromMarkdown() {
|
|
1562
|
+
return [
|
|
1563
|
+
gfmAutolinkLiteralFromMarkdown(),
|
|
1564
|
+
gfmFootnoteFromMarkdown(),
|
|
1565
|
+
gfmStrikethroughFromMarkdown(),
|
|
1566
|
+
gfmTableFromMarkdown(),
|
|
1567
|
+
gfmTaskListItemFromMarkdown()
|
|
1568
|
+
];
|
|
1569
|
+
}
|
|
1570
|
+
//#endregion
|
|
1571
|
+
//#region ../../../node_modules/.pnpm/micromark-util-chunked@2.0.1/node_modules/micromark-util-chunked/index.js
|
|
1572
|
+
/**
|
|
1573
|
+
* Like `Array#splice`, but smarter for giant arrays.
|
|
1574
|
+
*
|
|
1575
|
+
* `Array#splice` takes all items to be inserted as individual argument which
|
|
1576
|
+
* causes a stack overflow in V8 when trying to insert 100k items for instance.
|
|
1577
|
+
*
|
|
1578
|
+
* Otherwise, this does not return the removed items, and takes `items` as an
|
|
1579
|
+
* array instead of rest parameters.
|
|
1580
|
+
*
|
|
1581
|
+
* @template {unknown} T
|
|
1582
|
+
* Item type.
|
|
1583
|
+
* @param {Array<T>} list
|
|
1584
|
+
* List to operate on.
|
|
1585
|
+
* @param {number} start
|
|
1586
|
+
* Index to remove/insert at (can be negative).
|
|
1587
|
+
* @param {number} remove
|
|
1588
|
+
* Number of items to remove.
|
|
1589
|
+
* @param {Array<T>} items
|
|
1590
|
+
* Items to inject into `list`.
|
|
1591
|
+
* @returns {undefined}
|
|
1592
|
+
* Nothing.
|
|
1593
|
+
*/
|
|
1594
|
+
function splice(list, start, remove, items) {
|
|
1595
|
+
const end = list.length;
|
|
1596
|
+
let chunkStart = 0;
|
|
1597
|
+
/** @type {Array<unknown>} */
|
|
1598
|
+
let parameters;
|
|
1599
|
+
if (start < 0) start = -start > end ? 0 : end + start;
|
|
1600
|
+
else start = start > end ? end : start;
|
|
1601
|
+
remove = remove > 0 ? remove : 0;
|
|
1602
|
+
if (items.length < 1e4) {
|
|
1603
|
+
parameters = Array.from(items);
|
|
1604
|
+
parameters.unshift(start, remove);
|
|
1605
|
+
list.splice(...parameters);
|
|
1606
|
+
} else {
|
|
1607
|
+
if (remove) list.splice(start, remove);
|
|
1608
|
+
while (chunkStart < items.length) {
|
|
1609
|
+
parameters = items.slice(chunkStart, chunkStart + 1e4);
|
|
1610
|
+
parameters.unshift(start, 0);
|
|
1611
|
+
list.splice(...parameters);
|
|
1612
|
+
chunkStart += 1e4;
|
|
1613
|
+
start += 1e4;
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
//#endregion
|
|
1618
|
+
//#region ../../../node_modules/.pnpm/micromark-util-combine-extensions@2.0.1/node_modules/micromark-util-combine-extensions/index.js
|
|
1619
|
+
/**
|
|
1620
|
+
* @import {
|
|
1621
|
+
* Extension,
|
|
1622
|
+
* Handles,
|
|
1623
|
+
* HtmlExtension,
|
|
1624
|
+
* NormalizedExtension
|
|
1625
|
+
* } from 'micromark-util-types'
|
|
1626
|
+
*/
|
|
1627
|
+
const hasOwnProperty = {}.hasOwnProperty;
|
|
1628
|
+
/**
|
|
1629
|
+
* Combine multiple syntax extensions into one.
|
|
1630
|
+
*
|
|
1631
|
+
* @param {ReadonlyArray<Extension>} extensions
|
|
1632
|
+
* List of syntax extensions.
|
|
1633
|
+
* @returns {NormalizedExtension}
|
|
1634
|
+
* A single combined extension.
|
|
1635
|
+
*/
|
|
1636
|
+
function combineExtensions(extensions) {
|
|
1637
|
+
/** @type {NormalizedExtension} */
|
|
1638
|
+
const all = {};
|
|
1639
|
+
let index = -1;
|
|
1640
|
+
while (++index < extensions.length) syntaxExtension(all, extensions[index]);
|
|
1641
|
+
return all;
|
|
1642
|
+
}
|
|
1643
|
+
/**
|
|
1644
|
+
* Merge `extension` into `all`.
|
|
1645
|
+
*
|
|
1646
|
+
* @param {NormalizedExtension} all
|
|
1647
|
+
* Extension to merge into.
|
|
1648
|
+
* @param {Extension} extension
|
|
1649
|
+
* Extension to merge.
|
|
1650
|
+
* @returns {undefined}
|
|
1651
|
+
* Nothing.
|
|
1652
|
+
*/
|
|
1653
|
+
function syntaxExtension(all, extension) {
|
|
1654
|
+
/** @type {keyof Extension} */
|
|
1655
|
+
let hook;
|
|
1656
|
+
for (hook in extension) {
|
|
1657
|
+
/** @type {Record<string, unknown>} */
|
|
1658
|
+
const left = (hasOwnProperty.call(all, hook) ? all[hook] : void 0) || (all[hook] = {});
|
|
1659
|
+
/** @type {Record<string, unknown> | undefined} */
|
|
1660
|
+
const right = extension[hook];
|
|
1661
|
+
/** @type {string} */
|
|
1662
|
+
let code;
|
|
1663
|
+
if (right) for (code in right) {
|
|
1664
|
+
if (!hasOwnProperty.call(left, code)) left[code] = [];
|
|
1665
|
+
const value = right[code];
|
|
1666
|
+
constructs(left[code], Array.isArray(value) ? value : value ? [value] : []);
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
/**
|
|
1671
|
+
* Merge `list` into `existing` (both lists of constructs).
|
|
1672
|
+
* Mutates `existing`.
|
|
1673
|
+
*
|
|
1674
|
+
* @param {Array<unknown>} existing
|
|
1675
|
+
* List of constructs to merge into.
|
|
1676
|
+
* @param {Array<unknown>} list
|
|
1677
|
+
* List of constructs to merge.
|
|
1678
|
+
* @returns {undefined}
|
|
1679
|
+
* Nothing.
|
|
1680
|
+
*/
|
|
1681
|
+
function constructs(existing, list) {
|
|
1682
|
+
let index = -1;
|
|
1683
|
+
/** @type {Array<unknown>} */
|
|
1684
|
+
const before = [];
|
|
1685
|
+
while (++index < list.length) (list[index].add === "after" ? existing : before).push(list[index]);
|
|
1686
|
+
splice(existing, 0, 0, before);
|
|
1687
|
+
}
|
|
1688
|
+
//#endregion
|
|
1689
|
+
//#region ../../../node_modules/.pnpm/micromark-extension-gfm-autolink-literal@2.1.0/node_modules/micromark-extension-gfm-autolink-literal/lib/syntax.js
|
|
1690
|
+
/**
|
|
1691
|
+
* @import {Code, ConstructRecord, Event, Extension, Previous, State, TokenizeContext, Tokenizer} from 'micromark-util-types'
|
|
1692
|
+
*/
|
|
1693
|
+
const wwwPrefix = {
|
|
1694
|
+
tokenize: tokenizeWwwPrefix,
|
|
1695
|
+
partial: true
|
|
1696
|
+
};
|
|
1697
|
+
const domain = {
|
|
1698
|
+
tokenize: tokenizeDomain,
|
|
1699
|
+
partial: true
|
|
1700
|
+
};
|
|
1701
|
+
const path = {
|
|
1702
|
+
tokenize: tokenizePath,
|
|
1703
|
+
partial: true
|
|
1704
|
+
};
|
|
1705
|
+
const trail = {
|
|
1706
|
+
tokenize: tokenizeTrail,
|
|
1707
|
+
partial: true
|
|
1708
|
+
};
|
|
1709
|
+
const emailDomainDotTrail = {
|
|
1710
|
+
tokenize: tokenizeEmailDomainDotTrail,
|
|
1711
|
+
partial: true
|
|
1712
|
+
};
|
|
1713
|
+
const wwwAutolink = {
|
|
1714
|
+
name: "wwwAutolink",
|
|
1715
|
+
tokenize: tokenizeWwwAutolink,
|
|
1716
|
+
previous: previousWww
|
|
1717
|
+
};
|
|
1718
|
+
const protocolAutolink = {
|
|
1719
|
+
name: "protocolAutolink",
|
|
1720
|
+
tokenize: tokenizeProtocolAutolink,
|
|
1721
|
+
previous: previousProtocol
|
|
1722
|
+
};
|
|
1723
|
+
const emailAutolink = {
|
|
1724
|
+
name: "emailAutolink",
|
|
1725
|
+
tokenize: tokenizeEmailAutolink,
|
|
1726
|
+
previous: previousEmail
|
|
1727
|
+
};
|
|
1728
|
+
/** @type {ConstructRecord} */
|
|
1729
|
+
const text = {};
|
|
1730
|
+
/**
|
|
1731
|
+
* Create an extension for `micromark` to support GitHub autolink literal
|
|
1732
|
+
* syntax.
|
|
1733
|
+
*
|
|
1734
|
+
* @returns {Extension}
|
|
1735
|
+
* Extension for `micromark` that can be passed in `extensions` to enable GFM
|
|
1736
|
+
* autolink literal syntax.
|
|
1737
|
+
*/
|
|
1738
|
+
function gfmAutolinkLiteral() {
|
|
1739
|
+
return { text };
|
|
1740
|
+
}
|
|
1741
|
+
/** @type {Code} */
|
|
1742
|
+
let code = 48;
|
|
1743
|
+
while (code < 123) {
|
|
1744
|
+
text[code] = emailAutolink;
|
|
1745
|
+
code++;
|
|
1746
|
+
if (code === 58) code = 65;
|
|
1747
|
+
else if (code === 91) code = 97;
|
|
1748
|
+
}
|
|
1749
|
+
text[43] = emailAutolink;
|
|
1750
|
+
text[45] = emailAutolink;
|
|
1751
|
+
text[46] = emailAutolink;
|
|
1752
|
+
text[95] = emailAutolink;
|
|
1753
|
+
text[72] = [emailAutolink, protocolAutolink];
|
|
1754
|
+
text[104] = [emailAutolink, protocolAutolink];
|
|
1755
|
+
text[87] = [emailAutolink, wwwAutolink];
|
|
1756
|
+
text[119] = [emailAutolink, wwwAutolink];
|
|
1757
|
+
/**
|
|
1758
|
+
* Email autolink literal.
|
|
1759
|
+
*
|
|
1760
|
+
* ```markdown
|
|
1761
|
+
* > | a contact@example.org b
|
|
1762
|
+
* ^^^^^^^^^^^^^^^^^^^
|
|
1763
|
+
* ```
|
|
1764
|
+
*
|
|
1765
|
+
* @this {TokenizeContext}
|
|
1766
|
+
* @type {Tokenizer}
|
|
1767
|
+
*/
|
|
1768
|
+
function tokenizeEmailAutolink(effects, ok, nok) {
|
|
1769
|
+
const self = this;
|
|
1770
|
+
/** @type {boolean | undefined} */
|
|
1771
|
+
let dot;
|
|
1772
|
+
/** @type {boolean} */
|
|
1773
|
+
let data;
|
|
1774
|
+
return start;
|
|
1775
|
+
/**
|
|
1776
|
+
* Start of email autolink literal.
|
|
1777
|
+
*
|
|
1778
|
+
* ```markdown
|
|
1779
|
+
* > | a contact@example.org b
|
|
1780
|
+
* ^
|
|
1781
|
+
* ```
|
|
1782
|
+
*
|
|
1783
|
+
* @type {State}
|
|
1784
|
+
*/
|
|
1785
|
+
function start(code) {
|
|
1786
|
+
if (!gfmAtext(code) || !previousEmail.call(self, self.previous) || previousUnbalanced(self.events)) return nok(code);
|
|
1787
|
+
effects.enter("literalAutolink");
|
|
1788
|
+
effects.enter("literalAutolinkEmail");
|
|
1789
|
+
return atext(code);
|
|
1790
|
+
}
|
|
1791
|
+
/**
|
|
1792
|
+
* In email atext.
|
|
1793
|
+
*
|
|
1794
|
+
* ```markdown
|
|
1795
|
+
* > | a contact@example.org b
|
|
1796
|
+
* ^
|
|
1797
|
+
* ```
|
|
1798
|
+
*
|
|
1799
|
+
* @type {State}
|
|
1800
|
+
*/
|
|
1801
|
+
function atext(code) {
|
|
1802
|
+
if (gfmAtext(code)) {
|
|
1803
|
+
effects.consume(code);
|
|
1804
|
+
return atext;
|
|
1805
|
+
}
|
|
1806
|
+
if (code === 64) {
|
|
1807
|
+
effects.consume(code);
|
|
1808
|
+
return emailDomain;
|
|
1809
|
+
}
|
|
1810
|
+
return nok(code);
|
|
1811
|
+
}
|
|
1812
|
+
/**
|
|
1813
|
+
* In email domain.
|
|
1814
|
+
*
|
|
1815
|
+
* The reference code is a bit overly complex as it handles the `@`, of which
|
|
1816
|
+
* there may be just one.
|
|
1817
|
+
* Source: <https://github.com/github/cmark-gfm/blob/ef1cfcb/extensions/autolink.c#L318>
|
|
1818
|
+
*
|
|
1819
|
+
* ```markdown
|
|
1820
|
+
* > | a contact@example.org b
|
|
1821
|
+
* ^
|
|
1822
|
+
* ```
|
|
1823
|
+
*
|
|
1824
|
+
* @type {State}
|
|
1825
|
+
*/
|
|
1826
|
+
function emailDomain(code) {
|
|
1827
|
+
if (code === 46) return effects.check(emailDomainDotTrail, emailDomainAfter, emailDomainDot)(code);
|
|
1828
|
+
if (code === 45 || code === 95 || asciiAlphanumeric(code)) {
|
|
1829
|
+
data = true;
|
|
1830
|
+
effects.consume(code);
|
|
1831
|
+
return emailDomain;
|
|
1832
|
+
}
|
|
1833
|
+
return emailDomainAfter(code);
|
|
1834
|
+
}
|
|
1835
|
+
/**
|
|
1836
|
+
* In email domain, on dot that is not a trail.
|
|
1837
|
+
*
|
|
1838
|
+
* ```markdown
|
|
1839
|
+
* > | a contact@example.org b
|
|
1840
|
+
* ^
|
|
1841
|
+
* ```
|
|
1842
|
+
*
|
|
1843
|
+
* @type {State}
|
|
1844
|
+
*/
|
|
1845
|
+
function emailDomainDot(code) {
|
|
1846
|
+
effects.consume(code);
|
|
1847
|
+
dot = true;
|
|
1848
|
+
return emailDomain;
|
|
1849
|
+
}
|
|
1850
|
+
/**
|
|
1851
|
+
* After email domain.
|
|
1852
|
+
*
|
|
1853
|
+
* ```markdown
|
|
1854
|
+
* > | a contact@example.org b
|
|
1855
|
+
* ^
|
|
1856
|
+
* ```
|
|
1857
|
+
*
|
|
1858
|
+
* @type {State}
|
|
1859
|
+
*/
|
|
1860
|
+
function emailDomainAfter(code) {
|
|
1861
|
+
if (data && dot && asciiAlpha(self.previous)) {
|
|
1862
|
+
effects.exit("literalAutolinkEmail");
|
|
1863
|
+
effects.exit("literalAutolink");
|
|
1864
|
+
return ok(code);
|
|
1865
|
+
}
|
|
1866
|
+
return nok(code);
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
/**
|
|
1870
|
+
* `www` autolink literal.
|
|
1871
|
+
*
|
|
1872
|
+
* ```markdown
|
|
1873
|
+
* > | a www.example.org b
|
|
1874
|
+
* ^^^^^^^^^^^^^^^
|
|
1875
|
+
* ```
|
|
1876
|
+
*
|
|
1877
|
+
* @this {TokenizeContext}
|
|
1878
|
+
* @type {Tokenizer}
|
|
1879
|
+
*/
|
|
1880
|
+
function tokenizeWwwAutolink(effects, ok, nok) {
|
|
1881
|
+
const self = this;
|
|
1882
|
+
return wwwStart;
|
|
1883
|
+
/**
|
|
1884
|
+
* Start of www autolink literal.
|
|
1885
|
+
*
|
|
1886
|
+
* ```markdown
|
|
1887
|
+
* > | www.example.com/a?b#c
|
|
1888
|
+
* ^
|
|
1889
|
+
* ```
|
|
1890
|
+
*
|
|
1891
|
+
* @type {State}
|
|
1892
|
+
*/
|
|
1893
|
+
function wwwStart(code) {
|
|
1894
|
+
if (code !== 87 && code !== 119 || !previousWww.call(self, self.previous) || previousUnbalanced(self.events)) return nok(code);
|
|
1895
|
+
effects.enter("literalAutolink");
|
|
1896
|
+
effects.enter("literalAutolinkWww");
|
|
1897
|
+
return effects.check(wwwPrefix, effects.attempt(domain, effects.attempt(path, wwwAfter), nok), nok)(code);
|
|
1898
|
+
}
|
|
1899
|
+
/**
|
|
1900
|
+
* After a www autolink literal.
|
|
1901
|
+
*
|
|
1902
|
+
* ```markdown
|
|
1903
|
+
* > | www.example.com/a?b#c
|
|
1904
|
+
* ^
|
|
1905
|
+
* ```
|
|
1906
|
+
*
|
|
1907
|
+
* @type {State}
|
|
1908
|
+
*/
|
|
1909
|
+
function wwwAfter(code) {
|
|
1910
|
+
effects.exit("literalAutolinkWww");
|
|
1911
|
+
effects.exit("literalAutolink");
|
|
1912
|
+
return ok(code);
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
/**
|
|
1916
|
+
* Protocol autolink literal.
|
|
1917
|
+
*
|
|
1918
|
+
* ```markdown
|
|
1919
|
+
* > | a https://example.org b
|
|
1920
|
+
* ^^^^^^^^^^^^^^^^^^^
|
|
1921
|
+
* ```
|
|
1922
|
+
*
|
|
1923
|
+
* @this {TokenizeContext}
|
|
1924
|
+
* @type {Tokenizer}
|
|
1925
|
+
*/
|
|
1926
|
+
function tokenizeProtocolAutolink(effects, ok, nok) {
|
|
1927
|
+
const self = this;
|
|
1928
|
+
let buffer = "";
|
|
1929
|
+
let seen = false;
|
|
1930
|
+
return protocolStart;
|
|
1931
|
+
/**
|
|
1932
|
+
* Start of protocol autolink literal.
|
|
1933
|
+
*
|
|
1934
|
+
* ```markdown
|
|
1935
|
+
* > | https://example.com/a?b#c
|
|
1936
|
+
* ^
|
|
1937
|
+
* ```
|
|
1938
|
+
*
|
|
1939
|
+
* @type {State}
|
|
1940
|
+
*/
|
|
1941
|
+
function protocolStart(code) {
|
|
1942
|
+
if ((code === 72 || code === 104) && previousProtocol.call(self, self.previous) && !previousUnbalanced(self.events)) {
|
|
1943
|
+
effects.enter("literalAutolink");
|
|
1944
|
+
effects.enter("literalAutolinkHttp");
|
|
1945
|
+
buffer += String.fromCodePoint(code);
|
|
1946
|
+
effects.consume(code);
|
|
1947
|
+
return protocolPrefixInside;
|
|
1948
|
+
}
|
|
1949
|
+
return nok(code);
|
|
1950
|
+
}
|
|
1951
|
+
/**
|
|
1952
|
+
* In protocol.
|
|
1953
|
+
*
|
|
1954
|
+
* ```markdown
|
|
1955
|
+
* > | https://example.com/a?b#c
|
|
1956
|
+
* ^^^^^
|
|
1957
|
+
* ```
|
|
1958
|
+
*
|
|
1959
|
+
* @type {State}
|
|
1960
|
+
*/
|
|
1961
|
+
function protocolPrefixInside(code) {
|
|
1962
|
+
if (asciiAlpha(code) && buffer.length < 5) {
|
|
1963
|
+
buffer += String.fromCodePoint(code);
|
|
1964
|
+
effects.consume(code);
|
|
1965
|
+
return protocolPrefixInside;
|
|
1966
|
+
}
|
|
1967
|
+
if (code === 58) {
|
|
1968
|
+
const protocol = buffer.toLowerCase();
|
|
1969
|
+
if (protocol === "http" || protocol === "https") {
|
|
1970
|
+
effects.consume(code);
|
|
1971
|
+
return protocolSlashesInside;
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
return nok(code);
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1977
|
+
* In slashes.
|
|
1978
|
+
*
|
|
1979
|
+
* ```markdown
|
|
1980
|
+
* > | https://example.com/a?b#c
|
|
1981
|
+
* ^^
|
|
1982
|
+
* ```
|
|
1983
|
+
*
|
|
1984
|
+
* @type {State}
|
|
1985
|
+
*/
|
|
1986
|
+
function protocolSlashesInside(code) {
|
|
1987
|
+
if (code === 47) {
|
|
1988
|
+
effects.consume(code);
|
|
1989
|
+
if (seen) return afterProtocol;
|
|
1990
|
+
seen = true;
|
|
1991
|
+
return protocolSlashesInside;
|
|
1992
|
+
}
|
|
1993
|
+
return nok(code);
|
|
1994
|
+
}
|
|
1995
|
+
/**
|
|
1996
|
+
* After protocol, before domain.
|
|
1997
|
+
*
|
|
1998
|
+
* ```markdown
|
|
1999
|
+
* > | https://example.com/a?b#c
|
|
2000
|
+
* ^
|
|
2001
|
+
* ```
|
|
2002
|
+
*
|
|
2003
|
+
* @type {State}
|
|
2004
|
+
*/
|
|
2005
|
+
function afterProtocol(code) {
|
|
2006
|
+
return code === null || asciiControl(code) || markdownLineEndingOrSpace(code) || unicodeWhitespace(code) || unicodePunctuation(code) ? nok(code) : effects.attempt(domain, effects.attempt(path, protocolAfter), nok)(code);
|
|
2007
|
+
}
|
|
2008
|
+
/**
|
|
2009
|
+
* After a protocol autolink literal.
|
|
2010
|
+
*
|
|
2011
|
+
* ```markdown
|
|
2012
|
+
* > | https://example.com/a?b#c
|
|
2013
|
+
* ^
|
|
2014
|
+
* ```
|
|
2015
|
+
*
|
|
2016
|
+
* @type {State}
|
|
2017
|
+
*/
|
|
2018
|
+
function protocolAfter(code) {
|
|
2019
|
+
effects.exit("literalAutolinkHttp");
|
|
2020
|
+
effects.exit("literalAutolink");
|
|
2021
|
+
return ok(code);
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
/**
|
|
2025
|
+
* `www` prefix.
|
|
2026
|
+
*
|
|
2027
|
+
* ```markdown
|
|
2028
|
+
* > | a www.example.org b
|
|
2029
|
+
* ^^^^
|
|
2030
|
+
* ```
|
|
2031
|
+
*
|
|
2032
|
+
* @this {TokenizeContext}
|
|
2033
|
+
* @type {Tokenizer}
|
|
2034
|
+
*/
|
|
2035
|
+
function tokenizeWwwPrefix(effects, ok, nok) {
|
|
2036
|
+
let size = 0;
|
|
2037
|
+
return wwwPrefixInside;
|
|
2038
|
+
/**
|
|
2039
|
+
* In www prefix.
|
|
2040
|
+
*
|
|
2041
|
+
* ```markdown
|
|
2042
|
+
* > | www.example.com
|
|
2043
|
+
* ^^^^
|
|
2044
|
+
* ```
|
|
2045
|
+
*
|
|
2046
|
+
* @type {State}
|
|
2047
|
+
*/
|
|
2048
|
+
function wwwPrefixInside(code) {
|
|
2049
|
+
if ((code === 87 || code === 119) && size < 3) {
|
|
2050
|
+
size++;
|
|
2051
|
+
effects.consume(code);
|
|
2052
|
+
return wwwPrefixInside;
|
|
2053
|
+
}
|
|
2054
|
+
if (code === 46 && size === 3) {
|
|
2055
|
+
effects.consume(code);
|
|
2056
|
+
return wwwPrefixAfter;
|
|
2057
|
+
}
|
|
2058
|
+
return nok(code);
|
|
2059
|
+
}
|
|
2060
|
+
/**
|
|
2061
|
+
* After www prefix.
|
|
2062
|
+
*
|
|
2063
|
+
* ```markdown
|
|
2064
|
+
* > | www.example.com
|
|
2065
|
+
* ^
|
|
2066
|
+
* ```
|
|
2067
|
+
*
|
|
2068
|
+
* @type {State}
|
|
2069
|
+
*/
|
|
2070
|
+
function wwwPrefixAfter(code) {
|
|
2071
|
+
return code === null ? nok(code) : ok(code);
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
/**
|
|
2075
|
+
* Domain.
|
|
2076
|
+
*
|
|
2077
|
+
* ```markdown
|
|
2078
|
+
* > | a https://example.org b
|
|
2079
|
+
* ^^^^^^^^^^^
|
|
2080
|
+
* ```
|
|
2081
|
+
*
|
|
2082
|
+
* @this {TokenizeContext}
|
|
2083
|
+
* @type {Tokenizer}
|
|
2084
|
+
*/
|
|
2085
|
+
function tokenizeDomain(effects, ok, nok) {
|
|
2086
|
+
/** @type {boolean | undefined} */
|
|
2087
|
+
let underscoreInLastSegment;
|
|
2088
|
+
/** @type {boolean | undefined} */
|
|
2089
|
+
let underscoreInLastLastSegment;
|
|
2090
|
+
/** @type {boolean | undefined} */
|
|
2091
|
+
let seen;
|
|
2092
|
+
return domainInside;
|
|
2093
|
+
/**
|
|
2094
|
+
* In domain.
|
|
2095
|
+
*
|
|
2096
|
+
* ```markdown
|
|
2097
|
+
* > | https://example.com/a
|
|
2098
|
+
* ^^^^^^^^^^^
|
|
2099
|
+
* ```
|
|
2100
|
+
*
|
|
2101
|
+
* @type {State}
|
|
2102
|
+
*/
|
|
2103
|
+
function domainInside(code) {
|
|
2104
|
+
if (code === 46 || code === 95) return effects.check(trail, domainAfter, domainAtPunctuation)(code);
|
|
2105
|
+
if (code === null || markdownLineEndingOrSpace(code) || unicodeWhitespace(code) || code !== 45 && unicodePunctuation(code)) return domainAfter(code);
|
|
2106
|
+
seen = true;
|
|
2107
|
+
effects.consume(code);
|
|
2108
|
+
return domainInside;
|
|
2109
|
+
}
|
|
2110
|
+
/**
|
|
2111
|
+
* In domain, at potential trailing punctuation, that was not trailing.
|
|
2112
|
+
*
|
|
2113
|
+
* ```markdown
|
|
2114
|
+
* > | https://example.com
|
|
2115
|
+
* ^
|
|
2116
|
+
* ```
|
|
2117
|
+
*
|
|
2118
|
+
* @type {State}
|
|
2119
|
+
*/
|
|
2120
|
+
function domainAtPunctuation(code) {
|
|
2121
|
+
if (code === 95) underscoreInLastSegment = true;
|
|
2122
|
+
else {
|
|
2123
|
+
underscoreInLastLastSegment = underscoreInLastSegment;
|
|
2124
|
+
underscoreInLastSegment = void 0;
|
|
2125
|
+
}
|
|
2126
|
+
effects.consume(code);
|
|
2127
|
+
return domainInside;
|
|
2128
|
+
}
|
|
2129
|
+
/**
|
|
2130
|
+
* After domain.
|
|
2131
|
+
*
|
|
2132
|
+
* ```markdown
|
|
2133
|
+
* > | https://example.com/a
|
|
2134
|
+
* ^
|
|
2135
|
+
* ```
|
|
2136
|
+
*
|
|
2137
|
+
* @type {State} */
|
|
2138
|
+
function domainAfter(code) {
|
|
2139
|
+
if (underscoreInLastLastSegment || underscoreInLastSegment || !seen) return nok(code);
|
|
2140
|
+
return ok(code);
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
/**
|
|
2144
|
+
* Path.
|
|
2145
|
+
*
|
|
2146
|
+
* ```markdown
|
|
2147
|
+
* > | a https://example.org/stuff b
|
|
2148
|
+
* ^^^^^^
|
|
2149
|
+
* ```
|
|
2150
|
+
*
|
|
2151
|
+
* @this {TokenizeContext}
|
|
2152
|
+
* @type {Tokenizer}
|
|
2153
|
+
*/
|
|
2154
|
+
function tokenizePath(effects, ok) {
|
|
2155
|
+
let sizeOpen = 0;
|
|
2156
|
+
let sizeClose = 0;
|
|
2157
|
+
return pathInside;
|
|
2158
|
+
/**
|
|
2159
|
+
* In path.
|
|
2160
|
+
*
|
|
2161
|
+
* ```markdown
|
|
2162
|
+
* > | https://example.com/a
|
|
2163
|
+
* ^^
|
|
2164
|
+
* ```
|
|
2165
|
+
*
|
|
2166
|
+
* @type {State}
|
|
2167
|
+
*/
|
|
2168
|
+
function pathInside(code) {
|
|
2169
|
+
if (code === 40) {
|
|
2170
|
+
sizeOpen++;
|
|
2171
|
+
effects.consume(code);
|
|
2172
|
+
return pathInside;
|
|
2173
|
+
}
|
|
2174
|
+
if (code === 41 && sizeClose < sizeOpen) return pathAtPunctuation(code);
|
|
2175
|
+
if (code === 33 || code === 34 || code === 38 || code === 39 || code === 41 || code === 42 || code === 44 || code === 46 || code === 58 || code === 59 || code === 60 || code === 63 || code === 93 || code === 95 || code === 126) return effects.check(trail, ok, pathAtPunctuation)(code);
|
|
2176
|
+
if (code === null || markdownLineEndingOrSpace(code) || unicodeWhitespace(code)) return ok(code);
|
|
2177
|
+
effects.consume(code);
|
|
2178
|
+
return pathInside;
|
|
2179
|
+
}
|
|
2180
|
+
/**
|
|
2181
|
+
* In path, at potential trailing punctuation, that was not trailing.
|
|
2182
|
+
*
|
|
2183
|
+
* ```markdown
|
|
2184
|
+
* > | https://example.com/a"b
|
|
2185
|
+
* ^
|
|
2186
|
+
* ```
|
|
2187
|
+
*
|
|
2188
|
+
* @type {State}
|
|
2189
|
+
*/
|
|
2190
|
+
function pathAtPunctuation(code) {
|
|
2191
|
+
if (code === 41) sizeClose++;
|
|
2192
|
+
effects.consume(code);
|
|
2193
|
+
return pathInside;
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
/**
|
|
2197
|
+
* Trail.
|
|
2198
|
+
*
|
|
2199
|
+
* This calls `ok` if this *is* the trail, followed by an end, which means
|
|
2200
|
+
* the entire trail is not part of the link.
|
|
2201
|
+
* It calls `nok` if this *is* part of the link.
|
|
2202
|
+
*
|
|
2203
|
+
* ```markdown
|
|
2204
|
+
* > | https://example.com").
|
|
2205
|
+
* ^^^
|
|
2206
|
+
* ```
|
|
2207
|
+
*
|
|
2208
|
+
* @this {TokenizeContext}
|
|
2209
|
+
* @type {Tokenizer}
|
|
2210
|
+
*/
|
|
2211
|
+
function tokenizeTrail(effects, ok, nok) {
|
|
2212
|
+
return trail;
|
|
2213
|
+
/**
|
|
2214
|
+
* In trail of domain or path.
|
|
2215
|
+
*
|
|
2216
|
+
* ```markdown
|
|
2217
|
+
* > | https://example.com").
|
|
2218
|
+
* ^
|
|
2219
|
+
* ```
|
|
2220
|
+
*
|
|
2221
|
+
* @type {State}
|
|
2222
|
+
*/
|
|
2223
|
+
function trail(code) {
|
|
2224
|
+
if (code === 33 || code === 34 || code === 39 || code === 41 || code === 42 || code === 44 || code === 46 || code === 58 || code === 59 || code === 63 || code === 95 || code === 126) {
|
|
2225
|
+
effects.consume(code);
|
|
2226
|
+
return trail;
|
|
2227
|
+
}
|
|
2228
|
+
if (code === 38) {
|
|
2229
|
+
effects.consume(code);
|
|
2230
|
+
return trailCharacterReferenceStart;
|
|
2231
|
+
}
|
|
2232
|
+
if (code === 93) {
|
|
2233
|
+
effects.consume(code);
|
|
2234
|
+
return trailBracketAfter;
|
|
2235
|
+
}
|
|
2236
|
+
if (code === 60 || code === null || markdownLineEndingOrSpace(code) || unicodeWhitespace(code)) return ok(code);
|
|
2237
|
+
return nok(code);
|
|
2238
|
+
}
|
|
2239
|
+
/**
|
|
2240
|
+
* In trail, after `]`.
|
|
2241
|
+
*
|
|
2242
|
+
* > 👉 **Note**: this deviates from `cmark-gfm` to fix a bug.
|
|
2243
|
+
* > See end of <https://github.com/github/cmark-gfm/issues/278> for more.
|
|
2244
|
+
*
|
|
2245
|
+
* ```markdown
|
|
2246
|
+
* > | https://example.com](
|
|
2247
|
+
* ^
|
|
2248
|
+
* ```
|
|
2249
|
+
*
|
|
2250
|
+
* @type {State}
|
|
2251
|
+
*/
|
|
2252
|
+
function trailBracketAfter(code) {
|
|
2253
|
+
if (code === null || code === 40 || code === 91 || markdownLineEndingOrSpace(code) || unicodeWhitespace(code)) return ok(code);
|
|
2254
|
+
return trail(code);
|
|
2255
|
+
}
|
|
2256
|
+
/**
|
|
2257
|
+
* In character-reference like trail, after `&`.
|
|
2258
|
+
*
|
|
2259
|
+
* ```markdown
|
|
2260
|
+
* > | https://example.com&).
|
|
2261
|
+
* ^
|
|
2262
|
+
* ```
|
|
2263
|
+
*
|
|
2264
|
+
* @type {State}
|
|
2265
|
+
*/
|
|
2266
|
+
function trailCharacterReferenceStart(code) {
|
|
2267
|
+
return asciiAlpha(code) ? trailCharacterReferenceInside(code) : nok(code);
|
|
2268
|
+
}
|
|
2269
|
+
/**
|
|
2270
|
+
* In character-reference like trail.
|
|
2271
|
+
*
|
|
2272
|
+
* ```markdown
|
|
2273
|
+
* > | https://example.com&).
|
|
2274
|
+
* ^
|
|
2275
|
+
* ```
|
|
2276
|
+
*
|
|
2277
|
+
* @type {State}
|
|
2278
|
+
*/
|
|
2279
|
+
function trailCharacterReferenceInside(code) {
|
|
2280
|
+
if (code === 59) {
|
|
2281
|
+
effects.consume(code);
|
|
2282
|
+
return trail;
|
|
2283
|
+
}
|
|
2284
|
+
if (asciiAlpha(code)) {
|
|
2285
|
+
effects.consume(code);
|
|
2286
|
+
return trailCharacterReferenceInside;
|
|
2287
|
+
}
|
|
2288
|
+
return nok(code);
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
/**
|
|
2292
|
+
* Dot in email domain trail.
|
|
2293
|
+
*
|
|
2294
|
+
* This calls `ok` if this *is* the trail, followed by an end, which means
|
|
2295
|
+
* the trail is not part of the link.
|
|
2296
|
+
* It calls `nok` if this *is* part of the link.
|
|
2297
|
+
*
|
|
2298
|
+
* ```markdown
|
|
2299
|
+
* > | contact@example.org.
|
|
2300
|
+
* ^
|
|
2301
|
+
* ```
|
|
2302
|
+
*
|
|
2303
|
+
* @this {TokenizeContext}
|
|
2304
|
+
* @type {Tokenizer}
|
|
2305
|
+
*/
|
|
2306
|
+
function tokenizeEmailDomainDotTrail(effects, ok, nok) {
|
|
2307
|
+
return start;
|
|
2308
|
+
/**
|
|
2309
|
+
* Dot.
|
|
2310
|
+
*
|
|
2311
|
+
* ```markdown
|
|
2312
|
+
* > | contact@example.org.
|
|
2313
|
+
* ^ ^
|
|
2314
|
+
* ```
|
|
2315
|
+
*
|
|
2316
|
+
* @type {State}
|
|
2317
|
+
*/
|
|
2318
|
+
function start(code) {
|
|
2319
|
+
effects.consume(code);
|
|
2320
|
+
return after;
|
|
2321
|
+
}
|
|
2322
|
+
/**
|
|
2323
|
+
* After dot.
|
|
2324
|
+
*
|
|
2325
|
+
* ```markdown
|
|
2326
|
+
* > | contact@example.org.
|
|
2327
|
+
* ^ ^
|
|
2328
|
+
* ```
|
|
2329
|
+
*
|
|
2330
|
+
* @type {State}
|
|
2331
|
+
*/
|
|
2332
|
+
function after(code) {
|
|
2333
|
+
return asciiAlphanumeric(code) ? nok(code) : ok(code);
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
/**
|
|
2337
|
+
* See:
|
|
2338
|
+
* <https://github.com/github/cmark-gfm/blob/ef1cfcb/extensions/autolink.c#L156>.
|
|
2339
|
+
*
|
|
2340
|
+
* @type {Previous}
|
|
2341
|
+
*/
|
|
2342
|
+
function previousWww(code) {
|
|
2343
|
+
return code === null || code === 40 || code === 42 || code === 95 || code === 91 || code === 93 || code === 126 || markdownLineEndingOrSpace(code);
|
|
2344
|
+
}
|
|
2345
|
+
/**
|
|
2346
|
+
* See:
|
|
2347
|
+
* <https://github.com/github/cmark-gfm/blob/ef1cfcb/extensions/autolink.c#L214>.
|
|
2348
|
+
*
|
|
2349
|
+
* @type {Previous}
|
|
2350
|
+
*/
|
|
2351
|
+
function previousProtocol(code) {
|
|
2352
|
+
return !asciiAlpha(code);
|
|
2353
|
+
}
|
|
2354
|
+
/**
|
|
2355
|
+
* @this {TokenizeContext}
|
|
2356
|
+
* @type {Previous}
|
|
2357
|
+
*/
|
|
2358
|
+
function previousEmail(code) {
|
|
2359
|
+
return !(code === 47 || gfmAtext(code));
|
|
2360
|
+
}
|
|
2361
|
+
/**
|
|
2362
|
+
* @param {Code} code
|
|
2363
|
+
* @returns {boolean}
|
|
2364
|
+
*/
|
|
2365
|
+
function gfmAtext(code) {
|
|
2366
|
+
return code === 43 || code === 45 || code === 46 || code === 95 || asciiAlphanumeric(code);
|
|
2367
|
+
}
|
|
2368
|
+
/**
|
|
2369
|
+
* @param {Array<Event>} events
|
|
2370
|
+
* @returns {boolean}
|
|
2371
|
+
*/
|
|
2372
|
+
function previousUnbalanced(events) {
|
|
2373
|
+
let index = events.length;
|
|
2374
|
+
let result = false;
|
|
2375
|
+
while (index--) {
|
|
2376
|
+
const token = events[index][1];
|
|
2377
|
+
if ((token.type === "labelLink" || token.type === "labelImage") && !token._balanced) {
|
|
2378
|
+
result = true;
|
|
2379
|
+
break;
|
|
2380
|
+
}
|
|
2381
|
+
if (token._gfmAutolinkLiteralWalkedInto) {
|
|
2382
|
+
result = false;
|
|
2383
|
+
break;
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
if (events.length > 0 && !result) events[events.length - 1][1]._gfmAutolinkLiteralWalkedInto = true;
|
|
2387
|
+
return result;
|
|
2388
|
+
}
|
|
2389
|
+
//#endregion
|
|
2390
|
+
//#region ../../../node_modules/.pnpm/micromark-util-resolve-all@2.0.1/node_modules/micromark-util-resolve-all/index.js
|
|
2391
|
+
/**
|
|
2392
|
+
* @import {Event, Resolver, TokenizeContext} from 'micromark-util-types'
|
|
2393
|
+
*/
|
|
2394
|
+
/**
|
|
2395
|
+
* Call all `resolveAll`s.
|
|
2396
|
+
*
|
|
2397
|
+
* @param {ReadonlyArray<{resolveAll?: Resolver | undefined}>} constructs
|
|
2398
|
+
* List of constructs, optionally with `resolveAll`s.
|
|
2399
|
+
* @param {Array<Event>} events
|
|
2400
|
+
* List of events.
|
|
2401
|
+
* @param {TokenizeContext} context
|
|
2402
|
+
* Context used by `tokenize`.
|
|
2403
|
+
* @returns {Array<Event>}
|
|
2404
|
+
* Changed events.
|
|
2405
|
+
*/
|
|
2406
|
+
function resolveAll(constructs, events, context) {
|
|
2407
|
+
/** @type {Array<Resolver>} */
|
|
2408
|
+
const called = [];
|
|
2409
|
+
let index = -1;
|
|
2410
|
+
while (++index < constructs.length) {
|
|
2411
|
+
const resolve = constructs[index].resolveAll;
|
|
2412
|
+
if (resolve && !called.includes(resolve)) {
|
|
2413
|
+
events = resolve(events, context);
|
|
2414
|
+
called.push(resolve);
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
return events;
|
|
2418
|
+
}
|
|
2419
|
+
//#endregion
|
|
2420
|
+
//#region ../../../node_modules/.pnpm/micromark-factory-space@2.0.1/node_modules/micromark-factory-space/index.js
|
|
2421
|
+
/**
|
|
2422
|
+
* @import {Effects, State, TokenType} from 'micromark-util-types'
|
|
2423
|
+
*/
|
|
2424
|
+
/**
|
|
2425
|
+
* Parse spaces and tabs.
|
|
2426
|
+
*
|
|
2427
|
+
* There is no `nok` parameter:
|
|
2428
|
+
*
|
|
2429
|
+
* * spaces in markdown are often optional, in which case this factory can be
|
|
2430
|
+
* used and `ok` will be switched to whether spaces were found or not
|
|
2431
|
+
* * one line ending or space can be detected with `markdownSpace(code)` right
|
|
2432
|
+
* before using `factorySpace`
|
|
2433
|
+
*
|
|
2434
|
+
* ###### Examples
|
|
2435
|
+
*
|
|
2436
|
+
* Where `␉` represents a tab (plus how much it expands) and `␠` represents a
|
|
2437
|
+
* single space.
|
|
2438
|
+
*
|
|
2439
|
+
* ```markdown
|
|
2440
|
+
* ␉
|
|
2441
|
+
* ␠␠␠␠
|
|
2442
|
+
* ␉␠
|
|
2443
|
+
* ```
|
|
2444
|
+
*
|
|
2445
|
+
* @param {Effects} effects
|
|
2446
|
+
* Context.
|
|
2447
|
+
* @param {State} ok
|
|
2448
|
+
* State switched to when successful.
|
|
2449
|
+
* @param {TokenType} type
|
|
2450
|
+
* Type (`' \t'`).
|
|
2451
|
+
* @param {number | undefined} [max=Infinity]
|
|
2452
|
+
* Max (exclusive).
|
|
2453
|
+
* @returns {State}
|
|
2454
|
+
* Start state.
|
|
2455
|
+
*/
|
|
2456
|
+
function factorySpace(effects, ok, type, max) {
|
|
2457
|
+
const limit = max ? max - 1 : Number.POSITIVE_INFINITY;
|
|
2458
|
+
let size = 0;
|
|
2459
|
+
return start;
|
|
2460
|
+
/** @type {State} */
|
|
2461
|
+
function start(code) {
|
|
2462
|
+
if (markdownSpace(code)) {
|
|
2463
|
+
effects.enter(type);
|
|
2464
|
+
return prefix(code);
|
|
2465
|
+
}
|
|
2466
|
+
return ok(code);
|
|
2467
|
+
}
|
|
2468
|
+
/** @type {State} */
|
|
2469
|
+
function prefix(code) {
|
|
2470
|
+
if (markdownSpace(code) && size++ < limit) {
|
|
2471
|
+
effects.consume(code);
|
|
2472
|
+
return prefix;
|
|
2473
|
+
}
|
|
2474
|
+
effects.exit(type);
|
|
2475
|
+
return ok(code);
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
//#endregion
|
|
2479
|
+
//#region ../../../node_modules/.pnpm/micromark-core-commonmark@2.0.3/node_modules/micromark-core-commonmark/lib/blank-line.js
|
|
2480
|
+
/**
|
|
2481
|
+
* @import {
|
|
2482
|
+
* Construct,
|
|
2483
|
+
* State,
|
|
2484
|
+
* TokenizeContext,
|
|
2485
|
+
* Tokenizer
|
|
2486
|
+
* } from 'micromark-util-types'
|
|
2487
|
+
*/
|
|
2488
|
+
/** @type {Construct} */
|
|
2489
|
+
const blankLine = {
|
|
2490
|
+
partial: true,
|
|
2491
|
+
tokenize: tokenizeBlankLine
|
|
2492
|
+
};
|
|
2493
|
+
/**
|
|
2494
|
+
* @this {TokenizeContext}
|
|
2495
|
+
* Context.
|
|
2496
|
+
* @type {Tokenizer}
|
|
2497
|
+
*/
|
|
2498
|
+
function tokenizeBlankLine(effects, ok, nok) {
|
|
2499
|
+
return start;
|
|
2500
|
+
/**
|
|
2501
|
+
* Start of blank line.
|
|
2502
|
+
*
|
|
2503
|
+
* > 👉 **Note**: `␠` represents a space character.
|
|
2504
|
+
*
|
|
2505
|
+
* ```markdown
|
|
2506
|
+
* > | ␠␠␊
|
|
2507
|
+
* ^
|
|
2508
|
+
* > | ␊
|
|
2509
|
+
* ^
|
|
2510
|
+
* ```
|
|
2511
|
+
*
|
|
2512
|
+
* @type {State}
|
|
2513
|
+
*/
|
|
2514
|
+
function start(code) {
|
|
2515
|
+
return markdownSpace(code) ? factorySpace(effects, after, "linePrefix")(code) : after(code);
|
|
2516
|
+
}
|
|
2517
|
+
/**
|
|
2518
|
+
* At eof/eol, after optional whitespace.
|
|
2519
|
+
*
|
|
2520
|
+
* > 👉 **Note**: `␠` represents a space character.
|
|
2521
|
+
*
|
|
2522
|
+
* ```markdown
|
|
2523
|
+
* > | ␠␠␊
|
|
2524
|
+
* ^
|
|
2525
|
+
* > | ␊
|
|
2526
|
+
* ^
|
|
2527
|
+
* ```
|
|
2528
|
+
*
|
|
2529
|
+
* @type {State}
|
|
2530
|
+
*/
|
|
2531
|
+
function after(code) {
|
|
2532
|
+
return code === null || markdownLineEnding(code) ? ok(code) : nok(code);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
//#endregion
|
|
2536
|
+
//#region ../../../node_modules/.pnpm/micromark-extension-gfm-footnote@2.1.0/node_modules/micromark-extension-gfm-footnote/lib/syntax.js
|
|
2537
|
+
/**
|
|
2538
|
+
* @import {Event, Exiter, Extension, Resolver, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'
|
|
2539
|
+
*/
|
|
2540
|
+
const indent = {
|
|
2541
|
+
tokenize: tokenizeIndent,
|
|
2542
|
+
partial: true
|
|
2543
|
+
};
|
|
2544
|
+
/**
|
|
2545
|
+
* Create an extension for `micromark` to enable GFM footnote syntax.
|
|
2546
|
+
*
|
|
2547
|
+
* @returns {Extension}
|
|
2548
|
+
* Extension for `micromark` that can be passed in `extensions` to
|
|
2549
|
+
* enable GFM footnote syntax.
|
|
2550
|
+
*/
|
|
2551
|
+
function gfmFootnote() {
|
|
2552
|
+
/** @type {Extension} */
|
|
2553
|
+
return {
|
|
2554
|
+
document: { [91]: {
|
|
2555
|
+
name: "gfmFootnoteDefinition",
|
|
2556
|
+
tokenize: tokenizeDefinitionStart,
|
|
2557
|
+
continuation: { tokenize: tokenizeDefinitionContinuation },
|
|
2558
|
+
exit: gfmFootnoteDefinitionEnd
|
|
2559
|
+
} },
|
|
2560
|
+
text: {
|
|
2561
|
+
[91]: {
|
|
2562
|
+
name: "gfmFootnoteCall",
|
|
2563
|
+
tokenize: tokenizeGfmFootnoteCall
|
|
2564
|
+
},
|
|
2565
|
+
[93]: {
|
|
2566
|
+
name: "gfmPotentialFootnoteCall",
|
|
2567
|
+
add: "after",
|
|
2568
|
+
tokenize: tokenizePotentialGfmFootnoteCall,
|
|
2569
|
+
resolveTo: resolveToPotentialGfmFootnoteCall
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
};
|
|
2573
|
+
}
|
|
2574
|
+
/**
|
|
2575
|
+
* @this {TokenizeContext}
|
|
2576
|
+
* @type {Tokenizer}
|
|
2577
|
+
*/
|
|
2578
|
+
function tokenizePotentialGfmFootnoteCall(effects, ok, nok) {
|
|
2579
|
+
const self = this;
|
|
2580
|
+
let index = self.events.length;
|
|
2581
|
+
const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []);
|
|
2582
|
+
/** @type {Token} */
|
|
2583
|
+
let labelStart;
|
|
2584
|
+
while (index--) {
|
|
2585
|
+
const token = self.events[index][1];
|
|
2586
|
+
if (token.type === "labelImage") {
|
|
2587
|
+
labelStart = token;
|
|
2588
|
+
break;
|
|
2589
|
+
}
|
|
2590
|
+
if (token.type === "gfmFootnoteCall" || token.type === "labelLink" || token.type === "label" || token.type === "image" || token.type === "link") break;
|
|
2591
|
+
}
|
|
2592
|
+
return start;
|
|
2593
|
+
/**
|
|
2594
|
+
* @type {State}
|
|
2595
|
+
*/
|
|
2596
|
+
function start(code) {
|
|
2597
|
+
if (!labelStart || !labelStart._balanced) return nok(code);
|
|
2598
|
+
const id = normalizeIdentifier(self.sliceSerialize({
|
|
2599
|
+
start: labelStart.end,
|
|
2600
|
+
end: self.now()
|
|
2601
|
+
}));
|
|
2602
|
+
if (id.codePointAt(0) !== 94 || !defined.includes(id.slice(1))) return nok(code);
|
|
2603
|
+
effects.enter("gfmFootnoteCallLabelMarker");
|
|
2604
|
+
effects.consume(code);
|
|
2605
|
+
effects.exit("gfmFootnoteCallLabelMarker");
|
|
2606
|
+
return ok(code);
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
/** @type {Resolver} */
|
|
2610
|
+
function resolveToPotentialGfmFootnoteCall(events, context) {
|
|
2611
|
+
let index = events.length;
|
|
2612
|
+
while (index--) if (events[index][1].type === "labelImage" && events[index][0] === "enter") {
|
|
2613
|
+
events[index][1];
|
|
2614
|
+
break;
|
|
2615
|
+
}
|
|
2616
|
+
events[index + 1][1].type = "data";
|
|
2617
|
+
events[index + 3][1].type = "gfmFootnoteCallLabelMarker";
|
|
2618
|
+
/** @type {Token} */
|
|
2619
|
+
const call = {
|
|
2620
|
+
type: "gfmFootnoteCall",
|
|
2621
|
+
start: Object.assign({}, events[index + 3][1].start),
|
|
2622
|
+
end: Object.assign({}, events[events.length - 1][1].end)
|
|
2623
|
+
};
|
|
2624
|
+
/** @type {Token} */
|
|
2625
|
+
const marker = {
|
|
2626
|
+
type: "gfmFootnoteCallMarker",
|
|
2627
|
+
start: Object.assign({}, events[index + 3][1].end),
|
|
2628
|
+
end: Object.assign({}, events[index + 3][1].end)
|
|
2629
|
+
};
|
|
2630
|
+
marker.end.column++;
|
|
2631
|
+
marker.end.offset++;
|
|
2632
|
+
marker.end._bufferIndex++;
|
|
2633
|
+
/** @type {Token} */
|
|
2634
|
+
const string = {
|
|
2635
|
+
type: "gfmFootnoteCallString",
|
|
2636
|
+
start: Object.assign({}, marker.end),
|
|
2637
|
+
end: Object.assign({}, events[events.length - 1][1].start)
|
|
2638
|
+
};
|
|
2639
|
+
/** @type {Token} */
|
|
2640
|
+
const chunk = {
|
|
2641
|
+
type: "chunkString",
|
|
2642
|
+
contentType: "string",
|
|
2643
|
+
start: Object.assign({}, string.start),
|
|
2644
|
+
end: Object.assign({}, string.end)
|
|
2645
|
+
};
|
|
2646
|
+
/** @type {Array<Event>} */
|
|
2647
|
+
const replacement = [
|
|
2648
|
+
events[index + 1],
|
|
2649
|
+
events[index + 2],
|
|
2650
|
+
[
|
|
2651
|
+
"enter",
|
|
2652
|
+
call,
|
|
2653
|
+
context
|
|
2654
|
+
],
|
|
2655
|
+
events[index + 3],
|
|
2656
|
+
events[index + 4],
|
|
2657
|
+
[
|
|
2658
|
+
"enter",
|
|
2659
|
+
marker,
|
|
2660
|
+
context
|
|
2661
|
+
],
|
|
2662
|
+
[
|
|
2663
|
+
"exit",
|
|
2664
|
+
marker,
|
|
2665
|
+
context
|
|
2666
|
+
],
|
|
2667
|
+
[
|
|
2668
|
+
"enter",
|
|
2669
|
+
string,
|
|
2670
|
+
context
|
|
2671
|
+
],
|
|
2672
|
+
[
|
|
2673
|
+
"enter",
|
|
2674
|
+
chunk,
|
|
2675
|
+
context
|
|
2676
|
+
],
|
|
2677
|
+
[
|
|
2678
|
+
"exit",
|
|
2679
|
+
chunk,
|
|
2680
|
+
context
|
|
2681
|
+
],
|
|
2682
|
+
[
|
|
2683
|
+
"exit",
|
|
2684
|
+
string,
|
|
2685
|
+
context
|
|
2686
|
+
],
|
|
2687
|
+
events[events.length - 2],
|
|
2688
|
+
events[events.length - 1],
|
|
2689
|
+
[
|
|
2690
|
+
"exit",
|
|
2691
|
+
call,
|
|
2692
|
+
context
|
|
2693
|
+
]
|
|
2694
|
+
];
|
|
2695
|
+
events.splice(index, events.length - index + 1, ...replacement);
|
|
2696
|
+
return events;
|
|
2697
|
+
}
|
|
2698
|
+
/**
|
|
2699
|
+
* @this {TokenizeContext}
|
|
2700
|
+
* @type {Tokenizer}
|
|
2701
|
+
*/
|
|
2702
|
+
function tokenizeGfmFootnoteCall(effects, ok, nok) {
|
|
2703
|
+
const self = this;
|
|
2704
|
+
const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []);
|
|
2705
|
+
let size = 0;
|
|
2706
|
+
/** @type {boolean} */
|
|
2707
|
+
let data;
|
|
2708
|
+
return start;
|
|
2709
|
+
/**
|
|
2710
|
+
* Start of footnote label.
|
|
2711
|
+
*
|
|
2712
|
+
* ```markdown
|
|
2713
|
+
* > | a [^b] c
|
|
2714
|
+
* ^
|
|
2715
|
+
* ```
|
|
2716
|
+
*
|
|
2717
|
+
* @type {State}
|
|
2718
|
+
*/
|
|
2719
|
+
function start(code) {
|
|
2720
|
+
effects.enter("gfmFootnoteCall");
|
|
2721
|
+
effects.enter("gfmFootnoteCallLabelMarker");
|
|
2722
|
+
effects.consume(code);
|
|
2723
|
+
effects.exit("gfmFootnoteCallLabelMarker");
|
|
2724
|
+
return callStart;
|
|
2725
|
+
}
|
|
2726
|
+
/**
|
|
2727
|
+
* After `[`, at `^`.
|
|
2728
|
+
*
|
|
2729
|
+
* ```markdown
|
|
2730
|
+
* > | a [^b] c
|
|
2731
|
+
* ^
|
|
2732
|
+
* ```
|
|
2733
|
+
*
|
|
2734
|
+
* @type {State}
|
|
2735
|
+
*/
|
|
2736
|
+
function callStart(code) {
|
|
2737
|
+
if (code !== 94) return nok(code);
|
|
2738
|
+
effects.enter("gfmFootnoteCallMarker");
|
|
2739
|
+
effects.consume(code);
|
|
2740
|
+
effects.exit("gfmFootnoteCallMarker");
|
|
2741
|
+
effects.enter("gfmFootnoteCallString");
|
|
2742
|
+
effects.enter("chunkString").contentType = "string";
|
|
2743
|
+
return callData;
|
|
2744
|
+
}
|
|
2745
|
+
/**
|
|
2746
|
+
* In label.
|
|
2747
|
+
*
|
|
2748
|
+
* ```markdown
|
|
2749
|
+
* > | a [^b] c
|
|
2750
|
+
* ^
|
|
2751
|
+
* ```
|
|
2752
|
+
*
|
|
2753
|
+
* @type {State}
|
|
2754
|
+
*/
|
|
2755
|
+
function callData(code) {
|
|
2756
|
+
if (size > 999 || code === 93 && !data || code === null || code === 91 || markdownLineEndingOrSpace(code)) return nok(code);
|
|
2757
|
+
if (code === 93) {
|
|
2758
|
+
effects.exit("chunkString");
|
|
2759
|
+
const token = effects.exit("gfmFootnoteCallString");
|
|
2760
|
+
if (!defined.includes(normalizeIdentifier(self.sliceSerialize(token)))) return nok(code);
|
|
2761
|
+
effects.enter("gfmFootnoteCallLabelMarker");
|
|
2762
|
+
effects.consume(code);
|
|
2763
|
+
effects.exit("gfmFootnoteCallLabelMarker");
|
|
2764
|
+
effects.exit("gfmFootnoteCall");
|
|
2765
|
+
return ok;
|
|
2766
|
+
}
|
|
2767
|
+
if (!markdownLineEndingOrSpace(code)) data = true;
|
|
2768
|
+
size++;
|
|
2769
|
+
effects.consume(code);
|
|
2770
|
+
return code === 92 ? callEscape : callData;
|
|
2771
|
+
}
|
|
2772
|
+
/**
|
|
2773
|
+
* On character after escape.
|
|
2774
|
+
*
|
|
2775
|
+
* ```markdown
|
|
2776
|
+
* > | a [^b\c] d
|
|
2777
|
+
* ^
|
|
2778
|
+
* ```
|
|
2779
|
+
*
|
|
2780
|
+
* @type {State}
|
|
2781
|
+
*/
|
|
2782
|
+
function callEscape(code) {
|
|
2783
|
+
if (code === 91 || code === 92 || code === 93) {
|
|
2784
|
+
effects.consume(code);
|
|
2785
|
+
size++;
|
|
2786
|
+
return callData;
|
|
2787
|
+
}
|
|
2788
|
+
return callData(code);
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
/**
|
|
2792
|
+
* @this {TokenizeContext}
|
|
2793
|
+
* @type {Tokenizer}
|
|
2794
|
+
*/
|
|
2795
|
+
function tokenizeDefinitionStart(effects, ok, nok) {
|
|
2796
|
+
const self = this;
|
|
2797
|
+
const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []);
|
|
2798
|
+
/** @type {string} */
|
|
2799
|
+
let identifier;
|
|
2800
|
+
let size = 0;
|
|
2801
|
+
/** @type {boolean | undefined} */
|
|
2802
|
+
let data;
|
|
2803
|
+
return start;
|
|
2804
|
+
/**
|
|
2805
|
+
* Start of GFM footnote definition.
|
|
2806
|
+
*
|
|
2807
|
+
* ```markdown
|
|
2808
|
+
* > | [^a]: b
|
|
2809
|
+
* ^
|
|
2810
|
+
* ```
|
|
2811
|
+
*
|
|
2812
|
+
* @type {State}
|
|
2813
|
+
*/
|
|
2814
|
+
function start(code) {
|
|
2815
|
+
effects.enter("gfmFootnoteDefinition")._container = true;
|
|
2816
|
+
effects.enter("gfmFootnoteDefinitionLabel");
|
|
2817
|
+
effects.enter("gfmFootnoteDefinitionLabelMarker");
|
|
2818
|
+
effects.consume(code);
|
|
2819
|
+
effects.exit("gfmFootnoteDefinitionLabelMarker");
|
|
2820
|
+
return labelAtMarker;
|
|
2821
|
+
}
|
|
2822
|
+
/**
|
|
2823
|
+
* In label, at caret.
|
|
2824
|
+
*
|
|
2825
|
+
* ```markdown
|
|
2826
|
+
* > | [^a]: b
|
|
2827
|
+
* ^
|
|
2828
|
+
* ```
|
|
2829
|
+
*
|
|
2830
|
+
* @type {State}
|
|
2831
|
+
*/
|
|
2832
|
+
function labelAtMarker(code) {
|
|
2833
|
+
if (code === 94) {
|
|
2834
|
+
effects.enter("gfmFootnoteDefinitionMarker");
|
|
2835
|
+
effects.consume(code);
|
|
2836
|
+
effects.exit("gfmFootnoteDefinitionMarker");
|
|
2837
|
+
effects.enter("gfmFootnoteDefinitionLabelString");
|
|
2838
|
+
effects.enter("chunkString").contentType = "string";
|
|
2839
|
+
return labelInside;
|
|
2840
|
+
}
|
|
2841
|
+
return nok(code);
|
|
2842
|
+
}
|
|
2843
|
+
/**
|
|
2844
|
+
* In label.
|
|
2845
|
+
*
|
|
2846
|
+
* > 👉 **Note**: `cmark-gfm` prevents whitespace from occurring in footnote
|
|
2847
|
+
* > definition labels.
|
|
2848
|
+
*
|
|
2849
|
+
* ```markdown
|
|
2850
|
+
* > | [^a]: b
|
|
2851
|
+
* ^
|
|
2852
|
+
* ```
|
|
2853
|
+
*
|
|
2854
|
+
* @type {State}
|
|
2855
|
+
*/
|
|
2856
|
+
function labelInside(code) {
|
|
2857
|
+
if (size > 999 || code === 93 && !data || code === null || code === 91 || markdownLineEndingOrSpace(code)) return nok(code);
|
|
2858
|
+
if (code === 93) {
|
|
2859
|
+
effects.exit("chunkString");
|
|
2860
|
+
const token = effects.exit("gfmFootnoteDefinitionLabelString");
|
|
2861
|
+
identifier = normalizeIdentifier(self.sliceSerialize(token));
|
|
2862
|
+
effects.enter("gfmFootnoteDefinitionLabelMarker");
|
|
2863
|
+
effects.consume(code);
|
|
2864
|
+
effects.exit("gfmFootnoteDefinitionLabelMarker");
|
|
2865
|
+
effects.exit("gfmFootnoteDefinitionLabel");
|
|
2866
|
+
return labelAfter;
|
|
2867
|
+
}
|
|
2868
|
+
if (!markdownLineEndingOrSpace(code)) data = true;
|
|
2869
|
+
size++;
|
|
2870
|
+
effects.consume(code);
|
|
2871
|
+
return code === 92 ? labelEscape : labelInside;
|
|
2872
|
+
}
|
|
2873
|
+
/**
|
|
2874
|
+
* After `\`, at a special character.
|
|
2875
|
+
*
|
|
2876
|
+
* > 👉 **Note**: `cmark-gfm` currently does not support escaped brackets:
|
|
2877
|
+
* > <https://github.com/github/cmark-gfm/issues/240>
|
|
2878
|
+
*
|
|
2879
|
+
* ```markdown
|
|
2880
|
+
* > | [^a\*b]: c
|
|
2881
|
+
* ^
|
|
2882
|
+
* ```
|
|
2883
|
+
*
|
|
2884
|
+
* @type {State}
|
|
2885
|
+
*/
|
|
2886
|
+
function labelEscape(code) {
|
|
2887
|
+
if (code === 91 || code === 92 || code === 93) {
|
|
2888
|
+
effects.consume(code);
|
|
2889
|
+
size++;
|
|
2890
|
+
return labelInside;
|
|
2891
|
+
}
|
|
2892
|
+
return labelInside(code);
|
|
2893
|
+
}
|
|
2894
|
+
/**
|
|
2895
|
+
* After definition label.
|
|
2896
|
+
*
|
|
2897
|
+
* ```markdown
|
|
2898
|
+
* > | [^a]: b
|
|
2899
|
+
* ^
|
|
2900
|
+
* ```
|
|
2901
|
+
*
|
|
2902
|
+
* @type {State}
|
|
2903
|
+
*/
|
|
2904
|
+
function labelAfter(code) {
|
|
2905
|
+
if (code === 58) {
|
|
2906
|
+
effects.enter("definitionMarker");
|
|
2907
|
+
effects.consume(code);
|
|
2908
|
+
effects.exit("definitionMarker");
|
|
2909
|
+
if (!defined.includes(identifier)) defined.push(identifier);
|
|
2910
|
+
return factorySpace(effects, whitespaceAfter, "gfmFootnoteDefinitionWhitespace");
|
|
2911
|
+
}
|
|
2912
|
+
return nok(code);
|
|
2913
|
+
}
|
|
2914
|
+
/**
|
|
2915
|
+
* After definition prefix.
|
|
2916
|
+
*
|
|
2917
|
+
* ```markdown
|
|
2918
|
+
* > | [^a]: b
|
|
2919
|
+
* ^
|
|
2920
|
+
* ```
|
|
2921
|
+
*
|
|
2922
|
+
* @type {State}
|
|
2923
|
+
*/
|
|
2924
|
+
function whitespaceAfter(code) {
|
|
2925
|
+
return ok(code);
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
/**
|
|
2929
|
+
* @this {TokenizeContext}
|
|
2930
|
+
* @type {Tokenizer}
|
|
2931
|
+
*/
|
|
2932
|
+
function tokenizeDefinitionContinuation(effects, ok, nok) {
|
|
2933
|
+
return effects.check(blankLine, ok, effects.attempt(indent, ok, nok));
|
|
2934
|
+
}
|
|
2935
|
+
/** @type {Exiter} */
|
|
2936
|
+
function gfmFootnoteDefinitionEnd(effects) {
|
|
2937
|
+
effects.exit("gfmFootnoteDefinition");
|
|
2938
|
+
}
|
|
2939
|
+
/**
|
|
2940
|
+
* @this {TokenizeContext}
|
|
2941
|
+
* @type {Tokenizer}
|
|
2942
|
+
*/
|
|
2943
|
+
function tokenizeIndent(effects, ok, nok) {
|
|
2944
|
+
const self = this;
|
|
2945
|
+
return factorySpace(effects, afterPrefix, "gfmFootnoteDefinitionIndent", 5);
|
|
2946
|
+
/**
|
|
2947
|
+
* @type {State}
|
|
2948
|
+
*/
|
|
2949
|
+
function afterPrefix(code) {
|
|
2950
|
+
const tail = self.events[self.events.length - 1];
|
|
2951
|
+
return tail && tail[1].type === "gfmFootnoteDefinitionIndent" && tail[2].sliceSerialize(tail[1], true).length === 4 ? ok(code) : nok(code);
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2954
|
+
//#endregion
|
|
2955
|
+
//#region ../../../node_modules/.pnpm/micromark-extension-gfm-strikethrough@2.1.0/node_modules/micromark-extension-gfm-strikethrough/lib/syntax.js
|
|
2956
|
+
/**
|
|
2957
|
+
* @import {Options} from 'micromark-extension-gfm-strikethrough'
|
|
2958
|
+
* @import {Event, Extension, Resolver, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'
|
|
2959
|
+
*/
|
|
2960
|
+
/**
|
|
2961
|
+
* Create an extension for `micromark` to enable GFM strikethrough syntax.
|
|
2962
|
+
*
|
|
2963
|
+
* @param {Options | null | undefined} [options={}]
|
|
2964
|
+
* Configuration.
|
|
2965
|
+
* @returns {Extension}
|
|
2966
|
+
* Extension for `micromark` that can be passed in `extensions`, to
|
|
2967
|
+
* enable GFM strikethrough syntax.
|
|
2968
|
+
*/
|
|
2969
|
+
function gfmStrikethrough(options) {
|
|
2970
|
+
let single = (options || {}).singleTilde;
|
|
2971
|
+
const tokenizer = {
|
|
2972
|
+
name: "strikethrough",
|
|
2973
|
+
tokenize: tokenizeStrikethrough,
|
|
2974
|
+
resolveAll: resolveAllStrikethrough
|
|
2975
|
+
};
|
|
2976
|
+
if (single === null || single === void 0) single = true;
|
|
2977
|
+
return {
|
|
2978
|
+
text: { [126]: tokenizer },
|
|
2979
|
+
insideSpan: { null: [tokenizer] },
|
|
2980
|
+
attentionMarkers: { null: [126] }
|
|
2981
|
+
};
|
|
2982
|
+
/**
|
|
2983
|
+
* Take events and resolve strikethrough.
|
|
2984
|
+
*
|
|
2985
|
+
* @type {Resolver}
|
|
2986
|
+
*/
|
|
2987
|
+
function resolveAllStrikethrough(events, context) {
|
|
2988
|
+
let index = -1;
|
|
2989
|
+
while (++index < events.length) if (events[index][0] === "enter" && events[index][1].type === "strikethroughSequenceTemporary" && events[index][1]._close) {
|
|
2990
|
+
let open = index;
|
|
2991
|
+
while (open--) if (events[open][0] === "exit" && events[open][1].type === "strikethroughSequenceTemporary" && events[open][1]._open && events[index][1].end.offset - events[index][1].start.offset === events[open][1].end.offset - events[open][1].start.offset) {
|
|
2992
|
+
events[index][1].type = "strikethroughSequence";
|
|
2993
|
+
events[open][1].type = "strikethroughSequence";
|
|
2994
|
+
/** @type {Token} */
|
|
2995
|
+
const strikethrough = {
|
|
2996
|
+
type: "strikethrough",
|
|
2997
|
+
start: Object.assign({}, events[open][1].start),
|
|
2998
|
+
end: Object.assign({}, events[index][1].end)
|
|
2999
|
+
};
|
|
3000
|
+
/** @type {Token} */
|
|
3001
|
+
const text = {
|
|
3002
|
+
type: "strikethroughText",
|
|
3003
|
+
start: Object.assign({}, events[open][1].end),
|
|
3004
|
+
end: Object.assign({}, events[index][1].start)
|
|
3005
|
+
};
|
|
3006
|
+
/** @type {Array<Event>} */
|
|
3007
|
+
const nextEvents = [
|
|
3008
|
+
[
|
|
3009
|
+
"enter",
|
|
3010
|
+
strikethrough,
|
|
3011
|
+
context
|
|
3012
|
+
],
|
|
3013
|
+
[
|
|
3014
|
+
"enter",
|
|
3015
|
+
events[open][1],
|
|
3016
|
+
context
|
|
3017
|
+
],
|
|
3018
|
+
[
|
|
3019
|
+
"exit",
|
|
3020
|
+
events[open][1],
|
|
3021
|
+
context
|
|
3022
|
+
],
|
|
3023
|
+
[
|
|
3024
|
+
"enter",
|
|
3025
|
+
text,
|
|
3026
|
+
context
|
|
3027
|
+
]
|
|
3028
|
+
];
|
|
3029
|
+
const insideSpan = context.parser.constructs.insideSpan.null;
|
|
3030
|
+
if (insideSpan) splice(nextEvents, nextEvents.length, 0, resolveAll(insideSpan, events.slice(open + 1, index), context));
|
|
3031
|
+
splice(nextEvents, nextEvents.length, 0, [
|
|
3032
|
+
[
|
|
3033
|
+
"exit",
|
|
3034
|
+
text,
|
|
3035
|
+
context
|
|
3036
|
+
],
|
|
3037
|
+
[
|
|
3038
|
+
"enter",
|
|
3039
|
+
events[index][1],
|
|
3040
|
+
context
|
|
3041
|
+
],
|
|
3042
|
+
[
|
|
3043
|
+
"exit",
|
|
3044
|
+
events[index][1],
|
|
3045
|
+
context
|
|
3046
|
+
],
|
|
3047
|
+
[
|
|
3048
|
+
"exit",
|
|
3049
|
+
strikethrough,
|
|
3050
|
+
context
|
|
3051
|
+
]
|
|
3052
|
+
]);
|
|
3053
|
+
splice(events, open - 1, index - open + 3, nextEvents);
|
|
3054
|
+
index = open + nextEvents.length - 2;
|
|
3055
|
+
break;
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
index = -1;
|
|
3059
|
+
while (++index < events.length) if (events[index][1].type === "strikethroughSequenceTemporary") events[index][1].type = "data";
|
|
3060
|
+
return events;
|
|
3061
|
+
}
|
|
3062
|
+
/**
|
|
3063
|
+
* @this {TokenizeContext}
|
|
3064
|
+
* @type {Tokenizer}
|
|
3065
|
+
*/
|
|
3066
|
+
function tokenizeStrikethrough(effects, ok, nok) {
|
|
3067
|
+
const previous = this.previous;
|
|
3068
|
+
const events = this.events;
|
|
3069
|
+
let size = 0;
|
|
3070
|
+
return start;
|
|
3071
|
+
/** @type {State} */
|
|
3072
|
+
function start(code) {
|
|
3073
|
+
if (previous === 126 && events[events.length - 1][1].type !== "characterEscape") return nok(code);
|
|
3074
|
+
effects.enter("strikethroughSequenceTemporary");
|
|
3075
|
+
return more(code);
|
|
3076
|
+
}
|
|
3077
|
+
/** @type {State} */
|
|
3078
|
+
function more(code) {
|
|
3079
|
+
const before = classifyCharacter(previous);
|
|
3080
|
+
if (code === 126) {
|
|
3081
|
+
if (size > 1) return nok(code);
|
|
3082
|
+
effects.consume(code);
|
|
3083
|
+
size++;
|
|
3084
|
+
return more;
|
|
3085
|
+
}
|
|
3086
|
+
if (size < 2 && !single) return nok(code);
|
|
3087
|
+
const token = effects.exit("strikethroughSequenceTemporary");
|
|
3088
|
+
const after = classifyCharacter(code);
|
|
3089
|
+
token._open = !after || after === 2 && Boolean(before);
|
|
3090
|
+
token._close = !before || before === 2 && Boolean(after);
|
|
3091
|
+
return ok(code);
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
//#endregion
|
|
3096
|
+
//#region ../../../node_modules/.pnpm/micromark-extension-gfm-table@2.1.2/node_modules/micromark-extension-gfm-table/lib/edit-map.js
|
|
3097
|
+
/**
|
|
3098
|
+
* @import {Event} from 'micromark-util-types'
|
|
3099
|
+
*/
|
|
3100
|
+
/**
|
|
3101
|
+
* @typedef {[number, number, Array<Event>]} Change
|
|
3102
|
+
* @typedef {[number, number, number]} Jump
|
|
3103
|
+
*/
|
|
3104
|
+
/**
|
|
3105
|
+
* Tracks a bunch of edits.
|
|
3106
|
+
*/
|
|
3107
|
+
var EditMap = class {
|
|
3108
|
+
/**
|
|
3109
|
+
* Create a new edit map.
|
|
3110
|
+
*/
|
|
3111
|
+
constructor() {
|
|
3112
|
+
/**
|
|
3113
|
+
* Record of changes.
|
|
3114
|
+
*
|
|
3115
|
+
* @type {Array<Change>}
|
|
3116
|
+
*/
|
|
3117
|
+
this.map = [];
|
|
3118
|
+
/**
|
|
3119
|
+
* Changes by index, so `add` does not scan `map` (quadratic on
|
|
3120
|
+
* table-heavy documents).
|
|
3121
|
+
*
|
|
3122
|
+
* @type {Map<number, Change>}
|
|
3123
|
+
*/
|
|
3124
|
+
this.index = /* @__PURE__ */ new Map();
|
|
3125
|
+
}
|
|
3126
|
+
/**
|
|
3127
|
+
* Create an edit: a remove and/or add at a certain place.
|
|
3128
|
+
*
|
|
3129
|
+
* @param {number} index
|
|
3130
|
+
* Index at which to apply the edit.
|
|
3131
|
+
* @param {number} remove
|
|
3132
|
+
* Count of items to remove at the index.
|
|
3133
|
+
* @param {Array<Event>} add
|
|
3134
|
+
* Items to add at the index.
|
|
3135
|
+
* @returns {undefined}
|
|
3136
|
+
* Nothing.
|
|
3137
|
+
*/
|
|
3138
|
+
add(index, remove, add) {
|
|
3139
|
+
addImplementation(this, index, remove, add);
|
|
3140
|
+
}
|
|
3141
|
+
/**
|
|
3142
|
+
* Done, change the events.
|
|
3143
|
+
*
|
|
3144
|
+
* @param {Array<Event>} events
|
|
3145
|
+
* List of events to apply the edits to.
|
|
3146
|
+
* @returns {undefined}
|
|
3147
|
+
* Nothing.
|
|
3148
|
+
*/
|
|
3149
|
+
consume(events) {
|
|
3150
|
+
this.map.sort(function(a, b) {
|
|
3151
|
+
return a[0] - b[0];
|
|
3152
|
+
});
|
|
3153
|
+
/* c8 ignore next 3 -- `resolve` is never called without tables, so without edits. */
|
|
3154
|
+
if (this.map.length === 0) return;
|
|
3155
|
+
let index = this.map.length;
|
|
3156
|
+
/** @type {Array<Array<Event>>} */
|
|
3157
|
+
const vecs = [];
|
|
3158
|
+
while (index > 0) {
|
|
3159
|
+
index -= 1;
|
|
3160
|
+
vecs.push(events.slice(this.map[index][0] + this.map[index][1]), this.map[index][2]);
|
|
3161
|
+
events.length = this.map[index][0];
|
|
3162
|
+
}
|
|
3163
|
+
vecs.push(events.slice());
|
|
3164
|
+
events.length = 0;
|
|
3165
|
+
let slice = vecs.pop();
|
|
3166
|
+
while (slice) {
|
|
3167
|
+
for (const element of slice) events.push(element);
|
|
3168
|
+
slice = vecs.pop();
|
|
3169
|
+
}
|
|
3170
|
+
this.map.length = 0;
|
|
3171
|
+
this.index.clear();
|
|
3172
|
+
}
|
|
3173
|
+
};
|
|
3174
|
+
/**
|
|
3175
|
+
* Create an edit.
|
|
3176
|
+
*
|
|
3177
|
+
* @param {EditMap} editMap
|
|
3178
|
+
* Edit map to apply to.
|
|
3179
|
+
* @param {number} at
|
|
3180
|
+
* Index at which to apply the edit.
|
|
3181
|
+
* @param {number} remove
|
|
3182
|
+
* Count of items to remove at the index.
|
|
3183
|
+
* @param {Array<Event>} add
|
|
3184
|
+
* Items to add at the index.
|
|
3185
|
+
* @returns {undefined}
|
|
3186
|
+
* Nothing.
|
|
3187
|
+
*/
|
|
3188
|
+
function addImplementation(editMap, at, remove, add) {
|
|
3189
|
+
/* c8 ignore next 3 -- `resolve` is never called without tables, so without edits. */
|
|
3190
|
+
if (remove === 0 && add.length === 0) return;
|
|
3191
|
+
const existing = editMap.index.get(at);
|
|
3192
|
+
if (existing) {
|
|
3193
|
+
existing[1] += remove;
|
|
3194
|
+
existing[2].push(...add);
|
|
3195
|
+
return;
|
|
3196
|
+
}
|
|
3197
|
+
/** @type {Change} */
|
|
3198
|
+
const change = [
|
|
3199
|
+
at,
|
|
3200
|
+
remove,
|
|
3201
|
+
add
|
|
3202
|
+
];
|
|
3203
|
+
editMap.map.push(change);
|
|
3204
|
+
editMap.index.set(at, change);
|
|
3205
|
+
}
|
|
3206
|
+
//#endregion
|
|
3207
|
+
//#region ../../../node_modules/.pnpm/micromark-extension-gfm-table@2.1.2/node_modules/micromark-extension-gfm-table/lib/infer.js
|
|
3208
|
+
/**
|
|
3209
|
+
* @import {Event} from 'micromark-util-types'
|
|
3210
|
+
*/
|
|
3211
|
+
/**
|
|
3212
|
+
* @typedef {'center' | 'left' | 'none' | 'right'} Align
|
|
3213
|
+
*/
|
|
3214
|
+
/**
|
|
3215
|
+
* Figure out the alignment of a GFM table.
|
|
3216
|
+
*
|
|
3217
|
+
* @param {Readonly<Array<Event>>} events
|
|
3218
|
+
* List of events.
|
|
3219
|
+
* @param {number} index
|
|
3220
|
+
* Table enter event.
|
|
3221
|
+
* @returns {Array<Align>}
|
|
3222
|
+
* List of aligns.
|
|
3223
|
+
*/
|
|
3224
|
+
function gfmTableAlign(events, index) {
|
|
3225
|
+
let inDelimiterRow = false;
|
|
3226
|
+
/** @type {Array<Align>} */
|
|
3227
|
+
const align = [];
|
|
3228
|
+
while (index < events.length) {
|
|
3229
|
+
const event = events[index];
|
|
3230
|
+
if (inDelimiterRow) {
|
|
3231
|
+
if (event[0] === "enter") {
|
|
3232
|
+
if (event[1].type === "tableContent") align.push(events[index + 1][1].type === "tableDelimiterMarker" ? "left" : "none");
|
|
3233
|
+
} else if (event[1].type === "tableContent") {
|
|
3234
|
+
if (events[index - 1][1].type === "tableDelimiterMarker") {
|
|
3235
|
+
const alignIndex = align.length - 1;
|
|
3236
|
+
align[alignIndex] = align[alignIndex] === "left" ? "center" : "right";
|
|
3237
|
+
}
|
|
3238
|
+
} else if (event[1].type === "tableDelimiterRow") break;
|
|
3239
|
+
} else if (event[0] === "enter" && event[1].type === "tableDelimiterRow") inDelimiterRow = true;
|
|
3240
|
+
index += 1;
|
|
3241
|
+
}
|
|
3242
|
+
return align;
|
|
3243
|
+
}
|
|
3244
|
+
//#endregion
|
|
3245
|
+
//#region ../../../node_modules/.pnpm/micromark-extension-gfm-table@2.1.2/node_modules/micromark-extension-gfm-table/lib/syntax.js
|
|
3246
|
+
/**
|
|
3247
|
+
* @import {Event, Extension, Point, Resolver, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'
|
|
3248
|
+
*/
|
|
3249
|
+
/**
|
|
3250
|
+
* @typedef {[number, number, number, number]} Range
|
|
3251
|
+
* Cell info.
|
|
3252
|
+
*
|
|
3253
|
+
* @typedef {0 | 1 | 2 | 3} RowKind
|
|
3254
|
+
* Where we are: `1` for head row, `2` for delimiter row, `3` for body row.
|
|
3255
|
+
*/
|
|
3256
|
+
/**
|
|
3257
|
+
* Create an HTML extension for `micromark` to support GitHub tables syntax.
|
|
3258
|
+
*
|
|
3259
|
+
* @returns {Extension}
|
|
3260
|
+
* Extension for `micromark` that can be passed in `extensions` to enable GFM
|
|
3261
|
+
* table syntax.
|
|
3262
|
+
*/
|
|
3263
|
+
function gfmTable() {
|
|
3264
|
+
return { flow: { null: {
|
|
3265
|
+
name: "table",
|
|
3266
|
+
tokenize: tokenizeTable,
|
|
3267
|
+
resolveAll: resolveTable
|
|
3268
|
+
} } };
|
|
3269
|
+
}
|
|
3270
|
+
/**
|
|
3271
|
+
* Tokenizer for GFM tables.
|
|
3272
|
+
*
|
|
3273
|
+
* @this {TokenizeContext}
|
|
3274
|
+
* @type {Tokenizer}
|
|
3275
|
+
*/
|
|
3276
|
+
function tokenizeTable(effects, ok, nok) {
|
|
3277
|
+
const self = this;
|
|
3278
|
+
let size = 0;
|
|
3279
|
+
let sizeB = 0;
|
|
3280
|
+
/** @type {boolean | undefined} */
|
|
3281
|
+
let seen;
|
|
3282
|
+
return start;
|
|
3283
|
+
/**
|
|
3284
|
+
* Start of a GFM table.
|
|
3285
|
+
*
|
|
3286
|
+
* If there is a valid table row or table head before, then we try to parse
|
|
3287
|
+
* another row.
|
|
3288
|
+
* Otherwise, we try to parse a head.
|
|
3289
|
+
*
|
|
3290
|
+
* ```markdown
|
|
3291
|
+
* > | | a |
|
|
3292
|
+
* ^
|
|
3293
|
+
* | | - |
|
|
3294
|
+
* > | | b |
|
|
3295
|
+
* ^
|
|
3296
|
+
* ```
|
|
3297
|
+
* @type {State}
|
|
3298
|
+
*/
|
|
3299
|
+
function start(code) {
|
|
3300
|
+
let index = self.events.length - 1;
|
|
3301
|
+
while (index > -1) {
|
|
3302
|
+
const { type } = self.events[index][1];
|
|
3303
|
+
if (type === "lineEnding" || type === "linePrefix") index--;
|
|
3304
|
+
else break;
|
|
3305
|
+
}
|
|
3306
|
+
const tail = index > -1 ? self.events[index][1].type : null;
|
|
3307
|
+
const next = tail === "tableHead" || tail === "tableRow" ? bodyRowStart : headRowBefore;
|
|
3308
|
+
if (next === bodyRowStart && self.parser.lazy[self.now().line]) return nok(code);
|
|
3309
|
+
return next(code);
|
|
3310
|
+
}
|
|
3311
|
+
/**
|
|
3312
|
+
* Before table head row.
|
|
3313
|
+
*
|
|
3314
|
+
* ```markdown
|
|
3315
|
+
* > | | a |
|
|
3316
|
+
* ^
|
|
3317
|
+
* | | - |
|
|
3318
|
+
* | | b |
|
|
3319
|
+
* ```
|
|
3320
|
+
*
|
|
3321
|
+
* @type {State}
|
|
3322
|
+
*/
|
|
3323
|
+
function headRowBefore(code) {
|
|
3324
|
+
effects.enter("tableHead");
|
|
3325
|
+
effects.enter("tableRow");
|
|
3326
|
+
return headRowStart(code);
|
|
3327
|
+
}
|
|
3328
|
+
/**
|
|
3329
|
+
* Before table head row, after whitespace.
|
|
3330
|
+
*
|
|
3331
|
+
* ```markdown
|
|
3332
|
+
* > | | a |
|
|
3333
|
+
* ^
|
|
3334
|
+
* | | - |
|
|
3335
|
+
* | | b |
|
|
3336
|
+
* ```
|
|
3337
|
+
*
|
|
3338
|
+
* @type {State}
|
|
3339
|
+
*/
|
|
3340
|
+
function headRowStart(code) {
|
|
3341
|
+
if (code === 124) return headRowBreak(code);
|
|
3342
|
+
seen = true;
|
|
3343
|
+
sizeB += 1;
|
|
3344
|
+
return headRowBreak(code);
|
|
3345
|
+
}
|
|
3346
|
+
/**
|
|
3347
|
+
* At break in table head row.
|
|
3348
|
+
*
|
|
3349
|
+
* ```markdown
|
|
3350
|
+
* > | | a |
|
|
3351
|
+
* ^
|
|
3352
|
+
* ^
|
|
3353
|
+
* ^
|
|
3354
|
+
* | | - |
|
|
3355
|
+
* | | b |
|
|
3356
|
+
* ```
|
|
3357
|
+
*
|
|
3358
|
+
* @type {State}
|
|
3359
|
+
*/
|
|
3360
|
+
function headRowBreak(code) {
|
|
3361
|
+
if (code === null) return nok(code);
|
|
3362
|
+
if (markdownLineEnding(code)) {
|
|
3363
|
+
if (sizeB > 1) {
|
|
3364
|
+
sizeB = 0;
|
|
3365
|
+
self.interrupt = true;
|
|
3366
|
+
effects.exit("tableRow");
|
|
3367
|
+
effects.enter("lineEnding");
|
|
3368
|
+
effects.consume(code);
|
|
3369
|
+
effects.exit("lineEnding");
|
|
3370
|
+
return headDelimiterStart;
|
|
3371
|
+
}
|
|
3372
|
+
return nok(code);
|
|
3373
|
+
}
|
|
3374
|
+
if (markdownSpace(code)) return factorySpace(effects, headRowBreak, "whitespace")(code);
|
|
3375
|
+
sizeB += 1;
|
|
3376
|
+
if (seen) {
|
|
3377
|
+
seen = false;
|
|
3378
|
+
size += 1;
|
|
3379
|
+
}
|
|
3380
|
+
if (code === 124) {
|
|
3381
|
+
effects.enter("tableCellDivider");
|
|
3382
|
+
effects.consume(code);
|
|
3383
|
+
effects.exit("tableCellDivider");
|
|
3384
|
+
seen = true;
|
|
3385
|
+
return headRowBreak;
|
|
3386
|
+
}
|
|
3387
|
+
effects.enter("data");
|
|
3388
|
+
return headRowData(code);
|
|
3389
|
+
}
|
|
3390
|
+
/**
|
|
3391
|
+
* In table head row data.
|
|
3392
|
+
*
|
|
3393
|
+
* ```markdown
|
|
3394
|
+
* > | | a |
|
|
3395
|
+
* ^
|
|
3396
|
+
* | | - |
|
|
3397
|
+
* | | b |
|
|
3398
|
+
* ```
|
|
3399
|
+
*
|
|
3400
|
+
* @type {State}
|
|
3401
|
+
*/
|
|
3402
|
+
function headRowData(code) {
|
|
3403
|
+
if (code === null || code === 124 || markdownLineEndingOrSpace(code)) {
|
|
3404
|
+
effects.exit("data");
|
|
3405
|
+
return headRowBreak(code);
|
|
3406
|
+
}
|
|
3407
|
+
effects.consume(code);
|
|
3408
|
+
return code === 92 ? headRowEscape : headRowData;
|
|
3409
|
+
}
|
|
3410
|
+
/**
|
|
3411
|
+
* In table head row escape.
|
|
3412
|
+
*
|
|
3413
|
+
* ```markdown
|
|
3414
|
+
* > | | a\-b |
|
|
3415
|
+
* ^
|
|
3416
|
+
* | | ---- |
|
|
3417
|
+
* | | c |
|
|
3418
|
+
* ```
|
|
3419
|
+
*
|
|
3420
|
+
* @type {State}
|
|
3421
|
+
*/
|
|
3422
|
+
function headRowEscape(code) {
|
|
3423
|
+
if (code === 92 || code === 124) {
|
|
3424
|
+
effects.consume(code);
|
|
3425
|
+
return headRowData;
|
|
3426
|
+
}
|
|
3427
|
+
return headRowData(code);
|
|
3428
|
+
}
|
|
3429
|
+
/**
|
|
3430
|
+
* Before delimiter row.
|
|
3431
|
+
*
|
|
3432
|
+
* ```markdown
|
|
3433
|
+
* | | a |
|
|
3434
|
+
* > | | - |
|
|
3435
|
+
* ^
|
|
3436
|
+
* | | b |
|
|
3437
|
+
* ```
|
|
3438
|
+
*
|
|
3439
|
+
* @type {State}
|
|
3440
|
+
*/
|
|
3441
|
+
function headDelimiterStart(code) {
|
|
3442
|
+
self.interrupt = false;
|
|
3443
|
+
if (self.parser.lazy[self.now().line]) return nok(code);
|
|
3444
|
+
effects.enter("tableDelimiterRow");
|
|
3445
|
+
seen = false;
|
|
3446
|
+
if (markdownSpace(code)) return factorySpace(effects, headDelimiterBefore, "linePrefix", self.parser.constructs.disable.null.includes("codeIndented") ? void 0 : 4)(code);
|
|
3447
|
+
return headDelimiterBefore(code);
|
|
3448
|
+
}
|
|
3449
|
+
/**
|
|
3450
|
+
* Before delimiter row, after optional whitespace.
|
|
3451
|
+
*
|
|
3452
|
+
* Reused when a `|` is found later, to parse another cell.
|
|
3453
|
+
*
|
|
3454
|
+
* ```markdown
|
|
3455
|
+
* | | a |
|
|
3456
|
+
* > | | - |
|
|
3457
|
+
* ^
|
|
3458
|
+
* | | b |
|
|
3459
|
+
* ```
|
|
3460
|
+
*
|
|
3461
|
+
* @type {State}
|
|
3462
|
+
*/
|
|
3463
|
+
function headDelimiterBefore(code) {
|
|
3464
|
+
if (code === 45 || code === 58) return headDelimiterValueBefore(code);
|
|
3465
|
+
if (code === 124) {
|
|
3466
|
+
seen = true;
|
|
3467
|
+
effects.enter("tableCellDivider");
|
|
3468
|
+
effects.consume(code);
|
|
3469
|
+
effects.exit("tableCellDivider");
|
|
3470
|
+
return headDelimiterCellBefore;
|
|
3471
|
+
}
|
|
3472
|
+
return headDelimiterNok(code);
|
|
3473
|
+
}
|
|
3474
|
+
/**
|
|
3475
|
+
* After `|`, before delimiter cell.
|
|
3476
|
+
*
|
|
3477
|
+
* ```markdown
|
|
3478
|
+
* | | a |
|
|
3479
|
+
* > | | - |
|
|
3480
|
+
* ^
|
|
3481
|
+
* ```
|
|
3482
|
+
*
|
|
3483
|
+
* @type {State}
|
|
3484
|
+
*/
|
|
3485
|
+
function headDelimiterCellBefore(code) {
|
|
3486
|
+
if (markdownSpace(code)) return factorySpace(effects, headDelimiterValueBefore, "whitespace")(code);
|
|
3487
|
+
return headDelimiterValueBefore(code);
|
|
3488
|
+
}
|
|
3489
|
+
/**
|
|
3490
|
+
* Before delimiter cell value.
|
|
3491
|
+
*
|
|
3492
|
+
* ```markdown
|
|
3493
|
+
* | | a |
|
|
3494
|
+
* > | | - |
|
|
3495
|
+
* ^
|
|
3496
|
+
* ```
|
|
3497
|
+
*
|
|
3498
|
+
* @type {State}
|
|
3499
|
+
*/
|
|
3500
|
+
function headDelimiterValueBefore(code) {
|
|
3501
|
+
if (code === 58) {
|
|
3502
|
+
sizeB += 1;
|
|
3503
|
+
seen = true;
|
|
3504
|
+
effects.enter("tableDelimiterMarker");
|
|
3505
|
+
effects.consume(code);
|
|
3506
|
+
effects.exit("tableDelimiterMarker");
|
|
3507
|
+
return headDelimiterLeftAlignmentAfter;
|
|
3508
|
+
}
|
|
3509
|
+
if (code === 45) {
|
|
3510
|
+
sizeB += 1;
|
|
3511
|
+
return headDelimiterLeftAlignmentAfter(code);
|
|
3512
|
+
}
|
|
3513
|
+
if (code === null || markdownLineEnding(code)) return headDelimiterCellAfter(code);
|
|
3514
|
+
return headDelimiterNok(code);
|
|
3515
|
+
}
|
|
3516
|
+
/**
|
|
3517
|
+
* After delimiter cell left alignment marker.
|
|
3518
|
+
*
|
|
3519
|
+
* ```markdown
|
|
3520
|
+
* | | a |
|
|
3521
|
+
* > | | :- |
|
|
3522
|
+
* ^
|
|
3523
|
+
* ```
|
|
3524
|
+
*
|
|
3525
|
+
* @type {State}
|
|
3526
|
+
*/
|
|
3527
|
+
function headDelimiterLeftAlignmentAfter(code) {
|
|
3528
|
+
if (code === 45) {
|
|
3529
|
+
effects.enter("tableDelimiterFiller");
|
|
3530
|
+
return headDelimiterFiller(code);
|
|
3531
|
+
}
|
|
3532
|
+
return headDelimiterNok(code);
|
|
3533
|
+
}
|
|
3534
|
+
/**
|
|
3535
|
+
* In delimiter cell filler.
|
|
3536
|
+
*
|
|
3537
|
+
* ```markdown
|
|
3538
|
+
* | | a |
|
|
3539
|
+
* > | | - |
|
|
3540
|
+
* ^
|
|
3541
|
+
* ```
|
|
3542
|
+
*
|
|
3543
|
+
* @type {State}
|
|
3544
|
+
*/
|
|
3545
|
+
function headDelimiterFiller(code) {
|
|
3546
|
+
if (code === 45) {
|
|
3547
|
+
effects.consume(code);
|
|
3548
|
+
return headDelimiterFiller;
|
|
3549
|
+
}
|
|
3550
|
+
if (code === 58) {
|
|
3551
|
+
seen = true;
|
|
3552
|
+
effects.exit("tableDelimiterFiller");
|
|
3553
|
+
effects.enter("tableDelimiterMarker");
|
|
3554
|
+
effects.consume(code);
|
|
3555
|
+
effects.exit("tableDelimiterMarker");
|
|
3556
|
+
return headDelimiterRightAlignmentAfter;
|
|
3557
|
+
}
|
|
3558
|
+
effects.exit("tableDelimiterFiller");
|
|
3559
|
+
return headDelimiterRightAlignmentAfter(code);
|
|
3560
|
+
}
|
|
3561
|
+
/**
|
|
3562
|
+
* After delimiter cell right alignment marker.
|
|
3563
|
+
*
|
|
3564
|
+
* ```markdown
|
|
3565
|
+
* | | a |
|
|
3566
|
+
* > | | -: |
|
|
3567
|
+
* ^
|
|
3568
|
+
* ```
|
|
3569
|
+
*
|
|
3570
|
+
* @type {State}
|
|
3571
|
+
*/
|
|
3572
|
+
function headDelimiterRightAlignmentAfter(code) {
|
|
3573
|
+
if (markdownSpace(code)) return factorySpace(effects, headDelimiterCellAfter, "whitespace")(code);
|
|
3574
|
+
return headDelimiterCellAfter(code);
|
|
3575
|
+
}
|
|
3576
|
+
/**
|
|
3577
|
+
* After delimiter cell.
|
|
3578
|
+
*
|
|
3579
|
+
* ```markdown
|
|
3580
|
+
* | | a |
|
|
3581
|
+
* > | | -: |
|
|
3582
|
+
* ^
|
|
3583
|
+
* ```
|
|
3584
|
+
*
|
|
3585
|
+
* @type {State}
|
|
3586
|
+
*/
|
|
3587
|
+
function headDelimiterCellAfter(code) {
|
|
3588
|
+
if (code === 124) return headDelimiterBefore(code);
|
|
3589
|
+
if (code === null || markdownLineEnding(code)) {
|
|
3590
|
+
if (!seen || size !== sizeB) return headDelimiterNok(code);
|
|
3591
|
+
effects.exit("tableDelimiterRow");
|
|
3592
|
+
effects.exit("tableHead");
|
|
3593
|
+
return ok(code);
|
|
3594
|
+
}
|
|
3595
|
+
return headDelimiterNok(code);
|
|
3596
|
+
}
|
|
3597
|
+
/**
|
|
3598
|
+
* In delimiter row, at a disallowed byte.
|
|
3599
|
+
*
|
|
3600
|
+
* ```markdown
|
|
3601
|
+
* | | a |
|
|
3602
|
+
* > | | x |
|
|
3603
|
+
* ^
|
|
3604
|
+
* ```
|
|
3605
|
+
*
|
|
3606
|
+
* @type {State}
|
|
3607
|
+
*/
|
|
3608
|
+
function headDelimiterNok(code) {
|
|
3609
|
+
return nok(code);
|
|
3610
|
+
}
|
|
3611
|
+
/**
|
|
3612
|
+
* Before table body row.
|
|
3613
|
+
*
|
|
3614
|
+
* ```markdown
|
|
3615
|
+
* | | a |
|
|
3616
|
+
* | | - |
|
|
3617
|
+
* > | | b |
|
|
3618
|
+
* ^
|
|
3619
|
+
* ```
|
|
3620
|
+
*
|
|
3621
|
+
* @type {State}
|
|
3622
|
+
*/
|
|
3623
|
+
function bodyRowStart(code) {
|
|
3624
|
+
effects.enter("tableRow");
|
|
3625
|
+
return bodyRowBreak(code);
|
|
3626
|
+
}
|
|
3627
|
+
/**
|
|
3628
|
+
* At break in table body row.
|
|
3629
|
+
*
|
|
3630
|
+
* ```markdown
|
|
3631
|
+
* | | a |
|
|
3632
|
+
* | | - |
|
|
3633
|
+
* > | | b |
|
|
3634
|
+
* ^
|
|
3635
|
+
* ^
|
|
3636
|
+
* ^
|
|
3637
|
+
* ```
|
|
3638
|
+
*
|
|
3639
|
+
* @type {State}
|
|
3640
|
+
*/
|
|
3641
|
+
function bodyRowBreak(code) {
|
|
3642
|
+
if (code === 124) {
|
|
3643
|
+
effects.enter("tableCellDivider");
|
|
3644
|
+
effects.consume(code);
|
|
3645
|
+
effects.exit("tableCellDivider");
|
|
3646
|
+
return bodyRowBreak;
|
|
3647
|
+
}
|
|
3648
|
+
if (code === null || markdownLineEnding(code)) {
|
|
3649
|
+
effects.exit("tableRow");
|
|
3650
|
+
return ok(code);
|
|
3651
|
+
}
|
|
3652
|
+
if (markdownSpace(code)) return factorySpace(effects, bodyRowBreak, "whitespace")(code);
|
|
3653
|
+
effects.enter("data");
|
|
3654
|
+
return bodyRowData(code);
|
|
3655
|
+
}
|
|
3656
|
+
/**
|
|
3657
|
+
* In table body row data.
|
|
3658
|
+
*
|
|
3659
|
+
* ```markdown
|
|
3660
|
+
* | | a |
|
|
3661
|
+
* | | - |
|
|
3662
|
+
* > | | b |
|
|
3663
|
+
* ^
|
|
3664
|
+
* ```
|
|
3665
|
+
*
|
|
3666
|
+
* @type {State}
|
|
3667
|
+
*/
|
|
3668
|
+
function bodyRowData(code) {
|
|
3669
|
+
if (code === null || code === 124 || markdownLineEndingOrSpace(code)) {
|
|
3670
|
+
effects.exit("data");
|
|
3671
|
+
return bodyRowBreak(code);
|
|
3672
|
+
}
|
|
3673
|
+
effects.consume(code);
|
|
3674
|
+
return code === 92 ? bodyRowEscape : bodyRowData;
|
|
3675
|
+
}
|
|
3676
|
+
/**
|
|
3677
|
+
* In table body row escape.
|
|
3678
|
+
*
|
|
3679
|
+
* ```markdown
|
|
3680
|
+
* | | a |
|
|
3681
|
+
* | | ---- |
|
|
3682
|
+
* > | | b\-c |
|
|
3683
|
+
* ^
|
|
3684
|
+
* ```
|
|
3685
|
+
*
|
|
3686
|
+
* @type {State}
|
|
3687
|
+
*/
|
|
3688
|
+
function bodyRowEscape(code) {
|
|
3689
|
+
if (code === 92 || code === 124) {
|
|
3690
|
+
effects.consume(code);
|
|
3691
|
+
return bodyRowData;
|
|
3692
|
+
}
|
|
3693
|
+
return bodyRowData(code);
|
|
3694
|
+
}
|
|
3695
|
+
}
|
|
3696
|
+
/** @type {Resolver} */
|
|
3697
|
+
function resolveTable(events, context) {
|
|
3698
|
+
let index = -1;
|
|
3699
|
+
let inFirstCellAwaitingPipe = true;
|
|
3700
|
+
/** @type {RowKind} */
|
|
3701
|
+
let rowKind = 0;
|
|
3702
|
+
/** @type {Range} */
|
|
3703
|
+
let lastCell = [
|
|
3704
|
+
0,
|
|
3705
|
+
0,
|
|
3706
|
+
0,
|
|
3707
|
+
0
|
|
3708
|
+
];
|
|
3709
|
+
/** @type {Range} */
|
|
3710
|
+
let cell = [
|
|
3711
|
+
0,
|
|
3712
|
+
0,
|
|
3713
|
+
0,
|
|
3714
|
+
0
|
|
3715
|
+
];
|
|
3716
|
+
let afterHeadAwaitingFirstBodyRow = false;
|
|
3717
|
+
let lastTableEnd = 0;
|
|
3718
|
+
/** @type {Token | undefined} */
|
|
3719
|
+
let currentTable;
|
|
3720
|
+
/** @type {Token | undefined} */
|
|
3721
|
+
let currentBody;
|
|
3722
|
+
/** @type {Token | undefined} */
|
|
3723
|
+
let currentCell;
|
|
3724
|
+
const map = new EditMap();
|
|
3725
|
+
while (++index < events.length) {
|
|
3726
|
+
const event = events[index];
|
|
3727
|
+
const token = event[1];
|
|
3728
|
+
if (event[0] === "enter") {
|
|
3729
|
+
if (token.type === "tableHead") {
|
|
3730
|
+
afterHeadAwaitingFirstBodyRow = false;
|
|
3731
|
+
if (lastTableEnd !== 0) {
|
|
3732
|
+
flushTableEnd(map, context, lastTableEnd, currentTable, currentBody);
|
|
3733
|
+
currentBody = void 0;
|
|
3734
|
+
lastTableEnd = 0;
|
|
3735
|
+
}
|
|
3736
|
+
currentTable = {
|
|
3737
|
+
type: "table",
|
|
3738
|
+
start: Object.assign({}, token.start),
|
|
3739
|
+
end: Object.assign({}, token.end)
|
|
3740
|
+
};
|
|
3741
|
+
map.add(index, 0, [[
|
|
3742
|
+
"enter",
|
|
3743
|
+
currentTable,
|
|
3744
|
+
context
|
|
3745
|
+
]]);
|
|
3746
|
+
} else if (token.type === "tableRow" || token.type === "tableDelimiterRow") {
|
|
3747
|
+
inFirstCellAwaitingPipe = true;
|
|
3748
|
+
currentCell = void 0;
|
|
3749
|
+
lastCell = [
|
|
3750
|
+
0,
|
|
3751
|
+
0,
|
|
3752
|
+
0,
|
|
3753
|
+
0
|
|
3754
|
+
];
|
|
3755
|
+
cell = [
|
|
3756
|
+
0,
|
|
3757
|
+
index + 1,
|
|
3758
|
+
0,
|
|
3759
|
+
0
|
|
3760
|
+
];
|
|
3761
|
+
if (afterHeadAwaitingFirstBodyRow) {
|
|
3762
|
+
afterHeadAwaitingFirstBodyRow = false;
|
|
3763
|
+
currentBody = {
|
|
3764
|
+
type: "tableBody",
|
|
3765
|
+
start: Object.assign({}, token.start),
|
|
3766
|
+
end: Object.assign({}, token.end)
|
|
3767
|
+
};
|
|
3768
|
+
map.add(index, 0, [[
|
|
3769
|
+
"enter",
|
|
3770
|
+
currentBody,
|
|
3771
|
+
context
|
|
3772
|
+
]]);
|
|
3773
|
+
}
|
|
3774
|
+
rowKind = token.type === "tableDelimiterRow" ? 2 : currentBody ? 3 : 1;
|
|
3775
|
+
} else if (rowKind && (token.type === "data" || token.type === "tableDelimiterMarker" || token.type === "tableDelimiterFiller")) {
|
|
3776
|
+
inFirstCellAwaitingPipe = false;
|
|
3777
|
+
if (cell[2] === 0) {
|
|
3778
|
+
if (lastCell[1] !== 0) {
|
|
3779
|
+
cell[0] = cell[1];
|
|
3780
|
+
currentCell = flushCell(map, context, lastCell, rowKind, void 0, currentCell);
|
|
3781
|
+
lastCell = [
|
|
3782
|
+
0,
|
|
3783
|
+
0,
|
|
3784
|
+
0,
|
|
3785
|
+
0
|
|
3786
|
+
];
|
|
3787
|
+
}
|
|
3788
|
+
cell[2] = index;
|
|
3789
|
+
}
|
|
3790
|
+
} else if (token.type === "tableCellDivider") {
|
|
3791
|
+
if (inFirstCellAwaitingPipe) inFirstCellAwaitingPipe = false;
|
|
3792
|
+
else {
|
|
3793
|
+
if (lastCell[1] !== 0) {
|
|
3794
|
+
cell[0] = cell[1];
|
|
3795
|
+
currentCell = flushCell(map, context, lastCell, rowKind, void 0, currentCell);
|
|
3796
|
+
}
|
|
3797
|
+
lastCell = cell;
|
|
3798
|
+
cell = [
|
|
3799
|
+
lastCell[1],
|
|
3800
|
+
index,
|
|
3801
|
+
0,
|
|
3802
|
+
0
|
|
3803
|
+
];
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
} else if (token.type === "tableHead") {
|
|
3807
|
+
afterHeadAwaitingFirstBodyRow = true;
|
|
3808
|
+
lastTableEnd = index;
|
|
3809
|
+
} else if (token.type === "tableRow" || token.type === "tableDelimiterRow") {
|
|
3810
|
+
lastTableEnd = index;
|
|
3811
|
+
if (lastCell[1] !== 0) {
|
|
3812
|
+
cell[0] = cell[1];
|
|
3813
|
+
currentCell = flushCell(map, context, lastCell, rowKind, index, currentCell);
|
|
3814
|
+
} else if (cell[1] !== 0) currentCell = flushCell(map, context, cell, rowKind, index, currentCell);
|
|
3815
|
+
rowKind = 0;
|
|
3816
|
+
} else if (rowKind && (token.type === "data" || token.type === "tableDelimiterMarker" || token.type === "tableDelimiterFiller")) cell[3] = index;
|
|
3817
|
+
}
|
|
3818
|
+
if (lastTableEnd !== 0) flushTableEnd(map, context, lastTableEnd, currentTable, currentBody);
|
|
3819
|
+
map.consume(context.events);
|
|
3820
|
+
index = -1;
|
|
3821
|
+
while (++index < context.events.length) {
|
|
3822
|
+
const event = context.events[index];
|
|
3823
|
+
if (event[0] === "enter" && event[1].type === "table") event[1]._align = gfmTableAlign(context.events, index);
|
|
3824
|
+
}
|
|
3825
|
+
return events;
|
|
3826
|
+
}
|
|
3827
|
+
/**
|
|
3828
|
+
* Generate a cell.
|
|
3829
|
+
*
|
|
3830
|
+
* @param {EditMap} map
|
|
3831
|
+
* Edit map to apply to.
|
|
3832
|
+
* @param {Readonly<TokenizeContext>} context
|
|
3833
|
+
* Tokenize context.
|
|
3834
|
+
* @param {Readonly<Range>} range
|
|
3835
|
+
* Range of the cell within events.
|
|
3836
|
+
* @param {RowKind} rowKind
|
|
3837
|
+
* Type of row.
|
|
3838
|
+
* @param {number | undefined} rowEnd
|
|
3839
|
+
* Index of the end of the row, if known.
|
|
3840
|
+
* @param {Token | undefined} previousCell
|
|
3841
|
+
* Previous cell token, if any.
|
|
3842
|
+
* @returns {Token | undefined}
|
|
3843
|
+
* Current cell token after flushing, if any.
|
|
3844
|
+
*/
|
|
3845
|
+
function flushCell(map, context, range, rowKind, rowEnd, previousCell) {
|
|
3846
|
+
const groupName = rowKind === 1 ? "tableHeader" : rowKind === 2 ? "tableDelimiter" : "tableData";
|
|
3847
|
+
const valueName = "tableContent";
|
|
3848
|
+
if (range[0] !== 0) {
|
|
3849
|
+
previousCell.end = Object.assign({}, getPoint(context.events, range[0]));
|
|
3850
|
+
map.add(range[0], 0, [[
|
|
3851
|
+
"exit",
|
|
3852
|
+
previousCell,
|
|
3853
|
+
context
|
|
3854
|
+
]]);
|
|
3855
|
+
}
|
|
3856
|
+
const now = getPoint(context.events, range[1]);
|
|
3857
|
+
previousCell = {
|
|
3858
|
+
type: groupName,
|
|
3859
|
+
start: Object.assign({}, now),
|
|
3860
|
+
end: Object.assign({}, now)
|
|
3861
|
+
};
|
|
3862
|
+
map.add(range[1], 0, [[
|
|
3863
|
+
"enter",
|
|
3864
|
+
previousCell,
|
|
3865
|
+
context
|
|
3866
|
+
]]);
|
|
3867
|
+
if (range[2] !== 0) {
|
|
3868
|
+
const relatedStart = getPoint(context.events, range[2]);
|
|
3869
|
+
const relatedEnd = getPoint(context.events, range[3]);
|
|
3870
|
+
/** @type {Token} */
|
|
3871
|
+
const valueToken = {
|
|
3872
|
+
type: valueName,
|
|
3873
|
+
start: Object.assign({}, relatedStart),
|
|
3874
|
+
end: Object.assign({}, relatedEnd)
|
|
3875
|
+
};
|
|
3876
|
+
map.add(range[2], 0, [[
|
|
3877
|
+
"enter",
|
|
3878
|
+
valueToken,
|
|
3879
|
+
context
|
|
3880
|
+
]]);
|
|
3881
|
+
if (rowKind !== 2) {
|
|
3882
|
+
const start = context.events[range[2]];
|
|
3883
|
+
const end = context.events[range[3]];
|
|
3884
|
+
start[1].end = Object.assign({}, end[1].end);
|
|
3885
|
+
start[1].type = "chunkText";
|
|
3886
|
+
start[1].contentType = "text";
|
|
3887
|
+
if (range[3] > range[2] + 1) {
|
|
3888
|
+
const a = range[2] + 1;
|
|
3889
|
+
const b = range[3] - range[2] - 1;
|
|
3890
|
+
map.add(a, b, []);
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
map.add(range[3] + 1, 0, [[
|
|
3894
|
+
"exit",
|
|
3895
|
+
valueToken,
|
|
3896
|
+
context
|
|
3897
|
+
]]);
|
|
3898
|
+
}
|
|
3899
|
+
if (rowEnd !== void 0) {
|
|
3900
|
+
previousCell.end = Object.assign({}, getPoint(context.events, rowEnd));
|
|
3901
|
+
map.add(rowEnd, 0, [[
|
|
3902
|
+
"exit",
|
|
3903
|
+
previousCell,
|
|
3904
|
+
context
|
|
3905
|
+
]]);
|
|
3906
|
+
previousCell = void 0;
|
|
3907
|
+
}
|
|
3908
|
+
return previousCell;
|
|
3909
|
+
}
|
|
3910
|
+
/**
|
|
3911
|
+
* Generate table end (and table body end).
|
|
3912
|
+
*
|
|
3913
|
+
* @param {Readonly<EditMap>} map
|
|
3914
|
+
* Edit map to apply to.
|
|
3915
|
+
* @param {Readonly<TokenizeContext>} context
|
|
3916
|
+
* Tokenize context.
|
|
3917
|
+
* @param {number} index
|
|
3918
|
+
* Index within the events where the table end should be inserted.
|
|
3919
|
+
* @param {Token} table
|
|
3920
|
+
* Table token.
|
|
3921
|
+
* @param {Token | undefined} tableBody
|
|
3922
|
+
* Table body token, if any.
|
|
3923
|
+
* @returns {undefined}
|
|
3924
|
+
* Nothing.
|
|
3925
|
+
*/
|
|
3926
|
+
function flushTableEnd(map, context, index, table, tableBody) {
|
|
3927
|
+
/** @type {Array<Event>} */
|
|
3928
|
+
const exits = [];
|
|
3929
|
+
const related = getPoint(context.events, index);
|
|
3930
|
+
if (tableBody) {
|
|
3931
|
+
tableBody.end = Object.assign({}, related);
|
|
3932
|
+
exits.push([
|
|
3933
|
+
"exit",
|
|
3934
|
+
tableBody,
|
|
3935
|
+
context
|
|
3936
|
+
]);
|
|
3937
|
+
}
|
|
3938
|
+
table.end = Object.assign({}, related);
|
|
3939
|
+
exits.push([
|
|
3940
|
+
"exit",
|
|
3941
|
+
table,
|
|
3942
|
+
context
|
|
3943
|
+
]);
|
|
3944
|
+
map.add(index + 1, 0, exits);
|
|
3945
|
+
}
|
|
3946
|
+
/**
|
|
3947
|
+
* Get the point (start or end) for a given event in the list of events.
|
|
3948
|
+
*
|
|
3949
|
+
* @param {Readonly<Array<Event>>} events
|
|
3950
|
+
* List of events.
|
|
3951
|
+
* @param {number} index
|
|
3952
|
+
* Index of the event to get the point for.
|
|
3953
|
+
* @returns {Readonly<Point>}
|
|
3954
|
+
* Start point for enter and end point for exit.
|
|
3955
|
+
*/
|
|
3956
|
+
function getPoint(events, index) {
|
|
3957
|
+
const event = events[index];
|
|
3958
|
+
const side = event[0] === "enter" ? "start" : "end";
|
|
3959
|
+
return event[1][side];
|
|
3960
|
+
}
|
|
3961
|
+
//#endregion
|
|
3962
|
+
//#region ../../../node_modules/.pnpm/micromark-extension-gfm-task-list-item@2.1.0/node_modules/micromark-extension-gfm-task-list-item/lib/syntax.js
|
|
3963
|
+
/**
|
|
3964
|
+
* @import {Extension, State, TokenizeContext, Tokenizer} from 'micromark-util-types'
|
|
3965
|
+
*/
|
|
3966
|
+
const tasklistCheck = {
|
|
3967
|
+
name: "tasklistCheck",
|
|
3968
|
+
tokenize: tokenizeTasklistCheck
|
|
3969
|
+
};
|
|
3970
|
+
/**
|
|
3971
|
+
* Create an HTML extension for `micromark` to support GFM task list items
|
|
3972
|
+
* syntax.
|
|
3973
|
+
*
|
|
3974
|
+
* @returns {Extension}
|
|
3975
|
+
* Extension for `micromark` that can be passed in `htmlExtensions` to
|
|
3976
|
+
* support GFM task list items when serializing to HTML.
|
|
3977
|
+
*/
|
|
3978
|
+
function gfmTaskListItem() {
|
|
3979
|
+
return { text: { [91]: tasklistCheck } };
|
|
3980
|
+
}
|
|
3981
|
+
/**
|
|
3982
|
+
* @this {TokenizeContext}
|
|
3983
|
+
* @type {Tokenizer}
|
|
3984
|
+
*/
|
|
3985
|
+
function tokenizeTasklistCheck(effects, ok, nok) {
|
|
3986
|
+
const self = this;
|
|
3987
|
+
return open;
|
|
3988
|
+
/**
|
|
3989
|
+
* At start of task list item check.
|
|
3990
|
+
*
|
|
3991
|
+
* ```markdown
|
|
3992
|
+
* > | * [x] y.
|
|
3993
|
+
* ^
|
|
3994
|
+
* ```
|
|
3995
|
+
*
|
|
3996
|
+
* @type {State}
|
|
3997
|
+
*/
|
|
3998
|
+
function open(code) {
|
|
3999
|
+
if (self.previous !== null || !self._gfmTasklistFirstContentOfListItem) return nok(code);
|
|
4000
|
+
effects.enter("taskListCheck");
|
|
4001
|
+
effects.enter("taskListCheckMarker");
|
|
4002
|
+
effects.consume(code);
|
|
4003
|
+
effects.exit("taskListCheckMarker");
|
|
4004
|
+
return inside;
|
|
4005
|
+
}
|
|
4006
|
+
/**
|
|
4007
|
+
* In task list item check.
|
|
4008
|
+
*
|
|
4009
|
+
* ```markdown
|
|
4010
|
+
* > | * [x] y.
|
|
4011
|
+
* ^
|
|
4012
|
+
* ```
|
|
4013
|
+
*
|
|
4014
|
+
* @type {State}
|
|
4015
|
+
*/
|
|
4016
|
+
function inside(code) {
|
|
4017
|
+
if (markdownLineEndingOrSpace(code)) {
|
|
4018
|
+
effects.enter("taskListCheckValueUnchecked");
|
|
4019
|
+
effects.consume(code);
|
|
4020
|
+
effects.exit("taskListCheckValueUnchecked");
|
|
4021
|
+
return close;
|
|
4022
|
+
}
|
|
4023
|
+
if (code === 88 || code === 120) {
|
|
4024
|
+
effects.enter("taskListCheckValueChecked");
|
|
4025
|
+
effects.consume(code);
|
|
4026
|
+
effects.exit("taskListCheckValueChecked");
|
|
4027
|
+
return close;
|
|
4028
|
+
}
|
|
4029
|
+
return nok(code);
|
|
4030
|
+
}
|
|
4031
|
+
/**
|
|
4032
|
+
* At close of task list item check.
|
|
4033
|
+
*
|
|
4034
|
+
* ```markdown
|
|
4035
|
+
* > | * [x] y.
|
|
4036
|
+
* ^
|
|
4037
|
+
* ```
|
|
4038
|
+
*
|
|
4039
|
+
* @type {State}
|
|
4040
|
+
*/
|
|
4041
|
+
function close(code) {
|
|
4042
|
+
if (code === 93) {
|
|
4043
|
+
effects.enter("taskListCheckMarker");
|
|
4044
|
+
effects.consume(code);
|
|
4045
|
+
effects.exit("taskListCheckMarker");
|
|
4046
|
+
effects.exit("taskListCheck");
|
|
4047
|
+
return after;
|
|
4048
|
+
}
|
|
4049
|
+
return nok(code);
|
|
4050
|
+
}
|
|
4051
|
+
/**
|
|
4052
|
+
* @type {State}
|
|
4053
|
+
*/
|
|
4054
|
+
function after(code) {
|
|
4055
|
+
if (markdownLineEnding(code)) return ok(code);
|
|
4056
|
+
if (markdownSpace(code)) return effects.check({ tokenize: spaceThenNonSpace }, ok, nok)(code);
|
|
4057
|
+
return nok(code);
|
|
4058
|
+
}
|
|
4059
|
+
}
|
|
4060
|
+
/**
|
|
4061
|
+
* @this {TokenizeContext}
|
|
4062
|
+
* @type {Tokenizer}
|
|
4063
|
+
*/
|
|
4064
|
+
function spaceThenNonSpace(effects, ok, nok) {
|
|
4065
|
+
return factorySpace(effects, after, "whitespace");
|
|
4066
|
+
/**
|
|
4067
|
+
* After whitespace, after task list item check.
|
|
4068
|
+
*
|
|
4069
|
+
* ```markdown
|
|
4070
|
+
* > | * [x] y.
|
|
4071
|
+
* ^
|
|
4072
|
+
* ```
|
|
4073
|
+
*
|
|
4074
|
+
* @type {State}
|
|
4075
|
+
*/
|
|
4076
|
+
function after(code) {
|
|
4077
|
+
return code === null ? nok(code) : ok(code);
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
//#endregion
|
|
4081
|
+
//#region ../../../node_modules/.pnpm/micromark-extension-gfm@3.0.0/node_modules/micromark-extension-gfm/index.js
|
|
4082
|
+
/**
|
|
4083
|
+
* @typedef {import('micromark-extension-gfm-footnote').HtmlOptions} HtmlOptions
|
|
4084
|
+
* @typedef {import('micromark-extension-gfm-strikethrough').Options} Options
|
|
4085
|
+
* @typedef {import('micromark-util-types').Extension} Extension
|
|
4086
|
+
* @typedef {import('micromark-util-types').HtmlExtension} HtmlExtension
|
|
4087
|
+
*/
|
|
4088
|
+
/**
|
|
4089
|
+
* Create an extension for `micromark` to enable GFM syntax.
|
|
4090
|
+
*
|
|
4091
|
+
* @param {Options | null | undefined} [options]
|
|
4092
|
+
* Configuration (optional).
|
|
4093
|
+
*
|
|
4094
|
+
* Passed to `micromark-extens-gfm-strikethrough`.
|
|
4095
|
+
* @returns {Extension}
|
|
4096
|
+
* Extension for `micromark` that can be passed in `extensions` to enable GFM
|
|
4097
|
+
* syntax.
|
|
4098
|
+
*/
|
|
4099
|
+
function gfm(options) {
|
|
4100
|
+
return combineExtensions([
|
|
4101
|
+
gfmAutolinkLiteral(),
|
|
4102
|
+
gfmFootnote(),
|
|
4103
|
+
gfmStrikethrough(options),
|
|
4104
|
+
gfmTable(),
|
|
4105
|
+
gfmTaskListItem()
|
|
4106
|
+
]);
|
|
4107
|
+
}
|
|
4108
|
+
//#endregion
|
|
4109
|
+
//#region ../../../node_modules/.pnpm/micromark-util-symbol@2.0.1/node_modules/micromark-util-symbol/lib/codes.js
|
|
4110
|
+
/**
|
|
4111
|
+
* Character codes.
|
|
4112
|
+
*
|
|
4113
|
+
* This module is compiled away!
|
|
4114
|
+
*
|
|
4115
|
+
* micromark works based on character codes.
|
|
4116
|
+
* This module contains constants for the ASCII block and the replacement
|
|
4117
|
+
* character.
|
|
4118
|
+
* A couple of them are handled in a special way, such as the line endings
|
|
4119
|
+
* (CR, LF, and CR+LF, commonly known as end-of-line: EOLs), the tab (horizontal
|
|
4120
|
+
* tab) and its expansion based on what column it’s at (virtual space),
|
|
4121
|
+
* and the end-of-file (eof) character.
|
|
4122
|
+
* As values are preprocessed before handling them, the actual characters LF,
|
|
4123
|
+
* CR, HT, and NUL (which is present as the replacement character), are
|
|
4124
|
+
* guaranteed to not exist.
|
|
4125
|
+
*
|
|
4126
|
+
* Unicode basic latin block.
|
|
4127
|
+
*/
|
|
4128
|
+
const codes = {
|
|
4129
|
+
carriageReturn: -5,
|
|
4130
|
+
lineFeed: -4,
|
|
4131
|
+
carriageReturnLineFeed: -3,
|
|
4132
|
+
horizontalTab: -2,
|
|
4133
|
+
virtualSpace: -1,
|
|
4134
|
+
eof: null,
|
|
4135
|
+
nul: 0,
|
|
4136
|
+
soh: 1,
|
|
4137
|
+
stx: 2,
|
|
4138
|
+
etx: 3,
|
|
4139
|
+
eot: 4,
|
|
4140
|
+
enq: 5,
|
|
4141
|
+
ack: 6,
|
|
4142
|
+
bel: 7,
|
|
4143
|
+
bs: 8,
|
|
4144
|
+
ht: 9,
|
|
4145
|
+
lf: 10,
|
|
4146
|
+
vt: 11,
|
|
4147
|
+
ff: 12,
|
|
4148
|
+
cr: 13,
|
|
4149
|
+
so: 14,
|
|
4150
|
+
si: 15,
|
|
4151
|
+
dle: 16,
|
|
4152
|
+
dc1: 17,
|
|
4153
|
+
dc2: 18,
|
|
4154
|
+
dc3: 19,
|
|
4155
|
+
dc4: 20,
|
|
4156
|
+
nak: 21,
|
|
4157
|
+
syn: 22,
|
|
4158
|
+
etb: 23,
|
|
4159
|
+
can: 24,
|
|
4160
|
+
em: 25,
|
|
4161
|
+
sub: 26,
|
|
4162
|
+
esc: 27,
|
|
4163
|
+
fs: 28,
|
|
4164
|
+
gs: 29,
|
|
4165
|
+
rs: 30,
|
|
4166
|
+
us: 31,
|
|
4167
|
+
space: 32,
|
|
4168
|
+
exclamationMark: 33,
|
|
4169
|
+
quotationMark: 34,
|
|
4170
|
+
numberSign: 35,
|
|
4171
|
+
dollarSign: 36,
|
|
4172
|
+
percentSign: 37,
|
|
4173
|
+
ampersand: 38,
|
|
4174
|
+
apostrophe: 39,
|
|
4175
|
+
leftParenthesis: 40,
|
|
4176
|
+
rightParenthesis: 41,
|
|
4177
|
+
asterisk: 42,
|
|
4178
|
+
plusSign: 43,
|
|
4179
|
+
comma: 44,
|
|
4180
|
+
dash: 45,
|
|
4181
|
+
dot: 46,
|
|
4182
|
+
slash: 47,
|
|
4183
|
+
digit0: 48,
|
|
4184
|
+
digit1: 49,
|
|
4185
|
+
digit2: 50,
|
|
4186
|
+
digit3: 51,
|
|
4187
|
+
digit4: 52,
|
|
4188
|
+
digit5: 53,
|
|
4189
|
+
digit6: 54,
|
|
4190
|
+
digit7: 55,
|
|
4191
|
+
digit8: 56,
|
|
4192
|
+
digit9: 57,
|
|
4193
|
+
colon: 58,
|
|
4194
|
+
semicolon: 59,
|
|
4195
|
+
lessThan: 60,
|
|
4196
|
+
equalsTo: 61,
|
|
4197
|
+
greaterThan: 62,
|
|
4198
|
+
questionMark: 63,
|
|
4199
|
+
atSign: 64,
|
|
4200
|
+
uppercaseA: 65,
|
|
4201
|
+
uppercaseB: 66,
|
|
4202
|
+
uppercaseC: 67,
|
|
4203
|
+
uppercaseD: 68,
|
|
4204
|
+
uppercaseE: 69,
|
|
4205
|
+
uppercaseF: 70,
|
|
4206
|
+
uppercaseG: 71,
|
|
4207
|
+
uppercaseH: 72,
|
|
4208
|
+
uppercaseI: 73,
|
|
4209
|
+
uppercaseJ: 74,
|
|
4210
|
+
uppercaseK: 75,
|
|
4211
|
+
uppercaseL: 76,
|
|
4212
|
+
uppercaseM: 77,
|
|
4213
|
+
uppercaseN: 78,
|
|
4214
|
+
uppercaseO: 79,
|
|
4215
|
+
uppercaseP: 80,
|
|
4216
|
+
uppercaseQ: 81,
|
|
4217
|
+
uppercaseR: 82,
|
|
4218
|
+
uppercaseS: 83,
|
|
4219
|
+
uppercaseT: 84,
|
|
4220
|
+
uppercaseU: 85,
|
|
4221
|
+
uppercaseV: 86,
|
|
4222
|
+
uppercaseW: 87,
|
|
4223
|
+
uppercaseX: 88,
|
|
4224
|
+
uppercaseY: 89,
|
|
4225
|
+
uppercaseZ: 90,
|
|
4226
|
+
leftSquareBracket: 91,
|
|
4227
|
+
backslash: 92,
|
|
4228
|
+
rightSquareBracket: 93,
|
|
4229
|
+
caret: 94,
|
|
4230
|
+
underscore: 95,
|
|
4231
|
+
graveAccent: 96,
|
|
4232
|
+
lowercaseA: 97,
|
|
4233
|
+
lowercaseB: 98,
|
|
4234
|
+
lowercaseC: 99,
|
|
4235
|
+
lowercaseD: 100,
|
|
4236
|
+
lowercaseE: 101,
|
|
4237
|
+
lowercaseF: 102,
|
|
4238
|
+
lowercaseG: 103,
|
|
4239
|
+
lowercaseH: 104,
|
|
4240
|
+
lowercaseI: 105,
|
|
4241
|
+
lowercaseJ: 106,
|
|
4242
|
+
lowercaseK: 107,
|
|
4243
|
+
lowercaseL: 108,
|
|
4244
|
+
lowercaseM: 109,
|
|
4245
|
+
lowercaseN: 110,
|
|
4246
|
+
lowercaseO: 111,
|
|
4247
|
+
lowercaseP: 112,
|
|
4248
|
+
lowercaseQ: 113,
|
|
4249
|
+
lowercaseR: 114,
|
|
4250
|
+
lowercaseS: 115,
|
|
4251
|
+
lowercaseT: 116,
|
|
4252
|
+
lowercaseU: 117,
|
|
4253
|
+
lowercaseV: 118,
|
|
4254
|
+
lowercaseW: 119,
|
|
4255
|
+
lowercaseX: 120,
|
|
4256
|
+
lowercaseY: 121,
|
|
4257
|
+
lowercaseZ: 122,
|
|
4258
|
+
leftCurlyBrace: 123,
|
|
4259
|
+
verticalBar: 124,
|
|
4260
|
+
rightCurlyBrace: 125,
|
|
4261
|
+
tilde: 126,
|
|
4262
|
+
del: 127,
|
|
4263
|
+
byteOrderMarker: 65279,
|
|
4264
|
+
replacementCharacter: 65533
|
|
4265
|
+
};
|
|
4266
|
+
//#endregion
|
|
4267
|
+
//#region ../../../node_modules/.pnpm/micromark-util-symbol@2.0.1/node_modules/micromark-util-symbol/lib/types.js
|
|
4268
|
+
/**
|
|
4269
|
+
* This module is compiled away!
|
|
4270
|
+
*
|
|
4271
|
+
* Here is the list of all types of tokens exposed by micromark, with a short
|
|
4272
|
+
* explanation of what they include and where they are found.
|
|
4273
|
+
* In picking names, generally, the rule is to be as explicit as possible
|
|
4274
|
+
* instead of reusing names.
|
|
4275
|
+
* For example, there is a `definitionDestination` and a `resourceDestination`,
|
|
4276
|
+
* instead of one shared name.
|
|
4277
|
+
*/
|
|
4278
|
+
const types = {
|
|
4279
|
+
data: "data",
|
|
4280
|
+
whitespace: "whitespace",
|
|
4281
|
+
lineEnding: "lineEnding",
|
|
4282
|
+
lineEndingBlank: "lineEndingBlank",
|
|
4283
|
+
linePrefix: "linePrefix",
|
|
4284
|
+
lineSuffix: "lineSuffix",
|
|
4285
|
+
atxHeading: "atxHeading",
|
|
4286
|
+
atxHeadingSequence: "atxHeadingSequence",
|
|
4287
|
+
atxHeadingText: "atxHeadingText",
|
|
4288
|
+
autolink: "autolink",
|
|
4289
|
+
autolinkEmail: "autolinkEmail",
|
|
4290
|
+
autolinkMarker: "autolinkMarker",
|
|
4291
|
+
autolinkProtocol: "autolinkProtocol",
|
|
4292
|
+
characterEscape: "characterEscape",
|
|
4293
|
+
characterEscapeValue: "characterEscapeValue",
|
|
4294
|
+
characterReference: "characterReference",
|
|
4295
|
+
characterReferenceMarker: "characterReferenceMarker",
|
|
4296
|
+
characterReferenceMarkerNumeric: "characterReferenceMarkerNumeric",
|
|
4297
|
+
characterReferenceMarkerHexadecimal: "characterReferenceMarkerHexadecimal",
|
|
4298
|
+
characterReferenceValue: "characterReferenceValue",
|
|
4299
|
+
codeFenced: "codeFenced",
|
|
4300
|
+
codeFencedFence: "codeFencedFence",
|
|
4301
|
+
codeFencedFenceSequence: "codeFencedFenceSequence",
|
|
4302
|
+
codeFencedFenceInfo: "codeFencedFenceInfo",
|
|
4303
|
+
codeFencedFenceMeta: "codeFencedFenceMeta",
|
|
4304
|
+
codeFlowValue: "codeFlowValue",
|
|
4305
|
+
codeIndented: "codeIndented",
|
|
4306
|
+
codeText: "codeText",
|
|
4307
|
+
codeTextData: "codeTextData",
|
|
4308
|
+
codeTextPadding: "codeTextPadding",
|
|
4309
|
+
codeTextSequence: "codeTextSequence",
|
|
4310
|
+
content: "content",
|
|
4311
|
+
definition: "definition",
|
|
4312
|
+
definitionDestination: "definitionDestination",
|
|
4313
|
+
definitionDestinationLiteral: "definitionDestinationLiteral",
|
|
4314
|
+
definitionDestinationLiteralMarker: "definitionDestinationLiteralMarker",
|
|
4315
|
+
definitionDestinationRaw: "definitionDestinationRaw",
|
|
4316
|
+
definitionDestinationString: "definitionDestinationString",
|
|
4317
|
+
definitionLabel: "definitionLabel",
|
|
4318
|
+
definitionLabelMarker: "definitionLabelMarker",
|
|
4319
|
+
definitionLabelString: "definitionLabelString",
|
|
4320
|
+
definitionMarker: "definitionMarker",
|
|
4321
|
+
definitionTitle: "definitionTitle",
|
|
4322
|
+
definitionTitleMarker: "definitionTitleMarker",
|
|
4323
|
+
definitionTitleString: "definitionTitleString",
|
|
4324
|
+
emphasis: "emphasis",
|
|
4325
|
+
emphasisSequence: "emphasisSequence",
|
|
4326
|
+
emphasisText: "emphasisText",
|
|
4327
|
+
escapeMarker: "escapeMarker",
|
|
4328
|
+
hardBreakEscape: "hardBreakEscape",
|
|
4329
|
+
hardBreakTrailing: "hardBreakTrailing",
|
|
4330
|
+
htmlFlow: "htmlFlow",
|
|
4331
|
+
htmlFlowData: "htmlFlowData",
|
|
4332
|
+
htmlText: "htmlText",
|
|
4333
|
+
htmlTextData: "htmlTextData",
|
|
4334
|
+
image: "image",
|
|
4335
|
+
label: "label",
|
|
4336
|
+
labelText: "labelText",
|
|
4337
|
+
labelLink: "labelLink",
|
|
4338
|
+
labelImage: "labelImage",
|
|
4339
|
+
labelMarker: "labelMarker",
|
|
4340
|
+
labelImageMarker: "labelImageMarker",
|
|
4341
|
+
labelEnd: "labelEnd",
|
|
4342
|
+
link: "link",
|
|
4343
|
+
paragraph: "paragraph",
|
|
4344
|
+
reference: "reference",
|
|
4345
|
+
referenceMarker: "referenceMarker",
|
|
4346
|
+
referenceString: "referenceString",
|
|
4347
|
+
resource: "resource",
|
|
4348
|
+
resourceDestination: "resourceDestination",
|
|
4349
|
+
resourceDestinationLiteral: "resourceDestinationLiteral",
|
|
4350
|
+
resourceDestinationLiteralMarker: "resourceDestinationLiteralMarker",
|
|
4351
|
+
resourceDestinationRaw: "resourceDestinationRaw",
|
|
4352
|
+
resourceDestinationString: "resourceDestinationString",
|
|
4353
|
+
resourceMarker: "resourceMarker",
|
|
4354
|
+
resourceTitle: "resourceTitle",
|
|
4355
|
+
resourceTitleMarker: "resourceTitleMarker",
|
|
4356
|
+
resourceTitleString: "resourceTitleString",
|
|
4357
|
+
setextHeading: "setextHeading",
|
|
4358
|
+
setextHeadingText: "setextHeadingText",
|
|
4359
|
+
setextHeadingLine: "setextHeadingLine",
|
|
4360
|
+
setextHeadingLineSequence: "setextHeadingLineSequence",
|
|
4361
|
+
strong: "strong",
|
|
4362
|
+
strongSequence: "strongSequence",
|
|
4363
|
+
strongText: "strongText",
|
|
4364
|
+
thematicBreak: "thematicBreak",
|
|
4365
|
+
thematicBreakSequence: "thematicBreakSequence",
|
|
4366
|
+
blockQuote: "blockQuote",
|
|
4367
|
+
blockQuotePrefix: "blockQuotePrefix",
|
|
4368
|
+
blockQuoteMarker: "blockQuoteMarker",
|
|
4369
|
+
blockQuotePrefixWhitespace: "blockQuotePrefixWhitespace",
|
|
4370
|
+
listOrdered: "listOrdered",
|
|
4371
|
+
listUnordered: "listUnordered",
|
|
4372
|
+
listItemIndent: "listItemIndent",
|
|
4373
|
+
listItemMarker: "listItemMarker",
|
|
4374
|
+
listItemPrefix: "listItemPrefix",
|
|
4375
|
+
listItemPrefixWhitespace: "listItemPrefixWhitespace",
|
|
4376
|
+
listItemValue: "listItemValue",
|
|
4377
|
+
chunkDocument: "chunkDocument",
|
|
4378
|
+
chunkContent: "chunkContent",
|
|
4379
|
+
chunkFlow: "chunkFlow",
|
|
4380
|
+
chunkText: "chunkText",
|
|
4381
|
+
chunkString: "chunkString"
|
|
4382
|
+
};
|
|
4383
|
+
//#endregion
|
|
4384
|
+
//#region ../../client/ui-primitives/src/reference.ts
|
|
4385
|
+
const DEFAULT_PROTOCOL = "file";
|
|
4386
|
+
const LINE_FRAGMENT = /^L(\d+)(?:C(\d+))?(?:-L(\d+))?$/u;
|
|
4387
|
+
const SCHEME = /^([A-Za-z][A-Za-z0-9+.-]*):/u;
|
|
4388
|
+
const BARE_PATH = /^([^:]+):(\d+)(?::(\d+))?$/u;
|
|
4389
|
+
const PATH_PUNCTUATION = [
|
|
4390
|
+
codes.slash,
|
|
4391
|
+
codes.dash,
|
|
4392
|
+
codes.underscore,
|
|
4393
|
+
codes.dot,
|
|
4394
|
+
codes.plusSign,
|
|
4395
|
+
codes.percentSign,
|
|
4396
|
+
codes.atSign,
|
|
4397
|
+
codes.tilde,
|
|
4398
|
+
codes.equalsTo
|
|
4399
|
+
];
|
|
4400
|
+
const TRIGGERS = [
|
|
4401
|
+
":",
|
|
4402
|
+
"[",
|
|
4403
|
+
"@"
|
|
4404
|
+
];
|
|
4405
|
+
function parseReference(value, title) {
|
|
4406
|
+
const raw = value.trim();
|
|
4407
|
+
if (raw === "") return void 0;
|
|
4408
|
+
const matched = SCHEME.exec(raw);
|
|
4409
|
+
const protocol = matched === null ? DEFAULT_PROTOCOL : matched[1].toLowerCase();
|
|
4410
|
+
let rest = matched === null ? raw : raw.slice(matched[0].length);
|
|
4411
|
+
if (matched !== null && /\s/u.test(rest)) return void 0;
|
|
4412
|
+
const fragment = splitLineFragment(rest);
|
|
4413
|
+
rest = fragment.head;
|
|
4414
|
+
let origin;
|
|
4415
|
+
if (rest.startsWith("//")) {
|
|
4416
|
+
const end = authorityEnd(rest);
|
|
4417
|
+
const authority = rest.slice(2, end);
|
|
4418
|
+
if (authority === "") return void 0;
|
|
4419
|
+
origin = `${protocol}://${authority}`;
|
|
4420
|
+
rest = rest.slice(end).replace(/^\//u, "");
|
|
4421
|
+
}
|
|
4422
|
+
const decoded = protocol === DEFAULT_PROTOCOL ? decodeUri(rest) : rest;
|
|
4423
|
+
if (decoded === void 0 || decoded === "" && origin === void 0) return void 0;
|
|
4424
|
+
return {
|
|
4425
|
+
protocol,
|
|
4426
|
+
...origin === void 0 ? {} : { origin },
|
|
4427
|
+
...decoded === "" ? {} : { path: decoded },
|
|
4428
|
+
...title === void 0 || title === "" ? {} : { title },
|
|
4429
|
+
...fragment.lines
|
|
4430
|
+
};
|
|
4431
|
+
}
|
|
4432
|
+
function parseReferenceToken(value) {
|
|
4433
|
+
return SCHEME.test(value) ? parseReference(value) : void 0;
|
|
4434
|
+
}
|
|
4435
|
+
function findReferences(text) {
|
|
4436
|
+
const spans = [];
|
|
4437
|
+
if (text === "" || !TRIGGERS.some((trigger) => text.includes(trigger))) return spans;
|
|
4438
|
+
collectReferences(parseReferenceDocument(text), spans);
|
|
4439
|
+
return spans;
|
|
4440
|
+
}
|
|
4441
|
+
function parseReferenceDocument(text) {
|
|
4442
|
+
return fromMarkdown(text, {
|
|
4443
|
+
extensions: [gfm(), referenceSyntax()],
|
|
4444
|
+
mdastExtensions: [gfmFromMarkdown(), referenceFromMarkdown()]
|
|
4445
|
+
});
|
|
4446
|
+
}
|
|
4447
|
+
function collectReferences(node, spans) {
|
|
4448
|
+
const position = node.position;
|
|
4449
|
+
if (node.type === "reference" && position !== void 0) {
|
|
4450
|
+
const reference = referenceOfNode(node);
|
|
4451
|
+
if (reference !== void 0) spans.push({
|
|
4452
|
+
start: position.start.offset,
|
|
4453
|
+
end: position.end.offset,
|
|
4454
|
+
reference
|
|
4455
|
+
});
|
|
4456
|
+
}
|
|
4457
|
+
for (const child of node.children ?? []) collectReferences(child, spans);
|
|
4458
|
+
}
|
|
4459
|
+
function referenceOfNode(node) {
|
|
4460
|
+
const protocol = node.protocol;
|
|
4461
|
+
if (protocol === void 0) return void 0;
|
|
4462
|
+
return {
|
|
4463
|
+
protocol,
|
|
4464
|
+
...node.origin === void 0 ? {} : { origin: node.origin },
|
|
4465
|
+
...node.path === void 0 ? {} : { path: node.path },
|
|
4466
|
+
...node.title === void 0 ? {} : { title: node.title },
|
|
4467
|
+
...node.lineStart === void 0 ? {} : { lineStart: node.lineStart },
|
|
4468
|
+
...node.lineEnd === void 0 ? {} : { lineEnd: node.lineEnd },
|
|
4469
|
+
...node.column === void 0 ? {} : { column: node.column }
|
|
4470
|
+
};
|
|
4471
|
+
}
|
|
4472
|
+
const previousReference = function(code) {
|
|
4473
|
+
return isBoundary(code);
|
|
4474
|
+
};
|
|
4475
|
+
const tokenizeReference = function(effects, ok, nok) {
|
|
4476
|
+
const { events } = this;
|
|
4477
|
+
let at = false;
|
|
4478
|
+
let head = "";
|
|
4479
|
+
return start;
|
|
4480
|
+
function start(code) {
|
|
4481
|
+
if (insideLabel(events)) return nok(code);
|
|
4482
|
+
effects.enter("reference");
|
|
4483
|
+
if (code === codes.atSign) {
|
|
4484
|
+
at = true;
|
|
4485
|
+
effects.consume(code);
|
|
4486
|
+
return afterAt;
|
|
4487
|
+
}
|
|
4488
|
+
return headStart(code);
|
|
4489
|
+
}
|
|
4490
|
+
function afterAt(code) {
|
|
4491
|
+
if (code === codes.quotationMark) {
|
|
4492
|
+
effects.consume(code);
|
|
4493
|
+
return quotedPath;
|
|
4494
|
+
}
|
|
4495
|
+
return asciiAlpha(code) ? headStart(code) : pathStart(code);
|
|
4496
|
+
}
|
|
4497
|
+
function quotedPath(code) {
|
|
4498
|
+
if (code === null || markdownLineEnding(code)) return nok(code);
|
|
4499
|
+
effects.consume(code);
|
|
4500
|
+
return code === codes.quotationMark ? afterQuotedPath : quotedPath;
|
|
4501
|
+
}
|
|
4502
|
+
function afterQuotedPath(code) {
|
|
4503
|
+
if (code !== codes.numberSign) return finish(code);
|
|
4504
|
+
effects.consume(code);
|
|
4505
|
+
return fragmentInside;
|
|
4506
|
+
}
|
|
4507
|
+
function fragmentInside(code) {
|
|
4508
|
+
if (isPathCode(code) || code === codes.numberSign) {
|
|
4509
|
+
effects.consume(code);
|
|
4510
|
+
return fragmentInside;
|
|
4511
|
+
}
|
|
4512
|
+
return finish(code);
|
|
4513
|
+
}
|
|
4514
|
+
function headStart(code) {
|
|
4515
|
+
if (!asciiAlpha(code)) return nok(code);
|
|
4516
|
+
head = "";
|
|
4517
|
+
return headInside(code);
|
|
4518
|
+
}
|
|
4519
|
+
function headInside(code) {
|
|
4520
|
+
if (code === null || !asciiAlpha(code)) return afterHead(code);
|
|
4521
|
+
head += String.fromCodePoint(code);
|
|
4522
|
+
effects.consume(code);
|
|
4523
|
+
return headInside;
|
|
4524
|
+
}
|
|
4525
|
+
function afterHead(code) {
|
|
4526
|
+
if (code === codes.colon && isKnownScheme(head)) {
|
|
4527
|
+
effects.consume(code);
|
|
4528
|
+
return head.toLowerCase() === "skill" ? skillInside : fileInside;
|
|
4529
|
+
}
|
|
4530
|
+
return at ? pathInside(code) : nok(code);
|
|
4531
|
+
}
|
|
4532
|
+
function pathStart(code) {
|
|
4533
|
+
if (!isPathCode(code) || code === codes.atSign) return nok(code);
|
|
4534
|
+
effects.consume(code);
|
|
4535
|
+
return pathInside;
|
|
4536
|
+
}
|
|
4537
|
+
function fileInside(code) {
|
|
4538
|
+
if (!isFileCode(code)) return nok(code);
|
|
4539
|
+
effects.consume(code);
|
|
4540
|
+
return fileRest;
|
|
4541
|
+
}
|
|
4542
|
+
function fileRest(code) {
|
|
4543
|
+
if (isFileCode(code)) {
|
|
4544
|
+
effects.consume(code);
|
|
4545
|
+
return fileRest;
|
|
4546
|
+
}
|
|
4547
|
+
return finish(code);
|
|
4548
|
+
}
|
|
4549
|
+
function skillInside(code) {
|
|
4550
|
+
if (!isSkillCode(code)) return nok(code);
|
|
4551
|
+
effects.consume(code);
|
|
4552
|
+
return skillRest;
|
|
4553
|
+
}
|
|
4554
|
+
function skillRest(code) {
|
|
4555
|
+
if (isSkillCode(code)) {
|
|
4556
|
+
effects.consume(code);
|
|
4557
|
+
return skillRest;
|
|
4558
|
+
}
|
|
4559
|
+
return finish(code);
|
|
4560
|
+
}
|
|
4561
|
+
function pathInside(code) {
|
|
4562
|
+
if (isPathCode(code) || code === codes.numberSign) {
|
|
4563
|
+
effects.consume(code);
|
|
4564
|
+
return pathInside;
|
|
4565
|
+
}
|
|
4566
|
+
if (code !== codes.colon) return isBoundary(code) ? finish(code) : nok(code);
|
|
4567
|
+
effects.consume(code);
|
|
4568
|
+
return lineInside;
|
|
4569
|
+
}
|
|
4570
|
+
function lineInside(code) {
|
|
4571
|
+
if (!asciiDigit(code)) return nok(code);
|
|
4572
|
+
effects.consume(code);
|
|
4573
|
+
return lineRest;
|
|
4574
|
+
}
|
|
4575
|
+
function lineRest(code) {
|
|
4576
|
+
if (asciiDigit(code)) {
|
|
4577
|
+
effects.consume(code);
|
|
4578
|
+
return lineRest;
|
|
4579
|
+
}
|
|
4580
|
+
if (code !== codes.colon) return finish(code);
|
|
4581
|
+
effects.consume(code);
|
|
4582
|
+
return columnInside;
|
|
4583
|
+
}
|
|
4584
|
+
function columnInside(code) {
|
|
4585
|
+
if (!asciiDigit(code)) return nok(code);
|
|
4586
|
+
effects.consume(code);
|
|
4587
|
+
return columnRest;
|
|
4588
|
+
}
|
|
4589
|
+
function columnRest(code) {
|
|
4590
|
+
if (asciiDigit(code)) {
|
|
4591
|
+
effects.consume(code);
|
|
4592
|
+
return columnRest;
|
|
4593
|
+
}
|
|
4594
|
+
return finish(code);
|
|
4595
|
+
}
|
|
4596
|
+
function finish(code) {
|
|
4597
|
+
if (!isBoundary(code)) return nok(code);
|
|
4598
|
+
effects.exit("reference");
|
|
4599
|
+
return ok(code);
|
|
4600
|
+
}
|
|
4601
|
+
};
|
|
4602
|
+
const referenceConstruct = {
|
|
4603
|
+
name: "reference",
|
|
4604
|
+
previous: previousReference,
|
|
4605
|
+
tokenize: tokenizeReference
|
|
4606
|
+
};
|
|
4607
|
+
const referenceSyntaxExtension = { text: {
|
|
4608
|
+
[codes.atSign]: referenceConstruct,
|
|
4609
|
+
[codes.lowercaseF]: referenceConstruct,
|
|
4610
|
+
[codes.uppercaseF]: referenceConstruct,
|
|
4611
|
+
[codes.lowercaseS]: referenceConstruct,
|
|
4612
|
+
[codes.uppercaseS]: referenceConstruct
|
|
4613
|
+
} };
|
|
4614
|
+
function referenceSyntax() {
|
|
4615
|
+
return referenceSyntaxExtension;
|
|
4616
|
+
}
|
|
4617
|
+
function insideLabel(events) {
|
|
4618
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
4619
|
+
const token = events[index]?.[1];
|
|
4620
|
+
if (token === void 0) continue;
|
|
4621
|
+
if ((token.type === types.labelLink || token.type === types.labelImage) && token._balanced !== true) return true;
|
|
4622
|
+
}
|
|
4623
|
+
return false;
|
|
4624
|
+
}
|
|
4625
|
+
function isBoundary(code) {
|
|
4626
|
+
return code === null || markdownLineEndingOrSpace(code) || unicodeWhitespace(code) || unicodePunctuation(code);
|
|
4627
|
+
}
|
|
4628
|
+
function isPathCode(code) {
|
|
4629
|
+
if (code === null || markdownLineEndingOrSpace(code)) return false;
|
|
4630
|
+
if (!unicodePunctuation(code)) return true;
|
|
4631
|
+
return PATH_PUNCTUATION.includes(code);
|
|
4632
|
+
}
|
|
4633
|
+
function isFileCode(code) {
|
|
4634
|
+
return isPathCode(code) || code === codes.numberSign || code === codes.colon;
|
|
4635
|
+
}
|
|
4636
|
+
function isSkillCode(code) {
|
|
4637
|
+
return asciiAlphanumeric(code) || code === codes.dash || code === codes.underscore || code === codes.dot;
|
|
4638
|
+
}
|
|
4639
|
+
function enterReference(token) {
|
|
4640
|
+
this.enter({ type: "reference" }, token);
|
|
4641
|
+
}
|
|
4642
|
+
function exitReference(token) {
|
|
4643
|
+
const node = this.stack[this.stack.length - 1];
|
|
4644
|
+
const raw = this.sliceSerialize(token);
|
|
4645
|
+
const reference = parseBareReference(raw);
|
|
4646
|
+
if (node !== void 0) {
|
|
4647
|
+
if (reference === void 0) {
|
|
4648
|
+
node.type = "text";
|
|
4649
|
+
node.value = raw;
|
|
4650
|
+
} else Object.assign(node, reference);
|
|
4651
|
+
}
|
|
4652
|
+
this.exit(token);
|
|
4653
|
+
}
|
|
4654
|
+
const transformLinks = function(tree) {
|
|
4655
|
+
convertLinks(tree);
|
|
4656
|
+
};
|
|
4657
|
+
function convertLinks(parent) {
|
|
4658
|
+
const children = parent.children;
|
|
4659
|
+
if (children === void 0) return;
|
|
4660
|
+
for (let index = 0; index < children.length; index += 1) {
|
|
4661
|
+
const child = children[index];
|
|
4662
|
+
if (child === void 0) continue;
|
|
4663
|
+
if (child.type === "link") {
|
|
4664
|
+
const reference = parseReference(child.url ?? "", labelOf(child));
|
|
4665
|
+
if (reference !== void 0) {
|
|
4666
|
+
children[index] = referenceNodeOf(reference, child, children[index - 1]);
|
|
4667
|
+
continue;
|
|
4668
|
+
}
|
|
4669
|
+
}
|
|
4670
|
+
convertLinks(child);
|
|
4671
|
+
}
|
|
4672
|
+
}
|
|
4673
|
+
function referenceNodeOf(reference, link, previous) {
|
|
4674
|
+
const node = {
|
|
4675
|
+
type: "reference",
|
|
4676
|
+
...reference
|
|
4677
|
+
};
|
|
4678
|
+
const position = link.position;
|
|
4679
|
+
if (position === void 0) return node;
|
|
4680
|
+
node.position = startsAfterAt(previous, position.start) ? atStart(position) : position;
|
|
4681
|
+
return node;
|
|
4682
|
+
}
|
|
4683
|
+
function startsAfterAt(previous, start) {
|
|
4684
|
+
if (previous?.type !== "text" || previous.value?.endsWith("@") !== true) return false;
|
|
4685
|
+
const position = previous.position;
|
|
4686
|
+
if (position === void 0 || position.end.offset !== start.offset) return false;
|
|
4687
|
+
return position.end.offset - position.start.offset === previous.value.length;
|
|
4688
|
+
}
|
|
4689
|
+
function atStart(position) {
|
|
4690
|
+
return {
|
|
4691
|
+
start: {
|
|
4692
|
+
line: position.start.line,
|
|
4693
|
+
column: position.start.column - 1,
|
|
4694
|
+
offset: position.start.offset - 1
|
|
4695
|
+
},
|
|
4696
|
+
end: position.end
|
|
4697
|
+
};
|
|
4698
|
+
}
|
|
4699
|
+
function labelOf(node) {
|
|
4700
|
+
const label = textOf(node);
|
|
4701
|
+
return label === "" ? void 0 : label;
|
|
4702
|
+
}
|
|
4703
|
+
function textOf(node) {
|
|
4704
|
+
if (node.value !== void 0) return node.value;
|
|
4705
|
+
let text = "";
|
|
4706
|
+
for (const child of node.children ?? []) text += textOf(child);
|
|
4707
|
+
return text;
|
|
4708
|
+
}
|
|
4709
|
+
function parseBareReference(raw) {
|
|
4710
|
+
const body = raw.startsWith("@") ? raw.slice(1) : raw;
|
|
4711
|
+
if (body === "") return void 0;
|
|
4712
|
+
if (body.startsWith(QUOTED_PATH)) return parseQuotedReference(body);
|
|
4713
|
+
const scheme = SCHEME.exec(body);
|
|
4714
|
+
if (scheme !== null && isKnownScheme(scheme[1])) return parseReference(body);
|
|
4715
|
+
const matched = BARE_PATH.exec(body);
|
|
4716
|
+
const path = matched?.[1];
|
|
4717
|
+
const line = matched?.[2];
|
|
4718
|
+
if (path === void 0 || line === void 0) return parseReference(body);
|
|
4719
|
+
const decoded = decodeUri(path);
|
|
4720
|
+
if (decoded === void 0 || decoded === "") return void 0;
|
|
4721
|
+
const column = matched?.[3];
|
|
4722
|
+
return {
|
|
4723
|
+
protocol: DEFAULT_PROTOCOL,
|
|
4724
|
+
path: decoded,
|
|
4725
|
+
lineStart: Number(line),
|
|
4726
|
+
...column === void 0 ? {} : { column: Number(column) }
|
|
4727
|
+
};
|
|
4728
|
+
}
|
|
4729
|
+
/** 引号 mention 的起手字符:`@"path with spaces"`。 */
|
|
4730
|
+
const QUOTED_PATH = "\"";
|
|
4731
|
+
function parseQuotedReference(body) {
|
|
4732
|
+
const end = body.indexOf(QUOTED_PATH, 1);
|
|
4733
|
+
if (end === -1) return void 0;
|
|
4734
|
+
const path = body.slice(1, end);
|
|
4735
|
+
if (path === "") return void 0;
|
|
4736
|
+
const fragment = splitLineFragment(body.slice(end + 1));
|
|
4737
|
+
if (fragment.head !== "") return void 0;
|
|
4738
|
+
return {
|
|
4739
|
+
protocol: DEFAULT_PROTOCOL,
|
|
4740
|
+
path,
|
|
4741
|
+
...fragment.lines
|
|
4742
|
+
};
|
|
4743
|
+
}
|
|
4744
|
+
function referenceFromMarkdown() {
|
|
4745
|
+
return {
|
|
4746
|
+
enter: { reference: enterReference },
|
|
4747
|
+
exit: { reference: exitReference },
|
|
4748
|
+
transforms: [transformLinks]
|
|
4749
|
+
};
|
|
4750
|
+
}
|
|
4751
|
+
function isKnownScheme(name) {
|
|
4752
|
+
const protocol = name.toLowerCase();
|
|
4753
|
+
return protocol === "file" || protocol === "skill";
|
|
4754
|
+
}
|
|
4755
|
+
function splitLineFragment(value) {
|
|
4756
|
+
const hashAt = value.indexOf("#");
|
|
4757
|
+
if (hashAt === -1) return {
|
|
4758
|
+
head: value,
|
|
4759
|
+
lines: {}
|
|
4760
|
+
};
|
|
4761
|
+
const matched = LINE_FRAGMENT.exec(value.slice(hashAt + 1));
|
|
4762
|
+
if (matched === null) return {
|
|
4763
|
+
head: value,
|
|
4764
|
+
lines: {}
|
|
4765
|
+
};
|
|
4766
|
+
const lineStart = matched[1];
|
|
4767
|
+
if (lineStart === void 0) return {
|
|
4768
|
+
head: value,
|
|
4769
|
+
lines: {}
|
|
4770
|
+
};
|
|
4771
|
+
const column = matched[2];
|
|
4772
|
+
const lineEnd = matched[3];
|
|
4773
|
+
return {
|
|
4774
|
+
head: value.slice(0, hashAt),
|
|
4775
|
+
lines: {
|
|
4776
|
+
lineStart: Number(lineStart),
|
|
4777
|
+
...column === void 0 ? {} : { column: Number(column) },
|
|
4778
|
+
...lineEnd === void 0 ? {} : { lineEnd: Number(lineEnd) }
|
|
4779
|
+
}
|
|
4780
|
+
};
|
|
4781
|
+
}
|
|
4782
|
+
function authorityEnd(value) {
|
|
4783
|
+
for (let index = 2; index < value.length; index += 1) {
|
|
4784
|
+
const char = value[index];
|
|
4785
|
+
if (char === "/" || char === "?" || char === "#") return index;
|
|
4786
|
+
}
|
|
4787
|
+
return value.length;
|
|
4788
|
+
}
|
|
4789
|
+
function decodeUri(value) {
|
|
4790
|
+
try {
|
|
4791
|
+
return decodeURIComponent(value);
|
|
4792
|
+
} catch {
|
|
4793
|
+
return;
|
|
4794
|
+
}
|
|
4795
|
+
}
|
|
4796
|
+
//#endregion
|
|
4797
|
+
//#region src/links.ts
|
|
4798
|
+
const SKILL_PROTOCOL = "skill";
|
|
4799
|
+
const FILE_PROTOCOL = "file";
|
|
4800
|
+
const AT_PREFIX = "@";
|
|
4801
|
+
function walk(node, visit) {
|
|
4802
|
+
visit(node);
|
|
4803
|
+
for (const child of node.children ?? []) walk(child, visit);
|
|
4804
|
+
}
|
|
4805
|
+
function inlineCodeSkillNames(text) {
|
|
4806
|
+
const names = [];
|
|
4807
|
+
walk(fromMarkdown(text), (node) => {
|
|
4808
|
+
if (node.type !== "inlineCode" || node.value === void 0) return;
|
|
4809
|
+
const reference = parseReferenceToken(node.value);
|
|
4810
|
+
if (reference?.protocol === SKILL_PROTOCOL && reference.path !== void 0) names.push(reference.path);
|
|
4811
|
+
});
|
|
4812
|
+
return names;
|
|
4813
|
+
}
|
|
4814
|
+
function forEachTextBlock(messages, visit) {
|
|
4815
|
+
for (const message of messages) {
|
|
4816
|
+
if (message.source.kind !== "user") continue;
|
|
4817
|
+
for (const block of message.content) {
|
|
4818
|
+
if (block.type !== "text") continue;
|
|
4819
|
+
visit(block.text);
|
|
4820
|
+
}
|
|
4821
|
+
}
|
|
4822
|
+
}
|
|
4823
|
+
function skillNamesIn(messages) {
|
|
4824
|
+
const names = [];
|
|
4825
|
+
const push = (name) => {
|
|
4826
|
+
if (name === void 0 || name === "" || names.includes(name)) return;
|
|
4827
|
+
names.push(name);
|
|
4828
|
+
};
|
|
4829
|
+
forEachTextBlock(messages, (text) => {
|
|
4830
|
+
for (const span of findReferences(text)) {
|
|
4831
|
+
if (span.reference.protocol !== SKILL_PROTOCOL) continue;
|
|
4832
|
+
push(span.reference.path);
|
|
4833
|
+
}
|
|
4834
|
+
for (const name of inlineCodeSkillNames(text)) push(name);
|
|
4835
|
+
});
|
|
4836
|
+
return names;
|
|
4837
|
+
}
|
|
4838
|
+
function fileReferencesIn(messages) {
|
|
4839
|
+
const references = [];
|
|
4840
|
+
forEachTextBlock(messages, (text) => {
|
|
4841
|
+
for (const span of findReferences(text)) {
|
|
4842
|
+
const reference = span.reference;
|
|
4843
|
+
if (text[span.start] !== AT_PREFIX || reference.protocol !== FILE_PROTOCOL) continue;
|
|
4844
|
+
const path = reference.path;
|
|
4845
|
+
if (path === void 0 || path === "") continue;
|
|
4846
|
+
const lineStart = reference.lineStart;
|
|
4847
|
+
const next = {
|
|
4848
|
+
path,
|
|
4849
|
+
...lineStart === void 0 ? {} : { lineStart },
|
|
4850
|
+
...lineStart === void 0 || reference.lineEnd === void 0 ? {} : { lineEnd: reference.lineEnd }
|
|
4851
|
+
};
|
|
4852
|
+
if (references.some((known) => sameWindow(known, next))) continue;
|
|
4853
|
+
references.push(next);
|
|
4854
|
+
}
|
|
4855
|
+
});
|
|
4856
|
+
return references;
|
|
4857
|
+
}
|
|
4858
|
+
function sameWindow(left, right) {
|
|
4859
|
+
return left.path === right.path && left.lineStart === right.lineStart && left.lineEnd === right.lineEnd;
|
|
4860
|
+
}
|
|
4861
|
+
//#endregion
|
|
4862
|
+
//#region src/index.ts
|
|
4863
|
+
const name = "reference";
|
|
4864
|
+
const inject = ["skills"];
|
|
4865
|
+
/**
|
|
4866
|
+
* 内容之外的一条说明(见层级设计「内容之外的说明」):不说来源,模型会再 read 一遍同一段内容。
|
|
4867
|
+
* 与内容同处一条消息,所以同一步有多个引用时它也只说一次。
|
|
4868
|
+
*/
|
|
4869
|
+
const NOTE = [
|
|
4870
|
+
"<system-reminder>",
|
|
4871
|
+
"这些文件内容是按你消息里的 @ 引用刚读取的,直接用它即可,不必再 read 一遍。",
|
|
4872
|
+
"</system-reminder>"
|
|
4873
|
+
].join("\n");
|
|
4874
|
+
function apply(ctx) {
|
|
4875
|
+
ctx.on("agent/pre-step", async ({ agent, messages, signal }, next) => {
|
|
4876
|
+
const decision = await next();
|
|
4877
|
+
if (decision.kind === "reject") return decision;
|
|
4878
|
+
const tools = (() => {
|
|
4879
|
+
try {
|
|
4880
|
+
return ctx.get("tools");
|
|
4881
|
+
} catch {
|
|
4882
|
+
return;
|
|
4883
|
+
}
|
|
4884
|
+
})();
|
|
4885
|
+
const hasTool = (name) => tools === void 0 || tools.get(name, agent) !== void 0;
|
|
4886
|
+
const hasRead = hasTool("read");
|
|
4887
|
+
const names = hasTool("skill") ? skillNamesIn(messages) : [];
|
|
4888
|
+
const files = hasRead ? fileReferencesIn(messages) : [];
|
|
4889
|
+
if (names.length === 0 && files.length === 0) return decision;
|
|
4890
|
+
signal.throwIfAborted();
|
|
4891
|
+
const cwd = agent.session.header.cwd;
|
|
4892
|
+
const injections = [];
|
|
4893
|
+
for (const name of names) {
|
|
4894
|
+
const skill = await ctx.skills.get(name, {
|
|
4895
|
+
cwd,
|
|
4896
|
+
signal,
|
|
4897
|
+
scope: agent
|
|
4898
|
+
});
|
|
4899
|
+
signal.throwIfAborted();
|
|
4900
|
+
if (skill === void 0 || !isUserInvocable(skill)) continue;
|
|
4901
|
+
const source = {
|
|
4902
|
+
kind: "skill-invocation",
|
|
4903
|
+
name,
|
|
4904
|
+
form: "instructions"
|
|
4905
|
+
};
|
|
4906
|
+
injections.push(createUserMessage({
|
|
4907
|
+
content: [{
|
|
4908
|
+
type: "text",
|
|
4909
|
+
text: renderSkillContent(skill)
|
|
4910
|
+
}],
|
|
4911
|
+
source
|
|
4912
|
+
}));
|
|
4913
|
+
}
|
|
4914
|
+
const fs = ctx.get("fs");
|
|
4915
|
+
const read = [];
|
|
4916
|
+
const envelopes = [];
|
|
4917
|
+
for (const reference of files) {
|
|
4918
|
+
const envelope = fs === void 0 ? void 0 : await readFileContent(fs, reference, {
|
|
4919
|
+
cwd,
|
|
4920
|
+
signal
|
|
4921
|
+
});
|
|
4922
|
+
signal.throwIfAborted();
|
|
4923
|
+
if (envelope === void 0) continue;
|
|
4924
|
+
read.push(reference);
|
|
4925
|
+
envelopes.push({
|
|
4926
|
+
type: "text",
|
|
4927
|
+
text: envelope
|
|
4928
|
+
});
|
|
4929
|
+
}
|
|
4930
|
+
if (read.length > 0) injections.push(createUserMessage({
|
|
4931
|
+
content: [{
|
|
4932
|
+
type: "text",
|
|
4933
|
+
text: NOTE
|
|
4934
|
+
}, ...envelopes],
|
|
4935
|
+
source: {
|
|
4936
|
+
kind: "file-reference",
|
|
4937
|
+
references: read
|
|
4938
|
+
}
|
|
4939
|
+
}));
|
|
4940
|
+
if (injections.length === 0) return decision;
|
|
4941
|
+
return {
|
|
4942
|
+
...decision,
|
|
4943
|
+
messages: [...decision.messages, ...injections]
|
|
4944
|
+
};
|
|
4945
|
+
});
|
|
4946
|
+
}
|
|
4947
|
+
//#endregion
|
|
4948
|
+
export { apply, inject, name };
|