@tensor_1/react 2.18.0 → 2.19.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 (54) hide show
  1. package/README.md +102 -1
  2. package/dist/components/Comments.d.ts +18 -2
  3. package/dist/components/Comments.js +37 -12
  4. package/dist/components/Composer.d.ts +5 -1
  5. package/dist/components/EditorIcons.d.ts +39 -0
  6. package/dist/components/EditorIcons.js +51 -0
  7. package/dist/components/EmojiGlyph.d.ts +10 -0
  8. package/dist/components/EmojiGlyph.js +18 -0
  9. package/dist/components/EmojiPicker.d.ts +60 -0
  10. package/dist/components/EmojiPicker.js +277 -0
  11. package/dist/components/Markdown.d.ts +36 -0
  12. package/dist/components/Markdown.js +104 -0
  13. package/dist/components/ReactionBar.d.ts +57 -0
  14. package/dist/components/ReactionBar.js +81 -0
  15. package/dist/components/RelationshipGraph.js +23 -4
  16. package/dist/components/RichTextEditor.d.ts +128 -0
  17. package/dist/components/RichTextEditor.js +954 -0
  18. package/dist/components/SaveStatus.d.ts +32 -0
  19. package/dist/components/SaveStatus.js +21 -0
  20. package/dist/components/Tabs.d.ts +10 -3
  21. package/dist/components/Tabs.js +5 -3
  22. package/dist/emoji-image-WQLh8ZQP.d.cts +128 -0
  23. package/dist/emoji-image.d.ts +25 -0
  24. package/dist/emoji-image.js +80 -0
  25. package/dist/emoji-model.d.ts +66 -0
  26. package/dist/emoji-model.js +108 -0
  27. package/dist/emoji.cjs +871 -0
  28. package/dist/emoji.d.cts +57 -0
  29. package/dist/emoji.d.ts +6 -0
  30. package/dist/emoji.js +18 -0
  31. package/dist/index.cjs +587 -519
  32. package/dist/index.d.cts +64 -65
  33. package/dist/index.d.ts +1 -0
  34. package/dist/index.js +3 -0
  35. package/dist/markdown-model.d.ts +75 -0
  36. package/dist/markdown-model.js +438 -0
  37. package/dist/markdown.cjs +585 -0
  38. package/dist/markdown.d.cts +115 -0
  39. package/dist/markdown.d.ts +4 -0
  40. package/dist/markdown.js +9 -0
  41. package/dist/overlay-position-CEGSz6Z2.d.cts +59 -0
  42. package/dist/rich-text/emoji-items.d.ts +14 -0
  43. package/dist/rich-text/emoji-items.js +7 -0
  44. package/dist/rich-text/pipeline.d.ts +91 -0
  45. package/dist/rich-text/pipeline.js +379 -0
  46. package/dist/rich-text/round-trip.d.ts +24 -0
  47. package/dist/rich-text/round-trip.js +11 -0
  48. package/dist/rich-text.cjs +2578 -0
  49. package/dist/rich-text.d.cts +148 -0
  50. package/dist/rich-text.d.ts +8 -0
  51. package/dist/rich-text.js +10 -0
  52. package/dist/url-policy.d.ts +9 -0
  53. package/dist/url-policy.js +11 -0
  54. package/package.json +82 -1
@@ -0,0 +1,585 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/markdown.ts
21
+ var markdown_exports = {};
22
+ __export(markdown_exports, {
23
+ Markdown: () => Markdown,
24
+ defaultMarkdownIsSafeUrl: () => defaultMarkdownIsSafeUrl,
25
+ parseInline: () => parseInline,
26
+ parseMarkdown: () => parseMarkdown,
27
+ plainText: () => plainText
28
+ });
29
+ module.exports = __toCommonJS(markdown_exports);
30
+
31
+ // src/cx.ts
32
+ function cx(...args) {
33
+ return args.filter(Boolean).join(" ");
34
+ }
35
+
36
+ // src/markdown-model.ts
37
+ var ASCII_PUNCT = /[!-/:-@[-`{-~]/;
38
+ var WORD = /[\p{L}\p{N}]/u;
39
+ var NAMED_ENTITIES = {
40
+ amp: "&",
41
+ lt: "<",
42
+ gt: ">",
43
+ quot: '"',
44
+ apos: "'",
45
+ nbsp: "\xA0",
46
+ copy: "\xA9",
47
+ reg: "\xAE",
48
+ hellip: "\u2026",
49
+ mdash: "\u2014",
50
+ ndash: "\u2013"
51
+ };
52
+ var ENTITY_RE = /^&(?:#(\d{1,7})|#[xX]([\da-fA-F]{1,6})|([a-zA-Z][a-zA-Z\d]{1,31}));/;
53
+ var ENTITY_GLOBAL = /&(?:#\d{1,7}|#[xX][\da-fA-F]{1,6}|[a-zA-Z][a-zA-Z\d]{1,31});/g;
54
+ var BARE_URL_RE = /^https?:\/\/[^\s<>()]+/;
55
+ var BR_RE = /^<br\s*\/?>/i;
56
+ var AUTOLINK_RE = /^<((?:https?:|mailto:)[^\s<>]*)>/i;
57
+ var decodeEntity = (match) => {
58
+ const [, dec, hex, name] = match;
59
+ const code = dec ? Number(dec) : hex ? parseInt(hex, 16) : void 0;
60
+ if (code !== void 0) return code > 0 && code <= 1114111 ? String.fromCodePoint(code) : "\uFFFD";
61
+ return name && Object.prototype.hasOwnProperty.call(NAMED_ENTITIES, name) ? NAMED_ENTITIES[name] : null;
62
+ };
63
+ var MAX_SCAN = 2e3;
64
+ var MAX_DEPTH = 12;
65
+ var findBracketEnd = (text, open) => {
66
+ let depth = 0;
67
+ const stop = Math.min(text.length, open + MAX_SCAN);
68
+ for (let i = open; i < stop; i += 1) {
69
+ const ch = text[i];
70
+ if (ch === "\\") {
71
+ i += 1;
72
+ continue;
73
+ }
74
+ if (ch === "`") {
75
+ const close = text.indexOf("`", i + 1);
76
+ if (close > 0) {
77
+ i = close;
78
+ continue;
79
+ }
80
+ }
81
+ if (ch === "[") depth += 1;
82
+ else if (ch === "]") {
83
+ depth -= 1;
84
+ if (depth === 0) return i;
85
+ }
86
+ }
87
+ return -1;
88
+ };
89
+ var readDestination = (text, open) => {
90
+ if (text[open] !== "(") return null;
91
+ let depth = 0;
92
+ let end = -1;
93
+ const stop = Math.min(text.length, open + MAX_SCAN);
94
+ for (let i = open; i < stop; i += 1) {
95
+ const ch = text[i];
96
+ if (ch === "\\") {
97
+ i += 1;
98
+ continue;
99
+ }
100
+ if (ch === "(") depth += 1;
101
+ else if (ch === ")") {
102
+ depth -= 1;
103
+ if (depth === 0) {
104
+ end = i;
105
+ break;
106
+ }
107
+ }
108
+ }
109
+ if (end < 0) return null;
110
+ const inner = text.slice(open + 1, end).trim();
111
+ const titled = /^(\S+)\s+(?:"([^"]*)"|'([^']*)')$/.exec(inner);
112
+ const rawUrl = titled ? titled[1] : inner;
113
+ const url = rawUrl.replace(/^<(.*)>$/, "$1").replace(/\\([!-/:-@[-`{-~])/g, "$1").replace(ENTITY_GLOBAL, (match) => decodeEntity(ENTITY_RE.exec(match)) ?? match);
114
+ const title = titled ? titled[2] ?? titled[3] : void 0;
115
+ return title === void 0 ? { url, end } : { url, title, end };
116
+ };
117
+ var backtickRun = (text, at) => {
118
+ let end = at;
119
+ while (text[end] === "`") end += 1;
120
+ return text.slice(at, end);
121
+ };
122
+ var findCloser = (text, from, delim, misses) => {
123
+ if (from >= (misses.get(delim) ?? Infinity)) return -1;
124
+ for (let i = from; i < text.length; i += 1) {
125
+ const ch = text[i];
126
+ if (ch === "\\") {
127
+ i += 1;
128
+ continue;
129
+ }
130
+ if (ch === "`") {
131
+ const run = backtickRun(text, i);
132
+ const close = text.indexOf(run, i + run.length);
133
+ if (close > 0) {
134
+ i = close + run.length - 1;
135
+ continue;
136
+ }
137
+ }
138
+ if (text.startsWith(delim, i) && i > from && !/\s/u.test(text[i - 1])) {
139
+ if (delim[0] === "_" && WORD.test(text[i + delim.length] ?? "")) continue;
140
+ if (delim.length === 1 && text[i + 1] === delim) {
141
+ i += 1;
142
+ continue;
143
+ }
144
+ return i;
145
+ }
146
+ }
147
+ misses.set(delim, Math.min(from, misses.get(delim) ?? Infinity));
148
+ return -1;
149
+ };
150
+ var pushText = (out, value) => {
151
+ if (!value) return;
152
+ const last = out[out.length - 1];
153
+ if (last?.type === "text") last.value += value;
154
+ else out.push({ type: "text", value });
155
+ };
156
+ function parseInline(text, depth = 0) {
157
+ const out = [];
158
+ if (depth > MAX_DEPTH) {
159
+ pushText(out, text);
160
+ return out;
161
+ }
162
+ const misses = /* @__PURE__ */ new Map();
163
+ let i = 0;
164
+ while (i < text.length) {
165
+ const ch = text[i];
166
+ const rest = text.slice(i);
167
+ if (ch === "\\" && ASCII_PUNCT.test(text[i + 1] ?? "")) {
168
+ pushText(out, text[i + 1]);
169
+ i += 2;
170
+ continue;
171
+ }
172
+ if (ch === "\n") {
173
+ out.push({ type: "br" });
174
+ i += 1;
175
+ continue;
176
+ }
177
+ if (ch === "`") {
178
+ const run = backtickRun(text, i);
179
+ const close = text.indexOf(run, i + run.length);
180
+ if (close > 0 && text[close + run.length] !== "`") {
181
+ let value = text.slice(i + run.length, close).replace(/\n/g, " ");
182
+ if (/^ .* $/.test(value) && value.trim()) value = value.slice(1, -1);
183
+ out.push({ type: "code", value });
184
+ i = close + run.length;
185
+ continue;
186
+ }
187
+ pushText(out, run);
188
+ i += run.length;
189
+ continue;
190
+ }
191
+ if (ch === "!" && text[i + 1] === "[") {
192
+ const end = findBracketEnd(text, i + 1);
193
+ const dest = end > 0 ? readDestination(text, end + 1) : null;
194
+ if (dest) {
195
+ const alt = plainText(parseInline(text.slice(i + 2, end), depth + 1));
196
+ out.push(dest.title === void 0 ? { type: "image", src: dest.url, alt } : { type: "image", src: dest.url, alt, title: dest.title });
197
+ i = dest.end + 1;
198
+ continue;
199
+ }
200
+ }
201
+ if (ch === "[") {
202
+ const end = findBracketEnd(text, i);
203
+ const dest = end > 0 ? readDestination(text, end + 1) : null;
204
+ if (dest) {
205
+ const children = parseInline(text.slice(i + 1, end), depth + 1);
206
+ out.push(dest.title === void 0 ? { type: "link", href: dest.url, children } : { type: "link", href: dest.url, title: dest.title, children });
207
+ i = dest.end + 1;
208
+ continue;
209
+ }
210
+ }
211
+ if (ch === "<") {
212
+ const br = BR_RE.exec(rest);
213
+ if (br) {
214
+ out.push({ type: "br" });
215
+ i += br[0].length;
216
+ continue;
217
+ }
218
+ const auto = AUTOLINK_RE.exec(rest);
219
+ if (auto) {
220
+ out.push({ type: "link", href: auto[1], children: [{ type: "text", value: auto[1].replace(/^mailto:/i, "") }], bare: true });
221
+ i += auto[0].length;
222
+ continue;
223
+ }
224
+ }
225
+ if (ch === "&") {
226
+ const entity = ENTITY_RE.exec(rest);
227
+ const decoded = entity ? decodeEntity(entity) : null;
228
+ if (entity && decoded !== null) {
229
+ pushText(out, decoded);
230
+ i += entity[0].length;
231
+ continue;
232
+ }
233
+ }
234
+ if (ch === "~" && text[i + 1] === "~" && text[i + 2] && !/\s/u.test(text[i + 2])) {
235
+ const close = findCloser(text, i + 2, "~~", misses);
236
+ if (close > 0) {
237
+ out.push({ type: "del", children: parseInline(text.slice(i + 2, close), depth + 1) });
238
+ i = close + 2;
239
+ continue;
240
+ }
241
+ }
242
+ if (ch === "*" || ch === "_") {
243
+ const leftOk = ch === "*" || !WORD.test(text[i - 1] ?? "");
244
+ const double = text[i + 1] === ch;
245
+ const delim = double ? ch + ch : ch;
246
+ const after = text[i + delim.length];
247
+ if (leftOk && after && !/\s/u.test(after)) {
248
+ const close = findCloser(text, i + delim.length, delim, misses);
249
+ if (close > 0) {
250
+ const children = parseInline(text.slice(i + delim.length, close), depth + 1);
251
+ out.push(double ? { type: "strong", children } : { type: "em", children });
252
+ i = close + delim.length;
253
+ continue;
254
+ }
255
+ }
256
+ const run = new RegExp(`^\\${ch}+`).exec(rest)[0];
257
+ pushText(out, run);
258
+ i += run.length;
259
+ continue;
260
+ }
261
+ if (ch === "h" && !WORD.test(text[i - 1] ?? "")) {
262
+ const bare = BARE_URL_RE.exec(rest);
263
+ if (bare) {
264
+ const url = bare[0].replace(/[.,;:!?'"]+$/, "");
265
+ out.push({ type: "link", href: url, children: [{ type: "text", value: url }], bare: true });
266
+ i += url.length;
267
+ continue;
268
+ }
269
+ }
270
+ pushText(out, ch);
271
+ i += 1;
272
+ }
273
+ return out;
274
+ }
275
+ function plainText(nodes) {
276
+ return nodes.map((n) => {
277
+ switch (n.type) {
278
+ case "text":
279
+ case "code":
280
+ return n.value;
281
+ case "br":
282
+ return " ";
283
+ case "image":
284
+ return n.alt;
285
+ default:
286
+ return plainText(n.children);
287
+ }
288
+ }).join("");
289
+ }
290
+ var FENCE_RE = /^(`{3,}|~{3,})\s*([^`\s]*)/;
291
+ var HEADING_RE = /^(#{1,6})\s+(.*?)(?:\s+#+)?$/;
292
+ var RULE_RE = /^(?:(?:\*\s*){3,}|(?:-\s*){3,}|(?:_\s*){3,})$/;
293
+ var BULLET_RE = /^(\s*)([-*+])\s+(.*)$/;
294
+ var ORDERED_RE = /^(\s*)(\d{1,9})[.)]\s+(.*)$/;
295
+ var TASK_RE = /^\[([ xX])\]\s+(.*)$/;
296
+ var DELIMITER_ROW_RE = /^\s*\|?\s*:?-+:?\s*(?:\|\s*:?-+:?\s*)*\|?\s*$/;
297
+ var indentOf = (s) => s.replace(/\t/g, " ").length;
298
+ function splitTableRow(line) {
299
+ let row = line.trim();
300
+ if (row.startsWith("|")) row = row.slice(1);
301
+ if (row.endsWith("|") && !row.endsWith("\\|")) row = row.slice(0, -1);
302
+ const cells = [];
303
+ let cell = "";
304
+ let inCode = false;
305
+ for (let i = 0; i < row.length; i += 1) {
306
+ const ch = row[i];
307
+ if (ch === "\\" && row[i + 1] === "|") {
308
+ cell += "|";
309
+ i += 1;
310
+ continue;
311
+ }
312
+ if (ch === "`") inCode = !inCode;
313
+ if (ch === "|" && !inCode) {
314
+ cells.push(cell.trim());
315
+ cell = "";
316
+ continue;
317
+ }
318
+ cell += ch;
319
+ }
320
+ cells.push(cell.trim());
321
+ return cells;
322
+ }
323
+ var alignOf = (cell) => {
324
+ const c = cell.trim();
325
+ const left = c.startsWith(":");
326
+ const right = c.endsWith(":");
327
+ return left && right ? "center" : right ? "right" : left ? "left" : null;
328
+ };
329
+ var matchListLine = (line) => {
330
+ const bullet = BULLET_RE.exec(line);
331
+ if (bullet && !RULE_RE.test(line.trim())) return { indent: indentOf(bullet[1]), ordered: false, number: 1, text: bullet[3] };
332
+ const ordered = ORDERED_RE.exec(line);
333
+ if (ordered) return { indent: indentOf(ordered[1]), ordered: true, number: Number(ordered[2]), text: ordered[3] };
334
+ return null;
335
+ };
336
+ var toItem = (text) => {
337
+ const task = TASK_RE.exec(text);
338
+ return task ? { checked: task[1] !== " ", children: parseInline(task[2]), lists: [] } : { checked: null, children: parseInline(text), lists: [] };
339
+ };
340
+ var buildList = (lines) => {
341
+ const lists = [];
342
+ const stack = [];
343
+ for (const line of lines) {
344
+ while (stack.length && line.indent < stack[stack.length - 1].indent) stack.pop();
345
+ let top = stack[stack.length - 1];
346
+ if (top && line.indent > top.indent) {
347
+ const parentItem = top.list.items[top.list.items.length - 1];
348
+ const nested = { type: "list", ordered: line.ordered, start: line.number, items: [] };
349
+ parentItem.lists.push(nested);
350
+ stack.push({ list: nested, indent: line.indent });
351
+ top = stack[stack.length - 1];
352
+ } else if (!top || top.list.ordered !== line.ordered) {
353
+ const list = { type: "list", ordered: line.ordered, start: line.number, items: [] };
354
+ if (stack.length <= 1) {
355
+ lists.push(list);
356
+ stack.length = 0;
357
+ } else {
358
+ stack.pop();
359
+ const parent = stack[stack.length - 1].list;
360
+ parent.items[parent.items.length - 1].lists.push(list);
361
+ }
362
+ stack.push({ list, indent: line.indent });
363
+ top = stack[stack.length - 1];
364
+ }
365
+ top.list.items.push(toItem(line.text));
366
+ }
367
+ return lists;
368
+ };
369
+ function parseMarkdown(source) {
370
+ const lines = source.replace(/\r\n?/g, "\n").split("\n");
371
+ const blocks = [];
372
+ let paragraph = [];
373
+ let i = 0;
374
+ const flush = () => {
375
+ if (paragraph.length) {
376
+ blocks.push({ type: "paragraph", children: parseInline(paragraph.join("\n")) });
377
+ paragraph = [];
378
+ }
379
+ };
380
+ while (i < lines.length) {
381
+ const line = lines[i];
382
+ const trimmed = line.trim();
383
+ if (trimmed === "") {
384
+ flush();
385
+ i += 1;
386
+ continue;
387
+ }
388
+ const fence = FENCE_RE.exec(trimmed);
389
+ if (fence) {
390
+ flush();
391
+ const marker = fence[1];
392
+ const body = [];
393
+ i += 1;
394
+ while (i < lines.length && !lines[i].trim().startsWith(marker)) {
395
+ body.push(lines[i]);
396
+ i += 1;
397
+ }
398
+ i += 1;
399
+ blocks.push({ type: "code", lang: fence[2] ?? "", value: body.join("\n") });
400
+ continue;
401
+ }
402
+ const heading = HEADING_RE.exec(trimmed);
403
+ if (heading) {
404
+ flush();
405
+ blocks.push({ type: "heading", level: heading[1].length, children: parseInline(heading[2]) });
406
+ i += 1;
407
+ continue;
408
+ }
409
+ if (RULE_RE.test(trimmed)) {
410
+ flush();
411
+ blocks.push({ type: "rule" });
412
+ i += 1;
413
+ continue;
414
+ }
415
+ if (trimmed.startsWith(">")) {
416
+ flush();
417
+ const quote = [];
418
+ while (i < lines.length && lines[i].trim().startsWith(">")) {
419
+ quote.push(lines[i].trim().replace(/^>\s?/, ""));
420
+ i += 1;
421
+ }
422
+ blocks.push({ type: "quote", children: parseInline(quote.join(" ")) });
423
+ continue;
424
+ }
425
+ if (trimmed.includes("|") && i + 1 < lines.length && DELIMITER_ROW_RE.test(lines[i + 1]) && lines[i + 1].includes("-")) {
426
+ const head = splitTableRow(line);
427
+ const delimiters = splitTableRow(lines[i + 1]);
428
+ if (delimiters.length === head.length) {
429
+ flush();
430
+ const rows = [];
431
+ i += 2;
432
+ while (i < lines.length && lines[i].trim() !== "" && lines[i].includes("|")) {
433
+ const cells = splitTableRow(lines[i]);
434
+ rows.push(head.map((_, c) => parseInline(cells[c] ?? "")));
435
+ i += 1;
436
+ }
437
+ blocks.push({ type: "table", align: delimiters.map(alignOf), head: head.map((c) => parseInline(c)), rows });
438
+ continue;
439
+ }
440
+ }
441
+ const first = matchListLine(line);
442
+ if (first) {
443
+ flush();
444
+ const listLines = [];
445
+ while (i < lines.length) {
446
+ const current = lines[i];
447
+ const item = matchListLine(current);
448
+ if (item) {
449
+ if (listLines.length && item.indent <= listLines[0].indent && item.ordered !== listLines[0].ordered) break;
450
+ listLines.push(item);
451
+ } else if (current.trim() !== "" && indentOf(current) > listLines[0].indent && listLines.length) {
452
+ listLines[listLines.length - 1].text += `
453
+ ${current.trim()}`;
454
+ } else {
455
+ break;
456
+ }
457
+ i += 1;
458
+ }
459
+ const base = Math.min(...listLines.map((l) => l.indent));
460
+ blocks.push(...buildList(listLines.map((l) => ({ ...l, indent: l.indent - base }))));
461
+ continue;
462
+ }
463
+ paragraph.push(trimmed);
464
+ i += 1;
465
+ }
466
+ flush();
467
+ return blocks;
468
+ }
469
+
470
+ // src/url-policy.ts
471
+ var ALLOWED_START = /^(https?:|mailto:|\/|#|\.\/|\.\.\/)/i;
472
+ var CONTROL_OR_BACKSLASH = /[\x00-\x1f\x7f\\]/;
473
+ var PROTOCOL_RELATIVE = /^[/\\]{2}/;
474
+ function defaultIsSafeUrl(url) {
475
+ const candidate = url.replace(/[\t\n\r]/g, "").trim();
476
+ if (CONTROL_OR_BACKSLASH.test(candidate) || PROTOCOL_RELATIVE.test(candidate)) return false;
477
+ return ALLOWED_START.test(candidate);
478
+ }
479
+
480
+ // src/components/Markdown.tsx
481
+ var import_jsx_runtime = require("react/jsx-runtime");
482
+ var defaultMarkdownIsSafeUrl = defaultIsSafeUrl;
483
+ var isExternal = (href) => /^https?:/i.test(href.trim());
484
+ function renderInlines(nodes, policy) {
485
+ return nodes.map((node, i) => {
486
+ switch (node.type) {
487
+ case "text":
488
+ return node.value;
489
+ case "br":
490
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}, i);
491
+ case "code":
492
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: node.value }, i);
493
+ case "strong":
494
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: renderInlines(node.children, policy) }, i);
495
+ case "em":
496
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("em", { children: renderInlines(node.children, policy) }, i);
497
+ case "del":
498
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("del", { children: renderInlines(node.children, policy) }, i);
499
+ case "link": {
500
+ const children = renderInlines(node.children, policy);
501
+ if (!node.href.trim() || !policy.isSafeUrl(node.href)) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children }, i);
502
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
503
+ "a",
504
+ {
505
+ href: node.href.trim(),
506
+ title: node.title,
507
+ ...isExternal(node.href) ? { target: "_blank", rel: "noopener noreferrer" } : {},
508
+ children
509
+ },
510
+ i
511
+ );
512
+ }
513
+ case "image": {
514
+ const resolved = policy.resolveImageSrc?.(node.src) ?? null;
515
+ if (resolved) {
516
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: resolved, alt: node.alt, title: node.title, loading: "lazy", decoding: "async" }, i);
517
+ }
518
+ const label = node.alt || node.src;
519
+ if (!node.src.trim() || !policy.isSafeUrl(node.src)) return label;
520
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: node.src.trim(), ...isExternal(node.src) ? { target: "_blank", rel: "noopener noreferrer" } : {}, children: label }, i);
521
+ }
522
+ }
523
+ });
524
+ }
525
+ function renderList(list, policy, key) {
526
+ const items = list.items.map((item, i) => {
527
+ const content = renderInlines(item.children, policy);
528
+ const nested = item.lists.map((sub, n) => renderList(sub, policy, n));
529
+ if (item.checked === null) {
530
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
531
+ content,
532
+ nested
533
+ ] }, i);
534
+ }
535
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "uix-markdown__task", "data-checked": item.checked || void 0, children: [
536
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", defaultChecked: item.checked, disabled: true, "aria-label": plainText(item.children) }),
537
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: content }),
538
+ nested
539
+ ] }, i);
540
+ });
541
+ const hasTasks = list.items.some((item) => item.checked !== null);
542
+ const className = hasTasks ? "uix-markdown__tasks" : void 0;
543
+ return list.ordered ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className, start: list.start !== 1 ? list.start : void 0, children: items }, key) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className, children: items }, key);
544
+ }
545
+ function renderBlock(block, policy, headingOffset, key) {
546
+ switch (block.type) {
547
+ case "paragraph":
548
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: renderInlines(block.children, policy) }, key);
549
+ case "heading": {
550
+ const Tag = `h${Math.min(Math.max(block.level + headingOffset, 1), 6)}`;
551
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { children: renderInlines(block.children, policy) }, key);
552
+ }
553
+ case "code":
554
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { "data-language": block.lang || void 0, children: block.value }) }, key);
555
+ case "quote":
556
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("blockquote", { children: renderInlines(block.children, policy) }, key);
557
+ case "rule":
558
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("hr", {}, key);
559
+ case "list":
560
+ return renderList(block, policy, key);
561
+ case "table":
562
+ return (
563
+ // A scrollable region must be reachable from the keyboard.
564
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "uix-markdown__table", tabIndex: 0, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { children: [
565
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: block.head.map((cell, c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", style: block.align[c] ? { textAlign: block.align[c] } : void 0, children: renderInlines(cell, policy) }, c)) }) }),
566
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: block.rows.map((row, r) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: row.map((cell, c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: block.align[c] ? { textAlign: block.align[c] } : void 0, children: renderInlines(cell, policy) }, c)) }, r)) })
567
+ ] }) }, key)
568
+ );
569
+ }
570
+ }
571
+ function Markdown({ children, className, isSafeUrl = defaultMarkdownIsSafeUrl, resolveImageSrc, headingOffset = 2 }) {
572
+ const source = typeof children === "string" ? children : "";
573
+ if (source.trim() === "") return null;
574
+ const policy = { isSafeUrl, resolveImageSrc };
575
+ const blocks = parseMarkdown(source);
576
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cx("uix-prose", "uix-markdown", className), "data-component": "markdown", children: blocks.map((block, i) => renderBlock(block, policy, headingOffset, i)) });
577
+ }
578
+ // Annotate the CommonJS export names for ESM import in node:
579
+ 0 && (module.exports = {
580
+ Markdown,
581
+ defaultMarkdownIsSafeUrl,
582
+ parseInline,
583
+ parseMarkdown,
584
+ plainText
585
+ });
@@ -0,0 +1,115 @@
1
+ import * as react from 'react';
2
+
3
+ /**
4
+ * Allows http(s), mailto and same-app references (`/path`, `#anchor`, `./x`, `../x`).
5
+ * Browsers drop tabs and newlines inside URLs and read `\` as `/`, so those are removed
6
+ * or refused first: `//evil.test`, `/\evil.test` and `/<TAB>/evil.test` are not
7
+ * same-app paths.
8
+ */
9
+ declare function defaultIsSafeUrl(url: string): boolean;
10
+
11
+ /** Default link policy: http(s), mailto and same-app paths (`/`, `#`, `./`, `../`); never `//host`. */
12
+ declare const defaultMarkdownIsSafeUrl: typeof defaultIsSafeUrl;
13
+ interface MarkdownProps {
14
+ /** Raw markdown source. Empty or whitespace-only input renders nothing. */
15
+ children: string;
16
+ className?: string;
17
+ /** Link policy. Unsafe links render as their text, never as an anchor. */
18
+ isSafeUrl?: (url: string) => boolean;
19
+ /**
20
+ * Image policy. Return the URL to load, or `null` to show the image as a link
21
+ * (subject to `isSafeUrl`). Without it, no `<img>` is ever rendered.
22
+ */
23
+ resolveImageSrc?: (src: string) => string | null;
24
+ /**
25
+ * Added to markdown heading levels so content headings sit below the page's own
26
+ * (`#` → `<h3>` by default, as in TENSOR's original renderer). Capped at `<h6>`.
27
+ */
28
+ headingOffset?: number;
29
+ }
30
+ /**
31
+ * Safe markdown viewer over `.uix-prose`. It never produces an HTML string and never
32
+ * uses `dangerouslySetInnerHTML`: author text only becomes React text nodes, raw HTML
33
+ * shows as literal text, and link/image URLs pass the policy props first.
34
+ *
35
+ * Supports headings, paragraphs (single newline = line break), bold, italic,
36
+ * strikethrough, inline and fenced code, links and bare http(s) URLs, blockquotes,
37
+ * horizontal rules, nested bulleted/numbered lists, read-only task lists, GFM tables
38
+ * (in a keyboard-scrollable wrapper) and images gated by `resolveImageSrc`.
39
+ * Server-component safe.
40
+ */
41
+ declare function Markdown({ children, className, isSafeUrl, resolveImageSrc, headingOffset }: MarkdownProps): react.JSX.Element | null;
42
+
43
+ type MarkdownInline = {
44
+ type: 'text';
45
+ value: string;
46
+ } | {
47
+ type: 'code';
48
+ value: string;
49
+ } | {
50
+ type: 'strong';
51
+ children: MarkdownInline[];
52
+ } | {
53
+ type: 'em';
54
+ children: MarkdownInline[];
55
+ } | {
56
+ type: 'del';
57
+ children: MarkdownInline[];
58
+ } | {
59
+ type: 'link';
60
+ href: string;
61
+ title?: string;
62
+ children: MarkdownInline[];
63
+ bare?: boolean;
64
+ } | {
65
+ type: 'image';
66
+ src: string;
67
+ alt: string;
68
+ title?: string;
69
+ } | {
70
+ type: 'br';
71
+ };
72
+ type TableAlign = 'left' | 'center' | 'right' | null;
73
+ interface MarkdownListItem {
74
+ /** `null` for a plain item, otherwise the task state. */
75
+ checked: boolean | null;
76
+ children: MarkdownInline[];
77
+ /** Nested lists. */
78
+ lists: MarkdownList[];
79
+ }
80
+ interface MarkdownList {
81
+ type: 'list';
82
+ ordered: boolean;
83
+ start: number;
84
+ items: MarkdownListItem[];
85
+ }
86
+ type MarkdownBlock = {
87
+ type: 'paragraph';
88
+ children: MarkdownInline[];
89
+ } | {
90
+ type: 'heading';
91
+ level: number;
92
+ children: MarkdownInline[];
93
+ } | {
94
+ type: 'code';
95
+ lang: string;
96
+ value: string;
97
+ } | {
98
+ type: 'quote';
99
+ children: MarkdownInline[];
100
+ } | {
101
+ type: 'rule';
102
+ } | MarkdownList | {
103
+ type: 'table';
104
+ align: TableAlign[];
105
+ head: MarkdownInline[][];
106
+ rows: MarkdownInline[][][];
107
+ };
108
+ /** Inline markdown to nodes. Newlines become line breaks. */
109
+ declare function parseInline(text: string, depth?: number): MarkdownInline[];
110
+ /** The text a reader sees, for accessible names and image alt text. */
111
+ declare function plainText(nodes: ReadonlyArray<MarkdownInline>): string;
112
+ /** Markdown source to blocks. Empty or whitespace-only input yields no blocks. */
113
+ declare function parseMarkdown(source: string): MarkdownBlock[];
114
+
115
+ export { Markdown, type MarkdownBlock, type MarkdownInline, type MarkdownList, type MarkdownListItem, type MarkdownProps, type TableAlign, defaultMarkdownIsSafeUrl, parseInline, parseMarkdown, plainText };