typewright 0.2.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 (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +168 -0
  3. package/SPEC.md +327 -0
  4. package/dist/chunk-CZQO7TTL.js +1533 -0
  5. package/dist/chunk-CZQO7TTL.js.map +1 -0
  6. package/dist/chunk-KNEKNZXK.js +286 -0
  7. package/dist/chunk-KNEKNZXK.js.map +1 -0
  8. package/dist/chunk-M6IVEMXO.js +1398 -0
  9. package/dist/chunk-M6IVEMXO.js.map +1 -0
  10. package/dist/chunk-NJ7PJKHN.js +652 -0
  11. package/dist/chunk-NJ7PJKHN.js.map +1 -0
  12. package/dist/commands-Z3ndUSza.d.cts +221 -0
  13. package/dist/commands-Z3ndUSza.d.ts +221 -0
  14. package/dist/core/index.cjs +2952 -0
  15. package/dist/core/index.cjs.map +1 -0
  16. package/dist/core/index.d.cts +410 -0
  17. package/dist/core/index.d.ts +410 -0
  18. package/dist/core/index.js +4 -0
  19. package/dist/core/index.js.map +1 -0
  20. package/dist/mdx/index.cjs +662 -0
  21. package/dist/mdx/index.cjs.map +1 -0
  22. package/dist/mdx/index.d.cts +252 -0
  23. package/dist/mdx/index.d.ts +252 -0
  24. package/dist/mdx/index.js +3 -0
  25. package/dist/mdx/index.js.map +1 -0
  26. package/dist/react/index.cjs +7439 -0
  27. package/dist/react/index.cjs.map +1 -0
  28. package/dist/react/index.d.cts +140 -0
  29. package/dist/react/index.d.ts +140 -0
  30. package/dist/react/index.js +3644 -0
  31. package/dist/react/index.js.map +1 -0
  32. package/dist/streaming/index.cjs +1494 -0
  33. package/dist/streaming/index.cjs.map +1 -0
  34. package/dist/streaming/index.d.cts +64 -0
  35. package/dist/streaming/index.d.ts +64 -0
  36. package/dist/streaming/index.js +4 -0
  37. package/dist/streaming/index.js.map +1 -0
  38. package/dist/types-CX1GOx0Y.d.cts +319 -0
  39. package/dist/types-CX1GOx0Y.d.ts +319 -0
  40. package/package.json +128 -0
@@ -0,0 +1,1398 @@
1
+ // src/core/ast.ts
2
+ var INLINE_TYPES = /* @__PURE__ */ new Set([
3
+ "text",
4
+ "emphasis",
5
+ "strong",
6
+ "strikethrough",
7
+ "inlineCode",
8
+ "link",
9
+ "image",
10
+ "autolink",
11
+ "break",
12
+ "math",
13
+ "footnoteRef"
14
+ ]);
15
+ function isInline(node) {
16
+ return INLINE_TYPES.has(node.type);
17
+ }
18
+ function walk(node, visit) {
19
+ const go = (n) => {
20
+ if (visit(n) === false) return;
21
+ const kids = childrenOf(n);
22
+ for (const k of kids) go(k);
23
+ };
24
+ go(node);
25
+ }
26
+ function childrenOf(node) {
27
+ switch (node.type) {
28
+ case "document":
29
+ case "blockquote":
30
+ return node.children;
31
+ case "heading":
32
+ case "paragraph":
33
+ case "emphasis":
34
+ case "strong":
35
+ case "strikethrough":
36
+ case "tableCell":
37
+ return node.children;
38
+ case "link":
39
+ return node.children;
40
+ case "list":
41
+ return node.items;
42
+ case "listItem":
43
+ return node.children;
44
+ case "table":
45
+ return [...node.header, ...node.rows.flat()];
46
+ case "footnoteDef":
47
+ return node.children;
48
+ case "defList":
49
+ return node.items;
50
+ case "defItem":
51
+ return [...node.term, ...node.definitions.flat()];
52
+ default:
53
+ return [];
54
+ }
55
+ }
56
+
57
+ // src/core/parser.ts
58
+ var MAX_URL = 4096;
59
+ var MAX_TITLE = 1024;
60
+ var MAX_ALT = 4096;
61
+ var MAX_LANG = 256;
62
+ var MAX_VALUE = 1e6;
63
+ var MAX_FOOTNOTE_ID = 256;
64
+ var cap = (s, n) => s.length > n ? s.slice(0, n) : s;
65
+ var opts = { math: false, footnotes: false, defLists: false };
66
+ function splitLines(src) {
67
+ const lines = [];
68
+ let from = 0;
69
+ for (let i = 0; i <= src.length; i++) {
70
+ if (i === src.length || src[i] === "\n") {
71
+ let end = i;
72
+ if (end > from && src[end - 1] === "\r") end--;
73
+ lines.push({ from, to: end, text: src.slice(from, end) });
74
+ from = i + 1;
75
+ }
76
+ }
77
+ return lines;
78
+ }
79
+ var leadingSpaces = (t) => {
80
+ let n = 0;
81
+ while (n < t.length && t[n] === " ") n++;
82
+ return n;
83
+ };
84
+ var isBlank = (line) => line.text.trim() === "";
85
+ var FENCE_RE = /^( {0,3})(`{3,}|~{3,})(.*)$/;
86
+ var ATX_RE = /^( {0,3})(#{1,6})(?=\s|$)/;
87
+ var ITEM_RE = /^( {0,3})([-+*]|\d{1,9}[.)])( +|$)/;
88
+ var HTML_TAG_RE = /^<\/?([A-Za-z][A-Za-z0-9-]*)(?:[\s/>]|$)/;
89
+ var ESM_RE = /^(?:import|export)\b/;
90
+ var isFence = (t) => {
91
+ const m = FENCE_RE.exec(t);
92
+ if (!m) return false;
93
+ return m[2][0] !== "`" || !m[3].includes("`");
94
+ };
95
+ var isAtx = (t) => ATX_RE.test(t);
96
+ var isThematic = (t) => {
97
+ const trimmed = t.trim();
98
+ if (trimmed.length < 3) return false;
99
+ const compact = trimmed.replace(/ /g, "");
100
+ return /^(?:-{3,}|_{3,}|\*{3,})$/.test(compact);
101
+ };
102
+ var isQuote = (t) => /^ {0,3}>/.test(t);
103
+ function detectItem(line) {
104
+ const m = ITEM_RE.exec(line.text);
105
+ if (!m) return null;
106
+ const marker = m[2];
107
+ return {
108
+ indent: m[1].length,
109
+ marker,
110
+ markerLen: marker.length,
111
+ spacesAfter: m[3] === "" ? 0 : m[3].length,
112
+ ordered: /\d/.test(marker[0])
113
+ };
114
+ }
115
+ function htmlVariant(t) {
116
+ const s = t.replace(/^ {0,3}/, "");
117
+ if (ESM_RE.test(s)) return "mdxFlow";
118
+ const m = HTML_TAG_RE.exec(s);
119
+ if (!m) return null;
120
+ return /[A-Z]/.test(m[1][0]) ? "mdxFlow" : "html";
121
+ }
122
+ function isDelimRow(t) {
123
+ let s = t.trim();
124
+ if (!s.includes("-")) return false;
125
+ s = s.replace(/^\|/, "").replace(/\|$/, "");
126
+ const cells = s.split("|");
127
+ return cells.length >= 1 && cells.every((c) => /^ *:?-+:? *$/.test(c));
128
+ }
129
+ function isTableStartAt(lines, j) {
130
+ const line = lines[j];
131
+ const next = lines[j + 1];
132
+ if (!line || !next) return false;
133
+ if (isBlank(line)) return false;
134
+ return line.text.includes("|") && isDelimRow(next.text);
135
+ }
136
+ var MATH_FENCE_RE = /^ {0,3}\$\$[ \t]*$/;
137
+ var isMathOpen = (t) => opts.math && MATH_FENCE_RE.test(t);
138
+ var FOOTNOTE_DEF_RE = /^( {0,3})\[\^([^\]\s]+)\]:/;
139
+ var isFootnoteDef = (line) => opts.footnotes && FOOTNOTE_DEF_RE.test(line.text);
140
+ var DEF_RE = /^( {0,3}):[ \t]+/;
141
+ function isDefListStartAt(lines, j) {
142
+ if (!opts.defLists) return false;
143
+ const line = lines[j];
144
+ const next = lines[j + 1];
145
+ if (!line || !next) return false;
146
+ if (isBlank(line)) return false;
147
+ if (startsBlock(lines, j)) return false;
148
+ return DEF_RE.test(next.text);
149
+ }
150
+ function startsBlock(lines, j) {
151
+ const line = lines[j];
152
+ const t = line.text;
153
+ return isFence(t) || isAtx(t) || isThematic(t) || isQuote(t) || detectItem(line) !== null || htmlVariant(t) !== null || isTableStartAt(lines, j) || isMathOpen(t) || isFootnoteDef(line);
154
+ }
155
+ function startsOtherBlock(line) {
156
+ const t = line.text;
157
+ return isFence(t) || isAtx(t) || isThematic(t) || isQuote(t) || detectItem(line) !== null || htmlVariant(t) !== null || isMathOpen(t) || isFootnoteDef(line);
158
+ }
159
+ function buildHeading(line) {
160
+ const t = line.text;
161
+ const m = ATX_RE.exec(t);
162
+ const indent = m[1].length;
163
+ const hashes = m[2];
164
+ const level = hashes.length;
165
+ let ce = indent + hashes.length;
166
+ if (t[ce] === " ") ce++;
167
+ const contentFrom = line.from + ce;
168
+ let end = t.length;
169
+ while (end > ce && (t[end - 1] === " " || t[end - 1] === " ")) end--;
170
+ let e2 = end;
171
+ while (e2 > ce && t[e2 - 1] === "#") e2--;
172
+ if (e2 < end && (e2 === ce || t[e2 - 1] === " " || t[e2 - 1] === " ")) {
173
+ end = e2;
174
+ while (end > ce && (t[end - 1] === " " || t[end - 1] === " ")) end--;
175
+ }
176
+ const children = parseInlineSegs([
177
+ { from: contentFrom, to: line.from + end, text: t.slice(ce, end) }
178
+ ]);
179
+ return { type: "heading", from: line.from, to: line.to, level, contentFrom, children };
180
+ }
181
+ function buildFence(lines, i) {
182
+ const open = lines[i];
183
+ const m = FENCE_RE.exec(open.text);
184
+ const indent = m[1].length;
185
+ const fenceChar = m[2][0];
186
+ const fenceLen = m[2].length;
187
+ const lang = cap(m[3].trim(), MAX_LANG);
188
+ const inner = [];
189
+ let j = i + 1;
190
+ let closeTo = null;
191
+ while (j < lines.length) {
192
+ const cm = /^( {0,3})(`{3,}|~{3,}) *$/.exec(lines[j].text);
193
+ if (cm && cm[2][0] === fenceChar && cm[2].length >= fenceLen) {
194
+ closeTo = lines[j].to;
195
+ j++;
196
+ break;
197
+ }
198
+ inner.push(lines[j]);
199
+ j++;
200
+ }
201
+ const value = cap(
202
+ inner.map((l) => leadingSpaces(l.text) >= indent ? l.text.slice(indent) : l.text.trimStart()).join("\n"),
203
+ MAX_VALUE
204
+ );
205
+ const to = closeTo ?? (inner.length ? inner[inner.length - 1].to : open.to);
206
+ return { node: { type: "codeBlock", from: open.from, to, lang, value, fenced: true }, next: j };
207
+ }
208
+ function buildMathBlock(lines, i) {
209
+ const open = lines[i];
210
+ const inner = [];
211
+ let j = i + 1;
212
+ let closeTo = null;
213
+ while (j < lines.length) {
214
+ if (MATH_FENCE_RE.test(lines[j].text)) {
215
+ closeTo = lines[j].to;
216
+ j++;
217
+ break;
218
+ }
219
+ inner.push(lines[j]);
220
+ j++;
221
+ }
222
+ const value = cap(inner.map((l) => l.text).join("\n"), MAX_VALUE);
223
+ const to = closeTo ?? (inner.length ? inner[inner.length - 1].to : open.to);
224
+ const node = { type: "mathBlock", from: open.from, to, value };
225
+ return { node, next: j };
226
+ }
227
+ function buildIndentedCode(lines, i) {
228
+ const from = lines[i].from;
229
+ const inner = [lines[i]];
230
+ let j = i + 1;
231
+ let pending = [];
232
+ while (j < lines.length) {
233
+ const line = lines[j];
234
+ if (isBlank(line)) {
235
+ pending.push(line);
236
+ j++;
237
+ continue;
238
+ }
239
+ if (leadingSpaces(line.text) >= 4) {
240
+ inner.push(...pending, line);
241
+ pending = [];
242
+ j++;
243
+ continue;
244
+ }
245
+ break;
246
+ }
247
+ const last = inner[inner.length - 1];
248
+ const value = cap(inner.map((l) => l.text.slice(4)).join("\n"), MAX_VALUE);
249
+ return {
250
+ node: { type: "codeBlock", from, to: last.to, lang: "", value, fenced: false },
251
+ next: j
252
+ };
253
+ }
254
+ function buildThematic(line) {
255
+ return { type: "thematicBreak", from: line.from, to: line.to };
256
+ }
257
+ function stripQuote(line) {
258
+ const m = /^( {0,3})>( ?)/.exec(line.text);
259
+ const cut = m[0].length;
260
+ return { from: line.from + cut, to: line.to, text: line.text.slice(cut) };
261
+ }
262
+ function buildBlockquote(lines, i) {
263
+ const from = lines[i].from;
264
+ const inner = [];
265
+ let j = i;
266
+ while (j < lines.length && isQuote(lines[j].text)) {
267
+ inner.push(stripQuote(lines[j]));
268
+ j++;
269
+ }
270
+ const to = lines[j - 1].to;
271
+ const children = parseBlocks(inner);
272
+ return { node: { type: "blockquote", from, to, children }, next: j };
273
+ }
274
+ var TASK_RE = /^\[([ xX])\](\s|$)/;
275
+ function collectItem(lines, idx) {
276
+ const line0 = lines[idx];
277
+ const det = detectItem(line0);
278
+ const contentCol = det.indent + det.markerLen + 1;
279
+ const localStart = det.indent + det.markerLen + (det.spacesAfter > 0 ? 1 : 0);
280
+ let task = null;
281
+ let bodyStart = localStart;
282
+ const afterMarker = line0.text.slice(localStart);
283
+ const tm = TASK_RE.exec(afterMarker);
284
+ if (tm) {
285
+ task = tm[1] === " " ? "unchecked" : "checked";
286
+ bodyStart = localStart + tm[0].length;
287
+ }
288
+ const contentFrom = line0.from + bodyStart;
289
+ const body = [
290
+ { from: contentFrom, to: line0.to, text: line0.text.slice(bodyStart) }
291
+ ];
292
+ let lastTo = line0.to;
293
+ let loose = false;
294
+ let pendingBlank = false;
295
+ let j = idx + 1;
296
+ while (j < lines.length) {
297
+ const lj = lines[j];
298
+ if (isBlank(lj)) {
299
+ pendingBlank = true;
300
+ j++;
301
+ continue;
302
+ }
303
+ const ind = leadingSpaces(lj.text);
304
+ if (ind >= contentCol) {
305
+ if (pendingBlank) {
306
+ loose = true;
307
+ body.push({ from: lj.from, to: lj.from, text: "" });
308
+ }
309
+ body.push({
310
+ from: lj.from + contentCol,
311
+ to: lj.to,
312
+ text: lj.text.slice(contentCol)
313
+ });
314
+ lastTo = lj.to;
315
+ pendingBlank = false;
316
+ j++;
317
+ continue;
318
+ }
319
+ if (detectItem(lj)) break;
320
+ if (pendingBlank) break;
321
+ if (startsOtherBlock(lj)) break;
322
+ body.push({ from: lj.from, to: lj.to, text: lj.text });
323
+ lastTo = lj.to;
324
+ j++;
325
+ }
326
+ const children = parseBlocks(body);
327
+ const item = {
328
+ type: "listItem",
329
+ from: line0.from,
330
+ to: lastTo,
331
+ task,
332
+ contentFrom,
333
+ children
334
+ };
335
+ return { item, next: j, blankBefore: pendingBlank, loose };
336
+ }
337
+ function buildList(lines, start) {
338
+ const first = detectItem(lines[start]);
339
+ const ordered = first.ordered;
340
+ const startNum = ordered ? parseInt(first.marker, 10) || 0 : 1;
341
+ const items = [];
342
+ let loose = false;
343
+ let i = start;
344
+ while (i < lines.length) {
345
+ const det = detectItem(lines[i]);
346
+ if (!det || det.ordered !== ordered) break;
347
+ const r = collectItem(lines, i);
348
+ if (r.blankBefore) loose = true;
349
+ if (r.loose) loose = true;
350
+ items.push(r.item);
351
+ i = r.next;
352
+ }
353
+ const node = {
354
+ type: "list",
355
+ from: items[0].from,
356
+ to: items[items.length - 1].to,
357
+ ordered,
358
+ start: startNum,
359
+ tight: !loose,
360
+ items
361
+ };
362
+ return { node, next: i };
363
+ }
364
+ function parseAligns(delim) {
365
+ return splitCellRanges(delim).map(([a, b]) => {
366
+ const cell = delim.slice(a, b).trim();
367
+ const left = cell.startsWith(":");
368
+ const right = cell.endsWith(":");
369
+ if (left && right) return "center";
370
+ if (left) return "left";
371
+ if (right) return "right";
372
+ return null;
373
+ });
374
+ }
375
+ function splitCellRanges(t) {
376
+ const cells = [];
377
+ let s = 0;
378
+ for (let k = 0; k < t.length; k++) {
379
+ if (t[k] === "|" && t[k - 1] !== "\\") {
380
+ cells.push([s, k]);
381
+ s = k + 1;
382
+ }
383
+ }
384
+ cells.push([s, t.length]);
385
+ if (cells.length > 1 && t.slice(cells[0][0], cells[0][1]).trim() === "") cells.shift();
386
+ if (cells.length > 1 && t.slice(cells[cells.length - 1][0], cells[cells.length - 1][1]).trim() === "")
387
+ cells.pop();
388
+ return cells;
389
+ }
390
+ function splitRow(line) {
391
+ const t = line.text;
392
+ return splitCellRanges(t).map(([a, b]) => {
393
+ let ca = a;
394
+ while (ca < b && t[ca] === " ") ca++;
395
+ let cb = b;
396
+ while (cb > ca && t[cb - 1] === " ") cb--;
397
+ const from = line.from + ca;
398
+ const to = line.from + cb;
399
+ const children = parseInlineSegs([{ from, to, text: t.slice(ca, cb) }]);
400
+ return { type: "tableCell", from, to, children };
401
+ });
402
+ }
403
+ function buildTable(lines, i) {
404
+ const header = splitRow(lines[i]);
405
+ const align = parseAligns(lines[i + 1].text);
406
+ const rows = [];
407
+ let j = i + 2;
408
+ let lastTo = lines[i + 1].to;
409
+ while (j < lines.length) {
410
+ const line = lines[j];
411
+ if (isBlank(line) || startsOtherBlock(line)) break;
412
+ rows.push(splitRow(line));
413
+ lastTo = line.to;
414
+ j++;
415
+ }
416
+ return {
417
+ node: { type: "table", from: lines[i].from, to: lastTo, align, header, rows },
418
+ next: j
419
+ };
420
+ }
421
+ function buildHtml(lines, i) {
422
+ const variant = htmlVariant(lines[i].text);
423
+ const from = lines[i].from;
424
+ const block = [];
425
+ let j = i;
426
+ while (j < lines.length && !isBlank(lines[j])) {
427
+ block.push(lines[j]);
428
+ j++;
429
+ }
430
+ const to = block[block.length - 1].to;
431
+ const value = cap(block.map((l) => l.text).join("\n"), MAX_VALUE);
432
+ return { node: { type: "htmlBlock", from, to, value, variant }, next: j };
433
+ }
434
+ function buildFootnoteDef(lines, i) {
435
+ const line0 = lines[i];
436
+ const m = FOOTNOTE_DEF_RE.exec(line0.text);
437
+ const indent = m[1].length;
438
+ const id = m[2];
439
+ const markerLen = m[0].length - indent;
440
+ const contentCol = indent + markerLen + 1;
441
+ let bodyStart = indent + markerLen;
442
+ if (line0.text[bodyStart] === " ") bodyStart++;
443
+ const contentFrom = line0.from + bodyStart;
444
+ const body = [
445
+ { from: contentFrom, to: line0.to, text: line0.text.slice(bodyStart) }
446
+ ];
447
+ let lastTo = line0.to;
448
+ let pendingBlank = false;
449
+ let j = i + 1;
450
+ while (j < lines.length) {
451
+ const lj = lines[j];
452
+ if (isBlank(lj)) {
453
+ pendingBlank = true;
454
+ j++;
455
+ continue;
456
+ }
457
+ const ind = leadingSpaces(lj.text);
458
+ if (ind >= contentCol) {
459
+ if (pendingBlank) body.push({ from: lj.from, to: lj.from, text: "" });
460
+ body.push({ from: lj.from + contentCol, to: lj.to, text: lj.text.slice(contentCol) });
461
+ lastTo = lj.to;
462
+ pendingBlank = false;
463
+ j++;
464
+ continue;
465
+ }
466
+ if (pendingBlank) break;
467
+ if (isFootnoteDef(lj)) break;
468
+ if (startsOtherBlock(lj)) break;
469
+ if (isDefListStartAt(lines, j)) break;
470
+ body.push({ from: lj.from, to: lj.to, text: lj.text });
471
+ lastTo = lj.to;
472
+ j++;
473
+ }
474
+ const children = parseBlocks(body);
475
+ const node = { type: "footnoteDef", from: line0.from, to: lastTo, id, children };
476
+ return { node, next: j };
477
+ }
478
+ function collectDefinition(lines, idx) {
479
+ const line0 = lines[idx];
480
+ const m = DEF_RE.exec(line0.text);
481
+ const contentCol = m[0].length;
482
+ const body = [
483
+ { from: line0.from + contentCol, to: line0.to, text: line0.text.slice(contentCol) }
484
+ ];
485
+ let lastTo = line0.to;
486
+ let pendingBlank = false;
487
+ let j = idx + 1;
488
+ while (j < lines.length) {
489
+ const lj = lines[j];
490
+ if (isBlank(lj)) {
491
+ pendingBlank = true;
492
+ j++;
493
+ continue;
494
+ }
495
+ if (DEF_RE.test(lj.text)) break;
496
+ const ind = leadingSpaces(lj.text);
497
+ if (ind >= contentCol) {
498
+ if (pendingBlank) body.push({ from: lj.from, to: lj.from, text: "" });
499
+ body.push({ from: lj.from + contentCol, to: lj.to, text: lj.text.slice(contentCol) });
500
+ lastTo = lj.to;
501
+ pendingBlank = false;
502
+ j++;
503
+ continue;
504
+ }
505
+ if (pendingBlank) break;
506
+ if (startsOtherBlock(lj)) break;
507
+ if (isFootnoteDef(lj)) break;
508
+ if (isDefListStartAt(lines, j)) break;
509
+ body.push({ from: lj.from, to: lj.to, text: lj.text });
510
+ lastTo = lj.to;
511
+ j++;
512
+ }
513
+ return { blocks: parseBlocks(body), to: lastTo, next: j };
514
+ }
515
+ function collectDefItem(lines, idx) {
516
+ const termLine = lines[idx];
517
+ const term = parseInlineSegs([
518
+ { from: termLine.from, to: termLine.to, text: termLine.text }
519
+ ]);
520
+ const definitions = [];
521
+ let lastTo = termLine.to;
522
+ let j = idx + 1;
523
+ while (j < lines.length && DEF_RE.test(lines[j].text)) {
524
+ const d = collectDefinition(lines, j);
525
+ definitions.push(d.blocks);
526
+ lastTo = d.to;
527
+ j = d.next;
528
+ }
529
+ const item = { type: "defItem", from: termLine.from, to: lastTo, term, definitions };
530
+ return { item, next: j };
531
+ }
532
+ function buildDefList(lines, start) {
533
+ const items = [];
534
+ let i = start;
535
+ while (i < lines.length && isDefListStartAt(lines, i)) {
536
+ const r = collectDefItem(lines, i);
537
+ items.push(r.item);
538
+ i = r.next;
539
+ }
540
+ const node = {
541
+ type: "defList",
542
+ from: items[0].from,
543
+ to: items[items.length - 1].to,
544
+ items
545
+ };
546
+ return { node, next: i };
547
+ }
548
+ function buildParagraph(lines, i) {
549
+ const para = [lines[i]];
550
+ let j = i + 1;
551
+ while (j < lines.length) {
552
+ if (isBlank(lines[j])) break;
553
+ if (startsBlock(lines, j)) break;
554
+ para.push(lines[j]);
555
+ j++;
556
+ }
557
+ const from = para[0].from;
558
+ const to = para[para.length - 1].to;
559
+ const children = parseInlineSegs(para.map((l) => ({ from: l.from, to: l.to, text: l.text })));
560
+ return { node: { type: "paragraph", from, to, children }, next: j };
561
+ }
562
+ function parseBlocks(lines) {
563
+ const out = [];
564
+ let i = 0;
565
+ while (i < lines.length) {
566
+ const line = lines[i];
567
+ if (isBlank(line)) {
568
+ i++;
569
+ continue;
570
+ }
571
+ const t = line.text;
572
+ if (isFence(t)) {
573
+ const b = buildFence(lines, i);
574
+ out.push(b.node);
575
+ i = b.next;
576
+ } else if (isMathOpen(t)) {
577
+ const b = buildMathBlock(lines, i);
578
+ out.push(b.node);
579
+ i = b.next;
580
+ } else if (leadingSpaces(t) >= 4) {
581
+ const b = buildIndentedCode(lines, i);
582
+ out.push(b.node);
583
+ i = b.next;
584
+ } else if (isAtx(t)) {
585
+ out.push(buildHeading(line));
586
+ i++;
587
+ } else if (isThematic(t)) {
588
+ out.push(buildThematic(line));
589
+ i++;
590
+ } else if (isQuote(t)) {
591
+ const b = buildBlockquote(lines, i);
592
+ out.push(b.node);
593
+ i = b.next;
594
+ } else if (detectItem(line)) {
595
+ const b = buildList(lines, i);
596
+ out.push(b.node);
597
+ i = b.next;
598
+ } else if (isDefListStartAt(lines, i)) {
599
+ const b = buildDefList(lines, i);
600
+ out.push(b.node);
601
+ i = b.next;
602
+ } else if (isTableStartAt(lines, i)) {
603
+ const b = buildTable(lines, i);
604
+ out.push(b.node);
605
+ i = b.next;
606
+ } else if (htmlVariant(t)) {
607
+ const b = buildHtml(lines, i);
608
+ out.push(b.node);
609
+ i = b.next;
610
+ } else if (isFootnoteDef(line)) {
611
+ const b = buildFootnoteDef(lines, i);
612
+ out.push(b.node);
613
+ i = b.next;
614
+ } else {
615
+ const b = buildParagraph(lines, i);
616
+ out.push(b.node);
617
+ i = b.next;
618
+ }
619
+ }
620
+ return out;
621
+ }
622
+ var isWs = (ch) => ch === void 0 || ch === " " || ch === "\n" || ch === " " || ch === "\r";
623
+ var isAlnum = (ch) => ch !== void 0 && /[0-9A-Za-z]/.test(ch);
624
+ function parseInlineSegs(segs) {
625
+ if (segs.length === 0) return [];
626
+ let buf = "";
627
+ const map = [];
628
+ for (let s = 0; s < segs.length; s++) {
629
+ const seg = segs[s];
630
+ if (s > 0) {
631
+ map.push(segs[s - 1].to);
632
+ buf += "\n";
633
+ }
634
+ for (let k = 0; k < seg.text.length; k++) {
635
+ map.push(seg.from + k);
636
+ buf += seg.text[k];
637
+ }
638
+ }
639
+ map.push(segs[segs.length - 1].to);
640
+ const abs = (k) => k < map.length ? map[k] : segs[segs.length - 1].to;
641
+ const text = (from, to, value) => ({
642
+ type: "text",
643
+ from,
644
+ to,
645
+ value: cap(value, MAX_VALUE)
646
+ });
647
+ function tryCode(i, end) {
648
+ let n = 1;
649
+ while (i + n < end && buf[i + n] === "`") n++;
650
+ let k = i + n;
651
+ while (k < end) {
652
+ if (buf[k] === "`") {
653
+ let m = 1;
654
+ while (k + m < end && buf[k + m] === "`") m++;
655
+ if (m === n) {
656
+ let val = buf.slice(i + n, k);
657
+ if (val.length > 2 && val[0] === " " && val[val.length - 1] === " " && val.trim() !== "")
658
+ val = val.slice(1, -1);
659
+ const node = {
660
+ type: "inlineCode",
661
+ from: abs(i),
662
+ to: abs(k + n),
663
+ value: cap(val, MAX_VALUE),
664
+ ticks: n
665
+ };
666
+ return { node, endIdx: k + n };
667
+ }
668
+ k += m;
669
+ continue;
670
+ }
671
+ k++;
672
+ }
673
+ return null;
674
+ }
675
+ function tryMath(i, end) {
676
+ let n = 1;
677
+ while (i + n < end && buf[i + n] === "$" && n < 2) n++;
678
+ const after = buf[i + n];
679
+ if (after === void 0 || after === " " || after === " " || after === "\n") return null;
680
+ let k = i + n;
681
+ while (k < end) {
682
+ const ch = buf[k];
683
+ if (ch === "\\") {
684
+ k += 2;
685
+ continue;
686
+ }
687
+ if (ch === "\n") return null;
688
+ if (ch === "$") {
689
+ let m = 1;
690
+ while (k + m < end && buf[k + m] === "$" && m < 2) m++;
691
+ if (m === n && k > i + n) {
692
+ const prev = buf[k - 1];
693
+ if (prev !== " " && prev !== " " && prev !== "\n") {
694
+ const node = {
695
+ type: "math",
696
+ from: abs(i),
697
+ to: abs(k + n),
698
+ value: cap(buf.slice(i + n, k), MAX_VALUE),
699
+ display: n === 2
700
+ };
701
+ return { node, endIdx: k + n };
702
+ }
703
+ }
704
+ k += m;
705
+ continue;
706
+ }
707
+ k++;
708
+ }
709
+ return null;
710
+ }
711
+ function tryFootnoteRef(i, end) {
712
+ const idStart = i + 2;
713
+ const stop = Math.min(end, idStart + MAX_FOOTNOTE_ID);
714
+ let k = idStart;
715
+ while (k < stop) {
716
+ const ch = buf[k];
717
+ if (ch === "]") break;
718
+ if (ch === " " || ch === " " || ch === "\n" || ch === "[" || ch === "^") return null;
719
+ k++;
720
+ }
721
+ if (k >= stop || buf[k] !== "]" || k === idStart) return null;
722
+ const node = {
723
+ type: "footnoteRef",
724
+ from: abs(i),
725
+ to: abs(k + 1),
726
+ id: buf.slice(idStart, k)
727
+ };
728
+ return { node, endIdx: k + 1 };
729
+ }
730
+ function tryAutolink(i, end) {
731
+ let k = i + 1;
732
+ while (k < end && buf[k] !== ">" && buf[k] !== "<" && buf[k] !== " " && buf[k] !== "\n") k++;
733
+ if (k >= end || buf[k] !== ">") return null;
734
+ const content = buf.slice(i + 1, k);
735
+ const isUri = /^[a-zA-Z][a-zA-Z0-9+.-]*:[^\s]*$/.test(content);
736
+ const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(content);
737
+ if (!isUri && !isEmail) return null;
738
+ const node = {
739
+ type: "autolink",
740
+ from: abs(i),
741
+ to: abs(k + 1),
742
+ url: cap(content, MAX_URL)
743
+ };
744
+ return { node, endIdx: k + 1 };
745
+ }
746
+ function matchLabel(open, end) {
747
+ const stop = Math.min(end, open + 4096);
748
+ let depth = 0;
749
+ for (let k = open; k < stop; k++) {
750
+ const ch = buf[k];
751
+ if (ch === "\\") {
752
+ k++;
753
+ continue;
754
+ }
755
+ if (ch === "[") depth++;
756
+ else if (ch === "]") {
757
+ depth--;
758
+ if (depth === 0) return k;
759
+ }
760
+ }
761
+ return -1;
762
+ }
763
+ function tryLink(i, end, isImage) {
764
+ const br = i + (isImage ? 1 : 0);
765
+ if (buf[br] !== "[") return null;
766
+ const close = matchLabel(br, end);
767
+ if (close < 0) return null;
768
+ let k = close + 1;
769
+ if (buf[k] !== "(") return null;
770
+ k++;
771
+ while (k < end && (buf[k] === " " || buf[k] === "\n")) k++;
772
+ let url = "";
773
+ if (buf[k] === "<") {
774
+ k++;
775
+ const s = k;
776
+ while (k < end && buf[k] !== ">" && buf[k] !== "\n") k++;
777
+ if (buf[k] !== ">") return null;
778
+ url = buf.slice(s, k);
779
+ k++;
780
+ } else {
781
+ const s = k;
782
+ let depth = 0;
783
+ while (k < end) {
784
+ const ch = buf[k];
785
+ if (ch === " " || ch === "\n") break;
786
+ if (ch === "(") depth++;
787
+ else if (ch === ")") {
788
+ if (depth === 0) break;
789
+ depth--;
790
+ }
791
+ k++;
792
+ }
793
+ url = buf.slice(s, k);
794
+ }
795
+ let title;
796
+ while (k < end && (buf[k] === " " || buf[k] === "\n")) k++;
797
+ const q = buf[k];
798
+ if (q === '"' || q === "'" || q === "(") {
799
+ const closeCh = q === "(" ? ")" : q;
800
+ k++;
801
+ const s = k;
802
+ while (k < end && buf[k] !== closeCh) k++;
803
+ if (buf[k] !== closeCh) return null;
804
+ title = buf.slice(s, k);
805
+ k++;
806
+ while (k < end && (buf[k] === " " || buf[k] === "\n")) k++;
807
+ }
808
+ if (buf[k] !== ")") return null;
809
+ const endIdx = k + 1;
810
+ const from = abs(i);
811
+ const to = abs(endIdx);
812
+ if (isImage) {
813
+ const node2 = {
814
+ type: "image",
815
+ from,
816
+ to,
817
+ url: cap(url, MAX_URL),
818
+ alt: cap(buf.slice(br + 1, close), MAX_ALT)
819
+ };
820
+ if (title !== void 0) node2.title = cap(title, MAX_TITLE);
821
+ return { node: node2, endIdx };
822
+ }
823
+ const node = {
824
+ type: "link",
825
+ from,
826
+ to,
827
+ url: cap(url, MAX_URL),
828
+ children: parseInlineRange(br + 1, close)
829
+ };
830
+ if (title !== void 0) node.title = cap(title, MAX_TITLE);
831
+ return { node, endIdx };
832
+ }
833
+ function tryEmph(i, end) {
834
+ const c = buf[i];
835
+ let n = 1;
836
+ while (i + n < end && buf[i + n] === c) n++;
837
+ const isStrike = c === "~";
838
+ if (isStrike && n < 2) return null;
839
+ const strength = isStrike ? 2 : n >= 2 ? 2 : 1;
840
+ if (i + strength > end) return null;
841
+ const after = buf[i + strength];
842
+ const before = buf[i - 1];
843
+ if (isWs(after)) return null;
844
+ if (c === "_" && isAlnum(before)) return null;
845
+ let k = i + strength;
846
+ while (k < end) {
847
+ if (buf[k] === c) {
848
+ let m = 1;
849
+ while (k + m < end && buf[k + m] === c) m++;
850
+ if (m >= strength) {
851
+ const prev = buf[k - 1];
852
+ const aft = buf[k + strength];
853
+ if (!isWs(prev) && (c !== "_" || !isAlnum(aft))) {
854
+ const children = parseInlineRange(i + strength, k);
855
+ const from = abs(i);
856
+ const to = abs(k + strength);
857
+ let node;
858
+ if (isStrike) {
859
+ node = { type: "strikethrough", from, to, children };
860
+ } else if (strength === 2) {
861
+ node = { type: "strong", from, to, marker: c.repeat(2), children };
862
+ } else {
863
+ node = { type: "emphasis", from, to, marker: c, children };
864
+ }
865
+ return { node, endIdx: k + strength };
866
+ }
867
+ }
868
+ k += m;
869
+ continue;
870
+ }
871
+ k++;
872
+ }
873
+ return null;
874
+ }
875
+ function parseInlineRange(start, end) {
876
+ const out = [];
877
+ let i = start;
878
+ let textStart = start;
879
+ const flush = (upto) => {
880
+ if (upto > textStart) out.push(text(abs(textStart), abs(upto), buf.slice(textStart, upto)));
881
+ };
882
+ const commit = (hit) => {
883
+ flush(i);
884
+ out.push(hit.node);
885
+ i = hit.endIdx;
886
+ textStart = i;
887
+ };
888
+ while (i < end) {
889
+ const c = buf[i];
890
+ if (c === "\\") {
891
+ if (buf[i + 1] === "\n") {
892
+ flush(i);
893
+ out.push({ type: "break", from: abs(i), to: abs(i + 2), hard: true });
894
+ i += 2;
895
+ textStart = i;
896
+ continue;
897
+ }
898
+ i += 2;
899
+ continue;
900
+ }
901
+ if (c === "\n") {
902
+ let sp = 0;
903
+ let p = i - 1;
904
+ while (p >= textStart && buf[p] === " ") {
905
+ sp++;
906
+ p--;
907
+ }
908
+ const hard = sp >= 2;
909
+ flush(hard ? i - sp : i);
910
+ out.push({
911
+ type: "break",
912
+ from: abs(hard ? i - sp : i),
913
+ to: abs(i + 1),
914
+ hard
915
+ });
916
+ i++;
917
+ textStart = i;
918
+ continue;
919
+ }
920
+ if (c === "`") {
921
+ const r = tryCode(i, end);
922
+ if (r) {
923
+ commit(r);
924
+ continue;
925
+ }
926
+ i++;
927
+ continue;
928
+ }
929
+ if (c === "$" && opts.math) {
930
+ const r = tryMath(i, end);
931
+ if (r) {
932
+ commit(r);
933
+ continue;
934
+ }
935
+ i++;
936
+ continue;
937
+ }
938
+ if (c === "<") {
939
+ const r = tryAutolink(i, end);
940
+ if (r) {
941
+ commit(r);
942
+ continue;
943
+ }
944
+ i++;
945
+ continue;
946
+ }
947
+ if (c === "!" && buf[i + 1] === "[") {
948
+ const r = tryLink(i, end, true);
949
+ if (r) {
950
+ commit(r);
951
+ continue;
952
+ }
953
+ i++;
954
+ continue;
955
+ }
956
+ if (c === "[") {
957
+ if (opts.footnotes && buf[i + 1] === "^") {
958
+ const rf = tryFootnoteRef(i, end);
959
+ if (rf) {
960
+ commit(rf);
961
+ continue;
962
+ }
963
+ }
964
+ const r = tryLink(i, end, false);
965
+ if (r) {
966
+ commit(r);
967
+ continue;
968
+ }
969
+ i++;
970
+ continue;
971
+ }
972
+ if (c === "*" || c === "_" || c === "~") {
973
+ const r = tryEmph(i, end);
974
+ if (r) {
975
+ commit(r);
976
+ continue;
977
+ }
978
+ i++;
979
+ continue;
980
+ }
981
+ i++;
982
+ }
983
+ flush(end);
984
+ return out;
985
+ }
986
+ return parseInlineRange(0, buf.length);
987
+ }
988
+ function parse(src, options) {
989
+ opts = {
990
+ math: options?.math === true,
991
+ footnotes: options?.footnotes === true,
992
+ defLists: options?.defLists === true
993
+ };
994
+ const lines = splitLines(src);
995
+ const children = parseBlocks(lines);
996
+ return { type: "document", from: 0, to: src.length, children };
997
+ }
998
+ function headSafety(block) {
999
+ switch (block.type) {
1000
+ case "heading":
1001
+ case "thematicBreak":
1002
+ case "mathBlock":
1003
+ return "always";
1004
+ case "codeBlock":
1005
+ return block.fenced ? "always" : "never";
1006
+ case "paragraph":
1007
+ case "table":
1008
+ case "htmlBlock":
1009
+ case "blockquote":
1010
+ return "needs-blank";
1011
+ default:
1012
+ return "never";
1013
+ }
1014
+ }
1015
+ function prevLineIsBlank(src, lineStart) {
1016
+ if (lineStart <= 0) return false;
1017
+ const end = lineStart - 1;
1018
+ let start = end - 1;
1019
+ while (start >= 0 && src[start] !== "\n") start--;
1020
+ start += 1;
1021
+ return src.slice(start, end).trim() === "";
1022
+ }
1023
+ function blankLineFullyAfter(src, lineStart, minStart) {
1024
+ if (lineStart <= 0) return false;
1025
+ const end = lineStart - 1;
1026
+ let start = end - 1;
1027
+ while (start >= 0 && src[start] !== "\n") start--;
1028
+ start += 1;
1029
+ if (start < minStart) return false;
1030
+ return src.slice(start, end).trim() === "";
1031
+ }
1032
+ function shiftBlock(block, delta) {
1033
+ const clone = structuredClone(block);
1034
+ walk(clone, (n) => {
1035
+ const p = n;
1036
+ p.from += delta;
1037
+ p.to += delta;
1038
+ if (typeof p.contentFrom === "number") p.contentFrom += delta;
1039
+ });
1040
+ return clone;
1041
+ }
1042
+ function lineStartingAt(lines, off) {
1043
+ let lo = 0;
1044
+ let hi = lines.length - 1;
1045
+ while (lo <= hi) {
1046
+ const mid = lo + hi >> 1;
1047
+ const f = lines[mid].from;
1048
+ if (f === off) return mid;
1049
+ if (f < off) lo = mid + 1;
1050
+ else hi = mid - 1;
1051
+ }
1052
+ return -1;
1053
+ }
1054
+ function lastBlockAtOrBefore(blocks, off) {
1055
+ let lo = 0;
1056
+ let hi = blocks.length - 1;
1057
+ let ans = -1;
1058
+ while (lo <= hi) {
1059
+ const mid = lo + hi >> 1;
1060
+ if (blocks[mid].from <= off) {
1061
+ ans = mid;
1062
+ lo = mid + 1;
1063
+ } else {
1064
+ hi = mid - 1;
1065
+ }
1066
+ }
1067
+ return ans;
1068
+ }
1069
+ var MAX_JOIN_ATTEMPTS = 4;
1070
+ function tryReuseSuffix(blocks, prevSrc, to, delta, nextLines, cLine) {
1071
+ const dEnd = lastBlockAtOrBefore(blocks, to);
1072
+ let attempts = 0;
1073
+ for (let j = dEnd + 1; j < blocks.length; j++) {
1074
+ const joinOff = blocks[j].from;
1075
+ if (joinOff < to) continue;
1076
+ if (!blankLineFullyAfter(prevSrc, joinOff, to)) continue;
1077
+ const nextJoinOff = joinOff + delta;
1078
+ const joinLine = lineStartingAt(nextLines, nextJoinOff);
1079
+ if (joinLine <= cLine) continue;
1080
+ if (++attempts > MAX_JOIN_ATTEMPTS) break;
1081
+ const guard = parseBlocks(nextLines.slice(cLine, joinLine + 1));
1082
+ const dirty = [];
1083
+ let proven = false;
1084
+ for (const b of guard) {
1085
+ if (b.from === nextJoinOff) {
1086
+ proven = true;
1087
+ break;
1088
+ }
1089
+ if (b.from > nextJoinOff) break;
1090
+ dirty.push(b);
1091
+ }
1092
+ if (!proven) continue;
1093
+ const rest = blocks.slice(j);
1094
+ const shifted = rest.map((b) => shiftBlock(b, delta));
1095
+ return { dirty, shifted, endLine: joinLine, count: rest.length };
1096
+ }
1097
+ return null;
1098
+ }
1099
+ function runIncremental(prev, prevSrc, change, nextSrc, options) {
1100
+ const nextLines = splitLines(nextSrc);
1101
+ const total = nextLines.length;
1102
+ const full = () => ({
1103
+ doc: parse(nextSrc, options),
1104
+ stats: {
1105
+ fellBack: true,
1106
+ reusedBlocks: 0,
1107
+ reparsedFromLine: 0,
1108
+ reparsedToLine: total,
1109
+ reusedSuffixBlocks: 0,
1110
+ totalLines: total
1111
+ }
1112
+ });
1113
+ const from = Math.max(0, Math.min(change.from, change.to));
1114
+ const to = Math.min(prevSrc.length, Math.max(change.from, change.to));
1115
+ if (to < from) return full();
1116
+ if (nextSrc.length !== prevSrc.length + change.insert.length - (to - from)) return full();
1117
+ if (prevSrc.slice(0, from) !== nextSrc.slice(0, from)) return full();
1118
+ const delta = change.insert.length - (to - from);
1119
+ const blocks = prev.children;
1120
+ const hi = Math.min(blocks.length - 1, lastBlockAtOrBefore(blocks, from));
1121
+ for (let k = hi; k >= 1; k--) {
1122
+ const cut = blocks[k].from;
1123
+ if (cut > from) continue;
1124
+ const safety = headSafety(blocks[k - 1]);
1125
+ if (safety === "never") continue;
1126
+ if (safety === "needs-blank" && !prevLineIsBlank(prevSrc, cut)) continue;
1127
+ const c = lineStartingAt(nextLines, cut);
1128
+ if (c < 0) continue;
1129
+ opts = {
1130
+ math: options?.math === true,
1131
+ footnotes: options?.footnotes === true,
1132
+ defLists: options?.defLists === true
1133
+ };
1134
+ const suffix = tryReuseSuffix(blocks, prevSrc, to, delta, nextLines, c);
1135
+ if (suffix) {
1136
+ const children2 = blocks.slice(0, k).concat(suffix.dirty, suffix.shifted);
1137
+ return {
1138
+ doc: { type: "document", from: 0, to: nextSrc.length, children: children2 },
1139
+ stats: {
1140
+ fellBack: false,
1141
+ reusedBlocks: k,
1142
+ reparsedFromLine: c,
1143
+ reparsedToLine: suffix.endLine,
1144
+ reusedSuffixBlocks: suffix.count,
1145
+ totalLines: total
1146
+ }
1147
+ };
1148
+ }
1149
+ const tail = parseBlocks(nextLines.slice(c));
1150
+ const children = blocks.slice(0, k).concat(tail);
1151
+ return {
1152
+ doc: { type: "document", from: 0, to: nextSrc.length, children },
1153
+ stats: {
1154
+ fellBack: false,
1155
+ reusedBlocks: k,
1156
+ reparsedFromLine: c,
1157
+ reparsedToLine: total,
1158
+ reusedSuffixBlocks: 0,
1159
+ totalLines: total
1160
+ }
1161
+ };
1162
+ }
1163
+ return full();
1164
+ }
1165
+ function parseIncremental(prev, prevSrc, change, nextSrc, options) {
1166
+ return runIncremental(prev, prevSrc, change, nextSrc, options).doc;
1167
+ }
1168
+
1169
+ // src/core/render.ts
1170
+ var MAX_URL2 = 8192;
1171
+ var SAFE_SCHEMES = /^(https?:|mailto:)/;
1172
+ function newFnCtx() {
1173
+ return { nums: /* @__PURE__ */ new Map() };
1174
+ }
1175
+ function fnNumber(ctx, slug) {
1176
+ const existing = ctx.nums.get(slug);
1177
+ if (existing !== void 0) return existing;
1178
+ const n = ctx.nums.size + 1;
1179
+ ctx.nums.set(slug, n);
1180
+ return n;
1181
+ }
1182
+ function escapeHtml(value) {
1183
+ let out = "";
1184
+ for (let i = 0; i < value.length; i++) {
1185
+ const ch = value.charCodeAt(i);
1186
+ switch (ch) {
1187
+ case 38:
1188
+ out += "&amp;";
1189
+ break;
1190
+ case 60:
1191
+ out += "&lt;";
1192
+ break;
1193
+ case 62:
1194
+ out += "&gt;";
1195
+ break;
1196
+ case 34:
1197
+ out += "&quot;";
1198
+ break;
1199
+ default:
1200
+ out += value[i];
1201
+ }
1202
+ }
1203
+ return out;
1204
+ }
1205
+ function slugFootnoteId(id) {
1206
+ const slug = id.replace(/[^A-Za-z0-9_-]+/g, "-");
1207
+ return slug === "" ? "_" : slug;
1208
+ }
1209
+ function safeUrl(url) {
1210
+ if (typeof url !== "string" || url.length === 0) return "#";
1211
+ const trimmed = url.trim().slice(0, MAX_URL2);
1212
+ if (trimmed === "") return "#";
1213
+ const probe = trimmed.replace(/[\u0000-\u0020\u007f]/g, "").toLowerCase();
1214
+ if (probe === "") return "#";
1215
+ if (SAFE_SCHEMES.test(probe)) return trimmed;
1216
+ if (/^[a-z][a-z0-9+.-]*:/.test(probe)) return "#";
1217
+ return trimmed;
1218
+ }
1219
+ function attrUrl(url) {
1220
+ return escapeHtml(safeUrl(url));
1221
+ }
1222
+ function renderInline(nodes, options) {
1223
+ return inlineRun(nodes, options, newFnCtx());
1224
+ }
1225
+ function inlineRun(nodes, options, ctx) {
1226
+ let out = "";
1227
+ for (const node of nodes) out += renderInlineNode(node, options, ctx);
1228
+ return out;
1229
+ }
1230
+ function renderInlineNode(node, options, ctx) {
1231
+ switch (node.type) {
1232
+ case "text":
1233
+ return escapeHtml(node.value);
1234
+ case "strong":
1235
+ return `<strong>${inlineRun(node.children, options, ctx)}</strong>`;
1236
+ case "emphasis":
1237
+ return `<em>${inlineRun(node.children, options, ctx)}</em>`;
1238
+ case "strikethrough":
1239
+ return `<del>${inlineRun(node.children, options, ctx)}</del>`;
1240
+ case "inlineCode":
1241
+ return `<code>${escapeHtml(node.value)}</code>`;
1242
+ case "link": {
1243
+ const title = node.title ? ` title="${escapeHtml(node.title)}"` : "";
1244
+ return `<a href="${attrUrl(node.url)}"${title}>${inlineRun(node.children, options, ctx)}</a>`;
1245
+ }
1246
+ case "image": {
1247
+ const title = node.title ? ` title="${escapeHtml(node.title)}"` : "";
1248
+ return `<img src="${attrUrl(node.url)}" alt="${escapeHtml(node.alt)}"${title}>`;
1249
+ }
1250
+ case "autolink":
1251
+ return `<a href="${attrUrl(node.url)}">${escapeHtml(node.url)}</a>`;
1252
+ case "break":
1253
+ return node.hard ? "<br>\n" : "\n";
1254
+ case "math":
1255
+ return options?.math ? options.math(node.value, node.display) : `<span class="tw-math-src">${escapeHtml(node.value)}</span>`;
1256
+ case "footnoteRef": {
1257
+ const slug = slugFootnoteId(node.id);
1258
+ const n = fnNumber(ctx, slug);
1259
+ const safe = escapeHtml(slug);
1260
+ return `<sup class="tw-fnref" id="fnref-${safe}"><a href="#fn-${safe}">[${n}]</a></sup>`;
1261
+ }
1262
+ default: {
1263
+ const _never = node;
1264
+ return _never;
1265
+ }
1266
+ }
1267
+ }
1268
+ function renderNode(node, options) {
1269
+ return renderBlockNode(node, options, newFnCtx());
1270
+ }
1271
+ function renderBlockNode(node, options, ctx) {
1272
+ switch (node.type) {
1273
+ case "heading": {
1274
+ const l = node.level;
1275
+ return `<h${l}>${inlineRun(node.children, options, ctx)}</h${l}>`;
1276
+ }
1277
+ case "paragraph":
1278
+ return `<p>${inlineRun(node.children, options, ctx)}</p>`;
1279
+ case "blockquote":
1280
+ return `<blockquote>${renderBlocks(node.children, options, ctx)}</blockquote>`;
1281
+ case "list":
1282
+ return renderList(node.ordered, node.start, node.tight, node.items, options, ctx);
1283
+ case "codeBlock": {
1284
+ const cls = node.lang ? ` class="language-${escapeHtml(node.lang)}"` : "";
1285
+ const body = options?.highlight ? options.highlight(node.lang, node.value) : escapeHtml(node.value);
1286
+ return `<pre><code${cls}>${body}</code></pre>`;
1287
+ }
1288
+ case "thematicBreak":
1289
+ return "<hr>";
1290
+ case "table":
1291
+ return renderTable(node, options, ctx);
1292
+ case "htmlBlock":
1293
+ return `<pre>${escapeHtml(node.value)}</pre>`;
1294
+ case "mathBlock":
1295
+ return options?.math ? options.math(node.value, true) : `<div class="tw-math-src">${escapeHtml(node.value)}</div>`;
1296
+ case "footnoteDef":
1297
+ return `<div class="tw-footnote-def">${renderBlocks(node.children, options, ctx)}</div>`;
1298
+ case "defList": {
1299
+ let out = "";
1300
+ for (const item of node.items) {
1301
+ out += `<dt>${inlineRun(item.term, options, ctx)}</dt>`;
1302
+ for (const def of item.definitions) {
1303
+ out += `<dd>${renderBlocks(def, options, ctx)}</dd>`;
1304
+ }
1305
+ }
1306
+ return `<dl>${out}</dl>`;
1307
+ }
1308
+ default: {
1309
+ const _never = node;
1310
+ return _never;
1311
+ }
1312
+ }
1313
+ }
1314
+ function renderBlocks(blocks, options, ctx) {
1315
+ let out = "";
1316
+ for (const b of blocks) {
1317
+ if (b.type === "footnoteDef") continue;
1318
+ out += renderBlockNode(b, options, ctx);
1319
+ }
1320
+ return out;
1321
+ }
1322
+ function renderList(ordered, start, tight, items, options, ctx) {
1323
+ const tag = ordered ? "ol" : "ul";
1324
+ const startAttr = ordered && Number.isFinite(start) && start !== 1 ? ` start="${escapeHtml(String(Math.trunc(start)))}"` : "";
1325
+ let body = "";
1326
+ for (const item of items) body += renderListItem(item, tight, options, ctx);
1327
+ return `<${tag}${startAttr}>${body}</${tag}>`;
1328
+ }
1329
+ function renderListItem(item, tight, options, ctx) {
1330
+ let checkbox = "";
1331
+ if (item.task !== null) {
1332
+ const checked = item.task === "checked" ? " checked" : "";
1333
+ checkbox = `<input type="checkbox" disabled${checked}> `;
1334
+ }
1335
+ return `<li>${checkbox}${renderItemChildren(item.children, tight, options, ctx)}</li>`;
1336
+ }
1337
+ function renderItemChildren(children, tight, options, ctx) {
1338
+ if (tight) {
1339
+ let out = "";
1340
+ for (const child of children) {
1341
+ out += child.type === "paragraph" ? inlineRun(child.children, options, ctx) : renderBlockNode(child, options, ctx);
1342
+ }
1343
+ return out;
1344
+ }
1345
+ return renderBlocks(children, options, ctx);
1346
+ }
1347
+ function renderTable(node, options, ctx) {
1348
+ const align = node.align;
1349
+ const cellStyle = (col) => {
1350
+ const a = align[col];
1351
+ return a ? ` style="text-align:${a}"` : "";
1352
+ };
1353
+ const headCells = renderRow(node.header, "th", cellStyle, options, ctx);
1354
+ const head = `<thead><tr>${headCells}</tr></thead>`;
1355
+ let bodyRows = "";
1356
+ for (const row of node.rows) {
1357
+ bodyRows += `<tr>${renderRow(row, "td", cellStyle, options, ctx)}</tr>`;
1358
+ }
1359
+ const body = `<tbody>${bodyRows}</tbody>`;
1360
+ return `<table>${head}${body}</table>`;
1361
+ }
1362
+ function renderRow(cells, tag, cellStyle, options, ctx) {
1363
+ let out = "";
1364
+ for (let i = 0; i < cells.length; i++) {
1365
+ const cell = cells[i];
1366
+ out += `<${tag}${cellStyle(i)}>${inlineRun(cell.children, options, ctx)}</${tag}>`;
1367
+ }
1368
+ return out;
1369
+ }
1370
+ function collectFootnoteDefs(doc) {
1371
+ const defs = [];
1372
+ walk(doc, (n) => {
1373
+ if (n.type === "footnoteDef") {
1374
+ defs.push(n);
1375
+ return false;
1376
+ }
1377
+ return true;
1378
+ });
1379
+ return defs;
1380
+ }
1381
+ function renderToHtml(doc, options) {
1382
+ const ctx = newFnCtx();
1383
+ let out = renderBlocks(doc.children, options, ctx);
1384
+ const defs = collectFootnoteDefs(doc);
1385
+ if (defs.length > 0) {
1386
+ let items = "";
1387
+ for (const def of defs) {
1388
+ const safe = escapeHtml(slugFootnoteId(def.id));
1389
+ items += `<li id="fn-${safe}">` + renderBlocks(def.children, options, ctx) + ` <a href="#fnref-${safe}" class="tw-fn-back">\u21A9</a></li>`;
1390
+ }
1391
+ out += `<section class="tw-footnotes"><ol>${items}</ol></section>`;
1392
+ }
1393
+ return out;
1394
+ }
1395
+
1396
+ export { childrenOf, isInline, parse, parseIncremental, renderInline, renderNode, renderToHtml, safeUrl, walk };
1397
+ //# sourceMappingURL=chunk-M6IVEMXO.js.map
1398
+ //# sourceMappingURL=chunk-M6IVEMXO.js.map