@crewlethq/ui 0.29.0 → 0.31.0

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 (51) hide show
  1. package/README.md +28 -3
  2. package/dist/ArtifactBar/ArtifactBar.d.ts +13 -1
  3. package/dist/ArtifactBar/index.js +1 -1
  4. package/dist/{ArtifactBar-IBWB5POL.css → ArtifactBar-MLMJHWY6.css} +7 -0
  5. package/dist/ArtifactCover/index.js +2 -2
  6. package/dist/CommentThread/index.js +2 -2
  7. package/dist/DataView/index.js +2 -2
  8. package/dist/Document/Document.d.ts +8 -1
  9. package/dist/Document/index.js +1 -1
  10. package/dist/{Document-PQGXJHB7.css → Document-G3YTZIUL.css} +71 -0
  11. package/dist/EditingStatus/EditingStatus.d.ts +25 -0
  12. package/dist/EditingStatus/index.d.ts +3 -0
  13. package/dist/EditingStatus/index.js +2 -0
  14. package/dist/EditingStatus-NFADEPSX.css +53 -0
  15. package/dist/Editor-YZ7KG2RD.js +2099 -0
  16. package/dist/Markdown/grammar.d.ts +170 -0
  17. package/dist/Markdown/index.d.ts +2 -0
  18. package/dist/Markdown/index.js +1 -0
  19. package/dist/RichEditor/Editor.d.ts +17 -0
  20. package/dist/RichEditor/RichEditor.d.ts +26 -0
  21. package/dist/RichEditor/codec.d.ts +78 -0
  22. package/dist/RichEditor/commands.d.ts +89 -0
  23. package/dist/RichEditor/index.d.ts +4 -0
  24. package/dist/RichEditor/index.js +8 -0
  25. package/dist/RichEditor/keys.d.ts +16 -0
  26. package/dist/RichEditor/nodeviews.d.ts +60 -0
  27. package/dist/RichEditor/paste.d.ts +47 -0
  28. package/dist/RichEditor/plugins.d.ts +49 -0
  29. package/dist/RichEditor/roundtrip.d.ts +14 -0
  30. package/dist/RichEditor/schema.d.ts +23 -0
  31. package/dist/RichEditor/types.d.ts +140 -0
  32. package/dist/RichEditor-NPD2KAPS.css +419 -0
  33. package/dist/RichEditorMarkdown/index.d.ts +1 -0
  34. package/dist/RichEditorMarkdown/index.js +3 -0
  35. package/dist/chunk-3DPIU2Q7.js +28 -0
  36. package/dist/{chunk-XALUCIG5.js → chunk-6AH2XJ3Q.js} +1 -1
  37. package/dist/chunk-A4E5YLXO.js +85 -0
  38. package/dist/{chunk-FKULOLKG.js → chunk-GR55WT4R.js} +1 -1
  39. package/dist/chunk-IDBHX5SR.js +12 -0
  40. package/dist/{chunk-WI6K5M5X.js → chunk-M3LUNN7F.js} +1 -1
  41. package/dist/{chunk-QMBP23BL.js → chunk-P4BOXB6E.js} +17 -1
  42. package/dist/chunk-SKOYC2CF.js +288 -0
  43. package/dist/chunk-VOX3YRFO.js +76 -0
  44. package/dist/chunk-YFW4MTK4.js +749 -0
  45. package/dist/generated/index.d.ts +4 -0
  46. package/dist/generated/index.js +50 -44
  47. package/dist/index.js +50 -44
  48. package/dist/styles.css +558 -2
  49. package/package.json +13 -3
  50. package/dist/{chunk-IFNQKWUO.js → chunk-OC46246T.js} +0 -0
  51. package/dist/{chunk-RODMM35O.js → chunk-UVJ5FF5V.js} +1 -1
@@ -0,0 +1,749 @@
1
+ import { MARKDOWN_CALLOUT_TONES, parseMarkdownSpans, markdownInline, markdownCodeText } from './chunk-SKOYC2CF.js';
2
+ import { Schema, Fragment } from 'prosemirror-model';
3
+
4
+ function headingTag(level) {
5
+ return `h${Math.min(6, level + 1)}`;
6
+ }
7
+ function alignOf(value) {
8
+ return value === "center" || value === "right" ? value : "left";
9
+ }
10
+ function toneOf(value) {
11
+ return MARKDOWN_CALLOUT_TONES.includes(value) ? value : "note";
12
+ }
13
+ var cell = (tag) => ({
14
+ content: "(text | image)*",
15
+ marks: "_",
16
+ attrs: { align: { default: "left" } },
17
+ isolating: true,
18
+ parseDOM: [{ tag, getAttrs: (dom) => ({ align: alignOf(dom.getAttribute("data-align") ?? dom.style.textAlign) }) }],
19
+ toDOM: (node) => [tag, { "data-align": node.attrs.align }, 0]
20
+ });
21
+ var schema = new Schema({
22
+ nodes: {
23
+ doc: { content: "block+" },
24
+ paragraph: {
25
+ content: "inline*",
26
+ group: "block item_first item_rest",
27
+ parseDOM: [{ tag: "p" }],
28
+ toDOM: () => ["p", 0]
29
+ },
30
+ heading: {
31
+ attrs: { level: { default: 1 } },
32
+ // A heading is one line of Markdown, so it holds no line break.
33
+ content: "(text | image)*",
34
+ group: "block item_first",
35
+ defining: true,
36
+ // THE ELEMENT IS ONE LEVEL DOWN from the Markdown (a `#` is an `h2`), so
37
+ // the level it was written at travels in `data-level`, and a heading
38
+ // copied out of an editor reads back at the level it had. Pasted from
39
+ // anywhere else, an `h2` is a second level heading.
40
+ parseDOM: [1, 2, 3, 4, 5, 6].map((level) => ({
41
+ tag: `h${level}`,
42
+ getAttrs: (dom) => {
43
+ const written = Number(dom.getAttribute("data-level"));
44
+ return { level: written >= 1 && written <= 6 ? written : level };
45
+ }
46
+ })),
47
+ toDOM: (node) => [headingTag(node.attrs.level), { "data-level": String(node.attrs.level) }, 0]
48
+ },
49
+ code_block: {
50
+ attrs: { lang: { default: "" }, fence: { default: "```" } },
51
+ content: "text*",
52
+ marks: "",
53
+ group: "block",
54
+ code: true,
55
+ defining: true,
56
+ parseDOM: [
57
+ {
58
+ tag: "pre",
59
+ preserveWhitespace: "full",
60
+ getAttrs: (dom) => ({
61
+ lang: (dom.getAttribute("data-lang") ?? languageOfClass(dom.querySelector("code")?.className ?? "")).trim()
62
+ })
63
+ }
64
+ ],
65
+ toDOM: (node) => [
66
+ "pre",
67
+ { class: "md-code", ...node.attrs.lang ? { "data-lang": node.attrs.lang } : {} },
68
+ ["code", 0]
69
+ ]
70
+ },
71
+ blockquote: {
72
+ content: "block+",
73
+ group: "block item_first item_rest",
74
+ defining: true,
75
+ parseDOM: [{ tag: "blockquote" }],
76
+ toDOM: () => ["blockquote", 0]
77
+ },
78
+ callout: {
79
+ attrs: { tone: { default: "note" } },
80
+ content: "block+",
81
+ group: "block item_first item_rest",
82
+ defining: true,
83
+ parseDOM: [
84
+ {
85
+ tag: "div[data-callout]",
86
+ contentElement: "[data-callout-body]",
87
+ getAttrs: (dom) => ({ tone: toneOf(dom.getAttribute("data-callout")) })
88
+ }
89
+ ],
90
+ toDOM: (node) => [
91
+ "div",
92
+ { "data-callout": node.attrs.tone, role: "note" },
93
+ ["div", { "data-callout-body": "" }, 0]
94
+ ]
95
+ },
96
+ horizontal_rule: {
97
+ group: "block item_first item_rest",
98
+ parseDOM: [{ tag: "hr" }],
99
+ toDOM: () => ["hr"]
100
+ },
101
+ bullet_list: {
102
+ attrs: { marker: { default: "-" }, loose: { default: false } },
103
+ content: "list_item+",
104
+ group: "block item_first item_rest",
105
+ parseDOM: [{ tag: "ul" }],
106
+ toDOM: () => ["ul", 0]
107
+ },
108
+ ordered_list: {
109
+ attrs: { start: { default: 1 }, marker: { default: "." }, loose: { default: false } },
110
+ content: "list_item+",
111
+ group: "block item_first item_rest",
112
+ parseDOM: [
113
+ {
114
+ tag: "ol",
115
+ getAttrs: (dom) => ({ start: dom.hasAttribute("start") ? Number(dom.getAttribute("start")) || 1 : 1 })
116
+ }
117
+ ],
118
+ toDOM: (node) => ["ol", node.attrs.start === 1 ? {} : { start: node.attrs.start }, 0]
119
+ },
120
+ list_item: {
121
+ // null is a plain item; true and false are a task item, ticked or not.
122
+ attrs: { checked: { default: null } },
123
+ // WHAT AN ITEM CAN HOLD AND STILL BE WRITTEN BACK: the grammar reads an
124
+ // item's later blocks from indented lines, and an indented fence or
125
+ // heading is a paragraph to it. A heading is kept on the marker line;
126
+ // a code block is never inside an item.
127
+ content: "item_first item_rest*",
128
+ defining: true,
129
+ parseDOM: [
130
+ {
131
+ tag: "li",
132
+ getAttrs: (dom) => {
133
+ const box = dom.querySelector(':scope > input[type="checkbox"], :scope > p > input[type="checkbox"]');
134
+ return { checked: box ? box.checked || box.hasAttribute("checked") : null };
135
+ }
136
+ }
137
+ ],
138
+ toDOM: (node) => node.attrs.checked === null ? ["li", 0] : [
139
+ "li",
140
+ ["input", { type: "checkbox", disabled: "", ...node.attrs.checked ? { checked: "" } : {} }],
141
+ ["div", { class: "md-task-body" }, 0]
142
+ ]
143
+ },
144
+ table: {
145
+ // A column's alignment is on each of its cells, which is where the
146
+ // reader's renderer draws it; the header row's is what is written.
147
+ content: "table_row+",
148
+ group: "block item_first item_rest",
149
+ isolating: true,
150
+ parseDOM: [{ tag: "table" }],
151
+ toDOM: () => ["div", { class: "md-table" }, ["table", ["tbody", 0]]]
152
+ },
153
+ table_row: {
154
+ content: "(table_header | table_cell)+",
155
+ parseDOM: [{ tag: "tr" }],
156
+ toDOM: () => ["tr", 0]
157
+ },
158
+ table_header: cell("th"),
159
+ table_cell: cell("td"),
160
+ text: { group: "inline" },
161
+ image: {
162
+ inline: true,
163
+ group: "inline",
164
+ attrs: { src: { default: "" }, alt: { default: "" }, title: { default: null } },
165
+ draggable: true,
166
+ parseDOM: [
167
+ {
168
+ // A pasted picture arrives with its address in `data-src`, never
169
+ // `src`: the paste tree is built by hand and must load nothing.
170
+ tag: "img",
171
+ getAttrs: (dom) => ({
172
+ src: dom.getAttribute("data-src") ?? "",
173
+ alt: dom.getAttribute("alt") ?? "",
174
+ title: dom.getAttribute("title")
175
+ })
176
+ }
177
+ ],
178
+ toDOM: (node) => ["img", { alt: node.attrs.alt, "data-src": node.attrs.src }]
179
+ },
180
+ hard_break: {
181
+ inline: true,
182
+ group: "inline",
183
+ selectable: false,
184
+ attrs: { style: { default: "backslash" } },
185
+ parseDOM: [{ tag: "br" }],
186
+ toDOM: () => ["br"]
187
+ }
188
+ },
189
+ marks: {
190
+ // ORDER IS NESTING: a link outside the emphasis inside it, and a code
191
+ // span innermost, because its content is raw text.
192
+ link: {
193
+ attrs: { href: {}, title: { default: null }, auto: { default: false } },
194
+ inclusive: false,
195
+ parseDOM: [
196
+ {
197
+ tag: "a[href]",
198
+ getAttrs: (dom) => ({ href: dom.getAttribute("href") ?? "", title: dom.getAttribute("title") })
199
+ }
200
+ ],
201
+ toDOM: (mark) => ["a", { href: mark.attrs.href, rel: "noopener noreferrer" }, 0]
202
+ },
203
+ strong: {
204
+ attrs: { marker: { default: "**" } },
205
+ parseDOM: [
206
+ { tag: "strong" },
207
+ // Google Docs wraps a whole paste in a `b` that is not bold.
208
+ { tag: "b", getAttrs: (dom) => dom.style.fontWeight === "normal" ? false : null }
209
+ ],
210
+ toDOM: () => ["strong", 0]
211
+ },
212
+ em: {
213
+ attrs: { marker: { default: "*" } },
214
+ parseDOM: [{ tag: "em" }, { tag: "i" }],
215
+ toDOM: () => ["em", 0]
216
+ },
217
+ strike: {
218
+ parseDOM: [{ tag: "del" }, { tag: "s" }, { tag: "strike" }],
219
+ toDOM: () => ["del", 0]
220
+ },
221
+ code: {
222
+ parseDOM: [{ tag: "code" }],
223
+ toDOM: () => ["code", 0]
224
+ }
225
+ }
226
+ });
227
+ function languageOfClass(className) {
228
+ return /(?:^|\s)(?:language|lang)-([A-Za-z0-9_+-]+)/.exec(className)?.[1] ?? "";
229
+ }
230
+ function readMarkdown(markdown) {
231
+ const original = markdown ?? "";
232
+ const { lines, spans } = parseMarkdownSpans(original);
233
+ const blocks2 = [];
234
+ const byNode = /* @__PURE__ */ new WeakMap();
235
+ spans.forEach((span, index) => {
236
+ const node = blockNode(span.block);
237
+ const prevEnd = index === 0 ? 0 : spans[index - 1]?.end ?? 0;
238
+ const sep = index === 0 ? "" : "\n" + lines.slice(prevEnd, span.start).map((l) => `${l}
239
+ `).join("");
240
+ const block2 = { index, node, text: lines.slice(span.start, span.end).join("\n"), sep };
241
+ blocks2.push(block2);
242
+ byNode.set(node, block2);
243
+ });
244
+ const first = spans[0];
245
+ const last = spans[spans.length - 1];
246
+ const lead = first ? lines.slice(0, first.start).map((l) => `${l}
247
+ `).join("") : "";
248
+ const trail = last && last.end < lines.length ? "\n" + lines.slice(last.end).join("\n") : "";
249
+ const nodes = blocks2.map((b) => b.node);
250
+ const doc = schema.node("doc", null, nodes.length > 0 ? nodes : [schema.node("paragraph")]);
251
+ const crlf = /\r\n/.test(original) && !/(^|[^\r])\n/.test(original);
252
+ return { doc, source: { original, doc, lead, trail, blocks: blocks2, byNode, crlf } };
253
+ }
254
+ function blockNode(block2) {
255
+ switch (block2.kind) {
256
+ case "heading":
257
+ return schema.node("heading", { level: block2.level }, inline(block2.text, [], { breaks: false }));
258
+ case "paragraph":
259
+ return schema.node("paragraph", null, inline(block2.text, [], { breaks: true }));
260
+ case "code":
261
+ return schema.node(
262
+ "code_block",
263
+ { lang: block2.lang, fence: block2.fence },
264
+ block2.text ? schema.text(block2.text) : void 0
265
+ );
266
+ case "quote":
267
+ return schema.node("blockquote", null, blockNodes(block2.blocks));
268
+ case "callout":
269
+ return schema.node("callout", { tone: block2.tone }, blockNodes(block2.blocks));
270
+ case "rule":
271
+ return schema.node("horizontal_rule");
272
+ case "list":
273
+ return schema.node(
274
+ block2.ordered ? "ordered_list" : "bullet_list",
275
+ block2.ordered ? { start: block2.start, marker: block2.marker, loose: block2.loose } : { marker: block2.marker, loose: block2.loose },
276
+ block2.items.map((item) => schema.node("list_item", { checked: item.checked }, itemNodes(item.blocks)))
277
+ );
278
+ case "table":
279
+ return schema.node("table", null, [
280
+ row("table_header", block2.head, block2.align),
281
+ ...block2.rows.map((cells) => row("table_cell", cells, block2.align))
282
+ ]);
283
+ }
284
+ }
285
+ function blockNodes(blocks2) {
286
+ const nodes = blocks2.map(blockNode);
287
+ return nodes.length > 0 ? nodes : [schema.node("paragraph")];
288
+ }
289
+ function itemNodes(blocks2) {
290
+ const nodes = blockNodes(blocks2);
291
+ const item = schema.nodes.list_item;
292
+ const fitted = [];
293
+ for (const node of nodes) {
294
+ if (item.contentMatch.matchFragment(Fragment.from([...fitted, node]))) {
295
+ fitted.push(node);
296
+ } else {
297
+ fitted.push(schema.node("paragraph", null, node.textContent ? schema.text(node.textContent) : void 0));
298
+ }
299
+ }
300
+ return fitted;
301
+ }
302
+ function row(type, cells, align) {
303
+ const nodes = cells.map(
304
+ (cell2, i) => schema.node(type, { align: align[i] ?? "left" }, inline(cell2, [], { breaks: false }))
305
+ );
306
+ return schema.node("table_row", null, nodes.length > 0 ? nodes : [schema.node(type)]);
307
+ }
308
+ function inline(text, marks, options) {
309
+ const out = [];
310
+ walkInline(text, marks, options, out);
311
+ return collapse(out);
312
+ }
313
+ function walkInline(text, marks, options, out) {
314
+ let at = 0;
315
+ for (const { index, end, groups: g } of markdownInline(text)) {
316
+ if (index > at) plain(text.slice(at, index), marks, options, out);
317
+ at = end;
318
+ if (g.esc !== void 0) {
319
+ out.push(schema.text(g.esc, marks));
320
+ } else if (g.tick !== void 0) {
321
+ const code = markdownCodeText(g.code ?? "");
322
+ if (code) out.push(schema.text(code, schema.marks.code.create().addToSet(marks)));
323
+ } else if (g.src !== void 0) {
324
+ out.push(schema.node("image", { src: g.src, alt: g.alt ?? "", title: g.srcTitle ?? null }, void 0, marks));
325
+ } else if (g.href !== void 0) {
326
+ const link = schema.marks.link.create({ href: g.href, title: g.hrefTitle ?? null });
327
+ walkInline(g.label ?? "", link.addToSet(marks), options, out);
328
+ } else if (g.auto !== void 0) {
329
+ out.push(schema.text(g.auto, schema.marks.link.create({ href: g.auto, auto: true }).addToSet(marks)));
330
+ } else if (g.strong !== void 0 || g.strongUnder !== void 0) {
331
+ const mark = schema.marks.strong.create({ marker: g.strong !== void 0 ? "**" : "__" });
332
+ walkInline(g.strong ?? g.strongUnder ?? "", mark.addToSet(marks), options, out);
333
+ } else if (g.em !== void 0 || g.emUnder !== void 0) {
334
+ const mark = schema.marks.em.create({ marker: g.em !== void 0 ? "*" : "_" });
335
+ walkInline(g.em ?? g.emUnder ?? "", mark.addToSet(marks), options, out);
336
+ } else if (g.del !== void 0) {
337
+ walkInline(g.del, schema.marks.strike.create().addToSet(marks), options, out);
338
+ }
339
+ }
340
+ if (at < text.length) plain(text.slice(at), marks, options, out);
341
+ }
342
+ var BREAK = /( {2,}|\\)\n/;
343
+ function plain(text, marks, options, out) {
344
+ const parts = options.breaks ? text.split(BREAK) : [text];
345
+ for (let i = 0; i < parts.length; i++) {
346
+ const part = parts[i] ?? "";
347
+ if (i % 2 === 1) {
348
+ out.push(schema.node("hard_break", { style: part === "\\" ? "backslash" : "spaces" }, void 0, marks));
349
+ continue;
350
+ }
351
+ const spaced = part.replace(/[ \t\n]+/g, " ");
352
+ if (spaced) out.push(schema.text(spaced, marks));
353
+ }
354
+ }
355
+ function collapse(nodes) {
356
+ const out = [];
357
+ let lineStart = true;
358
+ let lastSpace = false;
359
+ for (const node of nodes) {
360
+ if (!node.isText) {
361
+ if (node.type.name === "hard_break") trimEnd(out);
362
+ out.push(node);
363
+ lineStart = node.type.name === "hard_break";
364
+ lastSpace = false;
365
+ continue;
366
+ }
367
+ let text = node.text ?? "";
368
+ if (lineStart || lastSpace) text = text.replace(/^ /, "");
369
+ if (!text) continue;
370
+ out.push(schema.text(text, node.marks));
371
+ lineStart = false;
372
+ lastSpace = text.endsWith(" ");
373
+ }
374
+ trimEnd(out);
375
+ return Fragment.from(out).content.slice();
376
+ }
377
+ function trimEnd(out) {
378
+ const last = out[out.length - 1];
379
+ if (!last?.isText) return;
380
+ const text = (last.text ?? "").replace(/ $/, "");
381
+ if (text) out[out.length - 1] = schema.text(text, last.marks);
382
+ else out.pop();
383
+ }
384
+ function writeMarkdown(doc, source) {
385
+ if (source && matchesAll(doc, source)) return source.original;
386
+ const used = /* @__PURE__ */ new Set();
387
+ let out = "";
388
+ let emitted = false;
389
+ let prev = null;
390
+ let prevNode = null;
391
+ for (let i = 0; i < doc.childCount; i++) {
392
+ const node = doc.child(i);
393
+ const known = source ? recall(node, source, used) : null;
394
+ const text = known ? known.text : writeBlock(node);
395
+ if (!known && text === "") continue;
396
+ if (!emitted) {
397
+ out = (known && known.index === 0 && source ? source.lead : "") + text;
398
+ } else {
399
+ const adjacent = known && prev && known.index === prev.index + 1;
400
+ out += (adjacent ? known.sep : separator(prevNode, node)) + text;
401
+ }
402
+ emitted = true;
403
+ prev = known;
404
+ prevNode = node;
405
+ }
406
+ if (source) {
407
+ const lastBlock = source.blocks[source.blocks.length - 1];
408
+ const endsAsRead = prev !== null && lastBlock !== void 0 && prev.index === lastBlock.index;
409
+ out += endsAsRead ? source.trail : emitted && source.original.endsWith("\n") ? "\n" : "";
410
+ if (source.crlf) out = out.replace(/\r?\n/g, "\r\n");
411
+ }
412
+ return out;
413
+ }
414
+ function matchesAll(doc, source) {
415
+ if (source.blocks.length === 0) return doc.childCount === 1 && doc.firstChild.childCount === 0;
416
+ if (doc.childCount !== source.blocks.length) return false;
417
+ let same = true;
418
+ doc.forEach((node, _offset, i) => {
419
+ if (source.blocks[i]?.node !== node) same = false;
420
+ });
421
+ return same;
422
+ }
423
+ function recall(node, source, used) {
424
+ const byIdentity = source.byNode.get(node);
425
+ if (byIdentity && !used.has(byIdentity.index)) {
426
+ used.add(byIdentity.index);
427
+ return byIdentity;
428
+ }
429
+ for (const block2 of source.blocks) {
430
+ if (!used.has(block2.index) && block2.node.eq(node)) {
431
+ used.add(block2.index);
432
+ return block2;
433
+ }
434
+ }
435
+ return null;
436
+ }
437
+ function separator(prev, next) {
438
+ if (prev && isList(prev) && isList(next) && (prev.type === next.type || bothBullet(prev, next))) return "\n\n\n";
439
+ return "\n\n";
440
+ }
441
+ function isList(node) {
442
+ return node.type.name === "bullet_list" || node.type.name === "ordered_list";
443
+ }
444
+ function bothBullet(a, b) {
445
+ return a.type.name === "bullet_list" && b.type.name === "bullet_list";
446
+ }
447
+ var RULE = "-".repeat(3);
448
+ var SPELLINGS = [
449
+ { markers: "keep", escape: "light" },
450
+ { markers: "star", escape: "light" },
451
+ { markers: "star", escape: "all" }
452
+ ];
453
+ function writeBlock(node) {
454
+ if (node.type.name === "paragraph" && node.childCount === 0) return "";
455
+ const want = signature(node);
456
+ let text = "";
457
+ for (const spelling of SPELLINGS) {
458
+ text = block(node, spelling);
459
+ const back = readMarkdown(text).doc;
460
+ if (back.childCount === 1 && signature(back.firstChild) === want) return text;
461
+ }
462
+ return text;
463
+ }
464
+ function block(node, s) {
465
+ switch (node.type.name) {
466
+ case "paragraph":
467
+ return lineStarts(inlineText(node, s, false).replace(/^[ \t]+|[ \t]+$/g, ""));
468
+ case "heading": {
469
+ const text = inlineText(node, s, false).trim();
470
+ return `${"#".repeat(node.attrs.level)} ${text.replace(/(\s)(#+)$/, "$1\\$2")}`;
471
+ }
472
+ case "code_block":
473
+ return codeBlock(node);
474
+ case "blockquote":
475
+ return quoted(blocks(node, s));
476
+ case "callout":
477
+ return quoted(`[!${node.attrs.tone.toUpperCase()}]
478
+ ${blocks(node, s)}`);
479
+ case "horizontal_rule":
480
+ return RULE;
481
+ case "bullet_list":
482
+ case "ordered_list":
483
+ return list(node, s);
484
+ case "table":
485
+ return table(node, s);
486
+ default:
487
+ return node.textContent;
488
+ }
489
+ }
490
+ function blocks(parent, s) {
491
+ const parts = [];
492
+ let prev = null;
493
+ parent.forEach((child) => {
494
+ const text = block(child, s);
495
+ if (parts.length > 0) parts.push(separator(prev, child));
496
+ parts.push(text);
497
+ prev = child;
498
+ });
499
+ return parts.join("");
500
+ }
501
+ function quoted(text) {
502
+ return text.split("\n").map((line) => line === "" ? ">" : `> ${line}`).join("\n");
503
+ }
504
+ function codeBlock(node) {
505
+ const text = node.textContent;
506
+ const lang = node.attrs.lang;
507
+ const closes = (fence2) => text.split("\n").some((line) => CLOSER[fence2].test(line));
508
+ const wanted = node.attrs.fence;
509
+ const other = wanted === "```" ? "~~~" : "```";
510
+ const fence = closes(wanted) && !closes(other) ? other : wanted;
511
+ return `${fence}${lang}
512
+ ${text}${text ? "\n" : ""}${fence}`;
513
+ }
514
+ var CLOSER = { "```": /^`{3,}[ \t]*$/, "~~~": /^~{3,}[ \t]*$/ };
515
+ function list(node, s) {
516
+ const ordered = node.type.name === "ordered_list";
517
+ const loose = node.attrs.loose;
518
+ const items = [];
519
+ node.forEach((item, _offset, i) => {
520
+ const marker = ordered ? `${node.attrs.start + i}${node.attrs.marker} ` : `${node.attrs.marker} `;
521
+ const checked = item.attrs.checked;
522
+ const box = checked === null ? "" : checked ? "[x] " : "[ ] ";
523
+ const indent = " ".repeat(marker.length);
524
+ const parts = [];
525
+ item.forEach((child) => {
526
+ if (parts.length > 0) parts.push(isList(child) ? "\n" : "\n\n");
527
+ parts.push(block(child, s));
528
+ });
529
+ const body = parts.join("");
530
+ const lines = body.split("\n");
531
+ items.push(
532
+ marker + box + lines.map((line, j) => j === 0 ? line : line === "" ? "" : indent + line).join("\n")
533
+ );
534
+ });
535
+ return items.join(loose ? "\n\n" : "\n");
536
+ }
537
+ function table(node, s) {
538
+ const rows = [];
539
+ const align = [];
540
+ node.forEach((r, _o, ri) => {
541
+ const cells = [];
542
+ r.forEach((cell2, _co, ci) => {
543
+ cells.push(inlineText(cell2, s, true));
544
+ if (ri === 0) align[ci] = cell2.attrs.align;
545
+ });
546
+ rows.push(cells);
547
+ });
548
+ const line = (cells) => `| ${cells.join(" | ")} |`;
549
+ const rule = align.map((a) => a === "center" ? `:${RULE}:` : a === "right" ? `${RULE}:` : RULE);
550
+ return [line(rows[0] ?? [""]), `| ${rule.join(" | ")} |`, ...rows.slice(1).map(line)].join("\n");
551
+ }
552
+ function lineStarts(text) {
553
+ return text.split("\n").map(
554
+ (line) => line.replace(/^(#{1,6})(?=\s|$)/, "\\$1").replace(/^>/, "\\>").replace(/^([-+])(?=\s)/, "\\$1").replace(/^(\d{1,9})([.)])(?=\s)/, "$1\\$2").replace(/^(-{3,}|_{3,})\s*$/, "\\$1").replace(/^\|/, "\\|")
555
+ ).join("\n");
556
+ }
557
+ function inlineText(parent, s, cell2) {
558
+ const children = [];
559
+ parent.forEach((child) => children.push(child));
560
+ return marked(expel(children), s, cell2);
561
+ }
562
+ function linkOf(node) {
563
+ return node.marks.find((m) => m.type.name === "link") ?? null;
564
+ }
565
+ var EMPHASIS = /* @__PURE__ */ new Set(["strong", "em", "strike"]);
566
+ function expel(nodes) {
567
+ const out = [];
568
+ nodes.forEach((node, i) => {
569
+ const emphasis = node.marks.filter((m2) => EMPHASIS.has(m2.type.name));
570
+ if (!node.isText || emphasis.length === 0 || node.marks.some((m2) => m2.type.name === "code")) {
571
+ out.push(node);
572
+ return;
573
+ }
574
+ const prev = nodes[i - 1];
575
+ const next = nodes[i + 1];
576
+ const opening = emphasis.filter((m2) => !prev || !m2.isInSet(prev.marks));
577
+ const closing2 = emphasis.filter((m2) => !next || !m2.isInSet(next.marks));
578
+ const text = node.text ?? "";
579
+ const m = /^(\s*)([\s\S]*?)(\s*)$/.exec(text);
580
+ const without = (gone) => node.marks.filter((mk) => !gone.includes(mk));
581
+ if (m[1]) out.push(schema.text(m[1], without(opening)));
582
+ if (m[2]) out.push(schema.text(m[2], node.marks));
583
+ if (m[3]) out.push(schema.text(m[3], without(closing2)));
584
+ });
585
+ return out;
586
+ }
587
+ function spanMarks(node) {
588
+ return node.marks.filter((m) => m.type.name !== "code");
589
+ }
590
+ var isLink = (mark) => mark.type.name === "link" ? 1 : 0;
591
+ function reach(nodes, i, mark) {
592
+ let n = 0;
593
+ while (i + n < nodes.length && mark.isInSet(nodes[i + n].marks)) n++;
594
+ return n;
595
+ }
596
+ function marked(nodes, s, cell2) {
597
+ let out = "";
598
+ const open = [];
599
+ const close = (to) => {
600
+ while (open.length > to) {
601
+ const top = open.pop();
602
+ out += closing(top.mark, top.auto, s);
603
+ }
604
+ };
605
+ nodes.forEach((node, i) => {
606
+ const want = spanMarks(node);
607
+ let keep = 0;
608
+ while (keep < open.length && open[keep].mark.isInSet(want)) keep++;
609
+ close(keep);
610
+ const opening = want.filter((m) => !open.some((o) => o.mark.eq(m))).sort((a, b) => reach(nodes, i, b) - reach(nodes, i, a) || isLink(a) - isLink(b));
611
+ for (const mark of opening) {
612
+ const auto = autolink(mark, nodes, i, open.length);
613
+ out += auto ? "<" : opener(mark, s);
614
+ open.push({ mark, auto });
615
+ }
616
+ const inAuto = open.some((o) => o.auto);
617
+ const inLink = open.some((o) => o.mark.type.name === "link");
618
+ out += inAuto ? node.text ?? "" : content(node, s, cell2, nodes[i + 1], inLink);
619
+ });
620
+ close(0);
621
+ return out;
622
+ }
623
+ function autolink(mark, nodes, i, depth) {
624
+ if (mark.type.name !== "link" || !mark.attrs.auto) return false;
625
+ const node = nodes[i];
626
+ const href = mark.attrs.href;
627
+ return reach(nodes, i, mark) === 1 && node.isText && node.text === href && spanMarks(node).length === depth + 1 && !node.marks.some((m) => m.type.name === "code") && /^(https?:|mailto:)[^>\s]+$/i.test(href);
628
+ }
629
+ function opener(mark, s) {
630
+ return mark.type.name === "link" ? "[" : delimiter(mark, s);
631
+ }
632
+ function closing(mark, auto, s) {
633
+ if (auto) return ">";
634
+ if (mark.type.name !== "link") return delimiter(mark, s);
635
+ const title = mark.attrs.title;
636
+ return `](${destination(mark.attrs.href)}${title ? ` "${title.replace(/"/g, "'")}"` : ""})`;
637
+ }
638
+ function delimiter(mark, s) {
639
+ switch (mark.type.name) {
640
+ case "strong":
641
+ return s.markers === "keep" ? mark.attrs.marker : "**";
642
+ case "em":
643
+ return s.markers === "keep" ? mark.attrs.marker : "*";
644
+ default:
645
+ return "~~";
646
+ }
647
+ }
648
+ function content(node, s, cell2, next, inLink) {
649
+ if (node.type.name === "hard_break") return node.attrs.style === "spaces" ? " \n" : "\\\n";
650
+ if (node.type.name === "image") {
651
+ const alt = node.attrs.alt.replace(/(^|[^\\])([[\]])/g, "$1\\$2");
652
+ const title = node.attrs.title;
653
+ return `![${alt}](${destination(node.attrs.src)}${title ? ` "${title.replace(/"/g, "'")}"` : ""})`;
654
+ }
655
+ const text = node.text ?? "";
656
+ if (node.marks.some((m) => m.type.name === "code")) return codeSpan(text, cell2);
657
+ const escaped = escapeText(text, s.escape, cell2, next);
658
+ return inLink ? escaped.replace(/(^|[^\\])\]/g, "$1\\]") : escaped;
659
+ }
660
+ function codeSpan(text, cell2) {
661
+ const longest = Math.max(0, ...(text.match(/`+/g) ?? []).map((run) => run.length));
662
+ const fence = "`".repeat(longest + 1);
663
+ const pad = (side) => side === " " || side === "`" ? " " : "";
664
+ const body = cell2 ? text.replace(/\|/g, "\\|") : text;
665
+ return `${fence}${pad(body[0] ?? "")}${body}${pad(body[body.length - 1] ?? "")}${fence}`;
666
+ }
667
+ var ASCII_PUNCTUATION = /[!-/:-@[-`{-~]/;
668
+ function escapeText(text, mode, cell2, next) {
669
+ if (mode === "all") {
670
+ return text.replace(/[!-/:-@[-`{-~]/g, (c) => c === "\\" || /[\\`*_[\]<>~|!#]/.test(c) ? `\\${c}` : c);
671
+ }
672
+ const nextChar = (next?.isText ? (next.text ?? "")[0] : next ? "!" : "") ?? "";
673
+ let out = "";
674
+ for (let i = 0; i < text.length; i++) {
675
+ const c = text[i];
676
+ const before = text[i - 1] ?? "";
677
+ const after = text[i + 1] ?? nextChar;
678
+ if (c === "\\") {
679
+ out += after === "" || ASCII_PUNCTUATION.test(after) ? "\\\\" : "\\";
680
+ } else if (c === "`" || c === "*") {
681
+ out += `\\${c}`;
682
+ } else if (c === "_") {
683
+ const word = /[\p{L}\p{N}]/u;
684
+ out += word.test(before) && word.test(after) ? "_" : "\\_";
685
+ } else if (c === "~") {
686
+ out += after === "~" || before === "~" ? "\\~" : "~";
687
+ } else if (c === "[") {
688
+ out += text.indexOf("](", i) >= 0 ? "\\[" : "[";
689
+ } else if (c === "<") {
690
+ out += /^<(https?:|mailto:)/i.test(text.slice(i)) ? "\\<" : "<";
691
+ } else if (c === "|" && cell2) {
692
+ out += "\\|";
693
+ } else {
694
+ out += c;
695
+ }
696
+ }
697
+ return out;
698
+ }
699
+ function destination(href) {
700
+ let depth = 0;
701
+ let balanced = true;
702
+ for (const c of href) {
703
+ if (c === "(") depth++;
704
+ if (c === ")") depth--;
705
+ if (depth < 0 || depth > 1) balanced = false;
706
+ }
707
+ const spaced = href.replace(/\s/g, (c) => encodeURIComponent(c));
708
+ return balanced && depth === 0 ? spaced : spaced.replace(/\(/g, "%28").replace(/\)/g, "%29");
709
+ }
710
+ function signature(node) {
711
+ if (node.isText) {
712
+ const marks = node.marks.filter((m) => m.type.name !== "link").map((m) => m.type.name).join("+");
713
+ const link = linkOf(node);
714
+ const tag = `${marks}${link ? `@${link.attrs.href}` : ""}`;
715
+ return [...node.text ?? ""].map((c) => c === " " ? " " : `${c}${tag ? `{${tag}}` : ""}`).join("");
716
+ }
717
+ const attrs = visibleAttrs(node);
718
+ let inner = "";
719
+ node.forEach((child) => {
720
+ inner += signature(child);
721
+ });
722
+ if (node.isTextblock && !node.type.spec.code) {
723
+ inner = inner.replace(/ +/g, " ").replace(/ ?(<hard_break[^>]*><\/>) ?/g, "$1").trim();
724
+ }
725
+ return `<${node.type.name}${attrs}>${inner}</>`;
726
+ }
727
+ function visibleAttrs(node) {
728
+ switch (node.type.name) {
729
+ case "heading":
730
+ return ` ${node.attrs.level}`;
731
+ case "code_block":
732
+ return ` ${node.attrs.lang}`;
733
+ case "callout":
734
+ return ` ${node.attrs.tone}`;
735
+ case "ordered_list":
736
+ return ` ${node.attrs.start}`;
737
+ case "list_item":
738
+ return ` ${String(node.attrs.checked)}`;
739
+ case "table_header":
740
+ case "table_cell":
741
+ return ` ${node.attrs.align}`;
742
+ case "image":
743
+ return ` ${node.attrs.src} ${node.attrs.alt}`;
744
+ default:
745
+ return "";
746
+ }
747
+ }
748
+
749
+ export { readMarkdown, schema, writeMarkdown };