@localix-ai/flowdown 0.0.0-stage → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -2
  3. package/dist/browser/file-actions.js +80 -0
  4. package/dist/browser/file-actions.js.map +1 -0
  5. package/dist/core/block-facts.js +72 -0
  6. package/dist/core/block-facts.js.map +1 -0
  7. package/dist/core/blocks.d.ts +25 -0
  8. package/dist/core/blocks.js +464 -0
  9. package/dist/core/blocks.js.map +1 -0
  10. package/dist/core/bounded-cache.js +42 -0
  11. package/dist/core/bounded-cache.js.map +1 -0
  12. package/dist/core/continues.js +15 -0
  13. package/dist/core/continues.js.map +1 -0
  14. package/dist/core/dollars.d.ts +12 -0
  15. package/dist/core/dollars.js +88 -0
  16. package/dist/core/dollars.js.map +1 -0
  17. package/dist/core/fence-scan.js +62 -0
  18. package/dist/core/fence-scan.js.map +1 -0
  19. package/dist/core/file-tree-parse.d.ts +26 -0
  20. package/dist/core/file-tree-parse.js +51 -0
  21. package/dist/core/file-tree-parse.js.map +1 -0
  22. package/dist/core/forms-html.js +63 -0
  23. package/dist/core/forms-html.js.map +1 -0
  24. package/dist/core/forms.d.ts +28 -0
  25. package/dist/core/forms.js +23 -0
  26. package/dist/core/forms.js.map +1 -0
  27. package/dist/core/headings.d.ts +11 -0
  28. package/dist/core/headings.js +74 -0
  29. package/dist/core/headings.js.map +1 -0
  30. package/dist/core/heal.d.ts +11 -0
  31. package/dist/core/heal.js +220 -0
  32. package/dist/core/heal.js.map +1 -0
  33. package/dist/core/load-once.js +23 -0
  34. package/dist/core/load-once.js.map +1 -0
  35. package/dist/core/math-delimiters.js +33 -0
  36. package/dist/core/math-delimiters.js.map +1 -0
  37. package/dist/core/math-syntax.js +56 -0
  38. package/dist/core/math-syntax.js.map +1 -0
  39. package/dist/core/prose.d.ts +10 -0
  40. package/dist/core/prose.js +77 -0
  41. package/dist/core/prose.js.map +1 -0
  42. package/dist/core/remark-answer-blocks.d.ts +5 -0
  43. package/dist/core/remark-answer-blocks.js +172 -0
  44. package/dist/core/remark-answer-blocks.js.map +1 -0
  45. package/dist/core/remark-answer-containers.js +299 -0
  46. package/dist/core/remark-answer-containers.js.map +1 -0
  47. package/dist/core/sanitize-schema.d.ts +18 -0
  48. package/dist/core/sanitize-schema.js +62 -0
  49. package/dist/core/sanitize-schema.js.map +1 -0
  50. package/dist/core/syntax.d.ts +8 -0
  51. package/dist/core/syntax.js +32 -0
  52. package/dist/core/syntax.js.map +1 -0
  53. package/dist/dialect.d.ts +92 -0
  54. package/dist/dialect.js +176 -0
  55. package/dist/dialect.js.map +1 -0
  56. package/dist/document/fence.d.ts +25 -0
  57. package/dist/document/fence.js +102 -0
  58. package/dist/document/fence.js.map +1 -0
  59. package/dist/document/index.d.ts +46 -0
  60. package/dist/document/index.js +66 -0
  61. package/dist/document/index.js.map +1 -0
  62. package/dist/document/table.d.ts +11 -0
  63. package/dist/document/table.js +35 -0
  64. package/dist/document/table.js.map +1 -0
  65. package/dist/dom/index.d.ts +21 -0
  66. package/dist/dom/index.js +141 -0
  67. package/dist/dom/index.js.map +1 -0
  68. package/dist/dom/patch.js +104 -0
  69. package/dist/dom/patch.js.map +1 -0
  70. package/dist/element/index.d.ts +35 -0
  71. package/dist/element/index.js +64 -0
  72. package/dist/element/index.js.map +1 -0
  73. package/dist/engine/blocks.js +785 -0
  74. package/dist/engine/blocks.js.map +1 -0
  75. package/dist/engine/entities.js +83 -0
  76. package/dist/engine/entities.js.map +1 -0
  77. package/dist/engine/entity-core.js +9 -0
  78. package/dist/engine/entity-core.js.map +1 -0
  79. package/dist/engine/entity-table.js +9 -0
  80. package/dist/engine/entity-table.js.map +1 -0
  81. package/dist/engine/html.d.ts +7 -0
  82. package/dist/engine/html.js +207 -0
  83. package/dist/engine/html.js.map +1 -0
  84. package/dist/engine/index.d.ts +7 -0
  85. package/dist/engine/index.js +74 -0
  86. package/dist/engine/index.js.map +1 -0
  87. package/dist/engine/inlines.js +887 -0
  88. package/dist/engine/inlines.js.map +1 -0
  89. package/dist/engine/types.d.ts +109 -0
  90. package/dist/engine/url.d.ts +11 -0
  91. package/dist/engine/url.js +16 -0
  92. package/dist/engine/url.js.map +1 -0
  93. package/dist/engine/visit.d.ts +10 -0
  94. package/dist/engine/visit.js +29 -0
  95. package/dist/engine/visit.js.map +1 -0
  96. package/dist/highlight/highlight.d.ts +4 -0
  97. package/dist/highlight/highlight.js +144 -0
  98. package/dist/highlight/highlight.js.map +1 -0
  99. package/dist/highlight/index.d.ts +4 -0
  100. package/dist/highlight/index.js +18 -0
  101. package/dist/highlight/index.js.map +1 -0
  102. package/dist/html/index.d.ts +4 -0
  103. package/dist/html/index.js +544 -0
  104. package/dist/html/index.js.map +1 -0
  105. package/dist/index.d.ts +27 -0
  106. package/dist/index.js +13 -0
  107. package/dist/math/index.d.ts +17 -0
  108. package/dist/math/index.js +20 -0
  109. package/dist/math/index.js.map +1 -0
  110. package/dist/math/typeset.d.ts +12 -0
  111. package/dist/math/typeset.js +74 -0
  112. package/dist/math/typeset.js.map +1 -0
  113. package/dist/mermaid/diagram.d.ts +8 -0
  114. package/dist/mermaid/diagram.js +114 -0
  115. package/dist/mermaid/diagram.js.map +1 -0
  116. package/dist/mermaid/drawing.js +139 -0
  117. package/dist/mermaid/drawing.js.map +1 -0
  118. package/dist/mermaid/icons.js +16 -0
  119. package/dist/mermaid/icons.js.map +1 -0
  120. package/dist/mermaid/index.d.ts +13 -0
  121. package/dist/mermaid/index.js +3 -0
  122. package/dist/mermaid/loader.d.ts +5 -0
  123. package/dist/mermaid/loader.js +18 -0
  124. package/dist/mermaid/loader.js.map +1 -0
  125. package/dist/mermaid/look.d.ts +16 -0
  126. package/dist/mermaid/look.js +167 -0
  127. package/dist/mermaid/look.js.map +1 -0
  128. package/dist/mermaid/normalize-svg.js +44 -0
  129. package/dist/mermaid/normalize-svg.js.map +1 -0
  130. package/dist/mermaid/renderer.d.ts +22 -0
  131. package/dist/mermaid/renderer.js +132 -0
  132. package/dist/mermaid/renderer.js.map +1 -0
  133. package/dist/mermaid/viewer.js +309 -0
  134. package/dist/mermaid/viewer.js.map +1 -0
  135. package/dist/prompt/index.d.ts +19 -0
  136. package/dist/prompt/index.js +54 -0
  137. package/dist/prompt/index.js.map +1 -0
  138. package/dist/react/callout.d.ts +9 -0
  139. package/dist/react/callout.js +12 -0
  140. package/dist/react/callout.js.map +1 -0
  141. package/dist/react/code-block.d.ts +18 -0
  142. package/dist/react/code-block.js +94 -0
  143. package/dist/react/code-block.js.map +1 -0
  144. package/dist/react/context.d.ts +18 -0
  145. package/dist/react/context.js +17 -0
  146. package/dist/react/context.js.map +1 -0
  147. package/dist/react/draw.d.ts +2 -0
  148. package/dist/react/draw.js +17 -0
  149. package/dist/react/draw.js.map +1 -0
  150. package/dist/react/file-tree.d.ts +16 -0
  151. package/dist/react/file-tree.js +69 -0
  152. package/dist/react/file-tree.js.map +1 -0
  153. package/dist/react/growing-code.js +36 -0
  154. package/dist/react/growing-code.js.map +1 -0
  155. package/dist/react/helpers.d.ts +6 -0
  156. package/dist/react/helpers.js +17 -0
  157. package/dist/react/helpers.js.map +1 -0
  158. package/dist/react/icons.js +23 -0
  159. package/dist/react/icons.js.map +1 -0
  160. package/dist/react/labels.js +9 -0
  161. package/dist/react/labels.js.map +1 -0
  162. package/dist/react/markdown.d.ts +78 -0
  163. package/dist/react/markdown.js +206 -0
  164. package/dist/react/markdown.js.map +1 -0
  165. package/dist/react/render.d.ts +8 -0
  166. package/dist/react/render.js +41 -0
  167. package/dist/react/render.js.map +1 -0
  168. package/dist/react/scrolls.js +62 -0
  169. package/dist/react/scrolls.js.map +1 -0
  170. package/dist/react/table-rows.js +66 -0
  171. package/dist/react/table-rows.js.map +1 -0
  172. package/dist/react/table.js +22 -0
  173. package/dist/react/table.js.map +1 -0
  174. package/dist/react/tabs.d.ts +25 -0
  175. package/dist/react/tabs.js +58 -0
  176. package/dist/react/tabs.js.map +1 -0
  177. package/dist/react/use-smooth-text.d.ts +6 -0
  178. package/dist/react/use-smooth-text.js +157 -0
  179. package/dist/react/use-smooth-text.js.map +1 -0
  180. package/dist/react/use-stage.d.ts +9 -0
  181. package/dist/react/use-stage.js +57 -0
  182. package/dist/react/use-stage.js.map +1 -0
  183. package/dist/remark.d.ts +20 -0
  184. package/dist/remark.js +10 -0
  185. package/dist/render/factory.d.ts +15 -0
  186. package/dist/render/labels.d.ts +46 -0
  187. package/dist/render/labels.js +46 -0
  188. package/dist/render/labels.js.map +1 -0
  189. package/dist/render/tree.js +314 -0
  190. package/dist/render/tree.js.map +1 -0
  191. package/dist/render/view.d.ts +58 -0
  192. package/dist/render/view.js +306 -0
  193. package/dist/render/view.js.map +1 -0
  194. package/dist/render/views.d.ts +16 -0
  195. package/dist/render/views.js +261 -0
  196. package/dist/render/views.js.map +1 -0
  197. package/dist/render/vnode.d.ts +21 -0
  198. package/dist/render/vnode.js +194 -0
  199. package/dist/render/vnode.js.map +1 -0
  200. package/dist/static/index.d.ts +28 -0
  201. package/dist/static/index.js +27 -0
  202. package/dist/static/index.js.map +1 -0
  203. package/dist/stream.d.ts +12 -0
  204. package/dist/stream.js +3 -0
  205. package/dist/styles.css +1362 -0
  206. package/dist/tui/code.d.ts +5 -0
  207. package/dist/tui/code.js +240 -0
  208. package/dist/tui/code.js.map +1 -0
  209. package/dist/tui/index.d.ts +54 -0
  210. package/dist/tui/index.js +99 -0
  211. package/dist/tui/index.js.map +1 -0
  212. package/dist/tui/math.js +242 -0
  213. package/dist/tui/math.js.map +1 -0
  214. package/dist/tui/printable.d.ts +12 -0
  215. package/dist/tui/printable.js +31 -0
  216. package/dist/tui/printable.js.map +1 -0
  217. package/dist/tui/render.d.ts +12 -0
  218. package/dist/tui/render.js +524 -0
  219. package/dist/tui/render.js.map +1 -0
  220. package/dist/tui/style.d.ts +35 -0
  221. package/dist/tui/style.js +77 -0
  222. package/dist/tui/style.js.map +1 -0
  223. package/dist/tui/table.js +73 -0
  224. package/dist/tui/table.js.map +1 -0
  225. package/dist/tui/width.d.ts +2 -0
  226. package/dist/tui/width.js +133 -0
  227. package/dist/tui/width.js.map +1 -0
  228. package/dist/tui/wrap.d.ts +8 -0
  229. package/dist/tui/wrap.js +191 -0
  230. package/dist/tui/wrap.js.map +1 -0
  231. package/package.json +128 -4
@@ -0,0 +1,785 @@
1
+ import { unescapeString } from "./entities.js";
2
+ import { CLOSETAG, OPENTAG, normalizeLabel, parseInlines, parseReference } from "./inlines.js";
3
+ // src/engine/blocks.ts
4
+ /**
5
+ * The block pass: a document read line by line into its blocks, by the algorithm in the
6
+ * CommonMark spec. Each line is matched against the containers still open (a quote's `>`, a list
7
+ * item's indent), then tried as the start of a new block, then added to the block it belongs to.
8
+ * The text of paragraphs, headings and cells is kept as written; the inline pass reads it once
9
+ * the whole document is known, since a link can refer to a definition further down.
10
+ */
11
+ const C_TAB = 9;
12
+ const C_SPACE = 32;
13
+ const C_HASH = 35;
14
+ const C_DOLLAR = 36;
15
+ const C_ASTERISK = 42;
16
+ const C_PLUS = 43;
17
+ const C_DASH = 45;
18
+ const C_COLON = 58;
19
+ const C_LESSTHAN = 60;
20
+ const C_EQUALS = 61;
21
+ const C_GREATERTHAN = 62;
22
+ const C_OPEN_BRACKET = 91;
23
+ const C_BACKSLASH = 92;
24
+ const C_UNDERSCORE = 95;
25
+ const C_BACKTICK = 96;
26
+ const C_PIPE = 124;
27
+ const C_TILDE = 126;
28
+ const reHtmlBlockOpen = [
29
+ /./,
30
+ /^<(?:script|pre|textarea|style)(?:\s|>|$)/i,
31
+ /^<!--/,
32
+ /^<[?]/,
33
+ /^<![A-Za-z]/,
34
+ /^<!\[CDATA\[/,
35
+ /^<[/]?(?:address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[123456]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)(?:\s|[/]?[>]|$)/i,
36
+ new RegExp(`^(?:${OPENTAG}|${CLOSETAG})\\s*$`, "i")
37
+ ];
38
+ const reHtmlBlockClose = [
39
+ /./,
40
+ /<\/(?:script|pre|textarea|style)>/i,
41
+ /-->/,
42
+ /\?>/,
43
+ />/,
44
+ /\]\]>/
45
+ ];
46
+ const reThematicBreak = /^(?:\*[ \t]*){3,}$|^(?:_[ \t]*){3,}$|^(?:-[ \t]*){3,}$/;
47
+ const reOrderedListMarker = /^(\d{1,9})([.)])/;
48
+ const reAtxHeadingMarker = /^#{1,6}(?:[ \t]+|$)/;
49
+ const reCodeFence = /^`{3,}(?!.*`)|^~{3,}/;
50
+ const reClosingCodeFence = /^(?:`{3,}|~{3,})(?=[ \t]*$)/;
51
+ /** A display formula's fence, read only when an extension asks for it: `$$` alone on its line. */
52
+ const reMathFence = /^\${2,}(?!.*\$)/;
53
+ const reClosingMathFence = /^\${2,}(?=[ \t]*$)/;
54
+ const reSetextHeadingLine = /^(?:=+|-+)[ \t]*$/;
55
+ const reLineEnding = /\r\n|\n|\r/g;
56
+ const reTableDelimiterCell = /^[ \t]*(:?)-+(:?)[ \t]*$/;
57
+ const reFootnoteDefinition = /^\[\^([^\]\s]+)\]:[ \t]*/;
58
+ const reTaskMarker = /^\[([ xX])\](?=[ \t\n])/;
59
+ const isSpaceOrTab = (code) => code === C_SPACE || code === C_TAB;
60
+ /**
61
+ * How deep blocks may hold blocks. A quote in a quote in a list is three; a hundred is past
62
+ * anything written to be read, and it bounds the depth of the tree every pass after this one
63
+ * walks: without it a line of twenty thousand `>` overflowed the stack. A line that would go
64
+ * deeper is read as text of the block it is in.
65
+ */
66
+ const MAX_NESTING = 100;
67
+ /** Whether a block holds other blocks; a list holds only items. */
68
+ const isContainer = (type) => type === "root" || type === "blockquote" || type === "item" || type === "list" || type === "footnoteDefinition";
69
+ /** Whether a block takes the lines after its first as they are. */
70
+ const acceptsLines = (type) => type === "paragraph" || type === "code" || type === "html";
71
+ /**
72
+ * A table row cut into its cells: on each `|` that is not escaped, without the outer pipes. Each
73
+ * cell is one cut of the row, joined from pieces only where an escaped pipe (`\\|`) is taken out.
74
+ */
75
+ const splitRow = (row) => {
76
+ const cells = [];
77
+ let line = row.trim();
78
+ if (line.charCodeAt(0) === C_PIPE) line = line.slice(1);
79
+ /** The cell's text before `from`: what came before an escaped pipe, and that pipe. */
80
+ let cell = "";
81
+ let from = 0;
82
+ for (let pipe = line.indexOf("|"); pipe !== -1; pipe = line.indexOf("|", pipe + 1)) {
83
+ if (pipe > 0 && line.charCodeAt(pipe - 1) === C_BACKSLASH) cell += `${line.slice(from, pipe - 1)}|`;
84
+ else {
85
+ cells.push((cell + line.slice(from, pipe)).trim());
86
+ cell = "";
87
+ }
88
+ from = pipe + 1;
89
+ }
90
+ const last = (cell + line.slice(from)).trim();
91
+ if (last !== "" || line.charCodeAt(line.length - 1) !== C_PIPE || line === "") cells.push(last);
92
+ return cells;
93
+ };
94
+ /** The alignments a table's delimiter row (`| :-- | --: |`) gives, or null when it is not one. */
95
+ const parseDelimiterRow = (row) => {
96
+ if (row.indexOf("|") === -1) return null;
97
+ const cells = splitRow(row);
98
+ const align = [];
99
+ for (const cell of cells) {
100
+ const found = reTableDelimiterCell.exec(cell);
101
+ if (found === null) return null;
102
+ align.push(found[1] ? found[2] ? "center" : "left" : found[2] ? "right" : null);
103
+ }
104
+ return align.length === 0 ? null : align;
105
+ };
106
+ /** Parses a whole document into its tree. */
107
+ const parseBlocks = (input, context) => {
108
+ const gfm = context.gfm;
109
+ const starts = [];
110
+ const ends = [];
111
+ const onlyLf = input.indexOf("\r") === -1;
112
+ if (onlyLf) for (let at = 0;;) {
113
+ const ending = input.indexOf("\n", at);
114
+ starts.push(at);
115
+ if (ending === -1) {
116
+ ends.push(input.length);
117
+ break;
118
+ }
119
+ ends.push(ending);
120
+ at = ending + 1;
121
+ }
122
+ else for (let at = 0;;) {
123
+ reLineEnding.lastIndex = at;
124
+ const ending = reLineEnding.exec(input);
125
+ starts.push(at);
126
+ if (ending === null) {
127
+ ends.push(input.length);
128
+ break;
129
+ }
130
+ ends.push(ending.index);
131
+ at = ending.index + ending[0].length;
132
+ }
133
+ let count = starts.length;
134
+ if (count > 0 && starts[count - 1] === ends[count - 1]) count--;
135
+ /** No NUL in the document: a line is then the document's own text, with nothing to replace. */
136
+ const noNul = input.indexOf("\0") === -1;
137
+ const block = (type, startLine) => ({
138
+ type,
139
+ parent: null,
140
+ children: [],
141
+ open: true,
142
+ lastLineBlank: false,
143
+ text: "",
144
+ startLine,
145
+ endLine: startLine,
146
+ startOffset: 0,
147
+ depth: 0,
148
+ ordered: false,
149
+ bullet: 0,
150
+ start: 0,
151
+ delimiter: 0,
152
+ padding: 0,
153
+ markerOffset: 0,
154
+ tight: true,
155
+ fenced: false,
156
+ fenceChar: 0,
157
+ fenceLength: 0,
158
+ fenceOffset: 0,
159
+ htmlType: 0,
160
+ level: 0,
161
+ align: null,
162
+ rows: null,
163
+ label: ""
164
+ });
165
+ const doc = block("root", 1);
166
+ let tip = doc;
167
+ let oldtip = doc;
168
+ let lastMatchedContainer = doc;
169
+ let allClosed = true;
170
+ let line = "";
171
+ let lineNumber = 0;
172
+ let offset = 0;
173
+ let column = 0;
174
+ let nextNonspace = 0;
175
+ let nextNonspaceColumn = 0;
176
+ let indent = 0;
177
+ let indented = false;
178
+ let blank = false;
179
+ let partiallyConsumedTab = false;
180
+ const findNextNonspace = () => {
181
+ let index = offset;
182
+ let cols = column;
183
+ let code = line.charCodeAt(index);
184
+ while (code === C_SPACE || code === C_TAB) {
185
+ cols += code === C_SPACE ? 1 : 4 - cols % 4;
186
+ code = line.charCodeAt(++index);
187
+ }
188
+ blank = index >= line.length;
189
+ nextNonspace = index;
190
+ nextNonspaceColumn = cols;
191
+ indent = cols - column;
192
+ indented = indent >= 4;
193
+ };
194
+ const advanceNextNonspace = () => {
195
+ offset = nextNonspace;
196
+ column = nextNonspaceColumn;
197
+ partiallyConsumedTab = false;
198
+ };
199
+ /** Moves past `amount` characters, or that many columns: a tab is up to four columns wide. */
200
+ const advanceOffset = (amount, columns) => {
201
+ let left = amount;
202
+ while (left > 0 && offset < line.length) if (line.charCodeAt(offset) === C_TAB) {
203
+ const toTab = 4 - column % 4;
204
+ if (columns) {
205
+ partiallyConsumedTab = toTab > left;
206
+ const step = toTab > left ? left : toTab;
207
+ column += step;
208
+ if (!partiallyConsumedTab) offset++;
209
+ left -= step;
210
+ } else {
211
+ partiallyConsumedTab = false;
212
+ column += toTab;
213
+ offset++;
214
+ left--;
215
+ }
216
+ } else {
217
+ partiallyConsumedTab = false;
218
+ offset++;
219
+ column++;
220
+ left--;
221
+ }
222
+ };
223
+ const addLine = () => {
224
+ if (partiallyConsumedTab) {
225
+ offset++;
226
+ tip.text += " ".repeat(4 - column % 4);
227
+ }
228
+ tip.text += `${line.slice(offset)}\n`;
229
+ };
230
+ const removeChild = (child) => {
231
+ const siblings = child.parent?.children;
232
+ if (siblings === void 0) return;
233
+ const index = siblings.lastIndexOf(child);
234
+ if (index !== -1) siblings.splice(index, 1);
235
+ child.parent = null;
236
+ };
237
+ /** Whether a block ends with a blank line before its next sibling. */
238
+ const gapAfter = (child, next) => next !== void 0 && child.endLine !== next.startLine - 1;
239
+ const takeReferences = (paragraph) => {
240
+ let content = paragraph.text;
241
+ while (content.charCodeAt(0) === C_OPEN_BRACKET) {
242
+ const taken = parseReference(content, context.refs);
243
+ if (taken === 0) break;
244
+ content = content.slice(taken);
245
+ }
246
+ paragraph.text = content;
247
+ };
248
+ const finalize = (closing, endLine) => {
249
+ const above = closing.parent;
250
+ closing.open = false;
251
+ closing.endLine = endLine;
252
+ switch (closing.type) {
253
+ case "paragraph":
254
+ takeReferences(closing);
255
+ if (/^[ \t\n]*$/.test(closing.text)) removeChild(closing);
256
+ break;
257
+ case "code":
258
+ if (closing.fenced) {
259
+ const newline = closing.text.indexOf("\n");
260
+ closing.label = unescapeString(closing.text.slice(0, newline).trim());
261
+ closing.text = closing.text.slice(newline + 1);
262
+ } else closing.text = closing.text.replace(/(?:\n *)+$/, "\n");
263
+ break;
264
+ case "list": {
265
+ const items = closing.children;
266
+ closing.tight = true;
267
+ for (let index = 0; index < items.length && closing.tight; index++) {
268
+ const item = items[index];
269
+ if (gapAfter(item, items[index + 1])) closing.tight = false;
270
+ const inner = item.children;
271
+ for (let child = 0; child < inner.length && closing.tight; child++) if (gapAfter(inner[child], inner[child + 1])) closing.tight = false;
272
+ }
273
+ const last = items[items.length - 1];
274
+ if (last !== void 0) closing.endLine = last.endLine;
275
+ break;
276
+ }
277
+ case "item": {
278
+ const last = closing.children[closing.children.length - 1];
279
+ closing.endLine = last === void 0 ? closing.startLine : last.endLine;
280
+ break;
281
+ }
282
+ }
283
+ if (above !== null) tip = above;
284
+ };
285
+ const addChild = (type) => {
286
+ while (!isContainer(tip.type) || tip.type === "list" && type !== "item") finalize(tip, lineNumber - 1);
287
+ const child = block(type, lineNumber);
288
+ child.startOffset = (starts[lineNumber - 1] ?? 0) + nextNonspace;
289
+ child.parent = tip;
290
+ child.depth = tip.depth + 1;
291
+ tip.children.push(child);
292
+ tip = child;
293
+ return child;
294
+ };
295
+ const closeUnmatchedBlocks = () => {
296
+ if (allClosed) return;
297
+ while (oldtip !== lastMatchedContainer) {
298
+ const parent = oldtip.parent;
299
+ finalize(oldtip, lineNumber - 1);
300
+ oldtip = parent;
301
+ }
302
+ allClosed = true;
303
+ };
304
+ /** Reads a list marker at the next non-space character into a new item's data, or null. */
305
+ const parseListMarker = (container) => {
306
+ if (indent >= 4) return null;
307
+ const rest = line.slice(nextNonspace);
308
+ const first = rest.charCodeAt(0);
309
+ const item = block("item", lineNumber);
310
+ let markerLength = 1;
311
+ if (first === C_ASTERISK || first === C_PLUS || first === C_DASH) item.bullet = first;
312
+ else {
313
+ const found = reOrderedListMarker.exec(rest);
314
+ if (found === null) return null;
315
+ if (container.type === "paragraph" && found[1] !== "1") return null;
316
+ item.ordered = true;
317
+ item.start = parseInt(found[1], 10);
318
+ item.delimiter = found[2].charCodeAt(0);
319
+ markerLength = found[0].length;
320
+ }
321
+ const after = line.charCodeAt(nextNonspace + markerLength);
322
+ if (!Number.isNaN(after) && !isSpaceOrTab(after)) return null;
323
+ if (container.type === "paragraph" && /^[ \t]*$/.test(line.slice(nextNonspace + markerLength))) return null;
324
+ advanceNextNonspace();
325
+ advanceOffset(markerLength, true);
326
+ const spacesStartColumn = column;
327
+ const spacesStartOffset = offset;
328
+ do
329
+ advanceOffset(1, true);
330
+ while (column - spacesStartColumn < 5 && isSpaceOrTab(line.charCodeAt(offset)));
331
+ const blankItem = offset >= line.length;
332
+ const spaces = column - spacesStartColumn;
333
+ if (spaces >= 5 || spaces < 1 || blankItem) {
334
+ item.padding = markerLength + 1;
335
+ column = spacesStartColumn;
336
+ offset = spacesStartOffset;
337
+ if (isSpaceOrTab(line.charCodeAt(offset))) advanceOffset(1, true);
338
+ } else item.padding = markerLength + spaces;
339
+ item.markerOffset = indent;
340
+ return item;
341
+ };
342
+ /**
343
+ * Whether an open block goes on with this line: 0 when it does, 1 when it does not, 2 when the
344
+ * line closed it and is used up.
345
+ */
346
+ const continues = (container) => {
347
+ switch (container.type) {
348
+ case "blockquote":
349
+ if (indented || line.charCodeAt(nextNonspace) !== C_GREATERTHAN) return 1;
350
+ advanceNextNonspace();
351
+ advanceOffset(1, false);
352
+ if (isSpaceOrTab(line.charCodeAt(offset))) advanceOffset(1, true);
353
+ return 0;
354
+ case "item":
355
+ if (blank) {
356
+ if (container.children.length === 0) return 1;
357
+ advanceNextNonspace();
358
+ } else if (indent >= container.markerOffset + container.padding) advanceOffset(container.markerOffset + container.padding, true);
359
+ else return 1;
360
+ return 0;
361
+ case "footnoteDefinition":
362
+ if (blank) advanceNextNonspace();
363
+ else if (indent >= 4) advanceOffset(4, true);
364
+ else return 1;
365
+ return 0;
366
+ case "code":
367
+ if (container.fenced) {
368
+ if (indent <= 3 && line.charCodeAt(nextNonspace) === container.fenceChar) {
369
+ const found = (container.fenceChar === C_DOLLAR ? reClosingMathFence : reClosingCodeFence).exec(line.slice(nextNonspace));
370
+ if (found !== null && found[0].length >= container.fenceLength) {
371
+ finalize(container, lineNumber);
372
+ return 2;
373
+ }
374
+ }
375
+ let skip = container.fenceOffset;
376
+ while (skip > 0 && isSpaceOrTab(line.charCodeAt(offset))) {
377
+ advanceOffset(1, true);
378
+ skip--;
379
+ }
380
+ } else if (indent >= 4) advanceOffset(4, true);
381
+ else if (blank) advanceNextNonspace();
382
+ else return 1;
383
+ return 0;
384
+ case "html": return blank && (container.htmlType === 6 || container.htmlType === 7) ? 1 : 0;
385
+ case "paragraph":
386
+ case "table": return blank ? 1 : 0;
387
+ case "heading":
388
+ case "thematicBreak": return 1;
389
+ default: return 0;
390
+ }
391
+ };
392
+ /**
393
+ * Tries the line as the start of a new block: 0 when it starts none, 1 when it starts a
394
+ * container (the rest of the line is tried again), 2 when it starts a leaf.
395
+ */
396
+ const startBlock = (container) => {
397
+ const first = line.charCodeAt(nextNonspace);
398
+ if (indented) {
399
+ if (tip.type !== "paragraph" && !blank) {
400
+ advanceOffset(4, true);
401
+ closeUnmatchedBlocks();
402
+ addChild("code");
403
+ return 2;
404
+ }
405
+ return 0;
406
+ }
407
+ switch (first) {
408
+ case C_GREATERTHAN:
409
+ if (container.depth >= MAX_NESTING) return 0;
410
+ advanceNextNonspace();
411
+ advanceOffset(1, false);
412
+ if (isSpaceOrTab(line.charCodeAt(offset))) advanceOffset(1, true);
413
+ closeUnmatchedBlocks();
414
+ addChild("blockquote");
415
+ return 1;
416
+ case C_HASH: {
417
+ const found = reAtxHeadingMarker.exec(line.slice(nextNonspace));
418
+ if (found === null) return 0;
419
+ advanceNextNonspace();
420
+ advanceOffset(found[0].length, false);
421
+ closeUnmatchedBlocks();
422
+ const heading = addChild("heading");
423
+ heading.level = found[0].trim().length;
424
+ heading.text = line.slice(offset).replace(/^[ \t]*#+[ \t]*$/, "").replace(/[ \t]+#+[ \t]*$/, "");
425
+ advanceOffset(line.length - offset, false);
426
+ return 2;
427
+ }
428
+ case C_DOLLAR:
429
+ case C_BACKTICK:
430
+ case C_TILDE: {
431
+ if (first === C_DOLLAR && !context.math) return 0;
432
+ const found = (first === C_DOLLAR ? reMathFence : reCodeFence).exec(line.slice(nextNonspace));
433
+ if (found === null) return 0;
434
+ closeUnmatchedBlocks();
435
+ const code = addChild("code");
436
+ code.fenced = true;
437
+ code.fenceLength = found[0].length;
438
+ code.fenceChar = first;
439
+ code.fenceOffset = indent;
440
+ advanceNextNonspace();
441
+ advanceOffset(code.fenceLength, false);
442
+ return 2;
443
+ }
444
+ case C_LESSTHAN: {
445
+ const rest = line.slice(nextNonspace);
446
+ for (let type = 1; type <= 7; type++) if (reHtmlBlockOpen[type].test(rest) && (type < 7 || container.type !== "paragraph" && !(!allClosed && !blank && tip.type === "paragraph"))) {
447
+ closeUnmatchedBlocks();
448
+ addChild("html").htmlType = type;
449
+ return 2;
450
+ }
451
+ return 0;
452
+ }
453
+ }
454
+ if (container.type === "paragraph") {
455
+ if (gfm && (first === C_PIPE || first === C_DASH || first === C_COLON)) {
456
+ const align = parseDelimiterRow(line.slice(nextNonspace));
457
+ if (align !== null) {
458
+ const content = container.text;
459
+ const cut = content.lastIndexOf("\n", content.length - 2);
460
+ const header = content.slice(cut + 1, -1);
461
+ if (splitRow(header).length === align.length) {
462
+ closeUnmatchedBlocks();
463
+ if (cut === -1) {
464
+ tip = container.parent;
465
+ removeChild(container);
466
+ } else {
467
+ container.text = content.slice(0, cut + 1);
468
+ finalize(container, lineNumber - 2);
469
+ }
470
+ const table = addChild("table");
471
+ table.startLine = lineNumber - 1;
472
+ table.startOffset = starts[lineNumber - 2] ?? 0;
473
+ table.align = align;
474
+ table.rows = [header];
475
+ advanceOffset(line.length - offset, false);
476
+ return 2;
477
+ }
478
+ }
479
+ }
480
+ if (first === C_EQUALS || first === C_DASH) {
481
+ if (reSetextHeadingLine.test(line.slice(nextNonspace))) {
482
+ closeUnmatchedBlocks();
483
+ takeReferences(container);
484
+ if (container.text.length > 0) {
485
+ container.type = "heading";
486
+ container.level = first === C_EQUALS ? 1 : 2;
487
+ advanceOffset(line.length - offset, false);
488
+ return 2;
489
+ }
490
+ }
491
+ }
492
+ }
493
+ if ((first === C_ASTERISK || first === C_DASH || first === C_UNDERSCORE) && reThematicBreak.test(line.slice(nextNonspace))) {
494
+ closeUnmatchedBlocks();
495
+ addChild("thematicBreak");
496
+ advanceOffset(line.length - offset, false);
497
+ return 2;
498
+ }
499
+ if (container.depth >= 99) return 0;
500
+ if (gfm && first === C_OPEN_BRACKET && line.charCodeAt(nextNonspace + 1) === 94) {
501
+ const found = reFootnoteDefinition.exec(line.slice(nextNonspace));
502
+ if (found !== null) {
503
+ closeUnmatchedBlocks();
504
+ advanceNextNonspace();
505
+ advanceOffset(found[0].length, false);
506
+ const definition = addChild("footnoteDefinition");
507
+ definition.label = found[1];
508
+ const key = normalizeLabel(`[${definition.label}]`);
509
+ if (!context.footnotes.has(key)) context.footnotes.set(key, definition.label);
510
+ return 1;
511
+ }
512
+ }
513
+ if (first === C_ASTERISK || first === C_PLUS || first === C_DASH || first >= 48 && first <= 57) {
514
+ const item = parseListMarker(container);
515
+ if (item === null) return 0;
516
+ closeUnmatchedBlocks();
517
+ if (tip.type !== "list" || tip.ordered !== item.ordered || tip.bullet !== item.bullet || tip.delimiter !== item.delimiter) {
518
+ const list = addChild("list");
519
+ list.ordered = item.ordered;
520
+ list.bullet = item.bullet;
521
+ list.delimiter = item.delimiter;
522
+ list.start = item.start;
523
+ }
524
+ const added = addChild("item");
525
+ added.ordered = item.ordered;
526
+ added.padding = item.padding;
527
+ added.markerOffset = item.markerOffset;
528
+ return 1;
529
+ }
530
+ return 0;
531
+ };
532
+ const incorporateLine = (text) => {
533
+ let container = doc;
534
+ oldtip = tip;
535
+ offset = 0;
536
+ column = 0;
537
+ blank = false;
538
+ partiallyConsumedTab = false;
539
+ lineNumber++;
540
+ line = noNul || text.indexOf("\0") === -1 ? text : text.replace(/\0/g, "�");
541
+ for (;;) {
542
+ const last = container.children[container.children.length - 1];
543
+ if (last === void 0 || !last.open) break;
544
+ container = last;
545
+ findNextNonspace();
546
+ const result = continues(container);
547
+ if (result === 2) return;
548
+ if (result === 1) {
549
+ container = container.parent;
550
+ break;
551
+ }
552
+ }
553
+ allClosed = container === oldtip;
554
+ lastMatchedContainer = container;
555
+ let matchedLeaf = container.type !== "paragraph" && acceptsLines(container.type);
556
+ while (!matchedLeaf) {
557
+ findNextNonspace();
558
+ const result = blank ? 0 : startBlock(container);
559
+ if (result === 0) {
560
+ advanceNextNonspace();
561
+ break;
562
+ }
563
+ container = tip;
564
+ if (result === 2) matchedLeaf = true;
565
+ }
566
+ if (!allClosed && !blank && tip.type === "paragraph") {
567
+ addLine();
568
+ return;
569
+ }
570
+ closeUnmatchedBlocks();
571
+ const type = container.type;
572
+ if (blank) {
573
+ const last = container.children[container.children.length - 1];
574
+ if (last !== void 0) last.lastLineBlank = true;
575
+ }
576
+ const lastLineBlank = blank && !(type === "blockquote" || type === "code" && container.fenced || type === "item" && container.children.length === 0 && container.startLine === lineNumber);
577
+ for (let above = container; above !== null; above = above.parent) above.lastLineBlank = lastLineBlank;
578
+ if (acceptsLines(type)) {
579
+ addLine();
580
+ if (type === "html" && container.htmlType >= 1 && container.htmlType <= 5 && reHtmlBlockClose[container.htmlType].test(line.slice(offset))) finalize(container, lineNumber);
581
+ } else if (offset < line.length && !blank) {
582
+ if (type === "table") container.rows.push(line.slice(offset));
583
+ else {
584
+ addChild("paragraph");
585
+ advanceNextNonspace();
586
+ addLine();
587
+ }
588
+ }
589
+ };
590
+ /**
591
+ * The lines of a fenced code block at the top of the document, taken without the work a line
592
+ * gets elsewhere: from the line after `index`, every line up to one that may close the fence
593
+ * goes into the code as it is written, in one cut of the document. Returns the last line taken.
594
+ *
595
+ * A line may close the fence when, after at most three spaces, it starts with the fence's
596
+ * character; that line, and whatever follows a fence that did not close, is read the long way.
597
+ */
598
+ const takeFencedLines = (code, index) => {
599
+ const fenceChar = code.fenceChar;
600
+ let next = index + 1;
601
+ for (; next < count; next++) {
602
+ let at = starts[next];
603
+ if (input.charCodeAt(at) === C_SPACE) {
604
+ at++;
605
+ if (input.charCodeAt(at) === C_SPACE) {
606
+ at++;
607
+ if (input.charCodeAt(at) === C_SPACE) at++;
608
+ }
609
+ }
610
+ if (input.charCodeAt(at) === fenceChar) break;
611
+ }
612
+ const last = next - 1;
613
+ if (last === index) return index;
614
+ const taken = input.slice(starts[index + 1], ends[last]);
615
+ code.text += `${onlyLf ? taken : taken.replace(reLineEnding, "\n")}\n`;
616
+ lineNumber += last - index;
617
+ return last;
618
+ };
619
+ for (let index = 0; index < count; index++) {
620
+ incorporateLine(input.slice(starts[index], ends[index]));
621
+ if (tip.fenced && tip.parent === doc && tip.fenceOffset === 0 && noNul) index = takeFencedLines(tip, index);
622
+ }
623
+ while (tip !== doc) finalize(tip, count);
624
+ finalize(doc, count);
625
+ const definitions = /* @__PURE__ */ new Map();
626
+ const kids = (from) => {
627
+ const out = [];
628
+ for (const child of from.children) if (child.type === "footnoteDefinition") {
629
+ const key = normalizeLabel(`[${child.label}]`);
630
+ if (!definitions.has(key)) definitions.set(key, child);
631
+ } else out.push(build(child));
632
+ return out;
633
+ };
634
+ const cells = (row, align, header) => {
635
+ const parts = splitRow(row);
636
+ const children = [];
637
+ for (let index = 0; index < align.length; index++) children.push({
638
+ type: "tableCell",
639
+ header,
640
+ cellAlign: align[index] ?? null,
641
+ children: parseInlines(parts[index] ?? "", context)
642
+ });
643
+ return {
644
+ type: "tableRow",
645
+ children
646
+ };
647
+ };
648
+ /** Where a block sits in the document: from its first character to the end of its last line. */
649
+ const place = (from) => {
650
+ const last = Math.min(Math.max(from.endLine, from.startLine), starts.length);
651
+ const lastStart = starts[last - 1] ?? 0;
652
+ const length = (ends[last - 1] ?? 0) - lastStart;
653
+ return {
654
+ start: {
655
+ line: from.startLine,
656
+ column: from.startOffset - (starts[from.startLine - 1] ?? 0) + 1,
657
+ offset: from.startOffset
658
+ },
659
+ end: {
660
+ line: last,
661
+ column: length + 1,
662
+ offset: lastStart + length
663
+ }
664
+ };
665
+ };
666
+ const build = (from) => {
667
+ switch (from.type) {
668
+ case "paragraph": return {
669
+ type: "paragraph",
670
+ position: place(from),
671
+ children: parseInlines(from.text, context)
672
+ };
673
+ case "heading": return {
674
+ type: "heading",
675
+ depth: from.level,
676
+ position: place(from),
677
+ children: parseInlines(from.text, context)
678
+ };
679
+ case "thematicBreak": return {
680
+ type: "thematicBreak",
681
+ position: place(from)
682
+ };
683
+ case "code": {
684
+ if (from.fenceChar === C_DOLLAR) {
685
+ const node = {
686
+ type: "math",
687
+ position: place(from),
688
+ value: from.text.replace(/\n$/, "")
689
+ };
690
+ if (from.label !== "") node.meta = from.label;
691
+ return node;
692
+ }
693
+ const node = {
694
+ type: "code",
695
+ position: place(from),
696
+ value: from.text
697
+ };
698
+ if (from.label !== "") {
699
+ const space = from.label.search(/[ \t]/);
700
+ node.lang = space === -1 ? from.label : from.label.slice(0, space);
701
+ if (space !== -1) node.meta = from.label.slice(space + 1).trim();
702
+ }
703
+ return node;
704
+ }
705
+ case "html": return {
706
+ type: "html",
707
+ position: place(from),
708
+ value: from.text.replace(/(?:\n *)+$/, "")
709
+ };
710
+ case "table": {
711
+ const align = from.align;
712
+ const rows = from.rows;
713
+ return {
714
+ type: "table",
715
+ position: place(from),
716
+ align,
717
+ children: rows.map((row, index) => cells(row, align, index === 0))
718
+ };
719
+ }
720
+ case "list": {
721
+ const node = {
722
+ type: "list",
723
+ position: place(from),
724
+ ordered: from.ordered,
725
+ spread: !from.tight,
726
+ children: kids(from)
727
+ };
728
+ for (const item of node.children) item.spread = !from.tight;
729
+ if (from.ordered) node.start = from.start;
730
+ return node;
731
+ }
732
+ case "item": {
733
+ const node = {
734
+ type: "listItem",
735
+ position: place(from),
736
+ children: []
737
+ };
738
+ const first = from.children[0];
739
+ if (gfm && first !== void 0 && first.type === "paragraph") {
740
+ const task = reTaskMarker.exec(first.text);
741
+ if (task !== null) {
742
+ node.checked = task[1] !== " ";
743
+ first.text = first.text.slice(task[0].length + 1);
744
+ }
745
+ }
746
+ node.children = kids(from);
747
+ return node;
748
+ }
749
+ default: return {
750
+ type: from.type,
751
+ position: place(from),
752
+ children: kids(from)
753
+ };
754
+ }
755
+ };
756
+ const root = {
757
+ type: "root",
758
+ children: kids(doc)
759
+ };
760
+ const footnotes = [];
761
+ for (let index = 0;; index++) {
762
+ let key;
763
+ let at = 0;
764
+ for (const used of context.footnoteUses.keys()) if (at++ === index) key = used;
765
+ if (key === void 0) break;
766
+ const from = definitions.get(key);
767
+ if (from === void 0) continue;
768
+ footnotes.push({
769
+ type: "footnoteDefinition",
770
+ identifier: normalizeLabel(`[${from.label}]`).toLowerCase(),
771
+ label: from.label,
772
+ index: index + 1,
773
+ position: place(from),
774
+ children: kids(from)
775
+ });
776
+ }
777
+ for (const node of footnotes) node.count = context.footnoteUses.get(normalizeLabel(`[${node.label}]`)) ?? 1;
778
+ return {
779
+ root,
780
+ footnotes
781
+ };
782
+ };
783
+ export { parseBlocks };
784
+
785
+ //# sourceMappingURL=blocks.js.map