@nuucognition/ncm-ui 0.1.0-dev.1 → 0.1.1-beta.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 (74) hide show
  1. package/README.md +90 -0
  2. package/dist/blocks/admonition/index.d.ts +2 -3
  3. package/dist/blocks/admonition/index.js +79 -23
  4. package/dist/blocks/aside/index.d.ts +2 -3
  5. package/dist/blocks/aside/index.js +79 -23
  6. package/dist/blocks/attribution/index.d.ts +2 -3
  7. package/dist/blocks/blockquote/index.d.ts +5 -4
  8. package/dist/blocks/blockquote/index.js +52 -7
  9. package/dist/blocks/chart/index.d.ts +2 -3
  10. package/dist/blocks/chart/index.js +2 -1
  11. package/dist/blocks/code/index.d.ts +2 -3
  12. package/dist/blocks/code/index.js +2 -2
  13. package/dist/blocks/container/index.d.ts +2 -3
  14. package/dist/blocks/container/index.js +50 -5
  15. package/dist/blocks/custom-code/index.d.ts +2 -3
  16. package/dist/blocks/custom-code/index.js +1 -1
  17. package/dist/blocks/dataview/index.d.ts +2 -3
  18. package/dist/blocks/dataview/index.js +2 -1
  19. package/dist/blocks/definition/index.d.ts +2 -3
  20. package/dist/blocks/definition/index.js +79 -23
  21. package/dist/blocks/embed/index.d.ts +2 -3
  22. package/dist/blocks/embedding/index.d.ts +2 -3
  23. package/dist/blocks/embedding/index.js +50 -5
  24. package/dist/blocks/figure/index.d.ts +2 -3
  25. package/dist/blocks/figure/index.js +50 -5
  26. package/dist/blocks/footnote/index.d.ts +2 -3
  27. package/dist/blocks/footnote/index.js +79 -23
  28. package/dist/blocks/frontmatter/index.d.ts +2 -3
  29. package/dist/blocks/header/index.d.ts +2 -3
  30. package/dist/blocks/header/index.js +50 -5
  31. package/dist/blocks/horizontal-rule/index.d.ts +2 -3
  32. package/dist/blocks/html/index.d.ts +3 -4
  33. package/dist/blocks/html/index.js +2 -1
  34. package/dist/blocks/index.d.ts +1 -2
  35. package/dist/blocks/index.js +79 -23
  36. package/dist/blocks/latex/index.d.ts +2 -3
  37. package/dist/blocks/latex/index.js +2 -2
  38. package/dist/blocks/link/index.d.ts +2 -3
  39. package/dist/blocks/list/index.d.ts +2 -3
  40. package/dist/blocks/list/index.js +57 -7
  41. package/dist/blocks/math/index.d.ts +2 -3
  42. package/dist/blocks/math/index.js +3 -2
  43. package/dist/blocks/mermaid/index.d.ts +2 -3
  44. package/dist/blocks/mermaid/index.js +2 -1
  45. package/dist/blocks/page-breaker/index.d.ts +2 -3
  46. package/dist/blocks/paragraph/index.d.ts +2 -3
  47. package/dist/blocks/paragraph/index.js +50 -5
  48. package/dist/blocks/spoiler/index.d.ts +2 -3
  49. package/dist/blocks/spoiler/index.js +79 -23
  50. package/dist/blocks/table/index.d.ts +2 -3
  51. package/dist/blocks/table/index.js +51 -6
  52. package/dist/blocks/task-list/index.d.ts +2 -3
  53. package/dist/blocks/task-list/index.js +52 -6
  54. package/dist/components/index.d.ts +34 -4
  55. package/dist/components/index.js +117 -25
  56. package/dist/components/ncm-block.d.ts +2 -3
  57. package/dist/components/ncm-block.js +79 -23
  58. package/dist/components/ncm-document.d.ts +4 -4
  59. package/dist/components/ncm-document.js +79 -23
  60. package/dist/context/index.d.ts +2 -3
  61. package/dist/hooks/index.d.ts +1 -2
  62. package/dist/hooks/index.js +79 -23
  63. package/dist/hooks/use-block-renderer.js +79 -23
  64. package/dist/hooks/use-ncm-config.d.ts +1 -2
  65. package/dist/index.d.ts +3 -4
  66. package/dist/index.js +118 -26
  67. package/dist/inline/index.d.ts +4 -4
  68. package/dist/inline/index.js +51 -6
  69. package/dist/lib/defaults.js +79 -23
  70. package/dist/{references-Bs5wJybr.d.ts → references-BYW5pnj_.d.ts} +4 -4
  71. package/dist/styles/nuu.css +329 -44
  72. package/dist/styles/paper.css +62 -1
  73. package/dist/{use-ncm-config-D0doMYTH.d.ts → use-ncm-config-CnntcShj.d.ts} +55 -4
  74. package/package.json +5 -5
@@ -506,9 +506,10 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
506
506
  case "image": {
507
507
  const src = config.inline?.resolveAssetPath?.(token.src) ?? token.src;
508
508
  return /* @__PURE__ */ jsx(
509
- "img",
509
+ EmbedImage,
510
510
  {
511
- "data-ncm-token": "image",
511
+ attrs: { "data-ncm-token": "image" },
512
+ target: token.src,
512
513
  src,
513
514
  alt: token.alt,
514
515
  title: token.title
@@ -542,10 +543,13 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
542
543
  }
543
544
  if (embedType === "image") {
544
545
  return /* @__PURE__ */ jsx(
545
- "img",
546
+ EmbedImage,
546
547
  {
547
- "data-ncm-token": "wiki_embed",
548
- "data-ncm-wikiembed-type": embedType,
548
+ attrs: {
549
+ "data-ncm-token": "wiki_embed",
550
+ "data-ncm-wikiembed-type": embedType
551
+ },
552
+ target: token.target,
549
553
  src: url,
550
554
  alt: token.display ?? token.target,
551
555
  className: config.embeddings?.imageClassName
@@ -576,6 +580,22 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
576
580
  }
577
581
  );
578
582
  }
583
+ const onEmbedClick = config.embeddings?.onEmbedClick;
584
+ if (onEmbedClick) {
585
+ const handleClick = (e) => {
586
+ onEmbedClick(token.target, result, e);
587
+ };
588
+ return /* @__PURE__ */ jsx(
589
+ "button",
590
+ {
591
+ type: "button",
592
+ "data-ncm-token": "wiki_embed",
593
+ "data-ncm-wikiembed-type": embedType,
594
+ onClick: handleClick,
595
+ children: token.display ?? token.target
596
+ }
597
+ );
598
+ }
579
599
  return /* @__PURE__ */ jsx(
580
600
  "a",
581
601
  {
@@ -594,6 +614,31 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
594
614
  return null;
595
615
  }
596
616
  }
617
+ function EmbedImage({ attrs, target, src, alt, title, className }) {
618
+ const config = useNcmConfig();
619
+ const Fallback = config.embeddings?.renderImageError;
620
+ const [failedSrc, setFailedSrc] = useState(null);
621
+ useEffect(() => {
622
+ setFailedSrc(null);
623
+ }, [src]);
624
+ if (!Fallback) {
625
+ return /* @__PURE__ */ jsx("img", { ...attrs, src, alt, title, className });
626
+ }
627
+ if (failedSrc === src) {
628
+ return /* @__PURE__ */ jsx(Fallback, { target, src, alt, retry: () => setFailedSrc(null) });
629
+ }
630
+ return /* @__PURE__ */ jsx(
631
+ "img",
632
+ {
633
+ ...attrs,
634
+ src,
635
+ alt,
636
+ title,
637
+ className,
638
+ onError: () => setFailedSrc(src)
639
+ }
640
+ );
641
+ }
597
642
  function renderReadingText(content, opts) {
598
643
  if (!content) return /* @__PURE__ */ jsx(Fragment, { children: content });
599
644
  const { bionic = false, beeline = false } = opts;
@@ -629,7 +674,7 @@ function renderReadingText(content, opts) {
629
674
  return /* @__PURE__ */ jsx(Fragment, { children: pieces });
630
675
  }
631
676
  function BlockquoteBlock({ block, className }) {
632
- const lines = block.content.split("\n").filter((line) => line.trim() !== "");
677
+ const lines = block.content.split("\n");
633
678
  return /* @__PURE__ */ jsx(
634
679
  "blockquote",
635
680
  {
@@ -639,7 +684,7 @@ function BlockquoteBlock({ block, className }) {
639
684
  "data-block-id": block.id,
640
685
  "data-ncm-blockquote": "",
641
686
  className,
642
- children: lines.length <= 1 ? /* @__PURE__ */ jsx(InlineContent, { content: block.content }) : lines.map((line, index) => /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx(InlineContent, { content: line }) }, index))
687
+ children: lines.length <= 1 ? /* @__PURE__ */ jsx(InlineContent, { content: block.content }) : lines.map((line, index) => /* @__PURE__ */ jsx("p", { children: line.trim().length > 0 ? /* @__PURE__ */ jsx(InlineContent, { content: line }) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xA0" }) }, index))
643
688
  }
644
689
  );
645
690
  }
@@ -654,7 +699,8 @@ function ChartBlock({ block, className }) {
654
699
  "data-ncm-chart": "",
655
700
  "data-ncm-chart-type": block.chartType ?? "unknown",
656
701
  className: cn(
657
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
702
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose see the note in `lib/defaults.ts`.
703
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
658
704
  className
659
705
  ),
660
706
  children: /* @__PURE__ */ jsx("code", { children: block.content })
@@ -779,7 +825,7 @@ function CodeBlock({ block, className }) {
779
825
  "data-ncm-language": block.language,
780
826
  className: cn("relative", className),
781
827
  children: [
782
- codeConfig.copyButton !== false && /* @__PURE__ */ jsx(CopyButton, { content: block.content }),
828
+ codeConfig.copyButton === true && /* @__PURE__ */ jsx(CopyButton, { content: block.content }),
783
829
  /* @__PURE__ */ jsx(CustomRenderer, { code: block.content, language: block.language }),
784
830
  languageLabel
785
831
  ]
@@ -798,7 +844,7 @@ function CodeBlock({ block, className }) {
798
844
  "data-ncm-language": block.language,
799
845
  className: cn("relative", className),
800
846
  children: [
801
- codeConfig?.copyButton !== false && /* @__PURE__ */ jsx(CopyButton, { content: block.content }),
847
+ codeConfig?.copyButton === true && /* @__PURE__ */ jsx(CopyButton, { content: block.content }),
802
848
  /* @__PURE__ */ jsx("pre", { "data-ncm-code-pre": "", children: /* @__PURE__ */ jsxs("div", { className: "flex", children: [
803
849
  codeConfig?.lineNumbers && /* @__PURE__ */ jsx(LineNumbers, { count: lineCount }),
804
850
  /* @__PURE__ */ jsx("code", { "data-ncm-code": "", className: "flex-1", children: /* @__PURE__ */ jsx(DefaultShikiRenderer, { code: block.content, language: block.language }) })
@@ -834,7 +880,8 @@ function DataviewBlock({ block, className }) {
834
880
  "data-ncm-dataview": "",
835
881
  "data-ncm-query-type": block.queryType,
836
882
  className: cn(
837
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
883
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose see the note in `lib/defaults.ts`.
884
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
838
885
  className
839
886
  ),
840
887
  children: /* @__PURE__ */ jsx("code", { children: block.query })
@@ -1173,7 +1220,8 @@ function HtmlBlock({ block, className }) {
1173
1220
  "data-block-id": block.id,
1174
1221
  "data-ncm-html": "",
1175
1222
  className: cn(
1176
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1223
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose see the note in `lib/defaults.ts`.
1224
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1177
1225
  className
1178
1226
  ),
1179
1227
  children: /* @__PURE__ */ jsx("code", { children: block.content })
@@ -1234,7 +1282,7 @@ function LatexDisplayBlock({ block, className }) {
1234
1282
  "data-ncm-type": block.type,
1235
1283
  "data-block-id": block.id,
1236
1284
  "data-ncm-latex-display": "",
1237
- className: cn("overflow-x-auto", className),
1285
+ className: cn("overflow-x-auto overflow-y-hidden", className),
1238
1286
  dangerouslySetInnerHTML: { __html: html }
1239
1287
  }
1240
1288
  );
@@ -1249,7 +1297,7 @@ function LatexDisplayBlock({ block, className }) {
1249
1297
  "data-ncm-type": block.type,
1250
1298
  "data-block-id": block.id,
1251
1299
  "data-ncm-latex-display": "",
1252
- className: cn("overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm", className),
1300
+ className: cn("overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm", className),
1253
1301
  children: /* @__PURE__ */ jsx("code", { children: block.content })
1254
1302
  }
1255
1303
  );
@@ -1273,10 +1321,12 @@ function LinkBlock({ block, className }) {
1273
1321
  function ListBlock({ block, className }) {
1274
1322
  const isOrdered = block.type === "list_ordered";
1275
1323
  const Tag = isOrdered ? "ol" : "ul";
1324
+ const start = isOrdered && typeof block.marker === "number" && block.marker !== 1 ? block.marker : void 0;
1276
1325
  return /* @__PURE__ */ jsx(
1277
1326
  Tag,
1278
1327
  {
1279
1328
  role: "list",
1329
+ start,
1280
1330
  "data-ncm-block": block.id,
1281
1331
  "data-ncm-stable": block.stableId,
1282
1332
  "data-ncm-type": block.type,
@@ -1288,6 +1338,9 @@ function ListBlock({ block, className }) {
1288
1338
  }
1289
1339
  );
1290
1340
  }
1341
+ function ItemContent({ content }) {
1342
+ return content.length > 0 ? /* @__PURE__ */ jsx(InlineContent, { content }) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xA0" });
1343
+ }
1291
1344
  function nestedItemIdKey(id) {
1292
1345
  if (!id) {
1293
1346
  return void 0;
@@ -1304,7 +1357,7 @@ function ListItems({ items, itemIds, ordered }) {
1304
1357
  return /* @__PURE__ */ jsx(Fragment, { children: items.map((item, index) => {
1305
1358
  const key = nestedItemIdKey(itemIds?.[index]) ?? `item-${index}`;
1306
1359
  if (typeof item === "string") {
1307
- return /* @__PURE__ */ jsx("li", { "data-ncm-list-item": "", children: /* @__PURE__ */ jsx(InlineContent, { content: item }) }, key);
1360
+ return /* @__PURE__ */ jsx("li", { "data-ncm-list-item": "", children: /* @__PURE__ */ jsx(ItemContent, { content: item }) }, key);
1308
1361
  }
1309
1362
  if (isTypedNestedList(item)) {
1310
1363
  return /* @__PURE__ */ jsx(NestedTypedList, { list: item }, key);
@@ -1314,7 +1367,7 @@ function ListItems({ items, itemIds, ordered }) {
1314
1367
  const content = typeof first === "string" ? first : "";
1315
1368
  const nestedContent = processNestedItems(rest, ordered);
1316
1369
  return /* @__PURE__ */ jsxs("li", { "data-ncm-list-item": "", children: [
1317
- /* @__PURE__ */ jsx(InlineContent, { content }),
1370
+ /* @__PURE__ */ jsx(ItemContent, { content }),
1318
1371
  nestedContent
1319
1372
  ] }, key);
1320
1373
  }
@@ -1364,7 +1417,7 @@ function MathBlock({ block, className }) {
1364
1417
  "data-ncm-type": block.type,
1365
1418
  "data-block-id": block.id,
1366
1419
  "data-ncm-math": "",
1367
- className: cn("overflow-x-auto", className),
1420
+ className: cn("overflow-x-auto overflow-y-hidden", className),
1368
1421
  dangerouslySetInnerHTML: { __html: html }
1369
1422
  }
1370
1423
  );
@@ -1380,7 +1433,8 @@ function MathBlock({ block, className }) {
1380
1433
  "data-block-id": block.id,
1381
1434
  "data-ncm-math": "",
1382
1435
  className: cn(
1383
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1436
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose see the note in `lib/defaults.ts`.
1437
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1384
1438
  className
1385
1439
  ),
1386
1440
  children: /* @__PURE__ */ jsx("code", { children: block.content })
@@ -1398,7 +1452,8 @@ function MermaidBlock({ block, className }) {
1398
1452
  "data-ncm-mermaid": "",
1399
1453
  "data-ncm-diagram-type": block.diagramType,
1400
1454
  className: cn(
1401
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1455
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose see the note in `lib/defaults.ts`.
1456
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1402
1457
  className
1403
1458
  ),
1404
1459
  children: /* @__PURE__ */ jsx("code", { children: block.content })
@@ -1459,7 +1514,7 @@ function TableBlock({ block, className }) {
1459
1514
  "data-ncm-type": block.type,
1460
1515
  "data-block-id": block.id,
1461
1516
  "data-ncm-table": "",
1462
- className: cn("w-full overflow-x-auto", className),
1517
+ className: cn("w-full overflow-x-auto overflow-y-hidden", className),
1463
1518
  children: /* @__PURE__ */ jsxs("table", { role: "table", "data-ncm-table-element": "", children: [
1464
1519
  /* @__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)) }) }),
1465
1520
  /* @__PURE__ */ jsx("tbody", { children: block.rows.map((row, rowIndex) => {
@@ -1473,6 +1528,7 @@ function TableBlock({ block, className }) {
1473
1528
  function TaskItems({ items }) {
1474
1529
  return /* @__PURE__ */ jsx(Fragment, { children: items.map((item) => {
1475
1530
  const status = item.checked ? "Completed" : "Incomplete";
1531
+ const text = serializeInlineContent(item.content);
1476
1532
  return /* @__PURE__ */ jsxs(
1477
1533
  "li",
1478
1534
  {
@@ -1499,7 +1555,7 @@ function TaskItems({ items }) {
1499
1555
  ":",
1500
1556
  " "
1501
1557
  ] }),
1502
- /* @__PURE__ */ jsx(InlineContent, { content: serializeInlineContent(item.content) })
1558
+ text.length > 0 ? /* @__PURE__ */ jsx(InlineContent, { content: text }) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xA0" })
1503
1559
  ] })
1504
1560
  ] }),
1505
1561
  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
@@ -1544,7 +1600,7 @@ function FallbackBlock({ block, className }) {
1544
1600
  "data-block-id": block.id,
1545
1601
  "data-ncm-fallback": "",
1546
1602
  className: cn(
1547
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1603
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1548
1604
  className
1549
1605
  )
1550
1606
  },
@@ -1600,7 +1656,7 @@ function CustomCodeBlock({ block, className }) {
1600
1656
  "data-block-id": block.id,
1601
1657
  "data-ncm-custom-code": "",
1602
1658
  "data-ncm-language": block.language,
1603
- className: cn("overflow-x-auto", className),
1659
+ className: cn("overflow-x-auto overflow-y-hidden", className),
1604
1660
  children: [
1605
1661
  /* @__PURE__ */ jsx("div", { className: "mb-2 text-xs font-medium text-muted-foreground", children: block.language }),
1606
1662
  /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: block.content }) })
@@ -1,9 +1,8 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { LatexDisplayBlock as LatexDisplayBlock$1 } from '@nuucognition/ncm';
3
3
  import { a as BlockRendererProps } from '../../renderers-C5f41FCy.js';
4
- import 'react';
5
4
 
6
5
  type LatexDisplayBlockProps = BlockRendererProps<LatexDisplayBlock$1>;
7
- declare function LatexDisplayBlock({ block, className }: LatexDisplayBlockProps): react_jsx_runtime.JSX.Element;
6
+ declare function LatexDisplayBlock({ block, className }: LatexDisplayBlockProps): react.JSX.Element;
8
7
 
9
8
  export { LatexDisplayBlock, type LatexDisplayBlockProps };
@@ -83,7 +83,7 @@ function LatexDisplayBlock({ block, className }) {
83
83
  "data-ncm-type": block.type,
84
84
  "data-block-id": block.id,
85
85
  "data-ncm-latex-display": "",
86
- className: cn("overflow-x-auto", className),
86
+ className: cn("overflow-x-auto overflow-y-hidden", className),
87
87
  dangerouslySetInnerHTML: { __html: html }
88
88
  }
89
89
  );
@@ -98,7 +98,7 @@ function LatexDisplayBlock({ block, className }) {
98
98
  "data-ncm-type": block.type,
99
99
  "data-block-id": block.id,
100
100
  "data-ncm-latex-display": "",
101
- className: cn("overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm", className),
101
+ className: cn("overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm", className),
102
102
  children: /* @__PURE__ */ jsx("code", { children: block.content })
103
103
  }
104
104
  );
@@ -1,7 +1,6 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { LinkBlock as LinkBlock$1 } from '@nuucognition/ncm';
3
3
  import { a as BlockRendererProps } from '../../renderers-C5f41FCy.js';
4
- import 'react';
5
4
 
6
5
  type LinkBlockProps = BlockRendererProps<LinkBlock$1>;
7
6
  /**
@@ -9,6 +8,6 @@ type LinkBlockProps = BlockRendererProps<LinkBlock$1>;
9
8
  * for card-style rendering. Default is a block-level anchor; override the `link`
10
9
  * renderer key for rich link previews.
11
10
  */
12
- declare function LinkBlock({ block, className }: LinkBlockProps): react_jsx_runtime.JSX.Element;
11
+ declare function LinkBlock({ block, className }: LinkBlockProps): react.JSX.Element;
13
12
 
14
13
  export { LinkBlock, type LinkBlockProps };
@@ -1,9 +1,8 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { ListBlock as ListBlock$1 } from '@nuucognition/ncm';
3
3
  import { a as BlockRendererProps } from '../../renderers-C5f41FCy.js';
4
- import 'react';
5
4
 
6
5
  type ListBlockProps = BlockRendererProps<ListBlock$1>;
7
- declare function ListBlock({ block, className }: ListBlockProps): react_jsx_runtime.JSX.Element;
6
+ declare function ListBlock({ block, className }: ListBlockProps): react.JSX.Element;
8
7
 
9
8
  export { ListBlock, type ListBlockProps };
@@ -468,9 +468,10 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
468
468
  case "image": {
469
469
  const src = config.inline?.resolveAssetPath?.(token.src) ?? token.src;
470
470
  return /* @__PURE__ */ jsx(
471
- "img",
471
+ EmbedImage,
472
472
  {
473
- "data-ncm-token": "image",
473
+ attrs: { "data-ncm-token": "image" },
474
+ target: token.src,
474
475
  src,
475
476
  alt: token.alt,
476
477
  title: token.title
@@ -504,10 +505,13 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
504
505
  }
505
506
  if (embedType === "image") {
506
507
  return /* @__PURE__ */ jsx(
507
- "img",
508
+ EmbedImage,
508
509
  {
509
- "data-ncm-token": "wiki_embed",
510
- "data-ncm-wikiembed-type": embedType,
510
+ attrs: {
511
+ "data-ncm-token": "wiki_embed",
512
+ "data-ncm-wikiembed-type": embedType
513
+ },
514
+ target: token.target,
511
515
  src: url,
512
516
  alt: token.display ?? token.target,
513
517
  className: config.embeddings?.imageClassName
@@ -538,6 +542,22 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
538
542
  }
539
543
  );
540
544
  }
545
+ const onEmbedClick = config.embeddings?.onEmbedClick;
546
+ if (onEmbedClick) {
547
+ const handleClick = (e) => {
548
+ onEmbedClick(token.target, result, e);
549
+ };
550
+ return /* @__PURE__ */ jsx(
551
+ "button",
552
+ {
553
+ type: "button",
554
+ "data-ncm-token": "wiki_embed",
555
+ "data-ncm-wikiembed-type": embedType,
556
+ onClick: handleClick,
557
+ children: token.display ?? token.target
558
+ }
559
+ );
560
+ }
541
561
  return /* @__PURE__ */ jsx(
542
562
  "a",
543
563
  {
@@ -556,6 +576,31 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
556
576
  return null;
557
577
  }
558
578
  }
579
+ function EmbedImage({ attrs, target, src, alt, title, className }) {
580
+ const config = useNcmConfig();
581
+ const Fallback = config.embeddings?.renderImageError;
582
+ const [failedSrc, setFailedSrc] = useState(null);
583
+ useEffect(() => {
584
+ setFailedSrc(null);
585
+ }, [src]);
586
+ if (!Fallback) {
587
+ return /* @__PURE__ */ jsx("img", { ...attrs, src, alt, title, className });
588
+ }
589
+ if (failedSrc === src) {
590
+ return /* @__PURE__ */ jsx(Fallback, { target, src, alt, retry: () => setFailedSrc(null) });
591
+ }
592
+ return /* @__PURE__ */ jsx(
593
+ "img",
594
+ {
595
+ ...attrs,
596
+ src,
597
+ alt,
598
+ title,
599
+ className,
600
+ onError: () => setFailedSrc(src)
601
+ }
602
+ );
603
+ }
559
604
  function renderReadingText(content, opts) {
560
605
  if (!content) return /* @__PURE__ */ jsx(Fragment, { children: content });
561
606
  const { bionic = false, beeline = false } = opts;
@@ -593,10 +638,12 @@ function renderReadingText(content, opts) {
593
638
  function ListBlock({ block, className }) {
594
639
  const isOrdered = block.type === "list_ordered";
595
640
  const Tag = isOrdered ? "ol" : "ul";
641
+ const start = isOrdered && typeof block.marker === "number" && block.marker !== 1 ? block.marker : void 0;
596
642
  return /* @__PURE__ */ jsx(
597
643
  Tag,
598
644
  {
599
645
  role: "list",
646
+ start,
600
647
  "data-ncm-block": block.id,
601
648
  "data-ncm-stable": block.stableId,
602
649
  "data-ncm-type": block.type,
@@ -608,6 +655,9 @@ function ListBlock({ block, className }) {
608
655
  }
609
656
  );
610
657
  }
658
+ function ItemContent({ content }) {
659
+ return content.length > 0 ? /* @__PURE__ */ jsx(InlineContent, { content }) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xA0" });
660
+ }
611
661
  function nestedItemIdKey(id) {
612
662
  if (!id) {
613
663
  return void 0;
@@ -624,7 +674,7 @@ function ListItems({ items, itemIds, ordered }) {
624
674
  return /* @__PURE__ */ jsx(Fragment, { children: items.map((item, index) => {
625
675
  const key = nestedItemIdKey(itemIds?.[index]) ?? `item-${index}`;
626
676
  if (typeof item === "string") {
627
- return /* @__PURE__ */ jsx("li", { "data-ncm-list-item": "", children: /* @__PURE__ */ jsx(InlineContent, { content: item }) }, key);
677
+ return /* @__PURE__ */ jsx("li", { "data-ncm-list-item": "", children: /* @__PURE__ */ jsx(ItemContent, { content: item }) }, key);
628
678
  }
629
679
  if (isTypedNestedList(item)) {
630
680
  return /* @__PURE__ */ jsx(NestedTypedList, { list: item }, key);
@@ -634,7 +684,7 @@ function ListItems({ items, itemIds, ordered }) {
634
684
  const content = typeof first === "string" ? first : "";
635
685
  const nestedContent = processNestedItems(rest, ordered);
636
686
  return /* @__PURE__ */ jsxs("li", { "data-ncm-list-item": "", children: [
637
- /* @__PURE__ */ jsx(InlineContent, { content }),
687
+ /* @__PURE__ */ jsx(ItemContent, { content }),
638
688
  nestedContent
639
689
  ] }, key);
640
690
  }
@@ -1,13 +1,12 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { MathBlock as MathBlock$1 } from '@nuucognition/ncm';
3
3
  import { a as BlockRendererProps } from '../../renderers-C5f41FCy.js';
4
- import 'react';
5
4
 
6
5
  type MathBlockProps = BlockRendererProps<MathBlock$1>;
7
6
  /**
8
7
  * Math renderer — promoted ```math fences rendered as display KaTeX (mirrors
9
8
  * LatexDisplayBlock). Falls back to escaped source on KaTeX errors.
10
9
  */
11
- declare function MathBlock({ block, className }: MathBlockProps): react_jsx_runtime.JSX.Element;
10
+ declare function MathBlock({ block, className }: MathBlockProps): react.JSX.Element;
12
11
 
13
12
  export { MathBlock, type MathBlockProps };
@@ -61,7 +61,7 @@ function MathBlock({ block, className }) {
61
61
  "data-ncm-type": block.type,
62
62
  "data-block-id": block.id,
63
63
  "data-ncm-math": "",
64
- className: cn("overflow-x-auto", className),
64
+ className: cn("overflow-x-auto overflow-y-hidden", className),
65
65
  dangerouslySetInnerHTML: { __html: html }
66
66
  }
67
67
  );
@@ -77,7 +77,8 @@ function MathBlock({ block, className }) {
77
77
  "data-block-id": block.id,
78
78
  "data-ncm-math": "",
79
79
  className: cn(
80
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
80
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose see the note in `lib/defaults.ts`.
81
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
81
82
  className
82
83
  ),
83
84
  children: /* @__PURE__ */ jsx("code", { children: block.content })
@@ -1,7 +1,6 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { MermaidBlock as MermaidBlock$1 } from '@nuucognition/ncm';
3
3
  import { a as BlockRendererProps } from '../../renderers-C5f41FCy.js';
4
- import 'react';
5
4
 
6
5
  type MermaidBlockProps = BlockRendererProps<MermaidBlock$1>;
7
6
  /**
@@ -9,6 +8,6 @@ type MermaidBlockProps = BlockRendererProps<MermaidBlock$1>;
9
8
  * is bundled in this package). Consumers wire a live renderer by overriding the
10
9
  * `mermaid` renderer key. `data-ncm-diagram-type` exposes the detected kind.
11
10
  */
12
- declare function MermaidBlock({ block, className }: MermaidBlockProps): react_jsx_runtime.JSX.Element;
11
+ declare function MermaidBlock({ block, className }: MermaidBlockProps): react.JSX.Element;
13
12
 
14
13
  export { MermaidBlock, type MermaidBlockProps };
@@ -18,7 +18,8 @@ function MermaidBlock({ block, className }) {
18
18
  "data-ncm-mermaid": "",
19
19
  "data-ncm-diagram-type": block.diagramType,
20
20
  className: cn(
21
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
21
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose see the note in `lib/defaults.ts`.
22
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
22
23
  className
23
24
  ),
24
25
  children: /* @__PURE__ */ jsx("code", { children: block.content })
@@ -1,7 +1,6 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { PageBreakerBlock as PageBreakerBlock$1 } from '@nuucognition/ncm';
3
3
  import { a as BlockRendererProps } from '../../renderers-C5f41FCy.js';
4
- import 'react';
5
4
 
6
5
  type PageBreakerBlockProps = BlockRendererProps<PageBreakerBlock$1>;
7
6
  /**
@@ -11,6 +10,6 @@ type PageBreakerBlockProps = BlockRendererProps<PageBreakerBlock$1>;
11
10
  * can locate where each source PDF page begins (e.g. to scroll-sync rendered
12
11
  * markdown against the original PDF). It produces no visible output.
13
12
  */
14
- declare function PageBreakerBlock({ block, className }: PageBreakerBlockProps): react_jsx_runtime.JSX.Element;
13
+ declare function PageBreakerBlock({ block, className }: PageBreakerBlockProps): react.JSX.Element;
15
14
 
16
15
  export { PageBreakerBlock, type PageBreakerBlockProps };
@@ -1,9 +1,8 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { ParagraphBlock as ParagraphBlock$1 } from '@nuucognition/ncm';
3
3
  import { a as BlockRendererProps } from '../../renderers-C5f41FCy.js';
4
- import 'react';
5
4
 
6
5
  type ParagraphBlockProps = BlockRendererProps<ParagraphBlock$1>;
7
- declare function ParagraphBlock({ block, className }: ParagraphBlockProps): react_jsx_runtime.JSX.Element;
6
+ declare function ParagraphBlock({ block, className }: ParagraphBlockProps): react.JSX.Element;
8
7
 
9
8
  export { ParagraphBlock, type ParagraphBlockProps };
@@ -468,9 +468,10 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
468
468
  case "image": {
469
469
  const src = config.inline?.resolveAssetPath?.(token.src) ?? token.src;
470
470
  return /* @__PURE__ */ jsx(
471
- "img",
471
+ EmbedImage,
472
472
  {
473
- "data-ncm-token": "image",
473
+ attrs: { "data-ncm-token": "image" },
474
+ target: token.src,
474
475
  src,
475
476
  alt: token.alt,
476
477
  title: token.title
@@ -504,10 +505,13 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
504
505
  }
505
506
  if (embedType === "image") {
506
507
  return /* @__PURE__ */ jsx(
507
- "img",
508
+ EmbedImage,
508
509
  {
509
- "data-ncm-token": "wiki_embed",
510
- "data-ncm-wikiembed-type": embedType,
510
+ attrs: {
511
+ "data-ncm-token": "wiki_embed",
512
+ "data-ncm-wikiembed-type": embedType
513
+ },
514
+ target: token.target,
511
515
  src: url,
512
516
  alt: token.display ?? token.target,
513
517
  className: config.embeddings?.imageClassName
@@ -538,6 +542,22 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
538
542
  }
539
543
  );
540
544
  }
545
+ const onEmbedClick = config.embeddings?.onEmbedClick;
546
+ if (onEmbedClick) {
547
+ const handleClick = (e) => {
548
+ onEmbedClick(token.target, result, e);
549
+ };
550
+ return /* @__PURE__ */ jsx(
551
+ "button",
552
+ {
553
+ type: "button",
554
+ "data-ncm-token": "wiki_embed",
555
+ "data-ncm-wikiembed-type": embedType,
556
+ onClick: handleClick,
557
+ children: token.display ?? token.target
558
+ }
559
+ );
560
+ }
541
561
  return /* @__PURE__ */ jsx(
542
562
  "a",
543
563
  {
@@ -556,6 +576,31 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
556
576
  return null;
557
577
  }
558
578
  }
579
+ function EmbedImage({ attrs, target, src, alt, title, className }) {
580
+ const config = useNcmConfig();
581
+ const Fallback = config.embeddings?.renderImageError;
582
+ const [failedSrc, setFailedSrc] = useState(null);
583
+ useEffect(() => {
584
+ setFailedSrc(null);
585
+ }, [src]);
586
+ if (!Fallback) {
587
+ return /* @__PURE__ */ jsx("img", { ...attrs, src, alt, title, className });
588
+ }
589
+ if (failedSrc === src) {
590
+ return /* @__PURE__ */ jsx(Fallback, { target, src, alt, retry: () => setFailedSrc(null) });
591
+ }
592
+ return /* @__PURE__ */ jsx(
593
+ "img",
594
+ {
595
+ ...attrs,
596
+ src,
597
+ alt,
598
+ title,
599
+ className,
600
+ onError: () => setFailedSrc(src)
601
+ }
602
+ );
603
+ }
559
604
  function renderReadingText(content, opts) {
560
605
  if (!content) return /* @__PURE__ */ jsx(Fragment, { children: content });
561
606
  const { bionic = false, beeline = false } = opts;
@@ -1,13 +1,12 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { SpoilerBlock as SpoilerBlock$1 } from '@nuucognition/ncm';
3
3
  import { a as BlockRendererProps } from '../../renderers-C5f41FCy.js';
4
- import 'react';
5
4
 
6
5
  type SpoilerBlockProps = BlockRendererProps<SpoilerBlock$1>;
7
6
  /**
8
7
  * Spoiler renderer — collapsible hidden content (`>!` or `<details>`). Child
9
8
  * blocks render through `NcmBlock`.
10
9
  */
11
- declare function SpoilerBlock({ block, className }: SpoilerBlockProps): react_jsx_runtime.JSX.Element;
10
+ declare function SpoilerBlock({ block, className }: SpoilerBlockProps): react.JSX.Element;
12
11
 
13
12
  export { SpoilerBlock, type SpoilerBlockProps };