@nuucognition/ncm-ui 0.1.1-beta.0 → 0.1.1-beta.2

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 (39) hide show
  1. package/dist/blocks/admonition/index.js +118 -46
  2. package/dist/blocks/aside/index.js +118 -46
  3. package/dist/blocks/blockquote/index.d.ts +7 -5
  4. package/dist/blocks/blockquote/index.js +1218 -36
  5. package/dist/blocks/chart/index.js +2 -1
  6. package/dist/blocks/container/index.js +72 -31
  7. package/dist/blocks/custom-code/index.js +1 -1
  8. package/dist/blocks/dataview/index.js +2 -1
  9. package/dist/blocks/definition/index.js +117 -45
  10. package/dist/blocks/embedding/index.js +72 -31
  11. package/dist/blocks/figure/index.js +72 -31
  12. package/dist/blocks/footnote/index.js +118 -46
  13. package/dist/blocks/header/index.js +72 -31
  14. package/dist/blocks/html/index.js +2 -1
  15. package/dist/blocks/index.js +118 -46
  16. package/dist/blocks/latex/index.js +2 -2
  17. package/dist/blocks/list/index.js +72 -31
  18. package/dist/blocks/math/index.js +3 -2
  19. package/dist/blocks/mermaid/index.js +2 -1
  20. package/dist/blocks/paragraph/index.js +72 -31
  21. package/dist/blocks/spoiler/index.js +118 -46
  22. package/dist/blocks/table/index.js +73 -32
  23. package/dist/blocks/task-list/index.js +72 -31
  24. package/dist/components/index.js +157 -65
  25. package/dist/components/ncm-block.js +118 -46
  26. package/dist/components/ncm-document.js +157 -65
  27. package/dist/context/index.d.ts +1 -1
  28. package/dist/context/index.js +119 -44
  29. package/dist/hooks/index.js +118 -46
  30. package/dist/hooks/use-block-renderer.js +118 -46
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.js +164 -58
  33. package/dist/inline/index.d.ts +2 -3
  34. package/dist/inline/index.js +72 -31
  35. package/dist/lib/defaults.js +118 -46
  36. package/dist/references-BM-lvGrq.d.ts +99 -0
  37. package/dist/styles/nuu.css +39 -16
  38. package/package.json +3 -4
  39. package/dist/references-BYW5pnj_.d.ts +0 -63
@@ -48,6 +48,52 @@ function tryParseInlineRef(input) {
48
48
  }
49
49
  return { token: { type: "inline_ref", kind: "footnote", content: inner.trim() }, length };
50
50
  }
51
+ function runLength(input, index, char) {
52
+ let end = index;
53
+ while (end < input.length && input[end] === char) end++;
54
+ return end - index;
55
+ }
56
+ function tryParseEmphasis(input) {
57
+ const char = input[0];
58
+ if (char !== "*" && char !== "_") return null;
59
+ const open = Math.min(3, runLength(input, 0, char));
60
+ const need = open;
61
+ let i = open;
62
+ while (i < input.length) {
63
+ const ch = input[i];
64
+ if (ch === "`") {
65
+ const close = input.indexOf("`", i + 1);
66
+ if (close === -1) break;
67
+ i = close + 1;
68
+ continue;
69
+ }
70
+ if (ch !== char) {
71
+ i++;
72
+ continue;
73
+ }
74
+ const run = runLength(input, i, char);
75
+ const closes = need === 1 ? run % 2 === 1 : run >= need;
76
+ if (!closes) {
77
+ i += run;
78
+ continue;
79
+ }
80
+ const extra = run - need;
81
+ const inner = input.slice(open, i + extra);
82
+ if (inner.length === 0) return null;
83
+ const length = i + run;
84
+ const children = parseInline(inner);
85
+ let token;
86
+ if (need === 3) {
87
+ token = { type: "bold", children: [{ type: "italic", children }] };
88
+ } else if (need === 2) {
89
+ token = { type: "bold", children };
90
+ } else {
91
+ token = { type: "italic", children };
92
+ }
93
+ return { token, length };
94
+ }
95
+ return null;
96
+ }
51
97
  function parseInline(content) {
52
98
  if (!content) return [];
53
99
  const tokens = [];
@@ -119,17 +165,11 @@ function parseInline(content) {
119
165
  remaining = remaining.slice(linkMatch[0].length);
120
166
  continue;
121
167
  }
122
- const boldMatch = remaining.match(/^\*\*(.+?)\*\*|^__(.+?)__/);
123
- if (boldMatch) {
124
- const innerContent = boldMatch[1] ?? boldMatch[2];
125
- if (innerContent !== void 0) {
126
- tokens.push({
127
- type: "bold",
128
- children: parseInline(innerContent)
129
- });
130
- remaining = remaining.slice(boldMatch[0].length);
131
- continue;
132
- }
168
+ const emphasis = tryParseEmphasis(remaining);
169
+ if (emphasis) {
170
+ tokens.push(emphasis.token);
171
+ remaining = remaining.slice(emphasis.length);
172
+ continue;
133
173
  }
134
174
  const strikeMatch = remaining.match(/^~~(.+?)~~/);
135
175
  if (strikeMatch && strikeMatch[1] !== void 0) {
@@ -140,18 +180,6 @@ function parseInline(content) {
140
180
  remaining = remaining.slice(strikeMatch[0].length);
141
181
  continue;
142
182
  }
143
- const italicMatch = remaining.match(/^\*([^*]+)\*|^_([^_]+)_/);
144
- if (italicMatch) {
145
- const innerContent = italicMatch[1] ?? italicMatch[2];
146
- if (innerContent !== void 0) {
147
- tokens.push({
148
- type: "italic",
149
- children: parseInline(innerContent)
150
- });
151
- remaining = remaining.slice(italicMatch[0].length);
152
- continue;
153
- }
154
- }
155
183
  const nextSpecial = findNextSpecialChar(remaining);
156
184
  if (nextSpecial > 0) {
157
185
  tokens.push({ type: "text", content: remaining.slice(0, nextSpecial) });
@@ -262,17 +290,30 @@ function ReferenceMarker({ kind, number, children }) {
262
290
  }
263
291
  );
264
292
  }
265
- var ReferenceBasesContext = createContext(null);
293
+ function normalizeReferenceContent(content) {
294
+ return content.replace(/\s+/g, " ").trim().toLowerCase();
295
+ }
296
+ var ReferenceNumberingContext = createContext(null);
266
297
  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 };
298
+ function BlockReferenceScope({ children }) {
299
+ const numbering = useContext(ReferenceNumberingContext);
300
+ const local = useRef({ ref: /* @__PURE__ */ new Map(), footnote: /* @__PURE__ */ new Map() });
270
301
  const counter = useRef({ ref: 0, footnote: 0 });
271
- counter.current = { ref: 0, footnote: 0 };
272
302
  const value = {
303
+ numberFor(kind, content) {
304
+ const key = normalizeReferenceContent(content);
305
+ const fromDocument = numbering?.[kind].get(key);
306
+ if (fromDocument !== void 0) return fromDocument;
307
+ const map = local.current[kind];
308
+ const existing = map.get(key);
309
+ if (existing !== void 0) return existing;
310
+ counter.current[kind] += 1;
311
+ map.set(key, counter.current[kind]);
312
+ return counter.current[kind];
313
+ },
273
314
  next(kind) {
274
315
  counter.current[kind] += 1;
275
- return base[kind] + counter.current[kind];
316
+ return counter.current[kind];
276
317
  }
277
318
  };
278
319
  return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value, children });
@@ -280,7 +321,7 @@ function BlockReferenceScope({ blockId, children }) {
280
321
  function useBlockReferenceScope() {
281
322
  return useContext(BlockReferenceScopeContext);
282
323
  }
283
- var INERT_SCOPE = { next: () => 0 };
324
+ var INERT_SCOPE = { numberFor: () => 0, next: () => 0 };
284
325
  function InertReferenceScope({ children }) {
285
326
  return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value: INERT_SCOPE, children });
286
327
  }
@@ -571,7 +612,7 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
571
612
  );
572
613
  }
573
614
  case "inline_ref": {
574
- const number = refScope?.next(token.kind) ?? 0;
615
+ const number = refScope?.numberFor(token.kind, token.content) ?? 0;
575
616
  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 });
576
617
  }
577
618
  default:
@@ -1,10 +1,10 @@
1
1
  "use client";
2
- import { createContext, createElement, useContext, useRef, Component, useState, useEffect, useMemo, useCallback, useId } from 'react';
2
+ import { createContext, createElement, useContext, useMemo, useRef, Component, useState, useEffect, useCallback, useId } from 'react';
3
3
  import { clsx } from 'clsx';
4
4
  import { twMerge } from 'tailwind-merge';
5
5
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
+ import { serializeInlineContent, isTypedNestedList, parseNcm } from '@nuucognition/ncm';
6
7
  import { extractExtension, embedTypeFromExtension } from '@nuucognition/mesh-core';
7
- import { serializeInlineContent, isTypedNestedList } from '@nuucognition/ncm';
8
8
 
9
9
  // src/components/block-shell.tsx
10
10
  function cn(...inputs) {
@@ -121,6 +121,52 @@ function tryParseInlineRef(input) {
121
121
  }
122
122
  return { token: { type: "inline_ref", kind: "footnote", content: inner.trim() }, length };
123
123
  }
124
+ function runLength(input, index, char) {
125
+ let end = index;
126
+ while (end < input.length && input[end] === char) end++;
127
+ return end - index;
128
+ }
129
+ function tryParseEmphasis(input) {
130
+ const char = input[0];
131
+ if (char !== "*" && char !== "_") return null;
132
+ const open = Math.min(3, runLength(input, 0, char));
133
+ const need = open;
134
+ let i = open;
135
+ while (i < input.length) {
136
+ const ch = input[i];
137
+ if (ch === "`") {
138
+ const close = input.indexOf("`", i + 1);
139
+ if (close === -1) break;
140
+ i = close + 1;
141
+ continue;
142
+ }
143
+ if (ch !== char) {
144
+ i++;
145
+ continue;
146
+ }
147
+ const run = runLength(input, i, char);
148
+ const closes = need === 1 ? run % 2 === 1 : run >= need;
149
+ if (!closes) {
150
+ i += run;
151
+ continue;
152
+ }
153
+ const extra = run - need;
154
+ const inner = input.slice(open, i + extra);
155
+ if (inner.length === 0) return null;
156
+ const length = i + run;
157
+ const children = parseInline(inner);
158
+ let token;
159
+ if (need === 3) {
160
+ token = { type: "bold", children: [{ type: "italic", children }] };
161
+ } else if (need === 2) {
162
+ token = { type: "bold", children };
163
+ } else {
164
+ token = { type: "italic", children };
165
+ }
166
+ return { token, length };
167
+ }
168
+ return null;
169
+ }
124
170
  function parseInline(content) {
125
171
  if (!content) return [];
126
172
  const tokens = [];
@@ -192,17 +238,11 @@ function parseInline(content) {
192
238
  remaining = remaining.slice(linkMatch[0].length);
193
239
  continue;
194
240
  }
195
- const boldMatch = remaining.match(/^\*\*(.+?)\*\*|^__(.+?)__/);
196
- if (boldMatch) {
197
- const innerContent = boldMatch[1] ?? boldMatch[2];
198
- if (innerContent !== void 0) {
199
- tokens.push({
200
- type: "bold",
201
- children: parseInline(innerContent)
202
- });
203
- remaining = remaining.slice(boldMatch[0].length);
204
- continue;
205
- }
241
+ const emphasis = tryParseEmphasis(remaining);
242
+ if (emphasis) {
243
+ tokens.push(emphasis.token);
244
+ remaining = remaining.slice(emphasis.length);
245
+ continue;
206
246
  }
207
247
  const strikeMatch = remaining.match(/^~~(.+?)~~/);
208
248
  if (strikeMatch && strikeMatch[1] !== void 0) {
@@ -213,18 +253,6 @@ function parseInline(content) {
213
253
  remaining = remaining.slice(strikeMatch[0].length);
214
254
  continue;
215
255
  }
216
- const italicMatch = remaining.match(/^\*([^*]+)\*|^_([^_]+)_/);
217
- if (italicMatch) {
218
- const innerContent = italicMatch[1] ?? italicMatch[2];
219
- if (innerContent !== void 0) {
220
- tokens.push({
221
- type: "italic",
222
- children: parseInline(innerContent)
223
- });
224
- remaining = remaining.slice(italicMatch[0].length);
225
- continue;
226
- }
227
- }
228
256
  const nextSpecial = findNextSpecialChar(remaining);
229
257
  if (nextSpecial > 0) {
230
258
  tokens.push({ type: "text", content: remaining.slice(0, nextSpecial) });
@@ -335,17 +363,30 @@ function ReferenceMarker({ kind, number, children }) {
335
363
  }
336
364
  );
337
365
  }
338
- var ReferenceBasesContext = createContext(null);
366
+ function normalizeReferenceContent(content) {
367
+ return content.replace(/\s+/g, " ").trim().toLowerCase();
368
+ }
369
+ var ReferenceNumberingContext = createContext(null);
339
370
  var BlockReferenceScopeContext = createContext(null);
340
- function BlockReferenceScope({ blockId, children }) {
341
- const bases = useContext(ReferenceBasesContext);
342
- const base = (blockId ? bases?.get(blockId) : void 0) ?? { ref: 0, footnote: 0 };
371
+ function BlockReferenceScope({ children }) {
372
+ const numbering = useContext(ReferenceNumberingContext);
373
+ const local = useRef({ ref: /* @__PURE__ */ new Map(), footnote: /* @__PURE__ */ new Map() });
343
374
  const counter = useRef({ ref: 0, footnote: 0 });
344
- counter.current = { ref: 0, footnote: 0 };
345
375
  const value = {
376
+ numberFor(kind, content) {
377
+ const key = normalizeReferenceContent(content);
378
+ const fromDocument = numbering?.[kind].get(key);
379
+ if (fromDocument !== void 0) return fromDocument;
380
+ const map = local.current[kind];
381
+ const existing = map.get(key);
382
+ if (existing !== void 0) return existing;
383
+ counter.current[kind] += 1;
384
+ map.set(key, counter.current[kind]);
385
+ return counter.current[kind];
386
+ },
346
387
  next(kind) {
347
388
  counter.current[kind] += 1;
348
- return base[kind] + counter.current[kind];
389
+ return counter.current[kind];
349
390
  }
350
391
  };
351
392
  return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value, children });
@@ -353,7 +394,7 @@ function BlockReferenceScope({ blockId, children }) {
353
394
  function useBlockReferenceScope() {
354
395
  return useContext(BlockReferenceScopeContext);
355
396
  }
356
- var INERT_SCOPE = { next: () => 0 };
397
+ var INERT_SCOPE = { numberFor: () => 0, next: () => 0 };
357
398
  function InertReferenceScope({ children }) {
358
399
  return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value: INERT_SCOPE, children });
359
400
  }
@@ -644,7 +685,7 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
644
685
  );
645
686
  }
646
687
  case "inline_ref": {
647
- const number = refScope?.next(token.kind) ?? 0;
688
+ const number = refScope?.numberFor(token.kind, token.content) ?? 0;
648
689
  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 });
649
690
  }
650
691
  default:
@@ -710,8 +751,32 @@ function renderReadingText(content, opts) {
710
751
  if (cursor < content.length) pieces.push(content.slice(cursor));
711
752
  return /* @__PURE__ */ jsx(Fragment, { children: pieces });
712
753
  }
754
+ function quoteBlocks(block) {
755
+ try {
756
+ const doc = parseNcm(block.content, {
757
+ preset: "ncm-full",
758
+ allowMissingFrontmatter: true,
759
+ // Attribution off, as the NUU Editor's bridge keeps it: the promoter's
760
+ // trigger is any last quote line starting with `-`, so a nested quote
761
+ // ending in a list item would lose that item to a `— Author` line.
762
+ blockOptions: { extensions: { attribution: false } }
763
+ });
764
+ const blocks = doc.blocks ?? [];
765
+ if (blocks.length === 0 || blocks.some((child) => child.type === "frontmatter")) {
766
+ return null;
767
+ }
768
+ return blocks.map((child, index) => ({ ...child, id: `${block.id}.${index + 1}`, stableId: void 0 }));
769
+ } catch {
770
+ return null;
771
+ }
772
+ }
773
+ function QuotedLines({ content }) {
774
+ const lines = content.split("\n");
775
+ return /* @__PURE__ */ jsx(Fragment, { children: 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)) });
776
+ }
713
777
  function BlockquoteBlock({ block, className }) {
714
- const lines = block.content.split("\n");
778
+ const multiline = block.content.includes("\n");
779
+ const blocks = useMemo(() => multiline ? quoteBlocks(block) : null, [block, multiline]);
715
780
  return /* @__PURE__ */ jsx(
716
781
  "blockquote",
717
782
  {
@@ -721,7 +786,9 @@ function BlockquoteBlock({ block, className }) {
721
786
  "data-block-id": block.id,
722
787
  "data-ncm-blockquote": "",
723
788
  className,
724
- 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))
789
+ children: !multiline ? /* @__PURE__ */ jsx(InlineContent, { content: block.content }) : blocks === null ? /* @__PURE__ */ jsx(QuotedLines, { content: block.content }) : blocks.map(
790
+ (child) => child.type === "paragraph" ? /* @__PURE__ */ jsx(QuotedLines, { content: child.content ?? "" }, blockKey(child)) : /* @__PURE__ */ jsx(NcmBlock, { block: child }, blockKey(child))
791
+ )
725
792
  }
726
793
  );
727
794
  }
@@ -736,7 +803,8 @@ function ChartBlock({ block, className }) {
736
803
  "data-ncm-chart": "",
737
804
  "data-ncm-chart-type": block.chartType ?? "unknown",
738
805
  className: cn(
739
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
806
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose — see the note in `lib/defaults.ts`.
807
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
740
808
  className
741
809
  ),
742
810
  children: /* @__PURE__ */ jsx("code", { children: block.content })
@@ -916,7 +984,8 @@ function DataviewBlock({ block, className }) {
916
984
  "data-ncm-dataview": "",
917
985
  "data-ncm-query-type": block.queryType,
918
986
  className: cn(
919
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
987
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose — see the note in `lib/defaults.ts`.
988
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
920
989
  className
921
990
  ),
922
991
  children: /* @__PURE__ */ jsx("code", { children: block.query })
@@ -1236,7 +1305,8 @@ function HtmlBlock({ block, className }) {
1236
1305
  "data-block-id": block.id,
1237
1306
  "data-ncm-html": "",
1238
1307
  className: cn(
1239
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1308
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose — see the note in `lib/defaults.ts`.
1309
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1240
1310
  className
1241
1311
  ),
1242
1312
  children: /* @__PURE__ */ jsx("code", { children: block.content })
@@ -1274,7 +1344,7 @@ function LatexDisplayBlock({ block, className }) {
1274
1344
  "data-ncm-type": block.type,
1275
1345
  "data-block-id": block.id,
1276
1346
  "data-ncm-latex-display": "",
1277
- className: cn("overflow-x-auto", className),
1347
+ className: cn("overflow-x-auto overflow-y-hidden", className),
1278
1348
  dangerouslySetInnerHTML: { __html: html }
1279
1349
  }
1280
1350
  );
@@ -1289,7 +1359,7 @@ function LatexDisplayBlock({ block, className }) {
1289
1359
  "data-ncm-type": block.type,
1290
1360
  "data-block-id": block.id,
1291
1361
  "data-ncm-latex-display": "",
1292
- className: cn("overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm", className),
1362
+ className: cn("overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm", className),
1293
1363
  children: /* @__PURE__ */ jsx("code", { children: block.content })
1294
1364
  }
1295
1365
  );
@@ -1409,7 +1479,7 @@ function MathBlock({ block, className }) {
1409
1479
  "data-ncm-type": block.type,
1410
1480
  "data-block-id": block.id,
1411
1481
  "data-ncm-math": "",
1412
- className: cn("overflow-x-auto", className),
1482
+ className: cn("overflow-x-auto overflow-y-hidden", className),
1413
1483
  dangerouslySetInnerHTML: { __html: html }
1414
1484
  }
1415
1485
  );
@@ -1425,7 +1495,8 @@ function MathBlock({ block, className }) {
1425
1495
  "data-block-id": block.id,
1426
1496
  "data-ncm-math": "",
1427
1497
  className: cn(
1428
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1498
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose — see the note in `lib/defaults.ts`.
1499
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1429
1500
  className
1430
1501
  ),
1431
1502
  children: /* @__PURE__ */ jsx("code", { children: block.content })
@@ -1443,7 +1514,8 @@ function MermaidBlock({ block, className }) {
1443
1514
  "data-ncm-mermaid": "",
1444
1515
  "data-ncm-diagram-type": block.diagramType,
1445
1516
  className: cn(
1446
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1517
+ // `overflow-y-hidden` pairs with `overflow-x-auto` on purpose — see the note in `lib/defaults.ts`.
1518
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1447
1519
  className
1448
1520
  ),
1449
1521
  children: /* @__PURE__ */ jsx("code", { children: block.content })
@@ -1504,7 +1576,7 @@ function TableBlock({ block, className }) {
1504
1576
  "data-ncm-type": block.type,
1505
1577
  "data-block-id": block.id,
1506
1578
  "data-ncm-table": "",
1507
- className: cn("w-full overflow-x-auto", className),
1579
+ className: cn("w-full overflow-x-auto overflow-y-hidden", className),
1508
1580
  children: /* @__PURE__ */ jsxs("table", { role: "table", "data-ncm-table-element": "", children: [
1509
1581
  /* @__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)) }) }),
1510
1582
  /* @__PURE__ */ jsx("tbody", { children: block.rows.map((row, rowIndex) => {
@@ -1590,7 +1662,7 @@ function FallbackBlock({ block, className }) {
1590
1662
  "data-block-id": block.id,
1591
1663
  "data-ncm-fallback": "",
1592
1664
  className: cn(
1593
- "overflow-x-auto rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1665
+ "overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-muted p-4 font-mono text-sm",
1594
1666
  className
1595
1667
  )
1596
1668
  },
@@ -1646,7 +1718,7 @@ function CustomCodeBlock({ block, className }) {
1646
1718
  "data-block-id": block.id,
1647
1719
  "data-ncm-custom-code": "",
1648
1720
  "data-ncm-language": block.language,
1649
- className: cn("overflow-x-auto", className),
1721
+ className: cn("overflow-x-auto overflow-y-hidden", className),
1650
1722
  children: [
1651
1723
  /* @__PURE__ */ jsx("div", { className: "mb-2 text-xs font-medium text-muted-foreground", children: block.language }),
1652
1724
  /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: block.content }) })
@@ -46,6 +46,52 @@ function tryParseInlineRef(input) {
46
46
  }
47
47
  return { token: { type: "inline_ref", kind: "footnote", content: inner.trim() }, length };
48
48
  }
49
+ function runLength(input, index, char) {
50
+ let end = index;
51
+ while (end < input.length && input[end] === char) end++;
52
+ return end - index;
53
+ }
54
+ function tryParseEmphasis(input) {
55
+ const char = input[0];
56
+ if (char !== "*" && char !== "_") return null;
57
+ const open = Math.min(3, runLength(input, 0, char));
58
+ const need = open;
59
+ let i = open;
60
+ while (i < input.length) {
61
+ const ch = input[i];
62
+ if (ch === "`") {
63
+ const close = input.indexOf("`", i + 1);
64
+ if (close === -1) break;
65
+ i = close + 1;
66
+ continue;
67
+ }
68
+ if (ch !== char) {
69
+ i++;
70
+ continue;
71
+ }
72
+ const run = runLength(input, i, char);
73
+ const closes = need === 1 ? run % 2 === 1 : run >= need;
74
+ if (!closes) {
75
+ i += run;
76
+ continue;
77
+ }
78
+ const extra = run - need;
79
+ const inner = input.slice(open, i + extra);
80
+ if (inner.length === 0) return null;
81
+ const length = i + run;
82
+ const children = parseInline(inner);
83
+ let token;
84
+ if (need === 3) {
85
+ token = { type: "bold", children: [{ type: "italic", children }] };
86
+ } else if (need === 2) {
87
+ token = { type: "bold", children };
88
+ } else {
89
+ token = { type: "italic", children };
90
+ }
91
+ return { token, length };
92
+ }
93
+ return null;
94
+ }
49
95
  function parseInline(content) {
50
96
  if (!content) return [];
51
97
  const tokens = [];
@@ -117,17 +163,11 @@ function parseInline(content) {
117
163
  remaining = remaining.slice(linkMatch[0].length);
118
164
  continue;
119
165
  }
120
- const boldMatch = remaining.match(/^\*\*(.+?)\*\*|^__(.+?)__/);
121
- if (boldMatch) {
122
- const innerContent = boldMatch[1] ?? boldMatch[2];
123
- if (innerContent !== void 0) {
124
- tokens.push({
125
- type: "bold",
126
- children: parseInline(innerContent)
127
- });
128
- remaining = remaining.slice(boldMatch[0].length);
129
- continue;
130
- }
166
+ const emphasis = tryParseEmphasis(remaining);
167
+ if (emphasis) {
168
+ tokens.push(emphasis.token);
169
+ remaining = remaining.slice(emphasis.length);
170
+ continue;
131
171
  }
132
172
  const strikeMatch = remaining.match(/^~~(.+?)~~/);
133
173
  if (strikeMatch && strikeMatch[1] !== void 0) {
@@ -138,18 +178,6 @@ function parseInline(content) {
138
178
  remaining = remaining.slice(strikeMatch[0].length);
139
179
  continue;
140
180
  }
141
- const italicMatch = remaining.match(/^\*([^*]+)\*|^_([^_]+)_/);
142
- if (italicMatch) {
143
- const innerContent = italicMatch[1] ?? italicMatch[2];
144
- if (innerContent !== void 0) {
145
- tokens.push({
146
- type: "italic",
147
- children: parseInline(innerContent)
148
- });
149
- remaining = remaining.slice(italicMatch[0].length);
150
- continue;
151
- }
152
- }
153
181
  const nextSpecial = findNextSpecialChar(remaining);
154
182
  if (nextSpecial > 0) {
155
183
  tokens.push({ type: "text", content: remaining.slice(0, nextSpecial) });
@@ -260,17 +288,30 @@ function ReferenceMarker({ kind, number, children }) {
260
288
  }
261
289
  );
262
290
  }
263
- var ReferenceBasesContext = createContext(null);
291
+ function normalizeReferenceContent(content) {
292
+ return content.replace(/\s+/g, " ").trim().toLowerCase();
293
+ }
294
+ var ReferenceNumberingContext = createContext(null);
264
295
  var BlockReferenceScopeContext = createContext(null);
265
- function BlockReferenceScope({ blockId, children }) {
266
- const bases = useContext(ReferenceBasesContext);
267
- const base = (blockId ? bases?.get(blockId) : void 0) ?? { ref: 0, footnote: 0 };
296
+ function BlockReferenceScope({ children }) {
297
+ const numbering = useContext(ReferenceNumberingContext);
298
+ const local = useRef({ ref: /* @__PURE__ */ new Map(), footnote: /* @__PURE__ */ new Map() });
268
299
  const counter = useRef({ ref: 0, footnote: 0 });
269
- counter.current = { ref: 0, footnote: 0 };
270
300
  const value = {
301
+ numberFor(kind, content) {
302
+ const key = normalizeReferenceContent(content);
303
+ const fromDocument = numbering?.[kind].get(key);
304
+ if (fromDocument !== void 0) return fromDocument;
305
+ const map = local.current[kind];
306
+ const existing = map.get(key);
307
+ if (existing !== void 0) return existing;
308
+ counter.current[kind] += 1;
309
+ map.set(key, counter.current[kind]);
310
+ return counter.current[kind];
311
+ },
271
312
  next(kind) {
272
313
  counter.current[kind] += 1;
273
- return base[kind] + counter.current[kind];
314
+ return counter.current[kind];
274
315
  }
275
316
  };
276
317
  return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value, children });
@@ -278,7 +319,7 @@ function BlockReferenceScope({ blockId, children }) {
278
319
  function useBlockReferenceScope() {
279
320
  return useContext(BlockReferenceScopeContext);
280
321
  }
281
- var INERT_SCOPE = { next: () => 0 };
322
+ var INERT_SCOPE = { numberFor: () => 0, next: () => 0 };
282
323
  function InertReferenceScope({ children }) {
283
324
  return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value: INERT_SCOPE, children });
284
325
  }
@@ -569,7 +610,7 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
569
610
  );
570
611
  }
571
612
  case "inline_ref": {
572
- const number = refScope?.next(token.kind) ?? 0;
613
+ const number = refScope?.numberFor(token.kind, token.content) ?? 0;
573
614
  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 });
574
615
  }
575
616
  default:
@@ -18,7 +18,8 @@ function HtmlBlock({ block, className }) {
18
18
  "data-block-id": block.id,
19
19
  "data-ncm-html": "",
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 })