@astryxdesign/core 0.6.2-canary.bfee8a4 → 0.6.2-canary.d4cc232
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/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +12 -2
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +6 -1
- package/dist/Kbd/Kbd.d.ts +5 -3
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +36 -42
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +6 -2
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +63 -59
- package/dist/Markdown/ast.d.ts +124 -0
- package/dist/Markdown/ast.d.ts.map +1 -0
- package/dist/Markdown/ast.js +38 -0
- package/dist/Markdown/parser.d.ts +14 -8
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +352 -97
- package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/parseOutlineFromMarkdown.js +7 -7
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +46 -30
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +13 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +5 -5
- package/dist/SideNav/SideNav.d.ts +2 -1
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +9 -3
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +14 -8
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +11 -0
- package/dist/TabList/Tab.d.ts +1 -1
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +20 -7
- package/dist/ToggleButton/ToggleButton.d.ts +2 -1
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +7 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +15 -6
- package/dist/astryx.css +8 -0
- package/dist/utils/interactionOverlay.stylex.d.ts +8 -0
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
- package/dist/utils/interactionOverlay.stylex.js +9 -0
- package/package.json +3 -3
- package/src/Button/__tests__/Button.a11y.chromium.spec.ts +17 -1
- package/src/Button/__tests__/Button.a11y.known-failures.ts +0 -29
- package/src/Button/__tests__/Button.a11y.renders.tsx +9 -2
- package/src/Button/__tests__/Button.a11y.states.ts +9 -0
- package/src/CheckboxInput/CheckboxInput.doc.mjs +11 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +34 -0
- package/src/CheckboxInput/CheckboxInput.tsx +21 -1
- package/src/ClickableCard/ClickableCard.test.tsx +102 -5
- package/src/Collapsible/Collapsible.doc.mjs +11 -0
- package/src/Collapsible/Collapsible.test.tsx +21 -0
- package/src/Collapsible/Collapsible.tsx +5 -0
- package/src/Kbd/Kbd.doc.mjs +3 -3
- package/src/Kbd/Kbd.test.tsx +57 -1
- package/src/Kbd/Kbd.tsx +57 -37
- package/src/Link/Link.doc.mjs +11 -0
- package/src/Link/Link.test.tsx +24 -0
- package/src/Link/Link.tsx +5 -0
- package/src/Markdown/Markdown.spec.md +159 -43
- package/src/Markdown/Markdown.test.tsx +11 -0
- package/src/Markdown/Markdown.tsx +106 -96
- package/src/Markdown/ast.test.ts +169 -0
- package/src/Markdown/ast.ts +231 -0
- package/src/Markdown/incremental.test.ts +12 -0
- package/src/Markdown/parser.ts +427 -118
- package/src/Outline/Outline.spec.md +1 -1
- package/src/Outline/modules/parseOutlineFromMarkdown.spec.md +142 -0
- package/src/Outline/parseOutlineFromMarkdown.ts +8 -13
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +150 -1
- package/src/PowerSearch/PowerSearchEditPopover.tsx +51 -28
- package/src/RadioList/RadioList.doc.mjs +11 -0
- package/src/RadioList/RadioList.test.tsx +32 -0
- package/src/RadioList/RadioListItem.tsx +25 -1
- package/src/SegmentedControl/SegmentedControl.doc.mjs +2 -2
- package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +6 -9
- package/src/SideNav/SideNav.doc.mjs +1 -1
- package/src/SideNav/SideNav.test.tsx +10 -0
- package/src/SideNav/SideNav.tsx +14 -2
- package/src/Slider/Slider.doc.mjs +11 -0
- package/src/Slider/Slider.test.tsx +128 -0
- package/src/Slider/Slider.tsx +25 -7
- package/src/Switch/Switch.doc.mjs +11 -0
- package/src/Switch/Switch.test.tsx +16 -0
- package/src/Switch/Switch.tsx +28 -0
- package/src/TabList/Tab.tsx +35 -7
- package/src/TabList/TabList.doc.mjs +11 -0
- package/src/TabList/TabList.test.tsx +66 -0
- package/src/TabList/__tests__/Tabs.a11y.known-failures.ts +1 -34
- package/src/ToggleButton/ToggleButton.test.tsx +133 -0
- package/src/ToggleButton/ToggleButton.tsx +9 -2
- package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +209 -0
- package/src/Tokenizer/Tokenizer.spec.md +142 -75
- package/src/Typeahead/BaseTypeahead.spec.md +4 -3
- package/src/Typeahead/BaseTypeahead.tsx +15 -6
- package/src/Typeahead/Typeahead.test.tsx +53 -0
- package/src/__tests__/PressedState.a11y.chromium.spec.ts +813 -0
- package/src/__tests__/pressState.ts +93 -0
- package/src/utils/interactionOverlay.stylex.ts +20 -0
package/dist/Markdown/parser.js
CHANGED
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @file parser.ts
|
|
5
|
-
* @input Markdown string
|
|
6
|
-
* @output
|
|
7
|
-
* helpers
|
|
8
|
-
*
|
|
9
|
-
* Outline's parseOutlineFromMarkdown
|
|
10
|
-
* @position Core parser; consumed by Markdown.tsx and Outline
|
|
5
|
+
* @input Markdown string and released parse options
|
|
6
|
+
* @output Canonical MDAST-aligned nodes for internal consumers plus unchanged
|
|
7
|
+
* released parser-node projections; shared heading slug helpers
|
|
8
|
+
* @position Core parser and compatibility boundary; consumed by Markdown and Outline
|
|
11
9
|
*/
|
|
12
10
|
|
|
13
11
|
// ---------------------------------------------------------------------------
|
|
@@ -36,6 +34,207 @@
|
|
|
36
34
|
* optional fields without breaking anyone.
|
|
37
35
|
*/
|
|
38
36
|
|
|
37
|
+
function projectRange(position) {
|
|
38
|
+
const start = position?.start.offset;
|
|
39
|
+
const end = position?.end.offset;
|
|
40
|
+
return start == null || end == null ? {} : {
|
|
41
|
+
range: {
|
|
42
|
+
start,
|
|
43
|
+
end
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function projectInlineNode(node, cache) {
|
|
48
|
+
const cached = cache.get(node);
|
|
49
|
+
if (cached != null) {
|
|
50
|
+
return cached;
|
|
51
|
+
}
|
|
52
|
+
let projected;
|
|
53
|
+
switch (node.type) {
|
|
54
|
+
case 'text':
|
|
55
|
+
projected = {
|
|
56
|
+
type: 'text',
|
|
57
|
+
content: node.value
|
|
58
|
+
};
|
|
59
|
+
break;
|
|
60
|
+
case 'strong':
|
|
61
|
+
projected = {
|
|
62
|
+
type: 'bold',
|
|
63
|
+
children: node.children.map(child => projectInlineNode(child, cache))
|
|
64
|
+
};
|
|
65
|
+
break;
|
|
66
|
+
case 'emphasis':
|
|
67
|
+
projected = {
|
|
68
|
+
type: 'italic',
|
|
69
|
+
children: node.children.map(child => projectInlineNode(child, cache))
|
|
70
|
+
};
|
|
71
|
+
break;
|
|
72
|
+
case 'delete':
|
|
73
|
+
projected = {
|
|
74
|
+
type: 'strikethrough',
|
|
75
|
+
children: node.children.map(child => projectInlineNode(child, cache))
|
|
76
|
+
};
|
|
77
|
+
break;
|
|
78
|
+
case 'inlineCode':
|
|
79
|
+
projected = {
|
|
80
|
+
type: 'code',
|
|
81
|
+
content: node.value
|
|
82
|
+
};
|
|
83
|
+
break;
|
|
84
|
+
case 'inlineMath':
|
|
85
|
+
projected = {
|
|
86
|
+
type: 'math',
|
|
87
|
+
value: node.value
|
|
88
|
+
};
|
|
89
|
+
break;
|
|
90
|
+
case 'link':
|
|
91
|
+
projected = {
|
|
92
|
+
type: 'link',
|
|
93
|
+
href: node.url,
|
|
94
|
+
children: node.children.map(child => projectInlineNode(child, cache))
|
|
95
|
+
};
|
|
96
|
+
break;
|
|
97
|
+
case 'image':
|
|
98
|
+
projected = {
|
|
99
|
+
type: 'image',
|
|
100
|
+
src: node.url,
|
|
101
|
+
alt: node.alt
|
|
102
|
+
};
|
|
103
|
+
break;
|
|
104
|
+
case 'citation':
|
|
105
|
+
projected = {
|
|
106
|
+
type: 'citation',
|
|
107
|
+
sourceId: node.sourceId
|
|
108
|
+
};
|
|
109
|
+
break;
|
|
110
|
+
case 'break':
|
|
111
|
+
projected = {
|
|
112
|
+
type: 'break'
|
|
113
|
+
};
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
cache.set(node, projected);
|
|
117
|
+
return projected;
|
|
118
|
+
}
|
|
119
|
+
function projectTableCell(node, cache) {
|
|
120
|
+
const cached = cache.get(node);
|
|
121
|
+
if (cached != null) {
|
|
122
|
+
return cached;
|
|
123
|
+
}
|
|
124
|
+
const projected = {
|
|
125
|
+
children: node.children.map(child => projectInlineNode(child, cache))
|
|
126
|
+
};
|
|
127
|
+
cache.set(node, projected);
|
|
128
|
+
return projected;
|
|
129
|
+
}
|
|
130
|
+
function projectListItem(node, cache) {
|
|
131
|
+
const cached = cache.get(node);
|
|
132
|
+
if (cached != null) {
|
|
133
|
+
return cached;
|
|
134
|
+
}
|
|
135
|
+
const projected = {
|
|
136
|
+
checked: node.checked,
|
|
137
|
+
children: node.children.map(child => projectBlockNode(child, cache))
|
|
138
|
+
};
|
|
139
|
+
cache.set(node, projected);
|
|
140
|
+
return projected;
|
|
141
|
+
}
|
|
142
|
+
function projectBlockNode(node, cache) {
|
|
143
|
+
const cached = cache.get(node);
|
|
144
|
+
if (cached != null) {
|
|
145
|
+
return cached;
|
|
146
|
+
}
|
|
147
|
+
const metadata = projectRange(node.position);
|
|
148
|
+
let projected;
|
|
149
|
+
switch (node.type) {
|
|
150
|
+
case 'heading':
|
|
151
|
+
projected = {
|
|
152
|
+
type: 'heading',
|
|
153
|
+
level: node.depth,
|
|
154
|
+
children: node.children.map(child => projectInlineNode(child, cache)),
|
|
155
|
+
...metadata
|
|
156
|
+
};
|
|
157
|
+
break;
|
|
158
|
+
case 'paragraph':
|
|
159
|
+
projected = {
|
|
160
|
+
type: 'paragraph',
|
|
161
|
+
children: node.children.map(child => projectInlineNode(child, cache)),
|
|
162
|
+
...metadata
|
|
163
|
+
};
|
|
164
|
+
break;
|
|
165
|
+
case 'code':
|
|
166
|
+
projected = {
|
|
167
|
+
type: 'codeblock',
|
|
168
|
+
language: node.lang ?? 'plaintext',
|
|
169
|
+
content: node.value,
|
|
170
|
+
...metadata
|
|
171
|
+
};
|
|
172
|
+
break;
|
|
173
|
+
case 'math':
|
|
174
|
+
projected = {
|
|
175
|
+
type: 'math',
|
|
176
|
+
value: node.value,
|
|
177
|
+
...metadata
|
|
178
|
+
};
|
|
179
|
+
break;
|
|
180
|
+
case 'blockquote':
|
|
181
|
+
projected = {
|
|
182
|
+
type: 'blockquote',
|
|
183
|
+
children: node.children.map(child => projectBlockNode(child, cache)),
|
|
184
|
+
...metadata
|
|
185
|
+
};
|
|
186
|
+
break;
|
|
187
|
+
case 'list':
|
|
188
|
+
projected = {
|
|
189
|
+
type: 'list',
|
|
190
|
+
ordered: node.ordered,
|
|
191
|
+
start: node.start,
|
|
192
|
+
delimiter: node.delimiter,
|
|
193
|
+
loose: node.spread,
|
|
194
|
+
items: node.children.map(item => projectListItem(item, cache)),
|
|
195
|
+
...metadata
|
|
196
|
+
};
|
|
197
|
+
break;
|
|
198
|
+
case 'table':
|
|
199
|
+
{
|
|
200
|
+
const [header = {
|
|
201
|
+
type: 'tableRow',
|
|
202
|
+
children: []
|
|
203
|
+
}, ...rows] = node.children;
|
|
204
|
+
projected = {
|
|
205
|
+
type: 'table',
|
|
206
|
+
headers: header.children.map(cell => projectTableCell(cell, cache)),
|
|
207
|
+
alignments: [...node.align],
|
|
208
|
+
rows: rows.map(row => row.children.map(cell => projectTableCell(cell, cache))),
|
|
209
|
+
...metadata
|
|
210
|
+
};
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
case 'thematicBreak':
|
|
214
|
+
projected = {
|
|
215
|
+
type: 'hr',
|
|
216
|
+
...metadata
|
|
217
|
+
};
|
|
218
|
+
break;
|
|
219
|
+
case 'image':
|
|
220
|
+
projected = {
|
|
221
|
+
type: 'image',
|
|
222
|
+
alt: node.alt,
|
|
223
|
+
src: node.url,
|
|
224
|
+
...metadata
|
|
225
|
+
};
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
cache.set(node, projected);
|
|
229
|
+
return projected;
|
|
230
|
+
}
|
|
231
|
+
function projectInlineNodes(nodes, cache = new WeakMap()) {
|
|
232
|
+
return nodes.map(node => projectInlineNode(node, cache));
|
|
233
|
+
}
|
|
234
|
+
function projectMarkdownRoot(root, cache = new WeakMap()) {
|
|
235
|
+
return root.children.map(node => projectBlockNode(node, cache));
|
|
236
|
+
}
|
|
237
|
+
|
|
39
238
|
// ---------------------------------------------------------------------------
|
|
40
239
|
// Parse options
|
|
41
240
|
// ---------------------------------------------------------------------------
|
|
@@ -359,7 +558,7 @@ function matchReferenceLink(text, start, linkDefs, opts) {
|
|
|
359
558
|
return {
|
|
360
559
|
node: {
|
|
361
560
|
type: 'link',
|
|
362
|
-
href,
|
|
561
|
+
url: href,
|
|
363
562
|
children: parseInlineImpl(linkText, opts)
|
|
364
563
|
},
|
|
365
564
|
end: labelClose + 1
|
|
@@ -380,7 +579,7 @@ function matchReferenceLink(text, start, linkDefs, opts) {
|
|
|
380
579
|
return {
|
|
381
580
|
node: {
|
|
382
581
|
type: 'link',
|
|
383
|
-
href,
|
|
582
|
+
url: href,
|
|
384
583
|
children: parseInlineImpl(linkText, opts)
|
|
385
584
|
},
|
|
386
585
|
end: textClose + 1
|
|
@@ -404,7 +603,7 @@ function matchReferenceImage(text, start, linkDefs) {
|
|
|
404
603
|
return {
|
|
405
604
|
node: {
|
|
406
605
|
type: 'image',
|
|
407
|
-
src,
|
|
606
|
+
url: src,
|
|
408
607
|
alt
|
|
409
608
|
},
|
|
410
609
|
end: labelClose + 1
|
|
@@ -423,7 +622,7 @@ function matchReferenceImage(text, start, linkDefs) {
|
|
|
423
622
|
return {
|
|
424
623
|
node: {
|
|
425
624
|
type: 'image',
|
|
426
|
-
src,
|
|
625
|
+
url: src,
|
|
427
626
|
alt
|
|
428
627
|
},
|
|
429
628
|
end: altClose + 1
|
|
@@ -571,6 +770,11 @@ function matchBracketCitation(text, i, opts) {
|
|
|
571
770
|
};
|
|
572
771
|
}
|
|
573
772
|
export function parseInline(text, arg) {
|
|
773
|
+
return projectInlineNodes(parseInlineAst(text, arg));
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/** @internal Canonical inline parse used by Markdown rendering. */
|
|
777
|
+
export function parseInlineAst(text, arg) {
|
|
574
778
|
return parseInlineEntry(text, resolveOptions(arg));
|
|
575
779
|
}
|
|
576
780
|
|
|
@@ -595,7 +799,7 @@ function parseInlineImpl(text, opts) {
|
|
|
595
799
|
if (text[i] === '\\' && i + 1 < text.length) {
|
|
596
800
|
nodes.push({
|
|
597
801
|
type: 'text',
|
|
598
|
-
|
|
802
|
+
value: text[i + 1]
|
|
599
803
|
});
|
|
600
804
|
i += 2;
|
|
601
805
|
continue;
|
|
@@ -608,8 +812,8 @@ function parseInlineImpl(text, opts) {
|
|
|
608
812
|
const closeIndex = text.indexOf('`'.repeat(tickCount), openIndex);
|
|
609
813
|
if (closeIndex !== -1) {
|
|
610
814
|
nodes.push({
|
|
611
|
-
type: '
|
|
612
|
-
|
|
815
|
+
type: 'inlineCode',
|
|
816
|
+
value: text.slice(openIndex, closeIndex)
|
|
613
817
|
});
|
|
614
818
|
i = closeIndex + tickCount;
|
|
615
819
|
continue;
|
|
@@ -621,7 +825,7 @@ function parseInlineImpl(text, opts) {
|
|
|
621
825
|
const closeIndex = findInlineMathEnd(text, i);
|
|
622
826
|
if (closeIndex !== -1) {
|
|
623
827
|
nodes.push({
|
|
624
|
-
type: '
|
|
828
|
+
type: 'inlineMath',
|
|
625
829
|
value: text.slice(i + 1, closeIndex)
|
|
626
830
|
});
|
|
627
831
|
i = closeIndex + 1;
|
|
@@ -653,12 +857,12 @@ function parseInlineImpl(text, opts) {
|
|
|
653
857
|
// Dangerous scheme — emit as plain text.
|
|
654
858
|
nodes.push({
|
|
655
859
|
type: 'text',
|
|
656
|
-
|
|
860
|
+
value: text.slice(i, srcClose + 1)
|
|
657
861
|
});
|
|
658
862
|
} else {
|
|
659
863
|
nodes.push({
|
|
660
864
|
type: 'image',
|
|
661
|
-
src,
|
|
865
|
+
url: src,
|
|
662
866
|
alt: text.slice(i + 2, altClose)
|
|
663
867
|
});
|
|
664
868
|
}
|
|
@@ -702,12 +906,12 @@ function parseInlineImpl(text, opts) {
|
|
|
702
906
|
// Dangerous scheme — emit as plain text instead of a link.
|
|
703
907
|
nodes.push({
|
|
704
908
|
type: 'text',
|
|
705
|
-
|
|
909
|
+
value: text.slice(i, urlClose + 1)
|
|
706
910
|
});
|
|
707
911
|
} else {
|
|
708
912
|
nodes.push({
|
|
709
913
|
type: 'link',
|
|
710
|
-
href,
|
|
914
|
+
url: href,
|
|
711
915
|
children: parseInlineImpl(text.slice(i + 1, textClose), opts)
|
|
712
916
|
});
|
|
713
917
|
}
|
|
@@ -737,9 +941,9 @@ function parseInlineImpl(text, opts) {
|
|
|
737
941
|
const closeIndex = text.indexOf(marker, i + 3);
|
|
738
942
|
if (closeIndex !== -1 && (!isUnderscore || !isWordChar(text[closeIndex + 3]))) {
|
|
739
943
|
nodes.push({
|
|
740
|
-
type: '
|
|
944
|
+
type: 'strong',
|
|
741
945
|
children: [{
|
|
742
|
-
type: '
|
|
946
|
+
type: 'emphasis',
|
|
743
947
|
children: parseInlineImpl(text.slice(i + 3, closeIndex), opts)
|
|
744
948
|
}]
|
|
745
949
|
});
|
|
@@ -759,7 +963,7 @@ function parseInlineImpl(text, opts) {
|
|
|
759
963
|
const closeIndex = text.indexOf(marker, i + 2);
|
|
760
964
|
if (closeIndex !== -1 && (!isUnderscore || !isWordChar(text[closeIndex + 2]))) {
|
|
761
965
|
nodes.push({
|
|
762
|
-
type: '
|
|
966
|
+
type: 'strong',
|
|
763
967
|
children: parseInlineImpl(text.slice(i + 2, closeIndex), opts)
|
|
764
968
|
});
|
|
765
969
|
i = closeIndex + 2;
|
|
@@ -773,7 +977,7 @@ function parseInlineImpl(text, opts) {
|
|
|
773
977
|
const closeIndex = text.indexOf('~~', i + 2);
|
|
774
978
|
if (closeIndex !== -1) {
|
|
775
979
|
nodes.push({
|
|
776
|
-
type: '
|
|
980
|
+
type: 'delete',
|
|
777
981
|
children: parseInlineImpl(text.slice(i + 2, closeIndex), opts)
|
|
778
982
|
});
|
|
779
983
|
i = closeIndex + 2;
|
|
@@ -790,7 +994,7 @@ function parseInlineImpl(text, opts) {
|
|
|
790
994
|
const closeIndex = text.indexOf(text[i], i + 1);
|
|
791
995
|
if (closeIndex !== -1 && closeIndex > i + 1 && (!isUnderscore || !isWordChar(text[closeIndex + 1]))) {
|
|
792
996
|
nodes.push({
|
|
793
|
-
type: '
|
|
997
|
+
type: 'emphasis',
|
|
794
998
|
children: parseInlineImpl(text.slice(i + 1, closeIndex), opts)
|
|
795
999
|
});
|
|
796
1000
|
i = closeIndex + 1;
|
|
@@ -813,11 +1017,14 @@ function parseInlineImpl(text, opts) {
|
|
|
813
1017
|
if (trimmed.length > 0) {
|
|
814
1018
|
const last = nodes[nodes.length - 1];
|
|
815
1019
|
if (last?.type === 'text') {
|
|
816
|
-
|
|
1020
|
+
nodes[nodes.length - 1] = {
|
|
1021
|
+
...last,
|
|
1022
|
+
value: last.value + trimmed
|
|
1023
|
+
};
|
|
817
1024
|
} else {
|
|
818
1025
|
nodes.push({
|
|
819
1026
|
type: 'text',
|
|
820
|
-
|
|
1027
|
+
value: trimmed
|
|
821
1028
|
});
|
|
822
1029
|
}
|
|
823
1030
|
}
|
|
@@ -830,11 +1037,14 @@ function parseInlineImpl(text, opts) {
|
|
|
830
1037
|
}
|
|
831
1038
|
const last = nodes[nodes.length - 1];
|
|
832
1039
|
if (last?.type === 'text') {
|
|
833
|
-
|
|
1040
|
+
nodes[nodes.length - 1] = {
|
|
1041
|
+
...last,
|
|
1042
|
+
value: last.value + content
|
|
1043
|
+
};
|
|
834
1044
|
} else {
|
|
835
1045
|
nodes.push({
|
|
836
1046
|
type: 'text',
|
|
837
|
-
content
|
|
1047
|
+
value: content
|
|
838
1048
|
});
|
|
839
1049
|
}
|
|
840
1050
|
i = end;
|
|
@@ -1063,7 +1273,7 @@ function splitTextOnAutolinks(content) {
|
|
|
1063
1273
|
if (matches.length === 0) {
|
|
1064
1274
|
return [{
|
|
1065
1275
|
type: 'text',
|
|
1066
|
-
content
|
|
1276
|
+
value: content
|
|
1067
1277
|
}];
|
|
1068
1278
|
}
|
|
1069
1279
|
const out = [];
|
|
@@ -1072,15 +1282,15 @@ function splitTextOnAutolinks(content) {
|
|
|
1072
1282
|
if (m.start > cursor) {
|
|
1073
1283
|
out.push({
|
|
1074
1284
|
type: 'text',
|
|
1075
|
-
|
|
1285
|
+
value: content.slice(cursor, m.start)
|
|
1076
1286
|
});
|
|
1077
1287
|
}
|
|
1078
1288
|
out.push({
|
|
1079
1289
|
type: 'link',
|
|
1080
|
-
|
|
1290
|
+
url: m.href,
|
|
1081
1291
|
children: [{
|
|
1082
1292
|
type: 'text',
|
|
1083
|
-
|
|
1293
|
+
value: m.display
|
|
1084
1294
|
}]
|
|
1085
1295
|
});
|
|
1086
1296
|
cursor = m.end;
|
|
@@ -1088,7 +1298,7 @@ function splitTextOnAutolinks(content) {
|
|
|
1088
1298
|
if (cursor < content.length) {
|
|
1089
1299
|
out.push({
|
|
1090
1300
|
type: 'text',
|
|
1091
|
-
|
|
1301
|
+
value: content.slice(cursor)
|
|
1092
1302
|
});
|
|
1093
1303
|
}
|
|
1094
1304
|
return out;
|
|
@@ -1106,16 +1316,19 @@ function transformAutolinks(nodes) {
|
|
|
1106
1316
|
const out = [];
|
|
1107
1317
|
for (const node of nodes) {
|
|
1108
1318
|
if (node.type === 'text') {
|
|
1109
|
-
const split = splitTextOnAutolinks(node.
|
|
1319
|
+
const split = splitTextOnAutolinks(node.value);
|
|
1110
1320
|
for (const seg of split) {
|
|
1111
1321
|
const last = out[out.length - 1];
|
|
1112
1322
|
if (seg.type === 'text' && last?.type === 'text') {
|
|
1113
|
-
|
|
1323
|
+
out[out.length - 1] = {
|
|
1324
|
+
...last,
|
|
1325
|
+
value: last.value + seg.value
|
|
1326
|
+
};
|
|
1114
1327
|
} else {
|
|
1115
1328
|
out.push(seg);
|
|
1116
1329
|
}
|
|
1117
1330
|
}
|
|
1118
|
-
} else if (node.type === '
|
|
1331
|
+
} else if (node.type === 'strong' || node.type === 'emphasis' || node.type === 'delete') {
|
|
1119
1332
|
out.push({
|
|
1120
1333
|
...node,
|
|
1121
1334
|
children: transformAutolinks(node.children)
|
|
@@ -1271,6 +1484,7 @@ function splitTableRow(line) {
|
|
|
1271
1484
|
}
|
|
1272
1485
|
function parseTable(lines, lineIndex, opts) {
|
|
1273
1486
|
const headers = splitTableRow(lines[lineIndex]).map(cell => ({
|
|
1487
|
+
type: 'tableCell',
|
|
1274
1488
|
children: parseInlineEntry(cell, opts)
|
|
1275
1489
|
}));
|
|
1276
1490
|
const alignments = splitTableRow(lines[lineIndex + 1]).map(cell => {
|
|
@@ -1282,17 +1496,23 @@ function parseTable(lines, lineIndex, opts) {
|
|
|
1282
1496
|
const rows = [];
|
|
1283
1497
|
let rowIndex = lineIndex + 2;
|
|
1284
1498
|
while (rowIndex < lines.length && lines[rowIndex].includes('|') && lines[rowIndex].trim() !== '') {
|
|
1285
|
-
rows.push(
|
|
1286
|
-
|
|
1287
|
-
|
|
1499
|
+
rows.push({
|
|
1500
|
+
type: 'tableRow',
|
|
1501
|
+
children: splitTableRow(lines[rowIndex]).map(cell => ({
|
|
1502
|
+
type: 'tableCell',
|
|
1503
|
+
children: parseInlineEntry(cell, opts)
|
|
1504
|
+
}))
|
|
1505
|
+
});
|
|
1288
1506
|
rowIndex++;
|
|
1289
1507
|
}
|
|
1290
1508
|
return {
|
|
1291
1509
|
node: {
|
|
1292
1510
|
type: 'table',
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1511
|
+
align: alignments,
|
|
1512
|
+
children: [{
|
|
1513
|
+
type: 'tableRow',
|
|
1514
|
+
children: headers
|
|
1515
|
+
}, ...rows]
|
|
1296
1516
|
},
|
|
1297
1517
|
nextIndex: rowIndex
|
|
1298
1518
|
};
|
|
@@ -1335,6 +1555,7 @@ function parseList(lines, startIndex, ordered, opts) {
|
|
|
1335
1555
|
itemText += '\n' + deindented.join('\n');
|
|
1336
1556
|
}
|
|
1337
1557
|
items.push({
|
|
1558
|
+
type: 'listItem',
|
|
1338
1559
|
checked,
|
|
1339
1560
|
children: parseMarkdownImpl(itemText, nested(opts))
|
|
1340
1561
|
});
|
|
@@ -1357,8 +1578,8 @@ function parseList(lines, startIndex, ordered, opts) {
|
|
|
1357
1578
|
ordered,
|
|
1358
1579
|
start,
|
|
1359
1580
|
delimiter: ordered ? delim : undefined,
|
|
1360
|
-
|
|
1361
|
-
items
|
|
1581
|
+
spread: loose || undefined,
|
|
1582
|
+
children: items
|
|
1362
1583
|
},
|
|
1363
1584
|
nextIndex: index
|
|
1364
1585
|
};
|
|
@@ -1369,7 +1590,15 @@ function parseList(lines, startIndex, ordered, opts) {
|
|
|
1369
1590
|
// ---------------------------------------------------------------------------
|
|
1370
1591
|
|
|
1371
1592
|
export function parseMarkdown(input, arg) {
|
|
1372
|
-
return
|
|
1593
|
+
return projectMarkdownRoot(parseMarkdownAst(input, arg));
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
/** @internal Canonical block parse used by Markdown and Outline rendering. */
|
|
1597
|
+
export function parseMarkdownAst(input, arg) {
|
|
1598
|
+
return {
|
|
1599
|
+
type: 'root',
|
|
1600
|
+
children: parseMarkdownImpl(input, resolveOptions(arg))
|
|
1601
|
+
};
|
|
1373
1602
|
}
|
|
1374
1603
|
function parseMarkdownImpl(input, baseOpts) {
|
|
1375
1604
|
// Collect this input's link reference definitions and strip their lines,
|
|
@@ -1425,7 +1654,7 @@ function parseMarkdownImpl(input, baseOpts) {
|
|
|
1425
1654
|
const fenceMatch = line.match(/^(`{3,}|~{3,})(\w*)/);
|
|
1426
1655
|
if (fenceMatch) {
|
|
1427
1656
|
const fence = fenceMatch[1];
|
|
1428
|
-
const language = fenceMatch[2] ||
|
|
1657
|
+
const language = fenceMatch[2] || null;
|
|
1429
1658
|
const codeLines = [];
|
|
1430
1659
|
index++;
|
|
1431
1660
|
while (index < lines.length && !lines[index].startsWith(fence)) {
|
|
@@ -1437,9 +1666,9 @@ function parseMarkdownImpl(input, baseOpts) {
|
|
|
1437
1666
|
// can end on them, so it states its own end rather than letting the
|
|
1438
1667
|
// positional derivation trim them off.
|
|
1439
1668
|
pushBlock({
|
|
1440
|
-
type: '
|
|
1441
|
-
language,
|
|
1442
|
-
|
|
1669
|
+
type: 'code',
|
|
1670
|
+
lang: language,
|
|
1671
|
+
value: codeLines.join('\n')
|
|
1443
1672
|
}, Math.min(index, lines.length) - 1);
|
|
1444
1673
|
continue;
|
|
1445
1674
|
}
|
|
@@ -1462,7 +1691,7 @@ function parseMarkdownImpl(input, baseOpts) {
|
|
|
1462
1691
|
if (headingMatch) {
|
|
1463
1692
|
pushBlock({
|
|
1464
1693
|
type: 'heading',
|
|
1465
|
-
|
|
1694
|
+
depth: headingMatch[1].length,
|
|
1466
1695
|
children: parseInlineEntry(headingMatch[2], opts)
|
|
1467
1696
|
});
|
|
1468
1697
|
index++;
|
|
@@ -1472,7 +1701,7 @@ function parseMarkdownImpl(input, baseOpts) {
|
|
|
1472
1701
|
// --- HR (must precede list check to handle `- - -`, `* * *`, `_ _ _`) ---
|
|
1473
1702
|
if (isHorizontalRule(line)) {
|
|
1474
1703
|
pushBlock({
|
|
1475
|
-
type: '
|
|
1704
|
+
type: 'thematicBreak'
|
|
1476
1705
|
});
|
|
1477
1706
|
index++;
|
|
1478
1707
|
continue;
|
|
@@ -1486,7 +1715,7 @@ function parseMarkdownImpl(input, baseOpts) {
|
|
|
1486
1715
|
pushBlock({
|
|
1487
1716
|
type: 'image',
|
|
1488
1717
|
alt: imageMatch[1],
|
|
1489
|
-
|
|
1718
|
+
url: imageMatch[2]
|
|
1490
1719
|
});
|
|
1491
1720
|
index++;
|
|
1492
1721
|
continue;
|
|
@@ -1586,9 +1815,13 @@ function stampSourceRanges(blocks, blockStartLines, blockEndLines, lines, lineMa
|
|
|
1586
1815
|
const end = lineStart(endLine) + lines[endLine].length;
|
|
1587
1816
|
blocks[i] = {
|
|
1588
1817
|
...blocks[i],
|
|
1589
|
-
|
|
1590
|
-
start:
|
|
1591
|
-
|
|
1818
|
+
position: {
|
|
1819
|
+
start: {
|
|
1820
|
+
offset: lineStart(startLine)
|
|
1821
|
+
},
|
|
1822
|
+
end: {
|
|
1823
|
+
offset: end
|
|
1824
|
+
}
|
|
1592
1825
|
}
|
|
1593
1826
|
};
|
|
1594
1827
|
}
|
|
@@ -1609,6 +1842,11 @@ function makeIncrementalCache(state) {
|
|
|
1609
1842
|
tailLinkDefs: new Map(),
|
|
1610
1843
|
linkDefs: defs,
|
|
1611
1844
|
linkDefsKey: linkDefsSignature(defs),
|
|
1845
|
+
settledAstBlocks: [],
|
|
1846
|
+
settledRevision: 0,
|
|
1847
|
+
projectedRevision: -1,
|
|
1848
|
+
projectedSettledBlocks: [],
|
|
1849
|
+
projectionCache: new WeakMap(),
|
|
1612
1850
|
work: {
|
|
1613
1851
|
splitCharacters: 0,
|
|
1614
1852
|
boundaryLines: 0,
|
|
@@ -2066,14 +2304,13 @@ function mergeSettledBlocks(prev, delta) {
|
|
|
2066
2304
|
ordered: prevLast.ordered,
|
|
2067
2305
|
start: prevLast.start,
|
|
2068
2306
|
delimiter: prevLast.delimiter,
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
// One list now, so one
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
end: deltaFirst.range.end
|
|
2307
|
+
spread: true,
|
|
2308
|
+
children: [...prevLast.children, ...deltaFirst.children],
|
|
2309
|
+
// One list now, so one position spans both halves.
|
|
2310
|
+
...(prevLast.position != null && deltaFirst.position != null ? {
|
|
2311
|
+
position: {
|
|
2312
|
+
start: prevLast.position.start,
|
|
2313
|
+
end: deltaFirst.position.end
|
|
2077
2314
|
}
|
|
2078
2315
|
} : null)
|
|
2079
2316
|
};
|
|
@@ -2085,11 +2322,11 @@ function mergeSettledBlocks(prev, delta) {
|
|
|
2085
2322
|
/** Append a newly-settled slice without copying the already-settled prefix. */
|
|
2086
2323
|
function appendSettledBlocks(prev, delta) {
|
|
2087
2324
|
if (delta.length === 0) {
|
|
2088
|
-
return;
|
|
2325
|
+
return false;
|
|
2089
2326
|
}
|
|
2090
2327
|
if (prev.length === 0) {
|
|
2091
2328
|
prev.push(...delta);
|
|
2092
|
-
return;
|
|
2329
|
+
return false;
|
|
2093
2330
|
}
|
|
2094
2331
|
const prevLast = prev[prev.length - 1];
|
|
2095
2332
|
const deltaFirst = delta[0];
|
|
@@ -2099,19 +2336,20 @@ function appendSettledBlocks(prev, delta) {
|
|
|
2099
2336
|
ordered: prevLast.ordered,
|
|
2100
2337
|
start: prevLast.start,
|
|
2101
2338
|
delimiter: prevLast.delimiter,
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
...(prevLast.
|
|
2105
|
-
|
|
2106
|
-
start: prevLast.
|
|
2107
|
-
end: deltaFirst.
|
|
2339
|
+
spread: true,
|
|
2340
|
+
children: [...prevLast.children, ...deltaFirst.children],
|
|
2341
|
+
...(prevLast.position != null && deltaFirst.position != null ? {
|
|
2342
|
+
position: {
|
|
2343
|
+
start: prevLast.position.start,
|
|
2344
|
+
end: deltaFirst.position.end
|
|
2108
2345
|
}
|
|
2109
2346
|
} : null)
|
|
2110
2347
|
};
|
|
2111
2348
|
prev.push(...delta.slice(1));
|
|
2112
|
-
return;
|
|
2349
|
+
return true;
|
|
2113
2350
|
}
|
|
2114
2351
|
prev.push(...delta);
|
|
2352
|
+
return false;
|
|
2115
2353
|
}
|
|
2116
2354
|
function sameUnsettledDefinitions(previous, next, settled) {
|
|
2117
2355
|
for (const [label, destination] of previous) {
|
|
@@ -2138,6 +2376,11 @@ function resetIncrementalCache(state, cache) {
|
|
|
2138
2376
|
cache.tailLinkDefs = new Map();
|
|
2139
2377
|
cache.linkDefs = new Map();
|
|
2140
2378
|
cache.linkDefsKey = '';
|
|
2379
|
+
cache.settledAstBlocks = [];
|
|
2380
|
+
cache.settledRevision++;
|
|
2381
|
+
cache.projectedRevision = -1;
|
|
2382
|
+
cache.projectedSettledBlocks = [];
|
|
2383
|
+
cache.projectionCache = new WeakMap();
|
|
2141
2384
|
cache.work = {
|
|
2142
2385
|
splitCharacters: 0,
|
|
2143
2386
|
boundaryLines: 0,
|
|
@@ -2159,6 +2402,25 @@ function resetIncrementalCache(state, cache) {
|
|
|
2159
2402
|
*/
|
|
2160
2403
|
|
|
2161
2404
|
export function parseMarkdownIncremental(input, state, arg) {
|
|
2405
|
+
const root = parseMarkdownAstIncremental(input, state, arg);
|
|
2406
|
+
const cache = incrementalCaches.get(state) ?? makeIncrementalCache(state);
|
|
2407
|
+
const projected = projectMarkdownRoot(root, cache.projectionCache);
|
|
2408
|
+
if (cache.projectedRevision !== cache.settledRevision) {
|
|
2409
|
+
cache.projectedSettledBlocks = cache.settledAstBlocks.map(block => projectBlockNode(block, cache.projectionCache));
|
|
2410
|
+
cache.projectedRevision = cache.settledRevision;
|
|
2411
|
+
}
|
|
2412
|
+
state.settledBlocks = cache.projectedSettledBlocks;
|
|
2413
|
+
return projected;
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
/** @internal Canonical incremental parse used by Markdown rendering. */
|
|
2417
|
+
export function parseMarkdownAstIncremental(input, state, arg) {
|
|
2418
|
+
return {
|
|
2419
|
+
type: 'root',
|
|
2420
|
+
children: parseMarkdownIncrementalAstBlocks(input, state, arg)
|
|
2421
|
+
};
|
|
2422
|
+
}
|
|
2423
|
+
function parseMarkdownIncrementalAstBlocks(input, state, arg) {
|
|
2162
2424
|
const opts = resolveOptions(arg);
|
|
2163
2425
|
const cache = incrementalCaches.get(state) ?? makeIncrementalCache(state);
|
|
2164
2426
|
let reparseSettled = false;
|
|
@@ -2262,12 +2524,27 @@ export function parseMarkdownIncremental(input, state, arg) {
|
|
|
2262
2524
|
const unsettledText = openFence ? unsettledRaw : openMath ? trimOpenDisplayMath(unsettledRaw) : trimUnsettledStructural(unsettledRaw);
|
|
2263
2525
|
let parsedSettledBlocks = 0;
|
|
2264
2526
|
if (reparseSettled) {
|
|
2265
|
-
|
|
2266
|
-
parsedSettledBlocks =
|
|
2527
|
+
cache.settledAstBlocks = state.settledText ? parseMarkdownImpl(state.settledText, parseOpts) : [];
|
|
2528
|
+
parsedSettledBlocks = cache.settledAstBlocks.length;
|
|
2529
|
+
cache.settledRevision++;
|
|
2530
|
+
cache.projectedSettledBlocks = cache.settledAstBlocks.map(block => projectBlockNode(block, cache.projectionCache));
|
|
2531
|
+
cache.projectedRevision = cache.settledRevision;
|
|
2267
2532
|
} else if (settledDelta !== '') {
|
|
2268
2533
|
const deltaBlocks = parseMarkdownImpl(settledDelta, atOffset(parseOpts, oldSettledEnd));
|
|
2269
|
-
|
|
2534
|
+
const mergeIndex = cache.settledAstBlocks.length - 1;
|
|
2535
|
+
const mergedList = appendSettledBlocks(cache.settledAstBlocks, deltaBlocks);
|
|
2270
2536
|
parsedSettledBlocks = deltaBlocks.length;
|
|
2537
|
+
cache.settledRevision++;
|
|
2538
|
+
const projectedDelta = deltaBlocks.map(block => projectBlockNode(block, cache.projectionCache));
|
|
2539
|
+
if (mergedList) {
|
|
2540
|
+
const canonicalMerged = cache.settledAstBlocks[mergeIndex];
|
|
2541
|
+
const projectedMerged = projectBlockNode(canonicalMerged, cache.projectionCache);
|
|
2542
|
+
cache.projectedSettledBlocks[mergeIndex] = projectedMerged;
|
|
2543
|
+
cache.projectedSettledBlocks.push(...projectedDelta.slice(1));
|
|
2544
|
+
} else {
|
|
2545
|
+
cache.projectedSettledBlocks.push(...projectedDelta);
|
|
2546
|
+
}
|
|
2547
|
+
cache.projectedRevision = cache.settledRevision;
|
|
2271
2548
|
}
|
|
2272
2549
|
|
|
2273
2550
|
// The unsettled tail is trimmed before parsing, so its offset in the
|
|
@@ -2290,7 +2567,7 @@ export function parseMarkdownIncremental(input, state, arg) {
|
|
|
2290
2567
|
definitionCharacters: settledDelta.length + unsettledInput.length,
|
|
2291
2568
|
renderedBlocks: parsedSettledBlocks + unsettledBlocks.length
|
|
2292
2569
|
};
|
|
2293
|
-
return mergeSettledBlocks(
|
|
2570
|
+
return mergeSettledBlocks(cache.settledAstBlocks, unsettledBlocks);
|
|
2294
2571
|
}
|
|
2295
2572
|
|
|
2296
2573
|
// ---------------------------------------------------------------------------
|
|
@@ -2301,28 +2578,6 @@ export function parseMarkdownIncremental(input, state, arg) {
|
|
|
2301
2578
|
// derives its item ids from the same functions, so outline hash links always
|
|
2302
2579
|
// resolve to a rendered heading by construction.
|
|
2303
2580
|
|
|
2304
|
-
/** Flatten inline nodes into their plain text content. */
|
|
2305
|
-
export function inlineText(nodes) {
|
|
2306
|
-
return nodes.map(node => {
|
|
2307
|
-
switch (node.type) {
|
|
2308
|
-
case 'text':
|
|
2309
|
-
case 'code':
|
|
2310
|
-
case 'math':
|
|
2311
|
-
return node.type === 'math' ? node.value : node.content;
|
|
2312
|
-
case 'bold':
|
|
2313
|
-
case 'italic':
|
|
2314
|
-
case 'strikethrough':
|
|
2315
|
-
case 'link':
|
|
2316
|
-
return inlineText(node.children);
|
|
2317
|
-
case 'image':
|
|
2318
|
-
return node.alt;
|
|
2319
|
-
case 'citation':
|
|
2320
|
-
case 'break':
|
|
2321
|
-
return '';
|
|
2322
|
-
}
|
|
2323
|
-
}).join('');
|
|
2324
|
-
}
|
|
2325
|
-
|
|
2326
2581
|
/** Turn heading text into a URL-safe slug (lowercase, hyphen-separated). */
|
|
2327
2582
|
export function slugify(value) {
|
|
2328
2583
|
return value.trim().toLowerCase().replace(/['"]/g, '').replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|