@nuucognition/ncm-ui 0.1.1-beta.1 → 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.
- package/dist/blocks/admonition/index.js +102 -35
- package/dist/blocks/aside/index.js +102 -35
- package/dist/blocks/blockquote/index.d.ts +7 -5
- package/dist/blocks/blockquote/index.js +1218 -36
- package/dist/blocks/container/index.js +72 -31
- package/dist/blocks/definition/index.js +101 -34
- package/dist/blocks/embedding/index.js +72 -31
- package/dist/blocks/figure/index.js +72 -31
- package/dist/blocks/footnote/index.js +102 -35
- package/dist/blocks/header/index.js +72 -31
- package/dist/blocks/index.js +102 -35
- package/dist/blocks/list/index.js +72 -31
- package/dist/blocks/paragraph/index.js +72 -31
- package/dist/blocks/spoiler/index.js +102 -35
- package/dist/blocks/table/index.js +72 -31
- package/dist/blocks/task-list/index.js +72 -31
- package/dist/components/index.js +141 -54
- package/dist/components/ncm-block.js +102 -35
- package/dist/components/ncm-document.js +141 -54
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.js +119 -44
- package/dist/hooks/index.js +102 -35
- package/dist/hooks/use-block-renderer.js +102 -35
- package/dist/index.d.ts +1 -1
- package/dist/index.js +148 -47
- package/dist/inline/index.d.ts +2 -3
- package/dist/inline/index.js +72 -31
- package/dist/lib/defaults.js +102 -35
- package/dist/references-BM-lvGrq.d.ts +99 -0
- package/package.json +3 -3
- package/dist/references-BYW5pnj_.d.ts +0 -63
package/dist/index.js
CHANGED
|
@@ -56,6 +56,52 @@ function tryParseInlineRef(input) {
|
|
|
56
56
|
}
|
|
57
57
|
return { token: { type: "inline_ref", kind: "footnote", content: inner.trim() }, length };
|
|
58
58
|
}
|
|
59
|
+
function runLength(input, index, char) {
|
|
60
|
+
let end = index;
|
|
61
|
+
while (end < input.length && input[end] === char) end++;
|
|
62
|
+
return end - index;
|
|
63
|
+
}
|
|
64
|
+
function tryParseEmphasis(input) {
|
|
65
|
+
const char = input[0];
|
|
66
|
+
if (char !== "*" && char !== "_") return null;
|
|
67
|
+
const open = Math.min(3, runLength(input, 0, char));
|
|
68
|
+
const need = open;
|
|
69
|
+
let i = open;
|
|
70
|
+
while (i < input.length) {
|
|
71
|
+
const ch = input[i];
|
|
72
|
+
if (ch === "`") {
|
|
73
|
+
const close = input.indexOf("`", i + 1);
|
|
74
|
+
if (close === -1) break;
|
|
75
|
+
i = close + 1;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (ch !== char) {
|
|
79
|
+
i++;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const run = runLength(input, i, char);
|
|
83
|
+
const closes = need === 1 ? run % 2 === 1 : run >= need;
|
|
84
|
+
if (!closes) {
|
|
85
|
+
i += run;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const extra = run - need;
|
|
89
|
+
const inner = input.slice(open, i + extra);
|
|
90
|
+
if (inner.length === 0) return null;
|
|
91
|
+
const length = i + run;
|
|
92
|
+
const children = parseInline(inner);
|
|
93
|
+
let token;
|
|
94
|
+
if (need === 3) {
|
|
95
|
+
token = { type: "bold", children: [{ type: "italic", children }] };
|
|
96
|
+
} else if (need === 2) {
|
|
97
|
+
token = { type: "bold", children };
|
|
98
|
+
} else {
|
|
99
|
+
token = { type: "italic", children };
|
|
100
|
+
}
|
|
101
|
+
return { token, length };
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
59
105
|
function parseInline(content) {
|
|
60
106
|
if (!content) return [];
|
|
61
107
|
const tokens = [];
|
|
@@ -127,17 +173,11 @@ function parseInline(content) {
|
|
|
127
173
|
remaining = remaining.slice(linkMatch[0].length);
|
|
128
174
|
continue;
|
|
129
175
|
}
|
|
130
|
-
const
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
type: "bold",
|
|
136
|
-
children: parseInline(innerContent)
|
|
137
|
-
});
|
|
138
|
-
remaining = remaining.slice(boldMatch[0].length);
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
176
|
+
const emphasis = tryParseEmphasis(remaining);
|
|
177
|
+
if (emphasis) {
|
|
178
|
+
tokens.push(emphasis.token);
|
|
179
|
+
remaining = remaining.slice(emphasis.length);
|
|
180
|
+
continue;
|
|
141
181
|
}
|
|
142
182
|
const strikeMatch = remaining.match(/^~~(.+?)~~/);
|
|
143
183
|
if (strikeMatch && strikeMatch[1] !== void 0) {
|
|
@@ -148,18 +188,6 @@ function parseInline(content) {
|
|
|
148
188
|
remaining = remaining.slice(strikeMatch[0].length);
|
|
149
189
|
continue;
|
|
150
190
|
}
|
|
151
|
-
const italicMatch = remaining.match(/^\*([^*]+)\*|^_([^_]+)_/);
|
|
152
|
-
if (italicMatch) {
|
|
153
|
-
const innerContent = italicMatch[1] ?? italicMatch[2];
|
|
154
|
-
if (innerContent !== void 0) {
|
|
155
|
-
tokens.push({
|
|
156
|
-
type: "italic",
|
|
157
|
-
children: parseInline(innerContent)
|
|
158
|
-
});
|
|
159
|
-
remaining = remaining.slice(italicMatch[0].length);
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
191
|
const nextSpecial = findNextSpecialChar(remaining);
|
|
164
192
|
if (nextSpecial > 0) {
|
|
165
193
|
tokens.push({ type: "text", content: remaining.slice(0, nextSpecial) });
|
|
@@ -230,48 +258,95 @@ function collectListStrings(items) {
|
|
|
230
258
|
}
|
|
231
259
|
return out;
|
|
232
260
|
}
|
|
233
|
-
function
|
|
261
|
+
function normalizeReferenceContent(content) {
|
|
262
|
+
return content.replace(/\s+/g, " ").trim().toLowerCase();
|
|
263
|
+
}
|
|
264
|
+
var BIBLIOGRAPHY_ENTRY_RE = /^\s*\[(\d+)\]\s+([\s\S]+?)\s*$/;
|
|
265
|
+
function collectBibliography(blocks) {
|
|
266
|
+
const entries = /* @__PURE__ */ new Map();
|
|
267
|
+
for (const block of blocks) {
|
|
268
|
+
if (block.type !== "paragraph") continue;
|
|
269
|
+
const content = block.content ?? "";
|
|
270
|
+
const match = BIBLIOGRAPHY_ENTRY_RE.exec(content);
|
|
271
|
+
if (!match || !match[1] || !match[2]) continue;
|
|
272
|
+
const key = normalizeReferenceContent(match[2]);
|
|
273
|
+
if (key && !entries.has(key)) entries.set(key, Number(match[1]));
|
|
274
|
+
}
|
|
275
|
+
return entries;
|
|
276
|
+
}
|
|
277
|
+
function walkInlineRefs(tokens, visit) {
|
|
234
278
|
for (const token of tokens) {
|
|
235
279
|
if (token.type === "inline_ref") {
|
|
236
|
-
|
|
280
|
+
visit(token);
|
|
237
281
|
} else if ("children" in token) {
|
|
238
|
-
|
|
282
|
+
walkInlineRefs(token.children, visit);
|
|
239
283
|
}
|
|
240
284
|
}
|
|
241
285
|
}
|
|
242
|
-
function
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
286
|
+
function computeReferenceNumbering(blocks) {
|
|
287
|
+
const bibliography = collectBibliography(blocks);
|
|
288
|
+
let maxBibliography = 0;
|
|
289
|
+
for (const n of bibliography.values()) maxBibliography = Math.max(maxBibliography, n);
|
|
290
|
+
const numbering = { ref: /* @__PURE__ */ new Map(), footnote: /* @__PURE__ */ new Map() };
|
|
291
|
+
let nextRef = maxBibliography;
|
|
292
|
+
let nextFootnote = 0;
|
|
293
|
+
for (const block of blocks) {
|
|
294
|
+
for (const str of collectInlineStrings(block)) {
|
|
295
|
+
if (!str) continue;
|
|
296
|
+
walkInlineRefs(parseInline(str), (token) => {
|
|
297
|
+
const key = normalizeReferenceContent(token.content);
|
|
298
|
+
const map = numbering[token.kind];
|
|
299
|
+
if (map.has(key)) return;
|
|
300
|
+
if (token.kind === "ref") {
|
|
301
|
+
const fromBibliography = bibliography.get(key);
|
|
302
|
+
map.set(key, fromBibliography ?? ++nextRef);
|
|
303
|
+
} else {
|
|
304
|
+
map.set(key, ++nextFootnote);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
}
|
|
246
308
|
}
|
|
247
|
-
return
|
|
309
|
+
return numbering;
|
|
248
310
|
}
|
|
249
311
|
function computeReferenceBases(blocks) {
|
|
250
312
|
const bases = /* @__PURE__ */ new Map();
|
|
251
313
|
const acc = { ref: 0, footnote: 0 };
|
|
252
314
|
for (const block of blocks) {
|
|
253
315
|
bases.set(block.id, { ...acc });
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
316
|
+
for (const str of collectInlineStrings(block)) {
|
|
317
|
+
if (!str) continue;
|
|
318
|
+
walkInlineRefs(parseInline(str), (token) => {
|
|
319
|
+
acc[token.kind] += 1;
|
|
320
|
+
});
|
|
321
|
+
}
|
|
257
322
|
}
|
|
258
323
|
return bases;
|
|
259
324
|
}
|
|
260
|
-
var
|
|
325
|
+
var ReferenceNumberingContext = createContext(null);
|
|
261
326
|
var BlockReferenceScopeContext = createContext(null);
|
|
262
327
|
function NcmReferencesProvider({ blocks, children }) {
|
|
263
|
-
const
|
|
264
|
-
return /* @__PURE__ */ jsx(
|
|
328
|
+
const numbering = useMemo(() => computeReferenceNumbering(blocks), [blocks]);
|
|
329
|
+
return /* @__PURE__ */ jsx(ReferenceNumberingContext.Provider, { value: numbering, children });
|
|
265
330
|
}
|
|
266
|
-
function BlockReferenceScope({
|
|
267
|
-
const
|
|
268
|
-
const
|
|
331
|
+
function BlockReferenceScope({ children }) {
|
|
332
|
+
const numbering = useContext(ReferenceNumberingContext);
|
|
333
|
+
const local = useRef({ ref: /* @__PURE__ */ new Map(), footnote: /* @__PURE__ */ new Map() });
|
|
269
334
|
const counter = useRef({ ref: 0, footnote: 0 });
|
|
270
|
-
counter.current = { ref: 0, footnote: 0 };
|
|
271
335
|
const value = {
|
|
336
|
+
numberFor(kind, content) {
|
|
337
|
+
const key = normalizeReferenceContent(content);
|
|
338
|
+
const fromDocument = numbering?.[kind].get(key);
|
|
339
|
+
if (fromDocument !== void 0) return fromDocument;
|
|
340
|
+
const map = local.current[kind];
|
|
341
|
+
const existing = map.get(key);
|
|
342
|
+
if (existing !== void 0) return existing;
|
|
343
|
+
counter.current[kind] += 1;
|
|
344
|
+
map.set(key, counter.current[kind]);
|
|
345
|
+
return counter.current[kind];
|
|
346
|
+
},
|
|
272
347
|
next(kind) {
|
|
273
348
|
counter.current[kind] += 1;
|
|
274
|
-
return
|
|
349
|
+
return counter.current[kind];
|
|
275
350
|
}
|
|
276
351
|
};
|
|
277
352
|
return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value, children });
|
|
@@ -279,7 +354,7 @@ function BlockReferenceScope({ blockId, children }) {
|
|
|
279
354
|
function useBlockReferenceScope() {
|
|
280
355
|
return useContext(BlockReferenceScopeContext);
|
|
281
356
|
}
|
|
282
|
-
var INERT_SCOPE = { next: () => 0 };
|
|
357
|
+
var INERT_SCOPE = { numberFor: () => 0, next: () => 0 };
|
|
283
358
|
function InertReferenceScope({ children }) {
|
|
284
359
|
return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value: INERT_SCOPE, children });
|
|
285
360
|
}
|
|
@@ -715,7 +790,7 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
|
|
|
715
790
|
);
|
|
716
791
|
}
|
|
717
792
|
case "inline_ref": {
|
|
718
|
-
const number = refScope?.
|
|
793
|
+
const number = refScope?.numberFor(token.kind, token.content) ?? 0;
|
|
719
794
|
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 });
|
|
720
795
|
}
|
|
721
796
|
default:
|
|
@@ -787,8 +862,32 @@ function renderBionicText(content, ratio = 0.5) {
|
|
|
787
862
|
function renderBeelineText(content) {
|
|
788
863
|
return renderReadingText(content, { beeline: true });
|
|
789
864
|
}
|
|
865
|
+
function quoteBlocks(block) {
|
|
866
|
+
try {
|
|
867
|
+
const doc = parseNcm(block.content, {
|
|
868
|
+
preset: "ncm-full",
|
|
869
|
+
allowMissingFrontmatter: true,
|
|
870
|
+
// Attribution off, as the NUU Editor's bridge keeps it: the promoter's
|
|
871
|
+
// trigger is any last quote line starting with `-`, so a nested quote
|
|
872
|
+
// ending in a list item would lose that item to a `— Author` line.
|
|
873
|
+
blockOptions: { extensions: { attribution: false } }
|
|
874
|
+
});
|
|
875
|
+
const blocks = doc.blocks ?? [];
|
|
876
|
+
if (blocks.length === 0 || blocks.some((child) => child.type === "frontmatter")) {
|
|
877
|
+
return null;
|
|
878
|
+
}
|
|
879
|
+
return blocks.map((child, index) => ({ ...child, id: `${block.id}.${index + 1}`, stableId: void 0 }));
|
|
880
|
+
} catch {
|
|
881
|
+
return null;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
function QuotedLines({ content }) {
|
|
885
|
+
const lines = content.split("\n");
|
|
886
|
+
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)) });
|
|
887
|
+
}
|
|
790
888
|
function BlockquoteBlock({ block, className }) {
|
|
791
|
-
const
|
|
889
|
+
const multiline = block.content.includes("\n");
|
|
890
|
+
const blocks = useMemo(() => multiline ? quoteBlocks(block) : null, [block, multiline]);
|
|
792
891
|
return /* @__PURE__ */ jsx(
|
|
793
892
|
"blockquote",
|
|
794
893
|
{
|
|
@@ -798,7 +897,9 @@ function BlockquoteBlock({ block, className }) {
|
|
|
798
897
|
"data-block-id": block.id,
|
|
799
898
|
"data-ncm-blockquote": "",
|
|
800
899
|
className,
|
|
801
|
-
children:
|
|
900
|
+
children: !multiline ? /* @__PURE__ */ jsx(InlineContent, { content: block.content }) : blocks === null ? /* @__PURE__ */ jsx(QuotedLines, { content: block.content }) : blocks.map(
|
|
901
|
+
(child) => child.type === "paragraph" ? /* @__PURE__ */ jsx(QuotedLines, { content: child.content ?? "" }, blockKey(child)) : /* @__PURE__ */ jsx(NcmBlock, { block: child }, blockKey(child))
|
|
902
|
+
)
|
|
802
903
|
}
|
|
803
904
|
);
|
|
804
905
|
}
|
|
@@ -1976,4 +2077,4 @@ function useCustomCodeRenderer(language) {
|
|
|
1976
2077
|
return customCodeRenderers[language];
|
|
1977
2078
|
}
|
|
1978
2079
|
|
|
1979
|
-
export { AdmonitionBlock, AsideBlock, AttributionBlock, BlockReferenceScope, BlockShell, BlockquoteBlock, ChartBlock, ChildBlocks, CodeBlock, ContainerBlock, CustomCodeBlock, DataviewBlock, DefinitionBlock, EmbeddingBlock, FigureBlock, FootnoteBlock, FrontmatterBlock, HeaderBlock, HorizontalRuleBlock, HtmlBlock, InertReferenceScope, InlineContent, LatexDisplayBlock, LinkBlock, ListBlock, MathBlock, MermaidBlock, NcmBlock, NcmBlockPreview, NcmDocument, NcmProvider, NcmReferencesProvider, PageBreakerBlock, ParagraphBlock, ReferenceMarker, SanitizedHtmlBlock, SpoilerBlock, TableBlock, TaskListBlock, blockDataAttributes, blockKey, cn, computeReferenceBases, defaultRenderers, parseInline, renderBeelineText, renderBionicText, renderReadingText, useBlockReferenceScope, useBlockRenderer, useCustomCodeRenderer, useNcmConfig };
|
|
2080
|
+
export { AdmonitionBlock, AsideBlock, AttributionBlock, BlockReferenceScope, BlockShell, BlockquoteBlock, ChartBlock, ChildBlocks, CodeBlock, ContainerBlock, CustomCodeBlock, DataviewBlock, DefinitionBlock, EmbeddingBlock, FigureBlock, FootnoteBlock, FrontmatterBlock, HeaderBlock, HorizontalRuleBlock, HtmlBlock, InertReferenceScope, InlineContent, LatexDisplayBlock, LinkBlock, ListBlock, MathBlock, MermaidBlock, NcmBlock, NcmBlockPreview, NcmDocument, NcmProvider, NcmReferencesProvider, PageBreakerBlock, ParagraphBlock, ReferenceMarker, SanitizedHtmlBlock, SpoilerBlock, TableBlock, TaskListBlock, blockDataAttributes, blockKey, cn, collectBibliography, computeReferenceBases, computeReferenceNumbering, defaultRenderers, normalizeReferenceContent, parseInline, renderBeelineText, renderBionicText, renderReadingText, useBlockReferenceScope, useBlockRenderer, useCustomCodeRenderer, useNcmConfig };
|
package/dist/inline/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { b as InlineToken } from '../inline-DwUYUmk4.js';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
|
-
import { d as ReferenceKind } from '../references-
|
|
4
|
+
import { d as ReferenceKind } from '../references-BM-lvGrq.js';
|
|
5
5
|
import '@nuucognition/ncm';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -13,8 +13,7 @@ import '@nuucognition/ncm';
|
|
|
13
13
|
* - Images: 
|
|
14
14
|
* - Links: [text](url "title")
|
|
15
15
|
* - Inline reference: ^[ref: ...] / ^[footnote: ...]
|
|
16
|
-
* -
|
|
17
|
-
* - Italic: *text* or _text_
|
|
16
|
+
* - Emphasis: ***both***, **bold**, *italic* (and the `_` spellings)
|
|
18
17
|
* - Strikethrough: ~~text~~
|
|
19
18
|
*/
|
|
20
19
|
declare function parseInline(content: string): InlineToken[];
|
package/dist/inline/index.js
CHANGED
|
@@ -44,6 +44,52 @@ function tryParseInlineRef(input) {
|
|
|
44
44
|
}
|
|
45
45
|
return { token: { type: "inline_ref", kind: "footnote", content: inner.trim() }, length };
|
|
46
46
|
}
|
|
47
|
+
function runLength(input, index, char) {
|
|
48
|
+
let end = index;
|
|
49
|
+
while (end < input.length && input[end] === char) end++;
|
|
50
|
+
return end - index;
|
|
51
|
+
}
|
|
52
|
+
function tryParseEmphasis(input) {
|
|
53
|
+
const char = input[0];
|
|
54
|
+
if (char !== "*" && char !== "_") return null;
|
|
55
|
+
const open = Math.min(3, runLength(input, 0, char));
|
|
56
|
+
const need = open;
|
|
57
|
+
let i = open;
|
|
58
|
+
while (i < input.length) {
|
|
59
|
+
const ch = input[i];
|
|
60
|
+
if (ch === "`") {
|
|
61
|
+
const close = input.indexOf("`", i + 1);
|
|
62
|
+
if (close === -1) break;
|
|
63
|
+
i = close + 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (ch !== char) {
|
|
67
|
+
i++;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const run = runLength(input, i, char);
|
|
71
|
+
const closes = need === 1 ? run % 2 === 1 : run >= need;
|
|
72
|
+
if (!closes) {
|
|
73
|
+
i += run;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const extra = run - need;
|
|
77
|
+
const inner = input.slice(open, i + extra);
|
|
78
|
+
if (inner.length === 0) return null;
|
|
79
|
+
const length = i + run;
|
|
80
|
+
const children = parseInline(inner);
|
|
81
|
+
let token;
|
|
82
|
+
if (need === 3) {
|
|
83
|
+
token = { type: "bold", children: [{ type: "italic", children }] };
|
|
84
|
+
} else if (need === 2) {
|
|
85
|
+
token = { type: "bold", children };
|
|
86
|
+
} else {
|
|
87
|
+
token = { type: "italic", children };
|
|
88
|
+
}
|
|
89
|
+
return { token, length };
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
47
93
|
function parseInline(content) {
|
|
48
94
|
if (!content) return [];
|
|
49
95
|
const tokens = [];
|
|
@@ -115,17 +161,11 @@ function parseInline(content) {
|
|
|
115
161
|
remaining = remaining.slice(linkMatch[0].length);
|
|
116
162
|
continue;
|
|
117
163
|
}
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
type: "bold",
|
|
124
|
-
children: parseInline(innerContent)
|
|
125
|
-
});
|
|
126
|
-
remaining = remaining.slice(boldMatch[0].length);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
164
|
+
const emphasis = tryParseEmphasis(remaining);
|
|
165
|
+
if (emphasis) {
|
|
166
|
+
tokens.push(emphasis.token);
|
|
167
|
+
remaining = remaining.slice(emphasis.length);
|
|
168
|
+
continue;
|
|
129
169
|
}
|
|
130
170
|
const strikeMatch = remaining.match(/^~~(.+?)~~/);
|
|
131
171
|
if (strikeMatch && strikeMatch[1] !== void 0) {
|
|
@@ -136,18 +176,6 @@ function parseInline(content) {
|
|
|
136
176
|
remaining = remaining.slice(strikeMatch[0].length);
|
|
137
177
|
continue;
|
|
138
178
|
}
|
|
139
|
-
const italicMatch = remaining.match(/^\*([^*]+)\*|^_([^_]+)_/);
|
|
140
|
-
if (italicMatch) {
|
|
141
|
-
const innerContent = italicMatch[1] ?? italicMatch[2];
|
|
142
|
-
if (innerContent !== void 0) {
|
|
143
|
-
tokens.push({
|
|
144
|
-
type: "italic",
|
|
145
|
-
children: parseInline(innerContent)
|
|
146
|
-
});
|
|
147
|
-
remaining = remaining.slice(italicMatch[0].length);
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
179
|
const nextSpecial = findNextSpecialChar(remaining);
|
|
152
180
|
if (nextSpecial > 0) {
|
|
153
181
|
tokens.push({ type: "text", content: remaining.slice(0, nextSpecial) });
|
|
@@ -258,17 +286,30 @@ function ReferenceMarker({ kind, number, children }) {
|
|
|
258
286
|
}
|
|
259
287
|
);
|
|
260
288
|
}
|
|
261
|
-
|
|
289
|
+
function normalizeReferenceContent(content) {
|
|
290
|
+
return content.replace(/\s+/g, " ").trim().toLowerCase();
|
|
291
|
+
}
|
|
292
|
+
var ReferenceNumberingContext = createContext(null);
|
|
262
293
|
var BlockReferenceScopeContext = createContext(null);
|
|
263
|
-
function BlockReferenceScope({
|
|
264
|
-
const
|
|
265
|
-
const
|
|
294
|
+
function BlockReferenceScope({ children }) {
|
|
295
|
+
const numbering = useContext(ReferenceNumberingContext);
|
|
296
|
+
const local = useRef({ ref: /* @__PURE__ */ new Map(), footnote: /* @__PURE__ */ new Map() });
|
|
266
297
|
const counter = useRef({ ref: 0, footnote: 0 });
|
|
267
|
-
counter.current = { ref: 0, footnote: 0 };
|
|
268
298
|
const value = {
|
|
299
|
+
numberFor(kind, content) {
|
|
300
|
+
const key = normalizeReferenceContent(content);
|
|
301
|
+
const fromDocument = numbering?.[kind].get(key);
|
|
302
|
+
if (fromDocument !== void 0) return fromDocument;
|
|
303
|
+
const map = local.current[kind];
|
|
304
|
+
const existing = map.get(key);
|
|
305
|
+
if (existing !== void 0) return existing;
|
|
306
|
+
counter.current[kind] += 1;
|
|
307
|
+
map.set(key, counter.current[kind]);
|
|
308
|
+
return counter.current[kind];
|
|
309
|
+
},
|
|
269
310
|
next(kind) {
|
|
270
311
|
counter.current[kind] += 1;
|
|
271
|
-
return
|
|
312
|
+
return counter.current[kind];
|
|
272
313
|
}
|
|
273
314
|
};
|
|
274
315
|
return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value, children });
|
|
@@ -276,7 +317,7 @@ function BlockReferenceScope({ blockId, children }) {
|
|
|
276
317
|
function useBlockReferenceScope() {
|
|
277
318
|
return useContext(BlockReferenceScopeContext);
|
|
278
319
|
}
|
|
279
|
-
var INERT_SCOPE = { next: () => 0 };
|
|
320
|
+
var INERT_SCOPE = { numberFor: () => 0, next: () => 0 };
|
|
280
321
|
function InertReferenceScope({ children }) {
|
|
281
322
|
return /* @__PURE__ */ jsx(BlockReferenceScopeContext.Provider, { value: INERT_SCOPE, children });
|
|
282
323
|
}
|
|
@@ -567,7 +608,7 @@ function TokenRenderer({ token, disableBionic, disableBeeline }) {
|
|
|
567
608
|
);
|
|
568
609
|
}
|
|
569
610
|
case "inline_ref": {
|
|
570
|
-
const number = refScope?.
|
|
611
|
+
const number = refScope?.numberFor(token.kind, token.content) ?? 0;
|
|
571
612
|
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 });
|
|
572
613
|
}
|
|
573
614
|
default:
|
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
|
}
|