poe-code 3.0.178 → 3.0.179
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/dist/index.js +6 -2
- package/dist/index.js.map +2 -2
- package/package.json +6 -2
- package/packages/cmdkit/dist/cli.compile-check.d.ts +1 -0
- package/packages/cmdkit/dist/cli.compile-check.js +26 -0
- package/packages/cmdkit/dist/cli.d.ts +12 -0
- package/packages/cmdkit/dist/cli.js +2306 -0
- package/packages/cmdkit/dist/cli.js.map +7 -0
- package/packages/cmdkit/dist/index.compile-check.d.ts +1 -0
- package/packages/cmdkit/dist/index.compile-check.js +50 -0
- package/packages/cmdkit/dist/index.d.ts +164 -0
- package/packages/cmdkit/dist/index.js +518 -0
- package/packages/cmdkit/dist/index.js.map +7 -0
- package/packages/cmdkit/dist/mcp.compile-check.d.ts +1 -0
- package/packages/cmdkit/dist/mcp.compile-check.js +26 -0
- package/packages/cmdkit/dist/mcp.d.ts +16 -0
- package/packages/cmdkit/dist/mcp.js +1153 -0
- package/packages/cmdkit/dist/mcp.js.map +7 -0
- package/packages/cmdkit/dist/renderer.d.ts +5 -0
- package/packages/cmdkit/dist/renderer.js +164 -0
- package/packages/cmdkit/dist/renderer.js.map +7 -0
- package/packages/cmdkit/dist/sdk.compile-check.d.ts +1 -0
- package/packages/cmdkit/dist/sdk.compile-check.js +79 -0
- package/packages/cmdkit/dist/sdk.d.ts +63 -0
- package/packages/cmdkit/dist/sdk.js +314 -0
- package/packages/cmdkit/dist/sdk.js.map +7 -0
- package/packages/cmdkit-schema/dist/index.compile-check.d.ts +1 -0
- package/packages/cmdkit-schema/dist/index.compile-check.js +11 -0
- package/packages/cmdkit-schema/dist/index.d.ts +81 -0
- package/packages/cmdkit-schema/dist/index.js +130 -0
- package/packages/design-system/dist/acp/components.d.ts +11 -0
- package/packages/design-system/dist/acp/components.js +121 -0
- package/packages/design-system/dist/acp/index.d.ts +3 -0
- package/packages/design-system/dist/acp/index.js +2 -0
- package/packages/design-system/dist/acp/writer.d.ts +13 -0
- package/packages/design-system/dist/acp/writer.js +21 -0
- package/packages/design-system/dist/components/command-errors.d.ts +16 -0
- package/packages/design-system/dist/components/command-errors.js +22 -0
- package/packages/design-system/dist/components/help-formatter.d.ts +20 -0
- package/packages/design-system/dist/components/help-formatter.js +27 -0
- package/packages/design-system/dist/components/index.d.ts +10 -0
- package/packages/design-system/dist/components/index.js +7 -0
- package/packages/design-system/dist/components/logger.d.ts +11 -0
- package/packages/design-system/dist/components/logger.js +60 -0
- package/packages/design-system/dist/components/symbols.d.ts +12 -0
- package/packages/design-system/dist/components/symbols.js +71 -0
- package/packages/design-system/dist/components/table.d.ts +13 -0
- package/packages/design-system/dist/components/table.js +74 -0
- package/packages/design-system/dist/components/text.d.ts +14 -0
- package/packages/design-system/dist/components/text.js +104 -0
- package/packages/design-system/dist/dashboard/ansi.d.ts +18 -0
- package/packages/design-system/dist/dashboard/ansi.js +298 -0
- package/packages/design-system/dist/dashboard/buffer.d.ts +25 -0
- package/packages/design-system/dist/dashboard/buffer.js +189 -0
- package/packages/design-system/dist/dashboard/components/border.d.ts +9 -0
- package/packages/design-system/dist/dashboard/components/border.js +123 -0
- package/packages/design-system/dist/dashboard/components/footer.d.ts +8 -0
- package/packages/design-system/dist/dashboard/components/footer.js +58 -0
- package/packages/design-system/dist/dashboard/components/output-pane.d.ts +21 -0
- package/packages/design-system/dist/dashboard/components/output-pane.js +323 -0
- package/packages/design-system/dist/dashboard/components/stats-pane.d.ts +7 -0
- package/packages/design-system/dist/dashboard/components/stats-pane.js +120 -0
- package/packages/design-system/dist/dashboard/dashboard.d.ts +20 -0
- package/packages/design-system/dist/dashboard/dashboard.js +187 -0
- package/packages/design-system/dist/dashboard/demo.d.ts +13 -0
- package/packages/design-system/dist/dashboard/demo.js +145 -0
- package/packages/design-system/dist/dashboard/index.d.ts +7 -0
- package/packages/design-system/dist/dashboard/index.js +3 -0
- package/packages/design-system/dist/dashboard/keymap.d.ts +3 -0
- package/packages/design-system/dist/dashboard/keymap.js +114 -0
- package/packages/design-system/dist/dashboard/layout.d.ts +25 -0
- package/packages/design-system/dist/dashboard/layout.js +79 -0
- package/packages/design-system/dist/dashboard/snapshot.d.ts +10 -0
- package/packages/design-system/dist/dashboard/snapshot.js +72 -0
- package/packages/design-system/dist/dashboard/store.d.ts +9 -0
- package/packages/design-system/dist/dashboard/store.js +107 -0
- package/packages/design-system/dist/dashboard/terminal.d.ts +35 -0
- package/packages/design-system/dist/dashboard/terminal.js +215 -0
- package/packages/design-system/dist/dashboard/types.d.ts +45 -0
- package/packages/design-system/dist/dashboard/types.js +1 -0
- package/packages/design-system/dist/index.d.ts +33 -0
- package/packages/design-system/dist/index.js +31 -0
- package/packages/design-system/dist/internal/output-format.d.ts +6 -0
- package/packages/design-system/dist/internal/output-format.js +22 -0
- package/packages/design-system/dist/internal/strip-ansi.d.ts +1 -0
- package/packages/design-system/dist/internal/strip-ansi.js +3 -0
- package/packages/design-system/dist/internal/theme-detect.d.ts +11 -0
- package/packages/design-system/dist/internal/theme-detect.js +49 -0
- package/packages/design-system/dist/prompts/index.d.ts +66 -0
- package/packages/design-system/dist/prompts/index.js +132 -0
- package/packages/design-system/dist/prompts/primitives/cancel.d.ts +2 -0
- package/packages/design-system/dist/prompts/primitives/cancel.js +9 -0
- package/packages/design-system/dist/prompts/primitives/intro.d.ts +1 -0
- package/packages/design-system/dist/prompts/primitives/intro.js +15 -0
- package/packages/design-system/dist/prompts/primitives/log.d.ts +18 -0
- package/packages/design-system/dist/prompts/primitives/log.js +101 -0
- package/packages/design-system/dist/prompts/primitives/note.d.ts +1 -0
- package/packages/design-system/dist/prompts/primitives/note.js +39 -0
- package/packages/design-system/dist/prompts/primitives/outro.d.ts +1 -0
- package/packages/design-system/dist/prompts/primitives/outro.js +16 -0
- package/packages/design-system/dist/prompts/primitives/spinner.d.ts +6 -0
- package/packages/design-system/dist/prompts/primitives/spinner.js +74 -0
- package/packages/design-system/dist/prompts/theme.d.ts +11 -0
- package/packages/design-system/dist/prompts/theme.js +12 -0
- package/packages/design-system/dist/static/index.d.ts +4 -0
- package/packages/design-system/dist/static/index.js +2 -0
- package/packages/design-system/dist/static/menu.d.ts +11 -0
- package/packages/design-system/dist/static/menu.js +36 -0
- package/packages/design-system/dist/static/spinner.d.ts +14 -0
- package/packages/design-system/dist/static/spinner.js +46 -0
- package/packages/design-system/dist/terminal-markdown/ast.d.ts +84 -0
- package/packages/design-system/dist/terminal-markdown/ast.js +1 -0
- package/packages/design-system/dist/terminal-markdown/demo-content.d.ts +2 -0
- package/packages/design-system/dist/terminal-markdown/demo-content.js +139 -0
- package/packages/design-system/dist/terminal-markdown/index.d.ts +6 -0
- package/packages/design-system/dist/terminal-markdown/index.js +8 -0
- package/packages/design-system/dist/terminal-markdown/parser/block.d.ts +6 -0
- package/packages/design-system/dist/terminal-markdown/parser/block.js +1205 -0
- package/packages/design-system/dist/terminal-markdown/parser/frontmatter.d.ts +6 -0
- package/packages/design-system/dist/terminal-markdown/parser/frontmatter.js +395 -0
- package/packages/design-system/dist/terminal-markdown/parser/inline.d.ts +6 -0
- package/packages/design-system/dist/terminal-markdown/parser/inline.js +1087 -0
- package/packages/design-system/dist/terminal-markdown/parser.d.ts +5 -0
- package/packages/design-system/dist/terminal-markdown/parser.js +13 -0
- package/packages/design-system/dist/terminal-markdown/renderer.d.ts +6 -0
- package/packages/design-system/dist/terminal-markdown/renderer.js +572 -0
- package/packages/design-system/dist/terminal-markdown/testing/theme-render-fixture.d.ts +1 -0
- package/packages/design-system/dist/terminal-markdown/testing/theme-render-fixture.js +27 -0
- package/packages/design-system/dist/tokens/colors.d.ts +35 -0
- package/packages/design-system/dist/tokens/colors.js +34 -0
- package/packages/design-system/dist/tokens/index.d.ts +4 -0
- package/packages/design-system/dist/tokens/index.js +4 -0
- package/packages/design-system/dist/tokens/spacing.d.ts +6 -0
- package/packages/design-system/dist/tokens/spacing.js +6 -0
- package/packages/design-system/dist/tokens/typography.d.ts +7 -0
- package/packages/design-system/dist/tokens/typography.js +8 -0
- package/packages/design-system/dist/tokens/widths.d.ts +5 -0
- package/packages/design-system/dist/tokens/widths.js +5 -0
- package/packages/tiny-stdio-mcp-server/dist/content/audio.d.ts +14 -0
- package/packages/tiny-stdio-mcp-server/dist/content/audio.js +76 -0
- package/packages/tiny-stdio-mcp-server/dist/content/convert.d.ts +16 -0
- package/packages/tiny-stdio-mcp-server/dist/content/convert.js +42 -0
- package/packages/tiny-stdio-mcp-server/dist/content/file-type.d.ts +11 -0
- package/packages/tiny-stdio-mcp-server/dist/content/file-type.js +93 -0
- package/packages/tiny-stdio-mcp-server/dist/content/file.d.ts +26 -0
- package/packages/tiny-stdio-mcp-server/dist/content/file.js +94 -0
- package/packages/tiny-stdio-mcp-server/dist/content/image.d.ts +14 -0
- package/packages/tiny-stdio-mcp-server/dist/content/image.js +64 -0
- package/packages/tiny-stdio-mcp-server/dist/content/index.d.ts +5 -0
- package/packages/tiny-stdio-mcp-server/dist/content/index.js +8 -0
- package/packages/tiny-stdio-mcp-server/dist/content/mime.d.ts +1 -0
- package/packages/tiny-stdio-mcp-server/dist/content/mime.js +1 -0
- package/packages/tiny-stdio-mcp-server/dist/index.d.ts +9 -0
- package/packages/tiny-stdio-mcp-server/dist/index.js +7 -0
- package/packages/tiny-stdio-mcp-server/dist/jsonrpc.d.ts +14 -0
- package/packages/tiny-stdio-mcp-server/dist/jsonrpc.js +99 -0
- package/packages/tiny-stdio-mcp-server/dist/schema.d.ts +19 -0
- package/packages/tiny-stdio-mcp-server/dist/schema.js +18 -0
- package/packages/tiny-stdio-mcp-server/dist/server.d.ts +13 -0
- package/packages/tiny-stdio-mcp-server/dist/server.js +226 -0
- package/packages/tiny-stdio-mcp-server/dist/testing.d.ts +7 -0
- package/packages/tiny-stdio-mcp-server/dist/testing.js +20 -0
- package/packages/tiny-stdio-mcp-server/dist/types.d.ts +119 -0
- package/packages/tiny-stdio-mcp-server/dist/types.js +16 -0
|
@@ -0,0 +1,1205 @@
|
|
|
1
|
+
import { extractFrontmatter } from "./frontmatter.js";
|
|
2
|
+
import { parseInline } from "./inline.js";
|
|
3
|
+
const BLOCK_HTML_TAGS = new Set([
|
|
4
|
+
"address",
|
|
5
|
+
"article",
|
|
6
|
+
"aside",
|
|
7
|
+
"base",
|
|
8
|
+
"basefont",
|
|
9
|
+
"blockquote",
|
|
10
|
+
"body",
|
|
11
|
+
"caption",
|
|
12
|
+
"center",
|
|
13
|
+
"col",
|
|
14
|
+
"colgroup",
|
|
15
|
+
"dd",
|
|
16
|
+
"details",
|
|
17
|
+
"dialog",
|
|
18
|
+
"dir",
|
|
19
|
+
"div",
|
|
20
|
+
"dl",
|
|
21
|
+
"dt",
|
|
22
|
+
"fieldset",
|
|
23
|
+
"figcaption",
|
|
24
|
+
"figure",
|
|
25
|
+
"footer",
|
|
26
|
+
"form",
|
|
27
|
+
"frame",
|
|
28
|
+
"frameset",
|
|
29
|
+
"h1",
|
|
30
|
+
"h2",
|
|
31
|
+
"h3",
|
|
32
|
+
"h4",
|
|
33
|
+
"h5",
|
|
34
|
+
"h6",
|
|
35
|
+
"head",
|
|
36
|
+
"header",
|
|
37
|
+
"hr",
|
|
38
|
+
"html",
|
|
39
|
+
"iframe",
|
|
40
|
+
"legend",
|
|
41
|
+
"li",
|
|
42
|
+
"link",
|
|
43
|
+
"main",
|
|
44
|
+
"menu",
|
|
45
|
+
"menuitem",
|
|
46
|
+
"nav",
|
|
47
|
+
"noframes",
|
|
48
|
+
"ol",
|
|
49
|
+
"optgroup",
|
|
50
|
+
"option",
|
|
51
|
+
"p",
|
|
52
|
+
"param",
|
|
53
|
+
"search",
|
|
54
|
+
"section",
|
|
55
|
+
"summary",
|
|
56
|
+
"table",
|
|
57
|
+
"tbody",
|
|
58
|
+
"td",
|
|
59
|
+
"tfoot",
|
|
60
|
+
"th",
|
|
61
|
+
"thead",
|
|
62
|
+
"title",
|
|
63
|
+
"tr",
|
|
64
|
+
"track",
|
|
65
|
+
"ul"
|
|
66
|
+
]);
|
|
67
|
+
const VOID_BLOCK_HTML_TAGS = new Set(["base", "basefont", "col", "hr", "link", "param", "track"]);
|
|
68
|
+
export function parseBlocks(input) {
|
|
69
|
+
return parseBlockDocument(input).children;
|
|
70
|
+
}
|
|
71
|
+
export function parseBlockDocument(input) {
|
|
72
|
+
const { frontmatter, body } = extractFrontmatter(input);
|
|
73
|
+
const children = applyInlineParsing(parseBlocksWithOptions(body, { preferListToThematicBreak: false }));
|
|
74
|
+
return frontmatter === undefined ? { children } : { frontmatter, children };
|
|
75
|
+
}
|
|
76
|
+
function parseBlocksWithOptions(input, options) {
|
|
77
|
+
const state = {
|
|
78
|
+
input: stripBom(input),
|
|
79
|
+
position: 0,
|
|
80
|
+
preferListToThematicBreak: options.preferListToThematicBreak
|
|
81
|
+
};
|
|
82
|
+
const blocks = [];
|
|
83
|
+
const rules = createBlockRules(state.preferListToThematicBreak);
|
|
84
|
+
while (state.position < state.input.length) {
|
|
85
|
+
const line = readLine(state.input, state.position);
|
|
86
|
+
if (isBlankLine(line.text)) {
|
|
87
|
+
state.position = line.nextPosition;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
let matchedNode = null;
|
|
91
|
+
for (const rule of rules) {
|
|
92
|
+
matchedNode = rule(state);
|
|
93
|
+
if (matchedNode !== null) {
|
|
94
|
+
blocks.push(matchedNode);
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (matchedNode !== null) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
blocks.push(parseParagraph(state));
|
|
102
|
+
}
|
|
103
|
+
return blocks;
|
|
104
|
+
}
|
|
105
|
+
function applyInlineParsing(nodes) {
|
|
106
|
+
const footnoteLabels = collectFootnoteLabels(nodes);
|
|
107
|
+
return nodes.map((node) => applyInlineParsingToNode(node, footnoteLabels));
|
|
108
|
+
}
|
|
109
|
+
function collectFootnoteLabels(nodes) {
|
|
110
|
+
const labels = new Set();
|
|
111
|
+
for (const node of nodes) {
|
|
112
|
+
collectFootnoteLabelsFromNode(node, labels);
|
|
113
|
+
}
|
|
114
|
+
return labels;
|
|
115
|
+
}
|
|
116
|
+
function collectFootnoteLabelsFromNode(node, labels) {
|
|
117
|
+
if (node.type === "footnoteDefinition") {
|
|
118
|
+
labels.add(node.label);
|
|
119
|
+
}
|
|
120
|
+
if (hasBlockChildren(node)) {
|
|
121
|
+
for (const child of node.children) {
|
|
122
|
+
collectFootnoteLabelsFromNode(child, labels);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function applyInlineParsingToNode(node, footnoteLabels) {
|
|
127
|
+
if (node.type === "paragraph" || node.type === "heading" || node.type === "tableCell") {
|
|
128
|
+
return {
|
|
129
|
+
...node,
|
|
130
|
+
children: applyInlineParsingToTextChildren(node.children, footnoteLabels)
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (hasBlockChildren(node)) {
|
|
134
|
+
return {
|
|
135
|
+
...node,
|
|
136
|
+
children: node.children.map((child) => applyInlineParsingToNode(child, footnoteLabels))
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return node;
|
|
140
|
+
}
|
|
141
|
+
function applyInlineParsingToTextChildren(children, footnoteLabels) {
|
|
142
|
+
let rawText = "";
|
|
143
|
+
for (const child of children) {
|
|
144
|
+
if (child.type !== "text") {
|
|
145
|
+
return children;
|
|
146
|
+
}
|
|
147
|
+
rawText += child.value;
|
|
148
|
+
}
|
|
149
|
+
return parseInline(rawText, { footnoteLabels });
|
|
150
|
+
}
|
|
151
|
+
function hasBlockChildren(node) {
|
|
152
|
+
return (node.type === "root" ||
|
|
153
|
+
node.type === "blockquote" ||
|
|
154
|
+
node.type === "list" ||
|
|
155
|
+
node.type === "listItem" ||
|
|
156
|
+
node.type === "table" ||
|
|
157
|
+
node.type === "tableRow" ||
|
|
158
|
+
node.type === "alert" ||
|
|
159
|
+
node.type === "footnoteDefinition");
|
|
160
|
+
}
|
|
161
|
+
function createBlockRules(preferListToThematicBreak) {
|
|
162
|
+
const middleRules = preferListToThematicBreak
|
|
163
|
+
? [parseAlert, parseBlockquote, parseList, parseHtmlBlock, parseThematicBreak]
|
|
164
|
+
: [parseThematicBreak, parseAlert, parseBlockquote, parseList, parseHtmlBlock];
|
|
165
|
+
return [
|
|
166
|
+
parseFencedCodeBlock,
|
|
167
|
+
parseAtxHeading,
|
|
168
|
+
...middleRules,
|
|
169
|
+
parseTable,
|
|
170
|
+
parseFootnoteDefinition,
|
|
171
|
+
parseSetextHeading
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
function parseFencedCodeBlock(state) {
|
|
175
|
+
const openingLine = readLine(state.input, state.position);
|
|
176
|
+
const fence = parseOpeningFence(openingLine.text);
|
|
177
|
+
if (fence === null) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
state.position = openingLine.nextPosition;
|
|
181
|
+
const contentLines = [];
|
|
182
|
+
while (state.position < state.input.length) {
|
|
183
|
+
const line = readLine(state.input, state.position);
|
|
184
|
+
if (isClosingFence(line.text, fence)) {
|
|
185
|
+
state.position = line.nextPosition;
|
|
186
|
+
return createCodeNode(fence, contentLines);
|
|
187
|
+
}
|
|
188
|
+
contentLines.push(line.text);
|
|
189
|
+
state.position = line.nextPosition;
|
|
190
|
+
}
|
|
191
|
+
return createCodeNode(fence, contentLines);
|
|
192
|
+
}
|
|
193
|
+
function parseAtxHeading(state) {
|
|
194
|
+
const line = readLine(state.input, state.position);
|
|
195
|
+
const heading = parseAtxHeadingLine(line.text);
|
|
196
|
+
if (heading === null) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
state.position = line.nextPosition;
|
|
200
|
+
return {
|
|
201
|
+
type: "heading",
|
|
202
|
+
depth: heading.depth,
|
|
203
|
+
children: createTextChildren(heading.text)
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function parseThematicBreak(state) {
|
|
207
|
+
const line = readLine(state.input, state.position);
|
|
208
|
+
if (!isThematicBreakLine(line.text)) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
state.position = line.nextPosition;
|
|
212
|
+
return { type: "thematicBreak" };
|
|
213
|
+
}
|
|
214
|
+
function parseSetextHeading(state) {
|
|
215
|
+
const contentLine = readLine(state.input, state.position);
|
|
216
|
+
if (isBlankLine(contentLine.text)) {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
if (contentLine.nextPosition >= state.input.length) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
const underlineLine = readLine(state.input, contentLine.nextPosition);
|
|
223
|
+
const depth = parseSetextUnderline(underlineLine.text);
|
|
224
|
+
if (depth === null) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
state.position = underlineLine.nextPosition;
|
|
228
|
+
return {
|
|
229
|
+
type: "heading",
|
|
230
|
+
depth,
|
|
231
|
+
children: createTextChildren(trimAsciiWhitespace(contentLine.text))
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function parseBlockquote(state) {
|
|
235
|
+
const firstLine = readLine(state.input, state.position);
|
|
236
|
+
if (stripBlockquoteMarker(firstLine.text) === null) {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
const contentLines = [];
|
|
240
|
+
while (state.position < state.input.length) {
|
|
241
|
+
const line = readLine(state.input, state.position);
|
|
242
|
+
const content = stripBlockquoteMarker(line.text);
|
|
243
|
+
if (content === null) {
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
contentLines.push(content);
|
|
247
|
+
state.position = line.nextPosition;
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
type: "blockquote",
|
|
251
|
+
children: parseBlocksWithOptions(contentLines.join("\n"), {
|
|
252
|
+
preferListToThematicBreak: state.preferListToThematicBreak
|
|
253
|
+
})
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function parseAlert(state) {
|
|
257
|
+
const firstLine = readLine(state.input, state.position);
|
|
258
|
+
const firstLineContent = stripBlockquoteMarker(firstLine.text);
|
|
259
|
+
if (firstLineContent === null) {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
const alertMarker = parseAlertMarker(firstLineContent);
|
|
263
|
+
if (alertMarker === null) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
state.position = firstLine.nextPosition;
|
|
267
|
+
const contentLines = alertMarker.content.length === 0 ? [] : [alertMarker.content];
|
|
268
|
+
while (state.position < state.input.length) {
|
|
269
|
+
const line = readLine(state.input, state.position);
|
|
270
|
+
const content = stripBlockquoteMarker(line.text);
|
|
271
|
+
if (content === null) {
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
contentLines.push(content);
|
|
275
|
+
state.position = line.nextPosition;
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
type: "alert",
|
|
279
|
+
kind: alertMarker.kind,
|
|
280
|
+
children: parseBlocksWithOptions(contentLines.join("\n"), {
|
|
281
|
+
preferListToThematicBreak: state.preferListToThematicBreak
|
|
282
|
+
})
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function parseList(state) {
|
|
286
|
+
const firstLine = readLine(state.input, state.position);
|
|
287
|
+
const firstMarker = parseListMarker(firstLine.text);
|
|
288
|
+
if (firstMarker === null) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
const children = [];
|
|
292
|
+
const ordered = firstMarker.ordered;
|
|
293
|
+
const start = firstMarker.start;
|
|
294
|
+
const indent = firstMarker.indent;
|
|
295
|
+
while (state.position < state.input.length) {
|
|
296
|
+
const item = parseListItem(state, {
|
|
297
|
+
ordered,
|
|
298
|
+
indent,
|
|
299
|
+
preferListToThematicBreak: true
|
|
300
|
+
});
|
|
301
|
+
if (item === null) {
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
children.push(item);
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
type: "list",
|
|
308
|
+
ordered,
|
|
309
|
+
...(ordered && start !== undefined ? { start } : {}),
|
|
310
|
+
children
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function parseTable(state) {
|
|
314
|
+
const table = parseTableAt(state.input, state.position, state.preferListToThematicBreak);
|
|
315
|
+
if (table === null) {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
state.position = table.nextPosition;
|
|
319
|
+
return {
|
|
320
|
+
type: "table",
|
|
321
|
+
align: table.align,
|
|
322
|
+
children: [
|
|
323
|
+
createTableRowNode(table.headerCells),
|
|
324
|
+
...table.rows.map((row) => createTableRowNode(row))
|
|
325
|
+
]
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function parseHtmlBlock(state) {
|
|
329
|
+
const firstLine = readLine(state.input, state.position);
|
|
330
|
+
const openingTag = parseBlockHtmlTagStart(firstLine.text);
|
|
331
|
+
if (openingTag === null) {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
state.position = firstLine.nextPosition;
|
|
335
|
+
const lines = [firstLine.text];
|
|
336
|
+
const isSelfContained = openingTag.closing ||
|
|
337
|
+
openingTag.selfClosing ||
|
|
338
|
+
VOID_BLOCK_HTML_TAGS.has(openingTag.tagName) ||
|
|
339
|
+
containsClosingHtmlTag(firstLine.text, openingTag.tagName, openingTag.tagEnd);
|
|
340
|
+
if (!isSelfContained) {
|
|
341
|
+
while (state.position < state.input.length) {
|
|
342
|
+
const line = readLine(state.input, state.position);
|
|
343
|
+
lines.push(line.text);
|
|
344
|
+
state.position = line.nextPosition;
|
|
345
|
+
if (containsClosingHtmlTag(line.text, openingTag.tagName)) {
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return { type: "html", value: lines.join("\n") };
|
|
351
|
+
}
|
|
352
|
+
function parseFootnoteDefinition(state) {
|
|
353
|
+
const firstLine = readLine(state.input, state.position);
|
|
354
|
+
const definition = parseFootnoteDefinitionMarker(firstLine.text);
|
|
355
|
+
if (definition === null) {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
state.position = firstLine.nextPosition;
|
|
359
|
+
const continuationLines = [];
|
|
360
|
+
const pendingBlankLines = [];
|
|
361
|
+
while (state.position < state.input.length) {
|
|
362
|
+
const line = readLine(state.input, state.position);
|
|
363
|
+
if (isBlankLine(line.text)) {
|
|
364
|
+
pendingBlankLines.push("");
|
|
365
|
+
state.position = line.nextPosition;
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
const strippedLine = stripIndent(line.text, 4);
|
|
369
|
+
if (strippedLine === null) {
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
state.position = line.nextPosition;
|
|
373
|
+
continuationLines.push(...pendingBlankLines, strippedLine);
|
|
374
|
+
pendingBlankLines.length = 0;
|
|
375
|
+
}
|
|
376
|
+
return {
|
|
377
|
+
type: "footnoteDefinition",
|
|
378
|
+
label: definition.label,
|
|
379
|
+
children: parseListItemChildren(firstLine.text.slice(definition.contentStart), continuationLines, state.preferListToThematicBreak)
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
function parseParagraph(state) {
|
|
383
|
+
const lines = [];
|
|
384
|
+
while (state.position < state.input.length) {
|
|
385
|
+
const line = readLine(state.input, state.position);
|
|
386
|
+
if (isBlankLine(line.text)) {
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
if (lines.length > 0 &&
|
|
390
|
+
startsBlockAt(state.input, state.position, state.preferListToThematicBreak)) {
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
lines.push(line.text);
|
|
394
|
+
state.position = line.nextPosition;
|
|
395
|
+
}
|
|
396
|
+
return {
|
|
397
|
+
type: "paragraph",
|
|
398
|
+
children: [{ type: "text", value: lines.join("\n") }]
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
function createCodeNode(fence, contentLines) {
|
|
402
|
+
return {
|
|
403
|
+
type: "code",
|
|
404
|
+
...(fence.lang === undefined ? {} : { lang: fence.lang }),
|
|
405
|
+
...(fence.meta === undefined ? {} : { meta: fence.meta }),
|
|
406
|
+
value: contentLines.join("\n")
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
function createTextChildren(value) {
|
|
410
|
+
return value.length === 0 ? [] : [{ type: "text", value }];
|
|
411
|
+
}
|
|
412
|
+
function createTableRowNode(values) {
|
|
413
|
+
return {
|
|
414
|
+
type: "tableRow",
|
|
415
|
+
children: values.map((value) => ({
|
|
416
|
+
type: "tableCell",
|
|
417
|
+
children: createTextChildren(value)
|
|
418
|
+
}))
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
function startsBlockAt(input, position, preferListToThematicBreak) {
|
|
422
|
+
const line = readLine(input, position);
|
|
423
|
+
if (startsSimpleBlock(line.text, preferListToThematicBreak)) {
|
|
424
|
+
return true;
|
|
425
|
+
}
|
|
426
|
+
if (line.nextPosition >= input.length) {
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
const nextLine = readLine(input, line.nextPosition);
|
|
430
|
+
return parseTableHeaderAndSeparator(line.text, nextLine.text) !== null;
|
|
431
|
+
}
|
|
432
|
+
function startsBlockInLines(lines, lineIndex, preferListToThematicBreak) {
|
|
433
|
+
const line = lines[lineIndex];
|
|
434
|
+
if (startsSimpleBlock(line, preferListToThematicBreak)) {
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
return (lineIndex + 1 < lines.length &&
|
|
438
|
+
parseTableHeaderAndSeparator(line, lines[lineIndex + 1]) !== null);
|
|
439
|
+
}
|
|
440
|
+
function startsSimpleBlock(line, preferListToThematicBreak) {
|
|
441
|
+
if (parseOpeningFence(line) !== null ||
|
|
442
|
+
parseAtxHeadingLine(line) !== null ||
|
|
443
|
+
parseBlockHtmlTagStart(line) !== null ||
|
|
444
|
+
parseFootnoteDefinitionMarker(line) !== null) {
|
|
445
|
+
return true;
|
|
446
|
+
}
|
|
447
|
+
if (stripBlockquoteMarker(line) !== null) {
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
450
|
+
if (preferListToThematicBreak) {
|
|
451
|
+
return parseListMarker(line) !== null || isThematicBreakLine(line);
|
|
452
|
+
}
|
|
453
|
+
return isThematicBreakLine(line) || parseListMarker(line) !== null;
|
|
454
|
+
}
|
|
455
|
+
function parseOpeningFence(line) {
|
|
456
|
+
const fenceStart = skipLeadingBlockIndent(line);
|
|
457
|
+
if (fenceStart === -1 || fenceStart >= line.length) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
const char = line[fenceStart];
|
|
461
|
+
if (char !== "`" && char !== "~") {
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
let fenceEnd = fenceStart;
|
|
465
|
+
while (fenceEnd < line.length && line[fenceEnd] === char) {
|
|
466
|
+
fenceEnd += 1;
|
|
467
|
+
}
|
|
468
|
+
const fenceLength = fenceEnd - fenceStart;
|
|
469
|
+
if (fenceLength < 3) {
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
472
|
+
const info = trimAsciiWhitespace(line.slice(fenceEnd));
|
|
473
|
+
if (info.length === 0) {
|
|
474
|
+
return { char, length: fenceLength };
|
|
475
|
+
}
|
|
476
|
+
const languageEnd = findWhitespaceIndex(info);
|
|
477
|
+
const lang = languageEnd === -1 ? info : info.slice(0, languageEnd);
|
|
478
|
+
const meta = languageEnd === -1 ? undefined : trimAsciiWhitespaceStart(info.slice(languageEnd));
|
|
479
|
+
return {
|
|
480
|
+
char,
|
|
481
|
+
length: fenceLength,
|
|
482
|
+
lang,
|
|
483
|
+
...(meta === undefined || meta.length === 0 ? {} : { meta })
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
function parseAtxHeadingLine(line) {
|
|
487
|
+
const markerStart = skipLeadingBlockIndent(line);
|
|
488
|
+
if (markerStart === -1 || markerStart >= line.length || line[markerStart] !== "#") {
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
let markerEnd = markerStart;
|
|
492
|
+
while (markerEnd < line.length && line[markerEnd] === "#") {
|
|
493
|
+
markerEnd += 1;
|
|
494
|
+
}
|
|
495
|
+
const depth = markerEnd - markerStart;
|
|
496
|
+
if (depth < 1 || depth > 6) {
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
if (markerEnd < line.length && line[markerEnd] !== " " && line[markerEnd] !== "\t") {
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
502
|
+
const rawContent = trimAsciiWhitespaceStart(line.slice(markerEnd));
|
|
503
|
+
return {
|
|
504
|
+
depth: depth,
|
|
505
|
+
text: stripClosingHeadingSequence(rawContent)
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function stripClosingHeadingSequence(value) {
|
|
509
|
+
const trimmedValue = trimAsciiWhitespaceEnd(value);
|
|
510
|
+
if (trimmedValue.length === 0) {
|
|
511
|
+
return "";
|
|
512
|
+
}
|
|
513
|
+
let hashStart = trimmedValue.length;
|
|
514
|
+
while (hashStart > 0 && trimmedValue[hashStart - 1] === "#") {
|
|
515
|
+
hashStart -= 1;
|
|
516
|
+
}
|
|
517
|
+
if (hashStart === trimmedValue.length) {
|
|
518
|
+
return trimmedValue;
|
|
519
|
+
}
|
|
520
|
+
if (hashStart === 0) {
|
|
521
|
+
return "";
|
|
522
|
+
}
|
|
523
|
+
const prefixEnd = hashStart - 1;
|
|
524
|
+
if (trimmedValue[prefixEnd] !== " " && trimmedValue[prefixEnd] !== "\t") {
|
|
525
|
+
return trimmedValue;
|
|
526
|
+
}
|
|
527
|
+
return trimAsciiWhitespaceEnd(trimmedValue.slice(0, prefixEnd));
|
|
528
|
+
}
|
|
529
|
+
function isClosingFence(line, fence) {
|
|
530
|
+
const fenceStart = skipLeadingBlockIndent(line);
|
|
531
|
+
if (fenceStart === -1 || fenceStart >= line.length) {
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
let index = fenceStart;
|
|
535
|
+
while (index < line.length && line[index] === fence.char) {
|
|
536
|
+
index += 1;
|
|
537
|
+
}
|
|
538
|
+
if (index - fenceStart < fence.length) {
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
if (fenceStart === index) {
|
|
542
|
+
return false;
|
|
543
|
+
}
|
|
544
|
+
for (let restIndex = index; restIndex < line.length; restIndex += 1) {
|
|
545
|
+
const char = line[restIndex];
|
|
546
|
+
if (char !== " " && char !== "\t") {
|
|
547
|
+
return false;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return true;
|
|
551
|
+
}
|
|
552
|
+
function isThematicBreakLine(line) {
|
|
553
|
+
const start = skipLeadingBlockIndent(line);
|
|
554
|
+
if (start === -1 || start >= line.length) {
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
557
|
+
const marker = line[start];
|
|
558
|
+
if (marker !== "-" && marker !== "*" && marker !== "_") {
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
let markerCount = 0;
|
|
562
|
+
for (let index = start; index < line.length; index += 1) {
|
|
563
|
+
const char = line[index];
|
|
564
|
+
if (char === marker) {
|
|
565
|
+
markerCount += 1;
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
if (char === " " || char === "\t") {
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
return markerCount >= 3;
|
|
574
|
+
}
|
|
575
|
+
function parseSetextUnderline(line) {
|
|
576
|
+
const start = skipLeadingBlockIndent(line);
|
|
577
|
+
if (start === -1 || start >= line.length) {
|
|
578
|
+
return null;
|
|
579
|
+
}
|
|
580
|
+
const marker = line[start];
|
|
581
|
+
if (marker !== "=" && marker !== "-") {
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
let index = start;
|
|
585
|
+
while (index < line.length && line[index] === marker) {
|
|
586
|
+
index += 1;
|
|
587
|
+
}
|
|
588
|
+
const markerCount = index - start;
|
|
589
|
+
if (markerCount === 0) {
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
for (; index < line.length; index += 1) {
|
|
593
|
+
const char = line[index];
|
|
594
|
+
if (char !== " " && char !== "\t") {
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return marker === "=" ? 1 : 2;
|
|
599
|
+
}
|
|
600
|
+
function parseTableAt(input, position, preferListToThematicBreak) {
|
|
601
|
+
const headerLine = readLine(input, position);
|
|
602
|
+
if (parseListMarker(headerLine.text) !== null ||
|
|
603
|
+
stripBlockquoteMarker(headerLine.text) !== null) {
|
|
604
|
+
return null;
|
|
605
|
+
}
|
|
606
|
+
if (headerLine.nextPosition >= input.length) {
|
|
607
|
+
return null;
|
|
608
|
+
}
|
|
609
|
+
const separatorLine = readLine(input, headerLine.nextPosition);
|
|
610
|
+
const header = parseTableHeaderAndSeparator(headerLine.text, separatorLine.text);
|
|
611
|
+
if (header === null) {
|
|
612
|
+
return null;
|
|
613
|
+
}
|
|
614
|
+
const rows = [];
|
|
615
|
+
let nextPosition = separatorLine.nextPosition;
|
|
616
|
+
while (nextPosition < input.length) {
|
|
617
|
+
const rowLine = readLine(input, nextPosition);
|
|
618
|
+
if (isBlankLine(rowLine.text)) {
|
|
619
|
+
break;
|
|
620
|
+
}
|
|
621
|
+
if (startsSimpleBlock(rowLine.text, preferListToThematicBreak)) {
|
|
622
|
+
break;
|
|
623
|
+
}
|
|
624
|
+
const cells = parsePipeTableCells(rowLine.text);
|
|
625
|
+
if (cells === null) {
|
|
626
|
+
break;
|
|
627
|
+
}
|
|
628
|
+
rows.push(normalizeTableCells(cells, header.headerCells.length));
|
|
629
|
+
nextPosition = rowLine.nextPosition;
|
|
630
|
+
}
|
|
631
|
+
return {
|
|
632
|
+
align: header.align,
|
|
633
|
+
headerCells: header.headerCells,
|
|
634
|
+
rows,
|
|
635
|
+
nextPosition
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function parseTableHeaderAndSeparator(headerLine, separatorLine) {
|
|
639
|
+
const headerCells = parsePipeTableCells(headerLine);
|
|
640
|
+
if (headerCells === null || headerCells.length === 0) {
|
|
641
|
+
return null;
|
|
642
|
+
}
|
|
643
|
+
const align = parsePipeTableSeparator(separatorLine);
|
|
644
|
+
if (align === null || align.length !== headerCells.length) {
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
647
|
+
return { align, headerCells };
|
|
648
|
+
}
|
|
649
|
+
function parsePipeTableCells(line) {
|
|
650
|
+
const start = skipLeadingBlockIndent(line);
|
|
651
|
+
if (start === -1 || start >= line.length) {
|
|
652
|
+
return null;
|
|
653
|
+
}
|
|
654
|
+
const content = trimAsciiWhitespaceEnd(line.slice(start));
|
|
655
|
+
let hasPipe = false;
|
|
656
|
+
const cells = [];
|
|
657
|
+
let cell = "";
|
|
658
|
+
let index = 0;
|
|
659
|
+
while (index < content.length) {
|
|
660
|
+
const char = content[index];
|
|
661
|
+
if (char === "\\" && index + 1 < content.length && content[index + 1] === "|") {
|
|
662
|
+
cell += "|";
|
|
663
|
+
index += 2;
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
if (char === "|") {
|
|
667
|
+
cells.push(trimAsciiWhitespace(cell));
|
|
668
|
+
cell = "";
|
|
669
|
+
hasPipe = true;
|
|
670
|
+
index += 1;
|
|
671
|
+
continue;
|
|
672
|
+
}
|
|
673
|
+
cell += char;
|
|
674
|
+
index += 1;
|
|
675
|
+
}
|
|
676
|
+
if (!hasPipe) {
|
|
677
|
+
return null;
|
|
678
|
+
}
|
|
679
|
+
cells.push(trimAsciiWhitespace(cell));
|
|
680
|
+
if (content[0] === "|") {
|
|
681
|
+
cells.shift();
|
|
682
|
+
}
|
|
683
|
+
if (content[content.length - 1] === "|") {
|
|
684
|
+
cells.pop();
|
|
685
|
+
}
|
|
686
|
+
return cells.length === 0 ? null : cells;
|
|
687
|
+
}
|
|
688
|
+
function parsePipeTableSeparator(line) {
|
|
689
|
+
const cells = parsePipeTableCells(line);
|
|
690
|
+
if (cells === null || cells.length === 0) {
|
|
691
|
+
return null;
|
|
692
|
+
}
|
|
693
|
+
const alignments = [];
|
|
694
|
+
for (const cell of cells) {
|
|
695
|
+
const alignment = parseTableAlignmentCell(cell);
|
|
696
|
+
if (alignment === undefined) {
|
|
697
|
+
return null;
|
|
698
|
+
}
|
|
699
|
+
alignments.push(alignment);
|
|
700
|
+
}
|
|
701
|
+
return alignments;
|
|
702
|
+
}
|
|
703
|
+
function parseTableAlignmentCell(value) {
|
|
704
|
+
if (value.length === 0) {
|
|
705
|
+
return undefined;
|
|
706
|
+
}
|
|
707
|
+
const hasLeadingColon = value[0] === ":";
|
|
708
|
+
const hasTrailingColon = value[value.length - 1] === ":";
|
|
709
|
+
const dashStart = hasLeadingColon ? 1 : 0;
|
|
710
|
+
const dashEnd = hasTrailingColon ? value.length - 1 : value.length;
|
|
711
|
+
if (dashEnd - dashStart < 3) {
|
|
712
|
+
return undefined;
|
|
713
|
+
}
|
|
714
|
+
for (let index = dashStart; index < dashEnd; index += 1) {
|
|
715
|
+
if (value[index] !== "-") {
|
|
716
|
+
return undefined;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
if (hasLeadingColon && hasTrailingColon) {
|
|
720
|
+
return "center";
|
|
721
|
+
}
|
|
722
|
+
if (hasLeadingColon) {
|
|
723
|
+
return "left";
|
|
724
|
+
}
|
|
725
|
+
if (hasTrailingColon) {
|
|
726
|
+
return "right";
|
|
727
|
+
}
|
|
728
|
+
return null;
|
|
729
|
+
}
|
|
730
|
+
function normalizeTableCells(cells, columnCount) {
|
|
731
|
+
if (cells.length === columnCount) {
|
|
732
|
+
return cells;
|
|
733
|
+
}
|
|
734
|
+
if (cells.length > columnCount) {
|
|
735
|
+
return cells.slice(0, columnCount);
|
|
736
|
+
}
|
|
737
|
+
return [...cells, ...Array.from({ length: columnCount - cells.length }, () => "")];
|
|
738
|
+
}
|
|
739
|
+
function stripBlockquoteMarker(line) {
|
|
740
|
+
const markerStart = skipLeadingBlockIndent(line);
|
|
741
|
+
if (markerStart === -1 || markerStart >= line.length || line[markerStart] !== ">") {
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
let contentStart = markerStart + 1;
|
|
745
|
+
if (contentStart < line.length && (line[contentStart] === " " || line[contentStart] === "\t")) {
|
|
746
|
+
contentStart += 1;
|
|
747
|
+
}
|
|
748
|
+
return line.slice(contentStart);
|
|
749
|
+
}
|
|
750
|
+
function parseAlertMarker(content) {
|
|
751
|
+
const endOfKind = content.indexOf("]");
|
|
752
|
+
if (content.length === 0 || !content.startsWith("[!") || endOfKind === -1) {
|
|
753
|
+
return null;
|
|
754
|
+
}
|
|
755
|
+
const kind = content.slice(2, endOfKind);
|
|
756
|
+
if (!isAlertKind(kind)) {
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
return {
|
|
760
|
+
kind,
|
|
761
|
+
content: trimAsciiWhitespaceStart(content.slice(endOfKind + 1))
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
function parseFootnoteDefinitionMarker(line) {
|
|
765
|
+
const markerStart = skipLeadingBlockIndent(line);
|
|
766
|
+
if (markerStart === -1 ||
|
|
767
|
+
markerStart + 3 >= line.length ||
|
|
768
|
+
line[markerStart] !== "[" ||
|
|
769
|
+
line[markerStart + 1] !== "^") {
|
|
770
|
+
return null;
|
|
771
|
+
}
|
|
772
|
+
let labelEnd = markerStart + 2;
|
|
773
|
+
while (labelEnd < line.length && line[labelEnd] !== "]") {
|
|
774
|
+
if (!isFootnoteLabelChar(line[labelEnd])) {
|
|
775
|
+
return null;
|
|
776
|
+
}
|
|
777
|
+
labelEnd += 1;
|
|
778
|
+
}
|
|
779
|
+
if (labelEnd === markerStart + 2 || labelEnd + 1 >= line.length || line[labelEnd + 1] !== ":") {
|
|
780
|
+
return null;
|
|
781
|
+
}
|
|
782
|
+
let contentStart = labelEnd + 2;
|
|
783
|
+
while (contentStart < line.length &&
|
|
784
|
+
(line[contentStart] === " " || line[contentStart] === "\t")) {
|
|
785
|
+
contentStart += 1;
|
|
786
|
+
}
|
|
787
|
+
return {
|
|
788
|
+
label: line.slice(markerStart + 2, labelEnd),
|
|
789
|
+
contentStart
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
function parseBlockHtmlTagStart(line) {
|
|
793
|
+
const start = skipLeadingBlockIndent(line);
|
|
794
|
+
if (start === -1 || start >= line.length || line[start] !== "<") {
|
|
795
|
+
return null;
|
|
796
|
+
}
|
|
797
|
+
let index = start + 1;
|
|
798
|
+
let closing = false;
|
|
799
|
+
if (index < line.length && line[index] === "/") {
|
|
800
|
+
closing = true;
|
|
801
|
+
index += 1;
|
|
802
|
+
}
|
|
803
|
+
if (index >= line.length || !isAsciiLetter(line[index])) {
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
const tagNameStart = index;
|
|
807
|
+
while (index < line.length && isHtmlTagNameChar(line[index])) {
|
|
808
|
+
index += 1;
|
|
809
|
+
}
|
|
810
|
+
const tagName = line.slice(tagNameStart, index).toLowerCase();
|
|
811
|
+
if (!BLOCK_HTML_TAGS.has(tagName)) {
|
|
812
|
+
return null;
|
|
813
|
+
}
|
|
814
|
+
if (closing) {
|
|
815
|
+
index = skipHtmlWhitespace(line, index);
|
|
816
|
+
if (index >= line.length || line[index] !== ">") {
|
|
817
|
+
return null;
|
|
818
|
+
}
|
|
819
|
+
return {
|
|
820
|
+
tagName,
|
|
821
|
+
tagEnd: index + 1,
|
|
822
|
+
closing: true,
|
|
823
|
+
selfClosing: false
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
while (index < line.length) {
|
|
827
|
+
index = skipHtmlWhitespace(line, index);
|
|
828
|
+
if (index >= line.length) {
|
|
829
|
+
return null;
|
|
830
|
+
}
|
|
831
|
+
if (line[index] === ">") {
|
|
832
|
+
return {
|
|
833
|
+
tagName,
|
|
834
|
+
tagEnd: index + 1,
|
|
835
|
+
closing: false,
|
|
836
|
+
selfClosing: false
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
if (line[index] === "/") {
|
|
840
|
+
const selfClosingStart = skipHtmlWhitespace(line, index + 1);
|
|
841
|
+
if (selfClosingStart >= line.length || line[selfClosingStart] !== ">") {
|
|
842
|
+
return null;
|
|
843
|
+
}
|
|
844
|
+
return {
|
|
845
|
+
tagName,
|
|
846
|
+
tagEnd: selfClosingStart + 1,
|
|
847
|
+
closing: false,
|
|
848
|
+
selfClosing: true
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
if (!isHtmlAttributeNameStartChar(line[index])) {
|
|
852
|
+
return null;
|
|
853
|
+
}
|
|
854
|
+
index += 1;
|
|
855
|
+
while (index < line.length && isHtmlAttributeNameChar(line[index])) {
|
|
856
|
+
index += 1;
|
|
857
|
+
}
|
|
858
|
+
index = skipHtmlWhitespace(line, index);
|
|
859
|
+
if (index >= line.length || line[index] !== "=") {
|
|
860
|
+
continue;
|
|
861
|
+
}
|
|
862
|
+
index = skipHtmlWhitespace(line, index + 1);
|
|
863
|
+
if (index >= line.length) {
|
|
864
|
+
return null;
|
|
865
|
+
}
|
|
866
|
+
const quote = line[index];
|
|
867
|
+
if (quote === '"' || quote === "'") {
|
|
868
|
+
index += 1;
|
|
869
|
+
while (index < line.length && line[index] !== quote) {
|
|
870
|
+
index += 1;
|
|
871
|
+
}
|
|
872
|
+
if (index >= line.length) {
|
|
873
|
+
return null;
|
|
874
|
+
}
|
|
875
|
+
index += 1;
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
while (index < line.length && !isHtmlWhitespace(line[index]) && line[index] !== ">") {
|
|
879
|
+
const char = line[index];
|
|
880
|
+
if (char === '"' || char === "'" || char === "<" || char === "=" || char === "`") {
|
|
881
|
+
return null;
|
|
882
|
+
}
|
|
883
|
+
index += 1;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
return null;
|
|
887
|
+
}
|
|
888
|
+
function containsClosingHtmlTag(line, tagName, fromIndex = 0) {
|
|
889
|
+
const lowerLine = line.toLowerCase();
|
|
890
|
+
const needle = `</${tagName}`;
|
|
891
|
+
let searchIndex = fromIndex;
|
|
892
|
+
while (searchIndex < lowerLine.length) {
|
|
893
|
+
const matchIndex = lowerLine.indexOf(needle, searchIndex);
|
|
894
|
+
if (matchIndex === -1) {
|
|
895
|
+
return false;
|
|
896
|
+
}
|
|
897
|
+
let endIndex = matchIndex + needle.length;
|
|
898
|
+
while (endIndex < lowerLine.length && isHtmlWhitespace(lowerLine[endIndex])) {
|
|
899
|
+
endIndex += 1;
|
|
900
|
+
}
|
|
901
|
+
if (endIndex < lowerLine.length && lowerLine[endIndex] === ">") {
|
|
902
|
+
return true;
|
|
903
|
+
}
|
|
904
|
+
searchIndex = matchIndex + 1;
|
|
905
|
+
}
|
|
906
|
+
return false;
|
|
907
|
+
}
|
|
908
|
+
function parseListMarker(line) {
|
|
909
|
+
const markerStart = skipLeadingBlockIndent(line);
|
|
910
|
+
if (markerStart === -1 || markerStart >= line.length) {
|
|
911
|
+
return null;
|
|
912
|
+
}
|
|
913
|
+
const marker = line[markerStart];
|
|
914
|
+
if (marker === "-" || marker === "+" || marker === "*") {
|
|
915
|
+
return parseBulletListMarker(line, markerStart);
|
|
916
|
+
}
|
|
917
|
+
if (isDigit(marker)) {
|
|
918
|
+
return parseOrderedListMarker(line, markerStart);
|
|
919
|
+
}
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
function parseBulletListMarker(line, markerStart) {
|
|
923
|
+
const contentStart = parseContentStart(line, markerStart + 1);
|
|
924
|
+
if (contentStart === null) {
|
|
925
|
+
return null;
|
|
926
|
+
}
|
|
927
|
+
return {
|
|
928
|
+
ordered: false,
|
|
929
|
+
indent: measureColumns(line.slice(0, markerStart)),
|
|
930
|
+
contentIndent: measureColumns(line.slice(0, contentStart)),
|
|
931
|
+
contentStart
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
function parseOrderedListMarker(line, markerStart) {
|
|
935
|
+
let markerEnd = markerStart;
|
|
936
|
+
while (markerEnd < line.length && isDigit(line[markerEnd])) {
|
|
937
|
+
markerEnd += 1;
|
|
938
|
+
}
|
|
939
|
+
if (markerEnd >= line.length || (line[markerEnd] !== "." && line[markerEnd] !== ")")) {
|
|
940
|
+
return null;
|
|
941
|
+
}
|
|
942
|
+
const contentStart = parseContentStart(line, markerEnd + 1);
|
|
943
|
+
if (contentStart === null) {
|
|
944
|
+
return null;
|
|
945
|
+
}
|
|
946
|
+
return {
|
|
947
|
+
ordered: true,
|
|
948
|
+
start: Number.parseInt(line.slice(markerStart, markerEnd), 10),
|
|
949
|
+
indent: measureColumns(line.slice(0, markerStart)),
|
|
950
|
+
contentIndent: measureColumns(line.slice(0, contentStart)),
|
|
951
|
+
contentStart
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
function parseContentStart(line, afterMarker) {
|
|
955
|
+
if (afterMarker >= line.length) {
|
|
956
|
+
return afterMarker;
|
|
957
|
+
}
|
|
958
|
+
if (line[afterMarker] !== " " && line[afterMarker] !== "\t") {
|
|
959
|
+
return null;
|
|
960
|
+
}
|
|
961
|
+
let pos = afterMarker;
|
|
962
|
+
while (pos < line.length && (line[pos] === " " || line[pos] === "\t")) {
|
|
963
|
+
pos += 1;
|
|
964
|
+
}
|
|
965
|
+
return pos;
|
|
966
|
+
}
|
|
967
|
+
function readLine(input, position) {
|
|
968
|
+
let index = position;
|
|
969
|
+
while (index < input.length) {
|
|
970
|
+
const char = input[index];
|
|
971
|
+
if (char === "\n" || char === "\r") {
|
|
972
|
+
break;
|
|
973
|
+
}
|
|
974
|
+
index += 1;
|
|
975
|
+
}
|
|
976
|
+
const text = input.slice(position, index);
|
|
977
|
+
if (index >= input.length) {
|
|
978
|
+
return { text, nextPosition: input.length };
|
|
979
|
+
}
|
|
980
|
+
if (input[index] === "\r" && input[index + 1] === "\n") {
|
|
981
|
+
return { text, nextPosition: index + 2 };
|
|
982
|
+
}
|
|
983
|
+
return { text, nextPosition: index + 1 };
|
|
984
|
+
}
|
|
985
|
+
function isBlankLine(line) {
|
|
986
|
+
for (let index = 0; index < line.length; index += 1) {
|
|
987
|
+
const char = line[index];
|
|
988
|
+
if (char !== " " && char !== "\t") {
|
|
989
|
+
return false;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
return true;
|
|
993
|
+
}
|
|
994
|
+
function skipLeadingBlockIndent(line) {
|
|
995
|
+
const leadingWhitespace = readLeadingWhitespace(line);
|
|
996
|
+
if (leadingWhitespace.columns > 3) {
|
|
997
|
+
return -1;
|
|
998
|
+
}
|
|
999
|
+
return leadingWhitespace.offset;
|
|
1000
|
+
}
|
|
1001
|
+
function trimAsciiWhitespace(value) {
|
|
1002
|
+
return trimAsciiWhitespaceEnd(trimAsciiWhitespaceStart(value));
|
|
1003
|
+
}
|
|
1004
|
+
function trimAsciiWhitespaceStart(value) {
|
|
1005
|
+
let start = 0;
|
|
1006
|
+
while (start < value.length) {
|
|
1007
|
+
const char = value[start];
|
|
1008
|
+
if (char !== " " && char !== "\t") {
|
|
1009
|
+
break;
|
|
1010
|
+
}
|
|
1011
|
+
start += 1;
|
|
1012
|
+
}
|
|
1013
|
+
return value.slice(start);
|
|
1014
|
+
}
|
|
1015
|
+
function trimAsciiWhitespaceEnd(value) {
|
|
1016
|
+
let end = value.length;
|
|
1017
|
+
while (end > 0) {
|
|
1018
|
+
const char = value[end - 1];
|
|
1019
|
+
if (char !== " " && char !== "\t") {
|
|
1020
|
+
break;
|
|
1021
|
+
}
|
|
1022
|
+
end -= 1;
|
|
1023
|
+
}
|
|
1024
|
+
return value.slice(0, end);
|
|
1025
|
+
}
|
|
1026
|
+
function findWhitespaceIndex(value) {
|
|
1027
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
1028
|
+
const char = value[index];
|
|
1029
|
+
if (char === " " || char === "\t") {
|
|
1030
|
+
return index;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
return -1;
|
|
1034
|
+
}
|
|
1035
|
+
function skipHtmlWhitespace(line, start) {
|
|
1036
|
+
let index = start;
|
|
1037
|
+
while (index < line.length && isHtmlWhitespace(line[index])) {
|
|
1038
|
+
index += 1;
|
|
1039
|
+
}
|
|
1040
|
+
return index;
|
|
1041
|
+
}
|
|
1042
|
+
function isDigit(value) {
|
|
1043
|
+
return value >= "0" && value <= "9";
|
|
1044
|
+
}
|
|
1045
|
+
function isAsciiLetter(value) {
|
|
1046
|
+
return (value >= "a" && value <= "z") || (value >= "A" && value <= "Z");
|
|
1047
|
+
}
|
|
1048
|
+
function isHtmlTagNameChar(value) {
|
|
1049
|
+
return isAsciiLetter(value) || isDigit(value) || value === "-";
|
|
1050
|
+
}
|
|
1051
|
+
function isHtmlAttributeNameStartChar(value) {
|
|
1052
|
+
return isAsciiLetter(value) || value === ":" || value === "_";
|
|
1053
|
+
}
|
|
1054
|
+
function isHtmlAttributeNameChar(value) {
|
|
1055
|
+
return isHtmlAttributeNameStartChar(value) || isDigit(value) || value === "-" || value === ".";
|
|
1056
|
+
}
|
|
1057
|
+
function isHtmlWhitespace(value) {
|
|
1058
|
+
return value === " " || value === "\t";
|
|
1059
|
+
}
|
|
1060
|
+
function isFootnoteLabelChar(value) {
|
|
1061
|
+
return isAsciiLetter(value) || isDigit(value) || value === "-" || value === "_";
|
|
1062
|
+
}
|
|
1063
|
+
function isAlertKind(value) {
|
|
1064
|
+
return (value === "NOTE" ||
|
|
1065
|
+
value === "TIP" ||
|
|
1066
|
+
value === "IMPORTANT" ||
|
|
1067
|
+
value === "WARNING" ||
|
|
1068
|
+
value === "CAUTION");
|
|
1069
|
+
}
|
|
1070
|
+
function stripBom(input) {
|
|
1071
|
+
return input[0] === "\uFEFF" ? input.slice(1) : input;
|
|
1072
|
+
}
|
|
1073
|
+
function parseListItem(state, list) {
|
|
1074
|
+
const firstLine = readLine(state.input, state.position);
|
|
1075
|
+
const marker = parseListMarker(firstLine.text);
|
|
1076
|
+
if (marker === null || marker.ordered !== list.ordered || marker.indent !== list.indent) {
|
|
1077
|
+
return null;
|
|
1078
|
+
}
|
|
1079
|
+
state.position = firstLine.nextPosition;
|
|
1080
|
+
let firstLineContent = firstLine.text.slice(marker.contentStart);
|
|
1081
|
+
let checked;
|
|
1082
|
+
const taskMarker = parseTaskMarker(firstLineContent);
|
|
1083
|
+
if (taskMarker !== null) {
|
|
1084
|
+
checked = taskMarker.checked;
|
|
1085
|
+
firstLineContent = taskMarker.content;
|
|
1086
|
+
}
|
|
1087
|
+
const continuationLines = [];
|
|
1088
|
+
const pendingBlankLines = [];
|
|
1089
|
+
while (state.position < state.input.length) {
|
|
1090
|
+
const line = readLine(state.input, state.position);
|
|
1091
|
+
if (isBlankLine(line.text)) {
|
|
1092
|
+
pendingBlankLines.push("");
|
|
1093
|
+
state.position = line.nextPosition;
|
|
1094
|
+
continue;
|
|
1095
|
+
}
|
|
1096
|
+
const nextMarker = parseListMarker(line.text);
|
|
1097
|
+
if (nextMarker !== null &&
|
|
1098
|
+
nextMarker.ordered === list.ordered &&
|
|
1099
|
+
nextMarker.indent === list.indent) {
|
|
1100
|
+
break;
|
|
1101
|
+
}
|
|
1102
|
+
const strippedLine = stripIndent(line.text, marker.contentIndent);
|
|
1103
|
+
if (strippedLine === null) {
|
|
1104
|
+
break;
|
|
1105
|
+
}
|
|
1106
|
+
state.position = line.nextPosition;
|
|
1107
|
+
continuationLines.push(...pendingBlankLines, strippedLine);
|
|
1108
|
+
pendingBlankLines.length = 0;
|
|
1109
|
+
}
|
|
1110
|
+
const children = parseListItemChildren(firstLineContent, continuationLines, list.preferListToThematicBreak);
|
|
1111
|
+
return {
|
|
1112
|
+
type: "listItem",
|
|
1113
|
+
...(checked === undefined ? {} : { checked }),
|
|
1114
|
+
children
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
function parseListItemChildren(firstLineContent, continuationLines, preferListToThematicBreak) {
|
|
1118
|
+
const blocks = [];
|
|
1119
|
+
let paragraphLines = firstLineContent.length === 0 ? [] : [firstLineContent];
|
|
1120
|
+
let lineIndex = 0;
|
|
1121
|
+
while (lineIndex < continuationLines.length) {
|
|
1122
|
+
const line = continuationLines[lineIndex];
|
|
1123
|
+
if (isBlankLine(line)) {
|
|
1124
|
+
if (paragraphLines.length > 0) {
|
|
1125
|
+
blocks.push(createParagraphNode(paragraphLines));
|
|
1126
|
+
paragraphLines = [];
|
|
1127
|
+
}
|
|
1128
|
+
lineIndex += 1;
|
|
1129
|
+
continue;
|
|
1130
|
+
}
|
|
1131
|
+
if (startsBlockInLines(continuationLines, lineIndex, preferListToThematicBreak)) {
|
|
1132
|
+
if (paragraphLines.length > 0) {
|
|
1133
|
+
blocks.push(createParagraphNode(paragraphLines));
|
|
1134
|
+
}
|
|
1135
|
+
blocks.push(...parseBlocksWithOptions(continuationLines.slice(lineIndex).join("\n"), {
|
|
1136
|
+
preferListToThematicBreak
|
|
1137
|
+
}));
|
|
1138
|
+
return blocks;
|
|
1139
|
+
}
|
|
1140
|
+
paragraphLines.push(line);
|
|
1141
|
+
lineIndex += 1;
|
|
1142
|
+
}
|
|
1143
|
+
if (paragraphLines.length > 0) {
|
|
1144
|
+
blocks.push(createParagraphNode(paragraphLines));
|
|
1145
|
+
}
|
|
1146
|
+
return blocks;
|
|
1147
|
+
}
|
|
1148
|
+
function createParagraphNode(lines) {
|
|
1149
|
+
return {
|
|
1150
|
+
type: "paragraph",
|
|
1151
|
+
children: [{ type: "text", value: lines.join("\n") }]
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
function parseTaskMarker(content) {
|
|
1155
|
+
if (content.length < 3 || content[0] !== "[" || content[2] !== "]") {
|
|
1156
|
+
return null;
|
|
1157
|
+
}
|
|
1158
|
+
const marker = content[1];
|
|
1159
|
+
if (marker !== " " && marker !== "x" && marker !== "X") {
|
|
1160
|
+
return null;
|
|
1161
|
+
}
|
|
1162
|
+
if (content.length > 3 && content[3] !== " " && content[3] !== "\t") {
|
|
1163
|
+
return null;
|
|
1164
|
+
}
|
|
1165
|
+
return {
|
|
1166
|
+
checked: marker === "x" || marker === "X",
|
|
1167
|
+
content: trimAsciiWhitespaceStart(content.slice(3))
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
function stripIndent(line, columns) {
|
|
1171
|
+
const leadingWhitespace = readLeadingWhitespace(line);
|
|
1172
|
+
if (leadingWhitespace.columns < columns) {
|
|
1173
|
+
return null;
|
|
1174
|
+
}
|
|
1175
|
+
return leadingWhitespace.normalized.slice(columns) + line.slice(leadingWhitespace.offset);
|
|
1176
|
+
}
|
|
1177
|
+
function readLeadingWhitespace(line) {
|
|
1178
|
+
let columns = 0;
|
|
1179
|
+
let offset = 0;
|
|
1180
|
+
let normalized = "";
|
|
1181
|
+
while (offset < line.length) {
|
|
1182
|
+
const char = line[offset];
|
|
1183
|
+
if (char === " ") {
|
|
1184
|
+
columns += 1;
|
|
1185
|
+
normalized += " ";
|
|
1186
|
+
offset += 1;
|
|
1187
|
+
continue;
|
|
1188
|
+
}
|
|
1189
|
+
if (char === "\t") {
|
|
1190
|
+
columns += 4;
|
|
1191
|
+
normalized += " ";
|
|
1192
|
+
offset += 1;
|
|
1193
|
+
continue;
|
|
1194
|
+
}
|
|
1195
|
+
break;
|
|
1196
|
+
}
|
|
1197
|
+
return { columns, offset, normalized };
|
|
1198
|
+
}
|
|
1199
|
+
function measureColumns(value) {
|
|
1200
|
+
let columns = 0;
|
|
1201
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
1202
|
+
columns += value[index] === "\t" ? 4 : 1;
|
|
1203
|
+
}
|
|
1204
|
+
return columns;
|
|
1205
|
+
}
|