@nuucognition/ncm-ui 0.1.1-beta.1 → 0.1.1-beta.3
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.
- package/dist/blocks/admonition/index.js +160 -36
- package/dist/blocks/aside/index.js +160 -36
- package/dist/blocks/blockquote/index.d.ts +7 -5
- package/dist/blocks/blockquote/index.js +1275 -36
- package/dist/blocks/container/index.js +72 -31
- package/dist/blocks/definition/index.js +159 -35
- package/dist/blocks/embed/index.js +46 -1
- package/dist/blocks/embedding/index.js +72 -31
- package/dist/blocks/figure/index.d.ts +3 -1
- package/dist/blocks/figure/index.js +128 -33
- package/dist/blocks/footnote/index.js +160 -36
- package/dist/blocks/header/index.js +72 -31
- package/dist/blocks/index.js +160 -36
- package/dist/blocks/list/index.js +72 -31
- package/dist/blocks/paragraph/index.js +72 -31
- package/dist/blocks/spoiler/index.js +160 -36
- package/dist/blocks/table/index.js +72 -31
- package/dist/blocks/task-list/index.js +72 -31
- package/dist/components/index.js +199 -55
- package/dist/components/ncm-block.js +160 -36
- package/dist/components/ncm-document.js +199 -55
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.js +119 -44
- package/dist/hooks/index.js +160 -36
- package/dist/hooks/use-block-renderer.js +160 -36
- package/dist/index.d.ts +1 -1
- package/dist/index.js +206 -48
- package/dist/inline/index.d.ts +2 -3
- package/dist/inline/index.js +72 -31
- package/dist/lib/defaults.js +160 -36
- package/dist/references-BM-lvGrq.d.ts +99 -0
- package/package.json +1 -1
- package/dist/references-BYW5pnj_.d.ts +0 -63
package/dist/lib/defaults.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { createContext, useState, createElement,
|
|
2
|
+
import { createContext, useMemo, useState, createElement, useContext, useCallback, useEffect, useRef, Component, 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 } from '@nuucognition/ncm';
|
|
6
|
+
import { serializeInlineContent, isTypedNestedList, parseNcm } from '@nuucognition/ncm';
|
|
7
7
|
import { extractExtension, embedTypeFromExtension } from '@nuucognition/mesh-core';
|
|
8
8
|
|
|
9
9
|
// src/lib/defaults.ts
|
|
@@ -71,6 +71,52 @@ function tryParseInlineRef(input) {
|
|
|
71
71
|
}
|
|
72
72
|
return { token: { type: "inline_ref", kind: "footnote", content: inner.trim() }, length };
|
|
73
73
|
}
|
|
74
|
+
function runLength(input, index, char) {
|
|
75
|
+
let end = index;
|
|
76
|
+
while (end < input.length && input[end] === char) end++;
|
|
77
|
+
return end - index;
|
|
78
|
+
}
|
|
79
|
+
function tryParseEmphasis(input) {
|
|
80
|
+
const char = input[0];
|
|
81
|
+
if (char !== "*" && char !== "_") return null;
|
|
82
|
+
const open = Math.min(3, runLength(input, 0, char));
|
|
83
|
+
const need = open;
|
|
84
|
+
let i = open;
|
|
85
|
+
while (i < input.length) {
|
|
86
|
+
const ch = input[i];
|
|
87
|
+
if (ch === "`") {
|
|
88
|
+
const close = input.indexOf("`", i + 1);
|
|
89
|
+
if (close === -1) break;
|
|
90
|
+
i = close + 1;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (ch !== char) {
|
|
94
|
+
i++;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const run = runLength(input, i, char);
|
|
98
|
+
const closes = need === 1 ? run % 2 === 1 : run >= need;
|
|
99
|
+
if (!closes) {
|
|
100
|
+
i += run;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const extra = run - need;
|
|
104
|
+
const inner = input.slice(open, i + extra);
|
|
105
|
+
if (inner.length === 0) return null;
|
|
106
|
+
const length = i + run;
|
|
107
|
+
const children = parseInline(inner);
|
|
108
|
+
let token;
|
|
109
|
+
if (need === 3) {
|
|
110
|
+
token = { type: "bold", children: [{ type: "italic", children }] };
|
|
111
|
+
} else if (need === 2) {
|
|
112
|
+
token = { type: "bold", children };
|
|
113
|
+
} else {
|
|
114
|
+
token = { type: "italic", children };
|
|
115
|
+
}
|
|
116
|
+
return { token, length };
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
74
120
|
function parseInline(content) {
|
|
75
121
|
if (!content) return [];
|
|
76
122
|
const tokens = [];
|
|
@@ -142,17 +188,11 @@ function parseInline(content) {
|
|
|
142
188
|
remaining = remaining.slice(linkMatch[0].length);
|
|
143
189
|
continue;
|
|
144
190
|
}
|
|
145
|
-
const
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
type: "bold",
|
|
151
|
-
children: parseInline(innerContent)
|
|
152
|
-
});
|
|
153
|
-
remaining = remaining.slice(boldMatch[0].length);
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
191
|
+
const emphasis = tryParseEmphasis(remaining);
|
|
192
|
+
if (emphasis) {
|
|
193
|
+
tokens.push(emphasis.token);
|
|
194
|
+
remaining = remaining.slice(emphasis.length);
|
|
195
|
+
continue;
|
|
156
196
|
}
|
|
157
197
|
const strikeMatch = remaining.match(/^~~(.+?)~~/);
|
|
158
198
|
if (strikeMatch && strikeMatch[1] !== void 0) {
|
|
@@ -163,18 +203,6 @@ function parseInline(content) {
|
|
|
163
203
|
remaining = remaining.slice(strikeMatch[0].length);
|
|
164
204
|
continue;
|
|
165
205
|
}
|
|
166
|
-
const italicMatch = remaining.match(/^\*([^*]+)\*|^_([^_]+)_/);
|
|
167
|
-
if (italicMatch) {
|
|
168
|
-
const innerContent = italicMatch[1] ?? italicMatch[2];
|
|
169
|
-
if (innerContent !== void 0) {
|
|
170
|
-
tokens.push({
|
|
171
|
-
type: "italic",
|
|
172
|
-
children: parseInline(innerContent)
|
|
173
|
-
});
|
|
174
|
-
remaining = remaining.slice(italicMatch[0].length);
|
|
175
|
-
continue;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
206
|
const nextSpecial = findNextSpecialChar(remaining);
|
|
179
207
|
if (nextSpecial > 0) {
|
|
180
208
|
tokens.push({ type: "text", content: remaining.slice(0, nextSpecial) });
|
|
@@ -209,17 +237,30 @@ function mergeAdjacentText(tokens) {
|
|
|
209
237
|
}
|
|
210
238
|
return result;
|
|
211
239
|
}
|
|
212
|
-
|
|
240
|
+
function normalizeReferenceContent(content) {
|
|
241
|
+
return content.replace(/\s+/g, " ").trim().toLowerCase();
|
|
242
|
+
}
|
|
243
|
+
var ReferenceNumberingContext = createContext(null);
|
|
213
244
|
var BlockReferenceScopeContext = createContext(null);
|
|
214
|
-
function BlockReferenceScope({
|
|
215
|
-
const
|
|
216
|
-
const
|
|
245
|
+
function BlockReferenceScope({ children }) {
|
|
246
|
+
const numbering = useContext(ReferenceNumberingContext);
|
|
247
|
+
const local = useRef({ ref: /* @__PURE__ */ new Map(), footnote: /* @__PURE__ */ new Map() });
|
|
217
248
|
const counter = useRef({ ref: 0, footnote: 0 });
|
|
218
|
-
counter.current = { ref: 0, footnote: 0 };
|
|
219
249
|
const value = {
|
|
250
|
+
numberFor(kind, content) {
|
|
251
|
+
const key = normalizeReferenceContent(content);
|
|
252
|
+
const fromDocument = numbering?.[kind].get(key);
|
|
253
|
+
if (fromDocument !== void 0) return fromDocument;
|
|
254
|
+
const map = local.current[kind];
|
|
255
|
+
const existing = map.get(key);
|
|
256
|
+
if (existing !== void 0) return existing;
|
|
257
|
+
counter.current[kind] += 1;
|
|
258
|
+
map.set(key, counter.current[kind]);
|
|
259
|
+
return counter.current[kind];
|
|
260
|
+
},
|
|
220
261
|
next(kind) {
|
|
221
262
|
counter.current[kind] += 1;
|
|
222
|
-
return
|
|
263
|
+
return counter.current[kind];
|
|
223
264
|
}
|
|
224
265
|
};
|
|
225
266
|
return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value, children });
|
|
@@ -227,7 +268,7 @@ function BlockReferenceScope({ blockId, children }) {
|
|
|
227
268
|
function useBlockReferenceScope() {
|
|
228
269
|
return useContext(BlockReferenceScopeContext);
|
|
229
270
|
}
|
|
230
|
-
var INERT_SCOPE = { next: () => 0 };
|
|
271
|
+
var INERT_SCOPE = { numberFor: () => 0, next: () => 0 };
|
|
231
272
|
function InertReferenceScope({ children }) {
|
|
232
273
|
return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value: INERT_SCOPE, children });
|
|
233
274
|
}
|
|
@@ -751,7 +792,7 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
|
|
|
751
792
|
);
|
|
752
793
|
}
|
|
753
794
|
case "inline_ref": {
|
|
754
|
-
const number = refScope?.
|
|
795
|
+
const number = refScope?.numberFor(token.kind, token.content) ?? 0;
|
|
755
796
|
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 });
|
|
756
797
|
}
|
|
757
798
|
default:
|
|
@@ -817,8 +858,32 @@ function renderReadingText(content, opts) {
|
|
|
817
858
|
if (cursor < content.length) pieces.push(content.slice(cursor));
|
|
818
859
|
return /* @__PURE__ */ jsx(Fragment, { children: pieces });
|
|
819
860
|
}
|
|
861
|
+
function quoteBlocks(block) {
|
|
862
|
+
try {
|
|
863
|
+
const doc = parseNcm(block.content, {
|
|
864
|
+
preset: "ncm-full",
|
|
865
|
+
allowMissingFrontmatter: true,
|
|
866
|
+
// Attribution off, as the NUU Editor's bridge keeps it: the promoter's
|
|
867
|
+
// trigger is any last quote line starting with `-`, so a nested quote
|
|
868
|
+
// ending in a list item would lose that item to a `— Author` line.
|
|
869
|
+
blockOptions: { extensions: { attribution: false } }
|
|
870
|
+
});
|
|
871
|
+
const blocks = doc.blocks ?? [];
|
|
872
|
+
if (blocks.length === 0 || blocks.some((child) => child.type === "frontmatter")) {
|
|
873
|
+
return null;
|
|
874
|
+
}
|
|
875
|
+
return blocks.map((child, index) => ({ ...child, id: `${block.id}.${index + 1}`, stableId: void 0 }));
|
|
876
|
+
} catch {
|
|
877
|
+
return null;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
function QuotedLines({ content }) {
|
|
881
|
+
const lines = content.split("\n");
|
|
882
|
+
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)) });
|
|
883
|
+
}
|
|
820
884
|
function BlockquoteBlock({ block, className }) {
|
|
821
|
-
const
|
|
885
|
+
const multiline = block.content.includes("\n");
|
|
886
|
+
const blocks = useMemo(() => multiline ? quoteBlocks(block) : null, [block, multiline]);
|
|
822
887
|
return /* @__PURE__ */ jsx(
|
|
823
888
|
"blockquote",
|
|
824
889
|
{
|
|
@@ -828,7 +893,9 @@ function BlockquoteBlock({ block, className }) {
|
|
|
828
893
|
"data-block-id": block.id,
|
|
829
894
|
"data-ncm-blockquote": "",
|
|
830
895
|
className,
|
|
831
|
-
children:
|
|
896
|
+
children: !multiline ? /* @__PURE__ */ jsx(InlineContent, { content: block.content }) : blocks === null ? /* @__PURE__ */ jsx(QuotedLines, { content: block.content }) : blocks.map(
|
|
897
|
+
(child) => child.type === "paragraph" ? /* @__PURE__ */ jsx(QuotedLines, { content: child.content ?? "" }, blockKey(child)) : /* @__PURE__ */ jsx(NcmBlock, { block: child }, blockKey(child))
|
|
898
|
+
)
|
|
832
899
|
}
|
|
833
900
|
);
|
|
834
901
|
}
|
|
@@ -1047,6 +1114,48 @@ function DefinitionBlock({ block, className }) {
|
|
|
1047
1114
|
}
|
|
1048
1115
|
);
|
|
1049
1116
|
}
|
|
1117
|
+
function fileNameOf(src) {
|
|
1118
|
+
let path = src.split(/[?#]/)[0] ?? "";
|
|
1119
|
+
if (/^https?:\/\//i.test(src)) {
|
|
1120
|
+
try {
|
|
1121
|
+
path = new URL(src).pathname;
|
|
1122
|
+
} catch {
|
|
1123
|
+
return "";
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
return path.slice(path.lastIndexOf("/") + 1);
|
|
1127
|
+
}
|
|
1128
|
+
function isExtensionless(src) {
|
|
1129
|
+
const name = fileNameOf(src);
|
|
1130
|
+
const dot = name.lastIndexOf(".");
|
|
1131
|
+
return dot <= 0 || dot === name.length - 1;
|
|
1132
|
+
}
|
|
1133
|
+
function EmbedPictureOrLink({
|
|
1134
|
+
src,
|
|
1135
|
+
alt,
|
|
1136
|
+
title,
|
|
1137
|
+
imgClassName,
|
|
1138
|
+
linkAttrs
|
|
1139
|
+
}) {
|
|
1140
|
+
const [failedSrc, setFailedSrc] = useState(null);
|
|
1141
|
+
useEffect(() => {
|
|
1142
|
+
setFailedSrc(null);
|
|
1143
|
+
}, [src]);
|
|
1144
|
+
if (failedSrc === src) {
|
|
1145
|
+
return /* @__PURE__ */ jsx("a", { href: src, title, ...linkAttrs, children: alt || src });
|
|
1146
|
+
}
|
|
1147
|
+
return /* @__PURE__ */ jsx(
|
|
1148
|
+
"img",
|
|
1149
|
+
{
|
|
1150
|
+
"data-ncm-embed-picture": "",
|
|
1151
|
+
src,
|
|
1152
|
+
alt,
|
|
1153
|
+
title,
|
|
1154
|
+
className: imgClassName,
|
|
1155
|
+
onError: () => setFailedSrc(src)
|
|
1156
|
+
}
|
|
1157
|
+
);
|
|
1158
|
+
}
|
|
1050
1159
|
function toEmbeddingConfigType(embedType) {
|
|
1051
1160
|
switch (embedType) {
|
|
1052
1161
|
case "image":
|
|
@@ -1075,6 +1184,9 @@ function EmbedBlock({ block, className }) {
|
|
|
1075
1184
|
if (block.embedType === "image") {
|
|
1076
1185
|
return /* @__PURE__ */ jsx("figure", { ...dataAttrs(block), className: cn(config.embeddings?.imageClassName, className), children: /* @__PURE__ */ jsx("img", { src: resolvedUrl, alt: block.alt, title: block.title ?? void 0 }) });
|
|
1077
1186
|
}
|
|
1187
|
+
if (block.embedType === "file" && isExtensionless(block.src)) {
|
|
1188
|
+
return /* @__PURE__ */ jsx("figure", { ...dataAttrs(block), className: cn(config.embeddings?.imageClassName, className), children: /* @__PURE__ */ jsx(EmbedPictureOrLink, { src: resolvedUrl, alt: block.alt, title: block.title ?? void 0 }) });
|
|
1189
|
+
}
|
|
1078
1190
|
return /* @__PURE__ */ jsx("figure", { ...dataAttrs(block), className, children: /* @__PURE__ */ jsx("a", { href: resolvedUrl, title: block.title ?? void 0, children: block.alt || block.src }) });
|
|
1079
1191
|
}
|
|
1080
1192
|
var embedFrameStyle = {
|
|
@@ -1251,7 +1363,19 @@ function FigureBlock({ block, className }) {
|
|
|
1251
1363
|
"data-ncm-figure": "",
|
|
1252
1364
|
className: cn("space-y-2", className),
|
|
1253
1365
|
children: [
|
|
1254
|
-
embed.embedType === "image" ? /* @__PURE__ */ jsx("img", { src: embed.src, alt: embed.alt, title: embed.title ?? void 0 }) :
|
|
1366
|
+
embed.embedType === "image" ? /* @__PURE__ */ jsx("img", { src: embed.src, alt: embed.alt, title: embed.title ?? void 0 }) : embed.embedType === "file" && isExtensionless(embed.src) ? (
|
|
1367
|
+
// Same rule as the standalone embed block: an image spelling with an
|
|
1368
|
+
// extension-less destination is a picture until it fails to load.
|
|
1369
|
+
/* @__PURE__ */ jsx(
|
|
1370
|
+
EmbedPictureOrLink,
|
|
1371
|
+
{
|
|
1372
|
+
src: embed.src,
|
|
1373
|
+
alt: embed.alt,
|
|
1374
|
+
title: embed.title ?? void 0,
|
|
1375
|
+
linkAttrs: { "data-ncm-embed-type": embed.embedType }
|
|
1376
|
+
}
|
|
1377
|
+
)
|
|
1378
|
+
) : /* @__PURE__ */ jsx(
|
|
1255
1379
|
"a",
|
|
1256
1380
|
{
|
|
1257
1381
|
href: embed.src,
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { Block } from '@nuucognition/ncm';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Numbering for inline references (`^[ref: ...]` / `^[footnote: ...]`).
|
|
7
|
+
*
|
|
8
|
+
* The two kinds are counted **independently**: refs produce `[1] [2] …` and
|
|
9
|
+
* footnotes produce `¹ ² …`.
|
|
10
|
+
*
|
|
11
|
+
* Numbers are assigned by a pure pre-pass over the `blocks` array and looked up
|
|
12
|
+
* by **token content**, never by render order. That makes the marker number a
|
|
13
|
+
* function of the document alone: it is stable under React re-renders,
|
|
14
|
+
* StrictMode double rendering, virtualised or out-of-order block rendering,
|
|
15
|
+
* and it gives every citation of the same source the same number.
|
|
16
|
+
*
|
|
17
|
+
* Refs additionally honour the document's own bibliography. When a paragraph
|
|
18
|
+
* reads `[16] Google Gemini Team. Gemini: …` and a `^[ref: Google Gemini
|
|
19
|
+
* Team. Gemini: …]` token carries that entry, the marker shows `[16]` — the
|
|
20
|
+
* number the source document uses — so the inline citation, the reference
|
|
21
|
+
* list, and the original paper all agree. Refs with no bibliography match are
|
|
22
|
+
* numbered sequentially in first-appearance order, continuing after the
|
|
23
|
+
* highest bibliography number so the two ranges never collide.
|
|
24
|
+
*
|
|
25
|
+
* Footnotes are numbered sequentially in first-appearance order (identical
|
|
26
|
+
* footnote text shares a number).
|
|
27
|
+
*/
|
|
28
|
+
type ReferenceKind = "ref" | "footnote";
|
|
29
|
+
interface ReferenceCounts {
|
|
30
|
+
ref: number;
|
|
31
|
+
footnote: number;
|
|
32
|
+
}
|
|
33
|
+
/** Document-wide numbering: normalised token content → marker number. */
|
|
34
|
+
interface ReferenceNumbering {
|
|
35
|
+
ref: Map<string, number>;
|
|
36
|
+
footnote: Map<string, number>;
|
|
37
|
+
}
|
|
38
|
+
/** Collapse whitespace and case so a token and its bibliography entry compare equal. */
|
|
39
|
+
declare function normalizeReferenceContent(content: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* Map every `[n] entry` paragraph in the document to its number. The first
|
|
42
|
+
* paragraph carrying a given entry text wins.
|
|
43
|
+
*/
|
|
44
|
+
declare function collectBibliography(blocks: readonly Block[]): Map<string, number>;
|
|
45
|
+
/**
|
|
46
|
+
* Compute the document-wide numbering (see the module comment for the rules).
|
|
47
|
+
*/
|
|
48
|
+
declare function computeReferenceNumbering(blocks: readonly Block[]): ReferenceNumbering;
|
|
49
|
+
/**
|
|
50
|
+
* Per-block count of inline references, as the *previous* numbering scheme
|
|
51
|
+
* exposed it. Kept for API compatibility; the marker numbers no longer derive
|
|
52
|
+
* from these offsets.
|
|
53
|
+
*/
|
|
54
|
+
declare function computeReferenceBases(blocks: readonly Block[]): Map<string, ReferenceCounts>;
|
|
55
|
+
interface BlockReferenceScopeValue {
|
|
56
|
+
/**
|
|
57
|
+
* The marker number for a token with this `kind` and `content`. Pure with
|
|
58
|
+
* respect to the document: the same content always gets the same number.
|
|
59
|
+
*/
|
|
60
|
+
numberFor(kind: ReferenceKind, content: string): number;
|
|
61
|
+
/**
|
|
62
|
+
* Allocate the next number for `kind` in render order. Legacy API — prefer
|
|
63
|
+
* `numberFor`, which is stable under re-renders.
|
|
64
|
+
*/
|
|
65
|
+
next(kind: ReferenceKind): number;
|
|
66
|
+
}
|
|
67
|
+
interface NcmReferencesProviderProps {
|
|
68
|
+
blocks: readonly Block[];
|
|
69
|
+
children: ReactNode;
|
|
70
|
+
}
|
|
71
|
+
/** Document-root provider — runs the numbering pre-pass over `blocks`. */
|
|
72
|
+
declare function NcmReferencesProvider({ blocks, children }: NcmReferencesProviderProps): react.JSX.Element;
|
|
73
|
+
interface BlockReferenceScopeProps {
|
|
74
|
+
/** Block id. Accepted for API compatibility; numbering is document-wide. */
|
|
75
|
+
blockId?: string;
|
|
76
|
+
children: ReactNode;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Reference scope for one block (or one standalone `InlineContent` fragment).
|
|
80
|
+
*
|
|
81
|
+
* Inside an `NcmDocument` it resolves numbers from the document pre-pass.
|
|
82
|
+
* Standalone — no `NcmReferencesProvider` above it — it numbers the fragment's
|
|
83
|
+
* own tokens by content in first-request order, which is still idempotent
|
|
84
|
+
* under StrictMode double rendering because a repeated request for the same
|
|
85
|
+
* content returns the same number.
|
|
86
|
+
*/
|
|
87
|
+
declare function BlockReferenceScope({ children }: BlockReferenceScopeProps): react.JSX.Element;
|
|
88
|
+
/** Read the active per-block reference scope, if any. */
|
|
89
|
+
declare function useBlockReferenceScope(): BlockReferenceScopeValue | null;
|
|
90
|
+
/**
|
|
91
|
+
* Wrap a subtree so any inline references inside it do NOT take document
|
|
92
|
+
* numbers — used for a reference's own popover content, which the numbering
|
|
93
|
+
* pre-pass deliberately does not descend into.
|
|
94
|
+
*/
|
|
95
|
+
declare function InertReferenceScope({ children }: {
|
|
96
|
+
children: ReactNode;
|
|
97
|
+
}): react.JSX.Element;
|
|
98
|
+
|
|
99
|
+
export { BlockReferenceScope as B, InertReferenceScope as I, NcmReferencesProvider as N, type ReferenceCounts as R, type BlockReferenceScopeProps as a, type BlockReferenceScopeValue as b, type NcmReferencesProviderProps as c, type ReferenceKind as d, type ReferenceNumbering as e, collectBibliography as f, computeReferenceBases as g, computeReferenceNumbering as h, normalizeReferenceContent as n, useBlockReferenceScope as u };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuucognition/ncm-ui",
|
|
3
|
-
"version": "0.1.1-beta.
|
|
3
|
+
"version": "0.1.1-beta.3",
|
|
4
4
|
"description": "React renderers for NUU Cognition Markdown (NCM) blocks — a component library that renders parsed NCM Blocks to accessible, themeable markup.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import * as react from 'react';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
-
import { Block } from '@nuucognition/ncm';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Document-order numbering for inline references (`^[ref: ...]` /
|
|
7
|
-
* `^[footnote: ...]`).
|
|
8
|
-
*
|
|
9
|
-
* The two kinds are counted **independently**: refs produce `[1] [2] …` and
|
|
10
|
-
* footnotes produce `¹ ² …`, each with its own running counter across the
|
|
11
|
-
* whole document.
|
|
12
|
-
*
|
|
13
|
-
* Numbering is computed from the `blocks` array — a pure pre-pass that does not
|
|
14
|
-
* depend on React render order — so markers stay stable even if a host
|
|
15
|
-
* virtualises blocks or renders them out of order. The pre-pass yields, per
|
|
16
|
-
* block, the count of each kind in all *preceding* blocks (the "base"); within
|
|
17
|
-
* a block, a `BlockReferenceScope` hands out sequential numbers in render
|
|
18
|
-
* order. Only the within-block step relies on the block's inline content
|
|
19
|
-
* rendering as a synchronous subtree (it always does).
|
|
20
|
-
*/
|
|
21
|
-
type ReferenceKind = "ref" | "footnote";
|
|
22
|
-
interface ReferenceCounts {
|
|
23
|
-
ref: number;
|
|
24
|
-
footnote: number;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Map each block id to the number of refs/footnotes that precede it in
|
|
28
|
-
* document order — the starting offset for that block's own markers.
|
|
29
|
-
*/
|
|
30
|
-
declare function computeReferenceBases(blocks: readonly Block[]): Map<string, ReferenceCounts>;
|
|
31
|
-
interface BlockReferenceScopeValue {
|
|
32
|
-
/** Allocate the next document-order number for `kind` within this block. */
|
|
33
|
-
next(kind: ReferenceKind): number;
|
|
34
|
-
}
|
|
35
|
-
interface NcmReferencesProviderProps {
|
|
36
|
-
blocks: readonly Block[];
|
|
37
|
-
children: ReactNode;
|
|
38
|
-
}
|
|
39
|
-
/** Document-root provider — runs the numbering pre-pass over `blocks`. */
|
|
40
|
-
declare function NcmReferencesProvider({ blocks, children }: NcmReferencesProviderProps): react.JSX.Element;
|
|
41
|
-
interface BlockReferenceScopeProps {
|
|
42
|
-
/** Block id; resolves the base offset from the document pre-pass. */
|
|
43
|
-
blockId?: string;
|
|
44
|
-
children: ReactNode;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Per-block numbering scope. Seeds a fresh counter from the block's base offset
|
|
48
|
-
* on every render and hands out sequential numbers as markers render. Resetting
|
|
49
|
-
* each render keeps numbering idempotent under React re-renders / StrictMode.
|
|
50
|
-
*/
|
|
51
|
-
declare function BlockReferenceScope({ blockId, children }: BlockReferenceScopeProps): react.JSX.Element;
|
|
52
|
-
/** Read the active per-block reference scope, if any. */
|
|
53
|
-
declare function useBlockReferenceScope(): BlockReferenceScopeValue | null;
|
|
54
|
-
/**
|
|
55
|
-
* Wrap a subtree so any inline references inside it do NOT allocate
|
|
56
|
-
* document-order numbers — used for a reference's own popover content, which
|
|
57
|
-
* the numbering pre-pass deliberately does not descend into.
|
|
58
|
-
*/
|
|
59
|
-
declare function InertReferenceScope({ children }: {
|
|
60
|
-
children: ReactNode;
|
|
61
|
-
}): react.JSX.Element;
|
|
62
|
-
|
|
63
|
-
export { BlockReferenceScope as B, InertReferenceScope as I, NcmReferencesProvider as N, type ReferenceCounts as R, type BlockReferenceScopeProps as a, type BlockReferenceScopeValue as b, type NcmReferencesProviderProps as c, type ReferenceKind as d, computeReferenceBases as e, useBlockReferenceScope as u };
|