@nuucognition/ncm-ui 0.1.0-dev.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 (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +129 -0
  3. package/dist/blocks/admonition/index.d.ts +13 -0
  4. package/dist/blocks/admonition/index.js +1713 -0
  5. package/dist/blocks/aside/index.d.ts +13 -0
  6. package/dist/blocks/aside/index.js +1713 -0
  7. package/dist/blocks/attribution/index.d.ts +13 -0
  8. package/dist/blocks/attribution/index.js +32 -0
  9. package/dist/blocks/blockquote/index.d.ts +15 -0
  10. package/dist/blocks/blockquote/index.js +609 -0
  11. package/dist/blocks/chart/index.d.ts +14 -0
  12. package/dist/blocks/chart/index.js +29 -0
  13. package/dist/blocks/code/index.d.ts +15 -0
  14. package/dist/blocks/code/index.js +163 -0
  15. package/dist/blocks/container/index.d.ts +17 -0
  16. package/dist/blocks/container/index.js +633 -0
  17. package/dist/blocks/custom-code/index.d.ts +15 -0
  18. package/dist/blocks/custom-code/index.js +31 -0
  19. package/dist/blocks/dataview/index.d.ts +14 -0
  20. package/dist/blocks/dataview/index.js +29 -0
  21. package/dist/blocks/definition/index.d.ts +13 -0
  22. package/dist/blocks/definition/index.js +1713 -0
  23. package/dist/blocks/embed/index.d.ts +12 -0
  24. package/dist/blocks/embed/index.js +46 -0
  25. package/dist/blocks/embedding/index.d.ts +13 -0
  26. package/dist/blocks/embedding/index.js +763 -0
  27. package/dist/blocks/figure/index.d.ts +13 -0
  28. package/dist/blocks/figure/index.js +656 -0
  29. package/dist/blocks/footnote/index.d.ts +13 -0
  30. package/dist/blocks/footnote/index.js +1713 -0
  31. package/dist/blocks/frontmatter/index.d.ts +16 -0
  32. package/dist/blocks/frontmatter/index.js +38 -0
  33. package/dist/blocks/header/index.d.ts +9 -0
  34. package/dist/blocks/header/index.js +610 -0
  35. package/dist/blocks/horizontal-rule/index.d.ts +9 -0
  36. package/dist/blocks/horizontal-rule/index.js +19 -0
  37. package/dist/blocks/html/index.d.ts +31 -0
  38. package/dist/blocks/html/index.js +52 -0
  39. package/dist/blocks/index.d.ts +32 -0
  40. package/dist/blocks/index.js +1736 -0
  41. package/dist/blocks/latex/index.d.ts +9 -0
  42. package/dist/blocks/latex/index.js +107 -0
  43. package/dist/blocks/link/index.d.ts +14 -0
  44. package/dist/blocks/link/index.js +27 -0
  45. package/dist/blocks/list/index.d.ts +9 -0
  46. package/dist/blocks/list/index.js +675 -0
  47. package/dist/blocks/math/index.d.ts +13 -0
  48. package/dist/blocks/math/index.js +88 -0
  49. package/dist/blocks/mermaid/index.d.ts +14 -0
  50. package/dist/blocks/mermaid/index.js +29 -0
  51. package/dist/blocks/page-breaker/index.d.ts +16 -0
  52. package/dist/blocks/page-breaker/index.js +21 -0
  53. package/dist/blocks/paragraph/index.d.ts +9 -0
  54. package/dist/blocks/paragraph/index.js +608 -0
  55. package/dist/blocks/spoiler/index.d.ts +13 -0
  56. package/dist/blocks/spoiler/index.js +1713 -0
  57. package/dist/blocks/table/index.d.ts +9 -0
  58. package/dist/blocks/table/index.js +619 -0
  59. package/dist/blocks/task-list/index.d.ts +13 -0
  60. package/dist/blocks/task-list/index.js +670 -0
  61. package/dist/components/index.d.ts +599 -0
  62. package/dist/components/index.js +1840 -0
  63. package/dist/components/ncm-block.d.ts +28 -0
  64. package/dist/components/ncm-block.js +1712 -0
  65. package/dist/components/ncm-document.d.ts +48 -0
  66. package/dist/components/ncm-document.js +1839 -0
  67. package/dist/context/index.d.ts +7 -0
  68. package/dist/context/index.js +284 -0
  69. package/dist/hooks/index.d.ts +7 -0
  70. package/dist/hooks/index.js +1731 -0
  71. package/dist/hooks/use-block-renderer.d.ts +28 -0
  72. package/dist/hooks/use-block-renderer.js +1731 -0
  73. package/dist/hooks/use-ncm-config.d.ts +6 -0
  74. package/dist/hooks/use-ncm-config.js +11 -0
  75. package/dist/index.d.ts +43 -0
  76. package/dist/index.js +1887 -0
  77. package/dist/inline/index.d.ts +108 -0
  78. package/dist/inline/index.js +598 -0
  79. package/dist/inline-DwUYUmk4.d.ts +75 -0
  80. package/dist/lib/defaults.d.ts +24 -0
  81. package/dist/lib/defaults.js +1713 -0
  82. package/dist/lib/index.d.ts +2 -0
  83. package/dist/lib/index.js +10 -0
  84. package/dist/lib/katex.d.ts +3 -0
  85. package/dist/lib/katex.js +45 -0
  86. package/dist/lib/utils.d.ts +8 -0
  87. package/dist/lib/utils.js +10 -0
  88. package/dist/references-Bs5wJybr.d.ts +63 -0
  89. package/dist/renderers-C5f41FCy.d.ts +99 -0
  90. package/dist/styles/fonts/OpenDyslexic3-Bold.woff +0 -0
  91. package/dist/styles/fonts/OpenDyslexic3-Bold.woff2 +0 -0
  92. package/dist/styles/fonts/OpenDyslexic3-Regular.woff +0 -0
  93. package/dist/styles/fonts/OpenDyslexic3-Regular.woff2 +0 -0
  94. package/dist/styles/nuu.css +364 -0
  95. package/dist/styles/paper.css +332 -0
  96. package/dist/types/index.d.ts +4 -0
  97. package/dist/types/index.js +2 -0
  98. package/dist/use-ncm-config-D0doMYTH.d.ts +114 -0
  99. package/package.json +99 -0
package/dist/index.js ADDED
@@ -0,0 +1,1887 @@
1
+ "use client";
2
+ import { createContext, useContext, useMemo, useRef, useId, useCallback, useState, createElement, useEffect, Component } from 'react';
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+ import { serializeInlineContent, sanitizeHtml, isTypedNestedList } from '@nuucognition/ncm';
5
+ import { clsx } from 'clsx';
6
+ import { twMerge } from 'tailwind-merge';
7
+ import { extractExtension, embedTypeFromExtension } from '@nuucognition/mesh-core';
8
+
9
+ // src/context/ncm-context.tsx
10
+ var NcmContext = createContext(null);
11
+ function useNcmConfig() {
12
+ return useContext(NcmContext) ?? {};
13
+ }
14
+ function NcmProvider({ config, children }) {
15
+ const value = useMemo(() => config ?? {}, [config]);
16
+ return /* @__PURE__ */ jsx(NcmContext.Provider, { value, children });
17
+ }
18
+
19
+ // src/inline/parser.ts
20
+ function splitOnce(input, delimiter) {
21
+ const idx = input.indexOf(delimiter);
22
+ if (idx === -1) {
23
+ return [input, null];
24
+ }
25
+ return [input.slice(0, idx), input.slice(idx + delimiter.length)];
26
+ }
27
+ function parseWikiTarget(rawInside) {
28
+ const inside = rawInside.trim();
29
+ const [targetPlusAnchor, displayRaw] = splitOnce(inside, "|");
30
+ const [targetRaw, anchorRaw] = splitOnce(targetPlusAnchor, "#");
31
+ const target = targetRaw.trim();
32
+ const display = displayRaw !== null ? displayRaw.trim() || null : null;
33
+ const anchor = anchorRaw !== null ? anchorRaw.trim() || null : null;
34
+ return { target, display, anchor };
35
+ }
36
+ var INLINE_REF_KIND_RE = /^\s*(ref|footnote)\s*:\s*([\s\S]*)$/i;
37
+ function tryParseInlineRef(input) {
38
+ let depth = 1;
39
+ let i = 2;
40
+ for (; i < input.length; i++) {
41
+ const ch = input[i];
42
+ if (ch === "[") {
43
+ depth++;
44
+ } else if (ch === "]") {
45
+ depth--;
46
+ if (depth === 0) break;
47
+ }
48
+ }
49
+ if (depth !== 0) return null;
50
+ const inner = input.slice(2, i);
51
+ const length = i + 1;
52
+ const match = INLINE_REF_KIND_RE.exec(inner);
53
+ if (match && match[1]) {
54
+ const kind = match[1].toLowerCase() === "ref" ? "ref" : "footnote";
55
+ return { token: { type: "inline_ref", kind, content: (match[2] ?? "").trim() }, length };
56
+ }
57
+ return { token: { type: "inline_ref", kind: "footnote", content: inner.trim() }, length };
58
+ }
59
+ function parseInline(content) {
60
+ if (!content) return [];
61
+ const tokens = [];
62
+ let remaining = content;
63
+ while (remaining.length > 0) {
64
+ const codeMatch = remaining.match(/^`([^`]+)`/);
65
+ if (codeMatch && codeMatch[1] !== void 0) {
66
+ tokens.push({ type: "code", content: codeMatch[1] });
67
+ remaining = remaining.slice(codeMatch[0].length);
68
+ continue;
69
+ }
70
+ const latexMatch = remaining.match(/^\$(?!\s)([^$\n]+?)(?<!\s)\$/);
71
+ if (latexMatch && latexMatch[1] !== void 0) {
72
+ tokens.push({ type: "latex", content: latexMatch[1] });
73
+ remaining = remaining.slice(latexMatch[0].length);
74
+ continue;
75
+ }
76
+ if (remaining.startsWith("^[")) {
77
+ const inlineRef = tryParseInlineRef(remaining);
78
+ if (inlineRef) {
79
+ tokens.push(inlineRef.token);
80
+ remaining = remaining.slice(inlineRef.length);
81
+ continue;
82
+ }
83
+ }
84
+ const wikiEmbedMatch = remaining.match(/^!\[\[([^\]]+)\]\]/);
85
+ if (wikiEmbedMatch && wikiEmbedMatch[1] !== void 0) {
86
+ const parsed = parseWikiTarget(wikiEmbedMatch[1]);
87
+ tokens.push({
88
+ type: "wiki_embed",
89
+ target: parsed.target,
90
+ display: parsed.display,
91
+ anchor: parsed.anchor
92
+ });
93
+ remaining = remaining.slice(wikiEmbedMatch[0].length);
94
+ continue;
95
+ }
96
+ const wikiLinkMatch = remaining.match(/^\[\[([^\]]+)\]\]/);
97
+ if (wikiLinkMatch && wikiLinkMatch[1] !== void 0) {
98
+ const parsed = parseWikiTarget(wikiLinkMatch[1]);
99
+ tokens.push({
100
+ type: "wiki_link",
101
+ target: parsed.target,
102
+ display: parsed.display,
103
+ anchor: parsed.anchor
104
+ });
105
+ remaining = remaining.slice(wikiLinkMatch[0].length);
106
+ continue;
107
+ }
108
+ const imageMatch = remaining.match(/^!\[([^\]]*)\]\(([^)\s]+)(?:\s+"([^"]+)")?\)/);
109
+ if (imageMatch && imageMatch[1] !== void 0 && imageMatch[2] !== void 0) {
110
+ tokens.push({
111
+ type: "image",
112
+ alt: imageMatch[1],
113
+ src: imageMatch[2],
114
+ title: imageMatch[3]
115
+ });
116
+ remaining = remaining.slice(imageMatch[0].length);
117
+ continue;
118
+ }
119
+ const linkMatch = remaining.match(/^\[([^\]]+)\]\(([^)\s]+)(?:\s+"([^"]+)")?\)/);
120
+ if (linkMatch && linkMatch[1] !== void 0 && linkMatch[2] !== void 0) {
121
+ tokens.push({
122
+ type: "link",
123
+ href: linkMatch[2],
124
+ title: linkMatch[3],
125
+ children: parseInline(linkMatch[1])
126
+ });
127
+ remaining = remaining.slice(linkMatch[0].length);
128
+ continue;
129
+ }
130
+ const boldMatch = remaining.match(/^\*\*(.+?)\*\*|^__(.+?)__/);
131
+ if (boldMatch) {
132
+ const innerContent = boldMatch[1] ?? boldMatch[2];
133
+ if (innerContent !== void 0) {
134
+ tokens.push({
135
+ type: "bold",
136
+ children: parseInline(innerContent)
137
+ });
138
+ remaining = remaining.slice(boldMatch[0].length);
139
+ continue;
140
+ }
141
+ }
142
+ const strikeMatch = remaining.match(/^~~(.+?)~~/);
143
+ if (strikeMatch && strikeMatch[1] !== void 0) {
144
+ tokens.push({
145
+ type: "strikethrough",
146
+ children: parseInline(strikeMatch[1])
147
+ });
148
+ remaining = remaining.slice(strikeMatch[0].length);
149
+ continue;
150
+ }
151
+ const italicMatch = remaining.match(/^\*([^*]+)\*|^_([^_]+)_/);
152
+ if (italicMatch) {
153
+ const innerContent = italicMatch[1] ?? italicMatch[2];
154
+ if (innerContent !== void 0) {
155
+ tokens.push({
156
+ type: "italic",
157
+ children: parseInline(innerContent)
158
+ });
159
+ remaining = remaining.slice(italicMatch[0].length);
160
+ continue;
161
+ }
162
+ }
163
+ const nextSpecial = findNextSpecialChar(remaining);
164
+ if (nextSpecial > 0) {
165
+ tokens.push({ type: "text", content: remaining.slice(0, nextSpecial) });
166
+ remaining = remaining.slice(nextSpecial);
167
+ } else {
168
+ tokens.push({ type: "text", content: remaining });
169
+ remaining = "";
170
+ }
171
+ }
172
+ return mergeAdjacentText(tokens);
173
+ }
174
+ function findNextSpecialChar(content) {
175
+ const specialChars = ["`", "$", "!", "[", "*", "_", "~", "^"];
176
+ let minIndex = -1;
177
+ for (const char of specialChars) {
178
+ const index = content.indexOf(char);
179
+ if (index > 0 && (minIndex === -1 || index < minIndex)) {
180
+ minIndex = index;
181
+ }
182
+ }
183
+ return minIndex;
184
+ }
185
+ function mergeAdjacentText(tokens) {
186
+ const result = [];
187
+ for (const token of tokens) {
188
+ const last = result[result.length - 1];
189
+ if (token.type === "text" && last?.type === "text") {
190
+ last.content += token.content;
191
+ } else {
192
+ result.push(token);
193
+ }
194
+ }
195
+ return result;
196
+ }
197
+ function collectInlineStrings(block) {
198
+ switch (block.type) {
199
+ case "paragraph":
200
+ case "header":
201
+ case "blockquote":
202
+ return [block.content ?? ""];
203
+ case "list_ordered":
204
+ case "list_unordered":
205
+ return collectListStrings(block.items ?? []);
206
+ case "table": {
207
+ const t = block;
208
+ return [...t.headers ?? [], ...(t.rows ?? []).flat()];
209
+ }
210
+ case "embedding": {
211
+ const caption = block.caption;
212
+ return caption ? [caption] : [];
213
+ }
214
+ default:
215
+ return [];
216
+ }
217
+ }
218
+ function collectListStrings(items) {
219
+ const out = [];
220
+ for (const item of items) {
221
+ if (typeof item === "string") {
222
+ out.push(item);
223
+ } else if (isTypedNestedList(item)) {
224
+ out.push(...collectListStrings(item.items));
225
+ } else if (Array.isArray(item) && item.length > 0) {
226
+ const [first, ...rest] = item;
227
+ if (typeof first === "string") out.push(first);
228
+ out.push(...collectListStrings(rest));
229
+ }
230
+ }
231
+ return out;
232
+ }
233
+ function countInlineRefs(tokens, acc) {
234
+ for (const token of tokens) {
235
+ if (token.type === "inline_ref") {
236
+ acc[token.kind] += 1;
237
+ } else if ("children" in token) {
238
+ countInlineRefs(token.children, acc);
239
+ }
240
+ }
241
+ }
242
+ function countBlock(block) {
243
+ const acc = { ref: 0, footnote: 0 };
244
+ for (const str of collectInlineStrings(block)) {
245
+ if (str) countInlineRefs(parseInline(str), acc);
246
+ }
247
+ return acc;
248
+ }
249
+ function computeReferenceBases(blocks) {
250
+ const bases = /* @__PURE__ */ new Map();
251
+ const acc = { ref: 0, footnote: 0 };
252
+ for (const block of blocks) {
253
+ bases.set(block.id, { ...acc });
254
+ const counts = countBlock(block);
255
+ acc.ref += counts.ref;
256
+ acc.footnote += counts.footnote;
257
+ }
258
+ return bases;
259
+ }
260
+ var ReferenceBasesContext = createContext(null);
261
+ var BlockReferenceScopeContext = createContext(null);
262
+ function NcmReferencesProvider({ blocks, children }) {
263
+ const bases = useMemo(() => computeReferenceBases(blocks), [blocks]);
264
+ return /* @__PURE__ */ jsx(ReferenceBasesContext.Provider, { value: bases, children });
265
+ }
266
+ function BlockReferenceScope({ blockId, children }) {
267
+ const bases = useContext(ReferenceBasesContext);
268
+ const base = (blockId ? bases?.get(blockId) : void 0) ?? { ref: 0, footnote: 0 };
269
+ const counter = useRef({ ref: 0, footnote: 0 });
270
+ counter.current = { ref: 0, footnote: 0 };
271
+ const value = {
272
+ next(kind) {
273
+ counter.current[kind] += 1;
274
+ return base[kind] + counter.current[kind];
275
+ }
276
+ };
277
+ return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value, children });
278
+ }
279
+ function useBlockReferenceScope() {
280
+ return useContext(BlockReferenceScopeContext);
281
+ }
282
+ var INERT_SCOPE = { next: () => 0 };
283
+ function InertReferenceScope({ children }) {
284
+ return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value: INERT_SCOPE, children });
285
+ }
286
+ function cn(...inputs) {
287
+ return twMerge(clsx(inputs));
288
+ }
289
+ function defaultTitle(type) {
290
+ return type.charAt(0).toUpperCase() + type.slice(1);
291
+ }
292
+ function AdmonitionBlock({ block, className }) {
293
+ const title = block.title ?? defaultTitle(block.admonitionType);
294
+ const classes = cn("rounded-lg border border-border bg-card p-4", className);
295
+ if (block.collapsible) {
296
+ return /* @__PURE__ */ jsxs(
297
+ BlockShell,
298
+ {
299
+ as: "details",
300
+ block,
301
+ "data-ncm-admonition": "",
302
+ "data-ncm-admonition-type": block.admonitionType,
303
+ open: !block.collapsed,
304
+ className: classes,
305
+ children: [
306
+ /* @__PURE__ */ jsx("summary", { className: "cursor-pointer font-medium", "data-ncm-admonition-title": "", children: title }),
307
+ /* @__PURE__ */ jsx(ChildBlocks, { blocks: block.children, className: "mt-2 space-y-2" })
308
+ ]
309
+ }
310
+ );
311
+ }
312
+ return /* @__PURE__ */ jsxs(
313
+ BlockShell,
314
+ {
315
+ block,
316
+ "data-ncm-admonition": "",
317
+ "data-ncm-admonition-type": block.admonitionType,
318
+ className: classes,
319
+ children: [
320
+ /* @__PURE__ */ jsx("p", { className: "mb-2 font-medium", "data-ncm-admonition-title": "", children: title }),
321
+ /* @__PURE__ */ jsx(ChildBlocks, { blocks: block.children, className: "space-y-2" })
322
+ ]
323
+ }
324
+ );
325
+ }
326
+ function AsideBlock({ block, className }) {
327
+ return /* @__PURE__ */ jsx(
328
+ BlockShell,
329
+ {
330
+ as: "aside",
331
+ block,
332
+ "data-ncm-aside": "",
333
+ className: cn("border-l-2 border-border pl-4 text-muted-foreground", className),
334
+ children: /* @__PURE__ */ jsx(ChildBlocks, { blocks: block.content, className: "space-y-2" })
335
+ }
336
+ );
337
+ }
338
+ function AttributionBlock({ block, className }) {
339
+ return /* @__PURE__ */ jsxs(
340
+ "p",
341
+ {
342
+ "data-ncm-block": block.id,
343
+ "data-ncm-stable": block.stableId,
344
+ "data-ncm-type": block.type,
345
+ "data-block-id": block.id,
346
+ "data-ncm-attribution": "",
347
+ className: cn("text-sm text-muted-foreground", className),
348
+ children: [
349
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2014 " }),
350
+ block.url ? /* @__PURE__ */ jsx("a", { href: block.url, className: "hover:underline", children: /* @__PURE__ */ jsx("cite", { children: block.source }) }) : /* @__PURE__ */ jsx("cite", { children: block.source }),
351
+ block.date ? /* @__PURE__ */ jsxs("span", { children: [
352
+ ", ",
353
+ block.date
354
+ ] }) : null
355
+ ]
356
+ }
357
+ );
358
+ }
359
+ function clipBounds(el) {
360
+ for (let node = el.parentElement; node; node = node.parentElement) {
361
+ const s = getComputedStyle(node);
362
+ if (/(auto|scroll|hidden)/.test(s.overflowX) || /(auto|scroll|hidden)/.test(s.overflowY)) {
363
+ const r = node.getBoundingClientRect();
364
+ return { left: r.left, right: r.right, top: r.top, bottom: r.bottom };
365
+ }
366
+ }
367
+ return { left: 0, right: window.innerWidth, top: 0, bottom: window.innerHeight };
368
+ }
369
+ function ReferenceMarker({ kind, number, children }) {
370
+ const config = useNcmConfig();
371
+ const popoverEnabled = config.inline?.referencePopover !== false && children != null;
372
+ const popoverId = useId();
373
+ const isRef = kind === "ref";
374
+ const popoverRef = useRef(null);
375
+ const positionPopover = useCallback(() => {
376
+ const el = popoverRef.current;
377
+ if (!el) return;
378
+ el.style.transform = "";
379
+ el.style.top = "";
380
+ el.style.bottom = "";
381
+ const margin = 8;
382
+ const bounds = clipBounds(el);
383
+ const rect = el.getBoundingClientRect();
384
+ if (rect.bottom > bounds.bottom - margin && rect.height < rect.top - bounds.top) {
385
+ el.style.top = "auto";
386
+ el.style.bottom = "1.6em";
387
+ }
388
+ let dx = 0;
389
+ if (rect.right > bounds.right - margin) dx = bounds.right - margin - rect.right;
390
+ if (rect.left + dx < bounds.left + margin) dx = bounds.left + margin - rect.left;
391
+ if (dx) el.style.transform = `translateX(${Math.round(dx)}px)`;
392
+ }, []);
393
+ const describedBy = popoverEnabled ? popoverId : void 0;
394
+ const label = `${isRef ? "Reference" : "Footnote"} ${number}`;
395
+ const marker = isRef ? /* @__PURE__ */ jsx(
396
+ "span",
397
+ {
398
+ "data-ncm-ref-marker": "",
399
+ tabIndex: 0,
400
+ role: "note",
401
+ "aria-label": label,
402
+ "aria-describedby": describedBy,
403
+ children: `[${number}]`
404
+ }
405
+ ) : /* @__PURE__ */ jsx(
406
+ "sup",
407
+ {
408
+ "data-ncm-ref-marker": "",
409
+ tabIndex: 0,
410
+ role: "note",
411
+ "aria-label": label,
412
+ "aria-describedby": describedBy,
413
+ children: number
414
+ }
415
+ );
416
+ return /* @__PURE__ */ jsxs(
417
+ "span",
418
+ {
419
+ "data-ncm-token": isRef ? "reference" : "footnote",
420
+ "data-ncm-ref-kind": kind,
421
+ "data-ncm-ref-number": number,
422
+ onMouseEnter: popoverEnabled ? positionPopover : void 0,
423
+ onFocus: popoverEnabled ? positionPopover : void 0,
424
+ children: [
425
+ marker,
426
+ popoverEnabled ? /* @__PURE__ */ jsx("span", { id: popoverId, ref: popoverRef, role: "tooltip", "data-ncm-ref-popover": "", children }) : null
427
+ ]
428
+ }
429
+ );
430
+ }
431
+ var katexPromise = null;
432
+ function loadKatex() {
433
+ if (!katexPromise) {
434
+ katexPromise = Promise.all([
435
+ import('katex'),
436
+ import('katex/dist/katex.min.css')
437
+ ]).then(([module]) => module.default).catch(() => null);
438
+ }
439
+ return katexPromise;
440
+ }
441
+ function useKatexHtml(content, displayMode, enabled = true) {
442
+ const [katexModule, setKatexModule] = useState(null);
443
+ useEffect(() => {
444
+ if (!enabled) {
445
+ return;
446
+ }
447
+ let active = true;
448
+ loadKatex().then((loaded) => {
449
+ if (active) {
450
+ setKatexModule(loaded);
451
+ }
452
+ });
453
+ return () => {
454
+ active = false;
455
+ };
456
+ }, [enabled]);
457
+ return useMemo(() => {
458
+ if (!enabled || !katexModule) {
459
+ return null;
460
+ }
461
+ try {
462
+ return katexModule.renderToString(content, {
463
+ throwOnError: false,
464
+ displayMode
465
+ });
466
+ } catch {
467
+ return null;
468
+ }
469
+ }, [content, displayMode, enabled, katexModule]);
470
+ }
471
+ function InlineContent({
472
+ content,
473
+ className,
474
+ disableBionic,
475
+ disableBeeline
476
+ }) {
477
+ const tokens = useMemo(() => parseInline(content), [content]);
478
+ const hasScope = useBlockReferenceScope() != null;
479
+ const rendered = tokens.map((token, index) => /* @__PURE__ */ jsx(
480
+ TokenRenderer,
481
+ {
482
+ token,
483
+ disableBionic,
484
+ disableBeeline
485
+ },
486
+ index
487
+ ));
488
+ const body = className ? /* @__PURE__ */ jsx("span", { "data-ncm-inline": "", className, children: rendered }) : /* @__PURE__ */ jsx(Fragment, { children: rendered });
489
+ return hasScope ? body : /* @__PURE__ */ jsx(BlockReferenceScope, { children: body });
490
+ }
491
+ function TokenRenderer({ token, disableBionic, disableBeeline }) {
492
+ const config = useNcmConfig();
493
+ const refScope = useBlockReferenceScope();
494
+ const bionicOn = !disableBionic && Boolean(config.reading?.bionic);
495
+ const beelineOn = !disableBeeline && Boolean(config.reading?.beeline);
496
+ const latexContent = token.type === "latex" ? token.content : "";
497
+ const latexHtml = useKatexHtml(latexContent, false, token.type === "latex");
498
+ switch (token.type) {
499
+ case "text":
500
+ if (bionicOn || beelineOn) {
501
+ return renderReadingText(token.content, {
502
+ bionic: bionicOn,
503
+ bionicRatio: config.reading?.bionicRatio,
504
+ beeline: beelineOn
505
+ });
506
+ }
507
+ return /* @__PURE__ */ jsx(Fragment, { children: token.content });
508
+ case "bold":
509
+ return /* @__PURE__ */ jsx("strong", { "data-ncm-token": "bold", children: token.children.map((child, i) => /* @__PURE__ */ jsx(
510
+ TokenRenderer,
511
+ {
512
+ token: child,
513
+ disableBionic,
514
+ disableBeeline
515
+ },
516
+ i
517
+ )) });
518
+ case "italic":
519
+ return /* @__PURE__ */ jsx("em", { "data-ncm-token": "italic", children: token.children.map((child, i) => /* @__PURE__ */ jsx(
520
+ TokenRenderer,
521
+ {
522
+ token: child,
523
+ disableBionic,
524
+ disableBeeline
525
+ },
526
+ i
527
+ )) });
528
+ case "code":
529
+ return /* @__PURE__ */ jsx("code", { "data-ncm-token": "code", children: token.content });
530
+ case "link": {
531
+ const handleClick = (e) => {
532
+ config.inline?.onLinkClick?.(token.href, e);
533
+ };
534
+ return /* @__PURE__ */ jsx(
535
+ "a",
536
+ {
537
+ "data-ncm-token": "link",
538
+ href: token.href,
539
+ title: token.title,
540
+ onClick: handleClick,
541
+ children: token.children.map((child, i) => /* @__PURE__ */ jsx(
542
+ TokenRenderer,
543
+ {
544
+ token: child,
545
+ disableBionic,
546
+ disableBeeline
547
+ },
548
+ i
549
+ ))
550
+ }
551
+ );
552
+ }
553
+ case "wiki_link": {
554
+ const result = config.mesh?.resolveLink(token.target) ?? {
555
+ status: "missing",
556
+ target: token.target,
557
+ resolved: null,
558
+ candidates: []
559
+ };
560
+ const href = config.inline?.resolveWikiLinkHref?.(token.target, result) ?? null;
561
+ const label = token.display ?? token.target;
562
+ if (href) {
563
+ const handleClick = (e) => {
564
+ config.inline?.onWikiLinkClick?.(token.target, result, e);
565
+ };
566
+ return /* @__PURE__ */ jsx(
567
+ "a",
568
+ {
569
+ "data-ncm-token": "wiki_link",
570
+ "data-ncm-wikilink-status": result.status,
571
+ href,
572
+ onClick: handleClick,
573
+ children: label
574
+ }
575
+ );
576
+ }
577
+ if (config.inline?.onWikiLinkClick) {
578
+ const handleClick = (e) => {
579
+ config.inline?.onWikiLinkClick?.(token.target, result, e);
580
+ };
581
+ return /* @__PURE__ */ jsx(
582
+ "button",
583
+ {
584
+ type: "button",
585
+ "data-ncm-token": "wiki_link",
586
+ "data-ncm-wikilink-status": result.status,
587
+ onClick: handleClick,
588
+ children: label
589
+ }
590
+ );
591
+ }
592
+ return /* @__PURE__ */ jsx("span", { "data-ncm-token": "wiki_link", "data-ncm-wikilink-status": result.status, children: label });
593
+ }
594
+ case "latex": {
595
+ const CustomRenderer = config.inline?.customLatexRenderer;
596
+ if (CustomRenderer) {
597
+ return /* @__PURE__ */ jsx(CustomRenderer, { content: token.content, display: false });
598
+ }
599
+ if (latexHtml) {
600
+ return /* @__PURE__ */ jsx("span", { "data-ncm-token": "latex", dangerouslySetInnerHTML: { __html: latexHtml } });
601
+ }
602
+ return /* @__PURE__ */ jsx("code", { "data-ncm-token": "latex", children: token.content });
603
+ }
604
+ case "strikethrough":
605
+ return /* @__PURE__ */ jsx("del", { "data-ncm-token": "strikethrough", children: token.children.map((child, i) => /* @__PURE__ */ jsx(
606
+ TokenRenderer,
607
+ {
608
+ token: child,
609
+ disableBionic,
610
+ disableBeeline
611
+ },
612
+ i
613
+ )) });
614
+ case "image": {
615
+ const src = config.inline?.resolveAssetPath?.(token.src) ?? token.src;
616
+ return /* @__PURE__ */ jsx(
617
+ "img",
618
+ {
619
+ "data-ncm-token": "image",
620
+ src,
621
+ alt: token.alt,
622
+ title: token.title
623
+ }
624
+ );
625
+ }
626
+ case "wiki_embed": {
627
+ const extension = extractExtension(token.target);
628
+ const embedType = embedTypeFromExtension(extension);
629
+ const result = config.mesh?.resolveEmbed(token.target) ?? null;
630
+ const url = config.embeddings?.resolveUrl?.(token.target, embedType) ?? token.target;
631
+ if (result?.status === "missing") {
632
+ return /* @__PURE__ */ jsx(
633
+ "span",
634
+ {
635
+ "data-ncm-token": "wiki_embed",
636
+ "data-ncm-wikiembed-status": "missing",
637
+ children: `![[${token.target}]]`
638
+ }
639
+ );
640
+ }
641
+ if (result?.status === "ambiguous") {
642
+ return /* @__PURE__ */ jsx(
643
+ "span",
644
+ {
645
+ "data-ncm-token": "wiki_embed",
646
+ "data-ncm-wikiembed-status": "ambiguous",
647
+ children: `![[${token.target}]]`
648
+ }
649
+ );
650
+ }
651
+ if (embedType === "image") {
652
+ return /* @__PURE__ */ jsx(
653
+ "img",
654
+ {
655
+ "data-ncm-token": "wiki_embed",
656
+ "data-ncm-wikiembed-type": embedType,
657
+ src: url,
658
+ alt: token.display ?? token.target,
659
+ className: config.embeddings?.imageClassName
660
+ }
661
+ );
662
+ }
663
+ if (embedType === "video") {
664
+ return /* @__PURE__ */ jsx(
665
+ "video",
666
+ {
667
+ "data-ncm-token": "wiki_embed",
668
+ "data-ncm-wikiembed-type": embedType,
669
+ src: url,
670
+ controls: true,
671
+ className: config.embeddings?.videoClassName
672
+ }
673
+ );
674
+ }
675
+ if (embedType === "audio") {
676
+ return /* @__PURE__ */ jsx(
677
+ "audio",
678
+ {
679
+ "data-ncm-token": "wiki_embed",
680
+ "data-ncm-wikiembed-type": embedType,
681
+ src: url,
682
+ controls: true,
683
+ className: config.embeddings?.audioClassName
684
+ }
685
+ );
686
+ }
687
+ return /* @__PURE__ */ jsx(
688
+ "a",
689
+ {
690
+ "data-ncm-token": "wiki_embed",
691
+ "data-ncm-wikiembed-type": embedType,
692
+ href: url,
693
+ children: token.display ?? token.target
694
+ }
695
+ );
696
+ }
697
+ case "inline_ref": {
698
+ const number = refScope?.next(token.kind) ?? 0;
699
+ return /* @__PURE__ */ jsx(ReferenceMarker, { kind: token.kind, number, children: token.content ? /* @__PURE__ */ jsx(InertReferenceScope, { children: /* @__PURE__ */ jsx(InlineContent, { content: token.content, disableBionic: true, disableBeeline: true }) }) : null });
700
+ }
701
+ default:
702
+ return null;
703
+ }
704
+ }
705
+ function renderReadingText(content, opts) {
706
+ if (!content) return /* @__PURE__ */ jsx(Fragment, { children: content });
707
+ const { bionic = false, beeline = false } = opts;
708
+ if (!bionic && !beeline) return /* @__PURE__ */ jsx(Fragment, { children: content });
709
+ const ratio = Math.min(1, Math.max(0.05, opts.bionicRatio ?? 0.5));
710
+ const pieces = [];
711
+ const regex = /[\p{L}\p{N}][\p{L}\p{N}\p{M}'’-]*/gu;
712
+ let match;
713
+ let key = 0;
714
+ let cursor = 0;
715
+ while ((match = regex.exec(content)) !== null) {
716
+ if (match.index > cursor) pieces.push(content.slice(cursor, match.index));
717
+ const segment = match[0];
718
+ const wrapperProps = {};
719
+ if (bionic) wrapperProps["data-ncm-bionic"] = "";
720
+ if (beeline) wrapperProps["data-ncm-beeline-word"] = "";
721
+ if (bionic) {
722
+ const headLen = Math.max(1, Math.ceil(segment.length * ratio));
723
+ pieces.push(
724
+ /* @__PURE__ */ jsxs("span", { ...wrapperProps, children: [
725
+ /* @__PURE__ */ jsx("span", { "data-ncm-bionic-bold": "", style: { fontWeight: 600 }, children: segment.slice(0, headLen) }),
726
+ segment.slice(headLen)
727
+ ] }, key++)
728
+ );
729
+ } else {
730
+ pieces.push(
731
+ /* @__PURE__ */ jsx("span", { ...wrapperProps, children: segment }, key++)
732
+ );
733
+ }
734
+ cursor = match.index + segment.length;
735
+ }
736
+ if (cursor < content.length) pieces.push(content.slice(cursor));
737
+ return /* @__PURE__ */ jsx(Fragment, { children: pieces });
738
+ }
739
+ function renderBionicText(content, ratio = 0.5) {
740
+ return renderReadingText(content, { bionic: true, bionicRatio: ratio });
741
+ }
742
+ function renderBeelineText(content) {
743
+ return renderReadingText(content, { beeline: true });
744
+ }
745
+ function BlockquoteBlock({ block, className }) {
746
+ const lines = block.content.split("\n").filter((line) => line.trim() !== "");
747
+ return /* @__PURE__ */ jsx(
748
+ "blockquote",
749
+ {
750
+ "data-ncm-block": block.id,
751
+ "data-ncm-stable": block.stableId,
752
+ "data-ncm-type": block.type,
753
+ "data-block-id": block.id,
754
+ "data-ncm-blockquote": "",
755
+ className,
756
+ children: lines.length <= 1 ? /* @__PURE__ */ jsx(InlineContent, { content: block.content }) : lines.map((line, index) => /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx(InlineContent, { content: line }) }, index))
757
+ }
758
+ );
759
+ }
760
+ function ChartBlock({ block, className }) {
761
+ return /* @__PURE__ */ jsx(
762
+ "pre",
763
+ {
764
+ "data-ncm-block": block.id,
765
+ "data-ncm-stable": block.stableId,
766
+ "data-ncm-type": block.type,
767
+ "data-block-id": block.id,
768
+ "data-ncm-chart": "",
769
+ "data-ncm-chart-type": block.chartType ?? "unknown",
770
+ className: cn(
771
+ "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
772
+ className
773
+ ),
774
+ children: /* @__PURE__ */ jsx("code", { children: block.content })
775
+ }
776
+ );
777
+ }
778
+ var highlighterPromise = import('shiki/bundle/web').then(async (shiki) => {
779
+ const highlighter = await shiki.createHighlighter({
780
+ themes: ["github-light", "github-dark"],
781
+ langs: Object.keys(shiki.bundledLanguages)
782
+ });
783
+ return highlighter;
784
+ }).catch(() => null);
785
+ function useIsDark() {
786
+ const [isDark, setIsDark] = useState(false);
787
+ useEffect(() => {
788
+ if (typeof document === "undefined") return;
789
+ const root = document.documentElement;
790
+ const update = () => setIsDark(root.classList.contains("dark"));
791
+ update();
792
+ const observer = new MutationObserver(update);
793
+ observer.observe(root, { attributes: true, attributeFilter: ["class"] });
794
+ return () => observer.disconnect();
795
+ }, []);
796
+ return isDark;
797
+ }
798
+ function DefaultShikiRenderer({
799
+ code,
800
+ language
801
+ }) {
802
+ const isDark = useIsDark();
803
+ const [highlighter, setHighlighter] = useState(null);
804
+ const shikiTheme = isDark ? "github-dark" : "github-light";
805
+ useEffect(() => {
806
+ let active = true;
807
+ highlighterPromise.then((h) => {
808
+ if (active) setHighlighter(h);
809
+ });
810
+ return () => {
811
+ active = false;
812
+ };
813
+ }, []);
814
+ const tokens = useMemo(() => {
815
+ if (!highlighter) return null;
816
+ const loaded = highlighter.getLoadedLanguages();
817
+ const lang = language && loaded.includes(language) ? language : "text";
818
+ try {
819
+ return highlighter.codeToTokens(code, { lang, theme: shikiTheme }).tokens;
820
+ } catch {
821
+ return null;
822
+ }
823
+ }, [code, language, highlighter, shikiTheme]);
824
+ if (!tokens) {
825
+ return /* @__PURE__ */ jsx(Fragment, { children: code });
826
+ }
827
+ return /* @__PURE__ */ jsx(Fragment, { children: tokens.map((line, lineIndex) => /* @__PURE__ */ jsx("span", { className: "block whitespace-pre", children: line.length === 0 ? " " : line.map((token, tokenIndex) => /* @__PURE__ */ jsx("span", { style: { color: token.color || "inherit" }, children: token.content }, tokenIndex)) }, lineIndex)) });
828
+ }
829
+ function CopyButton({ content }) {
830
+ const [copied, setCopied] = useState(false);
831
+ const handleCopy = useCallback(async () => {
832
+ try {
833
+ await navigator.clipboard.writeText(content);
834
+ setCopied(true);
835
+ setTimeout(() => setCopied(false), 2e3);
836
+ } catch {
837
+ const textarea = document.createElement("textarea");
838
+ textarea.value = content;
839
+ document.body.appendChild(textarea);
840
+ textarea.select();
841
+ document.execCommand("copy");
842
+ document.body.removeChild(textarea);
843
+ setCopied(true);
844
+ setTimeout(() => setCopied(false), 2e3);
845
+ }
846
+ }, [content]);
847
+ return /* @__PURE__ */ jsx(
848
+ "button",
849
+ {
850
+ type: "button",
851
+ onClick: handleCopy,
852
+ "aria-label": copied ? "Copied!" : "Copy code",
853
+ "data-ncm-copy-button": "",
854
+ className: "absolute right-2 top-2 rounded-md bg-background/80 px-2 py-1 text-xs font-medium text-muted-foreground hover:bg-background hover:text-foreground focus:outline-none focus:ring-2 focus:ring-ring",
855
+ children: copied ? "Copied!" : "Copy"
856
+ }
857
+ );
858
+ }
859
+ function LineNumbers({ count }) {
860
+ return /* @__PURE__ */ jsx(
861
+ "div",
862
+ {
863
+ "aria-hidden": "true",
864
+ "data-ncm-line-numbers": "",
865
+ className: "select-none pr-4 text-right text-muted-foreground/60",
866
+ children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx("div", { children: i + 1 }, i + 1))
867
+ }
868
+ );
869
+ }
870
+ function CodeBlock({ block, className }) {
871
+ const config = useNcmConfig();
872
+ const { code: codeConfig } = config;
873
+ const lineCount = block.content.split("\n").length;
874
+ const languageLabel = block.language ? /* @__PURE__ */ jsx(
875
+ "div",
876
+ {
877
+ "data-ncm-code-language": "",
878
+ className: "absolute right-2 bottom-2 text-xs text-muted-foreground/60",
879
+ children: block.language
880
+ }
881
+ ) : null;
882
+ if (codeConfig?.renderer) {
883
+ const CustomRenderer = codeConfig.renderer;
884
+ return /* @__PURE__ */ jsxs(
885
+ "div",
886
+ {
887
+ role: "region",
888
+ "aria-label": block.language ? `Code block: ${block.language}` : "Code block",
889
+ "data-ncm-block": block.id,
890
+ "data-ncm-stable": block.stableId,
891
+ "data-ncm-type": block.type,
892
+ "data-block-id": block.id,
893
+ "data-ncm-language": block.language,
894
+ className: cn("relative", className),
895
+ children: [
896
+ codeConfig.copyButton !== false && /* @__PURE__ */ jsx(CopyButton, { content: block.content }),
897
+ /* @__PURE__ */ jsx(CustomRenderer, { code: block.content, language: block.language }),
898
+ languageLabel
899
+ ]
900
+ }
901
+ );
902
+ }
903
+ return /* @__PURE__ */ jsxs(
904
+ "div",
905
+ {
906
+ role: "region",
907
+ "aria-label": block.language ? `Code block: ${block.language}` : "Code block",
908
+ "data-ncm-block": block.id,
909
+ "data-ncm-stable": block.stableId,
910
+ "data-ncm-type": block.type,
911
+ "data-block-id": block.id,
912
+ "data-ncm-language": block.language,
913
+ className: cn("relative", className),
914
+ children: [
915
+ codeConfig?.copyButton !== false && /* @__PURE__ */ jsx(CopyButton, { content: block.content }),
916
+ /* @__PURE__ */ jsx("pre", { "data-ncm-code-pre": "", children: /* @__PURE__ */ jsxs("div", { className: "flex", children: [
917
+ codeConfig?.lineNumbers && /* @__PURE__ */ jsx(LineNumbers, { count: lineCount }),
918
+ /* @__PURE__ */ jsx("code", { "data-ncm-code": "", className: "flex-1", children: /* @__PURE__ */ jsx(DefaultShikiRenderer, { code: block.content, language: block.language }) })
919
+ ] }) }),
920
+ languageLabel
921
+ ]
922
+ }
923
+ );
924
+ }
925
+ function ContainerBlock({ block, className }) {
926
+ return /* @__PURE__ */ jsxs(
927
+ BlockShell,
928
+ {
929
+ block,
930
+ "data-ncm-container": "",
931
+ "data-ncm-directive": block.directive,
932
+ className: cn("rounded-lg border border-border bg-card p-4", className),
933
+ children: [
934
+ block.directive && /* @__PURE__ */ jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-md bg-muted px-1.5 py-0.5 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: block.directive }) }),
935
+ /* @__PURE__ */ jsx(InlineContent, { content: block.innerContent })
936
+ ]
937
+ }
938
+ );
939
+ }
940
+ function DataviewBlock({ block, className }) {
941
+ return /* @__PURE__ */ jsx(
942
+ "pre",
943
+ {
944
+ "data-ncm-block": block.id,
945
+ "data-ncm-stable": block.stableId,
946
+ "data-ncm-type": block.type,
947
+ "data-block-id": block.id,
948
+ "data-ncm-dataview": "",
949
+ "data-ncm-query-type": block.queryType,
950
+ className: cn(
951
+ "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
952
+ className
953
+ ),
954
+ children: /* @__PURE__ */ jsx("code", { children: block.query })
955
+ }
956
+ );
957
+ }
958
+ function DefinitionBlock({ block, className }) {
959
+ return /* @__PURE__ */ jsxs(
960
+ BlockShell,
961
+ {
962
+ as: "dl",
963
+ block,
964
+ "data-ncm-definition": "",
965
+ className: cn("space-y-1", className),
966
+ children: [
967
+ /* @__PURE__ */ jsx("dt", { className: "font-medium", children: /* @__PURE__ */ jsx(InlineContent, { content: serializeInlineContent(block.term) }) }),
968
+ /* @__PURE__ */ jsx(ChildBlocks, { as: "dd", blocks: block.definition, className: "ml-4 space-y-2" })
969
+ ]
970
+ }
971
+ );
972
+ }
973
+ function toEmbeddingConfigType(embedType) {
974
+ switch (embedType) {
975
+ case "image":
976
+ return "image";
977
+ case "document":
978
+ return "pdf";
979
+ case "file":
980
+ default:
981
+ return "generic_file";
982
+ }
983
+ }
984
+ function dataAttrs(block) {
985
+ return {
986
+ "data-ncm-block": block.id,
987
+ "data-ncm-stable": block.stableId,
988
+ "data-ncm-type": block.type,
989
+ "data-block-id": block.id,
990
+ "data-ncm-embed": "",
991
+ "data-ncm-embed-type": block.embedType
992
+ };
993
+ }
994
+ function EmbedBlock({ block, className }) {
995
+ const config = useNcmConfig();
996
+ const configEmbedType = toEmbeddingConfigType(block.embedType);
997
+ const resolvedUrl = config.embeddings?.resolveUrl?.(block.src, configEmbedType) ?? block.src;
998
+ if (block.embedType === "image") {
999
+ return /* @__PURE__ */ jsx("figure", { ...dataAttrs(block), className: cn(config.embeddings?.imageClassName, className), children: /* @__PURE__ */ jsx("img", { src: resolvedUrl, alt: block.alt, title: block.title ?? void 0 }) });
1000
+ }
1001
+ return /* @__PURE__ */ jsx("figure", { ...dataAttrs(block), className, children: /* @__PURE__ */ jsx("a", { href: resolvedUrl, title: block.title ?? void 0, children: block.alt || block.src }) });
1002
+ }
1003
+ var embedFrameStyle = {
1004
+ display: "block",
1005
+ width: "100%",
1006
+ maxWidth: "100%",
1007
+ height: "min(80vh, 900px)",
1008
+ minHeight: "min(360px, 80vh)"
1009
+ };
1010
+ var embedMediaStyle = {
1011
+ display: "block",
1012
+ maxWidth: "100%",
1013
+ height: "auto"
1014
+ };
1015
+ function EmbeddingBlock({ block, className }) {
1016
+ const config = useNcmConfig();
1017
+ const resolvedUrl = config.embeddings?.resolveUrl?.(block.target, block.embed_type) ?? block.target;
1018
+ const CustomRenderer = config.embeddings?.renderers?.[block.embed_type];
1019
+ if (CustomRenderer) {
1020
+ return /* @__PURE__ */ jsx(CustomRenderer, { block, className, resolvedUrl });
1021
+ }
1022
+ switch (block.embed_type) {
1023
+ case "image":
1024
+ return /* @__PURE__ */ jsx(
1025
+ ImageEmbed,
1026
+ {
1027
+ block,
1028
+ resolvedUrl,
1029
+ className: cn(config.embeddings?.imageClassName, className)
1030
+ }
1031
+ );
1032
+ case "video":
1033
+ return /* @__PURE__ */ jsx(
1034
+ VideoEmbed,
1035
+ {
1036
+ block,
1037
+ resolvedUrl,
1038
+ className: cn(config.embeddings?.videoClassName, className)
1039
+ }
1040
+ );
1041
+ case "audio":
1042
+ return /* @__PURE__ */ jsx(
1043
+ AudioEmbed,
1044
+ {
1045
+ block,
1046
+ resolvedUrl,
1047
+ className: cn(config.embeddings?.audioClassName, className)
1048
+ }
1049
+ );
1050
+ case "pdf":
1051
+ return /* @__PURE__ */ jsx(PdfEmbed, { block, resolvedUrl, className });
1052
+ case "ncm_embed":
1053
+ return /* @__PURE__ */ jsx(NcmEmbed, { block, resolvedUrl, className });
1054
+ case "iframe":
1055
+ return /* @__PURE__ */ jsx(IframeEmbed, { block, resolvedUrl, className });
1056
+ case "generic_file":
1057
+ default:
1058
+ return /* @__PURE__ */ jsx(GenericFileEmbed, { block, resolvedUrl, className });
1059
+ }
1060
+ }
1061
+ function dataAttrs2(block, embedType) {
1062
+ return {
1063
+ "data-ncm-block": block.id,
1064
+ "data-ncm-stable": block.stableId,
1065
+ "data-ncm-type": block.type,
1066
+ "data-block-id": block.id,
1067
+ "data-ncm-embedding": "",
1068
+ "data-ncm-embed-type": embedType
1069
+ };
1070
+ }
1071
+ function ImageEmbed({ block, resolvedUrl, className }) {
1072
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs2(block, "image"), className, children: [
1073
+ /* @__PURE__ */ jsx("img", { src: resolvedUrl, alt: block.caption ?? "" }),
1074
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
1075
+ ] });
1076
+ }
1077
+ function VideoEmbed({ block, resolvedUrl, className }) {
1078
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs2(block, "video"), className, children: [
1079
+ /* @__PURE__ */ jsx("video", { src: resolvedUrl, controls: true }),
1080
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
1081
+ ] });
1082
+ }
1083
+ function AudioEmbed({ block, resolvedUrl, className }) {
1084
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs2(block, "audio"), className, children: [
1085
+ /* @__PURE__ */ jsx("audio", { src: resolvedUrl, controls: true, className: "w-full" }),
1086
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
1087
+ ] });
1088
+ }
1089
+ function PdfEmbed({ block, resolvedUrl, className }) {
1090
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs2(block, "pdf"), className: cn("w-full max-w-full", className), children: [
1091
+ /* @__PURE__ */ jsx(
1092
+ "iframe",
1093
+ {
1094
+ src: resolvedUrl,
1095
+ title: block.caption ?? "PDF document",
1096
+ className: "rounded-lg border border-border",
1097
+ style: embedFrameStyle
1098
+ }
1099
+ ),
1100
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
1101
+ ] });
1102
+ }
1103
+ function IframeEmbed({ block, resolvedUrl, className }) {
1104
+ const [useFrame, setUseFrame] = useState(false);
1105
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs2(block, "iframe"), className: cn("w-full max-w-full", className), children: [
1106
+ useFrame ? /* @__PURE__ */ jsx(
1107
+ "iframe",
1108
+ {
1109
+ src: resolvedUrl,
1110
+ title: block.caption ?? block.alt ?? block.target,
1111
+ className: "rounded-lg border border-border",
1112
+ style: embedFrameStyle
1113
+ }
1114
+ ) : /* @__PURE__ */ jsx(
1115
+ "img",
1116
+ {
1117
+ src: resolvedUrl,
1118
+ alt: block.alt || block.caption || block.target,
1119
+ style: embedMediaStyle,
1120
+ onError: () => setUseFrame(true)
1121
+ }
1122
+ ),
1123
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
1124
+ ] });
1125
+ }
1126
+ function NcmEmbed({ block, resolvedUrl, className }) {
1127
+ return /* @__PURE__ */ jsxs(
1128
+ "div",
1129
+ {
1130
+ ...dataAttrs2(block, "ncm_embed"),
1131
+ className: cn("rounded-lg border border-dashed border-border bg-muted p-4", className),
1132
+ children: [
1133
+ /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
1134
+ "Embedded: ",
1135
+ /* @__PURE__ */ jsx("code", { className: "rounded bg-background px-1", children: block.target }),
1136
+ resolvedUrl !== block.target && /* @__PURE__ */ jsxs(Fragment, { children: [
1137
+ " ",
1138
+ /* @__PURE__ */ jsx("a", { href: resolvedUrl, className: "underline underline-offset-4", children: "open" })
1139
+ ] })
1140
+ ] }),
1141
+ block.caption && /* @__PURE__ */ jsx("div", { className: "mt-2 text-sm text-muted-foreground", children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
1142
+ ]
1143
+ }
1144
+ );
1145
+ }
1146
+ function GenericFileEmbed({ block, resolvedUrl, className }) {
1147
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs2(block, "generic_file"), className, children: [
1148
+ /* @__PURE__ */ jsxs(
1149
+ "a",
1150
+ {
1151
+ href: resolvedUrl,
1152
+ download: true,
1153
+ className: "flex items-center gap-2 rounded-lg border border-border bg-muted p-4 hover:bg-background",
1154
+ children: [
1155
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: block.target }),
1156
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
1157
+ "(",
1158
+ block.file_format.toUpperCase(),
1159
+ ")"
1160
+ ] })
1161
+ ]
1162
+ }
1163
+ ),
1164
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
1165
+ ] });
1166
+ }
1167
+ function FigureBlock({ block, className }) {
1168
+ const { embed, caption, number } = block;
1169
+ return /* @__PURE__ */ jsxs(
1170
+ BlockShell,
1171
+ {
1172
+ as: "figure",
1173
+ block,
1174
+ "data-ncm-figure": "",
1175
+ className: cn("space-y-2", className),
1176
+ children: [
1177
+ embed.embedType === "image" ? /* @__PURE__ */ jsx("img", { src: embed.src, alt: embed.alt, title: embed.title ?? void 0 }) : /* @__PURE__ */ jsx(
1178
+ "a",
1179
+ {
1180
+ href: embed.src,
1181
+ title: embed.title ?? void 0,
1182
+ "data-ncm-embed-type": embed.embedType,
1183
+ children: embed.alt || embed.src
1184
+ }
1185
+ ),
1186
+ /* @__PURE__ */ jsxs(
1187
+ "figcaption",
1188
+ {
1189
+ className: "text-sm text-muted-foreground",
1190
+ "data-ncm-figure-number": number,
1191
+ children: [
1192
+ typeof number === "number" ? /* @__PURE__ */ jsxs("span", { "data-ncm-figure-label": "", children: [
1193
+ "Figure ",
1194
+ number,
1195
+ ". "
1196
+ ] }) : null,
1197
+ /* @__PURE__ */ jsx(InlineContent, { content: serializeInlineContent(caption.content) })
1198
+ ]
1199
+ }
1200
+ )
1201
+ ]
1202
+ }
1203
+ );
1204
+ }
1205
+ function FootnoteBlock({ block, className }) {
1206
+ return /* @__PURE__ */ jsxs(
1207
+ BlockShell,
1208
+ {
1209
+ id: block.stableId,
1210
+ block,
1211
+ "data-ncm-footnote": "",
1212
+ "data-ncm-footnote-label": block.label,
1213
+ className: cn("flex gap-2 text-sm text-muted-foreground", className),
1214
+ children: [
1215
+ /* @__PURE__ */ jsxs("span", { "data-ncm-footnote-marker": "", className: "font-medium", children: [
1216
+ block.label,
1217
+ "."
1218
+ ] }),
1219
+ /* @__PURE__ */ jsx(ChildBlocks, { blocks: block.content, className: "space-y-2" })
1220
+ ]
1221
+ }
1222
+ );
1223
+ }
1224
+ function formatValue(value) {
1225
+ if (Array.isArray(value)) return value.map((v) => String(v)).join(", ");
1226
+ if (value === null || value === void 0) return "";
1227
+ if (typeof value === "object") return JSON.stringify(value);
1228
+ return String(value);
1229
+ }
1230
+ function FrontmatterBlock({ block, className }) {
1231
+ const entries = Object.entries(block.data ?? {});
1232
+ return /* @__PURE__ */ jsx(
1233
+ "dl",
1234
+ {
1235
+ "data-ncm-block": block.id,
1236
+ "data-ncm-stable": block.stableId,
1237
+ "data-ncm-type": block.type,
1238
+ "data-block-id": block.id,
1239
+ "data-ncm-frontmatter": "",
1240
+ className: cn(
1241
+ "grid grid-cols-[auto_1fr] gap-x-4 gap-y-1 rounded-lg border border-border bg-muted/30 p-4 text-sm",
1242
+ className
1243
+ ),
1244
+ children: entries.map(([key, value]) => /* @__PURE__ */ jsxs("div", { className: "contents", children: [
1245
+ /* @__PURE__ */ jsx("dt", { className: "font-medium text-muted-foreground", children: key }),
1246
+ /* @__PURE__ */ jsx("dd", { className: "text-foreground", children: formatValue(value) })
1247
+ ] }, key))
1248
+ }
1249
+ );
1250
+ }
1251
+ function HeaderBlock({ block, className }) {
1252
+ const Tag = `h${block.level}`;
1253
+ return /* @__PURE__ */ jsx(
1254
+ Tag,
1255
+ {
1256
+ id: block.stableId ?? block.id,
1257
+ "data-ncm-block": block.id,
1258
+ "data-ncm-stable": block.stableId,
1259
+ "data-ncm-type": block.type,
1260
+ "data-block-id": block.id,
1261
+ "data-ncm-level": block.level,
1262
+ className,
1263
+ children: /* @__PURE__ */ jsx(InlineContent, { content: block.content, disableBionic: true, disableBeeline: true })
1264
+ }
1265
+ );
1266
+ }
1267
+ function HorizontalRuleBlock({ block, className }) {
1268
+ return /* @__PURE__ */ jsx(
1269
+ "hr",
1270
+ {
1271
+ "data-ncm-block": block.id,
1272
+ "data-ncm-stable": block.stableId,
1273
+ "data-ncm-type": block.type,
1274
+ "data-block-id": block.id,
1275
+ "data-ncm-horizontal-rule": "",
1276
+ className
1277
+ }
1278
+ );
1279
+ }
1280
+ function HtmlBlock({ block, className }) {
1281
+ return /* @__PURE__ */ jsx(
1282
+ "pre",
1283
+ {
1284
+ "data-ncm-block": block.id,
1285
+ "data-ncm-stable": block.stableId,
1286
+ "data-ncm-type": block.type,
1287
+ "data-block-id": block.id,
1288
+ "data-ncm-html": "",
1289
+ className: cn(
1290
+ "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1291
+ className
1292
+ ),
1293
+ children: /* @__PURE__ */ jsx("code", { children: block.content })
1294
+ }
1295
+ );
1296
+ }
1297
+ function SanitizedHtmlBlock({
1298
+ block,
1299
+ className,
1300
+ rawHtml = true,
1301
+ allowDataImages = false
1302
+ }) {
1303
+ const sanitized = sanitizeHtml(block.content, {
1304
+ rawHtml,
1305
+ allowDataImages
1306
+ });
1307
+ return /* @__PURE__ */ jsx(
1308
+ "div",
1309
+ {
1310
+ "data-ncm-block": block.id,
1311
+ "data-ncm-stable": block.stableId,
1312
+ "data-ncm-type": block.type,
1313
+ "data-block-id": block.id,
1314
+ "data-ncm-html-sanitized": "",
1315
+ className,
1316
+ dangerouslySetInnerHTML: { __html: sanitized.html }
1317
+ }
1318
+ );
1319
+ }
1320
+ function LatexDisplayBlock({ block, className }) {
1321
+ const config = useNcmConfig();
1322
+ const CustomRenderer = config.inline?.customLatexRenderer;
1323
+ const html = useKatexHtml(block.content, true, !CustomRenderer);
1324
+ if (CustomRenderer) {
1325
+ return /* @__PURE__ */ jsx(
1326
+ "div",
1327
+ {
1328
+ role: "region",
1329
+ "aria-label": "Mathematical expression",
1330
+ "data-ncm-block": block.id,
1331
+ "data-ncm-stable": block.stableId,
1332
+ "data-ncm-type": block.type,
1333
+ "data-block-id": block.id,
1334
+ "data-ncm-latex-display": "",
1335
+ className,
1336
+ children: /* @__PURE__ */ jsx(CustomRenderer, { content: block.content, display: true })
1337
+ }
1338
+ );
1339
+ }
1340
+ if (html) {
1341
+ return /* @__PURE__ */ jsx(
1342
+ "div",
1343
+ {
1344
+ role: "region",
1345
+ "aria-label": "Mathematical expression",
1346
+ "data-ncm-block": block.id,
1347
+ "data-ncm-stable": block.stableId,
1348
+ "data-ncm-type": block.type,
1349
+ "data-block-id": block.id,
1350
+ "data-ncm-latex-display": "",
1351
+ className: cn("overflow-x-auto", className),
1352
+ dangerouslySetInnerHTML: { __html: html }
1353
+ }
1354
+ );
1355
+ }
1356
+ return /* @__PURE__ */ jsx(
1357
+ "pre",
1358
+ {
1359
+ role: "region",
1360
+ "aria-label": "Mathematical expression (source)",
1361
+ "data-ncm-block": block.id,
1362
+ "data-ncm-stable": block.stableId,
1363
+ "data-ncm-type": block.type,
1364
+ "data-block-id": block.id,
1365
+ "data-ncm-latex-display": "",
1366
+ className: cn("overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm", className),
1367
+ children: /* @__PURE__ */ jsx("code", { children: block.content })
1368
+ }
1369
+ );
1370
+ }
1371
+ function LinkBlock({ block, className }) {
1372
+ return /* @__PURE__ */ jsx(
1373
+ "a",
1374
+ {
1375
+ "data-ncm-block": block.id,
1376
+ "data-ncm-stable": block.stableId,
1377
+ "data-ncm-type": block.type,
1378
+ "data-block-id": block.id,
1379
+ "data-ncm-link": "",
1380
+ href: block.url,
1381
+ title: block.title ?? void 0,
1382
+ className: cn("block text-primary hover:underline", className),
1383
+ children: block.text || block.url
1384
+ }
1385
+ );
1386
+ }
1387
+ function ListBlock({ block, className }) {
1388
+ const isOrdered = block.type === "list_ordered";
1389
+ const Tag = isOrdered ? "ol" : "ul";
1390
+ return /* @__PURE__ */ jsx(
1391
+ Tag,
1392
+ {
1393
+ role: "list",
1394
+ "data-ncm-block": block.id,
1395
+ "data-ncm-stable": block.stableId,
1396
+ "data-ncm-type": block.type,
1397
+ "data-block-id": block.id,
1398
+ "data-ncm-list": "",
1399
+ "data-ncm-list-type": isOrdered ? "ordered" : "unordered",
1400
+ className,
1401
+ children: /* @__PURE__ */ jsx(ListItems, { items: block.items, itemIds: block.itemIds, ordered: isOrdered })
1402
+ }
1403
+ );
1404
+ }
1405
+ function nestedItemIdKey(id) {
1406
+ if (!id) {
1407
+ return void 0;
1408
+ }
1409
+ if (typeof id === "string") {
1410
+ return id;
1411
+ }
1412
+ if (Array.isArray(id)) {
1413
+ return id.map(nestedItemIdKey).filter(Boolean).join(".");
1414
+ }
1415
+ return `${id.kind}:${id.items.map(nestedItemIdKey).filter(Boolean).join(".")}`;
1416
+ }
1417
+ function ListItems({ items, itemIds, ordered }) {
1418
+ return /* @__PURE__ */ jsx(Fragment, { children: items.map((item, index) => {
1419
+ const key = nestedItemIdKey(itemIds?.[index]) ?? `item-${index}`;
1420
+ if (typeof item === "string") {
1421
+ return /* @__PURE__ */ jsx("li", { "data-ncm-list-item": "", children: /* @__PURE__ */ jsx(InlineContent, { content: item }) }, key);
1422
+ }
1423
+ if (isTypedNestedList(item)) {
1424
+ return /* @__PURE__ */ jsx(NestedTypedList, { list: item }, key);
1425
+ }
1426
+ if (Array.isArray(item) && item.length > 0) {
1427
+ const [first, ...rest] = item;
1428
+ const content = typeof first === "string" ? first : "";
1429
+ const nestedContent = processNestedItems(rest, ordered);
1430
+ return /* @__PURE__ */ jsxs("li", { "data-ncm-list-item": "", children: [
1431
+ /* @__PURE__ */ jsx(InlineContent, { content }),
1432
+ nestedContent
1433
+ ] }, key);
1434
+ }
1435
+ return null;
1436
+ }) });
1437
+ }
1438
+ function processNestedItems(items, parentOrdered) {
1439
+ if (items.length === 0) return null;
1440
+ const groups = [];
1441
+ for (const item of items) {
1442
+ if (isTypedNestedList(item)) {
1443
+ const isOrdered = item.kind === "ordered";
1444
+ const lastGroup = groups[groups.length - 1];
1445
+ if (lastGroup && lastGroup.ordered === isOrdered) {
1446
+ lastGroup.items.push(...item.items);
1447
+ } else {
1448
+ groups.push({ ordered: isOrdered, items: [...item.items] });
1449
+ }
1450
+ } else {
1451
+ const lastGroup = groups[groups.length - 1];
1452
+ if (lastGroup && lastGroup.ordered === parentOrdered) {
1453
+ lastGroup.items.push(item);
1454
+ } else {
1455
+ groups.push({ ordered: parentOrdered, items: [item] });
1456
+ }
1457
+ }
1458
+ }
1459
+ return groups.map((group, index) => {
1460
+ const Tag = group.ordered ? "ol" : "ul";
1461
+ return /* @__PURE__ */ jsx(Tag, { "data-ncm-list-nested": "", children: /* @__PURE__ */ jsx(ListItems, { items: group.items, ordered: group.ordered }) }, index);
1462
+ });
1463
+ }
1464
+ function NestedTypedList({ list }) {
1465
+ const Tag = list.kind === "ordered" ? "ol" : "ul";
1466
+ return /* @__PURE__ */ jsx(Tag, { "data-ncm-list-nested": "", children: /* @__PURE__ */ jsx(ListItems, { items: list.items, ordered: list.kind === "ordered" }) });
1467
+ }
1468
+ function MathBlock({ block, className }) {
1469
+ const html = useKatexHtml(block.content, true);
1470
+ if (html) {
1471
+ return /* @__PURE__ */ jsx(
1472
+ "div",
1473
+ {
1474
+ role: "region",
1475
+ "aria-label": "Mathematical expression",
1476
+ "data-ncm-block": block.id,
1477
+ "data-ncm-stable": block.stableId,
1478
+ "data-ncm-type": block.type,
1479
+ "data-block-id": block.id,
1480
+ "data-ncm-math": "",
1481
+ className: cn("overflow-x-auto", className),
1482
+ dangerouslySetInnerHTML: { __html: html }
1483
+ }
1484
+ );
1485
+ }
1486
+ return /* @__PURE__ */ jsx(
1487
+ "pre",
1488
+ {
1489
+ role: "region",
1490
+ "aria-label": "Mathematical expression (source)",
1491
+ "data-ncm-block": block.id,
1492
+ "data-ncm-stable": block.stableId,
1493
+ "data-ncm-type": block.type,
1494
+ "data-block-id": block.id,
1495
+ "data-ncm-math": "",
1496
+ className: cn(
1497
+ "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1498
+ className
1499
+ ),
1500
+ children: /* @__PURE__ */ jsx("code", { children: block.content })
1501
+ }
1502
+ );
1503
+ }
1504
+ function MermaidBlock({ block, className }) {
1505
+ return /* @__PURE__ */ jsx(
1506
+ "pre",
1507
+ {
1508
+ "data-ncm-block": block.id,
1509
+ "data-ncm-stable": block.stableId,
1510
+ "data-ncm-type": block.type,
1511
+ "data-block-id": block.id,
1512
+ "data-ncm-mermaid": "",
1513
+ "data-ncm-diagram-type": block.diagramType,
1514
+ className: cn(
1515
+ "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1516
+ className
1517
+ ),
1518
+ children: /* @__PURE__ */ jsx("code", { children: block.content })
1519
+ }
1520
+ );
1521
+ }
1522
+ function PageBreakerBlock({ block, className }) {
1523
+ return /* @__PURE__ */ jsx(
1524
+ "div",
1525
+ {
1526
+ "data-ncm-block": block.id,
1527
+ "data-ncm-stable": block.stableId,
1528
+ "data-ncm-type": block.type,
1529
+ "data-block-id": block.id,
1530
+ "data-ncm-page": block.page,
1531
+ "aria-hidden": "true",
1532
+ className,
1533
+ style: { height: 0, margin: 0, padding: 0, border: 0 }
1534
+ }
1535
+ );
1536
+ }
1537
+ function ParagraphBlock({ block, className }) {
1538
+ return /* @__PURE__ */ jsx(
1539
+ "p",
1540
+ {
1541
+ "data-ncm-block": block.id,
1542
+ "data-ncm-stable": block.stableId,
1543
+ "data-ncm-type": block.type,
1544
+ "data-block-id": block.id,
1545
+ "data-ncm-paragraph": "",
1546
+ className,
1547
+ children: /* @__PURE__ */ jsx(InlineContent, { content: block.content })
1548
+ }
1549
+ );
1550
+ }
1551
+ function SpoilerBlock({ block, className }) {
1552
+ return /* @__PURE__ */ jsxs(
1553
+ BlockShell,
1554
+ {
1555
+ as: "details",
1556
+ block,
1557
+ "data-ncm-spoiler": "",
1558
+ open: block.open,
1559
+ className: cn("rounded-lg border border-border bg-card p-4", className),
1560
+ children: [
1561
+ /* @__PURE__ */ jsx("summary", { className: "cursor-pointer font-medium", children: block.summary }),
1562
+ /* @__PURE__ */ jsx(ChildBlocks, { blocks: block.children, className: "mt-2 space-y-2" })
1563
+ ]
1564
+ }
1565
+ );
1566
+ }
1567
+ function TableBlock({ block, className }) {
1568
+ return /* @__PURE__ */ jsx(
1569
+ "div",
1570
+ {
1571
+ "data-ncm-block": block.id,
1572
+ "data-ncm-stable": block.stableId,
1573
+ "data-ncm-type": block.type,
1574
+ "data-block-id": block.id,
1575
+ "data-ncm-table": "",
1576
+ className: cn("w-full overflow-x-auto", className),
1577
+ children: /* @__PURE__ */ jsxs("table", { role: "table", "data-ncm-table-element": "", children: [
1578
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { "data-ncm-table-row": "", children: block.headers.map((header, index) => /* @__PURE__ */ jsx("th", { "data-ncm-table-header": "", children: /* @__PURE__ */ jsx(InlineContent, { content: header }) }, index)) }) }),
1579
+ /* @__PURE__ */ jsx("tbody", { children: block.rows.map((row, rowIndex) => {
1580
+ const rowKey = block.rowIds?.[rowIndex] ?? `${block.id}.${rowIndex + 1}`;
1581
+ return /* @__PURE__ */ jsx("tr", { "data-ncm-table-row": "", children: row.map((cell, cellIndex) => /* @__PURE__ */ jsx("td", { "data-ncm-table-cell": "", children: /* @__PURE__ */ jsx(InlineContent, { content: cell }) }, `${rowKey}.${cellIndex + 1}`)) }, rowKey);
1582
+ }) })
1583
+ ] })
1584
+ }
1585
+ );
1586
+ }
1587
+ function TaskItems({ items }) {
1588
+ return /* @__PURE__ */ jsx(Fragment, { children: items.map((item) => {
1589
+ const status = item.checked ? "Completed" : "Incomplete";
1590
+ return /* @__PURE__ */ jsxs(
1591
+ "li",
1592
+ {
1593
+ "data-ncm-task-item": "",
1594
+ "data-block-id": item.id,
1595
+ "data-ncm-checked": item.checked ? "true" : "false",
1596
+ className: "flex flex-col",
1597
+ children: [
1598
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
1599
+ /* @__PURE__ */ jsx(
1600
+ "input",
1601
+ {
1602
+ type: "checkbox",
1603
+ checked: item.checked,
1604
+ disabled: true,
1605
+ readOnly: true,
1606
+ "aria-label": `${status} task`,
1607
+ className: "size-4 shrink-0"
1608
+ }
1609
+ ),
1610
+ /* @__PURE__ */ jsxs("span", { children: [
1611
+ /* @__PURE__ */ jsxs("span", { "data-ncm-task-status": "", className: "sr-only", children: [
1612
+ status,
1613
+ ":",
1614
+ " "
1615
+ ] }),
1616
+ /* @__PURE__ */ jsx(InlineContent, { content: serializeInlineContent(item.content) })
1617
+ ] })
1618
+ ] }),
1619
+ item.children ? /* @__PURE__ */ jsx("ul", { role: "list", "data-ncm-list-nested": "", className: "ml-6 list-none", children: /* @__PURE__ */ jsx(TaskItems, { items: item.children.items }) }) : null
1620
+ ]
1621
+ },
1622
+ item.stableId ?? item.id
1623
+ );
1624
+ }) });
1625
+ }
1626
+ function TaskListBlock({ block, className }) {
1627
+ return /* @__PURE__ */ jsx(
1628
+ BlockShell,
1629
+ {
1630
+ as: "ul",
1631
+ block,
1632
+ role: "list",
1633
+ "data-ncm-task-list": "",
1634
+ className: cn("list-none space-y-1", className),
1635
+ children: /* @__PURE__ */ jsx(TaskItems, { items: block.items })
1636
+ }
1637
+ );
1638
+ }
1639
+
1640
+ // src/lib/defaults.ts
1641
+ function fallbackSource(block) {
1642
+ const maybeSource = block;
1643
+ if (typeof maybeSource.raw === "string" && maybeSource.raw.length > 0) {
1644
+ return maybeSource.raw;
1645
+ }
1646
+ if (typeof maybeSource.content === "string" && maybeSource.content.length > 0) {
1647
+ return maybeSource.content;
1648
+ }
1649
+ return JSON.stringify(block, null, 2);
1650
+ }
1651
+ function FallbackBlock({ block, className }) {
1652
+ return createElement(
1653
+ "pre",
1654
+ {
1655
+ "data-ncm-block": block.id,
1656
+ "data-ncm-stable": block.stableId,
1657
+ "data-ncm-type": block.type,
1658
+ "data-block-id": block.id,
1659
+ "data-ncm-fallback": "",
1660
+ className: cn(
1661
+ "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1662
+ className
1663
+ )
1664
+ },
1665
+ createElement("code", null, fallbackSource(block))
1666
+ );
1667
+ }
1668
+ var defaultRenderers = {
1669
+ // Standard blocks
1670
+ paragraph: ParagraphBlock,
1671
+ header: HeaderBlock,
1672
+ blockquote: BlockquoteBlock,
1673
+ code: CodeBlock,
1674
+ container: ContainerBlock,
1675
+ frontmatter: FrontmatterBlock,
1676
+ html: HtmlBlock,
1677
+ list_ordered: ListBlock,
1678
+ list_unordered: ListBlock,
1679
+ table: TableBlock,
1680
+ embed: EmbedBlock,
1681
+ embedding: EmbeddingBlock,
1682
+ latex_display: LatexDisplayBlock,
1683
+ horizontal_rule: HorizontalRuleBlock,
1684
+ page_breaker: PageBreakerBlock,
1685
+ // Promoted blocks
1686
+ link: LinkBlock,
1687
+ figure: FigureBlock,
1688
+ // Extension blocks
1689
+ admonition: AdmonitionBlock,
1690
+ footnote: FootnoteBlock,
1691
+ task_list: TaskListBlock,
1692
+ definition: DefinitionBlock,
1693
+ spoiler: SpoilerBlock,
1694
+ aside: AsideBlock,
1695
+ attribution: AttributionBlock,
1696
+ // Promoted code blocks
1697
+ mermaid: MermaidBlock,
1698
+ dataview: DataviewBlock,
1699
+ math: MathBlock,
1700
+ chart: ChartBlock,
1701
+ // custom_code is handled separately by language (see NcmBlock dispatch)
1702
+ custom_code: {},
1703
+ fallback: FallbackBlock
1704
+ };
1705
+ function CustomCodeBlock({ block, className }) {
1706
+ return /* @__PURE__ */ jsxs(
1707
+ "div",
1708
+ {
1709
+ role: "region",
1710
+ "aria-label": `Custom code block: ${block.language}`,
1711
+ "data-ncm-block": block.id,
1712
+ "data-ncm-stable": block.stableId,
1713
+ "data-ncm-type": block.type,
1714
+ "data-block-id": block.id,
1715
+ "data-ncm-custom-code": "",
1716
+ "data-ncm-language": block.language,
1717
+ className: cn("overflow-x-auto", className),
1718
+ children: [
1719
+ /* @__PURE__ */ jsx("div", { className: "mb-2 text-xs font-medium text-muted-foreground", children: block.language }),
1720
+ /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: block.content }) })
1721
+ ]
1722
+ }
1723
+ );
1724
+ }
1725
+ var NcmBlockErrorBoundary = class extends Component {
1726
+ state = {
1727
+ error: null
1728
+ };
1729
+ static getDerivedStateFromError(error) {
1730
+ return { error };
1731
+ }
1732
+ componentDidCatch(error, info) {
1733
+ console.warn(
1734
+ `[ncm-ui] Renderer for block '${this.props.block.type}' failed; rendering fallback.`,
1735
+ { block: this.props.block, error, info }
1736
+ );
1737
+ }
1738
+ render() {
1739
+ if (this.state.error) {
1740
+ return /* @__PURE__ */ jsx(FallbackBlock, { block: this.props.block, className: this.props.className });
1741
+ }
1742
+ return this.props.children;
1743
+ }
1744
+ };
1745
+ function warnMissingRenderer(block) {
1746
+ console.warn(
1747
+ `[ncm-ui] No renderer registered for block type '${block.type}'; rendering fallback.`,
1748
+ { block }
1749
+ );
1750
+ }
1751
+ function NcmBlock({ block, className, renderers }) {
1752
+ const contextRenderers = useNcmConfig().renderers;
1753
+ const mergedRenderers = { ...defaultRenderers, ...contextRenderers, ...renderers };
1754
+ let content = null;
1755
+ if (block.type === "custom_code") {
1756
+ const customCodeBlock = block;
1757
+ const customCodeRenderers = {
1758
+ ...defaultRenderers.custom_code,
1759
+ ...contextRenderers?.custom_code,
1760
+ ...renderers?.custom_code
1761
+ };
1762
+ const LanguageRenderer = customCodeRenderers[customCodeBlock.language];
1763
+ content = LanguageRenderer ? /* @__PURE__ */ jsx(LanguageRenderer, { block: customCodeBlock, className }) : (
1764
+ // Fallback: use default CustomCodeBlock renderer
1765
+ /* @__PURE__ */ jsx(CustomCodeBlock, { block: customCodeBlock, className })
1766
+ );
1767
+ } else {
1768
+ const blockType = block.type;
1769
+ const Renderer = mergedRenderers[blockType];
1770
+ if (Renderer) {
1771
+ content = /* @__PURE__ */ jsx(Renderer, { block, className });
1772
+ } else if (mergedRenderers.fallback) {
1773
+ warnMissingRenderer(block);
1774
+ content = /* @__PURE__ */ jsx(mergedRenderers.fallback, { block, className });
1775
+ }
1776
+ }
1777
+ return /* @__PURE__ */ jsx(BlockReferenceScope, { blockId: block.id, children: /* @__PURE__ */ jsx(NcmBlockErrorBoundary, { block, className, children: content }) });
1778
+ }
1779
+ function blockKey(block) {
1780
+ return block.stableId ? `${block.id}:${block.stableId}` : block.id;
1781
+ }
1782
+ function blockDataAttributes(block) {
1783
+ return {
1784
+ "data-ncm-block": block.id,
1785
+ "data-ncm-stable": block.stableId,
1786
+ "data-ncm-type": block.type,
1787
+ "data-block-id": block.id
1788
+ };
1789
+ }
1790
+ function BlockShell({
1791
+ as = "div",
1792
+ block,
1793
+ children,
1794
+ ...props
1795
+ }) {
1796
+ return createElement(as, {
1797
+ ...blockDataAttributes(block),
1798
+ ...props
1799
+ }, children);
1800
+ }
1801
+ function ChildBlocks({
1802
+ as = "div",
1803
+ blocks,
1804
+ ...props
1805
+ }) {
1806
+ return createElement(
1807
+ as,
1808
+ props,
1809
+ blocks.map((block) => /* @__PURE__ */ jsx(NcmBlock, { block }, blockKey(block)))
1810
+ );
1811
+ }
1812
+ function NcmDocument({
1813
+ blocks,
1814
+ theme = "nuu",
1815
+ className,
1816
+ renderers: propsRenderers,
1817
+ blockClassName,
1818
+ renderBlock,
1819
+ "aria-label": ariaLabel,
1820
+ "aria-labelledby": ariaLabelledBy
1821
+ }) {
1822
+ const contextConfig = useNcmConfig();
1823
+ const mergedRenderers = useMemo(
1824
+ () => ({
1825
+ ...contextConfig.renderers,
1826
+ ...propsRenderers,
1827
+ custom_code: {
1828
+ ...contextConfig.renderers?.custom_code,
1829
+ ...propsRenderers?.custom_code
1830
+ }
1831
+ }),
1832
+ [contextConfig.renderers, propsRenderers]
1833
+ );
1834
+ const subtreeConfig = useMemo(
1835
+ () => ({ ...contextConfig, renderers: mergedRenderers }),
1836
+ [contextConfig, mergedRenderers]
1837
+ );
1838
+ return /* @__PURE__ */ jsx(
1839
+ "article",
1840
+ {
1841
+ role: "article",
1842
+ "data-ncm-document": "",
1843
+ "data-ncm-theme": theme,
1844
+ "data-ncm-block-count": blocks.length,
1845
+ "data-ncm-dyslexic-font": contextConfig.reading?.dyslexicFont ? "true" : void 0,
1846
+ "aria-label": ariaLabel,
1847
+ "aria-labelledby": ariaLabelledBy,
1848
+ className: cn(`ncm-theme-${theme}`, contextConfig.className, className),
1849
+ children: /* @__PURE__ */ jsx(NcmProvider, { config: subtreeConfig, children: /* @__PURE__ */ jsx(NcmReferencesProvider, { blocks, children: blocks.map((block, index) => {
1850
+ const customClassName = blockClassName?.(block, index);
1851
+ const renderDefault = () => /* @__PURE__ */ jsx(
1852
+ NcmBlock,
1853
+ {
1854
+ block,
1855
+ renderers: mergedRenderers,
1856
+ className: customClassName
1857
+ },
1858
+ blockKey(block)
1859
+ );
1860
+ if (renderBlock) {
1861
+ return renderBlock(block, index, renderDefault);
1862
+ }
1863
+ return renderDefault();
1864
+ }) }) })
1865
+ }
1866
+ );
1867
+ }
1868
+
1869
+ // src/hooks/use-block-renderer.ts
1870
+ function useBlockRenderer(blockType) {
1871
+ const config = useNcmConfig();
1872
+ const mergedRenderers = {
1873
+ ...defaultRenderers,
1874
+ ...config.renderers
1875
+ };
1876
+ return mergedRenderers[blockType];
1877
+ }
1878
+ function useCustomCodeRenderer(language) {
1879
+ const config = useNcmConfig();
1880
+ const customCodeRenderers = {
1881
+ ...defaultRenderers.custom_code,
1882
+ ...config.renderers?.custom_code
1883
+ };
1884
+ return customCodeRenderers[language];
1885
+ }
1886
+
1887
+ export { AdmonitionBlock, AsideBlock, AttributionBlock, BlockReferenceScope, BlockShell, BlockquoteBlock, ChartBlock, ChildBlocks, CodeBlock, ContainerBlock, CustomCodeBlock, DataviewBlock, DefinitionBlock, EmbeddingBlock, FigureBlock, FootnoteBlock, FrontmatterBlock, HeaderBlock, HorizontalRuleBlock, HtmlBlock, InertReferenceScope, InlineContent, LatexDisplayBlock, LinkBlock, ListBlock, MathBlock, MermaidBlock, NcmBlock, NcmDocument, NcmProvider, NcmReferencesProvider, PageBreakerBlock, ParagraphBlock, ReferenceMarker, SanitizedHtmlBlock, SpoilerBlock, TableBlock, TaskListBlock, blockDataAttributes, blockKey, cn, computeReferenceBases, defaultRenderers, parseInline, renderBeelineText, renderBionicText, renderReadingText, useBlockReferenceScope, useBlockRenderer, useCustomCodeRenderer, useNcmConfig };