@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
@@ -0,0 +1,763 @@
1
+ "use client";
2
+ import { createContext, useState, useContext, useMemo, useRef, useEffect, useId, useCallback } from 'react';
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+ import { extractExtension, embedTypeFromExtension } from '@nuucognition/mesh-core';
5
+ import '@nuucognition/ncm';
6
+ import { clsx } from 'clsx';
7
+ import { twMerge } from 'tailwind-merge';
8
+
9
+ // src/blocks/embedding/embedding.tsx
10
+ var NcmContext = createContext(null);
11
+ function useNcmConfig() {
12
+ return useContext(NcmContext) ?? {};
13
+ }
14
+
15
+ // src/inline/parser.ts
16
+ function splitOnce(input, delimiter) {
17
+ const idx = input.indexOf(delimiter);
18
+ if (idx === -1) {
19
+ return [input, null];
20
+ }
21
+ return [input.slice(0, idx), input.slice(idx + delimiter.length)];
22
+ }
23
+ function parseWikiTarget(rawInside) {
24
+ const inside = rawInside.trim();
25
+ const [targetPlusAnchor, displayRaw] = splitOnce(inside, "|");
26
+ const [targetRaw, anchorRaw] = splitOnce(targetPlusAnchor, "#");
27
+ const target = targetRaw.trim();
28
+ const display = displayRaw !== null ? displayRaw.trim() || null : null;
29
+ const anchor = anchorRaw !== null ? anchorRaw.trim() || null : null;
30
+ return { target, display, anchor };
31
+ }
32
+ var INLINE_REF_KIND_RE = /^\s*(ref|footnote)\s*:\s*([\s\S]*)$/i;
33
+ function tryParseInlineRef(input) {
34
+ let depth = 1;
35
+ let i = 2;
36
+ for (; i < input.length; i++) {
37
+ const ch = input[i];
38
+ if (ch === "[") {
39
+ depth++;
40
+ } else if (ch === "]") {
41
+ depth--;
42
+ if (depth === 0) break;
43
+ }
44
+ }
45
+ if (depth !== 0) return null;
46
+ const inner = input.slice(2, i);
47
+ const length = i + 1;
48
+ const match = INLINE_REF_KIND_RE.exec(inner);
49
+ if (match && match[1]) {
50
+ const kind = match[1].toLowerCase() === "ref" ? "ref" : "footnote";
51
+ return { token: { type: "inline_ref", kind, content: (match[2] ?? "").trim() }, length };
52
+ }
53
+ return { token: { type: "inline_ref", kind: "footnote", content: inner.trim() }, length };
54
+ }
55
+ function parseInline(content) {
56
+ if (!content) return [];
57
+ const tokens = [];
58
+ let remaining = content;
59
+ while (remaining.length > 0) {
60
+ const codeMatch = remaining.match(/^`([^`]+)`/);
61
+ if (codeMatch && codeMatch[1] !== void 0) {
62
+ tokens.push({ type: "code", content: codeMatch[1] });
63
+ remaining = remaining.slice(codeMatch[0].length);
64
+ continue;
65
+ }
66
+ const latexMatch = remaining.match(/^\$(?!\s)([^$\n]+?)(?<!\s)\$/);
67
+ if (latexMatch && latexMatch[1] !== void 0) {
68
+ tokens.push({ type: "latex", content: latexMatch[1] });
69
+ remaining = remaining.slice(latexMatch[0].length);
70
+ continue;
71
+ }
72
+ if (remaining.startsWith("^[")) {
73
+ const inlineRef = tryParseInlineRef(remaining);
74
+ if (inlineRef) {
75
+ tokens.push(inlineRef.token);
76
+ remaining = remaining.slice(inlineRef.length);
77
+ continue;
78
+ }
79
+ }
80
+ const wikiEmbedMatch = remaining.match(/^!\[\[([^\]]+)\]\]/);
81
+ if (wikiEmbedMatch && wikiEmbedMatch[1] !== void 0) {
82
+ const parsed = parseWikiTarget(wikiEmbedMatch[1]);
83
+ tokens.push({
84
+ type: "wiki_embed",
85
+ target: parsed.target,
86
+ display: parsed.display,
87
+ anchor: parsed.anchor
88
+ });
89
+ remaining = remaining.slice(wikiEmbedMatch[0].length);
90
+ continue;
91
+ }
92
+ const wikiLinkMatch = remaining.match(/^\[\[([^\]]+)\]\]/);
93
+ if (wikiLinkMatch && wikiLinkMatch[1] !== void 0) {
94
+ const parsed = parseWikiTarget(wikiLinkMatch[1]);
95
+ tokens.push({
96
+ type: "wiki_link",
97
+ target: parsed.target,
98
+ display: parsed.display,
99
+ anchor: parsed.anchor
100
+ });
101
+ remaining = remaining.slice(wikiLinkMatch[0].length);
102
+ continue;
103
+ }
104
+ const imageMatch = remaining.match(/^!\[([^\]]*)\]\(([^)\s]+)(?:\s+"([^"]+)")?\)/);
105
+ if (imageMatch && imageMatch[1] !== void 0 && imageMatch[2] !== void 0) {
106
+ tokens.push({
107
+ type: "image",
108
+ alt: imageMatch[1],
109
+ src: imageMatch[2],
110
+ title: imageMatch[3]
111
+ });
112
+ remaining = remaining.slice(imageMatch[0].length);
113
+ continue;
114
+ }
115
+ const linkMatch = remaining.match(/^\[([^\]]+)\]\(([^)\s]+)(?:\s+"([^"]+)")?\)/);
116
+ if (linkMatch && linkMatch[1] !== void 0 && linkMatch[2] !== void 0) {
117
+ tokens.push({
118
+ type: "link",
119
+ href: linkMatch[2],
120
+ title: linkMatch[3],
121
+ children: parseInline(linkMatch[1])
122
+ });
123
+ remaining = remaining.slice(linkMatch[0].length);
124
+ continue;
125
+ }
126
+ const boldMatch = remaining.match(/^\*\*(.+?)\*\*|^__(.+?)__/);
127
+ if (boldMatch) {
128
+ const innerContent = boldMatch[1] ?? boldMatch[2];
129
+ if (innerContent !== void 0) {
130
+ tokens.push({
131
+ type: "bold",
132
+ children: parseInline(innerContent)
133
+ });
134
+ remaining = remaining.slice(boldMatch[0].length);
135
+ continue;
136
+ }
137
+ }
138
+ const strikeMatch = remaining.match(/^~~(.+?)~~/);
139
+ if (strikeMatch && strikeMatch[1] !== void 0) {
140
+ tokens.push({
141
+ type: "strikethrough",
142
+ children: parseInline(strikeMatch[1])
143
+ });
144
+ remaining = remaining.slice(strikeMatch[0].length);
145
+ continue;
146
+ }
147
+ const italicMatch = remaining.match(/^\*([^*]+)\*|^_([^_]+)_/);
148
+ if (italicMatch) {
149
+ const innerContent = italicMatch[1] ?? italicMatch[2];
150
+ if (innerContent !== void 0) {
151
+ tokens.push({
152
+ type: "italic",
153
+ children: parseInline(innerContent)
154
+ });
155
+ remaining = remaining.slice(italicMatch[0].length);
156
+ continue;
157
+ }
158
+ }
159
+ const nextSpecial = findNextSpecialChar(remaining);
160
+ if (nextSpecial > 0) {
161
+ tokens.push({ type: "text", content: remaining.slice(0, nextSpecial) });
162
+ remaining = remaining.slice(nextSpecial);
163
+ } else {
164
+ tokens.push({ type: "text", content: remaining });
165
+ remaining = "";
166
+ }
167
+ }
168
+ return mergeAdjacentText(tokens);
169
+ }
170
+ function findNextSpecialChar(content) {
171
+ const specialChars = ["`", "$", "!", "[", "*", "_", "~", "^"];
172
+ let minIndex = -1;
173
+ for (const char of specialChars) {
174
+ const index = content.indexOf(char);
175
+ if (index > 0 && (minIndex === -1 || index < minIndex)) {
176
+ minIndex = index;
177
+ }
178
+ }
179
+ return minIndex;
180
+ }
181
+ function mergeAdjacentText(tokens) {
182
+ const result = [];
183
+ for (const token of tokens) {
184
+ const last = result[result.length - 1];
185
+ if (token.type === "text" && last?.type === "text") {
186
+ last.content += token.content;
187
+ } else {
188
+ result.push(token);
189
+ }
190
+ }
191
+ return result;
192
+ }
193
+ function clipBounds(el) {
194
+ for (let node = el.parentElement; node; node = node.parentElement) {
195
+ const s = getComputedStyle(node);
196
+ if (/(auto|scroll|hidden)/.test(s.overflowX) || /(auto|scroll|hidden)/.test(s.overflowY)) {
197
+ const r = node.getBoundingClientRect();
198
+ return { left: r.left, right: r.right, top: r.top, bottom: r.bottom };
199
+ }
200
+ }
201
+ return { left: 0, right: window.innerWidth, top: 0, bottom: window.innerHeight };
202
+ }
203
+ function ReferenceMarker({ kind, number, children }) {
204
+ const config = useNcmConfig();
205
+ const popoverEnabled = config.inline?.referencePopover !== false && children != null;
206
+ const popoverId = useId();
207
+ const isRef = kind === "ref";
208
+ const popoverRef = useRef(null);
209
+ const positionPopover = useCallback(() => {
210
+ const el = popoverRef.current;
211
+ if (!el) return;
212
+ el.style.transform = "";
213
+ el.style.top = "";
214
+ el.style.bottom = "";
215
+ const margin = 8;
216
+ const bounds = clipBounds(el);
217
+ const rect = el.getBoundingClientRect();
218
+ if (rect.bottom > bounds.bottom - margin && rect.height < rect.top - bounds.top) {
219
+ el.style.top = "auto";
220
+ el.style.bottom = "1.6em";
221
+ }
222
+ let dx = 0;
223
+ if (rect.right > bounds.right - margin) dx = bounds.right - margin - rect.right;
224
+ if (rect.left + dx < bounds.left + margin) dx = bounds.left + margin - rect.left;
225
+ if (dx) el.style.transform = `translateX(${Math.round(dx)}px)`;
226
+ }, []);
227
+ const describedBy = popoverEnabled ? popoverId : void 0;
228
+ const label = `${isRef ? "Reference" : "Footnote"} ${number}`;
229
+ const marker = isRef ? /* @__PURE__ */ jsx(
230
+ "span",
231
+ {
232
+ "data-ncm-ref-marker": "",
233
+ tabIndex: 0,
234
+ role: "note",
235
+ "aria-label": label,
236
+ "aria-describedby": describedBy,
237
+ children: `[${number}]`
238
+ }
239
+ ) : /* @__PURE__ */ jsx(
240
+ "sup",
241
+ {
242
+ "data-ncm-ref-marker": "",
243
+ tabIndex: 0,
244
+ role: "note",
245
+ "aria-label": label,
246
+ "aria-describedby": describedBy,
247
+ children: number
248
+ }
249
+ );
250
+ return /* @__PURE__ */ jsxs(
251
+ "span",
252
+ {
253
+ "data-ncm-token": isRef ? "reference" : "footnote",
254
+ "data-ncm-ref-kind": kind,
255
+ "data-ncm-ref-number": number,
256
+ onMouseEnter: popoverEnabled ? positionPopover : void 0,
257
+ onFocus: popoverEnabled ? positionPopover : void 0,
258
+ children: [
259
+ marker,
260
+ popoverEnabled ? /* @__PURE__ */ jsx("span", { id: popoverId, ref: popoverRef, role: "tooltip", "data-ncm-ref-popover": "", children }) : null
261
+ ]
262
+ }
263
+ );
264
+ }
265
+ var ReferenceBasesContext = createContext(null);
266
+ var BlockReferenceScopeContext = createContext(null);
267
+ function BlockReferenceScope({ blockId, children }) {
268
+ const bases = useContext(ReferenceBasesContext);
269
+ const base = (blockId ? bases?.get(blockId) : void 0) ?? { ref: 0, footnote: 0 };
270
+ const counter = useRef({ ref: 0, footnote: 0 });
271
+ counter.current = { ref: 0, footnote: 0 };
272
+ const value = {
273
+ next(kind) {
274
+ counter.current[kind] += 1;
275
+ return base[kind] + counter.current[kind];
276
+ }
277
+ };
278
+ return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value, children });
279
+ }
280
+ function useBlockReferenceScope() {
281
+ return useContext(BlockReferenceScopeContext);
282
+ }
283
+ var INERT_SCOPE = { next: () => 0 };
284
+ function InertReferenceScope({ children }) {
285
+ return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value: INERT_SCOPE, children });
286
+ }
287
+ var katexPromise = null;
288
+ function loadKatex() {
289
+ if (!katexPromise) {
290
+ katexPromise = Promise.all([
291
+ import('katex'),
292
+ import('katex/dist/katex.min.css')
293
+ ]).then(([module]) => module.default).catch(() => null);
294
+ }
295
+ return katexPromise;
296
+ }
297
+ function useKatexHtml(content, displayMode, enabled = true) {
298
+ const [katexModule, setKatexModule] = useState(null);
299
+ useEffect(() => {
300
+ if (!enabled) {
301
+ return;
302
+ }
303
+ let active = true;
304
+ loadKatex().then((loaded) => {
305
+ if (active) {
306
+ setKatexModule(loaded);
307
+ }
308
+ });
309
+ return () => {
310
+ active = false;
311
+ };
312
+ }, [enabled]);
313
+ return useMemo(() => {
314
+ if (!enabled || !katexModule) {
315
+ return null;
316
+ }
317
+ try {
318
+ return katexModule.renderToString(content, {
319
+ throwOnError: false,
320
+ displayMode
321
+ });
322
+ } catch {
323
+ return null;
324
+ }
325
+ }, [content, displayMode, enabled, katexModule]);
326
+ }
327
+ function InlineContent({
328
+ content,
329
+ className,
330
+ disableBionic,
331
+ disableBeeline
332
+ }) {
333
+ const tokens = useMemo(() => parseInline(content), [content]);
334
+ const hasScope = useBlockReferenceScope() != null;
335
+ const rendered = tokens.map((token, index) => /* @__PURE__ */ jsx(
336
+ TokenRenderer,
337
+ {
338
+ token,
339
+ disableBionic,
340
+ disableBeeline
341
+ },
342
+ index
343
+ ));
344
+ const body = className ? /* @__PURE__ */ jsx("span", { "data-ncm-inline": "", className, children: rendered }) : /* @__PURE__ */ jsx(Fragment, { children: rendered });
345
+ return hasScope ? body : /* @__PURE__ */ jsx(BlockReferenceScope, { children: body });
346
+ }
347
+ function TokenRenderer({ token, disableBionic, disableBeeline }) {
348
+ const config = useNcmConfig();
349
+ const refScope = useBlockReferenceScope();
350
+ const bionicOn = !disableBionic && Boolean(config.reading?.bionic);
351
+ const beelineOn = !disableBeeline && Boolean(config.reading?.beeline);
352
+ const latexContent = token.type === "latex" ? token.content : "";
353
+ const latexHtml = useKatexHtml(latexContent, false, token.type === "latex");
354
+ switch (token.type) {
355
+ case "text":
356
+ if (bionicOn || beelineOn) {
357
+ return renderReadingText(token.content, {
358
+ bionic: bionicOn,
359
+ bionicRatio: config.reading?.bionicRatio,
360
+ beeline: beelineOn
361
+ });
362
+ }
363
+ return /* @__PURE__ */ jsx(Fragment, { children: token.content });
364
+ case "bold":
365
+ return /* @__PURE__ */ jsx("strong", { "data-ncm-token": "bold", children: token.children.map((child, i) => /* @__PURE__ */ jsx(
366
+ TokenRenderer,
367
+ {
368
+ token: child,
369
+ disableBionic,
370
+ disableBeeline
371
+ },
372
+ i
373
+ )) });
374
+ case "italic":
375
+ return /* @__PURE__ */ jsx("em", { "data-ncm-token": "italic", children: token.children.map((child, i) => /* @__PURE__ */ jsx(
376
+ TokenRenderer,
377
+ {
378
+ token: child,
379
+ disableBionic,
380
+ disableBeeline
381
+ },
382
+ i
383
+ )) });
384
+ case "code":
385
+ return /* @__PURE__ */ jsx("code", { "data-ncm-token": "code", children: token.content });
386
+ case "link": {
387
+ const handleClick = (e) => {
388
+ config.inline?.onLinkClick?.(token.href, e);
389
+ };
390
+ return /* @__PURE__ */ jsx(
391
+ "a",
392
+ {
393
+ "data-ncm-token": "link",
394
+ href: token.href,
395
+ title: token.title,
396
+ onClick: handleClick,
397
+ children: token.children.map((child, i) => /* @__PURE__ */ jsx(
398
+ TokenRenderer,
399
+ {
400
+ token: child,
401
+ disableBionic,
402
+ disableBeeline
403
+ },
404
+ i
405
+ ))
406
+ }
407
+ );
408
+ }
409
+ case "wiki_link": {
410
+ const result = config.mesh?.resolveLink(token.target) ?? {
411
+ status: "missing",
412
+ target: token.target,
413
+ resolved: null,
414
+ candidates: []
415
+ };
416
+ const href = config.inline?.resolveWikiLinkHref?.(token.target, result) ?? null;
417
+ const label = token.display ?? token.target;
418
+ if (href) {
419
+ const handleClick = (e) => {
420
+ config.inline?.onWikiLinkClick?.(token.target, result, e);
421
+ };
422
+ return /* @__PURE__ */ jsx(
423
+ "a",
424
+ {
425
+ "data-ncm-token": "wiki_link",
426
+ "data-ncm-wikilink-status": result.status,
427
+ href,
428
+ onClick: handleClick,
429
+ children: label
430
+ }
431
+ );
432
+ }
433
+ if (config.inline?.onWikiLinkClick) {
434
+ const handleClick = (e) => {
435
+ config.inline?.onWikiLinkClick?.(token.target, result, e);
436
+ };
437
+ return /* @__PURE__ */ jsx(
438
+ "button",
439
+ {
440
+ type: "button",
441
+ "data-ncm-token": "wiki_link",
442
+ "data-ncm-wikilink-status": result.status,
443
+ onClick: handleClick,
444
+ children: label
445
+ }
446
+ );
447
+ }
448
+ return /* @__PURE__ */ jsx("span", { "data-ncm-token": "wiki_link", "data-ncm-wikilink-status": result.status, children: label });
449
+ }
450
+ case "latex": {
451
+ const CustomRenderer = config.inline?.customLatexRenderer;
452
+ if (CustomRenderer) {
453
+ return /* @__PURE__ */ jsx(CustomRenderer, { content: token.content, display: false });
454
+ }
455
+ if (latexHtml) {
456
+ return /* @__PURE__ */ jsx("span", { "data-ncm-token": "latex", dangerouslySetInnerHTML: { __html: latexHtml } });
457
+ }
458
+ return /* @__PURE__ */ jsx("code", { "data-ncm-token": "latex", children: token.content });
459
+ }
460
+ case "strikethrough":
461
+ return /* @__PURE__ */ jsx("del", { "data-ncm-token": "strikethrough", children: token.children.map((child, i) => /* @__PURE__ */ jsx(
462
+ TokenRenderer,
463
+ {
464
+ token: child,
465
+ disableBionic,
466
+ disableBeeline
467
+ },
468
+ i
469
+ )) });
470
+ case "image": {
471
+ const src = config.inline?.resolveAssetPath?.(token.src) ?? token.src;
472
+ return /* @__PURE__ */ jsx(
473
+ "img",
474
+ {
475
+ "data-ncm-token": "image",
476
+ src,
477
+ alt: token.alt,
478
+ title: token.title
479
+ }
480
+ );
481
+ }
482
+ case "wiki_embed": {
483
+ const extension = extractExtension(token.target);
484
+ const embedType = embedTypeFromExtension(extension);
485
+ const result = config.mesh?.resolveEmbed(token.target) ?? null;
486
+ const url = config.embeddings?.resolveUrl?.(token.target, embedType) ?? token.target;
487
+ if (result?.status === "missing") {
488
+ return /* @__PURE__ */ jsx(
489
+ "span",
490
+ {
491
+ "data-ncm-token": "wiki_embed",
492
+ "data-ncm-wikiembed-status": "missing",
493
+ children: `![[${token.target}]]`
494
+ }
495
+ );
496
+ }
497
+ if (result?.status === "ambiguous") {
498
+ return /* @__PURE__ */ jsx(
499
+ "span",
500
+ {
501
+ "data-ncm-token": "wiki_embed",
502
+ "data-ncm-wikiembed-status": "ambiguous",
503
+ children: `![[${token.target}]]`
504
+ }
505
+ );
506
+ }
507
+ if (embedType === "image") {
508
+ return /* @__PURE__ */ jsx(
509
+ "img",
510
+ {
511
+ "data-ncm-token": "wiki_embed",
512
+ "data-ncm-wikiembed-type": embedType,
513
+ src: url,
514
+ alt: token.display ?? token.target,
515
+ className: config.embeddings?.imageClassName
516
+ }
517
+ );
518
+ }
519
+ if (embedType === "video") {
520
+ return /* @__PURE__ */ jsx(
521
+ "video",
522
+ {
523
+ "data-ncm-token": "wiki_embed",
524
+ "data-ncm-wikiembed-type": embedType,
525
+ src: url,
526
+ controls: true,
527
+ className: config.embeddings?.videoClassName
528
+ }
529
+ );
530
+ }
531
+ if (embedType === "audio") {
532
+ return /* @__PURE__ */ jsx(
533
+ "audio",
534
+ {
535
+ "data-ncm-token": "wiki_embed",
536
+ "data-ncm-wikiembed-type": embedType,
537
+ src: url,
538
+ controls: true,
539
+ className: config.embeddings?.audioClassName
540
+ }
541
+ );
542
+ }
543
+ return /* @__PURE__ */ jsx(
544
+ "a",
545
+ {
546
+ "data-ncm-token": "wiki_embed",
547
+ "data-ncm-wikiembed-type": embedType,
548
+ href: url,
549
+ children: token.display ?? token.target
550
+ }
551
+ );
552
+ }
553
+ case "inline_ref": {
554
+ const number = refScope?.next(token.kind) ?? 0;
555
+ 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 });
556
+ }
557
+ default:
558
+ return null;
559
+ }
560
+ }
561
+ function renderReadingText(content, opts) {
562
+ if (!content) return /* @__PURE__ */ jsx(Fragment, { children: content });
563
+ const { bionic = false, beeline = false } = opts;
564
+ if (!bionic && !beeline) return /* @__PURE__ */ jsx(Fragment, { children: content });
565
+ const ratio = Math.min(1, Math.max(0.05, opts.bionicRatio ?? 0.5));
566
+ const pieces = [];
567
+ const regex = /[\p{L}\p{N}][\p{L}\p{N}\p{M}'’-]*/gu;
568
+ let match;
569
+ let key = 0;
570
+ let cursor = 0;
571
+ while ((match = regex.exec(content)) !== null) {
572
+ if (match.index > cursor) pieces.push(content.slice(cursor, match.index));
573
+ const segment = match[0];
574
+ const wrapperProps = {};
575
+ if (bionic) wrapperProps["data-ncm-bionic"] = "";
576
+ if (beeline) wrapperProps["data-ncm-beeline-word"] = "";
577
+ if (bionic) {
578
+ const headLen = Math.max(1, Math.ceil(segment.length * ratio));
579
+ pieces.push(
580
+ /* @__PURE__ */ jsxs("span", { ...wrapperProps, children: [
581
+ /* @__PURE__ */ jsx("span", { "data-ncm-bionic-bold": "", style: { fontWeight: 600 }, children: segment.slice(0, headLen) }),
582
+ segment.slice(headLen)
583
+ ] }, key++)
584
+ );
585
+ } else {
586
+ pieces.push(
587
+ /* @__PURE__ */ jsx("span", { ...wrapperProps, children: segment }, key++)
588
+ );
589
+ }
590
+ cursor = match.index + segment.length;
591
+ }
592
+ if (cursor < content.length) pieces.push(content.slice(cursor));
593
+ return /* @__PURE__ */ jsx(Fragment, { children: pieces });
594
+ }
595
+ function cn(...inputs) {
596
+ return twMerge(clsx(inputs));
597
+ }
598
+ var embedFrameStyle = {
599
+ display: "block",
600
+ width: "100%",
601
+ maxWidth: "100%",
602
+ height: "min(80vh, 900px)",
603
+ minHeight: "min(360px, 80vh)"
604
+ };
605
+ var embedMediaStyle = {
606
+ display: "block",
607
+ maxWidth: "100%",
608
+ height: "auto"
609
+ };
610
+ function EmbeddingBlock({ block, className }) {
611
+ const config = useNcmConfig();
612
+ const resolvedUrl = config.embeddings?.resolveUrl?.(block.target, block.embed_type) ?? block.target;
613
+ const CustomRenderer = config.embeddings?.renderers?.[block.embed_type];
614
+ if (CustomRenderer) {
615
+ return /* @__PURE__ */ jsx(CustomRenderer, { block, className, resolvedUrl });
616
+ }
617
+ switch (block.embed_type) {
618
+ case "image":
619
+ return /* @__PURE__ */ jsx(
620
+ ImageEmbed,
621
+ {
622
+ block,
623
+ resolvedUrl,
624
+ className: cn(config.embeddings?.imageClassName, className)
625
+ }
626
+ );
627
+ case "video":
628
+ return /* @__PURE__ */ jsx(
629
+ VideoEmbed,
630
+ {
631
+ block,
632
+ resolvedUrl,
633
+ className: cn(config.embeddings?.videoClassName, className)
634
+ }
635
+ );
636
+ case "audio":
637
+ return /* @__PURE__ */ jsx(
638
+ AudioEmbed,
639
+ {
640
+ block,
641
+ resolvedUrl,
642
+ className: cn(config.embeddings?.audioClassName, className)
643
+ }
644
+ );
645
+ case "pdf":
646
+ return /* @__PURE__ */ jsx(PdfEmbed, { block, resolvedUrl, className });
647
+ case "ncm_embed":
648
+ return /* @__PURE__ */ jsx(NcmEmbed, { block, resolvedUrl, className });
649
+ case "iframe":
650
+ return /* @__PURE__ */ jsx(IframeEmbed, { block, resolvedUrl, className });
651
+ case "generic_file":
652
+ default:
653
+ return /* @__PURE__ */ jsx(GenericFileEmbed, { block, resolvedUrl, className });
654
+ }
655
+ }
656
+ function dataAttrs(block, embedType) {
657
+ return {
658
+ "data-ncm-block": block.id,
659
+ "data-ncm-stable": block.stableId,
660
+ "data-ncm-type": block.type,
661
+ "data-block-id": block.id,
662
+ "data-ncm-embedding": "",
663
+ "data-ncm-embed-type": embedType
664
+ };
665
+ }
666
+ function ImageEmbed({ block, resolvedUrl, className }) {
667
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs(block, "image"), className, children: [
668
+ /* @__PURE__ */ jsx("img", { src: resolvedUrl, alt: block.caption ?? "" }),
669
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
670
+ ] });
671
+ }
672
+ function VideoEmbed({ block, resolvedUrl, className }) {
673
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs(block, "video"), className, children: [
674
+ /* @__PURE__ */ jsx("video", { src: resolvedUrl, controls: true }),
675
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
676
+ ] });
677
+ }
678
+ function AudioEmbed({ block, resolvedUrl, className }) {
679
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs(block, "audio"), className, children: [
680
+ /* @__PURE__ */ jsx("audio", { src: resolvedUrl, controls: true, className: "w-full" }),
681
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
682
+ ] });
683
+ }
684
+ function PdfEmbed({ block, resolvedUrl, className }) {
685
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs(block, "pdf"), className: cn("w-full max-w-full", className), children: [
686
+ /* @__PURE__ */ jsx(
687
+ "iframe",
688
+ {
689
+ src: resolvedUrl,
690
+ title: block.caption ?? "PDF document",
691
+ className: "rounded-lg border border-border",
692
+ style: embedFrameStyle
693
+ }
694
+ ),
695
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
696
+ ] });
697
+ }
698
+ function IframeEmbed({ block, resolvedUrl, className }) {
699
+ const [useFrame, setUseFrame] = useState(false);
700
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs(block, "iframe"), className: cn("w-full max-w-full", className), children: [
701
+ useFrame ? /* @__PURE__ */ jsx(
702
+ "iframe",
703
+ {
704
+ src: resolvedUrl,
705
+ title: block.caption ?? block.alt ?? block.target,
706
+ className: "rounded-lg border border-border",
707
+ style: embedFrameStyle
708
+ }
709
+ ) : /* @__PURE__ */ jsx(
710
+ "img",
711
+ {
712
+ src: resolvedUrl,
713
+ alt: block.alt || block.caption || block.target,
714
+ style: embedMediaStyle,
715
+ onError: () => setUseFrame(true)
716
+ }
717
+ ),
718
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
719
+ ] });
720
+ }
721
+ function NcmEmbed({ block, resolvedUrl, className }) {
722
+ return /* @__PURE__ */ jsxs(
723
+ "div",
724
+ {
725
+ ...dataAttrs(block, "ncm_embed"),
726
+ className: cn("rounded-lg border border-dashed border-border bg-muted p-4", className),
727
+ children: [
728
+ /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
729
+ "Embedded: ",
730
+ /* @__PURE__ */ jsx("code", { className: "rounded bg-background px-1", children: block.target }),
731
+ resolvedUrl !== block.target && /* @__PURE__ */ jsxs(Fragment, { children: [
732
+ " ",
733
+ /* @__PURE__ */ jsx("a", { href: resolvedUrl, className: "underline underline-offset-4", children: "open" })
734
+ ] })
735
+ ] }),
736
+ block.caption && /* @__PURE__ */ jsx("div", { className: "mt-2 text-sm text-muted-foreground", children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
737
+ ]
738
+ }
739
+ );
740
+ }
741
+ function GenericFileEmbed({ block, resolvedUrl, className }) {
742
+ return /* @__PURE__ */ jsxs("figure", { ...dataAttrs(block, "generic_file"), className, children: [
743
+ /* @__PURE__ */ jsxs(
744
+ "a",
745
+ {
746
+ href: resolvedUrl,
747
+ download: true,
748
+ className: "flex items-center gap-2 rounded-lg border border-border bg-muted p-4 hover:bg-background",
749
+ children: [
750
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: block.target }),
751
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
752
+ "(",
753
+ block.file_format.toUpperCase(),
754
+ ")"
755
+ ] })
756
+ ]
757
+ }
758
+ ),
759
+ block.caption && /* @__PURE__ */ jsx("figcaption", { children: /* @__PURE__ */ jsx(InlineContent, { content: block.caption }) })
760
+ ] });
761
+ }
762
+
763
+ export { EmbeddingBlock };