mdrefine 0.2.3 → 0.2.5
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/CHANGELOG.md +65 -0
- package/CONTRIBUTING.md +21 -1
- package/README.md +1 -1
- package/dist/core/engine.js +14 -3
- package/dist/core/engine.js.map +1 -1
- package/dist/rules/blocks.js +39 -4
- package/dist/rules/blocks.js.map +1 -1
- package/dist/rules/dialects.js +11 -0
- package/dist/rules/dialects.js.map +1 -1
- package/dist/rules/links.js +9 -2
- package/dist/rules/links.js.map +1 -1
- package/dist/rules/style.js +78 -1
- package/dist/rules/style.js.map +1 -1
- package/dist/syntax/misread-lists.d.ts +59 -8
- package/dist/syntax/misread-lists.js +273 -5
- package/dist/syntax/misread-lists.js.map +1 -1
- package/dist/syntax/obsidian.js +10 -2
- package/dist/syntax/obsidian.js.map +1 -1
- package/docs/design.md +7 -4
- package/docs/dialects.md +5 -2
- package/docs/obsidian.md +32 -0
- package/docs/quick-start.md +1 -1
- package/docs/rules.md +28 -14
- package/package.json +3 -1
|
@@ -6,25 +6,66 @@ import type { Document } from "../core/types.js";
|
|
|
6
6
|
* or `)`, and then a space, a tab, or the end of the line.
|
|
7
7
|
*/
|
|
8
8
|
export declare const listMarker: RegExp;
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* A line whose content, after blank space and block quote markers, starts with
|
|
11
|
+
* `:` and a space or tab. In a paragraph, such a line opens a definition
|
|
12
|
+
* description on Forgejo and Gitea.
|
|
13
|
+
*/
|
|
14
|
+
export declare const descriptionLine: RegExp;
|
|
15
|
+
/**
|
|
16
|
+
* Text that the parser read where renderers may read a list, or on Forgejo and
|
|
17
|
+
* Gitea a definition description, and the blocks after it.
|
|
18
|
+
*/
|
|
10
19
|
export interface MisreadLists {
|
|
11
20
|
/**
|
|
12
21
|
* Paragraphs, and headings underlined with `===` or `---`, whose text starts
|
|
13
|
-
* with a list marker, and the text that renderers read as continuing it.
|
|
22
|
+
* with a list marker, and the text that renderers read as continuing it. In
|
|
23
|
+
* the Obsidian dialect also those with a later line that Obsidian reads as
|
|
24
|
+
* starting a list item where CommonMark reads text (issue #375).
|
|
14
25
|
*/
|
|
15
26
|
text: ReadonlySet<Nodes>;
|
|
16
27
|
/**
|
|
17
|
-
* The blocks after such text in its container whose
|
|
18
|
-
* further right than the text, up to one that does not.
|
|
19
|
-
* them inside the list's last item
|
|
20
|
-
* item's text: an indented code block
|
|
28
|
+
* The blocks after such text, or after a description, in its container whose
|
|
29
|
+
* first lines start further right than the text, up to one that does not.
|
|
30
|
+
* Renderers may read them inside the list's last item or the description,
|
|
31
|
+
* where their indentation counts from the item's text: an indented code block
|
|
32
|
+
* can be a paragraph there.
|
|
21
33
|
*/
|
|
22
34
|
nested: ReadonlySet<Nodes>;
|
|
23
35
|
/**
|
|
24
|
-
* The block after those, which starts no further right than
|
|
25
|
-
* Renderers may read it as more items of the list.
|
|
36
|
+
* The block after those below such text, which starts no further right than
|
|
37
|
+
* the text. Renderers may read it as more items of the list.
|
|
26
38
|
*/
|
|
27
39
|
next: ReadonlySet<Nodes>;
|
|
40
|
+
/**
|
|
41
|
+
* In the Forgejo and Gitea dialects, paragraphs with a line that opens a
|
|
42
|
+
* definition description, as `Term` and `: 2. x` do. Those renderers read
|
|
43
|
+
* the description as blocks, here an ordered list (issue #344).
|
|
44
|
+
*/
|
|
45
|
+
descriptions: ReadonlySet<Nodes>;
|
|
46
|
+
/**
|
|
47
|
+
* In the Obsidian dialect, paragraphs, headings, and table cells whose text
|
|
48
|
+
* holds a backtick that no run of the same length closes, which the parser
|
|
49
|
+
* leaves as text, also in a highlight, an inline comment, or an image's
|
|
50
|
+
* description. Obsidian's Live Preview shows the text after it as code, at
|
|
51
|
+
* least to the end of its line, and Reading view pairs a run of two or more
|
|
52
|
+
* with a later, shorter one, as in ``a ``` b `c` d`` (issue #362).
|
|
53
|
+
*
|
|
54
|
+
* After a run of three or more, Live Preview shows the blocks below as code
|
|
55
|
+
* too, also out of a list item and across blank lines, up to a block with a
|
|
56
|
+
* run of the same length outside an indented code block, which it closes
|
|
57
|
+
* there, a fenced code block, or a list item. Those blocks are in the set as
|
|
58
|
+
* well, with a table that holds such a run.
|
|
59
|
+
*/
|
|
60
|
+
unclosedCode: ReadonlySet<Nodes>;
|
|
61
|
+
/**
|
|
62
|
+
* In the Obsidian dialect, the blocks that Reading view reads as more of an
|
|
63
|
+
* HTML block above them. A line of blank space directly below an HTML block
|
|
64
|
+
* that ends at a blank line continues the block, and so do the blocks after
|
|
65
|
+
* it, up to an empty line (issue #358). Each counts from the start of its
|
|
66
|
+
* first line, with the marker of a list item there.
|
|
67
|
+
*/
|
|
68
|
+
htmlText: ReadonlySet<Nodes>;
|
|
28
69
|
}
|
|
29
70
|
/**
|
|
30
71
|
* Where renderers may read a list in text that the parser read as text.
|
|
@@ -44,5 +85,15 @@ export interface MisreadLists {
|
|
|
44
85
|
* continues it too, and a block there is nested: a `---` would underline it.
|
|
45
86
|
* Where such text ends a list item or block quote, renderers continue it
|
|
46
87
|
* lazily into a paragraph or heading on the next line below the container.
|
|
88
|
+
*
|
|
89
|
+
* Forgejo and Gitea read a definition list, which the parser reads as text:
|
|
90
|
+
* `Term` and a line `: 2. x` below it are a term and a description, and the
|
|
91
|
+
* description holds blocks, here an ordered list, as a list item does. The
|
|
92
|
+
* blocks indented below it in its container belong to it too (issue #344).
|
|
93
|
+
*
|
|
94
|
+
* Obsidian starts a list below a paragraph line where CommonMark does not:
|
|
95
|
+
* Live Preview at an ordered marker with a number other than 1 and text after
|
|
96
|
+
* it, except in a block quote, and Reading view at an empty item, `*`, `+`,
|
|
97
|
+
* `- `, or `1.`, which Live Preview reads so for `+ ` and `- ` (issue #375).
|
|
47
98
|
*/
|
|
48
99
|
export declare function misreadLists(document: Document): MisreadLists;
|
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
* or `)`, and then a space, a tab, or the end of the line.
|
|
5
5
|
*/
|
|
6
6
|
export const listMarker = /^(?:[-+*]|\d{1,9}[.)])(?:[ \t\r\n]|$)/;
|
|
7
|
+
/**
|
|
8
|
+
* A line whose content, after blank space and block quote markers, starts with
|
|
9
|
+
* `:` and a space or tab. In a paragraph, such a line opens a definition
|
|
10
|
+
* description on Forgejo and Gitea.
|
|
11
|
+
*/
|
|
12
|
+
export const descriptionLine = /^[ \t>]*:[ \t]/m;
|
|
7
13
|
/** Leaf blocks: their children, if they have any, are not blocks. */
|
|
8
14
|
const leaves = new Set(["paragraph", "heading", "table", "code", "html"]);
|
|
9
15
|
const found = new WeakMap();
|
|
@@ -25,15 +31,28 @@ const found = new WeakMap();
|
|
|
25
31
|
* continues it too, and a block there is nested: a `---` would underline it.
|
|
26
32
|
* Where such text ends a list item or block quote, renderers continue it
|
|
27
33
|
* lazily into a paragraph or heading on the next line below the container.
|
|
34
|
+
*
|
|
35
|
+
* Forgejo and Gitea read a definition list, which the parser reads as text:
|
|
36
|
+
* `Term` and a line `: 2. x` below it are a term and a description, and the
|
|
37
|
+
* description holds blocks, here an ordered list, as a list item does. The
|
|
38
|
+
* blocks indented below it in its container belong to it too (issue #344).
|
|
39
|
+
*
|
|
40
|
+
* Obsidian starts a list below a paragraph line where CommonMark does not:
|
|
41
|
+
* Live Preview at an ordered marker with a number other than 1 and text after
|
|
42
|
+
* it, except in a block quote, and Reading view at an empty item, `*`, `+`,
|
|
43
|
+
* `- `, or `1.`, which Live Preview reads so for `+ ` and `- ` (issue #375).
|
|
28
44
|
*/
|
|
29
45
|
export function misreadLists(document) {
|
|
30
46
|
const known = found.get(document.tree);
|
|
31
47
|
if (known)
|
|
32
48
|
return known;
|
|
33
49
|
const { source } = document;
|
|
50
|
+
const forge = document.dialect === "forgejo" || document.dialect === "gitea";
|
|
34
51
|
const text = new Set();
|
|
35
52
|
const nested = new Set();
|
|
36
53
|
const next = new Set();
|
|
54
|
+
const descriptions = new Set();
|
|
55
|
+
const obsidian = document.dialect === "obsidian";
|
|
37
56
|
/** The column of the first character from `offset` on, after spaces and tabs. */
|
|
38
57
|
const columnAt = (offset) => {
|
|
39
58
|
let start = offset;
|
|
@@ -60,26 +79,69 @@ export function misreadLists(document) {
|
|
|
60
79
|
return node.children[0]?.position?.start.offset ?? start;
|
|
61
80
|
return undefined;
|
|
62
81
|
};
|
|
82
|
+
/**
|
|
83
|
+
* In the Obsidian dialect, the offset of the marker on the first line of
|
|
84
|
+
* `node` after its first that Obsidian reads as starting a list item where
|
|
85
|
+
* CommonMark reads text; `quoted` says whether `node` is in a block quote.
|
|
86
|
+
*/
|
|
87
|
+
const obsidianItem = (node, quoted) => {
|
|
88
|
+
const end = node.position.end.offset;
|
|
89
|
+
// A marker four or more columns right of the text is more of the text.
|
|
90
|
+
const text = columnAt(node.position.start.offset);
|
|
91
|
+
const breaks = /\r\n|\r|\n/g;
|
|
92
|
+
breaks.lastIndex = node.position.start.offset;
|
|
93
|
+
for (let found = breaks.exec(source); found && found.index < end; found = breaks.exec(source)) {
|
|
94
|
+
const lineStart = found.index + found[0].length;
|
|
95
|
+
let lineEnd = lineStart;
|
|
96
|
+
while (lineEnd < end && source[lineEnd] !== "\n" && source[lineEnd] !== "\r")
|
|
97
|
+
lineEnd++;
|
|
98
|
+
const line = source.slice(lineStart, lineEnd);
|
|
99
|
+
const prefix = /^[ \t>]*/.exec(line)[0].length;
|
|
100
|
+
const content = line.slice(prefix);
|
|
101
|
+
const ordered = /^(\d{1,9})[.)][ \t]+\S/.exec(content);
|
|
102
|
+
if (columnAt(lineStart + prefix) - text <= 3 &&
|
|
103
|
+
((ordered && Number(ordered[1]) !== 1 && !quoted) ||
|
|
104
|
+
/^(?:[*+]|-(?=[ \t])|0*1[.)])[ \t]*$/.test(content)))
|
|
105
|
+
return lineStart + prefix;
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
};
|
|
63
109
|
/** Returns the last line of misread text that ends `parent` and whose `===` renderers read as text. */
|
|
64
|
-
const visit = (parent) => {
|
|
110
|
+
const visit = (parent, quoted = false) => {
|
|
65
111
|
let reach;
|
|
66
112
|
/** The last line of misread text whose `===` renderers read as text, if the last block is that. */
|
|
67
113
|
let continued;
|
|
68
114
|
/** Whether that text ends the last block, a container, rather than being it. */
|
|
69
115
|
let inside = false;
|
|
116
|
+
/** The column of the last definition description while the blocks after it may belong to it. */
|
|
117
|
+
let described;
|
|
70
118
|
parent.children.forEach((child, index) => {
|
|
71
119
|
const offset = child.position?.start.offset;
|
|
72
120
|
if (offset === undefined)
|
|
73
121
|
return;
|
|
74
122
|
const start = textStart(child);
|
|
123
|
+
if (described !== undefined) {
|
|
124
|
+
if (columnAt(offset) > described)
|
|
125
|
+
nested.add(child);
|
|
126
|
+
else
|
|
127
|
+
described = undefined;
|
|
128
|
+
}
|
|
129
|
+
if (forge &&
|
|
130
|
+
start !== undefined &&
|
|
131
|
+
descriptionLine.test(source.slice(offset, child.position.end.offset))) {
|
|
132
|
+
descriptions.add(child);
|
|
133
|
+
described = Math.min(described ?? columnAt(offset), columnAt(offset));
|
|
134
|
+
}
|
|
75
135
|
// Renderers continue the text lazily on the line below the container
|
|
76
136
|
// that it ends, but only with text (issue #343).
|
|
77
137
|
const adjacent = continued === child.position.start.line - 1 && (!inside || start !== undefined);
|
|
78
|
-
const
|
|
138
|
+
const atStart = start !== undefined &&
|
|
79
139
|
(listMarker.test(source.slice(start, start + 11)) || adjacent) &&
|
|
80
140
|
!(index === 0 && parent.type === "listItem" && typeof parent.checked === "boolean");
|
|
141
|
+
const item = obsidian && start !== undefined ? obsidianItem(child, quoted) : undefined;
|
|
142
|
+
const misread = atStart || item !== undefined;
|
|
81
143
|
if (misread || adjacent || reach !== undefined) {
|
|
82
|
-
const column = columnAt(
|
|
144
|
+
const column = columnAt(atStart ? start : (item ?? offset));
|
|
83
145
|
if ((adjacent && !misread) || (reach !== undefined && column > reach))
|
|
84
146
|
nested.add(child);
|
|
85
147
|
else if (reach !== undefined) {
|
|
@@ -97,7 +159,7 @@ export function misreadLists(document) {
|
|
|
97
159
|
: undefined;
|
|
98
160
|
inside = false;
|
|
99
161
|
if ("children" in child && !leaves.has(child.type)) {
|
|
100
|
-
const last = visit(child);
|
|
162
|
+
const last = visit(child, quoted || child.type === "blockquote");
|
|
101
163
|
if (last !== undefined && last === child.position.end.line) {
|
|
102
164
|
continued = last;
|
|
103
165
|
inside = true;
|
|
@@ -107,8 +169,214 @@ export function misreadLists(document) {
|
|
|
107
169
|
return continued;
|
|
108
170
|
};
|
|
109
171
|
visit(document.tree);
|
|
110
|
-
const
|
|
172
|
+
const htmlText = new Set();
|
|
173
|
+
const unclosedCode = new Set();
|
|
174
|
+
if (document.dialect === "obsidian") {
|
|
175
|
+
/**
|
|
176
|
+
* Leaf blocks in document order, and whether each starts a list item, also
|
|
177
|
+
* inside a container that does, as in `- > a`.
|
|
178
|
+
*/
|
|
179
|
+
const order = [];
|
|
180
|
+
const collect = (node, item) => {
|
|
181
|
+
if (leaves.has(node.type) || !("children" in node))
|
|
182
|
+
order.push([node, item]);
|
|
183
|
+
else
|
|
184
|
+
node.children.forEach((child, index) => collect(child, index === 0 && (item || node.type === "listItem")));
|
|
185
|
+
};
|
|
186
|
+
collect(document.tree, false);
|
|
187
|
+
const lines = source.split(/\r\n|\r|\n/);
|
|
188
|
+
/** Whether line `number`, counted from 1, holds blank space and more than block quote markers. */
|
|
189
|
+
const spaced = (number) => {
|
|
190
|
+
const line = lines[number - 1] ?? "";
|
|
191
|
+
return /^[ \t>]*$/.test(line) && /[^>]/.test(line);
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Whether the last leaf block is an HTML block that ends at a blank line, or
|
|
195
|
+
* text that Obsidian reads as more of one, which the next block may continue.
|
|
196
|
+
* Leaf blocks count, not containers, because an empty line inside a list
|
|
197
|
+
* ends the HTML block there.
|
|
198
|
+
*/
|
|
199
|
+
let open = false;
|
|
200
|
+
order.forEach(([leaf], index) => {
|
|
201
|
+
const previous = order[index - 1]?.[0];
|
|
202
|
+
if (open && previous?.position && leaf.position) {
|
|
203
|
+
for (let line = previous.position.end.line + 1; line < leaf.position.start.line; line++)
|
|
204
|
+
if (!spaced(line))
|
|
205
|
+
open = false;
|
|
206
|
+
if (open) {
|
|
207
|
+
// From the start of its line: a list item's marker there, `- ` in
|
|
208
|
+
// `- *a*`, is text of the HTML block too.
|
|
209
|
+
const offset = leaf.position.start.offset ?? 0;
|
|
210
|
+
let from = offset;
|
|
211
|
+
while (from > 0 && source[from - 1] !== "\n" && source[from - 1] !== "\r")
|
|
212
|
+
from--;
|
|
213
|
+
const start = { ...leaf.position.start, offset: from, column: 1 };
|
|
214
|
+
htmlText.add(from === offset ? leaf : { ...leaf, position: { ...leaf.position, start } });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// Other HTML blocks end at their own end marker, as a comment does at `-->`.
|
|
218
|
+
if (!open &&
|
|
219
|
+
leaf.type === "html" &&
|
|
220
|
+
leaf.position &&
|
|
221
|
+
!/^<(?:!--|\?|!\[CDATA\[|![A-Za-z]|(?:script|pre|style|textarea)(?:[\s>]|$))/i.test(leaf.value.trimStart()))
|
|
222
|
+
open = spaced(leaf.position.end.line + 1);
|
|
223
|
+
});
|
|
224
|
+
/**
|
|
225
|
+
* The runs of backticks that nothing closes in the text of `node`, outside
|
|
226
|
+
* code, math, and wikilinks. Live Preview starts code at them also inside a
|
|
227
|
+
* highlight, an inline comment, and an image's description, whose source
|
|
228
|
+
* the parser does not read as code spans; a backtick in a link's
|
|
229
|
+
* destination or title starts none, but counts in an image's source.
|
|
230
|
+
*/
|
|
231
|
+
const openRuns = (node) => {
|
|
232
|
+
const start = node.position?.start.offset;
|
|
233
|
+
const end = node.position?.end.offset;
|
|
234
|
+
if (start === undefined || end === undefined)
|
|
235
|
+
return [];
|
|
236
|
+
if (node.type === "obsidianHighlight" ||
|
|
237
|
+
node.type === "obsidianComment" ||
|
|
238
|
+
node.type === "image" ||
|
|
239
|
+
node.type === "imageReference")
|
|
240
|
+
return unclosedRuns(source, start, end);
|
|
241
|
+
// The parser reads every run that another closes as code, so every one
|
|
242
|
+
// left in text is unclosed.
|
|
243
|
+
if (node.type === "text")
|
|
244
|
+
return backtickRuns(source, start, end);
|
|
245
|
+
return "children" in node ? node.children.flatMap(openRuns) : [];
|
|
246
|
+
};
|
|
247
|
+
/**
|
|
248
|
+
* The length of a run of three or more backticks whose code Live Preview
|
|
249
|
+
* carries into the blocks below, up to a block with a run of the same
|
|
250
|
+
* length, a fenced code block, or a list item. A run in a wikilink, in math,
|
|
251
|
+
* or in an HTML block closes it too, because Live Preview reads none of
|
|
252
|
+
* those inside the code.
|
|
253
|
+
*/
|
|
254
|
+
let carry;
|
|
255
|
+
for (const [leaf, item] of order) {
|
|
256
|
+
const start = leaf.position?.start.offset;
|
|
257
|
+
const end = leaf.position?.end.offset;
|
|
258
|
+
if (start === undefined || end === undefined)
|
|
259
|
+
continue;
|
|
260
|
+
if (carry !== undefined) {
|
|
261
|
+
const fenced = leaf.type === "code" && /^ {0,3}(?:```|~~~)/.test(source.slice(start, end));
|
|
262
|
+
if (item || fenced)
|
|
263
|
+
carry = undefined;
|
|
264
|
+
else {
|
|
265
|
+
unclosedCode.add(leaf);
|
|
266
|
+
// Live Preview shows an indented code block there as more of the
|
|
267
|
+
// code, and its backticks close nothing.
|
|
268
|
+
if (leaf.type === "code")
|
|
269
|
+
continue;
|
|
270
|
+
const runs = backtickRuns(source, start, end);
|
|
271
|
+
const close = runs.findIndex(([, length]) => length === carry);
|
|
272
|
+
if (close >= 0)
|
|
273
|
+
carry = carried(source, runs.slice(close + 1));
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const parts = leaf.type === "table"
|
|
278
|
+
? leaf.children.flatMap((row) => row.children)
|
|
279
|
+
: leaf.type === "paragraph" || leaf.type === "heading"
|
|
280
|
+
? [leaf]
|
|
281
|
+
: [];
|
|
282
|
+
const runs = parts.flatMap((part) => {
|
|
283
|
+
const open = openRuns(part);
|
|
284
|
+
if (open.length > 0)
|
|
285
|
+
unclosedCode.add(part);
|
|
286
|
+
return open;
|
|
287
|
+
});
|
|
288
|
+
const long = runs.find(([, length]) => length >= 3);
|
|
289
|
+
if (long === undefined)
|
|
290
|
+
continue;
|
|
291
|
+
// Live Preview shows the rest of a table as code from such a run.
|
|
292
|
+
if (leaf.type === "table")
|
|
293
|
+
unclosedCode.add(leaf);
|
|
294
|
+
const after = backtickRuns(source, long[0] + long[1], end);
|
|
295
|
+
const close = after.findIndex(([, length]) => length === long[1]);
|
|
296
|
+
carry = close < 0 ? long[1] : carried(source, after.slice(close + 1));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const result = { text, nested, next, descriptions, unclosedCode, htmlText };
|
|
111
300
|
found.set(document.tree, result);
|
|
112
301
|
return result;
|
|
113
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* The runs of backticks from `start` to `end`. A backslash before a run
|
|
305
|
+
* escapes its first backtick only.
|
|
306
|
+
*/
|
|
307
|
+
function backtickRuns(source, start, end) {
|
|
308
|
+
const runs = [];
|
|
309
|
+
for (let at = source.indexOf("`", start); at >= 0 && at < end;) {
|
|
310
|
+
let after = at;
|
|
311
|
+
while (after < end && source[after] === "`")
|
|
312
|
+
after++;
|
|
313
|
+
let slashes = 0;
|
|
314
|
+
while (source[at - 1 - slashes] === "\\")
|
|
315
|
+
slashes++;
|
|
316
|
+
const from = slashes % 2 === 0 ? at : at + 1;
|
|
317
|
+
if (after > from)
|
|
318
|
+
runs.push([from, after - from]);
|
|
319
|
+
at = source.indexOf("`", after);
|
|
320
|
+
}
|
|
321
|
+
return runs;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* The runs of backticks from `start` to `end` that no later run of the same
|
|
325
|
+
* length there closes, as CommonMark pairs them into code spans.
|
|
326
|
+
*/
|
|
327
|
+
function unclosedRuns(source, start, end) {
|
|
328
|
+
const runs = backtickRuns(source, start, end);
|
|
329
|
+
/** The index of the next run of the same length after each run, or -1. */
|
|
330
|
+
const next = [];
|
|
331
|
+
const later = new Map();
|
|
332
|
+
for (let index = runs.length - 1; index >= 0; index--) {
|
|
333
|
+
const length = runs[index][1];
|
|
334
|
+
next[index] = later.get(length) ?? -1;
|
|
335
|
+
later.set(length, index);
|
|
336
|
+
}
|
|
337
|
+
const open = [];
|
|
338
|
+
for (let index = 0; index < runs.length; index++) {
|
|
339
|
+
if (next[index] < 0)
|
|
340
|
+
open.push(runs[index]);
|
|
341
|
+
else
|
|
342
|
+
index = next[index];
|
|
343
|
+
}
|
|
344
|
+
return open;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* The length of the run of three or more backticks whose code Live Preview
|
|
348
|
+
* carries past the last of `runs`, if any. Live Preview closes a run with the
|
|
349
|
+
* next run of the same length; the code of a run of one or two backticks ends
|
|
350
|
+
* with its line.
|
|
351
|
+
*/
|
|
352
|
+
function carried(source, runs) {
|
|
353
|
+
let open;
|
|
354
|
+
/** Where the line of the open run ends, and that of the current one. */
|
|
355
|
+
let openLineEnd = 0;
|
|
356
|
+
let lineEnd = -1;
|
|
357
|
+
for (const run of runs) {
|
|
358
|
+
if (run[0] >= lineEnd)
|
|
359
|
+
lineEnd = lineBreak(source, run[0]);
|
|
360
|
+
if (open !== undefined) {
|
|
361
|
+
const sameLine = run[0] < openLineEnd;
|
|
362
|
+
if (run[1] === open[1] && (open[1] >= 3 || sameLine)) {
|
|
363
|
+
open = undefined;
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
// Other runs are part of the code.
|
|
367
|
+
if (open[1] >= 3 || sameLine)
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
open = run;
|
|
371
|
+
openLineEnd = lineEnd;
|
|
372
|
+
}
|
|
373
|
+
return open !== undefined && open[1] >= 3 ? open[1] : undefined;
|
|
374
|
+
}
|
|
375
|
+
/** The offset of the first line break at or after `from`, or the length of `source`. */
|
|
376
|
+
function lineBreak(source, from) {
|
|
377
|
+
for (let at = from; at < source.length; at++)
|
|
378
|
+
if (source[at] === "\n" || source[at] === "\r")
|
|
379
|
+
return at;
|
|
380
|
+
return source.length;
|
|
381
|
+
}
|
|
114
382
|
//# sourceMappingURL=misread-lists.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"misread-lists.js","sourceRoot":"","sources":["../../src/syntax/misread-lists.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,uCAAuC,CAAC;AAuBlE,qEAAqE;AACrE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAgB,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AACzF,MAAM,KAAK,GAAG,IAAI,OAAO,EAAsB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,YAAY,CAAC,QAAkB;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAS,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAS,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAS,CAAC;IAC9B,iFAAiF;IACjF,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,EAAE;QAClC,IAAI,KAAK,GAAG,MAAM,CAAC;QACnB,OAAO,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI;YAAE,KAAK,EAAE,CAAC;QACtF,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;YAC9C,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;YAC7B,IAAI,EAAE,IAAI,MAAM,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,IAAI;gBAAE,MAAM;YACnE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IACF,kEAAkE;IAClE,MAAM,SAAS,GAAG,CAAC,IAAW,EAAsB,EAAE;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;QAC1C,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACrF,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;YAAE,OAAO,KAAK,CAAC;QAC5C,yEAAyE;QACzE,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG;YAClD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC;QAC3D,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IACF,uGAAuG;IACvG,MAAM,KAAK,GAAG,CAAC,MAAe,EAAsB,EAAE;QACpD,IAAI,KAAyB,CAAC;QAC9B,mGAAmG;QACnG,IAAI,SAA6B,CAAC;QAClC,gFAAgF;QAChF,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;YAC5C,IAAI,MAAM,KAAK,SAAS;gBAAE,OAAO;YACjC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;YAC/B,qEAAqE;YACrE,iDAAiD;YACjD,MAAM,QAAQ,GACZ,SAAS,KAAK,KAAK,CAAC,QAAS,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC;YACnF,MAAM,OAAO,GACX,KAAK,KAAK,SAAS;gBACnB,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,EAAE,CAAC,CAAC,IAAI,QAAQ,CAAC;gBAC9D,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;YACtF,IAAI,OAAO,IAAI,QAAQ,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC/C,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,KAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBACnD,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,GAAG,KAAK,CAAC;oBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;qBACpF,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC7B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;oBAChB,KAAK,GAAG,SAAS,CAAC;gBACpB,CAAC;gBACD,IAAI,OAAO,EAAE,CAAC;oBACZ,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;oBAChB,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,MAAM,EAAE,MAAM,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC;YACD,SAAS;gBACP,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,CAAC;oBACtD,CAAC,CAAC,KAAK,CAAC,QAAS,CAAC,GAAG,CAAC,IAAI;oBAC1B,CAAC,CAAC,SAAS,CAAC;YAChB,MAAM,GAAG,KAAK,CAAC;YACf,IAAI,UAAU,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,KAAK,CAAC,QAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;oBAC5D,SAAS,GAAG,IAAI,CAAC;oBACjB,MAAM,GAAG,IAAI,CAAC;gBAChB,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IACF,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrB,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACtC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import type { Nodes, Parents, Root } from \"mdast\";\nimport type { Document } from \"../core/types.js\";\n\n/**\n * A list marker as CommonMark reads one at the start of a line's content: a\n * bullet, `-`, `*`, or `+`, or a number of one to nine digits followed by `.`\n * or `)`, and then a space, a tab, or the end of the line.\n */\nexport const listMarker = /^(?:[-+*]|\\d{1,9}[.)])(?:[ \\t\\r\\n]|$)/;\n\n/** Text that the parser read where renderers may read a list, and the blocks after it. */\nexport interface MisreadLists {\n /**\n * Paragraphs, and headings underlined with `===` or `---`, whose text starts\n * with a list marker, and the text that renderers read as continuing it.\n */\n text: ReadonlySet<Nodes>;\n /**\n * The blocks after such text in its container whose first lines start\n * further right than the text, up to one that does not. Renderers may read\n * them inside the list's last item, where their indentation counts from the\n * item's text: an indented code block can be a paragraph there.\n */\n nested: ReadonlySet<Nodes>;\n /**\n * The block after those, which starts no further right than the text.\n * Renderers may read it as more items of the list.\n */\n next: ReadonlySet<Nodes>;\n}\n\n/** Leaf blocks: their children, if they have any, are not blocks. */\nconst leaves = new Set<Nodes[\"type\"]>([\"paragraph\", \"heading\", \"table\", \"code\", \"html\"]);\nconst found = new WeakMap<Root, MisreadLists>();\n\n/**\n * Where renderers may read a list in text that the parser read as text.\n *\n * micromark refuses to start a list that does not start at 1, or an empty\n * item, where it would interrupt a paragraph, as CommonMark says, but also\n * where no paragraph is open: at the start of a list item, block quote, or\n * footnote definition below a paragraph, and after an indented code block\n * (issue #191). It reads the line as text there, where GitHub, commonmark.js,\n * and markdown-it read a list. By CommonMark's rules, text can start with a\n * list marker only below a link reference definition, as what remains of the\n * definition's lines; GitHub and commonmark.js read text there too, and\n * markdown-it a list. The paragraph of a task list item starts after its\n * checkbox, which renderers read as the start of the item's text, so it does\n * not count. Renderers read the `===` below such text as text, of the list\n * item or after an empty one, so a paragraph or heading on the next line\n * continues it too, and a block there is nested: a `---` would underline it.\n * Where such text ends a list item or block quote, renderers continue it\n * lazily into a paragraph or heading on the next line below the container.\n */\nexport function misreadLists(document: Document): MisreadLists {\n const known = found.get(document.tree);\n if (known) return known;\n const { source } = document;\n const text = new Set<Nodes>();\n const nested = new Set<Nodes>();\n const next = new Set<Nodes>();\n /** The column of the first character from `offset` on, after spaces and tabs. */\n const columnAt = (offset: number) => {\n let start = offset;\n while (start > 0 && source[start - 1] !== \"\\n\" && source[start - 1] !== \"\\r\") start--;\n let column = 0;\n for (let at = start; at < source.length; at++) {\n const character = source[at];\n if (at >= offset && character !== \" \" && character !== \"\\t\") break;\n column = character === \"\\t\" ? column + 4 - (column % 4) : column + 1;\n }\n return column;\n };\n /** Where a paragraph's or an underlined heading's text starts. */\n const textStart = (node: Nodes): number | undefined => {\n const start = node.position?.start.offset;\n if (start === undefined || node.position?.end.offset === undefined) return undefined;\n if (node.type === \"paragraph\") return start;\n // An underlined heading below link reference definitions starts at them.\n if (node.type === \"heading\" && source[start] !== \"#\")\n return node.children[0]?.position?.start.offset ?? start;\n return undefined;\n };\n /** Returns the last line of misread text that ends `parent` and whose `===` renderers read as text. */\n const visit = (parent: Parents): number | undefined => {\n let reach: number | undefined;\n /** The last line of misread text whose `===` renderers read as text, if the last block is that. */\n let continued: number | undefined;\n /** Whether that text ends the last block, a container, rather than being it. */\n let inside = false;\n parent.children.forEach((child, index) => {\n const offset = child.position?.start.offset;\n if (offset === undefined) return;\n const start = textStart(child);\n // Renderers continue the text lazily on the line below the container\n // that it ends, but only with text (issue #343).\n const adjacent =\n continued === child.position!.start.line - 1 && (!inside || start !== undefined);\n const misread =\n start !== undefined &&\n (listMarker.test(source.slice(start, start + 11)) || adjacent) &&\n !(index === 0 && parent.type === \"listItem\" && typeof parent.checked === \"boolean\");\n if (misread || adjacent || reach !== undefined) {\n const column = columnAt(misread ? start! : offset);\n if ((adjacent && !misread) || (reach !== undefined && column > reach)) nested.add(child);\n else if (reach !== undefined) {\n next.add(child);\n reach = undefined;\n }\n if (misread) {\n text.add(child);\n reach = Math.min(reach ?? column, column);\n }\n }\n continued =\n misread && child.type === \"heading\" && child.depth === 1\n ? child.position!.end.line\n : undefined;\n inside = false;\n if (\"children\" in child && !leaves.has(child.type)) {\n const last = visit(child);\n if (last !== undefined && last === child.position!.end.line) {\n continued = last;\n inside = true;\n }\n }\n });\n return continued;\n };\n visit(document.tree);\n const result = { text, nested, next };\n found.set(document.tree, result);\n return result;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"misread-lists.js","sourceRoot":"","sources":["../../src/syntax/misread-lists.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,uCAAuC,CAAC;AAClE;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAC;AA0DjD,qEAAqE;AACrE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAgB,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AACzF,MAAM,KAAK,GAAG,IAAI,OAAO,EAAsB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,YAAY,CAAC,QAAkB;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;IAC5B,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,KAAK,OAAO,CAAC;IAC7E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAS,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAS,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAS,CAAC;IAC9B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAS,CAAC;IACtC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,KAAK,UAAU,CAAC;IACjD,iFAAiF;IACjF,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,EAAE;QAClC,IAAI,KAAK,GAAG,MAAM,CAAC;QACnB,OAAO,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI;YAAE,KAAK,EAAE,CAAC;QACtF,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;YAC9C,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;YAC7B,IAAI,EAAE,IAAI,MAAM,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,IAAI;gBAAE,MAAM;YACnE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IACF,kEAAkE;IAClE,MAAM,SAAS,GAAG,CAAC,IAAW,EAAsB,EAAE;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;QAC1C,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACrF,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;YAAE,OAAO,KAAK,CAAC;QAC5C,yEAAyE;QACzE,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG;YAClD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC;QAC3D,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IACF;;;;OAIG;IACH,MAAM,YAAY,GAAG,CAAC,IAAW,EAAE,MAAe,EAAsB,EAAE;QACxE,MAAM,GAAG,GAAG,IAAI,CAAC,QAAS,CAAC,GAAG,CAAC,MAAO,CAAC;QACvC,uEAAuE;QACvE,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAS,CAAC,KAAK,CAAC,MAAO,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,aAAa,CAAC;QAC7B,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,QAAS,CAAC,KAAK,CAAC,MAAO,CAAC;QAChD,KAAK,IAAI,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,KAAK,CAAC,KAAK,GAAG,GAAG,EAAE,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9F,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAChD,IAAI,OAAO,GAAG,SAAS,CAAC;YACxB,OAAO,OAAO,GAAG,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI;gBAAE,OAAO,EAAE,CAAC;YACxF,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC9C,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAChD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACnC,MAAM,OAAO,GAAG,wBAAwB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvD,IACE,QAAQ,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC;gBACxC,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;oBAC/C,qCAAqC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAEtD,OAAO,SAAS,GAAG,MAAM,CAAC;QAC9B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IACF,uGAAuG;IACvG,MAAM,KAAK,GAAG,CAAC,MAAe,EAAE,MAAM,GAAG,KAAK,EAAsB,EAAE;QACpE,IAAI,KAAyB,CAAC;QAC9B,mGAAmG;QACnG,IAAI,SAA6B,CAAC;QAClC,gFAAgF;QAChF,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,gGAAgG;QAChG,IAAI,SAA6B,CAAC;QAClC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;YAC5C,IAAI,MAAM,KAAK,SAAS;gBAAE,OAAO;YACjC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,IAAI,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS;oBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;;oBAC/C,SAAS,GAAG,SAAS,CAAC;YAC7B,CAAC;YACD,IACE,KAAK;gBACL,KAAK,KAAK,SAAS;gBACnB,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,QAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EACtE,CAAC;gBACD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACxB,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;YACxE,CAAC;YACD,qEAAqE;YACrE,iDAAiD;YACjD,MAAM,QAAQ,GACZ,SAAS,KAAK,KAAK,CAAC,QAAS,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC;YACnF,MAAM,OAAO,GACX,KAAK,KAAK,SAAS;gBACnB,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,EAAE,CAAC,CAAC,IAAI,QAAQ,CAAC;gBAC9D,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;YACtF,MAAM,IAAI,GAAG,QAAQ,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACvF,MAAM,OAAO,GAAG,OAAO,IAAI,IAAI,KAAK,SAAS,CAAC;YAC9C,IAAI,OAAO,IAAI,QAAQ,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC/C,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,KAAM,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC;gBAC7D,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,GAAG,KAAK,CAAC;oBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;qBACpF,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC7B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;oBAChB,KAAK,GAAG,SAAS,CAAC;gBACpB,CAAC;gBACD,IAAI,OAAO,EAAE,CAAC;oBACZ,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;oBAChB,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,MAAM,EAAE,MAAM,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC;YACD,SAAS;gBACP,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,CAAC;oBACtD,CAAC,CAAC,KAAK,CAAC,QAAS,CAAC,GAAG,CAAC,IAAI;oBAC1B,CAAC,CAAC,SAAS,CAAC;YAChB,MAAM,GAAG,KAAK,CAAC;YACf,IAAI,UAAU,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;gBACjE,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,KAAK,CAAC,QAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;oBAC5D,SAAS,GAAG,IAAI,CAAC;oBACjB,MAAM,GAAG,IAAI,CAAC;gBAChB,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IACF,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAS,CAAC;IAClC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAS,CAAC;IACtC,IAAI,QAAQ,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACpC;;;WAGG;QACH,MAAM,KAAK,GAAuB,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,CAAC,IAAW,EAAE,IAAa,EAAE,EAAE;YAC7C,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;;gBAE3E,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CACrC,OAAO,CAAC,KAAK,EAAE,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAClE,CAAC;QACN,CAAC,CAAC;QACF,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACzC,kGAAkG;QAClG,MAAM,MAAM,GAAG,CAAC,MAAc,EAAE,EAAE;YAChC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACrC,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC,CAAC;QACF;;;;;WAKG;QACH,IAAI,IAAI,GAAG,KAAK,CAAC;QACjB,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE;YAC9B,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACvC,IAAI,IAAI,IAAI,QAAQ,EAAE,QAAQ,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChD,KAAK,IAAI,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE;oBACrF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;wBAAE,IAAI,GAAG,KAAK,CAAC;gBAClC,IAAI,IAAI,EAAE,CAAC;oBACT,kEAAkE;oBAClE,0CAA0C;oBAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;oBAC/C,IAAI,IAAI,GAAG,MAAM,CAAC;oBAClB,OAAO,IAAI,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI;wBAAE,IAAI,EAAE,CAAC;oBAClF,MAAM,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;oBAClE,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;gBAC5F,CAAC;YACH,CAAC;YACD,6EAA6E;YAC7E,IACE,CAAC,IAAI;gBACL,IAAI,CAAC,IAAI,KAAK,MAAM;gBACpB,IAAI,CAAC,QAAQ;gBACb,CAAC,6EAA6E,CAAC,IAAI,CACjF,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CACvB;gBAED,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QACH;;;;;;WAMG;QACH,MAAM,QAAQ,GAAG,CAAC,IAAW,EAAS,EAAE;YACtC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;YAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC;YACtC,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS;gBAAE,OAAO,EAAE,CAAC;YACxD,IACE,IAAI,CAAC,IAAI,KAAK,mBAAmB;gBACjC,IAAI,CAAC,IAAI,KAAK,iBAAiB;gBAC/B,IAAI,CAAC,IAAI,KAAK,OAAO;gBACrB,IAAI,CAAC,IAAI,KAAK,gBAAgB;gBAE9B,OAAO,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;YAC1C,uEAAuE;YACvE,4BAA4B;YAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;gBAAE,OAAO,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;YAClE,OAAO,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,CAAC,CAAC;QACF;;;;;;WAMG;QACH,IAAI,KAAyB,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;YAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC;YACtC,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS;gBAAE,SAAS;YACvD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;gBAC3F,IAAI,IAAI,IAAI,MAAM;oBAAE,KAAK,GAAG,SAAS,CAAC;qBACjC,CAAC;oBACJ,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBACvB,iEAAiE;oBACjE,yCAAyC;oBACzC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;wBAAE,SAAS;oBACnC,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;oBAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;oBAC/D,IAAI,KAAK,IAAI,CAAC;wBAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;oBAC/D,SAAS;gBACX,CAAC;YACH,CAAC;YACD,MAAM,KAAK,GACT,IAAI,CAAC,IAAI,KAAK,OAAO;gBACnB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAC9C,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;oBACpD,CAAC,CAAC,CAAC,IAAI,CAAC;oBACR,CAAC,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC5B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;oBAAE,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC5C,OAAO,IAAI,CAAC;YACd,CAAC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;YACpD,IAAI,IAAI,KAAK,SAAS;gBAAE,SAAS;YACjC,kEAAkE;YAClE,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;gBAAE,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YAC3D,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAClE,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;IAC5E,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC;AAChB,CAAC;AAKD;;;GAGG;AACH,SAAS,YAAY,CAAC,MAAc,EAAE,KAAa,EAAE,GAAW;IAC9D,MAAM,IAAI,GAAU,EAAE,CAAC;IACvB,KAAK,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC;QAC/D,IAAI,KAAK,GAAG,EAAE,CAAC;QACf,OAAO,KAAK,GAAG,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG;YAAE,KAAK,EAAE,CAAC;QACrD,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,OAAO,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,IAAI;YAAE,OAAO,EAAE,CAAC;QACpD,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7C,IAAI,KAAK,GAAG,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC;QAClD,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,MAAc,EAAE,KAAa,EAAE,GAAW;IAC9D,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAC9C,0EAA0E;IAC1E,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IACD,MAAM,IAAI,GAAU,EAAE,CAAC;IACvB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACjD,IAAI,IAAI,CAAC,KAAK,CAAE,GAAG,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC;;YACzC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAE,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,OAAO,CAAC,MAAc,EAAE,IAAW;IAC1C,IAAI,IAAqB,CAAC;IAC1B,wEAAwE;IACxE,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC;IACjB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,OAAO;YAAE,OAAO,GAAG,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC;YACtC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,EAAE,CAAC;gBACrD,IAAI,GAAG,SAAS,CAAC;gBACjB,SAAS;YACX,CAAC;YACD,mCAAmC;YACnC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,QAAQ;gBAAE,SAAS;QACzC,CAAC;QACD,IAAI,GAAG,GAAG,CAAC;QACX,WAAW,GAAG,OAAO,CAAC;IACxB,CAAC;IACD,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAClE,CAAC;AAED,wFAAwF;AACxF,SAAS,SAAS,CAAC,MAAc,EAAE,IAAY;IAC7C,KAAK,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE;QAC1C,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,IAAI;YAAE,OAAO,EAAE,CAAC;IAC5D,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC","sourcesContent":["import type { Nodes, Parents, Root } from \"mdast\";\nimport type { Document } from \"../core/types.js\";\n\n/**\n * A list marker as CommonMark reads one at the start of a line's content: a\n * bullet, `-`, `*`, or `+`, or a number of one to nine digits followed by `.`\n * or `)`, and then a space, a tab, or the end of the line.\n */\nexport const listMarker = /^(?:[-+*]|\\d{1,9}[.)])(?:[ \\t\\r\\n]|$)/;\n/**\n * A line whose content, after blank space and block quote markers, starts with\n * `:` and a space or tab. In a paragraph, such a line opens a definition\n * description on Forgejo and Gitea.\n */\nexport const descriptionLine = /^[ \\t>]*:[ \\t]/m;\n\n/**\n * Text that the parser read where renderers may read a list, or on Forgejo and\n * Gitea a definition description, and the blocks after it.\n */\nexport interface MisreadLists {\n /**\n * Paragraphs, and headings underlined with `===` or `---`, whose text starts\n * with a list marker, and the text that renderers read as continuing it. In\n * the Obsidian dialect also those with a later line that Obsidian reads as\n * starting a list item where CommonMark reads text (issue #375).\n */\n text: ReadonlySet<Nodes>;\n /**\n * The blocks after such text, or after a description, in its container whose\n * first lines start further right than the text, up to one that does not.\n * Renderers may read them inside the list's last item or the description,\n * where their indentation counts from the item's text: an indented code block\n * can be a paragraph there.\n */\n nested: ReadonlySet<Nodes>;\n /**\n * The block after those below such text, which starts no further right than\n * the text. Renderers may read it as more items of the list.\n */\n next: ReadonlySet<Nodes>;\n /**\n * In the Forgejo and Gitea dialects, paragraphs with a line that opens a\n * definition description, as `Term` and `: 2. x` do. Those renderers read\n * the description as blocks, here an ordered list (issue #344).\n */\n descriptions: ReadonlySet<Nodes>;\n /**\n * In the Obsidian dialect, paragraphs, headings, and table cells whose text\n * holds a backtick that no run of the same length closes, which the parser\n * leaves as text, also in a highlight, an inline comment, or an image's\n * description. Obsidian's Live Preview shows the text after it as code, at\n * least to the end of its line, and Reading view pairs a run of two or more\n * with a later, shorter one, as in ``a ``` b `c` d`` (issue #362).\n *\n * After a run of three or more, Live Preview shows the blocks below as code\n * too, also out of a list item and across blank lines, up to a block with a\n * run of the same length outside an indented code block, which it closes\n * there, a fenced code block, or a list item. Those blocks are in the set as\n * well, with a table that holds such a run.\n */\n unclosedCode: ReadonlySet<Nodes>;\n /**\n * In the Obsidian dialect, the blocks that Reading view reads as more of an\n * HTML block above them. A line of blank space directly below an HTML block\n * that ends at a blank line continues the block, and so do the blocks after\n * it, up to an empty line (issue #358). Each counts from the start of its\n * first line, with the marker of a list item there.\n */\n htmlText: ReadonlySet<Nodes>;\n}\n\n/** Leaf blocks: their children, if they have any, are not blocks. */\nconst leaves = new Set<Nodes[\"type\"]>([\"paragraph\", \"heading\", \"table\", \"code\", \"html\"]);\nconst found = new WeakMap<Root, MisreadLists>();\n\n/**\n * Where renderers may read a list in text that the parser read as text.\n *\n * micromark refuses to start a list that does not start at 1, or an empty\n * item, where it would interrupt a paragraph, as CommonMark says, but also\n * where no paragraph is open: at the start of a list item, block quote, or\n * footnote definition below a paragraph, and after an indented code block\n * (issue #191). It reads the line as text there, where GitHub, commonmark.js,\n * and markdown-it read a list. By CommonMark's rules, text can start with a\n * list marker only below a link reference definition, as what remains of the\n * definition's lines; GitHub and commonmark.js read text there too, and\n * markdown-it a list. The paragraph of a task list item starts after its\n * checkbox, which renderers read as the start of the item's text, so it does\n * not count. Renderers read the `===` below such text as text, of the list\n * item or after an empty one, so a paragraph or heading on the next line\n * continues it too, and a block there is nested: a `---` would underline it.\n * Where such text ends a list item or block quote, renderers continue it\n * lazily into a paragraph or heading on the next line below the container.\n *\n * Forgejo and Gitea read a definition list, which the parser reads as text:\n * `Term` and a line `: 2. x` below it are a term and a description, and the\n * description holds blocks, here an ordered list, as a list item does. The\n * blocks indented below it in its container belong to it too (issue #344).\n *\n * Obsidian starts a list below a paragraph line where CommonMark does not:\n * Live Preview at an ordered marker with a number other than 1 and text after\n * it, except in a block quote, and Reading view at an empty item, `*`, `+`,\n * `- `, or `1.`, which Live Preview reads so for `+ ` and `- ` (issue #375).\n */\nexport function misreadLists(document: Document): MisreadLists {\n const known = found.get(document.tree);\n if (known) return known;\n const { source } = document;\n const forge = document.dialect === \"forgejo\" || document.dialect === \"gitea\";\n const text = new Set<Nodes>();\n const nested = new Set<Nodes>();\n const next = new Set<Nodes>();\n const descriptions = new Set<Nodes>();\n const obsidian = document.dialect === \"obsidian\";\n /** The column of the first character from `offset` on, after spaces and tabs. */\n const columnAt = (offset: number) => {\n let start = offset;\n while (start > 0 && source[start - 1] !== \"\\n\" && source[start - 1] !== \"\\r\") start--;\n let column = 0;\n for (let at = start; at < source.length; at++) {\n const character = source[at];\n if (at >= offset && character !== \" \" && character !== \"\\t\") break;\n column = character === \"\\t\" ? column + 4 - (column % 4) : column + 1;\n }\n return column;\n };\n /** Where a paragraph's or an underlined heading's text starts. */\n const textStart = (node: Nodes): number | undefined => {\n const start = node.position?.start.offset;\n if (start === undefined || node.position?.end.offset === undefined) return undefined;\n if (node.type === \"paragraph\") return start;\n // An underlined heading below link reference definitions starts at them.\n if (node.type === \"heading\" && source[start] !== \"#\")\n return node.children[0]?.position?.start.offset ?? start;\n return undefined;\n };\n /**\n * In the Obsidian dialect, the offset of the marker on the first line of\n * `node` after its first that Obsidian reads as starting a list item where\n * CommonMark reads text; `quoted` says whether `node` is in a block quote.\n */\n const obsidianItem = (node: Nodes, quoted: boolean): number | undefined => {\n const end = node.position!.end.offset!;\n // A marker four or more columns right of the text is more of the text.\n const text = columnAt(node.position!.start.offset!);\n const breaks = /\\r\\n|\\r|\\n/g;\n breaks.lastIndex = node.position!.start.offset!;\n for (let found = breaks.exec(source); found && found.index < end; found = breaks.exec(source)) {\n const lineStart = found.index + found[0].length;\n let lineEnd = lineStart;\n while (lineEnd < end && source[lineEnd] !== \"\\n\" && source[lineEnd] !== \"\\r\") lineEnd++;\n const line = source.slice(lineStart, lineEnd);\n const prefix = /^[ \\t>]*/.exec(line)![0].length;\n const content = line.slice(prefix);\n const ordered = /^(\\d{1,9})[.)][ \\t]+\\S/.exec(content);\n if (\n columnAt(lineStart + prefix) - text <= 3 &&\n ((ordered && Number(ordered[1]) !== 1 && !quoted) ||\n /^(?:[*+]|-(?=[ \\t])|0*1[.)])[ \\t]*$/.test(content))\n )\n return lineStart + prefix;\n }\n return undefined;\n };\n /** Returns the last line of misread text that ends `parent` and whose `===` renderers read as text. */\n const visit = (parent: Parents, quoted = false): number | undefined => {\n let reach: number | undefined;\n /** The last line of misread text whose `===` renderers read as text, if the last block is that. */\n let continued: number | undefined;\n /** Whether that text ends the last block, a container, rather than being it. */\n let inside = false;\n /** The column of the last definition description while the blocks after it may belong to it. */\n let described: number | undefined;\n parent.children.forEach((child, index) => {\n const offset = child.position?.start.offset;\n if (offset === undefined) return;\n const start = textStart(child);\n if (described !== undefined) {\n if (columnAt(offset) > described) nested.add(child);\n else described = undefined;\n }\n if (\n forge &&\n start !== undefined &&\n descriptionLine.test(source.slice(offset, child.position!.end.offset))\n ) {\n descriptions.add(child);\n described = Math.min(described ?? columnAt(offset), columnAt(offset));\n }\n // Renderers continue the text lazily on the line below the container\n // that it ends, but only with text (issue #343).\n const adjacent =\n continued === child.position!.start.line - 1 && (!inside || start !== undefined);\n const atStart =\n start !== undefined &&\n (listMarker.test(source.slice(start, start + 11)) || adjacent) &&\n !(index === 0 && parent.type === \"listItem\" && typeof parent.checked === \"boolean\");\n const item = obsidian && start !== undefined ? obsidianItem(child, quoted) : undefined;\n const misread = atStart || item !== undefined;\n if (misread || adjacent || reach !== undefined) {\n const column = columnAt(atStart ? start! : (item ?? offset));\n if ((adjacent && !misread) || (reach !== undefined && column > reach)) nested.add(child);\n else if (reach !== undefined) {\n next.add(child);\n reach = undefined;\n }\n if (misread) {\n text.add(child);\n reach = Math.min(reach ?? column, column);\n }\n }\n continued =\n misread && child.type === \"heading\" && child.depth === 1\n ? child.position!.end.line\n : undefined;\n inside = false;\n if (\"children\" in child && !leaves.has(child.type)) {\n const last = visit(child, quoted || child.type === \"blockquote\");\n if (last !== undefined && last === child.position!.end.line) {\n continued = last;\n inside = true;\n }\n }\n });\n return continued;\n };\n visit(document.tree);\n const htmlText = new Set<Nodes>();\n const unclosedCode = new Set<Nodes>();\n if (document.dialect === \"obsidian\") {\n /**\n * Leaf blocks in document order, and whether each starts a list item, also\n * inside a container that does, as in `- > a`.\n */\n const order: [Nodes, boolean][] = [];\n const collect = (node: Nodes, item: boolean) => {\n if (leaves.has(node.type) || !(\"children\" in node)) order.push([node, item]);\n else\n node.children.forEach((child, index) =>\n collect(child, index === 0 && (item || node.type === \"listItem\")),\n );\n };\n collect(document.tree, false);\n const lines = source.split(/\\r\\n|\\r|\\n/);\n /** Whether line `number`, counted from 1, holds blank space and more than block quote markers. */\n const spaced = (number: number) => {\n const line = lines[number - 1] ?? \"\";\n return /^[ \\t>]*$/.test(line) && /[^>]/.test(line);\n };\n /**\n * Whether the last leaf block is an HTML block that ends at a blank line, or\n * text that Obsidian reads as more of one, which the next block may continue.\n * Leaf blocks count, not containers, because an empty line inside a list\n * ends the HTML block there.\n */\n let open = false;\n order.forEach(([leaf], index) => {\n const previous = order[index - 1]?.[0];\n if (open && previous?.position && leaf.position) {\n for (let line = previous.position.end.line + 1; line < leaf.position.start.line; line++)\n if (!spaced(line)) open = false;\n if (open) {\n // From the start of its line: a list item's marker there, `- ` in\n // `- *a*`, is text of the HTML block too.\n const offset = leaf.position.start.offset ?? 0;\n let from = offset;\n while (from > 0 && source[from - 1] !== \"\\n\" && source[from - 1] !== \"\\r\") from--;\n const start = { ...leaf.position.start, offset: from, column: 1 };\n htmlText.add(from === offset ? leaf : { ...leaf, position: { ...leaf.position, start } });\n }\n }\n // Other HTML blocks end at their own end marker, as a comment does at `-->`.\n if (\n !open &&\n leaf.type === \"html\" &&\n leaf.position &&\n !/^<(?:!--|\\?|!\\[CDATA\\[|![A-Za-z]|(?:script|pre|style|textarea)(?:[\\s>]|$))/i.test(\n leaf.value.trimStart(),\n )\n )\n open = spaced(leaf.position.end.line + 1);\n });\n /**\n * The runs of backticks that nothing closes in the text of `node`, outside\n * code, math, and wikilinks. Live Preview starts code at them also inside a\n * highlight, an inline comment, and an image's description, whose source\n * the parser does not read as code spans; a backtick in a link's\n * destination or title starts none, but counts in an image's source.\n */\n const openRuns = (node: Nodes): Run[] => {\n const start = node.position?.start.offset;\n const end = node.position?.end.offset;\n if (start === undefined || end === undefined) return [];\n if (\n node.type === \"obsidianHighlight\" ||\n node.type === \"obsidianComment\" ||\n node.type === \"image\" ||\n node.type === \"imageReference\"\n )\n return unclosedRuns(source, start, end);\n // The parser reads every run that another closes as code, so every one\n // left in text is unclosed.\n if (node.type === \"text\") return backtickRuns(source, start, end);\n return \"children\" in node ? node.children.flatMap(openRuns) : [];\n };\n /**\n * The length of a run of three or more backticks whose code Live Preview\n * carries into the blocks below, up to a block with a run of the same\n * length, a fenced code block, or a list item. A run in a wikilink, in math,\n * or in an HTML block closes it too, because Live Preview reads none of\n * those inside the code.\n */\n let carry: number | undefined;\n for (const [leaf, item] of order) {\n const start = leaf.position?.start.offset;\n const end = leaf.position?.end.offset;\n if (start === undefined || end === undefined) continue;\n if (carry !== undefined) {\n const fenced = leaf.type === \"code\" && /^ {0,3}(?:```|~~~)/.test(source.slice(start, end));\n if (item || fenced) carry = undefined;\n else {\n unclosedCode.add(leaf);\n // Live Preview shows an indented code block there as more of the\n // code, and its backticks close nothing.\n if (leaf.type === \"code\") continue;\n const runs = backtickRuns(source, start, end);\n const close = runs.findIndex(([, length]) => length === carry);\n if (close >= 0) carry = carried(source, runs.slice(close + 1));\n continue;\n }\n }\n const parts =\n leaf.type === \"table\"\n ? leaf.children.flatMap((row) => row.children)\n : leaf.type === \"paragraph\" || leaf.type === \"heading\"\n ? [leaf]\n : [];\n const runs = parts.flatMap((part) => {\n const open = openRuns(part);\n if (open.length > 0) unclosedCode.add(part);\n return open;\n });\n const long = runs.find(([, length]) => length >= 3);\n if (long === undefined) continue;\n // Live Preview shows the rest of a table as code from such a run.\n if (leaf.type === \"table\") unclosedCode.add(leaf);\n const after = backtickRuns(source, long[0] + long[1], end);\n const close = after.findIndex(([, length]) => length === long[1]);\n carry = close < 0 ? long[1] : carried(source, after.slice(close + 1));\n }\n }\n const result = { text, nested, next, descriptions, unclosedCode, htmlText };\n found.set(document.tree, result);\n return result;\n}\n\n/** A run of backticks: its offset and its length. */\ntype Run = [number, number];\n\n/**\n * The runs of backticks from `start` to `end`. A backslash before a run\n * escapes its first backtick only.\n */\nfunction backtickRuns(source: string, start: number, end: number): Run[] {\n const runs: Run[] = [];\n for (let at = source.indexOf(\"`\", start); at >= 0 && at < end;) {\n let after = at;\n while (after < end && source[after] === \"`\") after++;\n let slashes = 0;\n while (source[at - 1 - slashes] === \"\\\\\") slashes++;\n const from = slashes % 2 === 0 ? at : at + 1;\n if (after > from) runs.push([from, after - from]);\n at = source.indexOf(\"`\", after);\n }\n return runs;\n}\n\n/**\n * The runs of backticks from `start` to `end` that no later run of the same\n * length there closes, as CommonMark pairs them into code spans.\n */\nfunction unclosedRuns(source: string, start: number, end: number): Run[] {\n const runs = backtickRuns(source, start, end);\n /** The index of the next run of the same length after each run, or -1. */\n const next: number[] = [];\n const later = new Map<number, number>();\n for (let index = runs.length - 1; index >= 0; index--) {\n const length = runs[index]![1];\n next[index] = later.get(length) ?? -1;\n later.set(length, index);\n }\n const open: Run[] = [];\n for (let index = 0; index < runs.length; index++) {\n if (next[index]! < 0) open.push(runs[index]!);\n else index = next[index]!;\n }\n return open;\n}\n\n/**\n * The length of the run of three or more backticks whose code Live Preview\n * carries past the last of `runs`, if any. Live Preview closes a run with the\n * next run of the same length; the code of a run of one or two backticks ends\n * with its line.\n */\nfunction carried(source: string, runs: Run[]): number | undefined {\n let open: Run | undefined;\n /** Where the line of the open run ends, and that of the current one. */\n let openLineEnd = 0;\n let lineEnd = -1;\n for (const run of runs) {\n if (run[0] >= lineEnd) lineEnd = lineBreak(source, run[0]);\n if (open !== undefined) {\n const sameLine = run[0] < openLineEnd;\n if (run[1] === open[1] && (open[1] >= 3 || sameLine)) {\n open = undefined;\n continue;\n }\n // Other runs are part of the code.\n if (open[1] >= 3 || sameLine) continue;\n }\n open = run;\n openLineEnd = lineEnd;\n }\n return open !== undefined && open[1] >= 3 ? open[1] : undefined;\n}\n\n/** The offset of the first line break at or after `from`, or the length of `source`. */\nfunction lineBreak(source: string, from: number): number {\n for (let at = from; at < source.length; at++)\n if (source[at] === \"\\n\" || source[at] === \"\\r\") return at;\n return source.length;\n}\n"]}
|
package/dist/syntax/obsidian.js
CHANGED
|
@@ -36,7 +36,8 @@ const tokenize = function (effects, ok, nok) {
|
|
|
36
36
|
effects.consume(code);
|
|
37
37
|
count++;
|
|
38
38
|
if (code === closing.charCodeAt(1) && previous === closing.charCodeAt(0)) {
|
|
39
|
-
|
|
39
|
+
// `====` and `[[]]` are text, while Obsidian hides an empty comment, `%%%%`.
|
|
40
|
+
if (count <= 2 && opening !== "%%")
|
|
40
41
|
return nok(code);
|
|
41
42
|
effects.exit("obsidianCommentData");
|
|
42
43
|
effects.exit("obsidianLiteral");
|
|
@@ -52,12 +53,16 @@ const tokenize = function (effects, ok, nok) {
|
|
|
52
53
|
return start;
|
|
53
54
|
};
|
|
54
55
|
// Standalone comment blocks may cross blank lines. Keep their complete source opaque.
|
|
56
|
+
// Obsidian reads a comment as inline wherever a paragraph is open, so one that
|
|
57
|
+
// would interrupt a paragraph, or that text follows on the line where it
|
|
58
|
+
// closes, is left to the inline construct and continues the paragraph (#357).
|
|
55
59
|
const tokenizeBlockComment = function (effects, ok, nok) {
|
|
60
|
+
const interrupt = this.interrupt;
|
|
56
61
|
let opened = 0;
|
|
57
62
|
let previous = null;
|
|
58
63
|
let closed = false;
|
|
59
64
|
const start = (code) => {
|
|
60
|
-
if (code !== 37)
|
|
65
|
+
if (code !== 37 || interrupt)
|
|
61
66
|
return nok(code);
|
|
62
67
|
if (opened === 0) {
|
|
63
68
|
effects.enter("obsidianBlockComment");
|
|
@@ -81,6 +86,9 @@ const tokenizeBlockComment = function (effects, ok, nok) {
|
|
|
81
86
|
previous = null;
|
|
82
87
|
return before;
|
|
83
88
|
}
|
|
89
|
+
// Only blank space may follow the closing `%%` on its line.
|
|
90
|
+
if (closed && code !== 32 && code !== -1 && code !== -2)
|
|
91
|
+
return nok(code);
|
|
84
92
|
effects.consume(code);
|
|
85
93
|
if (code === 37 && previous === 37)
|
|
86
94
|
closed = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obsidian.js","sourceRoot":"","sources":["../../src/syntax/obsidian.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Literal } from \"mdast\";\nimport type { Extension, State, Tokenizer } from \"micromark-util-types\";\nimport type { Extension as TreeExtension } from \"mdast-util-from-markdown\";\n\n/** An Obsidian wikilink, `[[target|label]]`, or embed, `![[target]]`, in the Obsidian dialect. */\nexport interface WikiLink extends Literal {\n type: \"wikiLink\";\n /** The text between the brackets, with `\\|` read as `|`. */\n value: string;\n /** Whether it is an embed, written with `!` before the brackets. */\n embed: boolean;\n /** The part before the first `|`: a note name or path, and an optional `#heading` or `#^block`. */\n target: string;\n /** The part after the first `|`, when there is one. */\n label?: string;\n}\n/**\n * An Obsidian comment in the Obsidian dialect. `value` is the text between the\n * `%%` markers of a comment in running text, and the whole source of a comment\n * that stands as a block of its own, markers included.\n */\nexport interface ObsidianComment extends Literal {\n type: \"obsidianComment\";\n}\n/** An Obsidian highlight, `==text==`, in the Obsidian dialect. `value` is the text between the markers. */\nexport interface ObsidianHighlight extends Literal {\n type: \"obsidianHighlight\";\n}\ndeclare module \"mdast\" {\n interface RootContentMap {\n wikiLink: WikiLink;\n obsidianComment: ObsidianComment;\n obsidianHighlight: ObsidianHighlight;\n }\n interface PhrasingContentMap {\n wikiLink: WikiLink;\n obsidianComment: ObsidianComment;\n obsidianHighlight: ObsidianHighlight;\n }\n interface BlockContentMap {\n obsidianComment: ObsidianComment;\n }\n}\ndeclare module \"micromark-util-types\" {\n interface TokenTypeMap {\n obsidianLiteral: \"obsidianLiteral\";\n obsidianBlockComment: \"obsidianBlockComment\";\n obsidianCommentData: \"obsidianCommentData\";\n }\n}\n\n/** A tokenizer, not a pre-parse replacement: code, escapes, and fenced blocks stay opaque. */\nconst tokenize: Tokenizer = function (effects, ok, nok) {\n let opening = \"\";\n let closing = \"\";\n let index = 0;\n let previous: number | null = null;\n let count = 0;\n const start: State = (code) => {\n opening = code === 33 ? \"![[\" : code === 91 ? \"[[\" : code === 37 ? \"%%\" : \"==\";\n closing = opening.endsWith(\"[[\") ? \"]]\" : opening;\n effects.enter(\"obsidianLiteral\");\n effects.enter(\"obsidianCommentData\");\n return open(code);\n };\n const open: State = (code) => {\n if (code !== opening.charCodeAt(index)) return nok(code);\n effects.consume(code);\n index++;\n return index === opening.length ? body : open;\n };\n const body: State = (code) => {\n if (code === null || (opening !== \"%%\" && code < 0 && code !== -1 && code !== -2))\n return nok(code);\n if (code < -2) {\n // Micromark subtokenizes each physical line separately. Expose every\n // line ending so a multiline inline comment can span more than two chunks.\n effects.exit(\"obsidianCommentData\");\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n previous = null;\n count++;\n return resume;\n }\n effects.consume(code);\n count++;\n if (code === closing.charCodeAt(1) && previous === closing.charCodeAt(0)) {\n if (count <= 2) return nok(code);\n effects.exit(\"obsidianCommentData\");\n effects.exit(\"obsidianLiteral\");\n return ok;\n }\n previous = code;\n return body;\n };\n const resume: State = (code) => {\n effects.enter(\"obsidianCommentData\");\n return body(code);\n };\n return start;\n};\n\n// Standalone comment blocks may cross blank lines. Keep their complete source opaque.\nconst tokenizeBlockComment: Tokenizer = function (effects, ok, nok) {\n let opened = 0;\n let previous: number | null = null;\n let closed = false;\n const start: State = (code) => {\n if (code !== 37) return nok(code);\n if (opened === 0) {\n effects.enter(\"obsidianBlockComment\");\n effects.enter(\"obsidianCommentData\");\n }\n effects.consume(code);\n opened++;\n return opened === 2 ? body : start;\n };\n const body: State = (code) => {\n if (code === null || (closed && code < -2)) {\n effects.exit(\"obsidianCommentData\");\n effects.exit(\"obsidianBlockComment\");\n return ok(code);\n }\n if (code < -2) {\n effects.exit(\"obsidianCommentData\");\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n previous = null;\n return before;\n }\n effects.consume(code);\n if (code === 37 && previous === 37) closed = true;\n previous = code;\n return body;\n };\n const before: State = (code) => {\n if (code === null) {\n effects.exit(\"obsidianBlockComment\");\n return ok(code);\n }\n if (code < -2) {\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n return before;\n }\n effects.enter(\"obsidianCommentData\");\n return body(code);\n };\n return start;\n};\n\nexport const obsidianSyntax: Extension = {\n flow: { 37: { name: \"obsidianBlockComment\", tokenize: tokenizeBlockComment, concrete: true } },\n text: Object.fromEntries(\n [33, 91, 37, 61].map((code) => [code, { name: \"obsidianLiteral\", tokenize }]),\n ),\n};\nexport const obsidianTree: TreeExtension = {\n enter: {\n obsidianBlockComment(token) {\n this.enter({ type: \"obsidianComment\", value: this.sliceSerialize(token) }, token);\n },\n obsidianLiteral(token) {\n const raw = this.sliceSerialize(token);\n const wiki = raw.startsWith(\"[[\") || raw.startsWith(\"![[\");\n const embed = raw.startsWith(\"!\");\n const value = raw.slice(wiki && embed ? 3 : 2, -2).replaceAll(\"\\\\|\", \"|\");\n const divider = value.indexOf(\"|\");\n const node: WikiLink | ObsidianComment | ObsidianHighlight = wiki\n ? {\n type: \"wikiLink\",\n value,\n embed,\n target: divider < 0 ? value : value.slice(0, divider),\n ...(divider >= 0 ? { label: value.slice(divider + 1) } : {}),\n }\n : { type: raw.startsWith(\"%%\") ? \"obsidianComment\" : \"obsidianHighlight\", value };\n this.enter(node, token);\n },\n },\n exit: {\n obsidianBlockComment(token) {\n this.exit(token);\n },\n obsidianLiteral(token) {\n this.exit(token);\n },\n },\n};\n"]}
|
|
1
|
+
{"version":3,"file":"obsidian.js","sourceRoot":"","sources":["../../src/syntax/obsidian.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Literal } from \"mdast\";\nimport type { Extension, State, Tokenizer } from \"micromark-util-types\";\nimport type { Extension as TreeExtension } from \"mdast-util-from-markdown\";\n\n/** An Obsidian wikilink, `[[target|label]]`, or embed, `![[target]]`, in the Obsidian dialect. */\nexport interface WikiLink extends Literal {\n type: \"wikiLink\";\n /** The text between the brackets, with `\\|` read as `|`. */\n value: string;\n /** Whether it is an embed, written with `!` before the brackets. */\n embed: boolean;\n /** The part before the first `|`: a note name or path, and an optional `#heading` or `#^block`. */\n target: string;\n /** The part after the first `|`, when there is one. */\n label?: string;\n}\n/**\n * An Obsidian comment in the Obsidian dialect. `value` is the text between the\n * `%%` markers of a comment in running text, and the whole source of a comment\n * that stands as a block of its own, markers included.\n */\nexport interface ObsidianComment extends Literal {\n type: \"obsidianComment\";\n}\n/** An Obsidian highlight, `==text==`, in the Obsidian dialect. `value` is the text between the markers. */\nexport interface ObsidianHighlight extends Literal {\n type: \"obsidianHighlight\";\n}\ndeclare module \"mdast\" {\n interface RootContentMap {\n wikiLink: WikiLink;\n obsidianComment: ObsidianComment;\n obsidianHighlight: ObsidianHighlight;\n }\n interface PhrasingContentMap {\n wikiLink: WikiLink;\n obsidianComment: ObsidianComment;\n obsidianHighlight: ObsidianHighlight;\n }\n interface BlockContentMap {\n obsidianComment: ObsidianComment;\n }\n}\ndeclare module \"micromark-util-types\" {\n interface TokenTypeMap {\n obsidianLiteral: \"obsidianLiteral\";\n obsidianBlockComment: \"obsidianBlockComment\";\n obsidianCommentData: \"obsidianCommentData\";\n }\n}\n\n/** A tokenizer, not a pre-parse replacement: code, escapes, and fenced blocks stay opaque. */\nconst tokenize: Tokenizer = function (effects, ok, nok) {\n let opening = \"\";\n let closing = \"\";\n let index = 0;\n let previous: number | null = null;\n let count = 0;\n const start: State = (code) => {\n opening = code === 33 ? \"![[\" : code === 91 ? \"[[\" : code === 37 ? \"%%\" : \"==\";\n closing = opening.endsWith(\"[[\") ? \"]]\" : opening;\n effects.enter(\"obsidianLiteral\");\n effects.enter(\"obsidianCommentData\");\n return open(code);\n };\n const open: State = (code) => {\n if (code !== opening.charCodeAt(index)) return nok(code);\n effects.consume(code);\n index++;\n return index === opening.length ? body : open;\n };\n const body: State = (code) => {\n if (code === null || (opening !== \"%%\" && code < 0 && code !== -1 && code !== -2))\n return nok(code);\n if (code < -2) {\n // Micromark subtokenizes each physical line separately. Expose every\n // line ending so a multiline inline comment can span more than two chunks.\n effects.exit(\"obsidianCommentData\");\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n previous = null;\n count++;\n return resume;\n }\n effects.consume(code);\n count++;\n if (code === closing.charCodeAt(1) && previous === closing.charCodeAt(0)) {\n // `====` and `[[]]` are text, while Obsidian hides an empty comment, `%%%%`.\n if (count <= 2 && opening !== \"%%\") return nok(code);\n effects.exit(\"obsidianCommentData\");\n effects.exit(\"obsidianLiteral\");\n return ok;\n }\n previous = code;\n return body;\n };\n const resume: State = (code) => {\n effects.enter(\"obsidianCommentData\");\n return body(code);\n };\n return start;\n};\n\n// Standalone comment blocks may cross blank lines. Keep their complete source opaque.\n// Obsidian reads a comment as inline wherever a paragraph is open, so one that\n// would interrupt a paragraph, or that text follows on the line where it\n// closes, is left to the inline construct and continues the paragraph (#357).\nconst tokenizeBlockComment: Tokenizer = function (effects, ok, nok) {\n const interrupt = this.interrupt;\n let opened = 0;\n let previous: number | null = null;\n let closed = false;\n const start: State = (code) => {\n if (code !== 37 || interrupt) return nok(code);\n if (opened === 0) {\n effects.enter(\"obsidianBlockComment\");\n effects.enter(\"obsidianCommentData\");\n }\n effects.consume(code);\n opened++;\n return opened === 2 ? body : start;\n };\n const body: State = (code) => {\n if (code === null || (closed && code < -2)) {\n effects.exit(\"obsidianCommentData\");\n effects.exit(\"obsidianBlockComment\");\n return ok(code);\n }\n if (code < -2) {\n effects.exit(\"obsidianCommentData\");\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n previous = null;\n return before;\n }\n // Only blank space may follow the closing `%%` on its line.\n if (closed && code !== 32 && code !== -1 && code !== -2) return nok(code);\n effects.consume(code);\n if (code === 37 && previous === 37) closed = true;\n previous = code;\n return body;\n };\n const before: State = (code) => {\n if (code === null) {\n effects.exit(\"obsidianBlockComment\");\n return ok(code);\n }\n if (code < -2) {\n effects.enter(\"lineEnding\");\n effects.consume(code);\n effects.exit(\"lineEnding\");\n return before;\n }\n effects.enter(\"obsidianCommentData\");\n return body(code);\n };\n return start;\n};\n\nexport const obsidianSyntax: Extension = {\n flow: { 37: { name: \"obsidianBlockComment\", tokenize: tokenizeBlockComment, concrete: true } },\n text: Object.fromEntries(\n [33, 91, 37, 61].map((code) => [code, { name: \"obsidianLiteral\", tokenize }]),\n ),\n};\nexport const obsidianTree: TreeExtension = {\n enter: {\n obsidianBlockComment(token) {\n this.enter({ type: \"obsidianComment\", value: this.sliceSerialize(token) }, token);\n },\n obsidianLiteral(token) {\n const raw = this.sliceSerialize(token);\n const wiki = raw.startsWith(\"[[\") || raw.startsWith(\"![[\");\n const embed = raw.startsWith(\"!\");\n const value = raw.slice(wiki && embed ? 3 : 2, -2).replaceAll(\"\\\\|\", \"|\");\n const divider = value.indexOf(\"|\");\n const node: WikiLink | ObsidianComment | ObsidianHighlight = wiki\n ? {\n type: \"wikiLink\",\n value,\n embed,\n target: divider < 0 ? value : value.slice(0, divider),\n ...(divider >= 0 ? { label: value.slice(divider + 1) } : {}),\n }\n : { type: raw.startsWith(\"%%\") ? \"obsidianComment\" : \"obsidianHighlight\", value };\n this.enter(node, token);\n },\n },\n exit: {\n obsidianBlockComment(token) {\n this.exit(token);\n },\n obsidianLiteral(token) {\n this.exit(token);\n },\n },\n};\n"]}
|