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,1533 @@
1
+ import { walk } from './chunk-M6IVEMXO.js';
2
+
3
+ // src/core/unified.ts
4
+ function collectMarkers(doc, source) {
5
+ const markers = [];
6
+ const push = (from, to, kind) => {
7
+ if (to > from) markers.push({ from, to, kind });
8
+ };
9
+ walk(doc, (node) => {
10
+ switch (node.type) {
11
+ case "heading": {
12
+ push(node.from, node.contentFrom, "heading");
13
+ break;
14
+ }
15
+ case "emphasis":
16
+ case "strong":
17
+ case "strikethrough": {
18
+ const kind = node.type === "strikethrough" ? "strike" : node.type;
19
+ const kids = node.children;
20
+ const first = kids[0];
21
+ const last = kids[kids.length - 1];
22
+ const innerFrom = first ? first.from : node.to;
23
+ const innerTo = last ? last.to : node.from;
24
+ push(node.from, innerFrom, kind);
25
+ push(innerTo, node.to, kind);
26
+ break;
27
+ }
28
+ case "inlineCode": {
29
+ const ticks = Math.max(1, node.ticks);
30
+ const openTo = Math.min(node.from + ticks, node.to);
31
+ const closeFrom = Math.max(node.to - ticks, openTo);
32
+ push(node.from, openTo, "code");
33
+ push(closeFrom, node.to, "code");
34
+ break;
35
+ }
36
+ case "link": {
37
+ const kids = node.children;
38
+ const last = kids[kids.length - 1];
39
+ const textEnd = last ? last.to : node.from + 1;
40
+ const midTo = Math.min(textEnd + 2, node.to);
41
+ push(node.from, Math.min(node.from + 1, node.to), "link");
42
+ push(textEnd, midTo, "link");
43
+ push(midTo, node.to - 1, "link");
44
+ push(Math.max(node.to - 1, node.from), node.to, "link");
45
+ break;
46
+ }
47
+ case "image": {
48
+ const bracketOpen = node.from + 1;
49
+ const altStart = bracketOpen + 1;
50
+ const altEnd = Math.min(altStart + node.alt.length, node.to);
51
+ const midTo = Math.min(altEnd + 2, node.to);
52
+ push(node.from, Math.min(node.from + 1, node.to), "image");
53
+ push(bracketOpen, Math.min(bracketOpen + 1, node.to), "image");
54
+ push(altEnd, midTo, "image");
55
+ push(midTo, node.to - 1, "image");
56
+ push(Math.max(node.to - 1, node.from), node.to, "image");
57
+ break;
58
+ }
59
+ case "listItem": {
60
+ push(node.from, node.contentFrom, "listMarker");
61
+ break;
62
+ }
63
+ case "math": {
64
+ const delim = node.display ? 2 : 1;
65
+ const openTo = Math.min(node.from + delim, node.to);
66
+ const closeFrom = Math.max(node.to - delim, openTo);
67
+ push(node.from, openTo, "math");
68
+ push(closeFrom, node.to, "math");
69
+ break;
70
+ }
71
+ case "footnoteRef": {
72
+ const openTo = Math.min(node.from + 2, node.to);
73
+ const closeFrom = Math.max(node.to - 1, openTo);
74
+ push(node.from, openTo, "footnoteRef");
75
+ push(closeFrom, node.to, "footnoteRef");
76
+ break;
77
+ }
78
+ case "codeBlock": {
79
+ if (!source || !node.fenced) break;
80
+ let openTo = source.indexOf("\n", node.from);
81
+ if (openTo === -1 || openTo > node.to) openTo = node.to;
82
+ if (openTo > node.from && source[openTo - 1] === "\r") openTo--;
83
+ push(node.from, openTo, "fence");
84
+ const closeStart = source.lastIndexOf("\n", node.to - 1) + 1;
85
+ if (closeStart > node.from) {
86
+ const closeText = source.slice(closeStart, node.to);
87
+ const cm = /^( {0,3})(`{3,}|~{3,}) *$/.exec(closeText);
88
+ const om = /^ {0,3}([`~])/.exec(source.slice(node.from, openTo));
89
+ if (cm && om && cm[2][0] === om[1]) push(closeStart, node.to, "fence");
90
+ }
91
+ break;
92
+ }
93
+ case "blockquote": {
94
+ if (!source) break;
95
+ const lineStart2 = source.lastIndexOf("\n", node.from - 1) + 1;
96
+ if (lineStart2 !== node.from) break;
97
+ let p = node.from;
98
+ while (p < node.to) {
99
+ let end = source.indexOf("\n", p);
100
+ if (end === -1 || end > node.to) end = node.to;
101
+ const qm = /^(?: {0,3}> ?)+/.exec(source.slice(p, end));
102
+ if (qm) push(p, p + qm[0].length, "blockquote");
103
+ p = end + 1;
104
+ }
105
+ break;
106
+ }
107
+ }
108
+ return true;
109
+ });
110
+ return markers;
111
+ }
112
+ function hiddenMarkers(doc, sel, source) {
113
+ const lo = Math.min(sel.from, sel.to) - 1;
114
+ const hi = Math.max(sel.from, sel.to) + 1;
115
+ const intersects = (m) => m.from < hi && lo < m.to;
116
+ return collectMarkers(doc, source).filter((m) => !intersects(m));
117
+ }
118
+ function activeBlockIndex(doc, offset) {
119
+ const blocks = doc.children;
120
+ for (let i = 0; i < blocks.length; i++) {
121
+ const b = blocks[i];
122
+ if (b && offset >= b.from && offset <= b.to) return i;
123
+ }
124
+ return -1;
125
+ }
126
+
127
+ // src/core/fold.ts
128
+ function headingFoldRanges(doc) {
129
+ const blocks = doc.children;
130
+ const ranges = [];
131
+ for (let i = 0; i < blocks.length; i++) {
132
+ const h = blocks[i];
133
+ if (!h || h.type !== "heading") continue;
134
+ let to = doc.to;
135
+ for (let j = i + 1; j < blocks.length; j++) {
136
+ const n = blocks[j];
137
+ if (n && n.type === "heading" && n.level <= h.level) {
138
+ to = n.from;
139
+ break;
140
+ }
141
+ }
142
+ const from = h.to;
143
+ if (to > from) {
144
+ ranges.push({ headingFrom: h.from, level: h.level, from, to });
145
+ }
146
+ }
147
+ return ranges;
148
+ }
149
+
150
+ // src/core/commands.ts
151
+ var COMMANDS = [
152
+ { id: "bold", label: "Bold", kbd: "\u2318B", group: "inline" },
153
+ { id: "italic", label: "Italic", kbd: "\u2318I", group: "inline" },
154
+ { id: "strikethrough", label: "Strikethrough", group: "inline" },
155
+ { id: "inlineCode", label: "Inline Code", kbd: "\u2318E", group: "inline" },
156
+ { id: "link", label: "Link", kbd: "\u2318K", group: "inline" },
157
+ { id: "heading1", label: "Heading 1", group: "block" },
158
+ { id: "heading2", label: "Heading 2", group: "block" },
159
+ { id: "heading3", label: "Heading 3", group: "block" },
160
+ { id: "heading4", label: "Heading 4", group: "block" },
161
+ { id: "heading5", label: "Heading 5", group: "block" },
162
+ { id: "heading6", label: "Heading 6", group: "block" },
163
+ { id: "bulletList", label: "Bullet List", group: "block" },
164
+ { id: "orderedList", label: "Ordered List", group: "block" },
165
+ { id: "taskList", label: "Task List", group: "block" },
166
+ { id: "quote", label: "Quote", group: "block" },
167
+ { id: "horizontalRule", label: "Horizontal Rule", group: "insert" },
168
+ { id: "codeBlock", label: "Code Block", group: "insert" },
169
+ { id: "table", label: "Table", group: "insert" }
170
+ ];
171
+ function norm(sel) {
172
+ return { from: Math.min(sel.from, sel.to), to: Math.max(sel.from, sel.to) };
173
+ }
174
+ function toggleWrap(text, sel, marker) {
175
+ const len = marker.length;
176
+ const { from, to } = norm(sel);
177
+ if (from >= len && text.slice(from - len, from) === marker && text.slice(to, to + len) === marker) {
178
+ const t2 = text.slice(0, from - len) + text.slice(from, to) + text.slice(to + len);
179
+ return { text: t2, selection: { from: from - len, to: to - len } };
180
+ }
181
+ const selected = text.slice(from, to);
182
+ if (selected.length >= 2 * len && selected.startsWith(marker) && selected.endsWith(marker)) {
183
+ const inner = selected.slice(len, selected.length - len);
184
+ const t2 = text.slice(0, from) + inner + text.slice(to);
185
+ return { text: t2, selection: { from, to: from + inner.length } };
186
+ }
187
+ const t = text.slice(0, from) + marker + selected + marker + text.slice(to);
188
+ if (from === to) return { text: t, selection: { from: from + len, to: from + len } };
189
+ return { text: t, selection: { from: from + len, to: to + len } };
190
+ }
191
+ function insertLink(text, sel) {
192
+ const { from, to } = norm(sel);
193
+ const label = text.slice(from, to) || "text";
194
+ const url = "https://";
195
+ const inserted = `[${label}](${url})`;
196
+ const t = text.slice(0, from) + inserted + text.slice(to);
197
+ const urlStart = from + label.length + 3;
198
+ return { text: t, selection: { from: urlStart, to: urlStart + url.length } };
199
+ }
200
+ var HEADING_RE = /^ {0,3}#{1,6}\s+/;
201
+ var LIST_RE = /^ {0,3}(?:[-*+]\s(?:\[[ xX]\]\s)?|\d+[.)]\s)/;
202
+ var QUOTE_RE = /^ {0,3}>\s?/;
203
+ function applyLinePrefix(text, sel, p) {
204
+ const { from, to } = norm(sel);
205
+ const start = text.lastIndexOf("\n", from - 1) + 1;
206
+ const searchFrom = to > from ? to - 1 : to;
207
+ let end = text.indexOf("\n", searchFrom);
208
+ if (end === -1) end = text.length;
209
+ const lines = text.slice(start, end).split("\n");
210
+ const allHave = lines.every((l) => l.trim() === "" || p.has(l));
211
+ const out = lines.map((l, i) => l.trim() === "" ? l : allHave ? p.strip(l) : p.add(p.strip(l), i)).join("\n");
212
+ const t = text.slice(0, start) + out + text.slice(end);
213
+ return { text: t, selection: { from: start, to: start + out.length } };
214
+ }
215
+ function stripAllPrefixes(line) {
216
+ return line.replace(HEADING_RE, "").replace(LIST_RE, "").replace(QUOTE_RE, "");
217
+ }
218
+ function insertBlock(text, sel, block, selectInner) {
219
+ const { from, to } = norm(sel);
220
+ const before = text.slice(0, from);
221
+ const after = text.slice(to);
222
+ const lead = before === "" || before.endsWith("\n\n") ? "" : before.endsWith("\n") ? "\n" : "\n\n";
223
+ const trail = after === "" || after.startsWith("\n\n") ? "" : after.startsWith("\n") ? "\n" : "\n\n";
224
+ const insertedAt = from + lead.length;
225
+ const t = before + lead + block + trail + after;
226
+ const selection = selectInner ? { from: insertedAt + selectInner[0], to: insertedAt + selectInner[1] } : { from: insertedAt, to: insertedAt + block.length };
227
+ return { text: t, selection };
228
+ }
229
+ function applyCommand(text, sel, cmd) {
230
+ switch (cmd) {
231
+ case "bold":
232
+ return toggleWrap(text, sel, "**");
233
+ case "italic":
234
+ return toggleWrap(text, sel, "*");
235
+ case "strikethrough":
236
+ return toggleWrap(text, sel, "~~");
237
+ case "inlineCode":
238
+ return toggleWrap(text, sel, "`");
239
+ case "link":
240
+ return insertLink(text, sel);
241
+ case "heading1":
242
+ case "heading2":
243
+ case "heading3":
244
+ case "heading4":
245
+ case "heading5":
246
+ case "heading6": {
247
+ const level = cmd === "heading1" ? 1 : cmd === "heading2" ? 2 : cmd === "heading3" ? 3 : cmd === "heading4" ? 4 : cmd === "heading5" ? 5 : 6;
248
+ const marker = "#".repeat(level) + " ";
249
+ return applyLinePrefix(text, sel, {
250
+ has: (l) => new RegExp(`^ {0,3}#{${level}}\\s`).test(l),
251
+ strip: (l) => l.replace(HEADING_RE, ""),
252
+ add: (l) => marker + l
253
+ });
254
+ }
255
+ case "bulletList":
256
+ return applyLinePrefix(text, sel, {
257
+ has: (l) => /^ {0,3}[-*+]\s/.test(l),
258
+ strip: stripAllPrefixes,
259
+ add: (l) => "- " + l
260
+ });
261
+ case "orderedList":
262
+ return applyLinePrefix(text, sel, {
263
+ has: (l) => /^ {0,3}\d+[.)]\s/.test(l),
264
+ strip: stripAllPrefixes,
265
+ add: (l, i) => `${i + 1}. ` + l
266
+ });
267
+ case "taskList":
268
+ return applyLinePrefix(text, sel, {
269
+ has: (l) => /^ {0,3}[-*+]\s\[[ xX]\]\s/.test(l),
270
+ strip: stripAllPrefixes,
271
+ add: (l) => "- [ ] " + l
272
+ });
273
+ case "quote":
274
+ return applyLinePrefix(text, sel, {
275
+ has: (l) => QUOTE_RE.test(l),
276
+ strip: (l) => l.replace(QUOTE_RE, ""),
277
+ add: (l) => "> " + l
278
+ });
279
+ case "horizontalRule":
280
+ return insertBlock(text, sel, "---");
281
+ case "codeBlock": {
282
+ const selected = text.slice(norm(sel).from, norm(sel).to);
283
+ const block = "```\n" + selected + "\n```";
284
+ return insertBlock(text, sel, block, selected ? void 0 : [4, 4]);
285
+ }
286
+ case "table": {
287
+ const block = "| Column | Column |\n| --- | --- |\n| Cell | Cell |";
288
+ return insertBlock(text, sel, block, [2, 8]);
289
+ }
290
+ default: {
291
+ return { text, selection: norm(sel) };
292
+ }
293
+ }
294
+ }
295
+
296
+ // src/core/text.ts
297
+ var TextDoc = class _TextDoc {
298
+ text;
299
+ _lineStarts = null;
300
+ constructor(text = "") {
301
+ this.text = text;
302
+ }
303
+ get length() {
304
+ return this.text.length;
305
+ }
306
+ /** Apply one change, returning a new document. */
307
+ apply(change) {
308
+ const { from, to, insert } = normalize(change, this.text.length);
309
+ return new _TextDoc(this.text.slice(0, from) + insert + this.text.slice(to));
310
+ }
311
+ /**
312
+ * Apply several changes, returning a new document. Changes are given in
313
+ * document coordinates of THIS doc; they are applied right-to-left so earlier
314
+ * offsets stay valid.
315
+ */
316
+ applyAll(changes) {
317
+ const sorted = [...changes].sort((a, b) => b.from - a.from);
318
+ let text = this.text;
319
+ for (const c of sorted) {
320
+ const { from, to, insert } = normalize(c, text.length);
321
+ text = text.slice(0, from) + insert + text.slice(to);
322
+ }
323
+ return new _TextDoc(text);
324
+ }
325
+ lineStarts() {
326
+ if (this._lineStarts) return this._lineStarts;
327
+ const starts = [0];
328
+ for (let i = 0; i < this.text.length; i++) {
329
+ if (this.text.charCodeAt(i) === 10) starts.push(i + 1);
330
+ }
331
+ this._lineStarts = starts;
332
+ return starts;
333
+ }
334
+ /** Total number of lines (a trailing newline yields an extra empty line). */
335
+ get lines() {
336
+ return this.lineStarts().length;
337
+ }
338
+ /** The line (1-based) containing `offset`. */
339
+ lineAt(offset) {
340
+ const off = clamp(offset, 0, this.text.length);
341
+ const starts = this.lineStarts();
342
+ let lo = 0;
343
+ let hi = starts.length - 1;
344
+ while (lo < hi) {
345
+ const mid = lo + hi + 1 >> 1;
346
+ if (starts[mid] <= off) lo = mid;
347
+ else hi = mid - 1;
348
+ }
349
+ const from = starts[lo];
350
+ const nextStart = starts[lo + 1];
351
+ const to = nextStart === void 0 ? this.text.length : nextStart - 1;
352
+ return { number: lo + 1, from, to, text: this.text.slice(from, to) };
353
+ }
354
+ /** Line/column (both 1-based) for an offset. */
355
+ positionAt(offset) {
356
+ const line = this.lineAt(offset);
357
+ return { line: line.number, column: clamp(offset, 0, this.text.length) - line.from + 1 };
358
+ }
359
+ /** Offset for a 1-based line/column. */
360
+ offsetAt(line, column) {
361
+ const starts = this.lineStarts();
362
+ const idx = clamp(line, 1, starts.length) - 1;
363
+ const from = starts[idx];
364
+ const nextStart = starts[idx + 1];
365
+ const to = nextStart === void 0 ? this.text.length : nextStart - 1;
366
+ return clamp(from + (column - 1), from, to);
367
+ }
368
+ /**
369
+ * Map an offset from this document's coordinates to the coordinates AFTER the
370
+ * given change(s). `assoc` controls which side of an insertion at the offset
371
+ * the mapped position sticks to: -1 = before (default), 1 = after.
372
+ */
373
+ mapOffset(offset, changes, assoc = -1) {
374
+ const list = Array.isArray(changes) ? changes : [changes];
375
+ const ordered = [...list].sort((a, b) => a.from - b.from);
376
+ let result = offset;
377
+ for (const c of ordered) {
378
+ const { from, to, insert } = normalize(c, Number.MAX_SAFE_INTEGER);
379
+ const delta = insert.length - (to - from);
380
+ if (result < from) continue;
381
+ if (result > to) {
382
+ result += delta;
383
+ } else if (result === from && assoc < 0) ; else if (result === to && assoc > 0) {
384
+ result += delta;
385
+ } else {
386
+ result = assoc < 0 ? from : from + insert.length;
387
+ }
388
+ }
389
+ return result;
390
+ }
391
+ toString() {
392
+ return this.text;
393
+ }
394
+ };
395
+ function normalize(change, len) {
396
+ let from = clamp(Math.min(change.from, change.to), 0, len);
397
+ let to = clamp(Math.max(change.from, change.to), 0, len);
398
+ return { from, to, insert: change.insert };
399
+ }
400
+ function clamp(n, lo, hi) {
401
+ return n < lo ? lo : n > hi ? hi : n;
402
+ }
403
+
404
+ // src/core/highlight.ts
405
+ function escapeHtml(value) {
406
+ let out = "";
407
+ for (let i = 0; i < value.length; i++) {
408
+ const ch = value.charCodeAt(i);
409
+ switch (ch) {
410
+ case 38:
411
+ out += "&amp;";
412
+ break;
413
+ case 60:
414
+ out += "&lt;";
415
+ break;
416
+ case 62:
417
+ out += "&gt;";
418
+ break;
419
+ case 34:
420
+ out += "&quot;";
421
+ break;
422
+ default:
423
+ out += value.charAt(i);
424
+ }
425
+ }
426
+ return out;
427
+ }
428
+ function span(kind, text) {
429
+ return `<span class="tw-tok-${kind}">${escapeHtml(text)}</span>`;
430
+ }
431
+ function isDigit(ch) {
432
+ return ch >= 48 && ch <= 57;
433
+ }
434
+ function isIdentStart(ch) {
435
+ return ch >= 65 && ch <= 90 || // A-Z
436
+ ch >= 97 && ch <= 122 || // a-z
437
+ ch === 95 || // _
438
+ ch === 36;
439
+ }
440
+ function isIdentPart(ch) {
441
+ return isIdentStart(ch) || isDigit(ch);
442
+ }
443
+ function isNumberPart(ch) {
444
+ return isDigit(ch) || ch === 46 || // .
445
+ ch === 95 || // _ separator
446
+ ch === 120 || // x
447
+ ch === 88 || // X
448
+ ch === 111 || // o
449
+ ch === 79 || // O
450
+ ch === 98 || // b
451
+ ch === 66 || // B
452
+ ch >= 97 && ch <= 102 || // a-f (hex + exponent 'e')
453
+ ch >= 65 && ch <= 70;
454
+ }
455
+ function isPunct(ch) {
456
+ switch (ch) {
457
+ case 123:
458
+ // {
459
+ case 125:
460
+ // }
461
+ case 40:
462
+ // (
463
+ case 41:
464
+ // )
465
+ case 91:
466
+ // [
467
+ case 93:
468
+ // ]
469
+ case 60:
470
+ // <
471
+ case 62:
472
+ // >
473
+ case 61:
474
+ // =
475
+ case 43:
476
+ // +
477
+ case 45:
478
+ // -
479
+ case 42:
480
+ // *
481
+ case 47:
482
+ // /
483
+ case 37:
484
+ // %
485
+ case 33:
486
+ // !
487
+ case 63:
488
+ // ?
489
+ case 58:
490
+ // :
491
+ case 59:
492
+ // ;
493
+ case 44:
494
+ // ,
495
+ case 46:
496
+ // .
497
+ case 38:
498
+ // &
499
+ case 124:
500
+ // |
501
+ case 94:
502
+ // ^
503
+ case 126:
504
+ // ~
505
+ case 64:
506
+ return true;
507
+ default:
508
+ return false;
509
+ }
510
+ }
511
+ function prevNonSpace(code, i) {
512
+ let k = i - 1;
513
+ while (k >= 0) {
514
+ const c = code.charCodeAt(k);
515
+ if (c === 32 || c === 9 || c === 10 || c === 13) {
516
+ k--;
517
+ continue;
518
+ }
519
+ return c;
520
+ }
521
+ return 0;
522
+ }
523
+ function consumeString(code, start, quote) {
524
+ const n = code.length;
525
+ let j = start + 1;
526
+ while (j < n) {
527
+ const c = code.charCodeAt(j);
528
+ if (c === 92) {
529
+ j += 2;
530
+ continue;
531
+ }
532
+ if (c === quote) {
533
+ return j + 1;
534
+ }
535
+ if (quote !== 96 && c === 10) {
536
+ return j;
537
+ }
538
+ j++;
539
+ }
540
+ return n;
541
+ }
542
+ var JS_KEYWORDS = /* @__PURE__ */ new Set([
543
+ "abstract",
544
+ "any",
545
+ "as",
546
+ "asserts",
547
+ "async",
548
+ "await",
549
+ "break",
550
+ "case",
551
+ "catch",
552
+ "class",
553
+ "const",
554
+ "continue",
555
+ "debugger",
556
+ "declare",
557
+ "default",
558
+ "delete",
559
+ "do",
560
+ "else",
561
+ "enum",
562
+ "export",
563
+ "extends",
564
+ "false",
565
+ "finally",
566
+ "for",
567
+ "from",
568
+ "function",
569
+ "get",
570
+ "if",
571
+ "implements",
572
+ "import",
573
+ "in",
574
+ "infer",
575
+ "instanceof",
576
+ "interface",
577
+ "is",
578
+ "keyof",
579
+ "let",
580
+ "namespace",
581
+ "new",
582
+ "null",
583
+ "of",
584
+ "override",
585
+ "package",
586
+ "private",
587
+ "protected",
588
+ "public",
589
+ "readonly",
590
+ "return",
591
+ "satisfies",
592
+ "set",
593
+ "static",
594
+ "super",
595
+ "switch",
596
+ "this",
597
+ "throw",
598
+ "true",
599
+ "try",
600
+ "type",
601
+ "typeof",
602
+ "undefined",
603
+ "var",
604
+ "void",
605
+ "while",
606
+ "with",
607
+ "yield"
608
+ ]);
609
+ var TS_TYPES = /* @__PURE__ */ new Set([
610
+ "string",
611
+ "number",
612
+ "boolean",
613
+ "object",
614
+ "symbol",
615
+ "bigint",
616
+ "unknown",
617
+ "never",
618
+ "Array",
619
+ "Record",
620
+ "Promise",
621
+ "Partial",
622
+ "Required",
623
+ "Readonly",
624
+ "Pick",
625
+ "Omit",
626
+ "Map",
627
+ "Set",
628
+ "WeakMap",
629
+ "WeakSet",
630
+ "Date",
631
+ "RegExp",
632
+ "Error"
633
+ ]);
634
+ var PY_KEYWORDS = /* @__PURE__ */ new Set([
635
+ "and",
636
+ "as",
637
+ "assert",
638
+ "async",
639
+ "await",
640
+ "break",
641
+ "case",
642
+ "class",
643
+ "continue",
644
+ "def",
645
+ "del",
646
+ "elif",
647
+ "else",
648
+ "except",
649
+ "False",
650
+ "finally",
651
+ "for",
652
+ "from",
653
+ "global",
654
+ "if",
655
+ "import",
656
+ "in",
657
+ "is",
658
+ "lambda",
659
+ "match",
660
+ "None",
661
+ "nonlocal",
662
+ "not",
663
+ "or",
664
+ "pass",
665
+ "raise",
666
+ "return",
667
+ "True",
668
+ "try",
669
+ "while",
670
+ "with",
671
+ "yield"
672
+ ]);
673
+ var BASH_KEYWORDS = /* @__PURE__ */ new Set([
674
+ "if",
675
+ "then",
676
+ "else",
677
+ "elif",
678
+ "fi",
679
+ "for",
680
+ "while",
681
+ "until",
682
+ "do",
683
+ "done",
684
+ "case",
685
+ "esac",
686
+ "in",
687
+ "function",
688
+ "select",
689
+ "time",
690
+ "return",
691
+ "break",
692
+ "continue",
693
+ "echo",
694
+ "cd",
695
+ "export",
696
+ "local",
697
+ "read",
698
+ "printf",
699
+ "source",
700
+ "exit",
701
+ "set",
702
+ "unset",
703
+ "test",
704
+ "eval",
705
+ "exec",
706
+ "trap",
707
+ "shift"
708
+ ]);
709
+ var SQL_KEYWORDS = /* @__PURE__ */ new Set([
710
+ "add",
711
+ "all",
712
+ "alter",
713
+ "and",
714
+ "as",
715
+ "asc",
716
+ "auto_increment",
717
+ "begin",
718
+ "between",
719
+ "by",
720
+ "case",
721
+ "column",
722
+ "commit",
723
+ "constraint",
724
+ "create",
725
+ "cross",
726
+ "default",
727
+ "delete",
728
+ "desc",
729
+ "distinct",
730
+ "drop",
731
+ "else",
732
+ "end",
733
+ "exists",
734
+ "foreign",
735
+ "from",
736
+ "full",
737
+ "group",
738
+ "having",
739
+ "if",
740
+ "in",
741
+ "index",
742
+ "inner",
743
+ "insert",
744
+ "into",
745
+ "is",
746
+ "join",
747
+ "key",
748
+ "left",
749
+ "like",
750
+ "limit",
751
+ "not",
752
+ "null",
753
+ "offset",
754
+ "on",
755
+ "or",
756
+ "order",
757
+ "outer",
758
+ "primary",
759
+ "references",
760
+ "right",
761
+ "rollback",
762
+ "select",
763
+ "set",
764
+ "table",
765
+ "then",
766
+ "union",
767
+ "unique",
768
+ "update",
769
+ "values",
770
+ "view",
771
+ "when",
772
+ "where",
773
+ "with",
774
+ // common types / functions
775
+ "int",
776
+ "integer",
777
+ "bigint",
778
+ "smallint",
779
+ "decimal",
780
+ "numeric",
781
+ "float",
782
+ "real",
783
+ "double",
784
+ "char",
785
+ "varchar",
786
+ "text",
787
+ "boolean",
788
+ "bool",
789
+ "date",
790
+ "datetime",
791
+ "timestamp",
792
+ "count",
793
+ "sum",
794
+ "avg",
795
+ "min",
796
+ "max",
797
+ "coalesce"
798
+ ]);
799
+ function highlightCLike(code) {
800
+ const n = code.length;
801
+ let out = "";
802
+ let i = 0;
803
+ let prevWord = "";
804
+ while (i < n) {
805
+ const ch = code.charCodeAt(i);
806
+ if (ch === 47 && code.charCodeAt(i + 1) === 47) {
807
+ let j = i + 2;
808
+ while (j < n && code.charCodeAt(j) !== 10) j++;
809
+ out += span("comment", code.slice(i, j));
810
+ i = j;
811
+ continue;
812
+ }
813
+ if (ch === 47 && code.charCodeAt(i + 1) === 42) {
814
+ let j = i + 2;
815
+ while (j < n && !(code.charCodeAt(j) === 42 && code.charCodeAt(j + 1) === 47)) {
816
+ j++;
817
+ }
818
+ j = Math.min(n, j + 2);
819
+ out += span("comment", code.slice(i, j));
820
+ i = j;
821
+ continue;
822
+ }
823
+ if (ch === 34 || ch === 39 || ch === 96) {
824
+ const end = consumeString(code, i, ch);
825
+ out += span("string", code.slice(i, end));
826
+ i = end;
827
+ continue;
828
+ }
829
+ if (isDigit(ch) || ch === 46 && isDigit(code.charCodeAt(i + 1))) {
830
+ let j = i + 1;
831
+ while (j < n && isNumberPart(code.charCodeAt(j))) j++;
832
+ out += span("number", code.slice(i, j));
833
+ i = j;
834
+ prevWord = "";
835
+ continue;
836
+ }
837
+ if (isIdentStart(ch)) {
838
+ let j = i + 1;
839
+ while (j < n && isIdentPart(code.charCodeAt(j))) j++;
840
+ const word = code.slice(i, j);
841
+ if (JS_KEYWORDS.has(word)) {
842
+ out += span("keyword", word);
843
+ } else if (TS_TYPES.has(word)) {
844
+ out += span("type", word);
845
+ } else {
846
+ let k = j;
847
+ while (k < n) {
848
+ const c = code.charCodeAt(k);
849
+ if (c === 32 || c === 9) {
850
+ k++;
851
+ continue;
852
+ }
853
+ break;
854
+ }
855
+ const isCall = code.charCodeAt(k) === 40;
856
+ if (prevNonSpace(code, i) === 46) {
857
+ out += span("prop", word);
858
+ } else if (prevWord === "class" || prevWord === "interface") {
859
+ out += span("type", word);
860
+ } else if (isCall || prevWord === "function") {
861
+ out += span("fn", word);
862
+ } else {
863
+ out += escapeHtml(word);
864
+ }
865
+ }
866
+ prevWord = word;
867
+ i = j;
868
+ continue;
869
+ }
870
+ if (isPunct(ch)) {
871
+ out += span("punct", code.charAt(i));
872
+ i++;
873
+ continue;
874
+ }
875
+ out += escapeHtml(code.charAt(i));
876
+ i++;
877
+ }
878
+ return out;
879
+ }
880
+ function highlightJson(code) {
881
+ const n = code.length;
882
+ let out = "";
883
+ let i = 0;
884
+ while (i < n) {
885
+ const ch = code.charCodeAt(i);
886
+ if (ch === 34) {
887
+ const end = consumeString(code, i, 34);
888
+ const text = code.slice(i, end);
889
+ let k = end;
890
+ while (k < n) {
891
+ const c = code.charCodeAt(k);
892
+ if (c === 32 || c === 9 || c === 10 || c === 13) {
893
+ k++;
894
+ continue;
895
+ }
896
+ break;
897
+ }
898
+ out += span(code.charCodeAt(k) === 58 ? "prop" : "string", text);
899
+ i = end;
900
+ continue;
901
+ }
902
+ if (isDigit(ch) || ch === 45 && isDigit(code.charCodeAt(i + 1))) {
903
+ let j = i + 1;
904
+ while (j < n && isNumberPart(code.charCodeAt(j))) j++;
905
+ out += span("number", code.slice(i, j));
906
+ i = j;
907
+ continue;
908
+ }
909
+ if (isIdentStart(ch)) {
910
+ let j = i + 1;
911
+ while (j < n && isIdentPart(code.charCodeAt(j))) j++;
912
+ const word = code.slice(i, j);
913
+ if (word === "true" || word === "false" || word === "null") {
914
+ out += span("keyword", word);
915
+ } else {
916
+ out += escapeHtml(word);
917
+ }
918
+ i = j;
919
+ continue;
920
+ }
921
+ if (isPunct(ch)) {
922
+ out += span("punct", code.charAt(i));
923
+ i++;
924
+ continue;
925
+ }
926
+ out += escapeHtml(code.charAt(i));
927
+ i++;
928
+ }
929
+ return out;
930
+ }
931
+ function highlightCss(code) {
932
+ const n = code.length;
933
+ let out = "";
934
+ let i = 0;
935
+ let depth = 0;
936
+ let beforeColon = true;
937
+ while (i < n) {
938
+ const ch = code.charCodeAt(i);
939
+ if (ch === 47 && code.charCodeAt(i + 1) === 42) {
940
+ let j = i + 2;
941
+ while (j < n && !(code.charCodeAt(j) === 42 && code.charCodeAt(j + 1) === 47)) {
942
+ j++;
943
+ }
944
+ j = Math.min(n, j + 2);
945
+ out += span("comment", code.slice(i, j));
946
+ i = j;
947
+ continue;
948
+ }
949
+ if (ch === 34 || ch === 39) {
950
+ const end = consumeString(code, i, ch);
951
+ out += span("string", code.slice(i, end));
952
+ i = end;
953
+ continue;
954
+ }
955
+ if (ch === 64) {
956
+ let j = i + 1;
957
+ while (j < n && isIdentPart(code.charCodeAt(j))) j++;
958
+ out += span("keyword", code.slice(i, j));
959
+ i = j;
960
+ continue;
961
+ }
962
+ if (ch === 123) {
963
+ out += span("punct", "{");
964
+ depth++;
965
+ beforeColon = true;
966
+ i++;
967
+ continue;
968
+ }
969
+ if (ch === 125) {
970
+ out += span("punct", "}");
971
+ if (depth > 0) depth--;
972
+ beforeColon = true;
973
+ i++;
974
+ continue;
975
+ }
976
+ if (ch === 59) {
977
+ out += span("punct", ";");
978
+ beforeColon = true;
979
+ i++;
980
+ continue;
981
+ }
982
+ if (ch === 58) {
983
+ out += span("punct", ":");
984
+ beforeColon = false;
985
+ i++;
986
+ continue;
987
+ }
988
+ if (isDigit(ch) || ch === 46 && isDigit(code.charCodeAt(i + 1))) {
989
+ let j = i + 1;
990
+ while (j < n && isNumberPart(code.charCodeAt(j))) j++;
991
+ out += span("number", code.slice(i, j));
992
+ i = j;
993
+ continue;
994
+ }
995
+ if (isIdentStart(ch) || ch === 45) {
996
+ let j = i + 1;
997
+ while (j < n && (isIdentPart(code.charCodeAt(j)) || code.charCodeAt(j) === 45)) {
998
+ j++;
999
+ }
1000
+ const word = code.slice(i, j);
1001
+ if (depth > 0 && beforeColon) {
1002
+ out += span("prop", word);
1003
+ } else {
1004
+ out += escapeHtml(word);
1005
+ }
1006
+ i = j;
1007
+ continue;
1008
+ }
1009
+ if (isPunct(ch)) {
1010
+ out += span("punct", code.charAt(i));
1011
+ i++;
1012
+ continue;
1013
+ }
1014
+ out += escapeHtml(code.charAt(i));
1015
+ i++;
1016
+ }
1017
+ return out;
1018
+ }
1019
+ function isTagChar(ch) {
1020
+ return isIdentPart(ch) || ch === 45 || ch === 58;
1021
+ }
1022
+ function highlightHtml(code) {
1023
+ const n = code.length;
1024
+ let out = "";
1025
+ let i = 0;
1026
+ while (i < n) {
1027
+ const ch = code.charCodeAt(i);
1028
+ if (ch === 60 && code.startsWith("<!--", i)) {
1029
+ const idx = code.indexOf("-->", i + 4);
1030
+ const j = idx === -1 ? n : idx + 3;
1031
+ out += span("comment", code.slice(i, j));
1032
+ i = j;
1033
+ continue;
1034
+ }
1035
+ if (ch === 60) {
1036
+ let j = i + 1;
1037
+ if (code.charCodeAt(j) === 47) j++;
1038
+ out += span("punct", code.slice(i, j));
1039
+ const nameStart = j;
1040
+ while (j < n && isTagChar(code.charCodeAt(j))) j++;
1041
+ if (j > nameStart) out += span("keyword", code.slice(nameStart, j));
1042
+ while (j < n && code.charCodeAt(j) !== 62) {
1043
+ const c = code.charCodeAt(j);
1044
+ if (c === 34 || c === 39) {
1045
+ const end = consumeString(code, j, c);
1046
+ out += span("string", code.slice(j, end));
1047
+ j = end;
1048
+ continue;
1049
+ }
1050
+ if (c === 61) {
1051
+ out += span("punct", "=");
1052
+ j++;
1053
+ continue;
1054
+ }
1055
+ if (isTagChar(c)) {
1056
+ const a = j;
1057
+ while (j < n && isTagChar(code.charCodeAt(j))) j++;
1058
+ out += span("prop", code.slice(a, j));
1059
+ continue;
1060
+ }
1061
+ out += escapeHtml(code.charAt(j));
1062
+ j++;
1063
+ }
1064
+ if (j < n && code.charCodeAt(j) === 62) {
1065
+ out += span("punct", ">");
1066
+ j++;
1067
+ }
1068
+ i = j;
1069
+ continue;
1070
+ }
1071
+ if (ch === 38) {
1072
+ let j = i + 1;
1073
+ while (j < n && j - i < 12 && code.charCodeAt(j) !== 59 && (isIdentPart(code.charCodeAt(j)) || code.charCodeAt(j) === 35)) {
1074
+ j++;
1075
+ }
1076
+ if (j < n && code.charCodeAt(j) === 59) {
1077
+ out += span("type", code.slice(i, j + 1));
1078
+ i = j + 1;
1079
+ continue;
1080
+ }
1081
+ }
1082
+ out += escapeHtml(code.charAt(i));
1083
+ i++;
1084
+ }
1085
+ return out;
1086
+ }
1087
+ function highlightMarkdownLine(line) {
1088
+ const n = line.length;
1089
+ let out = "";
1090
+ let i = 0;
1091
+ while (i < n && (line.charCodeAt(i) === 32 || line.charCodeAt(i) === 9)) {
1092
+ out += line.charAt(i);
1093
+ i++;
1094
+ }
1095
+ if (line.charCodeAt(i) === 35) {
1096
+ let h = i;
1097
+ while (h < n && line.charCodeAt(h) === 35) h++;
1098
+ if (h - i <= 6 && (h >= n || line.charCodeAt(h) === 32)) {
1099
+ out += span("keyword", line.slice(i, h));
1100
+ i = h;
1101
+ }
1102
+ } else if (line.charCodeAt(i) === 62) {
1103
+ out += span("keyword", ">");
1104
+ i++;
1105
+ } else {
1106
+ const c = line.charCodeAt(i);
1107
+ if ((c === 45 || c === 43 || c === 42) && line.charCodeAt(i + 1) === 32) {
1108
+ out += span("punct", line.charAt(i));
1109
+ i++;
1110
+ }
1111
+ }
1112
+ while (i < n) {
1113
+ const ch = line.charCodeAt(i);
1114
+ if (ch === 96) {
1115
+ let j = i + 1;
1116
+ while (j < n && line.charCodeAt(j) !== 96) j++;
1117
+ j = Math.min(n, j + 1);
1118
+ out += span("string", line.slice(i, j));
1119
+ i = j;
1120
+ continue;
1121
+ }
1122
+ if (ch === 42 || ch === 95 || ch === 126) {
1123
+ let j = i;
1124
+ while (j < n && line.charCodeAt(j) === ch) j++;
1125
+ out += span("punct", line.slice(i, j));
1126
+ i = j;
1127
+ continue;
1128
+ }
1129
+ if (ch === 91 || ch === 93 || ch === 40 || ch === 41) {
1130
+ out += span("punct", line.charAt(i));
1131
+ i++;
1132
+ continue;
1133
+ }
1134
+ out += escapeHtml(line.charAt(i));
1135
+ i++;
1136
+ }
1137
+ return out;
1138
+ }
1139
+ function highlightMarkdown(code) {
1140
+ const lines = code.split("\n");
1141
+ let out = "";
1142
+ for (let i = 0; i < lines.length; i++) {
1143
+ if (i > 0) out += "\n";
1144
+ out += highlightMarkdownLine(lines[i] ?? "");
1145
+ }
1146
+ return out;
1147
+ }
1148
+ function highlightPython(code) {
1149
+ const n = code.length;
1150
+ let out = "";
1151
+ let i = 0;
1152
+ let prevWord = "";
1153
+ while (i < n) {
1154
+ const ch = code.charCodeAt(i);
1155
+ if (ch === 35) {
1156
+ let j = i + 1;
1157
+ while (j < n && code.charCodeAt(j) !== 10) j++;
1158
+ out += span("comment", code.slice(i, j));
1159
+ i = j;
1160
+ continue;
1161
+ }
1162
+ if ((ch === 34 || ch === 39) && code.charCodeAt(i + 1) === ch && code.charCodeAt(i + 2) === ch) {
1163
+ const marker = code.slice(i, i + 3);
1164
+ const idx = code.indexOf(marker, i + 3);
1165
+ const j = idx === -1 ? n : idx + 3;
1166
+ out += span("string", code.slice(i, j));
1167
+ i = j;
1168
+ prevWord = "";
1169
+ continue;
1170
+ }
1171
+ if (ch === 34 || ch === 39) {
1172
+ const end = consumeString(code, i, ch);
1173
+ out += span("string", code.slice(i, end));
1174
+ i = end;
1175
+ prevWord = "";
1176
+ continue;
1177
+ }
1178
+ if (ch === 64 && isIdentStart(code.charCodeAt(i + 1))) {
1179
+ let j = i + 1;
1180
+ while (j < n && isIdentPart(code.charCodeAt(j))) j++;
1181
+ out += span("keyword", code.slice(i, j));
1182
+ i = j;
1183
+ continue;
1184
+ }
1185
+ if (isDigit(ch) || ch === 46 && isDigit(code.charCodeAt(i + 1))) {
1186
+ let j = i + 1;
1187
+ while (j < n && isNumberPart(code.charCodeAt(j))) j++;
1188
+ out += span("number", code.slice(i, j));
1189
+ i = j;
1190
+ prevWord = "";
1191
+ continue;
1192
+ }
1193
+ if (isIdentStart(ch)) {
1194
+ let j = i + 1;
1195
+ while (j < n && isIdentPart(code.charCodeAt(j))) j++;
1196
+ const word = code.slice(i, j);
1197
+ if (PY_KEYWORDS.has(word)) {
1198
+ out += span("keyword", word);
1199
+ } else if (prevWord === "def") {
1200
+ out += span("fn", word);
1201
+ } else if (prevWord === "class") {
1202
+ out += span("type", word);
1203
+ } else {
1204
+ let k = j;
1205
+ while (k < n && (code.charCodeAt(k) === 32 || code.charCodeAt(k) === 9))
1206
+ k++;
1207
+ out += code.charCodeAt(k) === 40 ? span("fn", word) : escapeHtml(word);
1208
+ }
1209
+ prevWord = word;
1210
+ i = j;
1211
+ continue;
1212
+ }
1213
+ if (isPunct(ch)) {
1214
+ out += span("punct", code.charAt(i));
1215
+ i++;
1216
+ continue;
1217
+ }
1218
+ out += escapeHtml(code.charAt(i));
1219
+ i++;
1220
+ }
1221
+ return out;
1222
+ }
1223
+ function highlightBash(code) {
1224
+ const n = code.length;
1225
+ let out = "";
1226
+ let i = 0;
1227
+ while (i < n) {
1228
+ const ch = code.charCodeAt(i);
1229
+ if (ch === 35) {
1230
+ const prev = i > 0 ? code.charCodeAt(i - 1) : 10;
1231
+ if (i === 0 || prev === 32 || prev === 9 || prev === 10 || prev === 13 || prev === 59) {
1232
+ let j = i + 1;
1233
+ while (j < n && code.charCodeAt(j) !== 10) j++;
1234
+ out += span("comment", code.slice(i, j));
1235
+ i = j;
1236
+ continue;
1237
+ }
1238
+ }
1239
+ if (ch === 34 || ch === 39) {
1240
+ const end = consumeString(code, i, ch);
1241
+ out += span("string", code.slice(i, end));
1242
+ i = end;
1243
+ continue;
1244
+ }
1245
+ if (ch === 36) {
1246
+ let j = i + 1;
1247
+ if (code.charCodeAt(j) === 123) {
1248
+ while (j < n && code.charCodeAt(j) !== 125) j++;
1249
+ j = Math.min(n, j + 1);
1250
+ } else {
1251
+ while (j < n && isIdentPart(code.charCodeAt(j))) j++;
1252
+ }
1253
+ out += span("prop", code.slice(i, j));
1254
+ i = j;
1255
+ continue;
1256
+ }
1257
+ if (isDigit(ch)) {
1258
+ let j = i + 1;
1259
+ while (j < n && isNumberPart(code.charCodeAt(j))) j++;
1260
+ out += span("number", code.slice(i, j));
1261
+ i = j;
1262
+ continue;
1263
+ }
1264
+ if (isIdentStart(ch)) {
1265
+ let j = i + 1;
1266
+ while (j < n && isIdentPart(code.charCodeAt(j))) j++;
1267
+ const word = code.slice(i, j);
1268
+ out += BASH_KEYWORDS.has(word) ? span("keyword", word) : escapeHtml(word);
1269
+ i = j;
1270
+ continue;
1271
+ }
1272
+ if (isPunct(ch)) {
1273
+ out += span("punct", code.charAt(i));
1274
+ i++;
1275
+ continue;
1276
+ }
1277
+ out += escapeHtml(code.charAt(i));
1278
+ i++;
1279
+ }
1280
+ return out;
1281
+ }
1282
+ function highlightSql(code) {
1283
+ const n = code.length;
1284
+ let out = "";
1285
+ let i = 0;
1286
+ while (i < n) {
1287
+ const ch = code.charCodeAt(i);
1288
+ if (ch === 45 && code.charCodeAt(i + 1) === 45) {
1289
+ let j = i + 2;
1290
+ while (j < n && code.charCodeAt(j) !== 10) j++;
1291
+ out += span("comment", code.slice(i, j));
1292
+ i = j;
1293
+ continue;
1294
+ }
1295
+ if (ch === 47 && code.charCodeAt(i + 1) === 42) {
1296
+ let j = i + 2;
1297
+ while (j < n && !(code.charCodeAt(j) === 42 && code.charCodeAt(j + 1) === 47)) {
1298
+ j++;
1299
+ }
1300
+ j = Math.min(n, j + 2);
1301
+ out += span("comment", code.slice(i, j));
1302
+ i = j;
1303
+ continue;
1304
+ }
1305
+ if (ch === 39 || ch === 34) {
1306
+ const end = consumeString(code, i, ch);
1307
+ out += span("string", code.slice(i, end));
1308
+ i = end;
1309
+ continue;
1310
+ }
1311
+ if (isDigit(ch) || ch === 46 && isDigit(code.charCodeAt(i + 1))) {
1312
+ let j = i + 1;
1313
+ while (j < n && isNumberPart(code.charCodeAt(j))) j++;
1314
+ out += span("number", code.slice(i, j));
1315
+ i = j;
1316
+ continue;
1317
+ }
1318
+ if (isIdentStart(ch)) {
1319
+ let j = i + 1;
1320
+ while (j < n && isIdentPart(code.charCodeAt(j))) j++;
1321
+ const word = code.slice(i, j);
1322
+ out += SQL_KEYWORDS.has(word.toLowerCase()) ? span("keyword", word) : escapeHtml(word);
1323
+ i = j;
1324
+ continue;
1325
+ }
1326
+ if (isPunct(ch)) {
1327
+ out += span("punct", code.charAt(i));
1328
+ i++;
1329
+ continue;
1330
+ }
1331
+ out += escapeHtml(code.charAt(i));
1332
+ i++;
1333
+ }
1334
+ return out;
1335
+ }
1336
+ var ALIASES = {
1337
+ js: "javascript",
1338
+ jsx: "javascript",
1339
+ javascript: "javascript",
1340
+ mjs: "javascript",
1341
+ cjs: "javascript",
1342
+ ts: "typescript",
1343
+ tsx: "typescript",
1344
+ typescript: "typescript",
1345
+ json: "json",
1346
+ jsonc: "json",
1347
+ json5: "json",
1348
+ css: "css",
1349
+ html: "html",
1350
+ htm: "html",
1351
+ xml: "html",
1352
+ md: "markdown",
1353
+ markdown: "markdown",
1354
+ py: "python",
1355
+ python: "python",
1356
+ sh: "bash",
1357
+ bash: "bash",
1358
+ shell: "bash",
1359
+ zsh: "bash",
1360
+ sql: "sql"
1361
+ };
1362
+ var TOKENIZERS = {
1363
+ javascript: highlightCLike,
1364
+ typescript: highlightCLike,
1365
+ json: highlightJson,
1366
+ css: highlightCss,
1367
+ html: highlightHtml,
1368
+ markdown: highlightMarkdown,
1369
+ python: highlightPython,
1370
+ bash: highlightBash,
1371
+ sql: highlightSql
1372
+ };
1373
+ function highlightToHtml(lang, code) {
1374
+ const info = typeof lang === "string" ? lang : "";
1375
+ const first = info.trim().split(/\s+/)[0] ?? "";
1376
+ const key = first.toLowerCase();
1377
+ const resolved = ALIASES[key] ?? key;
1378
+ const tokenizer = TOKENIZERS[resolved];
1379
+ if (!tokenizer) return escapeHtml(code);
1380
+ return tokenizer(code);
1381
+ }
1382
+
1383
+ // src/core/comments.ts
1384
+ var MAPPER = new TextDoc();
1385
+ var ASSOC_FROM = 1;
1386
+ var ASSOC_TO = 1;
1387
+ function mapAnchor(anchor, change) {
1388
+ const from = MAPPER.mapOffset(anchor.from, change, ASSOC_FROM);
1389
+ const to = MAPPER.mapOffset(anchor.to, change, ASSOC_TO);
1390
+ const collapsed = from === to;
1391
+ const deletedWholeRange = change.to > change.from && change.from <= anchor.from && change.to >= anchor.to;
1392
+ if (collapsed && deletedWholeRange) return null;
1393
+ return { from: Math.min(from, to), to: Math.max(from, to) };
1394
+ }
1395
+
1396
+ // src/core/table.ts
1397
+ var clampInt = (n, lo, hi) => n < lo ? lo : n > hi ? hi : n;
1398
+ function delimCell(align) {
1399
+ switch (align) {
1400
+ case "left":
1401
+ return ":---";
1402
+ case "center":
1403
+ return ":---:";
1404
+ case "right":
1405
+ return "---:";
1406
+ default:
1407
+ return "---";
1408
+ }
1409
+ }
1410
+ var cellText = (text, cell) => text.slice(cell.from, cell.to);
1411
+ var emptyRow = (ncols) => Array.from({ length: ncols }, () => "");
1412
+ function tableToGrid(text, table) {
1413
+ const ncols = Math.max(1, table.header.length);
1414
+ const header = table.header.map((c) => cellText(text, c));
1415
+ while (header.length < ncols) header.push("");
1416
+ const align = [];
1417
+ for (let i = 0; i < ncols; i++) align.push(table.align[i] ?? null);
1418
+ const rows = table.rows.map((row) => {
1419
+ const cells = row.map((c) => cellText(text, c));
1420
+ while (cells.length < ncols) cells.push("");
1421
+ cells.length = ncols;
1422
+ return cells;
1423
+ });
1424
+ return { header, align, rows };
1425
+ }
1426
+ function cellsForLine(grid, lineIdx) {
1427
+ const ncols = grid.header.length;
1428
+ if (lineIdx === 0) return grid.header;
1429
+ if (lineIdx === 1) {
1430
+ const a = [];
1431
+ for (let i = 0; i < ncols; i++) a.push(delimCell(grid.align[i] ?? null));
1432
+ return a;
1433
+ }
1434
+ return grid.rows[lineIdx - 2] ?? grid.header;
1435
+ }
1436
+ function gridLines(grid) {
1437
+ const ncols = grid.header.length;
1438
+ const rowLine = (cells) => {
1439
+ const out = cells.slice(0, ncols);
1440
+ while (out.length < ncols) out.push("");
1441
+ return `| ${out.join(" | ")} |`;
1442
+ };
1443
+ const delim = [];
1444
+ for (let i = 0; i < ncols; i++) delim.push(delimCell(grid.align[i] ?? null));
1445
+ const lines = [rowLine(grid.header), `| ${delim.join(" | ")} |`];
1446
+ for (const r of grid.rows) lines.push(rowLine(r));
1447
+ return lines;
1448
+ }
1449
+ function lineStart(lines, lineIdx) {
1450
+ let off = 0;
1451
+ for (const l of lines.slice(0, lineIdx)) off += l.length + 1;
1452
+ return off;
1453
+ }
1454
+ function colOffsetInLine(cells, col) {
1455
+ let off = 2;
1456
+ for (const c of cells.slice(0, col)) off += c.length + 3;
1457
+ return off;
1458
+ }
1459
+ function commit(text, table, grid, lineIdx, col) {
1460
+ const lines = gridLines(grid);
1461
+ const block = lines.join("\n");
1462
+ const inBlock = lineStart(lines, lineIdx) + colOffsetInLine(cellsForLine(grid, lineIdx), col);
1463
+ const newText = text.slice(0, table.from) + block + text.slice(table.to);
1464
+ return { text: newText, selection: table.from + inBlock };
1465
+ }
1466
+ function cellSourceRange(table, row, col) {
1467
+ const cell = row === 0 ? table.header[col] : table.rows[row - 1]?.[col];
1468
+ if (!cell) return null;
1469
+ return { from: cell.from, to: cell.to };
1470
+ }
1471
+ function addRow(text, table, atRow) {
1472
+ const grid = tableToGrid(text, table);
1473
+ const bodyIdx = clampInt(atRow - 1, 0, grid.rows.length);
1474
+ grid.rows.splice(bodyIdx, 0, emptyRow(grid.header.length));
1475
+ return commit(text, table, grid, 2 + bodyIdx, 0);
1476
+ }
1477
+ function addColumn(text, table, atCol) {
1478
+ const grid = tableToGrid(text, table);
1479
+ const idx = clampInt(atCol, 0, grid.header.length);
1480
+ grid.header.splice(idx, 0, "");
1481
+ grid.align.splice(idx, 0, null);
1482
+ for (const r of grid.rows) r.splice(idx, 0, "");
1483
+ return commit(text, table, grid, 0, idx);
1484
+ }
1485
+ function removeRow(text, table, atRow) {
1486
+ const grid = tableToGrid(text, table);
1487
+ const bodyIdx = atRow - 1;
1488
+ if (bodyIdx >= 0 && bodyIdx < grid.rows.length) grid.rows.splice(bodyIdx, 1);
1489
+ const lineIdx = grid.rows.length === 0 ? 0 : 2 + clampInt(bodyIdx, 0, grid.rows.length - 1);
1490
+ return commit(text, table, grid, lineIdx, 0);
1491
+ }
1492
+ function removeColumn(text, table, atCol) {
1493
+ const grid = tableToGrid(text, table);
1494
+ if (grid.header.length > 1 && atCol >= 0 && atCol < grid.header.length) {
1495
+ grid.header.splice(atCol, 1);
1496
+ grid.align.splice(atCol, 1);
1497
+ for (const r of grid.rows) r.splice(atCol, 1);
1498
+ }
1499
+ const caretCol = clampInt(atCol, 0, grid.header.length - 1);
1500
+ return commit(text, table, grid, 0, caretCol);
1501
+ }
1502
+ function setAlignment(text, table, col, align) {
1503
+ const grid = tableToGrid(text, table);
1504
+ if (col >= 0 && col < grid.align.length) grid.align[col] = align;
1505
+ const caretCol = clampInt(col, 0, grid.align.length - 1);
1506
+ return commit(text, table, grid, 1, caretCol);
1507
+ }
1508
+
1509
+ // src/core/index.ts
1510
+ var EditorView = class {
1511
+ dom;
1512
+ constructor(options) {
1513
+ this.dom = options.parent;
1514
+ throw new Error(
1515
+ "typewright/core: engine not yet implemented (pre-alpha scaffold). See SPEC.md for the architecture and roadmap."
1516
+ );
1517
+ }
1518
+ /** Current document string. */
1519
+ get doc() {
1520
+ return "";
1521
+ }
1522
+ /** Apply an edit. */
1523
+ dispatch(_change) {
1524
+ }
1525
+ setSelection(_selection) {
1526
+ }
1527
+ destroy() {
1528
+ }
1529
+ };
1530
+
1531
+ export { COMMANDS, EditorView, TextDoc, activeBlockIndex, addColumn, addRow, applyCommand, cellSourceRange, collectMarkers, headingFoldRanges, hiddenMarkers, highlightToHtml, mapAnchor, removeColumn, removeRow, setAlignment };
1532
+ //# sourceMappingURL=chunk-CZQO7TTL.js.map
1533
+ //# sourceMappingURL=chunk-CZQO7TTL.js.map