toolcraft 0.0.1
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/README.md +91 -0
- package/dist/cli.compile-check.d.ts +1 -0
- package/dist/cli.compile-check.js +26 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.js +1312 -0
- package/dist/index.compile-check.d.ts +1 -0
- package/dist/index.compile-check.js +50 -0
- package/dist/index.d.ts +164 -0
- package/dist/index.js +366 -0
- package/dist/mcp.compile-check.d.ts +1 -0
- package/dist/mcp.compile-check.js +26 -0
- package/dist/mcp.d.ts +31 -0
- package/dist/mcp.js +354 -0
- package/dist/number-schema.d.ts +3 -0
- package/dist/number-schema.js +8 -0
- package/dist/renderer.d.ts +5 -0
- package/dist/renderer.js +148 -0
- package/dist/schema-scope.d.ts +4 -0
- package/dist/schema-scope.js +34 -0
- package/dist/sdk.compile-check.d.ts +1 -0
- package/dist/sdk.compile-check.js +79 -0
- package/dist/sdk.d.ts +63 -0
- package/dist/sdk.js +218 -0
- package/node_modules/@poe-code/design-system/dist/acp/components.d.ts +11 -0
- package/node_modules/@poe-code/design-system/dist/acp/components.js +121 -0
- package/node_modules/@poe-code/design-system/dist/acp/index.d.ts +3 -0
- package/node_modules/@poe-code/design-system/dist/acp/index.js +2 -0
- package/node_modules/@poe-code/design-system/dist/acp/writer.d.ts +13 -0
- package/node_modules/@poe-code/design-system/dist/acp/writer.js +21 -0
- package/node_modules/@poe-code/design-system/dist/components/command-errors.d.ts +16 -0
- package/node_modules/@poe-code/design-system/dist/components/command-errors.js +22 -0
- package/node_modules/@poe-code/design-system/dist/components/help-formatter.d.ts +20 -0
- package/node_modules/@poe-code/design-system/dist/components/help-formatter.js +27 -0
- package/node_modules/@poe-code/design-system/dist/components/index.d.ts +10 -0
- package/node_modules/@poe-code/design-system/dist/components/index.js +7 -0
- package/node_modules/@poe-code/design-system/dist/components/logger.d.ts +11 -0
- package/node_modules/@poe-code/design-system/dist/components/logger.js +60 -0
- package/node_modules/@poe-code/design-system/dist/components/symbols.d.ts +12 -0
- package/node_modules/@poe-code/design-system/dist/components/symbols.js +71 -0
- package/node_modules/@poe-code/design-system/dist/components/table.d.ts +13 -0
- package/node_modules/@poe-code/design-system/dist/components/table.js +74 -0
- package/node_modules/@poe-code/design-system/dist/components/text.d.ts +14 -0
- package/node_modules/@poe-code/design-system/dist/components/text.js +104 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/ansi.d.ts +18 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/ansi.js +298 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/buffer.d.ts +25 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/buffer.js +189 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/border.d.ts +9 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/border.js +123 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/footer.d.ts +8 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/footer.js +57 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/output-pane.d.ts +12 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/output-pane.js +254 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/stats-pane.d.ts +7 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/stats-pane.js +121 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/dashboard.d.ts +20 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/dashboard.js +167 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/demo.d.ts +13 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/demo.js +145 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/index.d.ts +8 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/index.js +4 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/keymap.d.ts +3 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/keymap.js +99 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/layout.d.ts +25 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/layout.js +79 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/should-use-dashboard.d.ts +10 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/should-use-dashboard.js +7 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/snapshot.d.ts +10 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/snapshot.js +68 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/store.d.ts +8 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/store.js +51 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/terminal.d.ts +37 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/terminal.js +233 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/types.d.ts +36 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/types.js +1 -0
- package/node_modules/@poe-code/design-system/dist/index.d.ts +33 -0
- package/node_modules/@poe-code/design-system/dist/index.js +31 -0
- package/node_modules/@poe-code/design-system/dist/internal/output-format.d.ts +6 -0
- package/node_modules/@poe-code/design-system/dist/internal/output-format.js +22 -0
- package/node_modules/@poe-code/design-system/dist/internal/strip-ansi.d.ts +1 -0
- package/node_modules/@poe-code/design-system/dist/internal/strip-ansi.js +3 -0
- package/node_modules/@poe-code/design-system/dist/internal/theme-detect.d.ts +11 -0
- package/node_modules/@poe-code/design-system/dist/internal/theme-detect.js +49 -0
- package/node_modules/@poe-code/design-system/dist/prompts/index.d.ts +66 -0
- package/node_modules/@poe-code/design-system/dist/prompts/index.js +132 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/cancel.d.ts +2 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/cancel.js +9 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/intro.d.ts +1 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/intro.js +15 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/log.d.ts +18 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/log.js +101 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/note.d.ts +1 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/note.js +39 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/outro.d.ts +1 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/outro.js +16 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/spinner.d.ts +6 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/spinner.js +74 -0
- package/node_modules/@poe-code/design-system/dist/prompts/theme.d.ts +11 -0
- package/node_modules/@poe-code/design-system/dist/prompts/theme.js +12 -0
- package/node_modules/@poe-code/design-system/dist/static/index.d.ts +4 -0
- package/node_modules/@poe-code/design-system/dist/static/index.js +2 -0
- package/node_modules/@poe-code/design-system/dist/static/menu.d.ts +11 -0
- package/node_modules/@poe-code/design-system/dist/static/menu.js +36 -0
- package/node_modules/@poe-code/design-system/dist/static/spinner.d.ts +14 -0
- package/node_modules/@poe-code/design-system/dist/static/spinner.js +46 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/ast.d.ts +92 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/ast.js +1 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/demo-content.d.ts +2 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/demo-content.js +139 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/index.d.ts +6 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/index.js +8 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/block.d.ts +7 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/block.js +1495 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/frontmatter.d.ts +8 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/frontmatter.js +412 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/inline.d.ts +10 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/inline.js +1166 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser.d.ts +5 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser.js +42 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/renderer.d.ts +6 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/renderer.js +572 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/testing/theme-render-fixture.d.ts +1 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/testing/theme-render-fixture.js +27 -0
- package/node_modules/@poe-code/design-system/dist/tokens/colors.d.ts +35 -0
- package/node_modules/@poe-code/design-system/dist/tokens/colors.js +34 -0
- package/node_modules/@poe-code/design-system/dist/tokens/index.d.ts +4 -0
- package/node_modules/@poe-code/design-system/dist/tokens/index.js +4 -0
- package/node_modules/@poe-code/design-system/dist/tokens/spacing.d.ts +6 -0
- package/node_modules/@poe-code/design-system/dist/tokens/spacing.js +6 -0
- package/node_modules/@poe-code/design-system/dist/tokens/typography.d.ts +7 -0
- package/node_modules/@poe-code/design-system/dist/tokens/typography.js +8 -0
- package/node_modules/@poe-code/design-system/dist/tokens/widths.d.ts +5 -0
- package/node_modules/@poe-code/design-system/dist/tokens/widths.js +5 -0
- package/node_modules/@poe-code/design-system/package.json +25 -0
- package/package.json +57 -0
|
@@ -0,0 +1,1166 @@
|
|
|
1
|
+
const INLINE_HTML_TAGS = new Set([
|
|
2
|
+
"a",
|
|
3
|
+
"abbr",
|
|
4
|
+
"address",
|
|
5
|
+
"article",
|
|
6
|
+
"aside",
|
|
7
|
+
"b",
|
|
8
|
+
"base",
|
|
9
|
+
"basefont",
|
|
10
|
+
"bdi",
|
|
11
|
+
"bdo",
|
|
12
|
+
"blockquote",
|
|
13
|
+
"body",
|
|
14
|
+
"br",
|
|
15
|
+
"button",
|
|
16
|
+
"caption",
|
|
17
|
+
"center",
|
|
18
|
+
"cite",
|
|
19
|
+
"code",
|
|
20
|
+
"col",
|
|
21
|
+
"colgroup",
|
|
22
|
+
"data",
|
|
23
|
+
"dd",
|
|
24
|
+
"del",
|
|
25
|
+
"details",
|
|
26
|
+
"dfn",
|
|
27
|
+
"dialog",
|
|
28
|
+
"div",
|
|
29
|
+
"dl",
|
|
30
|
+
"dt",
|
|
31
|
+
"em",
|
|
32
|
+
"fieldset",
|
|
33
|
+
"figcaption",
|
|
34
|
+
"figure",
|
|
35
|
+
"footer",
|
|
36
|
+
"form",
|
|
37
|
+
"h1",
|
|
38
|
+
"h2",
|
|
39
|
+
"h3",
|
|
40
|
+
"h4",
|
|
41
|
+
"h5",
|
|
42
|
+
"h6",
|
|
43
|
+
"head",
|
|
44
|
+
"header",
|
|
45
|
+
"hr",
|
|
46
|
+
"html",
|
|
47
|
+
"i",
|
|
48
|
+
"img",
|
|
49
|
+
"input",
|
|
50
|
+
"ins",
|
|
51
|
+
"kbd",
|
|
52
|
+
"label",
|
|
53
|
+
"legend",
|
|
54
|
+
"li",
|
|
55
|
+
"link",
|
|
56
|
+
"main",
|
|
57
|
+
"mark",
|
|
58
|
+
"menu",
|
|
59
|
+
"nav",
|
|
60
|
+
"ol",
|
|
61
|
+
"option",
|
|
62
|
+
"p",
|
|
63
|
+
"param",
|
|
64
|
+
"pre",
|
|
65
|
+
"q",
|
|
66
|
+
"rp",
|
|
67
|
+
"rt",
|
|
68
|
+
"rtc",
|
|
69
|
+
"ruby",
|
|
70
|
+
"s",
|
|
71
|
+
"samp",
|
|
72
|
+
"search",
|
|
73
|
+
"section",
|
|
74
|
+
"small",
|
|
75
|
+
"span",
|
|
76
|
+
"strong",
|
|
77
|
+
"sub",
|
|
78
|
+
"summary",
|
|
79
|
+
"sup",
|
|
80
|
+
"table",
|
|
81
|
+
"tbody",
|
|
82
|
+
"td",
|
|
83
|
+
"tfoot",
|
|
84
|
+
"th",
|
|
85
|
+
"thead",
|
|
86
|
+
"time",
|
|
87
|
+
"title",
|
|
88
|
+
"tr",
|
|
89
|
+
"u",
|
|
90
|
+
"ul",
|
|
91
|
+
"var",
|
|
92
|
+
"wbr"
|
|
93
|
+
]);
|
|
94
|
+
export function parseInline(raw, options = {}) {
|
|
95
|
+
const nodes = [];
|
|
96
|
+
const delimiters = [];
|
|
97
|
+
const footnoteLabels = options.footnoteLabels;
|
|
98
|
+
const allowLiteralAutolinks = options.allowLiteralAutolinks ?? true;
|
|
99
|
+
const offsets = options.offsets ?? createOffsetMap(raw, options.offset ?? 0);
|
|
100
|
+
let textBuffer = "";
|
|
101
|
+
let textStart = 0;
|
|
102
|
+
let index = 0;
|
|
103
|
+
const appendText = (value, start) => {
|
|
104
|
+
if (textBuffer.length === 0) {
|
|
105
|
+
textStart = start;
|
|
106
|
+
}
|
|
107
|
+
textBuffer += value;
|
|
108
|
+
};
|
|
109
|
+
const flushText = (end = index) => {
|
|
110
|
+
if (textBuffer.length === 0) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
nodes.push(createTextNode(textBuffer, createRange(offsets, textStart, end)));
|
|
114
|
+
textBuffer = "";
|
|
115
|
+
};
|
|
116
|
+
while (index < raw.length) {
|
|
117
|
+
const char = raw[index];
|
|
118
|
+
if (char === "\\" && index + 1 < raw.length && isEscapable(raw[index + 1])) {
|
|
119
|
+
appendText(raw[index + 1], index);
|
|
120
|
+
index += 2;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (char === "`") {
|
|
124
|
+
const code = parseInlineCode(raw, index, offsets);
|
|
125
|
+
if (code !== null) {
|
|
126
|
+
flushText();
|
|
127
|
+
nodes.push(code.node);
|
|
128
|
+
index = code.end;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (char === "!" && index + 1 < raw.length && raw[index + 1] === "[") {
|
|
133
|
+
const image = parseImage(raw, index, offsets);
|
|
134
|
+
if (image !== null) {
|
|
135
|
+
flushText();
|
|
136
|
+
nodes.push(image.node);
|
|
137
|
+
index = image.end;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (char === "[") {
|
|
142
|
+
const footnoteReference = parseFootnoteReference(raw, index, footnoteLabels, offsets);
|
|
143
|
+
if (footnoteReference !== null) {
|
|
144
|
+
flushText();
|
|
145
|
+
nodes.push(footnoteReference.node);
|
|
146
|
+
index = footnoteReference.end;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const link = parseLink(raw, index, footnoteLabels, offsets);
|
|
150
|
+
if (link !== null) {
|
|
151
|
+
flushText();
|
|
152
|
+
nodes.push(link.node);
|
|
153
|
+
index = link.end;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (char === "<") {
|
|
158
|
+
const autolink = parseAutolink(raw, index, offsets);
|
|
159
|
+
if (autolink !== null) {
|
|
160
|
+
flushText();
|
|
161
|
+
nodes.push(autolink.node);
|
|
162
|
+
index = autolink.end;
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const html = parseInlineHtmlTag(raw, index, offsets);
|
|
166
|
+
if (html !== null) {
|
|
167
|
+
flushText();
|
|
168
|
+
nodes.push(html.node);
|
|
169
|
+
index = html.end;
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (char === "\n") {
|
|
174
|
+
if (textBuffer.endsWith("\\")) {
|
|
175
|
+
textBuffer = textBuffer.slice(0, -1);
|
|
176
|
+
flushText(index - 1);
|
|
177
|
+
nodes.push(withRange({ type: "break" }, createRange(offsets, index, index + 1)));
|
|
178
|
+
index += 1;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const trailingSpaceStart = findTrailingHardBreakSpaceStart(textBuffer);
|
|
182
|
+
if (trailingSpaceStart !== -1) {
|
|
183
|
+
const trailingSpaceCount = textBuffer.length - trailingSpaceStart;
|
|
184
|
+
textBuffer = textBuffer.slice(0, trailingSpaceStart);
|
|
185
|
+
flushText(index - trailingSpaceCount);
|
|
186
|
+
nodes.push(withRange({ type: "break" }, createRange(offsets, index, index + 1)));
|
|
187
|
+
index += 1;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (allowLiteralAutolinks) {
|
|
192
|
+
const literalAutolink = parseLiteralAutolink(raw, index, offsets);
|
|
193
|
+
if (literalAutolink !== null) {
|
|
194
|
+
flushText();
|
|
195
|
+
nodes.push(literalAutolink.node);
|
|
196
|
+
index = literalAutolink.end;
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (char === "*" || char === "_" || char === "~") {
|
|
201
|
+
const delimiter = parseDelimiter(raw, index, char);
|
|
202
|
+
if (delimiter !== null) {
|
|
203
|
+
flushText();
|
|
204
|
+
const node = createTextNode(raw.slice(index, index + delimiter.length), {
|
|
205
|
+
start: offsets[index] ?? 0,
|
|
206
|
+
end: offsets[index + delimiter.length] ?? offsets[offsets.length - 1] ?? 0
|
|
207
|
+
});
|
|
208
|
+
nodes.push(node);
|
|
209
|
+
delimiters.push({
|
|
210
|
+
...delimiter,
|
|
211
|
+
node,
|
|
212
|
+
position: nodes.length - 1
|
|
213
|
+
});
|
|
214
|
+
index += delimiter.length;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
appendText(char, index);
|
|
219
|
+
index += 1;
|
|
220
|
+
}
|
|
221
|
+
flushText();
|
|
222
|
+
if (delimiters.length === 0) {
|
|
223
|
+
return normalizeInlineNodes(nodes);
|
|
224
|
+
}
|
|
225
|
+
const pairs = matchDelimiterPairs(delimiters);
|
|
226
|
+
if (pairs.length === 0) {
|
|
227
|
+
return normalizeInlineNodes(nodes);
|
|
228
|
+
}
|
|
229
|
+
return buildInlineNodes(nodes, delimiters, pairs);
|
|
230
|
+
}
|
|
231
|
+
function parseDelimiter(input, start, marker) {
|
|
232
|
+
const length = readRunLength(input, start, marker);
|
|
233
|
+
const before = start === 0 ? null : input[start - 1];
|
|
234
|
+
const after = start + length >= input.length ? null : input[start + length];
|
|
235
|
+
const leftFlanking = !isDelimiterWhitespace(after) &&
|
|
236
|
+
(!isDelimiterPunctuation(after) ||
|
|
237
|
+
isDelimiterWhitespace(before) ||
|
|
238
|
+
isDelimiterPunctuation(before));
|
|
239
|
+
const rightFlanking = !isDelimiterWhitespace(before) &&
|
|
240
|
+
(!isDelimiterPunctuation(before) ||
|
|
241
|
+
isDelimiterWhitespace(after) ||
|
|
242
|
+
isDelimiterPunctuation(after));
|
|
243
|
+
if (marker === "~") {
|
|
244
|
+
if (length < 2) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
marker,
|
|
249
|
+
length,
|
|
250
|
+
canOpen: leftFlanking,
|
|
251
|
+
canClose: rightFlanking
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
if (marker === "_") {
|
|
255
|
+
return {
|
|
256
|
+
marker,
|
|
257
|
+
length,
|
|
258
|
+
canOpen: leftFlanking && (!rightFlanking || isDelimiterPunctuation(before)),
|
|
259
|
+
canClose: rightFlanking && (!leftFlanking || isDelimiterPunctuation(after))
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
marker,
|
|
264
|
+
length,
|
|
265
|
+
canOpen: leftFlanking,
|
|
266
|
+
canClose: rightFlanking
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function matchDelimiterPairs(delimiters) {
|
|
270
|
+
const pairs = [];
|
|
271
|
+
const previous = delimiters.map((_, index) => index - 1);
|
|
272
|
+
const next = delimiters.map((_, index) => (index + 1 < delimiters.length ? index + 1 : -1));
|
|
273
|
+
const active = delimiters.map(() => true);
|
|
274
|
+
let sequence = 0;
|
|
275
|
+
let closerIndex = 0;
|
|
276
|
+
const unlinkDelimiter = (index) => {
|
|
277
|
+
if (!active[index]) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const previousIndex = previous[index];
|
|
281
|
+
const nextIndex = next[index];
|
|
282
|
+
if (previousIndex !== -1) {
|
|
283
|
+
next[previousIndex] = nextIndex;
|
|
284
|
+
}
|
|
285
|
+
if (nextIndex !== -1) {
|
|
286
|
+
previous[nextIndex] = previousIndex;
|
|
287
|
+
}
|
|
288
|
+
active[index] = false;
|
|
289
|
+
};
|
|
290
|
+
const pruneDelimiter = (index) => {
|
|
291
|
+
const delimiter = delimiters[index];
|
|
292
|
+
if (delimiter.length === 0) {
|
|
293
|
+
unlinkDelimiter(index);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (delimiter.marker === "~" && delimiter.length < 2) {
|
|
297
|
+
delimiter.canOpen = false;
|
|
298
|
+
delimiter.canClose = false;
|
|
299
|
+
unlinkDelimiter(index);
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
while (closerIndex !== -1) {
|
|
303
|
+
const closer = delimiters[closerIndex];
|
|
304
|
+
if (!closer.canClose || closer.length === 0) {
|
|
305
|
+
closerIndex = next[closerIndex];
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const openerIndex = findMatchingOpener(delimiters, previous, closerIndex);
|
|
309
|
+
if (openerIndex === null) {
|
|
310
|
+
const nextCloserIndex = next[closerIndex];
|
|
311
|
+
if (!closer.canOpen) {
|
|
312
|
+
unlinkDelimiter(closerIndex);
|
|
313
|
+
}
|
|
314
|
+
closerIndex = nextCloserIndex;
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
const opener = delimiters[openerIndex];
|
|
318
|
+
const pairLength = getPairLength(opener, closer);
|
|
319
|
+
if (pairLength === 0 || opener.position + 1 >= closer.position) {
|
|
320
|
+
closerIndex = next[closerIndex];
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
pairs.push({
|
|
324
|
+
opener,
|
|
325
|
+
closer,
|
|
326
|
+
kind: getPairKind(opener.marker, pairLength),
|
|
327
|
+
sequence
|
|
328
|
+
});
|
|
329
|
+
opener.length -= pairLength;
|
|
330
|
+
closer.length -= pairLength;
|
|
331
|
+
let trappedIndex = next[openerIndex];
|
|
332
|
+
while (trappedIndex !== -1 && trappedIndex !== closerIndex) {
|
|
333
|
+
const nextTrappedIndex = next[trappedIndex];
|
|
334
|
+
unlinkDelimiter(trappedIndex);
|
|
335
|
+
trappedIndex = nextTrappedIndex;
|
|
336
|
+
}
|
|
337
|
+
pruneDelimiter(openerIndex);
|
|
338
|
+
pruneDelimiter(closerIndex);
|
|
339
|
+
if (!active[closerIndex] || !closer.canClose || closer.length === 0) {
|
|
340
|
+
closerIndex = next[closerIndex];
|
|
341
|
+
}
|
|
342
|
+
sequence += 1;
|
|
343
|
+
}
|
|
344
|
+
return pairs;
|
|
345
|
+
}
|
|
346
|
+
function findMatchingOpener(delimiters, previous, closerIndex) {
|
|
347
|
+
const closer = delimiters[closerIndex];
|
|
348
|
+
let openerIndex = previous[closerIndex];
|
|
349
|
+
while (openerIndex !== -1) {
|
|
350
|
+
const opener = delimiters[openerIndex];
|
|
351
|
+
if (opener.marker === closer.marker &&
|
|
352
|
+
opener.canOpen &&
|
|
353
|
+
opener.length > 0 &&
|
|
354
|
+
!violatesMultipleOfThreeRule(opener, closer)) {
|
|
355
|
+
return openerIndex;
|
|
356
|
+
}
|
|
357
|
+
openerIndex = previous[openerIndex];
|
|
358
|
+
}
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
function violatesMultipleOfThreeRule(opener, closer) {
|
|
362
|
+
if (opener.marker === "~") {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
if (!opener.canClose || !closer.canOpen) {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
return ((opener.length + closer.length) % 3 === 0 &&
|
|
369
|
+
(opener.length % 3 !== 0 || closer.length % 3 !== 0));
|
|
370
|
+
}
|
|
371
|
+
function getPairLength(opener, closer) {
|
|
372
|
+
if (opener.marker === "~") {
|
|
373
|
+
return opener.length >= 2 && closer.length >= 2 ? 2 : 0;
|
|
374
|
+
}
|
|
375
|
+
return opener.length >= 2 && closer.length >= 2 ? 2 : 1;
|
|
376
|
+
}
|
|
377
|
+
function getPairKind(marker, pairLength) {
|
|
378
|
+
if (marker === "~") {
|
|
379
|
+
return "strikethrough";
|
|
380
|
+
}
|
|
381
|
+
return pairLength === 2 ? "strong" : "emphasis";
|
|
382
|
+
}
|
|
383
|
+
function buildInlineNodes(nodes, delimiters, pairs) {
|
|
384
|
+
const delimiterEntries = new Map();
|
|
385
|
+
for (const delimiter of delimiters) {
|
|
386
|
+
delimiterEntries.set(delimiter.node, {
|
|
387
|
+
delimiter,
|
|
388
|
+
opens: [],
|
|
389
|
+
closes: []
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
for (const pair of pairs) {
|
|
393
|
+
delimiterEntries.get(pair.opener.node)?.opens.push(pair);
|
|
394
|
+
delimiterEntries.get(pair.closer.node)?.closes.push(pair);
|
|
395
|
+
}
|
|
396
|
+
const root = [];
|
|
397
|
+
const stack = [{ children: root }];
|
|
398
|
+
const appendNode = (node) => {
|
|
399
|
+
stack[stack.length - 1]?.children.push(node);
|
|
400
|
+
};
|
|
401
|
+
for (const node of nodes) {
|
|
402
|
+
if (node.type !== "text") {
|
|
403
|
+
appendNode(node);
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
const delimiterEntry = delimiterEntries.get(node);
|
|
407
|
+
if (delimiterEntry === undefined) {
|
|
408
|
+
appendNode(node);
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
delimiterEntry.closes.sort((left, right) => left.sequence - right.sequence);
|
|
412
|
+
for (const pair of delimiterEntry.closes) {
|
|
413
|
+
const current = stack[stack.length - 1];
|
|
414
|
+
if (current?.pair === pair) {
|
|
415
|
+
stack.pop();
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
if (delimiterEntry.delimiter.length > 0) {
|
|
419
|
+
appendNode(createTextNode(delimiterEntry.delimiter.marker.repeat(delimiterEntry.delimiter.length), node.range));
|
|
420
|
+
}
|
|
421
|
+
delimiterEntry.opens.sort((left, right) => right.sequence - left.sequence);
|
|
422
|
+
for (const pair of delimiterEntry.opens) {
|
|
423
|
+
const wrapper = withRange(createDelimiterNode(pair.kind), {
|
|
424
|
+
start: pair.opener.node.range?.start ?? pair.opener.position,
|
|
425
|
+
end: pair.closer.node.range?.end ?? pair.closer.position
|
|
426
|
+
});
|
|
427
|
+
appendNode(wrapper);
|
|
428
|
+
stack.push({ pair, children: wrapper.children });
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return normalizeInlineNodes(root);
|
|
432
|
+
}
|
|
433
|
+
function createDelimiterNode(kind) {
|
|
434
|
+
return { type: kind, children: [] };
|
|
435
|
+
}
|
|
436
|
+
function createTextNode(value, range) {
|
|
437
|
+
return range === undefined ? { type: "text", value } : withRange({ type: "text", value }, range);
|
|
438
|
+
}
|
|
439
|
+
function withRange(node, range) {
|
|
440
|
+
Object.defineProperty(node, "range", {
|
|
441
|
+
value: range,
|
|
442
|
+
enumerable: false,
|
|
443
|
+
configurable: true,
|
|
444
|
+
writable: true
|
|
445
|
+
});
|
|
446
|
+
return node;
|
|
447
|
+
}
|
|
448
|
+
function mergeRanges(left, right) {
|
|
449
|
+
if (left === undefined) {
|
|
450
|
+
return right;
|
|
451
|
+
}
|
|
452
|
+
if (right === undefined) {
|
|
453
|
+
return left;
|
|
454
|
+
}
|
|
455
|
+
return {
|
|
456
|
+
start: Math.min(left.start, right.start),
|
|
457
|
+
end: Math.max(left.end, right.end)
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
function normalizeInlineNodes(nodes) {
|
|
461
|
+
const normalized = [];
|
|
462
|
+
for (const node of nodes) {
|
|
463
|
+
const nextNode = normalizeInlineNode(node);
|
|
464
|
+
if (nextNode === null) {
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
const previousNode = normalized[normalized.length - 1];
|
|
468
|
+
if (previousNode?.type === "text" && nextNode.type === "text") {
|
|
469
|
+
previousNode.value += nextNode.value;
|
|
470
|
+
const range = mergeRanges(previousNode.range, nextNode.range);
|
|
471
|
+
if (range !== undefined) {
|
|
472
|
+
withRange(previousNode, range);
|
|
473
|
+
}
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
normalized.push(nextNode);
|
|
477
|
+
}
|
|
478
|
+
return normalized;
|
|
479
|
+
}
|
|
480
|
+
function normalizeInlineNode(node) {
|
|
481
|
+
if (node.type === "text") {
|
|
482
|
+
return node.value.length === 0 ? null : node;
|
|
483
|
+
}
|
|
484
|
+
if (node.type === "emphasis" ||
|
|
485
|
+
node.type === "strong" ||
|
|
486
|
+
node.type === "strikethrough" ||
|
|
487
|
+
node.type === "link") {
|
|
488
|
+
const nextNode = { ...node, children: normalizeInlineNodes(node.children) };
|
|
489
|
+
return node.range === undefined ? nextNode : withRange(nextNode, node.range);
|
|
490
|
+
}
|
|
491
|
+
return node;
|
|
492
|
+
}
|
|
493
|
+
function parseInlineCode(input, start, offsets) {
|
|
494
|
+
const fenceLength = readRunLength(input, start, "`");
|
|
495
|
+
let index = start + fenceLength;
|
|
496
|
+
while (index < input.length) {
|
|
497
|
+
if (input[index] !== "`") {
|
|
498
|
+
index += 1;
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
const closingFenceLength = readRunLength(input, index, "`");
|
|
502
|
+
if (closingFenceLength === fenceLength) {
|
|
503
|
+
return {
|
|
504
|
+
node: offsets === undefined
|
|
505
|
+
? {
|
|
506
|
+
type: "inlineCode",
|
|
507
|
+
value: input.slice(start + fenceLength, index)
|
|
508
|
+
}
|
|
509
|
+
: withRange({
|
|
510
|
+
type: "inlineCode",
|
|
511
|
+
value: input.slice(start + fenceLength, index)
|
|
512
|
+
}, createRange(offsets, start, index + fenceLength)),
|
|
513
|
+
end: index + fenceLength
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
index += closingFenceLength;
|
|
517
|
+
}
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
function parseLink(input, start, footnoteLabels, offsets) {
|
|
521
|
+
const label = parseBracketedLabel(input, start);
|
|
522
|
+
if (label === null || label.end >= input.length || input[label.end] !== "(") {
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
525
|
+
const destination = parseLinkDestination(input, label.end);
|
|
526
|
+
if (destination === null) {
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
529
|
+
return {
|
|
530
|
+
node: withRange({
|
|
531
|
+
type: "link",
|
|
532
|
+
url: destination.url,
|
|
533
|
+
...(destination.title === undefined ? {} : { title: destination.title }),
|
|
534
|
+
children: parseInline(label.value, {
|
|
535
|
+
footnoteLabels,
|
|
536
|
+
allowLiteralAutolinks: false,
|
|
537
|
+
...(offsets === undefined
|
|
538
|
+
? {}
|
|
539
|
+
: { offsets: sliceOffsetMap(offsets, label.contentStart, label.end - 1) })
|
|
540
|
+
})
|
|
541
|
+
}, offsets === undefined ? { start, end: destination.end } : createRange(offsets, start, destination.end)),
|
|
542
|
+
end: destination.end
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
function parseImage(input, start, offsets) {
|
|
546
|
+
const label = parseBracketedLabel(input, start + 1);
|
|
547
|
+
if (label === null || label.end >= input.length || input[label.end] !== "(") {
|
|
548
|
+
return null;
|
|
549
|
+
}
|
|
550
|
+
const destination = parseLinkDestination(input, label.end);
|
|
551
|
+
if (destination === null) {
|
|
552
|
+
return null;
|
|
553
|
+
}
|
|
554
|
+
return {
|
|
555
|
+
node: withRange({
|
|
556
|
+
type: "image",
|
|
557
|
+
url: destination.url,
|
|
558
|
+
alt: decodeEscapes(label.value),
|
|
559
|
+
...(destination.title === undefined ? {} : { title: destination.title })
|
|
560
|
+
}, offsets === undefined ? { start, end: destination.end } : createRange(offsets, start, destination.end)),
|
|
561
|
+
end: destination.end
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
function parseBracketedLabel(input, start) {
|
|
565
|
+
if (start >= input.length || input[start] !== "[") {
|
|
566
|
+
return null;
|
|
567
|
+
}
|
|
568
|
+
let depth = 1;
|
|
569
|
+
let index = start + 1;
|
|
570
|
+
while (index < input.length) {
|
|
571
|
+
const char = input[index];
|
|
572
|
+
if (char === "\\" && index + 1 < input.length) {
|
|
573
|
+
index += 2;
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
if (char === "`") {
|
|
577
|
+
const code = parseInlineCode(input, index);
|
|
578
|
+
if (code !== null) {
|
|
579
|
+
index = code.end;
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
if (char === "[") {
|
|
584
|
+
depth += 1;
|
|
585
|
+
index += 1;
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
if (char === "]") {
|
|
589
|
+
depth -= 1;
|
|
590
|
+
if (depth === 0) {
|
|
591
|
+
return {
|
|
592
|
+
value: input.slice(start + 1, index),
|
|
593
|
+
contentStart: start + 1,
|
|
594
|
+
end: index + 1
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
index += 1;
|
|
599
|
+
}
|
|
600
|
+
return null;
|
|
601
|
+
}
|
|
602
|
+
function parseLinkDestination(input, openParenIndex) {
|
|
603
|
+
let depth = 1;
|
|
604
|
+
let quote = null;
|
|
605
|
+
let index = openParenIndex + 1;
|
|
606
|
+
while (index < input.length) {
|
|
607
|
+
const char = input[index];
|
|
608
|
+
if (quote !== null) {
|
|
609
|
+
if (char === "\\" && index + 1 < input.length) {
|
|
610
|
+
index += 2;
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
if (char === quote) {
|
|
614
|
+
quote = null;
|
|
615
|
+
}
|
|
616
|
+
index += 1;
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
if (char === "\\" && index + 1 < input.length && isEscapable(input[index + 1])) {
|
|
620
|
+
index += 2;
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
if (char === "\"" || char === "'") {
|
|
624
|
+
quote = char;
|
|
625
|
+
index += 1;
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
if (char === "(") {
|
|
629
|
+
depth += 1;
|
|
630
|
+
index += 1;
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
if (char === ")") {
|
|
634
|
+
depth -= 1;
|
|
635
|
+
if (depth === 0) {
|
|
636
|
+
const content = input.slice(openParenIndex + 1, index);
|
|
637
|
+
const parsed = parseLinkDestinationContent(content);
|
|
638
|
+
return {
|
|
639
|
+
...parsed,
|
|
640
|
+
end: index + 1
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
index += 1;
|
|
645
|
+
}
|
|
646
|
+
return null;
|
|
647
|
+
}
|
|
648
|
+
function parseLinkDestinationContent(content) {
|
|
649
|
+
const trimmedEnd = trimAsciiWhitespaceEndIndex(content);
|
|
650
|
+
if (trimmedEnd === 0) {
|
|
651
|
+
return { url: "" };
|
|
652
|
+
}
|
|
653
|
+
const quote = content[trimmedEnd - 1];
|
|
654
|
+
if (quote === "\"" || quote === "'") {
|
|
655
|
+
const titleStart = findTrailingQuotedSegmentStart(content, trimmedEnd, quote);
|
|
656
|
+
if (titleStart !== -1) {
|
|
657
|
+
let separatorStart = titleStart;
|
|
658
|
+
while (separatorStart > 0 && isAsciiWhitespace(content[separatorStart - 1])) {
|
|
659
|
+
separatorStart -= 1;
|
|
660
|
+
}
|
|
661
|
+
if (separatorStart < titleStart) {
|
|
662
|
+
return {
|
|
663
|
+
url: decodeEscapes(trimAsciiWhitespace(content.slice(0, separatorStart))),
|
|
664
|
+
title: decodeEscapes(content.slice(titleStart + 1, trimmedEnd - 1))
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
return { url: decodeEscapes(trimAsciiWhitespace(content.slice(0, trimmedEnd))) };
|
|
670
|
+
}
|
|
671
|
+
function findTrailingQuotedSegmentStart(content, end, quote) {
|
|
672
|
+
let index = end - 2;
|
|
673
|
+
while (index >= 0) {
|
|
674
|
+
if (content[index] === quote && !isEscaped(content, index)) {
|
|
675
|
+
return index;
|
|
676
|
+
}
|
|
677
|
+
index -= 1;
|
|
678
|
+
}
|
|
679
|
+
return -1;
|
|
680
|
+
}
|
|
681
|
+
function parseAutolink(input, start, offsets) {
|
|
682
|
+
let index = start + 1;
|
|
683
|
+
while (index < input.length && input[index] !== ">") {
|
|
684
|
+
const char = input[index];
|
|
685
|
+
if (char === "<" || char === "\n" || char === " " || char === "\t") {
|
|
686
|
+
return null;
|
|
687
|
+
}
|
|
688
|
+
index += 1;
|
|
689
|
+
}
|
|
690
|
+
if (index >= input.length || index === start + 1) {
|
|
691
|
+
return null;
|
|
692
|
+
}
|
|
693
|
+
const url = input.slice(start + 1, index);
|
|
694
|
+
if (!isAutolinkUrl(url)) {
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
return {
|
|
698
|
+
node: withRange({
|
|
699
|
+
type: "link",
|
|
700
|
+
url,
|
|
701
|
+
children: [
|
|
702
|
+
createTextNode(url, offsets === undefined ? { start: start + 1, end: index } : createRange(offsets, start + 1, index))
|
|
703
|
+
]
|
|
704
|
+
}, offsets === undefined ? { start, end: index + 1 } : createRange(offsets, start, index + 1)),
|
|
705
|
+
end: index + 1
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
function parseFootnoteReference(input, start, footnoteLabels, offsets) {
|
|
709
|
+
if (footnoteLabels === undefined ||
|
|
710
|
+
start + 3 >= input.length ||
|
|
711
|
+
input[start] !== "[" ||
|
|
712
|
+
input[start + 1] !== "^") {
|
|
713
|
+
return null;
|
|
714
|
+
}
|
|
715
|
+
let labelEnd = start + 2;
|
|
716
|
+
while (labelEnd < input.length && input[labelEnd] !== "]") {
|
|
717
|
+
if (!isFootnoteLabelChar(input[labelEnd])) {
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
labelEnd += 1;
|
|
721
|
+
}
|
|
722
|
+
if (labelEnd === start + 2 || labelEnd >= input.length) {
|
|
723
|
+
return null;
|
|
724
|
+
}
|
|
725
|
+
const label = input.slice(start + 2, labelEnd);
|
|
726
|
+
if (!footnoteLabels.has(label)) {
|
|
727
|
+
return null;
|
|
728
|
+
}
|
|
729
|
+
return {
|
|
730
|
+
node: withRange({ type: "footnoteReference", label }, offsets === undefined ? { start, end: labelEnd + 1 } : createRange(offsets, start, labelEnd + 1)),
|
|
731
|
+
end: labelEnd + 1
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
function parseLiteralAutolink(input, start, offsets) {
|
|
735
|
+
if (!isLiteralAutolinkBoundaryBefore(input, start)) {
|
|
736
|
+
return null;
|
|
737
|
+
}
|
|
738
|
+
const urlLiteral = parseLiteralUrlAutolink(input, start);
|
|
739
|
+
if (urlLiteral !== null) {
|
|
740
|
+
return createLiteralAutolinkNode(urlLiteral.text, urlLiteral.url, start, urlLiteral.end, offsets);
|
|
741
|
+
}
|
|
742
|
+
const wwwLiteral = parseLiteralWwwAutolink(input, start);
|
|
743
|
+
if (wwwLiteral !== null) {
|
|
744
|
+
return createLiteralAutolinkNode(wwwLiteral.text, `http://${wwwLiteral.text}`, start, wwwLiteral.end, offsets);
|
|
745
|
+
}
|
|
746
|
+
const emailLiteral = parseLiteralEmailAutolink(input, start);
|
|
747
|
+
if (emailLiteral !== null) {
|
|
748
|
+
return createLiteralAutolinkNode(emailLiteral.text, `mailto:${emailLiteral.text}`, start, emailLiteral.end, offsets);
|
|
749
|
+
}
|
|
750
|
+
return null;
|
|
751
|
+
}
|
|
752
|
+
function createLiteralAutolinkNode(text, url, start, end, offsets) {
|
|
753
|
+
return {
|
|
754
|
+
node: withRange({
|
|
755
|
+
type: "link",
|
|
756
|
+
url,
|
|
757
|
+
children: [createTextNode(text, offsets === undefined ? { start, end } : createRange(offsets, start, end))]
|
|
758
|
+
}, offsets === undefined ? { start, end } : createRange(offsets, start, end)),
|
|
759
|
+
end
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
function parseLiteralUrlAutolink(input, start) {
|
|
763
|
+
const hasHttp = input.startsWith("http://", start);
|
|
764
|
+
const hasHttps = input.startsWith("https://", start);
|
|
765
|
+
if (!hasHttp && !hasHttps) {
|
|
766
|
+
return null;
|
|
767
|
+
}
|
|
768
|
+
const end = scanLiteralAutolinkEnd(input, start);
|
|
769
|
+
const text = trimLiteralAutolinkText(input.slice(start, end));
|
|
770
|
+
const prefixLength = hasHttps ? "https://".length : "http://".length;
|
|
771
|
+
if (text.length <= prefixLength) {
|
|
772
|
+
return null;
|
|
773
|
+
}
|
|
774
|
+
return { text, url: text, end: start + text.length };
|
|
775
|
+
}
|
|
776
|
+
function parseLiteralWwwAutolink(input, start) {
|
|
777
|
+
if (!input.startsWith("www.", start)) {
|
|
778
|
+
return null;
|
|
779
|
+
}
|
|
780
|
+
const end = scanLiteralAutolinkEnd(input, start);
|
|
781
|
+
const text = trimLiteralAutolinkText(input.slice(start, end));
|
|
782
|
+
if (!hasDotAfterPrefix(text, 4)) {
|
|
783
|
+
return null;
|
|
784
|
+
}
|
|
785
|
+
return { text, end: start + text.length };
|
|
786
|
+
}
|
|
787
|
+
function parseLiteralEmailAutolink(input, start) {
|
|
788
|
+
if (!isEmailLocalPartChar(input[start] ?? "")) {
|
|
789
|
+
return null;
|
|
790
|
+
}
|
|
791
|
+
const end = scanLiteralAutolinkEnd(input, start);
|
|
792
|
+
const text = trimLiteralAutolinkText(input.slice(start, end));
|
|
793
|
+
if (!isValidLiteralEmail(text)) {
|
|
794
|
+
return null;
|
|
795
|
+
}
|
|
796
|
+
return { text, end: start + text.length };
|
|
797
|
+
}
|
|
798
|
+
function parseInlineHtmlTag(input, start, offsets) {
|
|
799
|
+
if (input[start] !== "<") {
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
let index = start + 1;
|
|
803
|
+
let closing = false;
|
|
804
|
+
if (index < input.length && input[index] === "/") {
|
|
805
|
+
closing = true;
|
|
806
|
+
index += 1;
|
|
807
|
+
}
|
|
808
|
+
if (index >= input.length || !isAsciiLetter(input[index])) {
|
|
809
|
+
return null;
|
|
810
|
+
}
|
|
811
|
+
index += 1;
|
|
812
|
+
while (index < input.length && isHtmlTagNameChar(input[index])) {
|
|
813
|
+
index += 1;
|
|
814
|
+
}
|
|
815
|
+
const tagName = input.slice(start + (closing ? 2 : 1), index).toLowerCase();
|
|
816
|
+
if (!INLINE_HTML_TAGS.has(tagName)) {
|
|
817
|
+
return null;
|
|
818
|
+
}
|
|
819
|
+
if (closing) {
|
|
820
|
+
index = skipHtmlWhitespace(input, index);
|
|
821
|
+
if (index >= input.length || input[index] !== ">") {
|
|
822
|
+
return null;
|
|
823
|
+
}
|
|
824
|
+
return {
|
|
825
|
+
node: withRange({ type: "html", value: input.slice(start, index + 1) }, offsets === undefined ? { start, end: index + 1 } : createRange(offsets, start, index + 1)),
|
|
826
|
+
end: index + 1
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
while (index < input.length) {
|
|
830
|
+
index = skipHtmlWhitespace(input, index);
|
|
831
|
+
if (index >= input.length) {
|
|
832
|
+
return null;
|
|
833
|
+
}
|
|
834
|
+
if (input[index] === ">") {
|
|
835
|
+
return {
|
|
836
|
+
node: withRange({ type: "html", value: input.slice(start, index + 1) }, offsets === undefined ? { start, end: index + 1 } : createRange(offsets, start, index + 1)),
|
|
837
|
+
end: index + 1
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
if (input[index] === "/") {
|
|
841
|
+
const selfClosingEnd = skipHtmlWhitespace(input, index + 1);
|
|
842
|
+
if (selfClosingEnd >= input.length || input[selfClosingEnd] !== ">") {
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
845
|
+
return {
|
|
846
|
+
node: withRange({ type: "html", value: input.slice(start, selfClosingEnd + 1) }, offsets === undefined
|
|
847
|
+
? { start, end: selfClosingEnd + 1 }
|
|
848
|
+
: createRange(offsets, start, selfClosingEnd + 1)),
|
|
849
|
+
end: selfClosingEnd + 1
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
if (!isHtmlAttributeNameStartChar(input[index])) {
|
|
853
|
+
return null;
|
|
854
|
+
}
|
|
855
|
+
index += 1;
|
|
856
|
+
while (index < input.length && isHtmlAttributeNameChar(input[index])) {
|
|
857
|
+
index += 1;
|
|
858
|
+
}
|
|
859
|
+
index = skipHtmlWhitespace(input, index);
|
|
860
|
+
if (index >= input.length || input[index] !== "=") {
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
index = skipHtmlWhitespace(input, index + 1);
|
|
864
|
+
if (index >= input.length) {
|
|
865
|
+
return null;
|
|
866
|
+
}
|
|
867
|
+
const quote = input[index];
|
|
868
|
+
if (quote === "\"" || quote === "'") {
|
|
869
|
+
index += 1;
|
|
870
|
+
while (index < input.length && input[index] !== quote) {
|
|
871
|
+
index += 1;
|
|
872
|
+
}
|
|
873
|
+
if (index >= input.length) {
|
|
874
|
+
return null;
|
|
875
|
+
}
|
|
876
|
+
index += 1;
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
while (index < input.length && !isHtmlWhitespace(input[index]) && input[index] !== ">") {
|
|
880
|
+
const char = input[index];
|
|
881
|
+
if (char === "\"" || char === "'" || char === "<" || char === "=" || char === "`") {
|
|
882
|
+
return null;
|
|
883
|
+
}
|
|
884
|
+
index += 1;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
889
|
+
function decodeEscapes(value) {
|
|
890
|
+
let result = "";
|
|
891
|
+
let index = 0;
|
|
892
|
+
while (index < value.length) {
|
|
893
|
+
if (value[index] === "\\" && index + 1 < value.length && isEscapable(value[index + 1])) {
|
|
894
|
+
result += value[index + 1];
|
|
895
|
+
index += 2;
|
|
896
|
+
continue;
|
|
897
|
+
}
|
|
898
|
+
result += value[index];
|
|
899
|
+
index += 1;
|
|
900
|
+
}
|
|
901
|
+
return result;
|
|
902
|
+
}
|
|
903
|
+
function findTrailingHardBreakSpaceStart(value) {
|
|
904
|
+
let start = value.length;
|
|
905
|
+
while (start > 0 && (value[start - 1] === " " || value[start - 1] === "\t")) {
|
|
906
|
+
start -= 1;
|
|
907
|
+
}
|
|
908
|
+
return value.length - start >= 2 ? start : -1;
|
|
909
|
+
}
|
|
910
|
+
function readRunLength(input, start, char) {
|
|
911
|
+
let index = start;
|
|
912
|
+
while (index < input.length && input[index] === char) {
|
|
913
|
+
index += 1;
|
|
914
|
+
}
|
|
915
|
+
return index - start;
|
|
916
|
+
}
|
|
917
|
+
function trimAsciiWhitespace(value) {
|
|
918
|
+
const start = trimAsciiWhitespaceStartIndex(value);
|
|
919
|
+
const end = trimAsciiWhitespaceEndIndex(value);
|
|
920
|
+
return value.slice(start, end);
|
|
921
|
+
}
|
|
922
|
+
function trimAsciiWhitespaceStartIndex(value) {
|
|
923
|
+
let index = 0;
|
|
924
|
+
while (index < value.length && isAsciiWhitespace(value[index])) {
|
|
925
|
+
index += 1;
|
|
926
|
+
}
|
|
927
|
+
return index;
|
|
928
|
+
}
|
|
929
|
+
function trimAsciiWhitespaceEndIndex(value) {
|
|
930
|
+
let index = value.length;
|
|
931
|
+
while (index > 0 && isAsciiWhitespace(value[index - 1])) {
|
|
932
|
+
index -= 1;
|
|
933
|
+
}
|
|
934
|
+
return index;
|
|
935
|
+
}
|
|
936
|
+
function isAutolinkUrl(value) {
|
|
937
|
+
if (value.length < 3 || !isAsciiLetter(value[0])) {
|
|
938
|
+
return false;
|
|
939
|
+
}
|
|
940
|
+
let index = 1;
|
|
941
|
+
while (index < value.length) {
|
|
942
|
+
const char = value[index];
|
|
943
|
+
if (char === ":") {
|
|
944
|
+
return index >= 2;
|
|
945
|
+
}
|
|
946
|
+
if (!isAsciiLetter(char) && !isDigit(char) && char !== "+" && char !== "." && char !== "-") {
|
|
947
|
+
return false;
|
|
948
|
+
}
|
|
949
|
+
index += 1;
|
|
950
|
+
}
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
function scanLiteralAutolinkEnd(input, start) {
|
|
954
|
+
let index = start;
|
|
955
|
+
while (index < input.length) {
|
|
956
|
+
const char = input[index];
|
|
957
|
+
if (char === "\n" || isAsciiWhitespace(char) || char === "<") {
|
|
958
|
+
break;
|
|
959
|
+
}
|
|
960
|
+
index += 1;
|
|
961
|
+
}
|
|
962
|
+
return index;
|
|
963
|
+
}
|
|
964
|
+
function trimLiteralAutolinkText(value) {
|
|
965
|
+
let end = value.length;
|
|
966
|
+
while (end > 0) {
|
|
967
|
+
const lastChar = value[end - 1];
|
|
968
|
+
if (lastChar === "." ||
|
|
969
|
+
lastChar === "," ||
|
|
970
|
+
lastChar === ":" ||
|
|
971
|
+
lastChar === ";" ||
|
|
972
|
+
lastChar === "!" ||
|
|
973
|
+
lastChar === "?") {
|
|
974
|
+
end -= 1;
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
977
|
+
if ((lastChar === ")" && hasMoreClosersThanOpeners(value.slice(0, end), "(", ")")) ||
|
|
978
|
+
(lastChar === "]" && hasMoreClosersThanOpeners(value.slice(0, end), "[", "]")) ||
|
|
979
|
+
(lastChar === "}" && hasMoreClosersThanOpeners(value.slice(0, end), "{", "}"))) {
|
|
980
|
+
end -= 1;
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
break;
|
|
984
|
+
}
|
|
985
|
+
return value.slice(0, end);
|
|
986
|
+
}
|
|
987
|
+
function hasMoreClosersThanOpeners(value, opener, closer) {
|
|
988
|
+
let balance = 0;
|
|
989
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
990
|
+
if (value[index] === opener) {
|
|
991
|
+
balance += 1;
|
|
992
|
+
continue;
|
|
993
|
+
}
|
|
994
|
+
if (value[index] === closer) {
|
|
995
|
+
balance -= 1;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
return balance < 0;
|
|
999
|
+
}
|
|
1000
|
+
function isLiteralAutolinkBoundaryBefore(input, start) {
|
|
1001
|
+
if (start === 0) {
|
|
1002
|
+
return true;
|
|
1003
|
+
}
|
|
1004
|
+
const previous = input[start - 1];
|
|
1005
|
+
if (previous === "(" && start >= 2 && input[start - 2] === "]") {
|
|
1006
|
+
return false;
|
|
1007
|
+
}
|
|
1008
|
+
return (!isAsciiLetter(previous) &&
|
|
1009
|
+
!isDigit(previous) &&
|
|
1010
|
+
previous !== "_" &&
|
|
1011
|
+
previous !== "." &&
|
|
1012
|
+
previous !== "+" &&
|
|
1013
|
+
previous !== "-" &&
|
|
1014
|
+
previous !== "@" &&
|
|
1015
|
+
previous !== "/");
|
|
1016
|
+
}
|
|
1017
|
+
function hasDotAfterPrefix(value, prefixLength) {
|
|
1018
|
+
if (value.length <= prefixLength) {
|
|
1019
|
+
return false;
|
|
1020
|
+
}
|
|
1021
|
+
for (let index = prefixLength; index < value.length; index += 1) {
|
|
1022
|
+
if (value[index] === ".") {
|
|
1023
|
+
return true;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
return false;
|
|
1027
|
+
}
|
|
1028
|
+
function isValidLiteralEmail(value) {
|
|
1029
|
+
const atIndex = value.indexOf("@");
|
|
1030
|
+
if (atIndex <= 0 || atIndex === value.length - 1 || value.indexOf("@", atIndex + 1) !== -1) {
|
|
1031
|
+
return false;
|
|
1032
|
+
}
|
|
1033
|
+
const localPart = value.slice(0, atIndex);
|
|
1034
|
+
const domain = value.slice(atIndex + 1);
|
|
1035
|
+
if (domain[0] === "." || domain[domain.length - 1] === "." || !hasDotAfterPrefix(domain, 0)) {
|
|
1036
|
+
return false;
|
|
1037
|
+
}
|
|
1038
|
+
for (let index = 0; index < localPart.length; index += 1) {
|
|
1039
|
+
if (!isEmailLocalPartChar(localPart[index])) {
|
|
1040
|
+
return false;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
for (let index = 0; index < domain.length; index += 1) {
|
|
1044
|
+
if (!isEmailDomainChar(domain[index])) {
|
|
1045
|
+
return false;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
return true;
|
|
1049
|
+
}
|
|
1050
|
+
function isEscaped(value, index) {
|
|
1051
|
+
let slashCount = 0;
|
|
1052
|
+
let cursor = index - 1;
|
|
1053
|
+
while (cursor >= 0 && value[cursor] === "\\") {
|
|
1054
|
+
slashCount += 1;
|
|
1055
|
+
cursor -= 1;
|
|
1056
|
+
}
|
|
1057
|
+
return slashCount % 2 === 1;
|
|
1058
|
+
}
|
|
1059
|
+
function skipHtmlWhitespace(value, start) {
|
|
1060
|
+
let index = start;
|
|
1061
|
+
while (index < value.length && isHtmlWhitespace(value[index])) {
|
|
1062
|
+
index += 1;
|
|
1063
|
+
}
|
|
1064
|
+
return index;
|
|
1065
|
+
}
|
|
1066
|
+
function isEscapable(value) {
|
|
1067
|
+
return (value === "!" ||
|
|
1068
|
+
value === "\"" ||
|
|
1069
|
+
value === "#" ||
|
|
1070
|
+
value === "$" ||
|
|
1071
|
+
value === "%" ||
|
|
1072
|
+
value === "&" ||
|
|
1073
|
+
value === "'" ||
|
|
1074
|
+
value === "(" ||
|
|
1075
|
+
value === ")" ||
|
|
1076
|
+
value === "*" ||
|
|
1077
|
+
value === "+" ||
|
|
1078
|
+
value === "," ||
|
|
1079
|
+
value === "-" ||
|
|
1080
|
+
value === "." ||
|
|
1081
|
+
value === "/" ||
|
|
1082
|
+
value === ":" ||
|
|
1083
|
+
value === ";" ||
|
|
1084
|
+
value === "<" ||
|
|
1085
|
+
value === "=" ||
|
|
1086
|
+
value === ">" ||
|
|
1087
|
+
value === "?" ||
|
|
1088
|
+
value === "@" ||
|
|
1089
|
+
value === "[" ||
|
|
1090
|
+
value === "\\" ||
|
|
1091
|
+
value === "]" ||
|
|
1092
|
+
value === "^" ||
|
|
1093
|
+
value === "_" ||
|
|
1094
|
+
value === "`" ||
|
|
1095
|
+
value === "{" ||
|
|
1096
|
+
value === "|" ||
|
|
1097
|
+
value === "}" ||
|
|
1098
|
+
value === "~");
|
|
1099
|
+
}
|
|
1100
|
+
function isAsciiWhitespace(value) {
|
|
1101
|
+
return value === " " || value === "\t";
|
|
1102
|
+
}
|
|
1103
|
+
function isDelimiterWhitespace(value) {
|
|
1104
|
+
return value === null || /\s/u.test(value);
|
|
1105
|
+
}
|
|
1106
|
+
function isDelimiterPunctuation(value) {
|
|
1107
|
+
return value !== null && /[\p{P}\p{S}]/u.test(value);
|
|
1108
|
+
}
|
|
1109
|
+
function isHtmlWhitespace(value) {
|
|
1110
|
+
return value === " " || value === "\t";
|
|
1111
|
+
}
|
|
1112
|
+
function isAsciiLetter(value) {
|
|
1113
|
+
return (value >= "a" && value <= "z") || (value >= "A" && value <= "Z");
|
|
1114
|
+
}
|
|
1115
|
+
function isDigit(value) {
|
|
1116
|
+
return value >= "0" && value <= "9";
|
|
1117
|
+
}
|
|
1118
|
+
function isEmailLocalPartChar(value) {
|
|
1119
|
+
return isAsciiLetter(value) || isDigit(value) || value === "." || value === "_" || value === "%" || value === "+" || value === "-";
|
|
1120
|
+
}
|
|
1121
|
+
function isEmailDomainChar(value) {
|
|
1122
|
+
return isAsciiLetter(value) || isDigit(value) || value === "." || value === "-";
|
|
1123
|
+
}
|
|
1124
|
+
function isFootnoteLabelChar(value) {
|
|
1125
|
+
return isAsciiLetter(value) || isDigit(value) || value === "-" || value === "_";
|
|
1126
|
+
}
|
|
1127
|
+
function isHtmlTagNameChar(value) {
|
|
1128
|
+
return isAsciiLetter(value) || isDigit(value) || value === "-";
|
|
1129
|
+
}
|
|
1130
|
+
function isHtmlAttributeNameStartChar(value) {
|
|
1131
|
+
return isAsciiLetter(value) || value === ":" || value === "_";
|
|
1132
|
+
}
|
|
1133
|
+
function isHtmlAttributeNameChar(value) {
|
|
1134
|
+
return (isHtmlAttributeNameStartChar(value) ||
|
|
1135
|
+
isDigit(value) ||
|
|
1136
|
+
value === "-" ||
|
|
1137
|
+
value === ".");
|
|
1138
|
+
}
|
|
1139
|
+
function createRange(offsets, start, end) {
|
|
1140
|
+
return {
|
|
1141
|
+
start: offsets[start] ?? offsets[offsets.length - 1] ?? 0,
|
|
1142
|
+
end: offsets[end] ?? offsets[offsets.length - 1] ?? 0
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
function sliceOffsetMap(offsets, start, end) {
|
|
1146
|
+
return offsets.slice(start, end + 1);
|
|
1147
|
+
}
|
|
1148
|
+
function createOffsetMap(input, absoluteStart = 0) {
|
|
1149
|
+
const offsets = new Array(input.length + 1).fill(absoluteStart);
|
|
1150
|
+
let byteOffset = absoluteStart;
|
|
1151
|
+
let index = 0;
|
|
1152
|
+
while (index < input.length) {
|
|
1153
|
+
offsets[index] = byteOffset;
|
|
1154
|
+
const codePoint = input.codePointAt(index) ?? 0;
|
|
1155
|
+
const codeUnitLength = codePoint > 0xffff ? 2 : 1;
|
|
1156
|
+
const byteLength = codePoint <= 0x7f ? 1 : codePoint <= 0x7ff ? 2 : codePoint <= 0xffff ? 3 : 4;
|
|
1157
|
+
for (let offsetIndex = 1; offsetIndex < codeUnitLength; offsetIndex += 1) {
|
|
1158
|
+
offsets[index + offsetIndex] = byteOffset;
|
|
1159
|
+
}
|
|
1160
|
+
byteOffset += byteLength;
|
|
1161
|
+
index += codeUnitLength;
|
|
1162
|
+
offsets[index] = byteOffset;
|
|
1163
|
+
}
|
|
1164
|
+
offsets[input.length] = byteOffset;
|
|
1165
|
+
return offsets;
|
|
1166
|
+
}
|