@linloir/limr 0.1.0 → 1.0.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.
- package/README.en.md +151 -0
- package/README.md +80 -127
- package/benchmarks/results/layout.json +2593 -0
- package/benchmarks/results/markstream-code.json +1823 -0
- package/benchmarks/results/markstream-reading-repeat.json +1152 -0
- package/benchmarks/results/markstream.json +12486 -0
- package/benchmarks/results/streaming-browser.json +77 -0
- package/benchmarks/results/streaming.json +357 -0
- package/dist/base.css +93 -10
- package/dist/{chunk-7JF5HHVF.js → chunk-BG5QUQFR.js} +340 -72
- package/dist/chunk-BG5QUQFR.js.map +1 -0
- package/dist/chunk-BVHHOVMT.js +179 -0
- package/dist/chunk-BVHHOVMT.js.map +1 -0
- package/dist/chunk-FJZCQY2S.js +155 -0
- package/dist/chunk-FJZCQY2S.js.map +1 -0
- package/dist/chunk-FSI5OTBW.js +1 -0
- package/dist/{chunk-ETHLPBKQ.js → chunk-GU2RPESF.js} +238 -131
- package/dist/chunk-GU2RPESF.js.map +1 -0
- package/dist/{chunk-65V5OZ4G.js → chunk-SUAAUGAX.js} +1350 -511
- package/dist/chunk-SUAAUGAX.js.map +1 -0
- package/dist/core/index.d.ts +6 -3
- package/dist/core/index.js +15 -5
- package/dist/extensions/index.d.ts +30 -5
- package/dist/extensions/index.js +15 -3
- package/dist/index.d.ts +4 -4
- package/dist/index.js +31 -8
- package/dist/{engine-43u8B4yt.d.ts → knuth-plass-C8mgFm7W.d.ts} +67 -1
- package/dist/knuth-plass-layout-CHQCWKB5.js +449 -0
- package/dist/knuth-plass-layout-CHQCWKB5.js.map +1 -0
- package/dist/react/index.d.ts +7 -5
- package/dist/react/index.js +7 -3
- package/dist/styles.css +93 -10
- package/dist/{translations-BliabrPd.d.ts → translations-BXzSwLBJ.d.ts} +49 -4
- package/docs/README.md +13 -0
- package/docs/api.md +5 -158
- package/docs/assets/rendered.svg +9 -0
- package/docs/assets/source.svg +9 -0
- package/docs/en/README.md +28 -0
- package/docs/en/ai-skills.md +57 -0
- package/docs/en/annotations.md +86 -0
- package/docs/en/api.md +115 -0
- package/docs/en/architecture.md +41 -0
- package/docs/en/extensions.md +208 -0
- package/docs/en/getting-started.md +69 -0
- package/docs/en/integration.md +154 -0
- package/docs/en/modules.md +84 -0
- package/docs/en/performance.md +93 -0
- package/docs/en/plugin-packages.md +68 -0
- package/docs/en/styles.md +99 -0
- package/docs/en/syntax.md +455 -0
- package/docs/extensions.md +5 -306
- package/docs/implementation.md +5 -76
- package/docs/performance.md +5 -81
- package/docs/screenshots/blocks.png +0 -0
- package/docs/screenshots/dark.png +0 -0
- package/docs/screenshots/desktop.png +0 -0
- package/docs/screenshots/plugin-mobile.png +0 -0
- package/docs/styles.md +5 -100
- package/docs/visual-upgrade.md +5 -145
- package/docs/zh-CN/README.md +28 -0
- package/docs/zh-CN/ai-skills.md +57 -0
- package/docs/zh-CN/annotations.md +86 -0
- package/docs/zh-CN/api.md +115 -0
- package/docs/zh-CN/architecture.md +41 -0
- package/docs/zh-CN/extensions.md +210 -0
- package/docs/zh-CN/getting-started.md +69 -0
- package/docs/zh-CN/integration.md +154 -0
- package/docs/zh-CN/modules.md +84 -0
- package/docs/zh-CN/performance.md +93 -0
- package/docs/zh-CN/plugin-packages.md +68 -0
- package/docs/zh-CN/styles.md +99 -0
- package/docs/zh-CN/syntax.md +457 -0
- package/examples/notes.tsx +18 -11
- package/examples/packages/paper-theme/index.css +25 -0
- package/examples/packages/paper-theme/package.json +7 -0
- package/examples/packages/reading-tools/index.d.ts +2 -0
- package/examples/packages/reading-tools/index.js +25 -0
- package/examples/packages/reading-tools/package.json +16 -0
- package/package.json +17 -5
- package/skills/limr-plugin-development/SKILL.md +22 -0
- package/skills/limr-plugin-development/agents/openai.yaml +4 -0
- package/skills/limr-plugin-development/assets/plugin-template/README.md +30 -0
- package/skills/limr-plugin-development/assets/plugin-template/package.json +36 -0
- package/skills/limr-plugin-development/assets/plugin-template/src/index.tsx +50 -0
- package/skills/limr-plugin-development/assets/plugin-template/src/styles.css +9 -0
- package/skills/limr-plugin-development/assets/plugin-template/tsconfig.json +20 -0
- package/skills/limr-plugin-development/assets/plugin-template/tsup.config.ts +8 -0
- package/skills/limr-plugin-development/references/contract.md +51 -0
- package/skills/limr-use/SKILL.md +23 -0
- package/skills/limr-use/agents/openai.yaml +4 -0
- package/skills/limr-use/references/integration.md +49 -0
- package/skills/limr-use/references/syntax.md +20 -0
- package/dist/chunk-65V5OZ4G.js.map +0 -1
- package/dist/chunk-7JF5HHVF.js.map +0 -1
- package/dist/chunk-ETHLPBKQ.js.map +0 -1
- package/dist/chunk-V2OG4Y3F.js +0 -1
- /package/dist/{chunk-V2OG4Y3F.js.map → chunk-FSI5OTBW.js.map} +0 -0
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
|
+
annotationReferenceRange,
|
|
2
3
|
createDocument,
|
|
3
4
|
defaultHighlight,
|
|
4
|
-
intersects,
|
|
5
5
|
mapText,
|
|
6
|
-
rangeOf,
|
|
7
6
|
resolveAnnotationAnchors,
|
|
8
|
-
safeUrl,
|
|
9
7
|
sameRange,
|
|
10
|
-
selectionFromRange
|
|
8
|
+
selectionFromRange
|
|
9
|
+
} from "./chunk-BG5QUQFR.js";
|
|
10
|
+
import {
|
|
11
|
+
atomicSelectionText,
|
|
12
|
+
leavesIn,
|
|
13
|
+
measurementRange,
|
|
14
|
+
textRange
|
|
15
|
+
} from "./chunk-BVHHOVMT.js";
|
|
16
|
+
import {
|
|
17
|
+
intersects,
|
|
18
|
+
rangeOf,
|
|
19
|
+
safeUrl,
|
|
11
20
|
textContent,
|
|
12
21
|
walk
|
|
13
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-FJZCQY2S.js";
|
|
14
23
|
import {
|
|
15
24
|
ResourceCache
|
|
16
25
|
} from "./chunk-6N6TFHEN.js";
|
|
@@ -56,6 +65,8 @@ function scrollWithMotion(root, top) {
|
|
|
56
65
|
|
|
57
66
|
// src/react/runtime.ts
|
|
58
67
|
var english = {
|
|
68
|
+
language: "en",
|
|
69
|
+
citation: "Citation",
|
|
59
70
|
contents: "Contents",
|
|
60
71
|
annotations: "Annotations",
|
|
61
72
|
expand: "Expand",
|
|
@@ -91,10 +102,13 @@ var english = {
|
|
|
91
102
|
highlightWavy: "Wavy",
|
|
92
103
|
hideHighlight: "Hide highlight",
|
|
93
104
|
showHighlight: "Show highlight",
|
|
105
|
+
inlineHighlightHint: "Markdown inline highlight, editing unavailable",
|
|
94
106
|
deleteAnnotations: "Delete",
|
|
95
107
|
deleteAnnotationsHint: "Deletes {count} annotations on this text and any highlight."
|
|
96
108
|
};
|
|
97
109
|
var chinese = {
|
|
110
|
+
language: "zh-CN",
|
|
111
|
+
citation: "\u5F15\u7528",
|
|
98
112
|
contents: "\u76EE\u5F55",
|
|
99
113
|
annotations: "\u6CE8\u91CA",
|
|
100
114
|
expand: "\u5C55\u5F00",
|
|
@@ -130,6 +144,7 @@ var chinese = {
|
|
|
130
144
|
highlightWavy: "\u6CE2\u6D6A\u7EBF",
|
|
131
145
|
hideHighlight: "\u9690\u85CF\u9AD8\u4EAE",
|
|
132
146
|
showHighlight: "\u663E\u793A\u9AD8\u4EAE",
|
|
147
|
+
inlineHighlightHint: "Markdown \u5185\u5D4C\u9AD8\u4EAE\uFF0C\u4E0D\u652F\u6301\u7F16\u8F91",
|
|
133
148
|
deleteAnnotations: "\u5220\u9664",
|
|
134
149
|
deleteAnnotationsHint: "\u5C06\u5220\u9664\u8FD9\u6BB5\u6587\u5B57\u5173\u8054\u7684 {count} \u4E2A\u6CE8\u91CA\u53CA\u9AD8\u4EAE\u3002"
|
|
135
150
|
};
|
|
@@ -158,7 +173,7 @@ var ReaderRuntime = class {
|
|
|
158
173
|
layout = new Store(0);
|
|
159
174
|
viewport = new Store(0);
|
|
160
175
|
documentOffset = new Store(0);
|
|
161
|
-
decorations = new Store({ annotations: /* @__PURE__ */ new Map(), highlights: /* @__PURE__ */ new Map(), occurrences: [], byBlock: /* @__PURE__ */ new Map() });
|
|
176
|
+
decorations = new Store({ annotations: /* @__PURE__ */ new Map(), highlights: /* @__PURE__ */ new Map(), occurrences: [], referenceRanges: /* @__PURE__ */ new Map(), byBlock: /* @__PURE__ */ new Map() });
|
|
162
177
|
configuration;
|
|
163
178
|
resources = new ResourceCache(128);
|
|
164
179
|
resourceVersions = new Store(/* @__PURE__ */ new Map());
|
|
@@ -170,7 +185,9 @@ var ReaderRuntime = class {
|
|
|
170
185
|
bindings = /* @__PURE__ */ new WeakMap();
|
|
171
186
|
textBinders = /* @__PURE__ */ new WeakMap();
|
|
172
187
|
components = {};
|
|
188
|
+
rendererOverrides = /* @__PURE__ */ new Map();
|
|
173
189
|
annotationTypes = /* @__PURE__ */ new Map();
|
|
190
|
+
resolvedTypes = /* @__PURE__ */ new WeakMap();
|
|
174
191
|
locale = english;
|
|
175
192
|
content = null;
|
|
176
193
|
selectionRange = null;
|
|
@@ -190,7 +207,7 @@ var ReaderRuntime = class {
|
|
|
190
207
|
addAnnotation: (annotation, options = {}) => {
|
|
191
208
|
this.changeAnnotations((items) => {
|
|
192
209
|
const next = [...items.filter((item) => item.id !== annotation.id), annotation];
|
|
193
|
-
if (annotation.type !== "highlight" && options.highlight !== false) {
|
|
210
|
+
if (annotation.type !== "highlight" && options.highlight !== false && (options.highlight !== void 0 || this.annotationTypes.get(annotation.type)?.highlight !== "hover")) {
|
|
194
211
|
const doc = this.document.getSnapshot();
|
|
195
212
|
for (const anchor of resolveAnnotationAnchors(annotation, doc)) {
|
|
196
213
|
if (anchor.range.start === anchor.range.end || next.some((item) => item.type === "highlight" && resolveAnnotationAnchors(item, doc).some((other) => sameRange(other.range, anchor.range)))) continue;
|
|
@@ -270,10 +287,24 @@ var ReaderRuntime = class {
|
|
|
270
287
|
});
|
|
271
288
|
}
|
|
272
289
|
installConfiguration(config) {
|
|
290
|
+
this.locale = { ...english, ...config.locale };
|
|
273
291
|
this.components = Object.assign({}, ...(config.extensions ?? []).map((ext) => ext.components), config.components);
|
|
292
|
+
this.rendererOverrides = /* @__PURE__ */ new Map();
|
|
293
|
+
const rules = [
|
|
294
|
+
...(config.extensions ?? []).flatMap((ext) => ext.rendererOverrides ?? []),
|
|
295
|
+
...Object.entries(config.components ?? {}).map(([type, component]) => ({ type, component })),
|
|
296
|
+
...config.rendererOverrides ?? []
|
|
297
|
+
];
|
|
298
|
+
for (const rule of rules) this.rendererOverrides.set(rule.type, [...this.rendererOverrides.get(rule.type) ?? [], rule]);
|
|
274
299
|
const annotationTypes = [...(config.extensions ?? []).flatMap((ext) => [...ext.annotationTypes ?? []]), ...config.annotationTypes ?? []];
|
|
275
|
-
this.annotationTypes = new Map(annotationTypes.map((type) =>
|
|
276
|
-
|
|
300
|
+
this.annotationTypes = new Map(annotationTypes.map((type) => {
|
|
301
|
+
if (typeof type.label === "string") return [type.type, type];
|
|
302
|
+
const label = type.label(this.locale);
|
|
303
|
+
const previous = this.resolvedTypes.get(type);
|
|
304
|
+
const resolved = previous?.label === label ? previous : { ...type, label };
|
|
305
|
+
this.resolvedTypes.set(type, resolved);
|
|
306
|
+
return [type.type, resolved];
|
|
307
|
+
}));
|
|
277
308
|
}
|
|
278
309
|
configure(config) {
|
|
279
310
|
const old = this.configuration.get();
|
|
@@ -281,7 +312,7 @@ var ReaderRuntime = class {
|
|
|
281
312
|
this.installConfiguration(config);
|
|
282
313
|
this.configuration.set(config);
|
|
283
314
|
if (old.extensions !== config.extensions) this.document.setExtensions(config.extensions ?? []);
|
|
284
|
-
if (old.annotations !== config.annotations) this.rebuildDecorations();
|
|
315
|
+
else if (old.annotations !== config.annotations || old.annotationTypes !== config.annotationTypes) this.rebuildDecorations();
|
|
285
316
|
if (old.annotationTypes !== config.annotationTypes || old.extensions !== config.extensions) this.resources.invalidate();
|
|
286
317
|
}
|
|
287
318
|
updateInteraction(patch) {
|
|
@@ -339,17 +370,29 @@ var ReaderRuntime = class {
|
|
|
339
370
|
if ([...versions.keys()].some((id) => !annotations.has(id))) this.resourceVersions.set(new Map([...versions].filter(([id]) => annotations.has(id))));
|
|
340
371
|
const occurrences = [...doc.occurrences];
|
|
341
372
|
const allHighlights = [];
|
|
342
|
-
for (const annotation of
|
|
373
|
+
for (const annotation of annotations.values()) {
|
|
343
374
|
resolveAnnotationAnchors(annotation, doc).forEach((anchor, index) => {
|
|
344
375
|
if (annotation.type === "highlight") {
|
|
345
376
|
const id = index ? `${annotation.id}:${index}` : annotation.id;
|
|
346
377
|
const value = { ...annotation.data, id, annotationId: annotation.id, range: anchor.range };
|
|
347
378
|
const old = previous.highlights.get(id);
|
|
348
|
-
allHighlights.push(old && sameRange(old.range, value.range) && old.color === value.color && old.style === value.style && old.hidden === value.hidden ? old : value);
|
|
379
|
+
allHighlights.push(old && !old.occurrenceId && sameRange(old.range, value.range) && old.color === value.color && old.style === value.style && old.hidden === value.hidden && old.readOnly === value.readOnly ? old : value);
|
|
349
380
|
} else occurrences.push({ ...anchor, id: anchor.id ?? `${doc.id}-${annotation.id}-${index}`, annotationIds: [annotation.id] });
|
|
350
381
|
});
|
|
351
382
|
}
|
|
352
383
|
occurrences.sort((a, b) => a.range.end - b.range.end || a.id.localeCompare(b.id));
|
|
384
|
+
const referenceRanges = new Map(occurrences.map((occurrence) => [occurrence.id, annotationReferenceRange(doc, occurrence)]));
|
|
385
|
+
for (const occurrence of occurrences) {
|
|
386
|
+
const annotation = annotations.get(occurrence.annotationIds[0]);
|
|
387
|
+
const definition2 = annotation && this.annotationTypes.get(annotation.type);
|
|
388
|
+
if (!annotation || definition2?.highlight !== "hover") continue;
|
|
389
|
+
const range = referenceRanges.get(occurrence.id);
|
|
390
|
+
if (range.start === range.end) continue;
|
|
391
|
+
const id = `reference-${occurrence.id}`;
|
|
392
|
+
const value = { id, annotationId: annotation.id, occurrenceId: occurrence.id, range, color: definition2.color ?? defaultHighlight.color, style: "background" };
|
|
393
|
+
const old = previous.highlights.get(id);
|
|
394
|
+
allHighlights.push(old && old.occurrenceId === value.occurrenceId && old.annotationId === value.annotationId && sameRange(old.range, range) && old.color === value.color ? old : value);
|
|
395
|
+
}
|
|
353
396
|
const byBlock = /* @__PURE__ */ new Map();
|
|
354
397
|
for (const block of occurrences.length || allHighlights.length ? doc.blocks : []) {
|
|
355
398
|
const marks = occurrences.filter((item) => !item.embedded && item.range.end > block.range.start && item.range.end <= block.range.end);
|
|
@@ -363,7 +406,7 @@ var ReaderRuntime = class {
|
|
|
363
406
|
}
|
|
364
407
|
const sameBlocks = byBlock.size === previous.byBlock.size && [...byBlock].every(([id, value]) => previous.byBlock.get(id) === value);
|
|
365
408
|
const highlights = new Map(allHighlights.map((item) => [item.id, item]));
|
|
366
|
-
this.decorations.set({ annotations, highlights, occurrences, byBlock: sameBlocks ? previous.byBlock : byBlock });
|
|
409
|
+
this.decorations.set({ annotations, highlights, occurrences, referenceRanges, byBlock: sameBlocks ? previous.byBlock : byBlock });
|
|
367
410
|
const state = this.interaction.get();
|
|
368
411
|
if (state.editing && !annotations.has(state.editing) && this.pendingOpen !== state.editing) this.updateInteraction({ editing: null });
|
|
369
412
|
if (state.activeHighlight && !highlights.has(state.activeHighlight)) this.activateHighlight(null);
|
|
@@ -514,7 +557,7 @@ var emptyList = EMPTY;
|
|
|
514
557
|
import { gfm as syntax } from "micromark-extension-gfm";
|
|
515
558
|
import { gfmFromMarkdown } from "mdast-util-gfm";
|
|
516
559
|
function gfm() {
|
|
517
|
-
return { name: "gfm", micromark: [syntax()], mdast: gfmFromMarkdown(), scope: "local" };
|
|
560
|
+
return { name: "gfm", directives: ["gfm"], micromark: [syntax()], mdast: gfmFromMarkdown(), scope: "local", components: { gfm: ({ children }) => children } };
|
|
518
561
|
}
|
|
519
562
|
|
|
520
563
|
// src/extensions/math.tsx
|
|
@@ -523,10 +566,10 @@ import { math as syntax2 } from "micromark-extension-math";
|
|
|
523
566
|
import { mathFromMarkdown } from "mdast-util-math";
|
|
524
567
|
|
|
525
568
|
// src/components/CopyButton.tsx
|
|
526
|
-
import { useEffect as
|
|
569
|
+
import { useEffect as useEffect10, useRef as useRef15, useState as useState10 } from "react";
|
|
527
570
|
|
|
528
571
|
// src/react/context.tsx
|
|
529
|
-
import { createContext as createContext2, useCallback as
|
|
572
|
+
import { createContext as createContext2, useCallback as useCallback3, useContext as useContext3, useEffect as useEffect9, useId, useLayoutEffect, useMemo as useMemo5, useRef as useRef14, useState as useState9, useSyncExternalStore } from "react";
|
|
530
573
|
|
|
531
574
|
// src/extensions/code.tsx
|
|
532
575
|
import { useEffect, useRef, useState } from "react";
|
|
@@ -538,6 +581,16 @@ function literalValue(node) {
|
|
|
538
581
|
function mapLiteral(source, node) {
|
|
539
582
|
const range = rangeOf(node), raw = source.slice(range.start, range.end), value = literalValue(node);
|
|
540
583
|
const starts = [], ends = [];
|
|
584
|
+
if (node.valueRange) {
|
|
585
|
+
const payload = node.valueRange;
|
|
586
|
+
for (let at = payload.start; at < payload.end && starts.length < value.length; at++) {
|
|
587
|
+
const size = source[at] === "\r" && source[at + 1] === "\n" ? 2 : 1;
|
|
588
|
+
starts.push(at);
|
|
589
|
+
ends.push(at + size);
|
|
590
|
+
at += size - 1;
|
|
591
|
+
}
|
|
592
|
+
return { starts, ends, exact: starts.length === value.length };
|
|
593
|
+
}
|
|
541
594
|
if (node.type === "inlineCode") {
|
|
542
595
|
const fence = /^`+/.exec(raw)?.[0].length ?? 0;
|
|
543
596
|
let from = fence, until = raw.length - fence;
|
|
@@ -577,6 +630,24 @@ function mapLiteral(source, node) {
|
|
|
577
630
|
return { starts, ends, exact };
|
|
578
631
|
}
|
|
579
632
|
|
|
633
|
+
// src/extensions/literal-directive.ts
|
|
634
|
+
function literalDirective(root, source, name, aliases3 = [name]) {
|
|
635
|
+
walk(root, (node) => {
|
|
636
|
+
if (node.type !== "component" || !aliases3.includes(node.name ?? "") || !node.position) return;
|
|
637
|
+
const start = node.position.start.offset, end = node.position.end.offset;
|
|
638
|
+
const raw = source.slice(start, end);
|
|
639
|
+
const header = /^[^\r\n]*(?:\r\n|\r|\n)/.exec(raw);
|
|
640
|
+
const closing = /(?:\r\n|\r|\n)[ \t]*:{2,}[ \t]*$/.exec(raw);
|
|
641
|
+
const from = start + (header?.[0].length ?? raw.length);
|
|
642
|
+
const until = closing ? start + closing.index : end;
|
|
643
|
+
node.type = name;
|
|
644
|
+
node.value = source.slice(from, until).replace(/\r\n?/g, "\n").replace(node.incomplete ? /\n$/ : /$^/, "");
|
|
645
|
+
node.valueRange = { start: from, end: until };
|
|
646
|
+
if (name === "code") node.lang = String(node.attributes?.lang ?? node.attributes?.language ?? "text");
|
|
647
|
+
node.children = void 0;
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
|
|
580
651
|
// src/extensions/code.tsx
|
|
581
652
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
582
653
|
var cache = new ResourceCache(96);
|
|
@@ -606,9 +677,10 @@ function codeHighlight(options = {}) {
|
|
|
606
677
|
return () => observer.disconnect();
|
|
607
678
|
}, [visible, runtime]);
|
|
608
679
|
useEffect(() => {
|
|
609
|
-
if (!visible || code.length > (options.maxLength ?? 1e5)) return;
|
|
680
|
+
if (!visible || pending || code.length > (options.maxLength ?? 1e5)) return;
|
|
610
681
|
let disposed = false;
|
|
611
682
|
let release;
|
|
683
|
+
let waiting;
|
|
612
684
|
const timer = setTimeout(() => {
|
|
613
685
|
if (normalized === "text" || options.languages && !options.languages.includes(normalized)) return;
|
|
614
686
|
const request = cache.acquire(JSON.stringify([code, normalized, options.lightTheme, options.darkTheme]), async () => {
|
|
@@ -630,14 +702,31 @@ function codeHighlight(options = {}) {
|
|
|
630
702
|
});
|
|
631
703
|
release = request.release;
|
|
632
704
|
request.promise.then((tokens2) => {
|
|
633
|
-
|
|
705
|
+
const apply = () => {
|
|
706
|
+
if (disposed) return;
|
|
707
|
+
const selection = ref.current?.ownerDocument.getSelection();
|
|
708
|
+
if (selection && !selection.isCollapsed && selection.rangeCount && ref.current && selection.getRangeAt(0).intersectsNode(ref.current)) {
|
|
709
|
+
if (!waiting) {
|
|
710
|
+
waiting = apply;
|
|
711
|
+
document.addEventListener("selectionchange", waiting);
|
|
712
|
+
}
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (waiting) {
|
|
716
|
+
document.removeEventListener("selectionchange", waiting);
|
|
717
|
+
waiting = void 0;
|
|
718
|
+
}
|
|
719
|
+
setResult({ code, tokens: tokens2 });
|
|
720
|
+
};
|
|
721
|
+
apply();
|
|
634
722
|
}).catch(() => {
|
|
635
723
|
});
|
|
636
|
-
},
|
|
724
|
+
}, 0);
|
|
637
725
|
return () => {
|
|
638
726
|
disposed = true;
|
|
639
727
|
clearTimeout(timer);
|
|
640
728
|
release?.();
|
|
729
|
+
if (waiting) document.removeEventListener("selectionchange", waiting);
|
|
641
730
|
};
|
|
642
731
|
}, [code, normalized, pending, visible]);
|
|
643
732
|
const tokens = result?.code === code ? result.tokens : void 0;
|
|
@@ -649,29 +738,29 @@ function codeHighlight(options = {}) {
|
|
|
649
738
|
/* @__PURE__ */ jsx("pre", { className: tokens?.length ? "shiki" : void 0, children: /* @__PURE__ */ jsx("code", { children: renderValue(tokens) }) })
|
|
650
739
|
] });
|
|
651
740
|
}
|
|
652
|
-
return { name: "code-highlight", scope: "local", components: { code: CodeNode } };
|
|
741
|
+
return { name: "code-highlight", directives: ["code", "code-highlight"], literal: true, scope: "local", components: { code: CodeNode }, transform: (root, context) => literalDirective(root, context.source, "code", ["code", "code-highlight"]) };
|
|
653
742
|
}
|
|
654
743
|
|
|
655
744
|
// src/extensions/annotations.tsx
|
|
656
|
-
import { useMemo as useMemo2, useRef as
|
|
745
|
+
import { useMemo as useMemo2, useRef as useRef8 } from "react";
|
|
657
746
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
658
747
|
|
|
659
748
|
// src/react/Markdown.tsx
|
|
660
|
-
import { useContext, useEffect as
|
|
749
|
+
import { useContext, useEffect as useEffect5, useRef as useRef6 } from "react";
|
|
661
750
|
|
|
662
751
|
// src/react/render.tsx
|
|
663
|
-
import { cloneElement, Component, createElement, Fragment, isValidElement, memo, useCallback, useMemo, useRef as
|
|
752
|
+
import { cloneElement, Component as Component2, createElement, Fragment, isValidElement, memo, useCallback as useCallback2, useMemo, useRef as useRef4 } from "react";
|
|
664
753
|
|
|
665
754
|
// src/react/text-binding.ts
|
|
666
755
|
var atomic = /* @__PURE__ */ new Set(["inlineCode", "code", "math", "inlineMath", "image", "imageReference", "html"]);
|
|
667
756
|
var hidden = /* @__PURE__ */ new Set(["definition", "footnoteDefinition", "annotationDefinition", "footnoteReference"]);
|
|
668
757
|
var ordinary = /* @__PURE__ */ new Set(["text", "paragraph", "heading", "strong", "emphasis", "delete", "blockquote", "list", "listItem", "link", "linkReference", "table", "tableRow", "tableCell", "thematicBreak", "break", "annotationReference"]);
|
|
669
|
-
function compactTextNodes(node, components) {
|
|
758
|
+
function compactTextNodes(node, components, overrides) {
|
|
670
759
|
const texts = [];
|
|
671
760
|
let supported = true;
|
|
672
761
|
const visit = (node2) => {
|
|
673
762
|
if (node2.selection === "atomic" || atomic.has(node2.type) || hidden.has(node2.type)) return;
|
|
674
|
-
if (!ordinary.has(node2.type) || components[node2.type]) {
|
|
763
|
+
if (!ordinary.has(node2.type) || components[node2.type] || overrides?.has(node2.type)) {
|
|
675
764
|
supported = false;
|
|
676
765
|
return;
|
|
677
766
|
}
|
|
@@ -753,8 +842,182 @@ function bindCompactText(element, nodes, runtime) {
|
|
|
753
842
|
return clear;
|
|
754
843
|
}
|
|
755
844
|
|
|
845
|
+
// src/react/stream-text.tsx
|
|
846
|
+
import { useCallback, useEffect as useEffect2, useRef as useRef3 } from "react";
|
|
847
|
+
|
|
848
|
+
// src/react/stream-effect.tsx
|
|
849
|
+
import { useRef as useRef2 } from "react";
|
|
850
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
851
|
+
var defaultStreamEffect = {
|
|
852
|
+
keyframes: [{ opacity: 0 }, { opacity: 1 }],
|
|
853
|
+
timing: { duration: 420, easing: "cubic-bezier(.16,1,.3,1)" }
|
|
854
|
+
};
|
|
855
|
+
function streamEffect(runtime) {
|
|
856
|
+
const config = runtime.configuration.get();
|
|
857
|
+
if (config.streamEffect !== void 0) return config.streamEffect;
|
|
858
|
+
let effect = defaultStreamEffect;
|
|
859
|
+
for (const extension of config.extensions ?? []) if (extension.streaming?.effect !== void 0) effect = extension.streaming.effect;
|
|
860
|
+
return effect;
|
|
861
|
+
}
|
|
862
|
+
function animateStream(element, effect) {
|
|
863
|
+
if (effect === false || !element.animate || matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
864
|
+
return element.animate(effect.keyframes ?? defaultStreamEffect.keyframes, { ...defaultStreamEffect.timing, ...effect.timing });
|
|
865
|
+
}
|
|
866
|
+
function useStreamEntrance(ref, enabled, state = true, contents = false) {
|
|
867
|
+
const runtime = useRuntime();
|
|
868
|
+
useIsomorphicLayoutEffect(() => {
|
|
869
|
+
const host = ref.current;
|
|
870
|
+
const target = contents ? host?.firstElementChild : host;
|
|
871
|
+
if (!enabled || !target) return;
|
|
872
|
+
const effect = streamEffect(runtime);
|
|
873
|
+
const classes = effect && effect.className?.split(/\s+/).filter(Boolean);
|
|
874
|
+
if (classes) target.classList.add(...classes);
|
|
875
|
+
target.dataset.limrEntrance = "";
|
|
876
|
+
const animation = animateStream(target, effect);
|
|
877
|
+
return () => {
|
|
878
|
+
animation?.cancel();
|
|
879
|
+
if (classes) target.classList.remove(...classes);
|
|
880
|
+
};
|
|
881
|
+
}, [runtime, enabled, state]);
|
|
882
|
+
}
|
|
883
|
+
function StreamEntrance({ children, state }) {
|
|
884
|
+
const ref = useRef2(null);
|
|
885
|
+
useStreamEntrance(ref, true, state, true);
|
|
886
|
+
return /* @__PURE__ */ jsx2("div", { ref, className: "limr-stream-block", children });
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
// src/react/stream-text.tsx
|
|
890
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
891
|
+
function StreamText({ value, animateInitial = true }) {
|
|
892
|
+
const runtime = useRuntime();
|
|
893
|
+
const initial = useRef3(value), previous = useRef3(value);
|
|
894
|
+
const element = useRef3(null);
|
|
895
|
+
const animations = useRef3(/* @__PURE__ */ new Set());
|
|
896
|
+
const waiting = useRef3(false);
|
|
897
|
+
const mounted = useRef3(false);
|
|
898
|
+
const compact = useCallback(() => {
|
|
899
|
+
const host = element.current;
|
|
900
|
+
if (!host) return;
|
|
901
|
+
const selection = host.ownerDocument.getSelection();
|
|
902
|
+
if (selection && !selection.isCollapsed && selection.rangeCount && selection.getRangeAt(0).intersectsNode(host)) {
|
|
903
|
+
if (!waiting.current) {
|
|
904
|
+
host.ownerDocument.addEventListener("selectionchange", compact);
|
|
905
|
+
waiting.current = true;
|
|
906
|
+
}
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
if (waiting.current) {
|
|
910
|
+
host.ownerDocument.removeEventListener("selectionchange", compact);
|
|
911
|
+
waiting.current = false;
|
|
912
|
+
}
|
|
913
|
+
for (const span of host.querySelectorAll("[data-limr-increment-done]")) span.replaceWith(...span.childNodes);
|
|
914
|
+
host.normalize();
|
|
915
|
+
}, []);
|
|
916
|
+
useIsomorphicLayoutEffect(() => {
|
|
917
|
+
const host = element.current;
|
|
918
|
+
if (!host) return;
|
|
919
|
+
const effect = streamEffect(runtime);
|
|
920
|
+
const animate = (element2) => {
|
|
921
|
+
const animation = animateStream(element2, effect);
|
|
922
|
+
if (!animation) return;
|
|
923
|
+
animations.current.add(animation);
|
|
924
|
+
void animation.finished.then(() => {
|
|
925
|
+
animations.current.delete(animation);
|
|
926
|
+
if (element2.hasAttribute("data-limr-increment")) element2.dataset.limrIncrementDone = "";
|
|
927
|
+
compact();
|
|
928
|
+
}, () => animations.current.delete(animation));
|
|
929
|
+
};
|
|
930
|
+
if (!mounted.current) {
|
|
931
|
+
mounted.current = true;
|
|
932
|
+
if (animateInitial && value && runtime.document.getSnapshot().streaming) animate(host);
|
|
933
|
+
}
|
|
934
|
+
if (value === previous.current) return;
|
|
935
|
+
let from = previous.current.length;
|
|
936
|
+
if (!value.startsWith(previous.current)) {
|
|
937
|
+
for (const animation of animations.current) animation.cancel();
|
|
938
|
+
animations.current.clear();
|
|
939
|
+
for (const span of host.querySelectorAll("[data-limr-increment]")) span.dataset.limrIncrementDone = "";
|
|
940
|
+
from = 0;
|
|
941
|
+
while (from < Math.min(previous.current.length, value.length) && previous.current[from] === value[from]) from++;
|
|
942
|
+
const walker = host.ownerDocument.createTreeWalker(host, NodeFilter.SHOW_TEXT);
|
|
943
|
+
const texts = [];
|
|
944
|
+
for (let node = walker.nextNode(); node; node = walker.nextNode()) texts.push(node);
|
|
945
|
+
let at = 0;
|
|
946
|
+
for (const text of texts) {
|
|
947
|
+
const size = text.length;
|
|
948
|
+
if (at >= from) text.remove();
|
|
949
|
+
else if (at + size > from) text.deleteData(from - at, size);
|
|
950
|
+
at += size;
|
|
951
|
+
}
|
|
952
|
+
for (const span of host.querySelectorAll("[data-limr-increment]")) if (!span.textContent) span.remove();
|
|
953
|
+
}
|
|
954
|
+
const addition = value.slice(from);
|
|
955
|
+
if (addition) {
|
|
956
|
+
if (effect === false || !host.animate || matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
|
957
|
+
const tail = host.lastChild;
|
|
958
|
+
if (tail?.nodeType === Node.TEXT_NODE) tail.appendData(addition);
|
|
959
|
+
else host.append(host.ownerDocument.createTextNode(addition));
|
|
960
|
+
} else {
|
|
961
|
+
const span = host.ownerDocument.createElement("span");
|
|
962
|
+
span.dataset.limrIncrement = "";
|
|
963
|
+
span.className = `limr-stream-increment ${effect.className ?? ""}`;
|
|
964
|
+
span.textContent = addition;
|
|
965
|
+
host.append(span);
|
|
966
|
+
animate(span);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
previous.current = value;
|
|
970
|
+
}, [value, runtime]);
|
|
971
|
+
useEffect2(() => {
|
|
972
|
+
const document2 = element.current?.ownerDocument;
|
|
973
|
+
return () => {
|
|
974
|
+
document2?.removeEventListener("selectionchange", compact);
|
|
975
|
+
for (const animation of animations.current) animation.cancel();
|
|
976
|
+
animations.current.clear();
|
|
977
|
+
};
|
|
978
|
+
}, []);
|
|
979
|
+
return /* @__PURE__ */ jsx3("span", { ref: element, "data-limr-stream-text": "", children: initial.current });
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// src/react/knuth-plass-boundary.tsx
|
|
983
|
+
import { Component } from "react";
|
|
984
|
+
var implementation;
|
|
985
|
+
var KnuthPlassBoundary = class extends Component {
|
|
986
|
+
release;
|
|
987
|
+
version = 0;
|
|
988
|
+
start() {
|
|
989
|
+
const version = ++this.version;
|
|
990
|
+
if (!this.props.enabled || this.props.pending) return;
|
|
991
|
+
implementation ??= import("./knuth-plass-layout-CHQCWKB5.js");
|
|
992
|
+
void implementation.then((module) => {
|
|
993
|
+
if (version !== this.version) return;
|
|
994
|
+
const root = this.props.element();
|
|
995
|
+
if (root) this.release = module.typeset(root, this.props.runtime, this.props.options);
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
componentDidMount() {
|
|
999
|
+
this.start();
|
|
1000
|
+
}
|
|
1001
|
+
getSnapshotBeforeUpdate() {
|
|
1002
|
+
this.version++;
|
|
1003
|
+
this.release?.();
|
|
1004
|
+
this.release = void 0;
|
|
1005
|
+
return null;
|
|
1006
|
+
}
|
|
1007
|
+
componentDidUpdate() {
|
|
1008
|
+
this.start();
|
|
1009
|
+
}
|
|
1010
|
+
componentWillUnmount() {
|
|
1011
|
+
this.version++;
|
|
1012
|
+
this.release?.();
|
|
1013
|
+
}
|
|
1014
|
+
render() {
|
|
1015
|
+
return this.props.children;
|
|
1016
|
+
}
|
|
1017
|
+
};
|
|
1018
|
+
|
|
756
1019
|
// src/react/render.tsx
|
|
757
|
-
import { Fragment as Fragment2, jsx as
|
|
1020
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
758
1021
|
var blockAttributes = (block) => block ? { "data-limr-block": block.id, "data-source-start": block.range.start, "data-source-end": block.range.end, "data-pending": block.pending || void 0 } : {};
|
|
759
1022
|
function AnnotationMarker({ occurrence }) {
|
|
760
1023
|
const runtime = useRuntime();
|
|
@@ -762,10 +1025,10 @@ function AnnotationMarker({ occurrence }) {
|
|
|
762
1025
|
const active = useStoreSelector(runtime.interaction, (state) => state.active === occurrence.id);
|
|
763
1026
|
const hovered = useStoreSelector(runtime.interaction, (state) => state.hovered === occurrence.id);
|
|
764
1027
|
const definition2 = useStoreSelector(runtime.configuration, () => runtime.annotationTypes.get(annotation?.type ?? "citation"));
|
|
765
|
-
const
|
|
1028
|
+
const Icon2 = definition2?.icon;
|
|
766
1029
|
const Custom = definition2?.Marker;
|
|
767
|
-
const icon = typeof
|
|
768
|
-
return /* @__PURE__ */
|
|
1030
|
+
const icon = typeof Icon2 === "function" || Icon2 && typeof Icon2 === "object" && !isValidElement(Icon2) && "$$typeof" in Icon2 ? createElement(Icon2) : Icon2;
|
|
1031
|
+
return /* @__PURE__ */ jsx4("span", { className: "limr-mark-wrap", "data-limr-ignore": "true", "data-limr-marker": occurrence.id, "data-source-start": occurrence.range.start, "data-source-end": occurrence.range.end, children: /* @__PURE__ */ jsxs2(
|
|
769
1032
|
"button",
|
|
770
1033
|
{
|
|
771
1034
|
type: "button",
|
|
@@ -795,8 +1058,8 @@ function AnnotationMarker({ occurrence }) {
|
|
|
795
1058
|
if (hovering) runtime.hover(occurrence.id);
|
|
796
1059
|
},
|
|
797
1060
|
children: [
|
|
798
|
-
/* @__PURE__ */
|
|
799
|
-
occurrence.annotationIds.length > 1 && /* @__PURE__ */
|
|
1061
|
+
/* @__PURE__ */ jsx4("span", { className: "limr-mark-icon", children: Custom && annotation ? /* @__PURE__ */ jsx4(Custom, { annotation, active }) : icon ?? "\u2022" }),
|
|
1062
|
+
occurrence.annotationIds.length > 1 && /* @__PURE__ */ jsx4("span", { className: "limr-mark-count", children: occurrence.annotationIds.length })
|
|
800
1063
|
]
|
|
801
1064
|
}
|
|
802
1065
|
) });
|
|
@@ -810,7 +1073,7 @@ function Text({ node, context, mapping: literalMapping, marks: literalMarks, sty
|
|
|
810
1073
|
let mapping2;
|
|
811
1074
|
const raw = source.slice(range.start, range.end);
|
|
812
1075
|
return () => {
|
|
813
|
-
if (literalMapping) return literalMapping;
|
|
1076
|
+
if (literalMapping) return typeof literalMapping === "function" ? literalMapping() : literalMapping;
|
|
814
1077
|
if (!mapping2) {
|
|
815
1078
|
const relative = mapText(raw, value, { start: 0, end: raw.length }, { escapes: node.verbatimEscapes !== true });
|
|
816
1079
|
mapping2 = { starts: relative.starts.map((offset) => offset + range.start), ends: relative.ends.map((offset) => offset + range.start), exact: relative.exact };
|
|
@@ -822,7 +1085,7 @@ function Text({ node, context, mapping: literalMapping, marks: literalMarks, sty
|
|
|
822
1085
|
const highlights = context.highlights.filter((highlight) => intersects(highlight.range, range));
|
|
823
1086
|
if (!marks.length && !highlights.length) {
|
|
824
1087
|
const direct = !literalMapping && source.slice(range.start, range.end) === value;
|
|
825
|
-
return /* @__PURE__ */
|
|
1088
|
+
return /* @__PURE__ */ jsx4("span", { style, className, "data-limr-text": "", "data-source-start": range.start, "data-source-end": range.end, ref: (element) => {
|
|
826
1089
|
if (element) runtime.bindings.set(element, {
|
|
827
1090
|
range,
|
|
828
1091
|
atomic: false,
|
|
@@ -831,7 +1094,7 @@ function Text({ node, context, mapping: literalMapping, marks: literalMarks, sty
|
|
|
831
1094
|
},
|
|
832
1095
|
resolve: (offset, edge) => direct ? Math.max(range.start, Math.min(range.end, range.start + offset)) : edge === "start" ? mapped().starts[offset] ?? range.end : mapped().ends[offset - 1] ?? range.start
|
|
833
1096
|
});
|
|
834
|
-
}, children: value });
|
|
1097
|
+
}, children: context.live ? /* @__PURE__ */ jsx4(StreamText, { value, animateInitial: range.end > context.revealFrom }) : value });
|
|
835
1098
|
}
|
|
836
1099
|
const mapping = mapped();
|
|
837
1100
|
const markerAt = /* @__PURE__ */ new Map();
|
|
@@ -849,12 +1112,12 @@ function Text({ node, context, mapping: literalMapping, marks: literalMarks, sty
|
|
|
849
1112
|
boundaries.add(end < 0 ? value.length : end);
|
|
850
1113
|
}
|
|
851
1114
|
const points = [...boundaries].sort((a, b) => a - b);
|
|
852
|
-
return /* @__PURE__ */
|
|
1115
|
+
return /* @__PURE__ */ jsx4(Fragment2, { children: points.slice(1).map((end, index) => {
|
|
853
1116
|
const start = points[index];
|
|
854
1117
|
const segmentRange = { start: mapping.starts[start] ?? range.start, end: mapping.ends[end - 1] ?? range.end };
|
|
855
1118
|
const styles = highlights.filter((highlight) => intersects(highlight.range, segmentRange));
|
|
856
|
-
let text = value.slice(start, end);
|
|
857
|
-
for (const highlight of styles) text = /* @__PURE__ */
|
|
1119
|
+
let text = context.live ? /* @__PURE__ */ jsx4(StreamText, { value: value.slice(start, end), animateInitial: segmentRange.end > context.revealFrom }) : value.slice(start, end);
|
|
1120
|
+
for (const highlight of styles) text = /* @__PURE__ */ jsx4("mark", { "data-limr-highlight": highlight.id, "data-hidden": highlight.hidden || void 0, className: `limr-highlight limr-highlight-${highlight.style ?? "background"}`, style: { "--limr-highlight": highlight.color ?? "#f3ce7380" }, children: text }, highlight.id);
|
|
858
1121
|
return /* @__PURE__ */ jsxs2("span", { style, className, ref: (element) => {
|
|
859
1122
|
if (element) runtime.bindings.set(element, { range: segmentRange, atomic: false, exact: mapping.exact, resolve: (offset, edge) => {
|
|
860
1123
|
const at = Math.max(start, Math.min(end, start + offset));
|
|
@@ -862,22 +1125,27 @@ function Text({ node, context, mapping: literalMapping, marks: literalMarks, sty
|
|
|
862
1125
|
} });
|
|
863
1126
|
}, "data-limr-text": "", "data-source-start": segmentRange.start, "data-source-end": segmentRange.end, children: [
|
|
864
1127
|
text,
|
|
865
|
-
markerAt.get(end)?.map((occurrence) => /* @__PURE__ */
|
|
1128
|
+
markerAt.get(end)?.map((occurrence) => /* @__PURE__ */ jsx4(AnnotationMarker, { occurrence }, occurrence.id))
|
|
866
1129
|
] }, start);
|
|
867
1130
|
}) });
|
|
868
1131
|
}
|
|
869
1132
|
function LiteralValue({ node, context, tokens }) {
|
|
870
1133
|
const source = context.runtime.document.getSnapshot().source;
|
|
871
|
-
const
|
|
1134
|
+
const mapped = useMemo(() => {
|
|
1135
|
+
let value2;
|
|
1136
|
+
return () => value2 ??= mapLiteral(source, node);
|
|
1137
|
+
}, [node]);
|
|
872
1138
|
const value = literalValue(node);
|
|
873
1139
|
const marks = context.marks.get(node) ?? emptyList;
|
|
1140
|
+
if (!tokens?.length) return /* @__PURE__ */ jsx4(Text, { node: { ...node, type: "text", value }, context, mapping: mapped, marks }, 0);
|
|
1141
|
+
const mapping = mapped();
|
|
874
1142
|
const segments = tokens?.length ? tokens : [{ content: value, offset: 0 }];
|
|
875
|
-
return /* @__PURE__ */
|
|
1143
|
+
return /* @__PURE__ */ jsx4(Fragment2, { children: segments.map((token, index) => {
|
|
876
1144
|
const start = token.offset, end = start + token.content.length;
|
|
877
|
-
const
|
|
878
|
-
const range = { start:
|
|
1145
|
+
const mapped2 = { starts: mapping.starts.slice(start, end), ends: mapping.ends.slice(start, end), exact: mapping.exact };
|
|
1146
|
+
const range = { start: mapped2.starts[0] ?? rangeOf(node).start, end: mapped2.ends.at(-1) ?? rangeOf(node).end };
|
|
879
1147
|
const leaf = { type: "text", value: token.content, position: { start: { offset: range.start, line: 0, column: 0 }, end: { offset: range.end, line: 0, column: 0 } } };
|
|
880
|
-
return /* @__PURE__ */
|
|
1148
|
+
return /* @__PURE__ */ jsx4(Text, { className: token.style ? "limr-code-token" : void 0, style: token.style, node: leaf, context, mapping: mapped2, marks: marks.filter((mark) => mark.range.end > range.start && mark.range.end <= range.end) }, index);
|
|
881
1149
|
}) });
|
|
882
1150
|
}
|
|
883
1151
|
function Atomic({ node, context, children, inline, blockElement }) {
|
|
@@ -888,7 +1156,7 @@ function Atomic({ node, context, children, inline, blockElement }) {
|
|
|
888
1156
|
const image = ["image", "imageReference"].includes(node.type) || node.type === "component" && node.name === "img";
|
|
889
1157
|
const corner = image || !inline;
|
|
890
1158
|
const marks = [...context.marks.get(node) ?? [], ...corner ? context.afterMarks.get(node) ?? [] : []];
|
|
891
|
-
const markers = marks.map((occurrence) => /* @__PURE__ */
|
|
1159
|
+
const markers = marks.map((occurrence) => /* @__PURE__ */ jsx4(AnnotationMarker, { occurrence }, occurrence.id));
|
|
892
1160
|
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
893
1161
|
/* @__PURE__ */ jsxs2(
|
|
894
1162
|
Tag,
|
|
@@ -907,7 +1175,7 @@ function Atomic({ node, context, children, inline, blockElement }) {
|
|
|
907
1175
|
},
|
|
908
1176
|
children: [
|
|
909
1177
|
children,
|
|
910
|
-
corner && !!marks.length && /* @__PURE__ */
|
|
1178
|
+
corner && !!marks.length && /* @__PURE__ */ jsx4("span", { className: "limr-corner-marks", "data-limr-ignore": "true", children: markers })
|
|
911
1179
|
]
|
|
912
1180
|
}
|
|
913
1181
|
),
|
|
@@ -933,16 +1201,16 @@ function HeadingNode({ node, children, runtime, blockElement }) {
|
|
|
933
1201
|
}
|
|
934
1202
|
function Reference({ node, children, image }) {
|
|
935
1203
|
const definition2 = useDocumentSelector((doc) => doc.definitions.get(String(node.identifier)));
|
|
936
|
-
if (!definition2) return /* @__PURE__ */
|
|
937
|
-
return image ? /* @__PURE__ */
|
|
1204
|
+
if (!definition2) return /* @__PURE__ */ jsx4(Fragment2, { children: children || String(node.alt ?? node.label ?? "") });
|
|
1205
|
+
return image ? /* @__PURE__ */ jsx4("img", { src: safeUrl(definition2.url, true), alt: String(node.alt ?? ""), title: definition2.title ? String(definition2.title) : void 0, loading: "lazy", decoding: "async" }) : /* @__PURE__ */ jsx4("a", { href: safeUrl(definition2.url), title: definition2.title ? String(definition2.title) : void 0, children });
|
|
938
1206
|
}
|
|
939
1207
|
function FootnoteReference({ node }) {
|
|
940
1208
|
const runtime = useRuntime();
|
|
941
1209
|
const identifier2 = String(node.identifier);
|
|
942
1210
|
const number = useDocumentSelector((doc) => doc.footnoteOrder.indexOf(identifier2) + 1);
|
|
943
|
-
return /* @__PURE__ */
|
|
1211
|
+
return /* @__PURE__ */ jsx4("sup", { "data-limr-ignore": "true", children: /* @__PURE__ */ jsx4("a", { href: `#${runtime.document.id}-fn-${encodeURIComponent(identifier2)}`, id: `${runtime.document.id}-fnref-${rangeOf(node).start}`, "aria-label": `Footnote ${number}`, children: number }) });
|
|
944
1212
|
}
|
|
945
|
-
var ExtensionBoundary = class extends
|
|
1213
|
+
var ExtensionBoundary = class extends Component2 {
|
|
946
1214
|
state = { failed: false };
|
|
947
1215
|
static getDerivedStateFromError() {
|
|
948
1216
|
return { failed: true };
|
|
@@ -953,7 +1221,7 @@ var ExtensionBoundary = class extends Component {
|
|
|
953
1221
|
if (this.state.failed && previous.fallback !== this.props.fallback) this.setState({ failed: false });
|
|
954
1222
|
}
|
|
955
1223
|
render() {
|
|
956
|
-
return this.state.failed ? /* @__PURE__ */
|
|
1224
|
+
return this.state.failed ? /* @__PURE__ */ jsx4("pre", { className: "limr-extension-error", children: this.props.fallback }) : this.props.children;
|
|
957
1225
|
}
|
|
958
1226
|
};
|
|
959
1227
|
function containsBlock(node) {
|
|
@@ -961,20 +1229,26 @@ function containsBlock(node) {
|
|
|
961
1229
|
}
|
|
962
1230
|
function renderNode(node, context, index = 0, trailing) {
|
|
963
1231
|
const { runtime } = context;
|
|
964
|
-
if (node.type === "text" && context.compact) return node.value ?? "";
|
|
1232
|
+
if (node.type === "text" && context.compact) return context.live ? /* @__PURE__ */ jsx4(StreamText, { value: node.value ?? "", animateInitial: rangeOf(node).end > context.revealFrom }, `text-${node.position?.start.offset ?? index}`) : node.value ?? "";
|
|
1233
|
+
if (node.type === "streamPending") return null;
|
|
965
1234
|
const blockElement = node === context.block.node ? context.blockElement : void 0;
|
|
966
1235
|
const key = `${node.type}-${node.position?.start.offset ?? index}-${index}`;
|
|
967
|
-
|
|
1236
|
+
let childContext = node.type === "list" ? { ...context, tightList: !node.spread } : context;
|
|
1237
|
+
if (runtime.rendererOverrides.size) childContext = { ...childContext, ancestors: [...context.ancestors ?? [], node] };
|
|
968
1238
|
const renderChildren = (nodes, options) => {
|
|
969
1239
|
let last = -1;
|
|
970
1240
|
nodes.forEach((child, i) => {
|
|
971
1241
|
if (!["definition", "footnoteDefinition", "annotationDefinition"].includes(child.type)) last = i;
|
|
972
1242
|
});
|
|
973
|
-
if (last < 0 && options?.trailing) return [/* @__PURE__ */
|
|
1243
|
+
if (last < 0 && options?.trailing) return [/* @__PURE__ */ jsx4(Fragment, { children: options.trailing }, "trailing")];
|
|
974
1244
|
return nodes.map((child, i) => renderNode(child, childContext, i, i === last ? options?.trailing : void 0));
|
|
975
1245
|
};
|
|
976
1246
|
const children = node.type === "table" ? [] : node.type === "listItem" && context.tightList ? (node.children ?? []).flatMap((child, index2) => child.type === "paragraph" ? renderChildren(child.children ?? []) : renderNode(child, context, index2)) : renderChildren(node.children ?? []);
|
|
977
|
-
const
|
|
1247
|
+
const componentName = node.type === "component" ? node.name ?? "" : node.type;
|
|
1248
|
+
const rules = runtime.rendererOverrides.get(componentName);
|
|
1249
|
+
const override = rules?.slice().reverse().find((rule) => !rule.when || rule.when(node, { pending: context.block.pending, incomplete: !!node.incomplete, ancestors: context.ancestors ?? [] }));
|
|
1250
|
+
const owner = node.incomplete && !override ? runtime.configuration.get().extensions?.slice().reverse().find((extension) => extension.components?.[componentName]) : void 0;
|
|
1251
|
+
const Renderer = override?.component ?? (node.incomplete && owner?.streaming?.Loading || runtime.components[componentName]);
|
|
978
1252
|
let element;
|
|
979
1253
|
if (Renderer) {
|
|
980
1254
|
const range = rangeOf(node);
|
|
@@ -982,14 +1256,14 @@ function renderNode(node, context, index = 0, trailing) {
|
|
|
982
1256
|
const attribute = node.attributeNodes?.[name];
|
|
983
1257
|
if (!attribute) return String(node.attributes?.[name] ?? "");
|
|
984
1258
|
const range2 = rangeOf(attribute);
|
|
985
|
-
return /* @__PURE__ */
|
|
1259
|
+
return /* @__PURE__ */ jsx4(Text, { node: attribute, context, marks: context.occurrences.filter((item) => item.range.end > range2.start && item.range.end <= range2.end) });
|
|
986
1260
|
};
|
|
987
|
-
element = /* @__PURE__ */
|
|
1261
|
+
element = /* @__PURE__ */ jsx4(ExtensionBoundary, { fallback: runtime.document.getSnapshot().source.slice(range.start, range.end), children: /* @__PURE__ */ jsx4(Renderer, { node, children, pending: context.block.pending, incomplete: !!node.incomplete, source: runtime.document.getSnapshot().source.slice(range.start, range.end), renderChildren, renderValue: (tokens) => /* @__PURE__ */ jsx4(LiteralValue, { node, context, tokens }), renderAttribute }) }, key);
|
|
988
1262
|
} else {
|
|
989
1263
|
switch (node.type) {
|
|
990
1264
|
case "text":
|
|
991
1265
|
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
992
|
-
context.compact ? node.value ?? "" : /* @__PURE__ */
|
|
1266
|
+
context.compact ? node.value ?? "" : /* @__PURE__ */ jsx4(Text, { node, context }),
|
|
993
1267
|
trailing
|
|
994
1268
|
] }, key);
|
|
995
1269
|
case "paragraph":
|
|
@@ -1008,62 +1282,62 @@ function renderNode(node, context, index = 0, trailing) {
|
|
|
1008
1282
|
trailing
|
|
1009
1283
|
] }, key);
|
|
1010
1284
|
case "strong":
|
|
1011
|
-
element = /* @__PURE__ */
|
|
1285
|
+
element = /* @__PURE__ */ jsx4("strong", { children });
|
|
1012
1286
|
break;
|
|
1013
1287
|
case "emphasis":
|
|
1014
|
-
element = /* @__PURE__ */
|
|
1288
|
+
element = /* @__PURE__ */ jsx4("em", { children });
|
|
1015
1289
|
break;
|
|
1016
1290
|
case "delete":
|
|
1017
|
-
element = /* @__PURE__ */
|
|
1291
|
+
element = /* @__PURE__ */ jsx4("del", { children });
|
|
1018
1292
|
break;
|
|
1019
1293
|
case "inlineCode":
|
|
1020
|
-
element = /* @__PURE__ */
|
|
1294
|
+
element = /* @__PURE__ */ jsx4("code", { className: "limr-inline-code", "data-limr-inline-syntax": "", "data-source-start": rangeOf(node).start, "data-source-end": rangeOf(node).end, children: /* @__PURE__ */ jsx4(LiteralValue, { node, context }) });
|
|
1021
1295
|
break;
|
|
1022
1296
|
case "code":
|
|
1023
|
-
element = /* @__PURE__ */
|
|
1297
|
+
element = /* @__PURE__ */ jsx4("pre", { children: /* @__PURE__ */ jsx4("code", { children: /* @__PURE__ */ jsx4(LiteralValue, { node, context }) }) });
|
|
1024
1298
|
break;
|
|
1025
1299
|
case "math":
|
|
1026
1300
|
case "inlineMath":
|
|
1027
|
-
element = /* @__PURE__ */
|
|
1301
|
+
element = /* @__PURE__ */ jsx4("code", { children: node.value });
|
|
1028
1302
|
break;
|
|
1029
1303
|
case "blockquote":
|
|
1030
1304
|
element = /* @__PURE__ */ jsxs2("blockquote", { className: "limr-note", children: [
|
|
1031
|
-
/* @__PURE__ */
|
|
1032
|
-
/* @__PURE__ */
|
|
1305
|
+
/* @__PURE__ */ jsx4("div", { className: "limr-card-label", "data-limr-ignore": "true", children: runtime.locale.note }),
|
|
1306
|
+
/* @__PURE__ */ jsx4("div", { className: "limr-block-content", children })
|
|
1033
1307
|
] });
|
|
1034
1308
|
break;
|
|
1035
1309
|
case "list":
|
|
1036
|
-
element = node.ordered ? /* @__PURE__ */
|
|
1310
|
+
element = node.ordered ? /* @__PURE__ */ jsx4("ol", { start: Number(node.start ?? 1), children }) : /* @__PURE__ */ jsx4("ul", { children });
|
|
1037
1311
|
break;
|
|
1038
1312
|
case "listItem":
|
|
1039
1313
|
element = /* @__PURE__ */ jsxs2("li", { className: typeof node.checked === "boolean" ? "limr-task-item" : void 0, children: [
|
|
1040
|
-
typeof node.checked === "boolean" && /* @__PURE__ */
|
|
1314
|
+
typeof node.checked === "boolean" && /* @__PURE__ */ jsx4("input", { type: "checkbox", checked: node.checked, disabled: true, "aria-label": "Task" }),
|
|
1041
1315
|
children
|
|
1042
1316
|
] });
|
|
1043
1317
|
break;
|
|
1044
1318
|
case "link":
|
|
1045
|
-
element = /* @__PURE__ */
|
|
1319
|
+
element = /* @__PURE__ */ jsx4("a", { href: safeUrl(node.url), title: node.title ? String(node.title) : void 0, children });
|
|
1046
1320
|
break;
|
|
1047
1321
|
case "image":
|
|
1048
|
-
element = /* @__PURE__ */
|
|
1322
|
+
element = /* @__PURE__ */ jsx4("img", { src: safeUrl(node.url, true), alt: String(node.alt ?? ""), title: node.title ? String(node.title) : void 0, loading: "lazy", decoding: "async" });
|
|
1049
1323
|
break;
|
|
1050
1324
|
case "linkReference":
|
|
1051
|
-
element = /* @__PURE__ */
|
|
1325
|
+
element = /* @__PURE__ */ jsx4(Reference, { node, image: false, children });
|
|
1052
1326
|
break;
|
|
1053
1327
|
case "imageReference":
|
|
1054
|
-
element = /* @__PURE__ */
|
|
1328
|
+
element = /* @__PURE__ */ jsx4(Reference, { node, image: true, children });
|
|
1055
1329
|
break;
|
|
1056
1330
|
case "thematicBreak":
|
|
1057
|
-
element = /* @__PURE__ */
|
|
1331
|
+
element = /* @__PURE__ */ jsx4("hr", {});
|
|
1058
1332
|
break;
|
|
1059
1333
|
case "break":
|
|
1060
|
-
element = /* @__PURE__ */
|
|
1334
|
+
element = /* @__PURE__ */ jsx4("br", { "data-limr-break": "", "data-source-start": rangeOf(node).start, "data-source-end": rangeOf(node).end });
|
|
1061
1335
|
break;
|
|
1062
1336
|
case "table": {
|
|
1063
1337
|
const rows = node.children ?? [], alignment = node.align;
|
|
1064
|
-
element = /* @__PURE__ */
|
|
1065
|
-
/* @__PURE__ */
|
|
1066
|
-
/* @__PURE__ */
|
|
1338
|
+
element = /* @__PURE__ */ jsx4("div", { className: "limr-table-scroll", children: /* @__PURE__ */ jsxs2("table", { children: [
|
|
1339
|
+
/* @__PURE__ */ jsx4("thead", { children: rows.slice(0, 1).map((row, i) => /* @__PURE__ */ jsx4("tr", { children: row.children?.map((cell, j) => /* @__PURE__ */ jsx4("th", { style: { textAlign: alignment?.[j] }, children: renderChildren(cell.children ?? []) }, j)) }, i)) }),
|
|
1340
|
+
/* @__PURE__ */ jsx4("tbody", { children: rows.slice(1).map((row, i) => /* @__PURE__ */ jsx4("tr", { children: row.children?.map((cell, j) => /* @__PURE__ */ jsx4("td", { style: { textAlign: alignment?.[j] }, children: renderChildren(cell.children ?? []) }, j)) }, i)) })
|
|
1067
1341
|
] }) });
|
|
1068
1342
|
break;
|
|
1069
1343
|
}
|
|
@@ -1073,19 +1347,19 @@ function renderNode(node, context, index = 0, trailing) {
|
|
|
1073
1347
|
return null;
|
|
1074
1348
|
case "footnoteReference":
|
|
1075
1349
|
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1076
|
-
/* @__PURE__ */
|
|
1350
|
+
/* @__PURE__ */ jsx4(FootnoteReference, { node }),
|
|
1077
1351
|
trailing
|
|
1078
1352
|
] }, key);
|
|
1079
1353
|
case "annotationReference": {
|
|
1080
1354
|
const Tag = node.inline ? "span" : "div";
|
|
1081
1355
|
element = /* @__PURE__ */ jsxs2(Tag, { children: [
|
|
1082
1356
|
children,
|
|
1083
|
-
/* @__PURE__ */
|
|
1357
|
+
/* @__PURE__ */ jsx4(AnnotationMarker, { occurrence: { id: `${runtime.document.id}-ref-${rangeOf(node).start}`, range: rangeOf(node), annotationIds: node.annotationIds, embedded: true } })
|
|
1084
1358
|
] });
|
|
1085
1359
|
break;
|
|
1086
1360
|
}
|
|
1087
1361
|
case "html":
|
|
1088
|
-
element = /* @__PURE__ */
|
|
1362
|
+
element = /* @__PURE__ */ jsx4("span", { className: "limr-literal", children: node.value });
|
|
1089
1363
|
break;
|
|
1090
1364
|
case "component":
|
|
1091
1365
|
element = children;
|
|
@@ -1097,26 +1371,40 @@ function renderNode(node, context, index = 0, trailing) {
|
|
|
1097
1371
|
const atomic2 = node.selection === "atomic" || ["math", "inlineMath", "image", "imageReference", "html"].includes(node.type);
|
|
1098
1372
|
const corner = atomic2 && (!node.inline && !["inlineCode", "inlineMath", "html"].includes(node.type) || ["image", "imageReference"].includes(node.type) || node.name === "img");
|
|
1099
1373
|
const after = corner ? void 0 : context.afterMarks.get(node);
|
|
1100
|
-
const withMarkers = (element2) =>
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1374
|
+
const withMarkers = (element2) => {
|
|
1375
|
+
const result = after?.length || trailing ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1376
|
+
element2,
|
|
1377
|
+
after?.map((occurrence) => /* @__PURE__ */ jsx4(AnnotationMarker, { occurrence }, occurrence.id)),
|
|
1378
|
+
trailing
|
|
1379
|
+
] }, key) : element2;
|
|
1380
|
+
return context.live && !node.inline && (node.type === "component" || ["code", "math", "mermaid", "callout", "blockquote", "table"].includes(node.type)) ? /* @__PURE__ */ jsx4(StreamEntrance, { state: node.type === "component" ? !!node.incomplete : true, children: result }, key) : result;
|
|
1381
|
+
};
|
|
1382
|
+
if (atomic2) return withMarkers(/* @__PURE__ */ jsx4(Atomic, { node, context, blockElement, inline: node.inline || ["inlineCode", "inlineMath", "image", "imageReference", "html"].includes(node.type), children: element }, key));
|
|
1106
1383
|
if (blockElement) {
|
|
1107
1384
|
const attributes = { ...blockAttributes(blockElement), ref: blockElement.ref };
|
|
1108
|
-
return withMarkers(isValidElement(element) && typeof element.type === "string" ? cloneElement(element, { ...attributes, key }) : /* @__PURE__ */
|
|
1385
|
+
return withMarkers(isValidElement(element) && typeof element.type === "string" ? cloneElement(element, { ...attributes, key }) : /* @__PURE__ */ jsx4("div", { ...attributes, children: element }, key));
|
|
1109
1386
|
}
|
|
1110
|
-
return withMarkers(isValidElement(element) ? cloneElement(element, { key }) : /* @__PURE__ */
|
|
1387
|
+
return withMarkers(isValidElement(element) ? cloneElement(element, { key }) : /* @__PURE__ */ jsx4(Fragment, { children: element }, key));
|
|
1111
1388
|
}
|
|
1112
|
-
var BlockView = memo(function BlockView2({ block, runtime, components, extensions, decorations, footnoteId }) {
|
|
1113
|
-
const
|
|
1114
|
-
|
|
1115
|
-
const
|
|
1389
|
+
var BlockView = memo(function BlockView2({ block, runtime, components, extensions, rendererOverrides, decorations, footnoteId }) {
|
|
1390
|
+
const streamed = useRef4(runtime.document.getSnapshot().streaming);
|
|
1391
|
+
if (block.pending) streamed.current = true;
|
|
1392
|
+
const revealed = useRef4(block.range.start);
|
|
1393
|
+
const revealFrom = revealed.current;
|
|
1394
|
+
useIsomorphicLayoutEffect(() => {
|
|
1395
|
+
revealed.current = Math.max(revealed.current, block.range.end);
|
|
1396
|
+
}, [block.range.end]);
|
|
1397
|
+
const element = useRef4(null);
|
|
1398
|
+
const getElement = useCallback2(() => element.current, []);
|
|
1399
|
+
const typography = useStoreSelector(runtime.configuration, (config) => config.typography);
|
|
1400
|
+
const knuthPlass = useStoreSelector(runtime.configuration, (config) => config.knuthPlass);
|
|
1401
|
+
const clearBindings = useRef4(void 0);
|
|
1402
|
+
const { occurrences } = decorations;
|
|
1403
|
+
const highlights = useMemo(() => decorations.highlights.filter((highlight) => !highlight.occurrenceId), [decorations.highlights]);
|
|
1116
1404
|
const root = useMemo(() => footnoteId ? { ...block.node, type: "listItem" } : block.node, [block, footnoteId]);
|
|
1117
|
-
const texts = useMemo(() => compactTextNodes(root, runtime.components), [root, runtime, components, extensions]);
|
|
1118
|
-
const compact = !!texts && !occurrences.length && !highlights.length;
|
|
1119
|
-
const observe =
|
|
1405
|
+
const texts = useMemo(() => compactTextNodes(root, runtime.components, runtime.rendererOverrides), [root, runtime, components, extensions, rendererOverrides]);
|
|
1406
|
+
const compact = typography !== "knuth-plass" && !!texts && !occurrences.length && !highlights.length;
|
|
1407
|
+
const observe = useCallback2((next) => {
|
|
1120
1408
|
clearBindings.current?.();
|
|
1121
1409
|
clearBindings.current = void 0;
|
|
1122
1410
|
if (element.current) runtime.textBinders.delete(element.current);
|
|
@@ -1160,148 +1448,32 @@ var BlockView = memo(function BlockView2({ block, runtime, components, extension
|
|
|
1160
1448
|
return { marks: map, afterMarks: after };
|
|
1161
1449
|
}, [block, occurrences]);
|
|
1162
1450
|
if (!footnoteId && ["definition", "footnoteDefinition", "annotationDefinition"].includes(block.node.type)) return null;
|
|
1163
|
-
const context = { runtime, block, marks, afterMarks, highlights, occurrences, compact, blockElement: { id: block.id, range: block.range, pending: block.pending, ref: observe } };
|
|
1164
|
-
|
|
1165
|
-
return
|
|
1451
|
+
const context = { runtime, block, marks, afterMarks, highlights, occurrences, compact, live: streamed.current, revealFrom, blockElement: { id: block.id, range: block.range, pending: block.pending, ref: observe } };
|
|
1452
|
+
const content = footnoteId ? /* @__PURE__ */ jsx4("li", { id: `${runtime.document.id}-fn-${encodeURIComponent(footnoteId)}`, ...blockAttributes(context.blockElement), ref: observe, children: block.node.children?.map((child, index) => renderNode(child, { ...context, blockElement: void 0 }, index)) }) : renderNode(block.node, context);
|
|
1453
|
+
return /* @__PURE__ */ jsx4(KnuthPlassBoundary, { element: getElement, runtime, enabled: typography === "knuth-plass", pending: block.pending, options: knuthPlass, children: content });
|
|
1166
1454
|
});
|
|
1167
1455
|
function Footnotes() {
|
|
1168
1456
|
const runtime = useRuntime();
|
|
1169
1457
|
const doc = useDocumentSelector((snapshot) => snapshot);
|
|
1170
1458
|
const components = useStoreSelector(runtime.configuration, (config) => config.components);
|
|
1171
1459
|
const extensions = useStoreSelector(runtime.configuration, (config) => config.extensions);
|
|
1460
|
+
const rendererOverrides = useStoreSelector(runtime.configuration, (config) => config.rendererOverrides);
|
|
1172
1461
|
const decorations = useStoreSelector(runtime.decorations, (state) => state.byBlock);
|
|
1173
1462
|
const blocks = useMemo(() => new Map(doc.blocks.filter((block) => block.node.type === "footnoteDefinition").map((block) => [String(block.node.identifier), block])), [doc.blocks]);
|
|
1174
1463
|
if (!doc.footnoteOrder.length) return null;
|
|
1175
1464
|
return /* @__PURE__ */ jsxs2("section", { className: "limr-footnotes", "aria-label": runtime.locale.footnotes, children: [
|
|
1176
|
-
/* @__PURE__ */
|
|
1177
|
-
/* @__PURE__ */
|
|
1465
|
+
/* @__PURE__ */ jsx4("hr", {}),
|
|
1466
|
+
/* @__PURE__ */ jsx4("ol", { children: doc.footnoteOrder.map((id) => {
|
|
1178
1467
|
const node = doc.footnotes.get(id);
|
|
1179
1468
|
if (!node) return null;
|
|
1180
1469
|
const block = blocks.get(id) ?? { id: `${doc.id}-fn-${id}`, range: rangeOf(node), node, pending: false };
|
|
1181
|
-
return /* @__PURE__ */
|
|
1470
|
+
return /* @__PURE__ */ jsx4(BlockView, { block, runtime, components, extensions, rendererOverrides, footnoteId: id, decorations: decorations.get(block.id) ?? emptyDecorations }, id);
|
|
1182
1471
|
}) })
|
|
1183
1472
|
] });
|
|
1184
1473
|
}
|
|
1185
1474
|
|
|
1186
1475
|
// src/react/selection.ts
|
|
1187
|
-
import { useEffect as
|
|
1188
|
-
|
|
1189
|
-
// src/react/source-geometry.ts
|
|
1190
|
-
function flowOf(element, container) {
|
|
1191
|
-
const known = element.closest("pre,p,figcaption,li,th,td,h1,h2,h3,h4,h5,h6,.limr-choice-text,.limr-definition-title,.limr-question-title,.limr-block-content");
|
|
1192
|
-
return known && container.contains(known) ? known : element.closest("[data-limr-block]") ?? container;
|
|
1193
|
-
}
|
|
1194
|
-
function leavesIn(block, runtime) {
|
|
1195
|
-
runtime.prepareTextBindings(block);
|
|
1196
|
-
const result = [];
|
|
1197
|
-
const visit = (node, inherited) => {
|
|
1198
|
-
if (node instanceof HTMLElement) {
|
|
1199
|
-
if (node !== block && node.hasAttribute("data-limr-document") || node.hasAttribute("inert")) return;
|
|
1200
|
-
const marker = node.dataset.limrMarker;
|
|
1201
|
-
const atomic2 = node.dataset.limrAtomic;
|
|
1202
|
-
if (marker || atomic2) {
|
|
1203
|
-
const image = node.dataset.limrMedia === "image";
|
|
1204
|
-
result.push({ node, kind: marker ? "marker" : image ? "image" : atomic2 === "block" ? "block" : "inline", range: { start: Number(node.dataset.sourceStart), end: Number(node.dataset.sourceEnd) }, flow: image ? node : flowOf(node, runtime.content), offset: 0 });
|
|
1205
|
-
return;
|
|
1206
|
-
}
|
|
1207
|
-
if (node.hasAttribute("data-limr-ignore")) return;
|
|
1208
|
-
const binding = runtime.bindings.get(node);
|
|
1209
|
-
if (binding) inherited = { binding, offset: 0 };
|
|
1210
|
-
}
|
|
1211
|
-
if (node.nodeType === Node.TEXT_NODE) {
|
|
1212
|
-
const binding = runtime.bindings.get(node) ?? inherited?.binding;
|
|
1213
|
-
const offset = runtime.bindings.has(node) ? 0 : inherited?.offset ?? 0;
|
|
1214
|
-
const length = node.textContent?.length ?? 0;
|
|
1215
|
-
if (binding?.resolve && length) result.push({ node, kind: "text", range: { start: binding.resolve(offset, "start"), end: binding.resolve(offset + length, "end") }, flow: flowOf(node.parentElement, runtime.content), binding, offset });
|
|
1216
|
-
if (inherited) inherited.offset += length;
|
|
1217
|
-
return;
|
|
1218
|
-
}
|
|
1219
|
-
node.childNodes.forEach((child) => visit(child, inherited));
|
|
1220
|
-
};
|
|
1221
|
-
visit(block);
|
|
1222
|
-
return result;
|
|
1223
|
-
}
|
|
1224
|
-
function textRange(leaf, source, viewport) {
|
|
1225
|
-
const node = leaf.node, length = node.length;
|
|
1226
|
-
const resolve = leaf.binding.resolve;
|
|
1227
|
-
let lo = 0, hi = length;
|
|
1228
|
-
while (lo < hi) {
|
|
1229
|
-
const mid = lo + hi >>> 1;
|
|
1230
|
-
if (resolve(leaf.offset + mid + 1, "end") <= source.start) lo = mid + 1;
|
|
1231
|
-
else hi = mid;
|
|
1232
|
-
}
|
|
1233
|
-
let start = lo;
|
|
1234
|
-
lo = start;
|
|
1235
|
-
hi = length;
|
|
1236
|
-
while (lo < hi) {
|
|
1237
|
-
const mid = lo + hi >>> 1;
|
|
1238
|
-
if (resolve(leaf.offset + mid, "start") < source.end) lo = mid + 1;
|
|
1239
|
-
else hi = mid;
|
|
1240
|
-
}
|
|
1241
|
-
if (start === lo) return null;
|
|
1242
|
-
let end = lo;
|
|
1243
|
-
const range = document.createRange();
|
|
1244
|
-
if (viewport && end - start > 1024) {
|
|
1245
|
-
range.setStart(node, start);
|
|
1246
|
-
range.setEnd(node, end);
|
|
1247
|
-
const box = range.getBoundingClientRect();
|
|
1248
|
-
if (box.height > viewport.bottom - viewport.top + 80) {
|
|
1249
|
-
lo = start;
|
|
1250
|
-
hi = end;
|
|
1251
|
-
while (lo < hi) {
|
|
1252
|
-
const mid = lo + hi >>> 1;
|
|
1253
|
-
range.setStart(node, mid);
|
|
1254
|
-
range.setEnd(node, mid + 1);
|
|
1255
|
-
if (range.getBoundingClientRect().bottom < viewport.top) lo = mid + 1;
|
|
1256
|
-
else hi = mid;
|
|
1257
|
-
}
|
|
1258
|
-
start = lo;
|
|
1259
|
-
hi = end;
|
|
1260
|
-
while (lo < hi) {
|
|
1261
|
-
const mid = lo + hi >>> 1;
|
|
1262
|
-
range.setStart(node, mid);
|
|
1263
|
-
range.setEnd(node, mid + 1);
|
|
1264
|
-
if (range.getBoundingClientRect().top <= viewport.bottom) lo = mid + 1;
|
|
1265
|
-
else hi = mid;
|
|
1266
|
-
}
|
|
1267
|
-
end = lo;
|
|
1268
|
-
}
|
|
1269
|
-
}
|
|
1270
|
-
if (start === end) return null;
|
|
1271
|
-
range.setStart(node, start);
|
|
1272
|
-
range.setEnd(node, end);
|
|
1273
|
-
return range;
|
|
1274
|
-
}
|
|
1275
|
-
function sourceRangeStartRect(runtime, source) {
|
|
1276
|
-
for (const block of runtime.document.getSnapshot().blocks) {
|
|
1277
|
-
if (!intersects(block.range, source)) continue;
|
|
1278
|
-
const element = runtime.blocks.get(block.id);
|
|
1279
|
-
if (!element) continue;
|
|
1280
|
-
for (const leaf of leavesIn(element, runtime)) {
|
|
1281
|
-
if (leaf.kind === "marker" || !intersects(leaf.range, source)) continue;
|
|
1282
|
-
if (leaf.kind === "text") {
|
|
1283
|
-
const range = textRange(leaf, source);
|
|
1284
|
-
if (!range) continue;
|
|
1285
|
-
const node = leaf.node, end = range.endOffset;
|
|
1286
|
-
for (let start = range.startOffset; start < end; ) {
|
|
1287
|
-
const next = Math.min(end, start + (node.data.codePointAt(start) > 65535 ? 2 : 1));
|
|
1288
|
-
range.setStart(node, start);
|
|
1289
|
-
range.setEnd(node, next);
|
|
1290
|
-
const rect = range.getBoundingClientRect();
|
|
1291
|
-
if (rect.width && rect.height) return rect;
|
|
1292
|
-
start = next;
|
|
1293
|
-
}
|
|
1294
|
-
} else {
|
|
1295
|
-
const node = leaf.node;
|
|
1296
|
-
const rect = (node.querySelector(leaf.kind === "image" ? "img" : "[data-limr-selection-surface]") ?? node).getBoundingClientRect();
|
|
1297
|
-
if (rect.width && rect.height) return rect;
|
|
1298
|
-
}
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
return null;
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
// src/react/selection.ts
|
|
1476
|
+
import { useEffect as useEffect3 } from "react";
|
|
1305
1477
|
function visualSelection(runtime, native, options) {
|
|
1306
1478
|
if (![...runtime.content.querySelectorAll('[data-limr-selection-order="visual"]')].some((element) => native.intersectsNode(element))) return;
|
|
1307
1479
|
const blocks = [...runtime.blocks.values()].filter((block) => native.intersectsNode(block));
|
|
@@ -1348,7 +1520,7 @@ function visualSelection(runtime, native, options) {
|
|
|
1348
1520
|
return { ...selections[0], raw: combine("raw"), syntax: combine("syntax"), blocks: combine("blocks") };
|
|
1349
1521
|
}
|
|
1350
1522
|
function useSelectionTracking(runtime, enabled) {
|
|
1351
|
-
|
|
1523
|
+
useEffect3(() => {
|
|
1352
1524
|
const container = runtime.content;
|
|
1353
1525
|
if (!container || !enabled) return;
|
|
1354
1526
|
let frame = 0, dragging = false;
|
|
@@ -1356,6 +1528,10 @@ function useSelectionTracking(runtime, enabled) {
|
|
|
1356
1528
|
function resolve(node, offset, edge) {
|
|
1357
1529
|
let element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
1358
1530
|
if (!element || element.closest("[data-limr-document]") !== container || element.closest("[data-limr-ignore]")) return null;
|
|
1531
|
+
let atom = element.closest("[data-limr-atomic]");
|
|
1532
|
+
for (let outer = atom?.parentElement?.closest("[data-limr-atomic]"); outer && container?.contains(outer); outer = atom.parentElement?.closest("[data-limr-atomic]")) atom = outer;
|
|
1533
|
+
const atomicBinding = atom && runtime.bindings.get(atom);
|
|
1534
|
+
if (atomicBinding?.atomic) return { offset: edge === "start" ? atomicBinding.range.start : atomicBinding.range.end, atomic: true, exact: true };
|
|
1359
1535
|
runtime.prepareTextBindings(element);
|
|
1360
1536
|
const native = node.nodeType === Node.TEXT_NODE ? runtime.bindings.get(node) : void 0;
|
|
1361
1537
|
if (native?.resolve) return { offset: native.resolve(offset, edge), atomic: false, exact: native.exact !== false };
|
|
@@ -1363,7 +1539,7 @@ function useSelectionTracking(runtime, enabled) {
|
|
|
1363
1539
|
const binding = runtime.bindings.get(element);
|
|
1364
1540
|
if (binding) {
|
|
1365
1541
|
if (binding.atomic) return { offset: edge === "start" ? binding.range.start : binding.range.end, atomic: true, exact: true };
|
|
1366
|
-
const range =
|
|
1542
|
+
const range = measurementRange(element.ownerDocument);
|
|
1367
1543
|
range.setStart(element, 0);
|
|
1368
1544
|
try {
|
|
1369
1545
|
range.setEnd(node, offset);
|
|
@@ -1424,12 +1600,20 @@ function useSelectionTracking(runtime, enabled) {
|
|
|
1424
1600
|
previous = { startNode: range.startContainer, start: range.startOffset, endNode: range.endContainer, end: range.endOffset, revision, settled: !dragging };
|
|
1425
1601
|
runtime.selectionRange = range.cloneRange();
|
|
1426
1602
|
runtime.highlightReference = null;
|
|
1603
|
+
const text = selection.toString();
|
|
1427
1604
|
const options = {
|
|
1428
|
-
text
|
|
1605
|
+
// An image/diagram can prohibit internal text selection while its
|
|
1606
|
+
// complete source block remains selectable and copyable.
|
|
1607
|
+
text: text || (start.atomic && end.atomic ? runtime.document.getSnapshot().source.slice(start.offset, end.offset) : ""),
|
|
1429
1608
|
settled: !dragging,
|
|
1430
1609
|
quality: !start.exact || !end.exact ? "unmapped" : start.atomic || end.atomic ? "atomic" : "exact"
|
|
1431
1610
|
};
|
|
1432
|
-
|
|
1611
|
+
let captured = visualSelection(runtime, range, options) ?? selectionFromRange(runtime.document.getSnapshot(), { start: start.offset, end: end.offset }, options);
|
|
1612
|
+
if (!dragging) {
|
|
1613
|
+
const atomicText = atomicSelectionText(runtime, captured.raw.ranges);
|
|
1614
|
+
if (atomicText !== void 0) captured = { ...captured, text: atomicText, quality: "atomic" };
|
|
1615
|
+
}
|
|
1616
|
+
runtime.updateInteraction({ activeHighlight: null, selection: captured });
|
|
1433
1617
|
}
|
|
1434
1618
|
const schedule = () => {
|
|
1435
1619
|
if (!frame) frame = requestAnimationFrame(process);
|
|
@@ -1441,11 +1625,34 @@ function useSelectionTracking(runtime, enabled) {
|
|
|
1441
1625
|
dragging = false;
|
|
1442
1626
|
schedule();
|
|
1443
1627
|
};
|
|
1628
|
+
const atomicCopyText = (event) => {
|
|
1629
|
+
const native = window.getSelection(), captured = runtime.interaction.get().selection;
|
|
1630
|
+
if (event.defaultPrevented || !native?.anchorNode || native.isCollapsed || !container.contains(native.anchorNode) || captured?.quality !== "atomic") return null;
|
|
1631
|
+
if (event.target instanceof Element && event.target.closest("input,textarea,[contenteditable],[data-limr-selection-ui]")) return null;
|
|
1632
|
+
return captured.settled ? captured.text : atomicSelectionText(runtime, captured.raw.ranges) ?? captured.text;
|
|
1633
|
+
};
|
|
1634
|
+
const copy = (event) => {
|
|
1635
|
+
const text = atomicCopyText(event);
|
|
1636
|
+
if (!text || !event.clipboardData) return;
|
|
1637
|
+
event.clipboardData.setData("text/plain", text);
|
|
1638
|
+
event.preventDefault();
|
|
1639
|
+
};
|
|
1640
|
+
const copyKey = (event) => {
|
|
1641
|
+
if (event.key.toLowerCase() !== "c" || !(event.ctrlKey || event.metaKey) || event.altKey || !navigator.clipboard?.writeText) return;
|
|
1642
|
+
if (window.getSelection()?.toString()) return;
|
|
1643
|
+
const text = atomicCopyText(event);
|
|
1644
|
+
if (!text) return;
|
|
1645
|
+
event.preventDefault();
|
|
1646
|
+
void navigator.clipboard.writeText(text).catch(() => {
|
|
1647
|
+
});
|
|
1648
|
+
};
|
|
1444
1649
|
document.addEventListener("selectionchange", schedule);
|
|
1445
1650
|
container.addEventListener("pointerdown", down);
|
|
1446
1651
|
document.addEventListener("pointerup", up);
|
|
1447
1652
|
document.addEventListener("pointercancel", up);
|
|
1448
1653
|
document.addEventListener("keyup", schedule);
|
|
1654
|
+
document.addEventListener("copy", copy);
|
|
1655
|
+
document.addEventListener("keydown", copyKey);
|
|
1449
1656
|
if (window.getSelection()?.isCollapsed === false) schedule();
|
|
1450
1657
|
return () => {
|
|
1451
1658
|
cancelAnimationFrame(frame);
|
|
@@ -1454,13 +1661,15 @@ function useSelectionTracking(runtime, enabled) {
|
|
|
1454
1661
|
document.removeEventListener("pointerup", up);
|
|
1455
1662
|
document.removeEventListener("pointercancel", up);
|
|
1456
1663
|
document.removeEventListener("keyup", schedule);
|
|
1664
|
+
document.removeEventListener("copy", copy);
|
|
1665
|
+
document.removeEventListener("keydown", copyKey);
|
|
1457
1666
|
};
|
|
1458
1667
|
}, [runtime, enabled]);
|
|
1459
1668
|
}
|
|
1460
1669
|
|
|
1461
1670
|
// src/react/selection-paint.tsx
|
|
1462
|
-
import { useEffect as
|
|
1463
|
-
import { jsx as
|
|
1671
|
+
import { useEffect as useEffect4, useRef as useRef5 } from "react";
|
|
1672
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1464
1673
|
function rectangles(leaves, source, viewport, measure) {
|
|
1465
1674
|
const raw = [];
|
|
1466
1675
|
const geometry = (leaf, rect, reference) => {
|
|
@@ -1483,7 +1692,7 @@ function rectangles(leaves, source, viewport, measure) {
|
|
|
1483
1692
|
};
|
|
1484
1693
|
const edgeRect = (leaf, edge) => {
|
|
1485
1694
|
const node = leaf.node;
|
|
1486
|
-
const range =
|
|
1695
|
+
const range = measurementRange(node.ownerDocument);
|
|
1487
1696
|
const offset = edge === "first" ? 0 : Math.max(0, node.length - 1);
|
|
1488
1697
|
range.setStart(node, offset);
|
|
1489
1698
|
range.setEnd(node, Math.min(node.length, offset + 1));
|
|
@@ -1501,7 +1710,7 @@ function rectangles(leaves, source, viewport, measure) {
|
|
|
1501
1710
|
const boxAt = (index) => {
|
|
1502
1711
|
const leaf = leaves[index];
|
|
1503
1712
|
if (leaf.kind !== "text") return leaf.node.getBoundingClientRect();
|
|
1504
|
-
const range =
|
|
1713
|
+
const range = measurementRange(leaf.node.ownerDocument);
|
|
1505
1714
|
range.selectNodeContents(leaf.node);
|
|
1506
1715
|
return range.getBoundingClientRect();
|
|
1507
1716
|
};
|
|
@@ -1531,6 +1740,13 @@ function rectangles(leaves, source, viewport, measure) {
|
|
|
1531
1740
|
raw.push({ ...item, marker: leaf.node.dataset.limrMarker });
|
|
1532
1741
|
} else if (intersects(leaf.range, source)) {
|
|
1533
1742
|
if (leaf.kind === "text") {
|
|
1743
|
+
const glue = leaf.node.parentElement?.closest(".limr-kp-glue");
|
|
1744
|
+
if (glue) {
|
|
1745
|
+
const rect = glue.getBoundingClientRect();
|
|
1746
|
+
const reference = referenceFor(index, rect);
|
|
1747
|
+
if (rect.width && reference && rect.bottom >= viewport.top && rect.top <= viewport.bottom) raw.push(geometry(leaf, rect, reference));
|
|
1748
|
+
continue;
|
|
1749
|
+
}
|
|
1534
1750
|
const range = textRange(leaf, source, viewport);
|
|
1535
1751
|
const shell = leaf.node.parentElement?.closest("[data-limr-inline-syntax]");
|
|
1536
1752
|
const edges = shell ? Array.from(shell.getClientRects()) : [];
|
|
@@ -1579,15 +1795,42 @@ function rectangles(leaves, source, viewport, measure) {
|
|
|
1579
1795
|
const gap = right.left - left.left - left.width;
|
|
1580
1796
|
if (left.flow === right.flow && Math.abs(left.top - right.top) < 0.5 && gap > 0.1 && gap < left.height * 0.6) bridges.push({ left: left.left + left.width, top: left.top, width: gap, height: left.height, flow: left.flow });
|
|
1581
1797
|
}
|
|
1582
|
-
|
|
1798
|
+
const result = [], rows = /* @__PURE__ */ new Map();
|
|
1799
|
+
for (const rect of [...aligned, ...bridges]) {
|
|
1800
|
+
if (!rect.flow.hasAttribute("data-limr-kp") || rect.atomic || rect.marker) {
|
|
1801
|
+
result.push(rect);
|
|
1802
|
+
continue;
|
|
1803
|
+
}
|
|
1804
|
+
let flow = rows.get(rect.flow);
|
|
1805
|
+
if (!flow) {
|
|
1806
|
+
flow = /* @__PURE__ */ new Map();
|
|
1807
|
+
rows.set(rect.flow, flow);
|
|
1808
|
+
}
|
|
1809
|
+
const row = flow.get(rect.top) ?? [];
|
|
1810
|
+
row.push(rect);
|
|
1811
|
+
flow.set(rect.top, row);
|
|
1812
|
+
}
|
|
1813
|
+
for (const flow of rows.values()) for (const row of flow.values()) {
|
|
1814
|
+
row.sort((a, b) => a.left - b.left);
|
|
1815
|
+
let previous;
|
|
1816
|
+
for (const rect of row) {
|
|
1817
|
+
if (previous && rect.left <= previous.left + previous.width + 0.1 && Math.abs(rect.height - previous.height) < 0.1) previous.width = Math.max(previous.width, rect.left + rect.width - previous.left);
|
|
1818
|
+
else {
|
|
1819
|
+
previous = { ...rect };
|
|
1820
|
+
result.push(previous);
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
return result;
|
|
1583
1825
|
}
|
|
1584
1826
|
function SelectionPaint({ runtime, interactive = true }) {
|
|
1585
|
-
const layer =
|
|
1586
|
-
|
|
1827
|
+
const layer = useRef5(null);
|
|
1828
|
+
useEffect4(() => {
|
|
1587
1829
|
const container = runtime.content, paint = layer.current;
|
|
1588
1830
|
if (!container || !paint) return;
|
|
1589
|
-
let frame = 0;
|
|
1831
|
+
let frame = 0, translating = false;
|
|
1590
1832
|
let leavesCache = /* @__PURE__ */ new WeakMap();
|
|
1833
|
+
let geometryCache = /* @__PURE__ */ new WeakMap();
|
|
1591
1834
|
let metrics = /* @__PURE__ */ new WeakMap();
|
|
1592
1835
|
const fontMetrics = /* @__PURE__ */ new Map();
|
|
1593
1836
|
let blocks;
|
|
@@ -1603,7 +1846,14 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1603
1846
|
const highlightRects = (id) => [...highlightLayers.values()].flatMap((layer2) => Array.from(layer2.children).filter((item) => item.dataset.paint === id).map((item) => item.getBoundingClientRect()));
|
|
1604
1847
|
const focusedRange = () => {
|
|
1605
1848
|
const state = runtime.interaction.get(), decorations = runtime.decorations.get();
|
|
1606
|
-
return decorations.
|
|
1849
|
+
return decorations.referenceRanges.get(state.hovered ?? "") ?? (state.activeHighlight ? decorations.highlights.get(state.activeHighlight)?.range : void 0) ?? decorations.referenceRanges.get(state.active ?? "");
|
|
1850
|
+
};
|
|
1851
|
+
const referenceActive = (occurrenceId) => {
|
|
1852
|
+
const state = runtime.interaction.get(), decorations = runtime.decorations.get();
|
|
1853
|
+
if (occurrenceId === state.hovered) return true;
|
|
1854
|
+
if (occurrenceId !== state.active) return false;
|
|
1855
|
+
const hovered = decorations.highlights.get(`reference-${state.hovered}`);
|
|
1856
|
+
return !hovered?.occurrenceId || !sameRange(hovered.range, decorations.referenceRanges.get(occurrenceId));
|
|
1607
1857
|
};
|
|
1608
1858
|
const feedback = () => {
|
|
1609
1859
|
const state = runtime.interaction.get();
|
|
@@ -1612,6 +1862,12 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1612
1862
|
for (const layer2 of highlightLayers.values()) for (const item of layer2.children) {
|
|
1613
1863
|
item.toggleAttribute("data-hovered", item.dataset.paint === state.hoveredHighlight);
|
|
1614
1864
|
const highlight = decorations.highlights.get(item.dataset.paint ?? "");
|
|
1865
|
+
if (highlight?.occurrenceId) {
|
|
1866
|
+
const active = referenceActive(highlight.occurrenceId);
|
|
1867
|
+
item.toggleAttribute("data-active", active);
|
|
1868
|
+
item.toggleAttribute("data-muted", !active);
|
|
1869
|
+
continue;
|
|
1870
|
+
}
|
|
1615
1871
|
item.toggleAttribute("data-active", item.dataset.paint === state.activeHighlight || !!focused && !!highlight && sameRange(focused, highlight.range));
|
|
1616
1872
|
item.toggleAttribute("data-muted", !!highlight?.hidden || !!focused && !!highlight && !sameRange(focused, highlight.range));
|
|
1617
1873
|
}
|
|
@@ -1712,17 +1968,31 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1712
1968
|
};
|
|
1713
1969
|
for (let index = lo; index < blocks.length; index++) {
|
|
1714
1970
|
const block = blocks[index];
|
|
1715
|
-
|
|
1971
|
+
const blockBox = block.element.getBoundingClientRect();
|
|
1972
|
+
if (blockBox.top > viewport.bottom + 32) break;
|
|
1716
1973
|
const tasks = [...decorations.get(block.id)?.highlights ?? []];
|
|
1717
1974
|
for (const range of selections) if (intersects(range, block.range)) tasks.push({ id: "selection", range, selection: true });
|
|
1718
1975
|
if (!tasks.length) continue;
|
|
1719
1976
|
let leaves = leavesCache.get(block.element);
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1977
|
+
let cached = geometryCache.get(block.element);
|
|
1978
|
+
if (cached?.width !== blockBox.width || cached.height !== blockBox.height) cached = void 0;
|
|
1979
|
+
if (!cached && blockBox.height < (viewport.bottom - viewport.top) * 3) {
|
|
1980
|
+
cached = { width: blockBox.width, height: blockBox.height, tasks: /* @__PURE__ */ new Map() };
|
|
1981
|
+
geometryCache.set(block.element, cached);
|
|
1723
1982
|
}
|
|
1724
1983
|
for (const task of tasks) {
|
|
1725
|
-
const
|
|
1984
|
+
const saved = cached?.tasks.get(task.id);
|
|
1985
|
+
if (task.occurrenceId && !referenceActive(task.occurrenceId) && !saved) continue;
|
|
1986
|
+
if (!leaves) {
|
|
1987
|
+
leaves = leavesIn(block.element, runtime);
|
|
1988
|
+
leavesCache.set(block.element, leaves);
|
|
1989
|
+
}
|
|
1990
|
+
let local = saved && sameRange(saved.source, task.range) ? saved.rects : void 0;
|
|
1991
|
+
if (!local && cached) {
|
|
1992
|
+
local = rectangles(leaves, task.range, { ...viewport, top: -Infinity, bottom: Infinity }, measure).map((rect) => ({ ...rect, left: rect.left - blockBox.left, top: rect.top - blockBox.top }));
|
|
1993
|
+
cached.tasks.set(task.id, { source: task.range, rects: local });
|
|
1994
|
+
}
|
|
1995
|
+
const rects = local ? local.map((rect) => ({ ...rect, left: rect.left + blockBox.left, top: rect.top + blockBox.top })) : rectangles(leaves, task.range, { ...viewport, top: viewport.top - 32, bottom: viewport.bottom + 32 }, measure);
|
|
1726
1996
|
for (const rect of rects) {
|
|
1727
1997
|
const clip = clipFor(rect.flow);
|
|
1728
1998
|
const left = Math.max(rect.left, clip.left), top = Math.max(rect.top, clip.top);
|
|
@@ -1732,13 +2002,14 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1732
2002
|
}
|
|
1733
2003
|
}
|
|
1734
2004
|
}
|
|
1735
|
-
paint.style.top = `${viewport.top - origin.top + scrollTop}px`;
|
|
1736
|
-
paint.style.height = `${Math.max(0, viewport.bottom - viewport.top)}px`;
|
|
1737
2005
|
const hostGeometry = /* @__PURE__ */ new Map();
|
|
1738
2006
|
for (const { rect, task } of output) if (!task.selection && !hostGeometry.has(rect.flow)) {
|
|
1739
2007
|
const host = rect.flow, box = host.getBoundingClientRect();
|
|
1740
|
-
|
|
2008
|
+
const x = host.scrollLeft - host.clientLeft, y = host.scrollTop - host.clientTop;
|
|
2009
|
+
hostGeometry.set(host, { box, x, y, top: Math.max(viewport.top, box.top) - box.top + y, positioned: getComputedStyle(host).position !== "static" });
|
|
1741
2010
|
}
|
|
2011
|
+
paint.style.top = `${viewport.top - origin.top + scrollTop}px`;
|
|
2012
|
+
paint.style.height = `${Math.max(0, viewport.bottom - viewport.top)}px`;
|
|
1742
2013
|
const counts = /* @__PURE__ */ new Map();
|
|
1743
2014
|
const nextHits = [];
|
|
1744
2015
|
output.forEach(({ rect, task }) => {
|
|
@@ -1759,8 +2030,8 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1759
2030
|
layer2.style.top = `${geometry.top}px`;
|
|
1760
2031
|
layer2.style.height = `${Math.max(0, Math.min(viewport.bottom, geometry.box.bottom) - Math.max(viewport.top, geometry.box.top))}px`;
|
|
1761
2032
|
target = layer2;
|
|
1762
|
-
left += origin.left - geometry.box.left
|
|
1763
|
-
top += viewport.top - geometry.box.top
|
|
2033
|
+
left += origin.left - geometry.box.left + geometry.x;
|
|
2034
|
+
top += viewport.top - geometry.box.top + geometry.y - geometry.top;
|
|
1764
2035
|
nextHits.push({ id: task.id, rect: { left: rect.left + origin.left - scrollLeft, top: rect.top + viewport.top, width: rect.width, height: rect.height } });
|
|
1765
2036
|
}
|
|
1766
2037
|
const index = counts.get(target) ?? 0;
|
|
@@ -1769,6 +2040,7 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1769
2040
|
const className = `limr-paint-rect limr-paint-${task.selection ? "selection" : task.style ?? "background"}`;
|
|
1770
2041
|
if (item.className !== className) item.className = className;
|
|
1771
2042
|
item.dataset.paint = task.id;
|
|
2043
|
+
item.toggleAttribute("data-reference", !!task.occurrenceId);
|
|
1772
2044
|
if (rect.marker) item.dataset.marker = rect.marker;
|
|
1773
2045
|
else delete item.dataset.marker;
|
|
1774
2046
|
if (rect.atomic) item.dataset.atomic = "true";
|
|
@@ -1781,18 +2053,38 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1781
2053
|
item.dataset.geometry = css;
|
|
1782
2054
|
}
|
|
1783
2055
|
if (!task.selection) item.style.setProperty("--limr-highlight", task.color ?? "#F2C744");
|
|
2056
|
+
if (task.occurrenceId) {
|
|
2057
|
+
const active2 = referenceActive(task.occurrenceId);
|
|
2058
|
+
item.toggleAttribute("data-active", active2);
|
|
2059
|
+
item.toggleAttribute("data-muted", !active2);
|
|
2060
|
+
}
|
|
1784
2061
|
if (!item.parentNode) target.append(item);
|
|
1785
2062
|
});
|
|
1786
|
-
for (const layer2 of [paint, ...highlightLayers.values()]) while (layer2.children.length > (counts.get(layer2) ?? 0)) layer2.lastChild.remove();
|
|
1787
2063
|
for (const [host, layer2] of highlightLayers) if (!counts.has(layer2)) removeLayer(host, layer2);
|
|
2064
|
+
for (const layer2 of [paint, ...highlightLayers.values()]) {
|
|
2065
|
+
const count = counts.get(layer2) ?? 0;
|
|
2066
|
+
if (layer2.children.length > count) layer2.replaceChildren(...Array.from(layer2.children).slice(0, count));
|
|
2067
|
+
}
|
|
1788
2068
|
hits = nextHits;
|
|
1789
2069
|
const active = runtime.interaction.get().activeHighlight;
|
|
1790
2070
|
if (active && !hits.some((hit) => hit.id === active)) runtime.clearSelection();
|
|
1791
2071
|
feedback();
|
|
2072
|
+
if (translating) {
|
|
2073
|
+
translating = container.getAnimations().some((animation) => animation instanceof CSSTransition && animation.transitionProperty === "translate" && animation.playState === "running");
|
|
2074
|
+
if (translating) schedule();
|
|
2075
|
+
}
|
|
1792
2076
|
};
|
|
1793
2077
|
const schedule = () => {
|
|
1794
2078
|
if (!frame) frame = requestAnimationFrame(render);
|
|
1795
2079
|
};
|
|
2080
|
+
const translate = (event) => {
|
|
2081
|
+
if (event.target !== container || event.propertyName !== "translate") return;
|
|
2082
|
+
translating = true;
|
|
2083
|
+
schedule();
|
|
2084
|
+
};
|
|
2085
|
+
container.addEventListener("transitionrun", translate);
|
|
2086
|
+
container.addEventListener("transitionend", translate);
|
|
2087
|
+
container.addEventListener("transitioncancel", translate);
|
|
1796
2088
|
const invalidate = () => {
|
|
1797
2089
|
blocks = void 0;
|
|
1798
2090
|
metrics = /* @__PURE__ */ new WeakMap();
|
|
@@ -1800,10 +2092,12 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1800
2092
|
};
|
|
1801
2093
|
const fontsChanged = () => {
|
|
1802
2094
|
fontMetrics.clear();
|
|
2095
|
+
geometryCache = /* @__PURE__ */ new WeakMap();
|
|
1803
2096
|
invalidate();
|
|
1804
2097
|
};
|
|
1805
2098
|
const unsubscribers = [runtime.interaction.subscribe(() => {
|
|
1806
2099
|
const state = runtime.interaction.get(), selection = state.selection;
|
|
2100
|
+
const referenceChanged = state.active !== lastAnnotation || state.hovered !== lastHoveredAnnotation;
|
|
1807
2101
|
if (state.hoveredHighlight !== lastHovered || state.activeHighlight !== lastActive || state.active !== lastAnnotation || state.hovered !== lastHoveredAnnotation) {
|
|
1808
2102
|
lastHovered = state.hoveredHighlight;
|
|
1809
2103
|
lastActive = state.activeHighlight;
|
|
@@ -1811,6 +2105,7 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1811
2105
|
lastHoveredAnnotation = state.hovered;
|
|
1812
2106
|
feedback();
|
|
1813
2107
|
}
|
|
2108
|
+
if (referenceChanged) schedule();
|
|
1814
2109
|
if (selection === lastSelection) return;
|
|
1815
2110
|
lastSelection = selection;
|
|
1816
2111
|
render();
|
|
@@ -1819,8 +2114,12 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1819
2114
|
if (decorations === lastDecorations) return;
|
|
1820
2115
|
lastDecorations = decorations;
|
|
1821
2116
|
leavesCache = /* @__PURE__ */ new WeakMap();
|
|
2117
|
+
geometryCache = /* @__PURE__ */ new WeakMap();
|
|
1822
2118
|
schedule();
|
|
1823
|
-
}), runtime.layout.subscribe(invalidate), runtime.configuration.subscribe(
|
|
2119
|
+
}), runtime.layout.subscribe(invalidate), runtime.documentOffset.subscribe(schedule), runtime.configuration.subscribe(() => {
|
|
2120
|
+
geometryCache = /* @__PURE__ */ new WeakMap();
|
|
2121
|
+
invalidate();
|
|
2122
|
+
})];
|
|
1824
2123
|
const observer = new MutationObserver((records) => {
|
|
1825
2124
|
let changed = false;
|
|
1826
2125
|
for (const record of records) {
|
|
@@ -1828,8 +2127,13 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1828
2127
|
if (!target || target === paint || paint.contains(target) || target.closest(".limr-highlight-layer")) continue;
|
|
1829
2128
|
if (record.type === "childList" && [...record.addedNodes, ...record.removedNodes].every((node) => node instanceof Element && node.classList.contains("limr-highlight-layer"))) continue;
|
|
1830
2129
|
const block = target.closest("[data-limr-block]");
|
|
1831
|
-
if (block)
|
|
1832
|
-
|
|
2130
|
+
if (block) {
|
|
2131
|
+
leavesCache.delete(block);
|
|
2132
|
+
geometryCache.delete(block);
|
|
2133
|
+
} else {
|
|
2134
|
+
blocks = void 0;
|
|
2135
|
+
geometryCache = /* @__PURE__ */ new WeakMap();
|
|
2136
|
+
}
|
|
1833
2137
|
changed = true;
|
|
1834
2138
|
}
|
|
1835
2139
|
if (changed) {
|
|
@@ -1838,7 +2142,12 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1838
2142
|
}
|
|
1839
2143
|
});
|
|
1840
2144
|
observer.observe(container, { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: ["class", "style", "inert", "open", "data-limr-theme", "data-limr-justify"] });
|
|
1841
|
-
const scroll = () => {
|
|
2145
|
+
const scroll = (event) => {
|
|
2146
|
+
const target = event.target;
|
|
2147
|
+
if (target instanceof Element) {
|
|
2148
|
+
const block = target.closest("[data-limr-block]");
|
|
2149
|
+
if (block) geometryCache.delete(block);
|
|
2150
|
+
}
|
|
1842
2151
|
runtime.hoverHighlight(null);
|
|
1843
2152
|
schedule();
|
|
1844
2153
|
};
|
|
@@ -1853,7 +2162,7 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1853
2162
|
for (let index = hits.length - 1; index >= 0; index--) {
|
|
1854
2163
|
const { rect, id } = hits[index];
|
|
1855
2164
|
const highlight = decorations.highlights.get(id);
|
|
1856
|
-
if (highlight?.hidden || focused && highlight && !sameRange(focused, highlight.range)) continue;
|
|
2165
|
+
if (highlight?.occurrenceId || highlight?.hidden || focused && highlight && !sameRange(focused, highlight.range)) continue;
|
|
1857
2166
|
if (event.clientX >= rect.left && event.clientX <= rect.left + rect.width && event.clientY >= rect.top && event.clientY <= rect.top + rect.height) return id;
|
|
1858
2167
|
}
|
|
1859
2168
|
return null;
|
|
@@ -1918,6 +2227,9 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1918
2227
|
window.visualViewport?.removeEventListener("resize", schedule);
|
|
1919
2228
|
window.visualViewport?.removeEventListener("scroll", schedule);
|
|
1920
2229
|
document.fonts?.removeEventListener("loadingdone", fontsChanged);
|
|
2230
|
+
container.removeEventListener("transitionrun", translate);
|
|
2231
|
+
container.removeEventListener("transitionend", translate);
|
|
2232
|
+
container.removeEventListener("transitioncancel", translate);
|
|
1921
2233
|
container.removeEventListener("pointermove", move);
|
|
1922
2234
|
container.removeEventListener("pointerleave", leave);
|
|
1923
2235
|
container.removeEventListener("pointerdown", pointerDown);
|
|
@@ -1926,15 +2238,15 @@ function SelectionPaint({ runtime, interactive = true }) {
|
|
|
1926
2238
|
clear();
|
|
1927
2239
|
};
|
|
1928
2240
|
}, [runtime, interactive]);
|
|
1929
|
-
return /* @__PURE__ */
|
|
2241
|
+
return /* @__PURE__ */ jsx5("div", { ref: layer, className: "limr-paint-layer", "data-limr-ignore": "true", "aria-hidden": "true" });
|
|
1930
2242
|
}
|
|
1931
2243
|
|
|
1932
2244
|
// src/react/Markdown.tsx
|
|
1933
|
-
import { jsx as
|
|
2245
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1934
2246
|
function Markdown({ className, style, interactive = true, followOutput = false, justify, ...props }) {
|
|
1935
2247
|
const parent = useContext(RuntimeContext);
|
|
1936
|
-
if (props.source !== void 0 || !parent) return /* @__PURE__ */
|
|
1937
|
-
return /* @__PURE__ */
|
|
2248
|
+
if (props.source !== void 0 || !parent) return /* @__PURE__ */ jsx6(DocumentProvider, { ...props, justify, children: /* @__PURE__ */ jsx6(MarkdownBody, { className, style, interactive, followOutput }) });
|
|
2249
|
+
return /* @__PURE__ */ jsx6(MarkdownBody, { className, style, interactive, followOutput, justify });
|
|
1938
2250
|
}
|
|
1939
2251
|
function MarkdownBody({ className, style, interactive, followOutput, justify }) {
|
|
1940
2252
|
const runtime = useRuntime();
|
|
@@ -1942,17 +2254,20 @@ function MarkdownBody({ className, style, interactive, followOutput, justify })
|
|
|
1942
2254
|
const appearance = useAppearance();
|
|
1943
2255
|
const theme = useStoreSelector(runtime.configuration, (config) => config.theme ?? "light");
|
|
1944
2256
|
const configuredJustify = useStoreSelector(runtime.configuration, (config) => config.justify ?? false);
|
|
2257
|
+
const typography = useStoreSelector(runtime.configuration, (config) => config.typography ?? "standard");
|
|
2258
|
+
const justified = justify ?? (typography === "justify" || configuredJustify);
|
|
1945
2259
|
const scrollRoot = useStoreSelector(runtime.configuration, (config) => config.scrollRoot);
|
|
1946
2260
|
const offset = useStoreSelector(runtime.documentOffset, (value) => value);
|
|
1947
2261
|
const components = useStoreSelector(runtime.configuration, (config) => config.components);
|
|
1948
2262
|
const extensions = useStoreSelector(runtime.configuration, (config) => config.extensions);
|
|
2263
|
+
const rendererOverrides = useStoreSelector(runtime.configuration, (config) => config.rendererOverrides);
|
|
1949
2264
|
const decorations = useStoreSelector(runtime.decorations, (state) => state.byBlock);
|
|
1950
|
-
const ref =
|
|
1951
|
-
const pinned =
|
|
2265
|
+
const ref = useRef6(null);
|
|
2266
|
+
const pinned = useRef6(true);
|
|
1952
2267
|
useIsomorphicLayoutEffect(() => ref.current ? runtime.mountContent(ref.current) : void 0, [runtime, scrollRoot]);
|
|
1953
|
-
useIsomorphicLayoutEffect(() => runtime.requestLayout(), [runtime, justify, configuredJustify]);
|
|
2268
|
+
useIsomorphicLayoutEffect(() => runtime.requestLayout(), [runtime, justify, configuredJustify, typography]);
|
|
1954
2269
|
useSelectionTracking(runtime, interactive);
|
|
1955
|
-
|
|
2270
|
+
useEffect5(() => {
|
|
1956
2271
|
if (!followOutput) return;
|
|
1957
2272
|
const root = scrollRoot ?? window;
|
|
1958
2273
|
const onScroll = () => {
|
|
@@ -1968,23 +2283,23 @@ function MarkdownBody({ className, style, interactive, followOutput, justify })
|
|
|
1968
2283
|
const frame = requestAnimationFrame(() => runtime.scrollTo(scrollRoot?.scrollHeight ?? window.document.documentElement.scrollHeight, "instant"));
|
|
1969
2284
|
return () => cancelAnimationFrame(frame);
|
|
1970
2285
|
}, [document2, runtime, followOutput, scrollRoot]);
|
|
1971
|
-
return /* @__PURE__ */ jsxs3("article", { ref, className: `limr-prose ${className ?? ""}`, style: { ...style, translate: offset ? `0 ${offset}px` : style?.translate }, "data-limr-theme": theme, "data-limr-appearance": appearance, "data-limr-document": document2.id, "data-limr-justify":
|
|
1972
|
-
document2.blocks.map((block) => /* @__PURE__ */
|
|
1973
|
-
/* @__PURE__ */
|
|
1974
|
-
/* @__PURE__ */
|
|
2286
|
+
return /* @__PURE__ */ jsxs3("article", { ref, className: `limr-prose ${className ?? ""}`, style: { ...style, translate: offset ? `0 ${offset}px` : style?.translate }, "data-limr-theme": theme, "data-limr-appearance": appearance, "data-limr-document": document2.id, "data-limr-justify": justified, "data-limr-typography": typography, children: [
|
|
2287
|
+
document2.blocks.map((block) => /* @__PURE__ */ jsx6(BlockView, { block, runtime, components, extensions, rendererOverrides, decorations: decorations.get(block.id) ?? emptyDecorations }, block.id)),
|
|
2288
|
+
/* @__PURE__ */ jsx6(Footnotes, {}),
|
|
2289
|
+
/* @__PURE__ */ jsx6(SelectionPaint, { runtime, interactive })
|
|
1975
2290
|
] });
|
|
1976
2291
|
}
|
|
1977
2292
|
|
|
1978
2293
|
// src/components/OverlayScrollArea.tsx
|
|
1979
|
-
import { useRef as
|
|
1980
|
-
import { jsx as
|
|
2294
|
+
import { useRef as useRef7 } from "react";
|
|
2295
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1981
2296
|
function OverlayScrollArea({ children, active, resetKey, label }) {
|
|
1982
|
-
const area =
|
|
1983
|
-
const content =
|
|
1984
|
-
const thumb =
|
|
1985
|
-
const track =
|
|
1986
|
-
const drag =
|
|
1987
|
-
const show =
|
|
2297
|
+
const area = useRef7(null);
|
|
2298
|
+
const content = useRef7(null);
|
|
2299
|
+
const thumb = useRef7(null);
|
|
2300
|
+
const track = useRef7(null);
|
|
2301
|
+
const drag = useRef7(null);
|
|
2302
|
+
const show = useRef7(() => {
|
|
1988
2303
|
});
|
|
1989
2304
|
useIsomorphicLayoutEffect(() => {
|
|
1990
2305
|
const element = area.current, wrapper = element.parentElement;
|
|
@@ -2057,73 +2372,73 @@ function OverlayScrollArea({ children, active, resetKey, label }) {
|
|
|
2057
2372
|
show.current();
|
|
2058
2373
|
};
|
|
2059
2374
|
return /* @__PURE__ */ jsxs4("div", { className: "limr-overlay-scroll", children: [
|
|
2060
|
-
/* @__PURE__ */
|
|
2061
|
-
/* @__PURE__ */
|
|
2375
|
+
/* @__PURE__ */ jsx7("div", { ref: area, className: "limr-overlay-content", "data-limr-card-body": "", tabIndex: 0, role: "region", "aria-label": label, children: /* @__PURE__ */ jsx7("div", { ref: content, className: "limr-overlay-scroll-inner", children }) }),
|
|
2376
|
+
/* @__PURE__ */ jsx7("div", { ref: track, className: "limr-overlay-scrollbar", "aria-hidden": "true", onPointerDown: startDrag, onPointerMove: move, onPointerUp: end, onPointerCancel: end, onLostPointerCapture: end, children: /* @__PURE__ */ jsx7("div", { ref: thumb, className: "limr-overlay-scroll-thumb" }) })
|
|
2062
2377
|
] });
|
|
2063
2378
|
}
|
|
2064
2379
|
|
|
2065
2380
|
// src/components/AnnotationCard.tsx
|
|
2066
|
-
import { Fragment as Fragment3, jsx as
|
|
2381
|
+
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2067
2382
|
function AnnotationCard({ title, bodyLabel, occurrence, expanded, pinned, canExpand, expand, collapse, close, children }) {
|
|
2068
2383
|
const locale = useLocale();
|
|
2069
2384
|
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2070
2385
|
/* @__PURE__ */ jsxs5("div", { className: "limr-overlay-header", children: [
|
|
2071
|
-
/* @__PURE__ */
|
|
2386
|
+
/* @__PURE__ */ jsx8("span", { children: title }),
|
|
2072
2387
|
/* @__PURE__ */ jsxs5("div", { className: "limr-overlay-controls", children: [
|
|
2073
|
-
expanded ? /* @__PURE__ */
|
|
2074
|
-
pinned && /* @__PURE__ */
|
|
2388
|
+
expanded ? /* @__PURE__ */ jsx8("button", { type: "button", onClick: collapse, children: /* @__PURE__ */ jsx8("span", { className: "limr-underline", children: locale.collapse }) }) : canExpand && /* @__PURE__ */ jsx8("button", { type: "button", onClick: expand, children: /* @__PURE__ */ jsx8("span", { className: "limr-underline", children: locale.expand }) }),
|
|
2389
|
+
pinned && /* @__PURE__ */ jsx8("button", { type: "button", className: "limr-overlay-close", onClick: close, "aria-label": locale.close, children: "\xD7" })
|
|
2075
2390
|
] })
|
|
2076
2391
|
] }),
|
|
2077
|
-
/* @__PURE__ */
|
|
2392
|
+
/* @__PURE__ */ jsx8(OverlayScrollArea, { active: true, resetKey: occurrence.id, label: bodyLabel ?? (typeof title === "string" ? title : locale.annotations), children })
|
|
2078
2393
|
] });
|
|
2079
2394
|
}
|
|
2080
2395
|
|
|
2081
2396
|
// src/extensions/annotations.tsx
|
|
2082
|
-
import { jsx as
|
|
2083
|
-
var CitationParagraph = ({ children }) => /* @__PURE__ */
|
|
2397
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2398
|
+
var CitationParagraph = ({ children }) => /* @__PURE__ */ jsx9("p", { children: /* @__PURE__ */ jsx9("span", { className: "limr-underline", children }) });
|
|
2084
2399
|
function CitationIcon() {
|
|
2085
|
-
return /* @__PURE__ */
|
|
2400
|
+
return /* @__PURE__ */ jsx9("svg", { viewBox: "0 0 16 16", "aria-hidden": "true", fill: "currentColor", children: /* @__PURE__ */ jsx9("path", { d: "M2.5 4.2h4.3v4.3c0 2.1-1.2 3.3-3.5 3.8l-.5-1.4c1.4-.4 2-1 2-2H2.5V4.2Zm6.7 0h4.3v4.3c0 2.1-1.2 3.3-3.5 3.8l-.5-1.4c1.4-.4 2-1 2-2H9.2V4.2Z" }) });
|
|
2086
2401
|
}
|
|
2087
2402
|
function AnnotationMarkdown({ source, className, ...props }) {
|
|
2088
2403
|
const runtime = useRuntime();
|
|
2089
2404
|
const config = useStoreSelector(runtime.configuration, (config2) => config2);
|
|
2090
|
-
return /* @__PURE__ */
|
|
2405
|
+
return /* @__PURE__ */ jsx9(Markdown, { source, extensions: config.extensions, parameters: config.parameters, components: config.components, annotationTypes: config.annotationTypes, theme: config.theme, appearance: config.appearance, locale: config.locale, interactive: false, ...props, className: `limr-annotation-markdown ${className ?? ""}` });
|
|
2091
2406
|
}
|
|
2092
2407
|
function citation(options = {}) {
|
|
2093
|
-
function
|
|
2408
|
+
function Preview2({ annotations }) {
|
|
2094
2409
|
const summary = useMemo2(() => annotations.filter((annotation) => annotation.type === (options.type ?? "citation")).map((annotation) => {
|
|
2095
2410
|
const data = annotation.data;
|
|
2096
2411
|
const source = data?.summary?.trim() || data?.description?.trim();
|
|
2097
2412
|
if (source) return fromMarkdown(source).children?.map(textContent).join(" ").replace(/\s+/g, " ").trim();
|
|
2098
2413
|
return safeUrl(data?.url) || data?.title;
|
|
2099
2414
|
}).filter(Boolean).join(" \xB7 "), [annotations]);
|
|
2100
|
-
return summary ? /* @__PURE__ */
|
|
2415
|
+
return summary ? /* @__PURE__ */ jsx9("span", { title: summary, children: summary }) : null;
|
|
2101
2416
|
}
|
|
2102
|
-
function
|
|
2417
|
+
function Card2(props) {
|
|
2103
2418
|
const locale = useLocale();
|
|
2104
|
-
return /* @__PURE__ */
|
|
2419
|
+
return /* @__PURE__ */ jsx9(AnnotationCard, { ...props, title: locale.citation ?? locale.annotations });
|
|
2105
2420
|
}
|
|
2106
|
-
function
|
|
2421
|
+
function Content3({ data }) {
|
|
2107
2422
|
const runtime = useRuntime();
|
|
2108
2423
|
const configured = useStoreSelector(runtime.configuration, () => runtime.components);
|
|
2109
2424
|
const components = useMemo2(() => ({ ...configured, paragraph: configured.paragraph ?? CitationParagraph }), [configured]);
|
|
2110
|
-
const link =
|
|
2425
|
+
const link = useRef8(null);
|
|
2111
2426
|
const url = safeUrl(data?.url);
|
|
2112
2427
|
return /* @__PURE__ */ jsxs6("div", { className: "limr-citation-content", "data-linked": !!url || void 0, onClick: (event) => {
|
|
2113
2428
|
if (url && !event.defaultPrevented && !event.target.closest('a,button,input,textarea,select,summary,[role="button"],[contenteditable="true"],[data-limr-card-interactive]') && window.getSelection()?.isCollapsed !== false) link.current?.click();
|
|
2114
2429
|
}, children: [
|
|
2115
|
-
/* @__PURE__ */
|
|
2116
|
-
(data?.description || data?.summary) && /* @__PURE__ */
|
|
2430
|
+
/* @__PURE__ */ jsx9("a", { ref: link, className: "limr-citation-title", href: url, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx9("span", { className: "limr-underline", children: data?.title ?? data?.url ?? "Citation" }) }),
|
|
2431
|
+
(data?.description || data?.summary) && /* @__PURE__ */ jsx9(AnnotationMarkdown, { source: data.description || data.summary, components })
|
|
2117
2432
|
] });
|
|
2118
2433
|
}
|
|
2119
2434
|
return {
|
|
2120
2435
|
name: "citation",
|
|
2121
2436
|
tags: ["citation", "ref"],
|
|
2122
2437
|
scope: "local",
|
|
2123
|
-
annotationTypes: [{ type: "citation", label: "Citation", icon: CitationIcon, color: "#6366f1", Content, ...options, sidebar: { Preview, collapseOnContentClick: false, ...options.sidebar }, overlay: { Card, expand: false, ...options.overlay } }],
|
|
2438
|
+
annotationTypes: [{ type: "citation", label: (locale) => locale.citation ?? "Citation", icon: CitationIcon, color: "#6366f1", highlight: "hover", Content: Content3, ...options, sidebar: { Preview: Preview2, collapseOnContentClick: false, ...options.sidebar }, overlay: { Card: Card2, expand: false, ...options.overlay } }],
|
|
2124
2439
|
transform(root) {
|
|
2125
2440
|
walk(root, (node) => {
|
|
2126
|
-
if (node.type !== "component") return;
|
|
2441
|
+
if (node.type !== "component" || node.incomplete) return;
|
|
2127
2442
|
if (node.name === "citation") {
|
|
2128
2443
|
const attributes = node.attributes ?? {};
|
|
2129
2444
|
const id = String(attributes["cite-id"] ?? attributes.id ?? "");
|
|
@@ -2147,13 +2462,13 @@ function citation(options = {}) {
|
|
|
2147
2462
|
}
|
|
2148
2463
|
|
|
2149
2464
|
// src/extensions/translations.tsx
|
|
2150
|
-
import { useRef as
|
|
2465
|
+
import { useRef as useRef10, useState as useState3 } from "react";
|
|
2151
2466
|
|
|
2152
2467
|
// src/components/InlineMarker.tsx
|
|
2153
2468
|
import { forwardRef } from "react";
|
|
2154
|
-
import { jsx as
|
|
2469
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
2155
2470
|
var InlineMarker = forwardRef(function InlineMarker2({ label, color, children, className = "", style, ...props }, ref) {
|
|
2156
|
-
return /* @__PURE__ */
|
|
2471
|
+
return /* @__PURE__ */ jsx10("span", { className: "limr-mark-wrap", "data-limr-ignore": "true", children: /* @__PURE__ */ jsx10(
|
|
2157
2472
|
"button",
|
|
2158
2473
|
{
|
|
2159
2474
|
...props,
|
|
@@ -2163,18 +2478,18 @@ var InlineMarker = forwardRef(function InlineMarker2({ label, color, children, c
|
|
|
2163
2478
|
title: props.title ?? label,
|
|
2164
2479
|
className: `limr-mark limr-action-mark ${className}`,
|
|
2165
2480
|
style: { "--limr-mark-color": color, ...style },
|
|
2166
|
-
children: /* @__PURE__ */
|
|
2481
|
+
children: /* @__PURE__ */ jsx10("span", { className: "limr-mark-icon", children })
|
|
2167
2482
|
}
|
|
2168
2483
|
) });
|
|
2169
2484
|
});
|
|
2170
2485
|
|
|
2171
2486
|
// src/components/Collapse.tsx
|
|
2172
|
-
import { useRef as
|
|
2173
|
-
import { jsx as
|
|
2487
|
+
import { useRef as useRef9, useState as useState2 } from "react";
|
|
2488
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2174
2489
|
function Collapse({ open, children, className = "", keepMounted = false }) {
|
|
2175
2490
|
const [mounted, setMounted] = useState2(open);
|
|
2176
2491
|
const [visible, setVisible] = useState2(open);
|
|
2177
|
-
const panel =
|
|
2492
|
+
const panel = useRef9(null);
|
|
2178
2493
|
useIsomorphicLayoutEffect(() => {
|
|
2179
2494
|
if (keepMounted) return;
|
|
2180
2495
|
if (open) {
|
|
@@ -2190,24 +2505,24 @@ function Collapse({ open, children, className = "", keepMounted = false }) {
|
|
|
2190
2505
|
const timer = setTimeout(() => setMounted(false), 420);
|
|
2191
2506
|
return () => clearTimeout(timer);
|
|
2192
2507
|
}, [open, keepMounted, mounted]);
|
|
2193
|
-
return /* @__PURE__ */
|
|
2508
|
+
return /* @__PURE__ */ jsx11("div", { ref: (element) => {
|
|
2194
2509
|
panel.current = element;
|
|
2195
2510
|
element?.toggleAttribute("inert", !open);
|
|
2196
|
-
}, className: `limr-collapse ${className}`, "data-open": (keepMounted ? open : visible) || void 0, "aria-hidden": !open, children: /* @__PURE__ */
|
|
2511
|
+
}, className: `limr-collapse ${className}`, "data-open": (keepMounted ? open : visible) || void 0, "aria-hidden": !open, children: /* @__PURE__ */ jsx11("div", { className: "limr-collapse-inner", children: mounted || keepMounted ? children : null }) });
|
|
2197
2512
|
}
|
|
2198
2513
|
|
|
2199
2514
|
// src/extensions/translations.tsx
|
|
2200
|
-
import { Fragment as Fragment4, jsx as
|
|
2515
|
+
import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2201
2516
|
var modes = ["origin", "translation", "both"];
|
|
2202
2517
|
var names = { origin: "\u539F\u6587", translation: "\u8BD1\u6587", both: "\u5BF9\u7167" };
|
|
2203
2518
|
function TranslationIcon({ mode }) {
|
|
2204
|
-
return /* @__PURE__ */
|
|
2205
|
-
/* @__PURE__ */
|
|
2206
|
-
/* @__PURE__ */
|
|
2207
|
-
/* @__PURE__ */
|
|
2519
|
+
return /* @__PURE__ */ jsx12("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: mode === "both" ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
2520
|
+
/* @__PURE__ */ jsx12("rect", { x: "2.5", y: "4", width: "8", height: "16", rx: "2.5" }),
|
|
2521
|
+
/* @__PURE__ */ jsx12("rect", { x: "13.5", y: "4", width: "8", height: "16", rx: "2.5" }),
|
|
2522
|
+
/* @__PURE__ */ jsx12("path", { d: "M5 9h3M5 12h3M16 9h3M16 12h3" })
|
|
2208
2523
|
] }) : /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
2209
|
-
/* @__PURE__ */
|
|
2210
|
-
mode === "origin" ? /* @__PURE__ */
|
|
2524
|
+
/* @__PURE__ */ jsx12("rect", { x: "4.5", y: "3", width: "15", height: "18", rx: "3" }),
|
|
2525
|
+
mode === "origin" ? /* @__PURE__ */ jsx12("path", { d: "M8.5 8h7M8.5 12h7M8.5 16h4" }) : /* @__PURE__ */ jsx12("path", { d: "M8 8.5h8M12 6.5v2M14.5 8.5c-.5 4-3 6.5-6.5 8M9.5 11c1.2 2.5 3.2 4.2 6.5 5.5" })
|
|
2211
2526
|
] }) });
|
|
2212
2527
|
}
|
|
2213
2528
|
function modeOf(value, fallback) {
|
|
@@ -2231,8 +2546,8 @@ function translations(options = {}) {
|
|
|
2231
2546
|
const requested = modeOf(globalMode ?? localMode ?? node.attributes?.default, options.defaultMode ?? "origin");
|
|
2232
2547
|
const mode = !origin ? "translation" : !translation ? "origin" : requested;
|
|
2233
2548
|
const next = modes[(modes.indexOf(mode) + 1) % modes.length];
|
|
2234
|
-
const marker =
|
|
2235
|
-
const restoreFocus =
|
|
2549
|
+
const marker = useRef10(null);
|
|
2550
|
+
const restoreFocus = useRef10(false);
|
|
2236
2551
|
const locked = globalMode !== void 0 && !onGlobalChange;
|
|
2237
2552
|
useIsomorphicLayoutEffect(() => {
|
|
2238
2553
|
if (restoreFocus.current) {
|
|
@@ -2240,8 +2555,8 @@ function translations(options = {}) {
|
|
|
2240
2555
|
restoreFocus.current = false;
|
|
2241
2556
|
}
|
|
2242
2557
|
}, [mode]);
|
|
2243
|
-
if (!origin && !translation) return /* @__PURE__ */
|
|
2244
|
-
const toggle = origin && translation ? /* @__PURE__ */
|
|
2558
|
+
if (!origin && !translation) return /* @__PURE__ */ jsx12(Fragment4, { children });
|
|
2559
|
+
const toggle = origin && translation ? /* @__PURE__ */ jsx12(
|
|
2245
2560
|
InlineMarker,
|
|
2246
2561
|
{
|
|
2247
2562
|
ref: marker,
|
|
@@ -2255,12 +2570,12 @@ function translations(options = {}) {
|
|
|
2255
2570
|
if (globalMode !== void 0) onGlobalChange?.(next);
|
|
2256
2571
|
else setLocalMode(next);
|
|
2257
2572
|
},
|
|
2258
|
-
children: /* @__PURE__ */
|
|
2573
|
+
children: /* @__PURE__ */ jsx12(TranslationIcon, { mode })
|
|
2259
2574
|
}
|
|
2260
2575
|
) : void 0;
|
|
2261
2576
|
return /* @__PURE__ */ jsxs7("div", { className: "limr-translations", "data-mode": mode, children: [
|
|
2262
|
-
translation && /* @__PURE__ */
|
|
2263
|
-
origin && /* @__PURE__ */
|
|
2577
|
+
translation && /* @__PURE__ */ jsx12(Collapse, { open: mode !== "origin", keepMounted: true, className: "limr-translation-panel", children: /* @__PURE__ */ jsx12("div", { className: "limr-translation-text", "data-language": "translation", children: renderChildren(translation.children ?? [], { trailing: mode === "translation" ? toggle : void 0 }) }) }),
|
|
2578
|
+
origin && /* @__PURE__ */ jsx12(Collapse, { open: mode !== "translation", keepMounted: true, className: "limr-translation-panel", children: /* @__PURE__ */ jsx12("div", { className: "limr-translation-text", "data-language": "origin", children: renderChildren(origin.children ?? [], { trailing: mode !== "translation" ? toggle : void 0 }) }) })
|
|
2264
2579
|
] });
|
|
2265
2580
|
}
|
|
2266
2581
|
return {
|
|
@@ -2270,16 +2585,338 @@ function translations(options = {}) {
|
|
|
2270
2585
|
display: "block",
|
|
2271
2586
|
scope: "local",
|
|
2272
2587
|
parameters: { translationMode: void 0, onTranslationModeChange: void 0 },
|
|
2273
|
-
components: { translations: Translations, origin: ({ children }) => /* @__PURE__ */
|
|
2588
|
+
components: { translations: Translations, origin: ({ children }) => /* @__PURE__ */ jsx12(Fragment4, { children }), translation: ({ children }) => /* @__PURE__ */ jsx12(Fragment4, { children }) }
|
|
2274
2589
|
};
|
|
2275
2590
|
}
|
|
2276
2591
|
|
|
2277
|
-
// src/extensions/
|
|
2278
|
-
import { useState as
|
|
2592
|
+
// src/extensions/mermaid.tsx
|
|
2593
|
+
import { useEffect as useEffect6, useRef as useRef11, useState as useState4 } from "react";
|
|
2594
|
+
|
|
2595
|
+
// src/components/LoadingRing.tsx
|
|
2596
|
+
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2597
|
+
function LoadingRing() {
|
|
2598
|
+
const locale = useLocale();
|
|
2599
|
+
return /* @__PURE__ */ jsx13("span", { className: "limr-loading", role: "status", "aria-label": locale.loading, "data-limr-ignore": "true", children: /* @__PURE__ */ jsxs8("svg", { viewBox: "0 0 32 32", "aria-hidden": "true", children: [
|
|
2600
|
+
/* @__PURE__ */ jsx13("circle", { className: "limr-loading-track", cx: "16", cy: "16", r: "12" }),
|
|
2601
|
+
/* @__PURE__ */ jsx13("g", { className: "limr-loading-orbit", children: /* @__PURE__ */ jsx13("circle", { className: "limr-loading-arc", cx: "16", cy: "16", r: "12", pathLength: "100" }) })
|
|
2602
|
+
] }) });
|
|
2603
|
+
}
|
|
2604
|
+
function BlockLoading() {
|
|
2605
|
+
return /* @__PURE__ */ jsx13("div", { className: "limr-block-loading", children: /* @__PURE__ */ jsx13(LoadingRing, {}) });
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
// src/components/ToolIcon.tsx
|
|
2609
|
+
import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2610
|
+
function ToolIcon({ name, ...props }) {
|
|
2611
|
+
return /* @__PURE__ */ jsx14("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsxs9("g", { transform: name === "highlight" ? "translate(0 -1.25)" : name === "comment" ? "translate(0 -.5)" : void 0, children: [
|
|
2612
|
+
(name === "eye" || name === "eye-off") && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2613
|
+
/* @__PURE__ */ jsx14("path", { d: "M3 12s3.3-6 9-6 9 6 9 6-3.3 6-9 6-9-6-9-6Z" }),
|
|
2614
|
+
/* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "2.7" }),
|
|
2615
|
+
name === "eye-off" && /* @__PURE__ */ jsx14("path", { d: "m4 4 16 16" })
|
|
2616
|
+
] }),
|
|
2617
|
+
name === "question" && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2618
|
+
/* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "8.5" }),
|
|
2619
|
+
/* @__PURE__ */ jsx14("path", { d: "M9.4 9a2.7 2.7 0 0 1 5.2 1c0 1.8-2.6 2-2.6 3.7M12 17h.01" })
|
|
2620
|
+
] }),
|
|
2621
|
+
name === "highlight" && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2622
|
+
/* @__PURE__ */ jsx14("path", { d: "m8 15 7.6-9a2 2 0 0 1 2.8-.2l.8.7a2 2 0 0 1 .2 2.8L12 18l-4-3Z" }),
|
|
2623
|
+
/* @__PURE__ */ jsx14("path", { d: "m8 15-2 3 3 1 3-1M4 21h10M14 8l4 3.5" })
|
|
2624
|
+
] }),
|
|
2625
|
+
name === "edit" && /* @__PURE__ */ jsx14(Fragment5, { children: /* @__PURE__ */ jsx14("path", { d: "m14.5 5.5 4 4M4.5 19.5l4.5-1 11-11a2.1 2.1 0 0 0 0-3 2.1 2.1 0 0 0-3 0l-11 11-1.5 4Z" }) }),
|
|
2626
|
+
name === "close" && /* @__PURE__ */ jsx14("path", { d: "m6 6 12 12M18 6 6 18" }),
|
|
2627
|
+
name === "copy" && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2628
|
+
/* @__PURE__ */ jsx14("rect", { x: "8.5", y: "8", width: "10.5", height: "12", rx: "3" }),
|
|
2629
|
+
/* @__PURE__ */ jsx14("path", { d: "M15.5 8V6.8A2.8 2.8 0 0 0 12.7 4H7A3 3 0 0 0 4 7v6a3 3 0 0 0 3 3h1.5" })
|
|
2630
|
+
] }),
|
|
2631
|
+
(name === "zoom-in" || name === "zoom-out") && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2632
|
+
/* @__PURE__ */ jsx14("circle", { cx: "10.5", cy: "10.5", r: "6.5" }),
|
|
2633
|
+
/* @__PURE__ */ jsx14("path", { d: "m15.4 15.4 4.6 4.6M7.5 10.5h6" }),
|
|
2634
|
+
name === "zoom-in" && /* @__PURE__ */ jsx14("path", { d: "M10.5 7.5v6" })
|
|
2635
|
+
] }),
|
|
2636
|
+
name === "source" && /* @__PURE__ */ jsx14(Fragment5, { children: /* @__PURE__ */ jsx14("path", { d: "m7 7-4 5 4 5m10-10 4 5-4 5m-4-13-2 16" }) }),
|
|
2637
|
+
name === "image" && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2638
|
+
/* @__PURE__ */ jsx14("rect", { x: "3.5", y: "4.5", width: "17", height: "15", rx: "3.5" }),
|
|
2639
|
+
/* @__PURE__ */ jsx14("circle", { cx: "15.5", cy: "9", r: "1.5" }),
|
|
2640
|
+
/* @__PURE__ */ jsx14("path", { d: "m4 16 4.4-4.4a1.5 1.5 0 0 1 2.2 0L17 19m-3-3 1.4-1.4a1.5 1.5 0 0 1 2.2 0L20 17" })
|
|
2641
|
+
] }),
|
|
2642
|
+
["background", "underline", "dotted", "wavy"].includes(name) && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2643
|
+
name === "background" && /* @__PURE__ */ jsx14("rect", { x: "3", y: "3", width: "18", height: "18", rx: "5", fill: "currentColor", fillOpacity: ".13", stroke: "none" }),
|
|
2644
|
+
/* @__PURE__ */ jsx14("path", { d: "m8 15 3-8a1.05 1.05 0 0 1 2 0l3 8M9.2 12h5.6" }),
|
|
2645
|
+
name === "background" && /* @__PURE__ */ jsx14("path", { d: "M7 19h10", strokeWidth: "2.5" }),
|
|
2646
|
+
name === "underline" && /* @__PURE__ */ jsx14("path", { d: "M5 20h14" }),
|
|
2647
|
+
name === "dotted" && /* @__PURE__ */ jsx14("path", { d: "M5 20h14", strokeDasharray: ".1 3.4", strokeWidth: "2.4" }),
|
|
2648
|
+
name === "wavy" && /* @__PURE__ */ jsx14("path", { d: "M4 20c1.3-2 2.7-2 4 0s2.7 2 4 0 2.7-2 4 0 2.7 2 4 0" })
|
|
2649
|
+
] }),
|
|
2650
|
+
name === "chevron" && /* @__PURE__ */ jsx14("path", { d: "m8 10 4 4 4-4" }),
|
|
2651
|
+
name === "check" && /* @__PURE__ */ jsx14("path", { d: "m5.5 12 4.2 4.2 8.8-9" }),
|
|
2652
|
+
name === "trash" && /* @__PURE__ */ jsx14(Fragment5, { children: /* @__PURE__ */ jsx14("path", { d: "M4.5 7h15M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2M7 7l.7 12a2 2 0 0 0 2 2h4.6a2 2 0 0 0 2-2L17 7M10 11v6M14 11v6" }) }),
|
|
2653
|
+
name === "note" && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2654
|
+
/* @__PURE__ */ jsx14("path", { d: "M14 3H7a3 3 0 0 0-3 3v12a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V9l-6-6Z" }),
|
|
2655
|
+
/* @__PURE__ */ jsx14("path", { d: "M14 3v4a2 2 0 0 0 2 2h4M8 13h8M8 17h5" })
|
|
2656
|
+
] }),
|
|
2657
|
+
name === "comment" && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2658
|
+
/* @__PURE__ */ jsx14("path", { d: "M8 19 4 21V7a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v9a3 3 0 0 1-3 3H8Z" }),
|
|
2659
|
+
/* @__PURE__ */ jsx14("path", { d: "M8 9h8M8 13h5" })
|
|
2660
|
+
] }),
|
|
2661
|
+
name === "footnote" && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2662
|
+
/* @__PURE__ */ jsx14("path", { d: "M5 7h9M5 11h12M5 15h8M5 20h14M18 4h2v5" }),
|
|
2663
|
+
/* @__PURE__ */ jsx14("path", { d: "M17.5 9h4" })
|
|
2664
|
+
] }),
|
|
2665
|
+
name === "sparkles" && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2666
|
+
/* @__PURE__ */ jsx14("path", { d: "m10.5 4 1.8 4.8 4.7 1.7-4.7 1.8-1.8 4.7-1.7-4.7L4 10.5l4.8-1.7L10.5 4Z" }),
|
|
2667
|
+
/* @__PURE__ */ jsx14("path", { d: "m19 15 .8 2.2L22 18l-2.2.8L19 21l-.8-2.2L16 18l2.2-.8L19 15ZM19 3v4M17 5h4" })
|
|
2668
|
+
] })
|
|
2669
|
+
] }) });
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2672
|
+
// src/extensions/mermaid.tsx
|
|
2673
|
+
import { Fragment as Fragment6, jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2674
|
+
var nextId = 0;
|
|
2675
|
+
var queue = Promise.resolve();
|
|
2676
|
+
var cache2 = new ResourceCache(32);
|
|
2677
|
+
async function diagram(id, code, dark, font, signal) {
|
|
2678
|
+
let result = "";
|
|
2679
|
+
const work = queue.then(async () => {
|
|
2680
|
+
if (signal.aborted) throw signal.reason;
|
|
2681
|
+
const { default: mermaid2 } = await import("mermaid");
|
|
2682
|
+
await document.fonts.ready;
|
|
2683
|
+
if (signal.aborted) throw signal.reason;
|
|
2684
|
+
mermaid2.initialize({
|
|
2685
|
+
startOnLoad: false,
|
|
2686
|
+
securityLevel: "strict",
|
|
2687
|
+
suppressErrorRendering: true,
|
|
2688
|
+
fontFamily: font,
|
|
2689
|
+
theme: "base",
|
|
2690
|
+
themeVariables: dark ? { background: "#242321", primaryColor: "#383531", primaryTextColor: "#e2ded7", primaryBorderColor: "#7b746a", lineColor: "#a29a8e", secondaryColor: "#302e2a", tertiaryColor: "#302e2a" } : { background: "#f9f8f6", primaryColor: "#eeebe6", primaryTextColor: "#49443e", primaryBorderColor: "#b5aca0", lineColor: "#91877a", secondaryColor: "#f5f3ef", tertiaryColor: "#f5f3ef" }
|
|
2691
|
+
});
|
|
2692
|
+
const host = document.createElement("div");
|
|
2693
|
+
host.style.cssText = "position:fixed;left:-100000px;top:0;visibility:hidden;pointer-events:none";
|
|
2694
|
+
host.style.fontFamily = font;
|
|
2695
|
+
document.body.append(host);
|
|
2696
|
+
try {
|
|
2697
|
+
result = (await mermaid2.render(id, code, host)).svg;
|
|
2698
|
+
} finally {
|
|
2699
|
+
host.remove();
|
|
2700
|
+
}
|
|
2701
|
+
});
|
|
2702
|
+
queue = work.catch(() => {
|
|
2703
|
+
});
|
|
2704
|
+
await work;
|
|
2705
|
+
return result;
|
|
2706
|
+
}
|
|
2707
|
+
function MermaidNode({ node, incomplete }) {
|
|
2708
|
+
const locale = useLocale(), theme = useTheme(), runtime = useRuntime();
|
|
2709
|
+
const zh = locale.language?.startsWith("zh");
|
|
2710
|
+
const [id] = useState4(() => `limr-mermaid-${++nextId}`);
|
|
2711
|
+
const [systemDark, setSystemDark] = useState4(false);
|
|
2712
|
+
const [result, setResult] = useState4();
|
|
2713
|
+
const [sourceView, setSourceView] = useState4(false), [scale, setScale] = useState4(1), [attempt, setAttempt] = useState4(0);
|
|
2714
|
+
const ref = useRef11(null), content = useRef11(null);
|
|
2715
|
+
const drag = useRef11(null);
|
|
2716
|
+
const suppressClick = useRef11(false);
|
|
2717
|
+
const code = node.value ?? "";
|
|
2718
|
+
const dark = theme === "dark" || theme === "auto" && systemDark;
|
|
2719
|
+
const key = JSON.stringify([id, code, dark, attempt]);
|
|
2720
|
+
const current = result?.key === key ? result : void 0;
|
|
2721
|
+
useEffect6(() => {
|
|
2722
|
+
if (theme !== "auto") return;
|
|
2723
|
+
const media = matchMedia("(prefers-color-scheme: dark)");
|
|
2724
|
+
const update = () => setSystemDark(media.matches);
|
|
2725
|
+
update();
|
|
2726
|
+
media.addEventListener("change", update);
|
|
2727
|
+
return () => media.removeEventListener("change", update);
|
|
2728
|
+
}, [theme]);
|
|
2729
|
+
useEffect6(() => {
|
|
2730
|
+
if (incomplete) return;
|
|
2731
|
+
let disposed = false;
|
|
2732
|
+
const font = ref.current ? getComputedStyle(ref.current).fontFamily : "sans-serif";
|
|
2733
|
+
const request = cache2.acquire(`${key}:${font}`, (signal) => diagram(id, code, dark, font, signal));
|
|
2734
|
+
request.promise.then((svg) => {
|
|
2735
|
+
if (!disposed) setResult({ key, svg });
|
|
2736
|
+
}, () => {
|
|
2737
|
+
if (!disposed) setResult({ key, error: true });
|
|
2738
|
+
});
|
|
2739
|
+
return () => {
|
|
2740
|
+
disposed = true;
|
|
2741
|
+
request.release();
|
|
2742
|
+
};
|
|
2743
|
+
}, [key, incomplete]);
|
|
2744
|
+
useStreamEntrance(content, !!current?.svg, current?.svg);
|
|
2745
|
+
const loading2 = incomplete || !current;
|
|
2746
|
+
const source = sourceView || current?.error;
|
|
2747
|
+
useEffect6(() => {
|
|
2748
|
+
const viewport = content.current;
|
|
2749
|
+
if (!viewport || source) return;
|
|
2750
|
+
const wheel = (event) => {
|
|
2751
|
+
if (!event.shiftKey || event.ctrlKey || event.metaKey || !event.deltaY || viewport.scrollWidth <= viewport.clientWidth) return;
|
|
2752
|
+
const unit = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? viewport.clientWidth : 1;
|
|
2753
|
+
viewport.scrollLeft += (event.deltaX || event.deltaY) * unit;
|
|
2754
|
+
event.preventDefault();
|
|
2755
|
+
};
|
|
2756
|
+
viewport.addEventListener("wheel", wheel, { passive: false });
|
|
2757
|
+
return () => viewport.removeEventListener("wheel", wheel);
|
|
2758
|
+
}, [loading2, source]);
|
|
2759
|
+
const select = () => {
|
|
2760
|
+
const canvas = content.current?.firstElementChild;
|
|
2761
|
+
if (!canvas) return;
|
|
2762
|
+
const range = document.createRange();
|
|
2763
|
+
range.selectNodeContents(canvas);
|
|
2764
|
+
const selection = canvas.ownerDocument.getSelection();
|
|
2765
|
+
selection?.removeAllRanges();
|
|
2766
|
+
selection?.addRange(range);
|
|
2767
|
+
};
|
|
2768
|
+
const label = sourceView ? zh ? "\u663E\u793A\u56FE\u50CF" : "Show diagram" : zh ? "\u663E\u793A\u6E90\u4EE3\u7801" : "Show source";
|
|
2769
|
+
return /* @__PURE__ */ jsxs10("div", { className: "limr-math-block limr-mermaid-block", ref, "data-mermaid-state": loading2 ? "loading" : current?.error ? "error" : "ready", children: [
|
|
2770
|
+
/* @__PURE__ */ jsxs10("div", { className: "limr-math-display limr-mermaid-display", children: [
|
|
2771
|
+
loading2 && /* @__PURE__ */ jsx15("div", { className: "limr-mermaid-loading", children: /* @__PURE__ */ jsx15(LoadingRing, {}) }),
|
|
2772
|
+
!loading2 && /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
2773
|
+
current?.error && /* @__PURE__ */ jsxs10("div", { className: "limr-mermaid-error", "data-limr-ignore": "true", role: "status", children: [
|
|
2774
|
+
zh ? "\u56FE\u8868\u6682\u65F6\u65E0\u6CD5\u7ED8\u5236" : "Unable to render diagram",
|
|
2775
|
+
" ",
|
|
2776
|
+
/* @__PURE__ */ jsx15("button", { type: "button", onClick: () => setAttempt((value) => value + 1), children: locale.retry })
|
|
2777
|
+
] }),
|
|
2778
|
+
/* @__PURE__ */ jsx15("pre", { className: "limr-mermaid-source", hidden: !source, children: /* @__PURE__ */ jsx15("code", { children: code }) }),
|
|
2779
|
+
/* @__PURE__ */ jsx15(
|
|
2780
|
+
"div",
|
|
2781
|
+
{
|
|
2782
|
+
className: "limr-mermaid-viewport",
|
|
2783
|
+
hidden: !!source,
|
|
2784
|
+
ref: content,
|
|
2785
|
+
tabIndex: 0,
|
|
2786
|
+
role: "region",
|
|
2787
|
+
"aria-label": zh ? "\u56FE\u8868\u89C6\u53E3" : "Diagram viewport",
|
|
2788
|
+
"aria-description": zh ? "\u62D6\u52A8\u5E73\u79FB\uFF1B\u65B9\u5411\u952E\u6216\u6EDA\u8F6E\u79FB\u52A8\uFF0CShift \u52A0\u6EDA\u8F6E\u6A2A\u5411\u79FB\u52A8\uFF1B\u5355\u51FB\u6216\u6309 Enter \u6574\u5757\u9009\u62E9\u3002" : "Drag to pan; use arrow keys or the wheel to scroll, Shift+wheel to scroll horizontally; click or press Enter to select the block.",
|
|
2789
|
+
onDragStart: (event) => event.preventDefault(),
|
|
2790
|
+
onPointerDown: (event) => {
|
|
2791
|
+
suppressClick.current = false;
|
|
2792
|
+
if (event.button !== 0 || event.pointerType === "touch") return;
|
|
2793
|
+
const viewport = event.currentTarget;
|
|
2794
|
+
const bounds = viewport.getBoundingClientRect();
|
|
2795
|
+
if (event.clientX >= bounds.left + viewport.clientLeft + viewport.clientWidth || event.clientY >= bounds.top + viewport.clientTop + viewport.clientHeight) return;
|
|
2796
|
+
event.preventDefault();
|
|
2797
|
+
viewport.focus({ preventScroll: true });
|
|
2798
|
+
drag.current = { id: event.pointerId, x: event.clientX, y: event.clientY, left: viewport.scrollLeft, top: viewport.scrollTop, moved: false };
|
|
2799
|
+
viewport.setPointerCapture(event.pointerId);
|
|
2800
|
+
},
|
|
2801
|
+
onPointerMove: (event) => {
|
|
2802
|
+
const gesture = drag.current;
|
|
2803
|
+
if (!gesture || gesture.id !== event.pointerId) return;
|
|
2804
|
+
const x = event.clientX - gesture.x, y = event.clientY - gesture.y;
|
|
2805
|
+
if (!gesture.moved && Math.hypot(x, y) <= 4) return;
|
|
2806
|
+
if (!gesture.moved) {
|
|
2807
|
+
gesture.moved = true;
|
|
2808
|
+
runtime.clearSelection();
|
|
2809
|
+
event.currentTarget.dataset.dragging = "true";
|
|
2810
|
+
}
|
|
2811
|
+
event.currentTarget.scrollTo(gesture.left - x, gesture.top - y);
|
|
2812
|
+
},
|
|
2813
|
+
onPointerUp: (event) => {
|
|
2814
|
+
if (drag.current?.id !== event.pointerId) return;
|
|
2815
|
+
suppressClick.current = drag.current.moved;
|
|
2816
|
+
drag.current = null;
|
|
2817
|
+
delete event.currentTarget.dataset.dragging;
|
|
2818
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);
|
|
2819
|
+
},
|
|
2820
|
+
onLostPointerCapture: (event) => {
|
|
2821
|
+
drag.current = null;
|
|
2822
|
+
delete event.currentTarget.dataset.dragging;
|
|
2823
|
+
},
|
|
2824
|
+
onClick: (event) => {
|
|
2825
|
+
if (!event.defaultPrevented && !suppressClick.current && !event.ctrlKey && !event.metaKey && !event.shiftKey && !event.altKey) select();
|
|
2826
|
+
},
|
|
2827
|
+
onKeyDown: (event) => {
|
|
2828
|
+
if (event.altKey || event.ctrlKey || event.metaKey) return;
|
|
2829
|
+
const viewport = event.currentTarget;
|
|
2830
|
+
const moves = { ArrowLeft: [-48, 0], ArrowRight: [48, 0], ArrowUp: [0, -48], ArrowDown: [0, 48], PageUp: [0, -viewport.clientHeight * 0.9], PageDown: [0, viewport.clientHeight * 0.9] };
|
|
2831
|
+
if (moves[event.key]) viewport.scrollBy(...moves[event.key]);
|
|
2832
|
+
else if (event.key === "Home") viewport.scrollTo(0, 0);
|
|
2833
|
+
else if (event.key === "End") viewport.scrollTo(viewport.scrollWidth, viewport.scrollHeight);
|
|
2834
|
+
else if (event.key === "Enter") select();
|
|
2835
|
+
else return;
|
|
2836
|
+
event.preventDefault();
|
|
2837
|
+
},
|
|
2838
|
+
children: /* @__PURE__ */ jsx15("div", { className: "limr-mermaid-canvas", style: { width: `${scale * 100}%` }, role: "img", "aria-label": zh ? "Mermaid \u56FE\u8868" : "Mermaid diagram", dangerouslySetInnerHTML: { __html: current?.svg ?? "" } })
|
|
2839
|
+
}
|
|
2840
|
+
)
|
|
2841
|
+
] })
|
|
2842
|
+
] }),
|
|
2843
|
+
/* @__PURE__ */ jsxs10("div", { className: "limr-block-tools", "data-limr-ignore": "true", role: "group", "aria-label": zh ? "\u56FE\u8868\u5DE5\u5177" : "Diagram tools", children: [
|
|
2844
|
+
/* @__PURE__ */ jsx15(CopyButton, { value: code, label: zh ? "\u590D\u5236 Mermaid \u6E90\u4EE3\u7801" : "Copy Mermaid source" }),
|
|
2845
|
+
/* @__PURE__ */ jsx15("button", { type: "button", disabled: loading2 || !!source || scale >= 3, title: zh ? "\u653E\u5927" : "Zoom in", "aria-label": zh ? "\u653E\u5927" : "Zoom in", onClick: () => setScale((value) => Math.min(3, +(value + 0.25).toFixed(2))), children: /* @__PURE__ */ jsx15(ToolIcon, { name: "zoom-in" }) }),
|
|
2846
|
+
/* @__PURE__ */ jsx15("button", { type: "button", disabled: loading2 || !!source || scale <= 0.5, title: zh ? "\u7F29\u5C0F" : "Zoom out", "aria-label": zh ? "\u7F29\u5C0F" : "Zoom out", onClick: () => setScale((value) => Math.max(0.5, +(value - 0.25).toFixed(2))), children: /* @__PURE__ */ jsx15(ToolIcon, { name: "zoom-out" }) }),
|
|
2847
|
+
/* @__PURE__ */ jsx15("button", { type: "button", disabled: loading2 || current?.error, title: label, "aria-label": label, "aria-pressed": sourceView, onClick: () => setSourceView((value) => !value), children: /* @__PURE__ */ jsx15(ToolIcon, { name: sourceView ? "image" : "source" }) })
|
|
2848
|
+
] })
|
|
2849
|
+
] });
|
|
2850
|
+
}
|
|
2851
|
+
function mermaid() {
|
|
2852
|
+
return {
|
|
2853
|
+
name: "mermaid",
|
|
2854
|
+
directives: ["mermaid"],
|
|
2855
|
+
literal: true,
|
|
2856
|
+
scope: "local",
|
|
2857
|
+
components: { mermaid: MermaidNode },
|
|
2858
|
+
transform(root, context) {
|
|
2859
|
+
literalDirective(root, context.source, "mermaid");
|
|
2860
|
+
walk(root, (node) => {
|
|
2861
|
+
if (node.type === "code" && String(node.lang).toLowerCase() === "mermaid") node.type = "mermaid";
|
|
2862
|
+
if (node.type === "mermaid") node.selection = "atomic";
|
|
2863
|
+
});
|
|
2864
|
+
}
|
|
2865
|
+
};
|
|
2866
|
+
}
|
|
2867
|
+
|
|
2868
|
+
// src/extensions/callout.tsx
|
|
2869
|
+
import { useState as useState5 } from "react";
|
|
2870
|
+
|
|
2871
|
+
// src/extensions/inline-source.ts
|
|
2872
|
+
function point(source, offset, base) {
|
|
2873
|
+
const between = source.slice(base.offset, offset), breaks = [...between.matchAll(/\r\n|\r|\n/g)], last = breaks.at(-1);
|
|
2874
|
+
return { offset, line: base.line + breaks.length, column: last ? between.length - last.index - last[0].length + 1 : base.column + between.length };
|
|
2875
|
+
}
|
|
2876
|
+
function sliceInline(node, from, until, source) {
|
|
2877
|
+
if (!node.position) return;
|
|
2878
|
+
const range = rangeOf(node);
|
|
2879
|
+
if (range.end <= from || range.start >= until) return;
|
|
2880
|
+
if (range.start >= from && range.end <= until) return node;
|
|
2881
|
+
let start = Math.max(range.start, from), end = Math.min(range.end, until);
|
|
2882
|
+
const result = { ...node };
|
|
2883
|
+
if (node.type === "text") {
|
|
2884
|
+
const value = (node.value ?? "").replace(/\r\n?/g, "\n"), mapped = mapText(source, value, range);
|
|
2885
|
+
const first = mapped.ends.findIndex((offset) => offset > start);
|
|
2886
|
+
let last = mapped.starts.findIndex((offset) => offset >= end);
|
|
2887
|
+
if (first < 0) return;
|
|
2888
|
+
if (last < 0) last = mapped.starts.length;
|
|
2889
|
+
if (last <= first) return;
|
|
2890
|
+
result.value = value.slice(first, last);
|
|
2891
|
+
start = mapped.starts[first];
|
|
2892
|
+
end = mapped.ends[last - 1];
|
|
2893
|
+
}
|
|
2894
|
+
if (node.children) result.children = sliceChildren(node.children, start, end, source);
|
|
2895
|
+
result.position = { start: point(source, start, node.position.start), end: point(source, end, node.position.start) };
|
|
2896
|
+
return result;
|
|
2897
|
+
}
|
|
2898
|
+
function sliceChildren(children, from, until, source) {
|
|
2899
|
+
return children.flatMap((child) => {
|
|
2900
|
+
const value = sliceInline(child, from, until, source);
|
|
2901
|
+
return value ? [value] : [];
|
|
2902
|
+
});
|
|
2903
|
+
}
|
|
2904
|
+
function textTokens(children, expression, source) {
|
|
2905
|
+
return children.flatMap((node) => {
|
|
2906
|
+
if (node.type !== "text" || !node.value || !node.position) return [];
|
|
2907
|
+
const matches = [...node.value.matchAll(expression)];
|
|
2908
|
+
if (!matches.length) return [];
|
|
2909
|
+
const map = mapText(source, node.value, rangeOf(node));
|
|
2910
|
+
return matches.flatMap((match) => {
|
|
2911
|
+
const start = map.starts[match.index], end = map.ends[match.index + match[0].length - 1];
|
|
2912
|
+
return source.slice(start, end) === match[0] ? [{ start, end }] : [];
|
|
2913
|
+
});
|
|
2914
|
+
});
|
|
2915
|
+
}
|
|
2279
2916
|
|
|
2280
2917
|
// src/extensions/define.ts
|
|
2281
|
-
function defineBlock({ name, component, tags = [name], directives = [name], selection = "content" }) {
|
|
2282
|
-
return { name, tags, directives, selection, display: "block", scope: "local", components: Object.fromEntries([.../* @__PURE__ */ new Set([...tags, ...directives])].map((tag) => [tag, component])) };
|
|
2918
|
+
function defineBlock({ name, component, tags = [name], directives = [name], selection = "content", streaming }) {
|
|
2919
|
+
return { name, tags, directives, selection, streaming, display: "block", scope: "local", components: Object.fromEntries([.../* @__PURE__ */ new Set([...tags, ...directives])].map((tag) => [tag, component])) };
|
|
2283
2920
|
}
|
|
2284
2921
|
function defineAnnotation(type) {
|
|
2285
2922
|
return { name: `annotation:${type.type}`, annotationTypes: [type], scope: "local" };
|
|
@@ -2288,43 +2925,293 @@ function defineExtension(extension) {
|
|
|
2288
2925
|
return extension;
|
|
2289
2926
|
}
|
|
2290
2927
|
|
|
2928
|
+
// src/extensions/callout.tsx
|
|
2929
|
+
import { Fragment as Fragment7, jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2930
|
+
var types = {
|
|
2931
|
+
note: { color: "#6488b5", icon: "edit" },
|
|
2932
|
+
abstract: { color: "#4b9ba0", icon: "note" },
|
|
2933
|
+
info: { color: "#6488b5", icon: "note" },
|
|
2934
|
+
todo: { color: "#6488b5", icon: "check" },
|
|
2935
|
+
tip: { color: "#4b9b8d", icon: "sparkles" },
|
|
2936
|
+
success: { color: "#659664", icon: "check" },
|
|
2937
|
+
question: { color: "#b38b4e", icon: "question" },
|
|
2938
|
+
warning: { color: "#bc8850", icon: "question" },
|
|
2939
|
+
failure: { color: "#be6967", icon: "close" },
|
|
2940
|
+
danger: { color: "#be6967", icon: "close" },
|
|
2941
|
+
bug: { color: "#be6967", icon: "note" },
|
|
2942
|
+
example: { color: "#9580b4", icon: "note" },
|
|
2943
|
+
quote: { color: "#928b80", icon: "comment" }
|
|
2944
|
+
};
|
|
2945
|
+
var aliases2 = { summary: "abstract", tldr: "abstract", hint: "tip", important: "tip", check: "success", done: "success", help: "question", faq: "question", caution: "warning", attention: "warning", fail: "failure", missing: "failure", error: "danger", cite: "quote" };
|
|
2946
|
+
function calloutType(value) {
|
|
2947
|
+
const name = value.toLowerCase();
|
|
2948
|
+
return aliases2[name] ?? (Object.hasOwn(types, name) ? name : "note");
|
|
2949
|
+
}
|
|
2950
|
+
function Callout({ node, renderChildren, renderAttribute }) {
|
|
2951
|
+
const zh = useLocale().language?.startsWith("zh");
|
|
2952
|
+
const name = String(node.attributes?.type ?? "note").toLowerCase(), type = calloutType(name), style = types[type];
|
|
2953
|
+
const title = node.children?.find((child) => child.type === "calloutTitle");
|
|
2954
|
+
const body = node.children?.filter((child) => child.type !== "calloutTitle") ?? [];
|
|
2955
|
+
const fold = node.attributes?.fold;
|
|
2956
|
+
const [expanded, setExpanded] = useState5(fold !== "-" && fold !== "closed");
|
|
2957
|
+
const content = /* @__PURE__ */ jsx16("div", { className: "limr-block-content", children: renderChildren(body) });
|
|
2958
|
+
const label = /* @__PURE__ */ jsxs11(Fragment7, { children: [
|
|
2959
|
+
/* @__PURE__ */ jsx16(ToolIcon, { name: style.icon, "data-limr-ignore": "true" }),
|
|
2960
|
+
/* @__PURE__ */ jsx16("span", { children: title ? renderChildren(title.children ?? []) : node.attributes?.title ? renderAttribute("title") : /* @__PURE__ */ jsx16("span", { "data-limr-ignore": "true", children: name.charAt(0).toUpperCase() + name.slice(1) }) })
|
|
2961
|
+
] });
|
|
2962
|
+
return /* @__PURE__ */ jsxs11("aside", { className: "limr-note limr-callout", "data-callout": name, "data-callout-type": type, style: { "--limr-callout-color": style.color }, children: [
|
|
2963
|
+
/* @__PURE__ */ jsxs11("div", { className: "limr-card-label limr-callout-title", children: [
|
|
2964
|
+
label,
|
|
2965
|
+
fold && /* @__PURE__ */ jsx16("button", { type: "button", className: "limr-callout-toggle", "aria-label": expanded ? zh ? "\u6536\u8D77\u63D0\u793A\u5757" : "Collapse callout" : zh ? "\u5C55\u5F00\u63D0\u793A\u5757" : "Expand callout", "aria-expanded": expanded, onClick: () => setExpanded((value) => !value), "data-limr-ignore": "true", children: /* @__PURE__ */ jsx16(ToolIcon, { name: "chevron" }) })
|
|
2966
|
+
] }),
|
|
2967
|
+
fold ? /* @__PURE__ */ jsx16(Collapse, { open: expanded, keepMounted: true, children: content }) : content
|
|
2968
|
+
] });
|
|
2969
|
+
}
|
|
2970
|
+
function callout(options = {}) {
|
|
2971
|
+
return {
|
|
2972
|
+
...defineBlock({ name: "callout", component: options.component ?? Callout, streaming: options.component ? void 0 : { Loading: BlockLoading } }),
|
|
2973
|
+
transform(root, context) {
|
|
2974
|
+
walk(root, (node) => {
|
|
2975
|
+
if (node.type !== "blockquote") return;
|
|
2976
|
+
const first = node.children?.[0];
|
|
2977
|
+
if (first?.type !== "paragraph" || !first.position) return;
|
|
2978
|
+
const from = first.position.start.offset, end = first.position.end.offset;
|
|
2979
|
+
const raw = context.source.slice(from, end);
|
|
2980
|
+
const header = /^\[!([\w-]+)\]([+-])?[ \t]*/.exec(raw);
|
|
2981
|
+
if (!header) {
|
|
2982
|
+
if (context.streaming && /^\[![\w-]*$/.test(raw)) {
|
|
2983
|
+
node.type = "callout";
|
|
2984
|
+
node.incomplete = true;
|
|
2985
|
+
node.children = [];
|
|
2986
|
+
}
|
|
2987
|
+
return;
|
|
2988
|
+
}
|
|
2989
|
+
node.type = "callout";
|
|
2990
|
+
node.attributes = { type: header[1].toLowerCase(), ...header[2] ? { fold: header[2] } : {} };
|
|
2991
|
+
const newline = /\r\n|\r|\n/.exec(raw), titleEnd = newline ? from + newline.index : end;
|
|
2992
|
+
const bodyStart = newline ? titleEnd + newline[0].length : end;
|
|
2993
|
+
const title = sliceInline(first, from + header[0].length, titleEnd, context.source);
|
|
2994
|
+
const body = sliceInline(first, bodyStart, end, context.source);
|
|
2995
|
+
node.children = [...title?.children?.length ? [{ ...title, type: "calloutTitle" }] : [], ...body?.children?.length ? [body] : [], ...node.children.slice(1)];
|
|
2996
|
+
});
|
|
2997
|
+
}
|
|
2998
|
+
};
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
// src/extensions/inline-highlights.tsx
|
|
3002
|
+
import { Fragment as Fragment8, jsx as jsx17 } from "react/jsx-runtime";
|
|
3003
|
+
var Content = ({ children }) => /* @__PURE__ */ jsx17(Fragment8, { children });
|
|
3004
|
+
function inlineHighlights(options = {}) {
|
|
3005
|
+
const decorate = (node, range) => {
|
|
3006
|
+
node.type = "embeddedHighlight";
|
|
3007
|
+
node.highlightRange = range;
|
|
3008
|
+
node.annotation = {
|
|
3009
|
+
id: `inline-highlight:${rangeOf(node).start}`,
|
|
3010
|
+
type: "highlight",
|
|
3011
|
+
range,
|
|
3012
|
+
data: { color: options.color ?? "var(--limr-inline-highlight, #6B9BD2)", style: "background", readOnly: true }
|
|
3013
|
+
};
|
|
3014
|
+
};
|
|
3015
|
+
return {
|
|
3016
|
+
name: "inline-highlights",
|
|
3017
|
+
tags: ["highlight"],
|
|
3018
|
+
scope: "local",
|
|
3019
|
+
components: { embeddedHighlight: options.component ?? Content },
|
|
3020
|
+
transform(root, { source, streaming }) {
|
|
3021
|
+
const visit = (node) => {
|
|
3022
|
+
if (!node.children || ["code", "inlineCode", "math", "inlineMath", "html", "footnoteDefinition", "annotationDefinition"].includes(node.type)) return;
|
|
3023
|
+
node.children.forEach(visit);
|
|
3024
|
+
if (node.type === "component" && node.name === "highlight") {
|
|
3025
|
+
const first = node.children[0], last = node.children.at(-1);
|
|
3026
|
+
if (first && last) decorate(node, { start: rangeOf(first).start, end: rangeOf(last).end });
|
|
3027
|
+
return;
|
|
3028
|
+
}
|
|
3029
|
+
const tokens = textTokens(node.children, /(?<!=)==(?!=)/g, source);
|
|
3030
|
+
if (!node.position) return;
|
|
3031
|
+
if (!tokens.length) {
|
|
3032
|
+
const last = node.children.at(-1), end = rangeOf(node).end;
|
|
3033
|
+
if (streaming && end === source.length && last?.type === "text" && source.endsWith("=") && source[end - 2] !== "\\") node.children = sliceChildren(node.children, rangeOf(node).start, end - 1, source);
|
|
3034
|
+
return;
|
|
3035
|
+
}
|
|
3036
|
+
const children = [];
|
|
3037
|
+
let from = rangeOf(node).start;
|
|
3038
|
+
for (let index = 0; index < tokens.length; index += 2) {
|
|
3039
|
+
const open = tokens[index], close = tokens[index + 1];
|
|
3040
|
+
if (!close && (!streaming || rangeOf(node).end < source.trimEnd().length)) break;
|
|
3041
|
+
let end = close?.start ?? rangeOf(node).end;
|
|
3042
|
+
if (!close && source[end - 1] === "=" && source[end - 2] !== "=" && source[end - 2] !== "\\") end--;
|
|
3043
|
+
const body = sliceChildren(node.children, open.end, end, source);
|
|
3044
|
+
if (!body.length && close) continue;
|
|
3045
|
+
children.push(...sliceChildren(node.children, from, open.start, source));
|
|
3046
|
+
const highlight = {
|
|
3047
|
+
type: "embeddedHighlight",
|
|
3048
|
+
inline: true,
|
|
3049
|
+
children: body,
|
|
3050
|
+
incomplete: close ? void 0 : true,
|
|
3051
|
+
position: { start: point(source, open.start, node.position.start), end: point(source, close?.end ?? rangeOf(node).end, node.position.start) }
|
|
3052
|
+
};
|
|
3053
|
+
if (body.length) decorate(highlight, { start: open.end, end });
|
|
3054
|
+
children.push(highlight);
|
|
3055
|
+
from = close?.end ?? rangeOf(node).end;
|
|
3056
|
+
}
|
|
3057
|
+
children.push(...sliceChildren(node.children, from, rangeOf(node).end, source));
|
|
3058
|
+
node.children = children;
|
|
3059
|
+
};
|
|
3060
|
+
visit(root);
|
|
3061
|
+
}
|
|
3062
|
+
};
|
|
3063
|
+
}
|
|
3064
|
+
|
|
3065
|
+
// src/extensions/footnotes.tsx
|
|
3066
|
+
import { useMemo as useMemo3 } from "react";
|
|
3067
|
+
import { fromMarkdown as fromMarkdown2 } from "mdast-util-from-markdown";
|
|
3068
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
3069
|
+
var idFor = (identifier2) => `footnote:${String(identifier2).trim().replace(/\s+/g, " ").toLowerCase()}`;
|
|
3070
|
+
function Icon() {
|
|
3071
|
+
return /* @__PURE__ */ jsx18(ToolIcon, { name: "comment" });
|
|
3072
|
+
}
|
|
3073
|
+
function Content2({ data }) {
|
|
3074
|
+
return /* @__PURE__ */ jsx18(AnnotationMarkdown, { source: data?.body ?? "" });
|
|
3075
|
+
}
|
|
3076
|
+
function Card(props) {
|
|
3077
|
+
return /* @__PURE__ */ jsx18(AnnotationCard, { ...props, title: useLocale().footnotes });
|
|
3078
|
+
}
|
|
3079
|
+
function Preview({ data }) {
|
|
3080
|
+
const summary = useMemo3(() => textContent(fromMarkdown2(data?.body ?? "")).replace(/\s+/g, " ").trim(), [data?.body]);
|
|
3081
|
+
return summary ? /* @__PURE__ */ jsx18("span", { title: summary, children: summary }) : null;
|
|
3082
|
+
}
|
|
3083
|
+
function footnotes(options = {}) {
|
|
3084
|
+
const type = options.type ?? "footnote";
|
|
3085
|
+
const definition2 = (id, body) => ({ id, type, data: { body } });
|
|
3086
|
+
return {
|
|
3087
|
+
name: "footnotes",
|
|
3088
|
+
tags: ["footnote", "footnote-ref"],
|
|
3089
|
+
scope: "local",
|
|
3090
|
+
annotationTypes: [{
|
|
3091
|
+
type,
|
|
3092
|
+
label: (locale) => locale.footnotes,
|
|
3093
|
+
icon: Icon,
|
|
3094
|
+
color: "#6B9BD2",
|
|
3095
|
+
highlight: "hover",
|
|
3096
|
+
Content: Content2,
|
|
3097
|
+
...options,
|
|
3098
|
+
sidebar: { Preview, collapseOnContentClick: false, ...options.sidebar },
|
|
3099
|
+
overlay: { Card, expand: false, ...options.overlay }
|
|
3100
|
+
}],
|
|
3101
|
+
transform(root, { source, streaming }) {
|
|
3102
|
+
const visit = (node) => {
|
|
3103
|
+
if (node.type === "footnoteDefinition") {
|
|
3104
|
+
const range = rangeOf(node), raw = source.slice(range.start, range.end);
|
|
3105
|
+
const body = raw.replace(/^\[\^[^\]]+\]:[ \t]*/, "").replace(/(\r\n|\r|\n)(?: {4}|\t)/g, "$1");
|
|
3106
|
+
node.annotation = definition2(idFor(node.identifier), body);
|
|
3107
|
+
return;
|
|
3108
|
+
}
|
|
3109
|
+
if (node.type === "footnoteReference") {
|
|
3110
|
+
node.type = "annotationReference";
|
|
3111
|
+
node.inline = true;
|
|
3112
|
+
node.annotationIds = [idFor(node.identifier)];
|
|
3113
|
+
return;
|
|
3114
|
+
}
|
|
3115
|
+
if (node.type === "component" && ["footnote", "footnote-ref"].includes(node.name ?? "")) {
|
|
3116
|
+
if (node.incomplete) {
|
|
3117
|
+
node.children = [];
|
|
3118
|
+
return;
|
|
3119
|
+
}
|
|
3120
|
+
const id = idFor(node.attributes?.id ?? "");
|
|
3121
|
+
if (node.name === "footnote") {
|
|
3122
|
+
const first = node.children?.[0], last = node.children?.at(-1);
|
|
3123
|
+
node.type = "annotationDefinition";
|
|
3124
|
+
node.annotation = definition2(id, first && last ? source.slice(rangeOf(first).start, rangeOf(last).end) : String(node.attributes?.body ?? ""));
|
|
3125
|
+
return;
|
|
3126
|
+
}
|
|
3127
|
+
node.type = "annotationReference";
|
|
3128
|
+
node.annotationIds = [id];
|
|
3129
|
+
return;
|
|
3130
|
+
}
|
|
3131
|
+
if (!node.children || ["code", "inlineCode", "math", "inlineMath", "html", "annotationDefinition"].includes(node.type)) return;
|
|
3132
|
+
node.children.forEach(visit);
|
|
3133
|
+
const opens = textTokens(node.children, /\^\[/g, source);
|
|
3134
|
+
if (opens.length && node.position) {
|
|
3135
|
+
const children = [], range = rangeOf(node);
|
|
3136
|
+
let from = range.start;
|
|
3137
|
+
for (const open of opens) {
|
|
3138
|
+
if (open.start < from) continue;
|
|
3139
|
+
let depth = 1, at = open.end;
|
|
3140
|
+
const protectedNodes = node.children.filter((child) => child.type !== "text").map(rangeOf);
|
|
3141
|
+
for (; at < range.end && depth; at++) {
|
|
3142
|
+
const protectedNode = protectedNodes.find((child) => child.start <= at && child.end > at);
|
|
3143
|
+
if (protectedNode) {
|
|
3144
|
+
at = protectedNode.end - 1;
|
|
3145
|
+
continue;
|
|
3146
|
+
}
|
|
3147
|
+
if (source[at] === "\\") {
|
|
3148
|
+
at++;
|
|
3149
|
+
continue;
|
|
3150
|
+
}
|
|
3151
|
+
if (source[at] === "[") depth++;
|
|
3152
|
+
else if (source[at] === "]") depth--;
|
|
3153
|
+
}
|
|
3154
|
+
if (depth) {
|
|
3155
|
+
if (streaming && range.end >= source.trimEnd().length) {
|
|
3156
|
+
children.push(...sliceChildren(node.children, from, open.start, source));
|
|
3157
|
+
from = range.end;
|
|
3158
|
+
break;
|
|
3159
|
+
}
|
|
3160
|
+
continue;
|
|
3161
|
+
}
|
|
3162
|
+
const id = `inline-footnote:${open.start}`;
|
|
3163
|
+
children.push(...sliceChildren(node.children, from, open.start, source), {
|
|
3164
|
+
type: "annotationReference",
|
|
3165
|
+
inline: true,
|
|
3166
|
+
annotationIds: [id],
|
|
3167
|
+
annotation: definition2(id, source.slice(open.end, at - 1)),
|
|
3168
|
+
position: { start: point(source, open.start, node.position.start), end: point(source, at, node.position.start) }
|
|
3169
|
+
});
|
|
3170
|
+
from = at;
|
|
3171
|
+
}
|
|
3172
|
+
children.push(...sliceChildren(node.children, from, range.end, source));
|
|
3173
|
+
node.children = children;
|
|
3174
|
+
}
|
|
3175
|
+
node.children.forEach((child, index) => {
|
|
3176
|
+
const previous = node.children[index - 1];
|
|
3177
|
+
if (child.type === "annotationReference" && previous?.type === "embeddedHighlight" && rangeOf(previous).end === rangeOf(child).start) child.referenceRange = previous.highlightRange;
|
|
3178
|
+
});
|
|
3179
|
+
};
|
|
3180
|
+
visit(root);
|
|
3181
|
+
}
|
|
3182
|
+
};
|
|
3183
|
+
}
|
|
3184
|
+
|
|
3185
|
+
// src/extensions/blocks.tsx
|
|
3186
|
+
import { useState as useState8 } from "react";
|
|
3187
|
+
|
|
2291
3188
|
// src/components/Disclosure.tsx
|
|
2292
|
-
import {
|
|
2293
|
-
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3189
|
+
import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2294
3190
|
function Disclosure({ title, open, onChange, children }) {
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
if (open) {
|
|
2298
|
-
setPresent(true);
|
|
2299
|
-
return;
|
|
2300
|
-
}
|
|
2301
|
-
const timer = setTimeout(() => setPresent(false), 420);
|
|
2302
|
-
return () => clearTimeout(timer);
|
|
2303
|
-
}, [open]);
|
|
2304
|
-
return /* @__PURE__ */ jsxs8("details", { className: "limr-disclosure", open: present || open, "data-expanded": open || void 0, children: [
|
|
2305
|
-
/* @__PURE__ */ jsxs8("summary", { "aria-expanded": open, onClick: (event) => {
|
|
3191
|
+
return /* @__PURE__ */ jsxs12("details", { className: "limr-disclosure", open: true, "data-expanded": open || void 0, children: [
|
|
3192
|
+
/* @__PURE__ */ jsxs12("summary", { "aria-expanded": open, onClick: (event) => {
|
|
2306
3193
|
event.preventDefault();
|
|
2307
3194
|
onChange(!open);
|
|
2308
3195
|
}, "data-limr-ignore": "true", children: [
|
|
2309
|
-
/* @__PURE__ */
|
|
2310
|
-
/* @__PURE__ */
|
|
3196
|
+
/* @__PURE__ */ jsx19("span", { className: "limr-underline", children: title }),
|
|
3197
|
+
/* @__PURE__ */ jsx19("svg", { viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx19("path", { d: "m6 8 4 4 4-4" }) })
|
|
2311
3198
|
] }),
|
|
2312
|
-
/* @__PURE__ */
|
|
3199
|
+
/* @__PURE__ */ jsx19(Collapse, { open, keepMounted: true, children: /* @__PURE__ */ jsx19("div", { className: "limr-question-detail", children }) })
|
|
2313
3200
|
] });
|
|
2314
3201
|
}
|
|
2315
3202
|
|
|
2316
3203
|
// src/components/DiamondCheck.tsx
|
|
2317
|
-
import { jsx as
|
|
3204
|
+
import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2318
3205
|
function DiamondCheck({ checked }) {
|
|
2319
|
-
return /* @__PURE__ */
|
|
2320
|
-
/* @__PURE__ */
|
|
2321
|
-
/* @__PURE__ */
|
|
3206
|
+
return /* @__PURE__ */ jsxs13("svg", { className: "limr-choice-diamond", width: "14", height: "14", viewBox: "0 0 18 18", fill: "none", "aria-hidden": "true", "data-limr-ignore": "true", "data-checked": checked || void 0, children: [
|
|
3207
|
+
/* @__PURE__ */ jsx20("path", { className: "limr-diamond-outline", d: "M9 1.5L16.5 9L9 16.5L1.5 9Z", fill: "none" }),
|
|
3208
|
+
/* @__PURE__ */ jsx20("path", { className: "limr-diamond-fill", d: "M9 5L13 9L9 13L5 9Z", fill: "currentColor" })
|
|
2322
3209
|
] });
|
|
2323
3210
|
}
|
|
2324
3211
|
|
|
2325
3212
|
// src/extensions/video.tsx
|
|
2326
|
-
import { useEffect as
|
|
2327
|
-
import { jsx as
|
|
3213
|
+
import { useEffect as useEffect7, useRef as useRef12, useState as useState6 } from "react";
|
|
3214
|
+
import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2328
3215
|
function resolveVideo(source, provider = "auto") {
|
|
2329
3216
|
const safe = safeUrl(source);
|
|
2330
3217
|
if (!safe) return;
|
|
@@ -2372,21 +3259,21 @@ function video(options = {}) {
|
|
|
2372
3259
|
function Video({ node, source: markdown, renderAttribute }) {
|
|
2373
3260
|
const runtime = useRuntime();
|
|
2374
3261
|
const scrollRoot = useStoreSelector(runtime.configuration, (config) => config.scrollRoot);
|
|
2375
|
-
const element =
|
|
2376
|
-
const [visible, setVisible] =
|
|
2377
|
-
const [playing, setPlaying] =
|
|
2378
|
-
const [failed, setFailed] =
|
|
3262
|
+
const element = useRef12(null);
|
|
3263
|
+
const [visible, setVisible] = useState6(false);
|
|
3264
|
+
const [playing, setPlaying] = useState6(false);
|
|
3265
|
+
const [failed, setFailed] = useState6(false);
|
|
2379
3266
|
const provider = String(node.attributes?.provider ?? "auto");
|
|
2380
3267
|
const source = String(node.attributes?.url ?? node.attributes?.src ?? "");
|
|
2381
3268
|
const requested = node.attributes?.loading ?? options.loading ?? "visible";
|
|
2382
3269
|
const loading2 = requested === "click" || requested === "eager" ? requested : "visible";
|
|
2383
3270
|
const resolved = options.resolveUrl?.(provider, source);
|
|
2384
3271
|
const media = resolved && safeUrl(resolved) ? { url: safeUrl(resolved), native: provider === "native" } : resolveVideo(source, provider);
|
|
2385
|
-
|
|
3272
|
+
useEffect7(() => {
|
|
2386
3273
|
setFailed(false);
|
|
2387
3274
|
setPlaying(false);
|
|
2388
3275
|
}, [source, provider]);
|
|
2389
|
-
|
|
3276
|
+
useEffect7(() => {
|
|
2390
3277
|
if (visible || loading2 !== "visible" || !element.current) return;
|
|
2391
3278
|
if (typeof IntersectionObserver === "undefined") {
|
|
2392
3279
|
setVisible(true);
|
|
@@ -2404,20 +3291,20 @@ function video(options = {}) {
|
|
|
2404
3291
|
const enabled = loading2 === "eager" || loading2 === "visible" && visible || playing;
|
|
2405
3292
|
const title = String(node.attributes?.title ?? `${provider === "auto" ? "Video" : provider} video`);
|
|
2406
3293
|
const original = safeUrl(source);
|
|
2407
|
-
return /* @__PURE__ */
|
|
2408
|
-
/* @__PURE__ */
|
|
2409
|
-
/* @__PURE__ */
|
|
2410
|
-
original && /* @__PURE__ */
|
|
2411
|
-
] }) : enabled ? media.native ? /* @__PURE__ */
|
|
2412
|
-
node.attributes?.title && /* @__PURE__ */
|
|
2413
|
-
/* @__PURE__ */
|
|
3294
|
+
return /* @__PURE__ */ jsxs14("div", { ref: element, className: "limr-video", "data-limr-selection-surface": "", "data-loading": loading2, children: [
|
|
3295
|
+
/* @__PURE__ */ jsx21("div", { className: "limr-video-frame", children: !media || failed ? /* @__PURE__ */ jsxs14("div", { className: "limr-video-error", children: [
|
|
3296
|
+
/* @__PURE__ */ jsx21("span", { children: runtime.locale.unavailable }),
|
|
3297
|
+
original && /* @__PURE__ */ jsx21("a", { href: original, target: "_blank", rel: "noopener noreferrer", children: source })
|
|
3298
|
+
] }) : enabled ? media.native ? /* @__PURE__ */ jsx21("video", { controls: true, playsInline: true, preload: "metadata", src: media.url, "aria-label": title, onError: () => setFailed(true) }) : /* @__PURE__ */ jsx21("iframe", { src: media.url, title, allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", allowFullScreen: true, referrerPolicy: "strict-origin-when-cross-origin", onError: () => setFailed(true) }) : /* @__PURE__ */ jsx21("button", { type: "button", className: "limr-video-play", onClick: () => setPlaying(true), "aria-label": runtime.locale.play, children: /* @__PURE__ */ jsx21("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx21("path", { d: "m8 5 11 7-11 7Z", fill: "currentColor" }) }) }) }),
|
|
3299
|
+
node.attributes?.title && /* @__PURE__ */ jsx21("div", { className: "limr-video-title", children: renderAttribute("title") }),
|
|
3300
|
+
/* @__PURE__ */ jsx21(CopyButton, { className: "limr-video-copy", variant: "glass", value: markdown })
|
|
2414
3301
|
] });
|
|
2415
3302
|
}
|
|
2416
|
-
return defineBlock({ name: "video", tags: ["video", "md-video"], component: options.component ?? Video, selection: "atomic" });
|
|
3303
|
+
return defineBlock({ name: "video", streaming: options.component ? void 0 : { Loading: BlockLoading }, tags: ["video", "md-video"], component: options.component ?? Video, selection: "atomic" });
|
|
2417
3304
|
}
|
|
2418
3305
|
|
|
2419
3306
|
// src/extensions/figures.tsx
|
|
2420
|
-
import { createContext, useContext as useContext2, useEffect as
|
|
3307
|
+
import { createContext, useContext as useContext2, useEffect as useEffect8, useMemo as useMemo4, useRef as useRef13, useState as useState7 } from "react";
|
|
2421
3308
|
|
|
2422
3309
|
// src/extensions/figure-layout.ts
|
|
2423
3310
|
var defaultFigureLimits = { minWidth: 220, maxWidth: 560, minHeight: 120, maxHeight: 480 };
|
|
@@ -2459,7 +3346,7 @@ function figureLimits(attributes = {}, defaults2 = defaultFigureLimits) {
|
|
|
2459
3346
|
}
|
|
2460
3347
|
|
|
2461
3348
|
// src/extensions/figures.tsx
|
|
2462
|
-
import { jsx as
|
|
3349
|
+
import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2463
3350
|
var FigureContext = createContext(defaultFigureLimits);
|
|
2464
3351
|
var captionNode = (node) => node.name === "figcaption" || node.name === "caption";
|
|
2465
3352
|
var flatten = (nodes) => nodes.flatMap((node) => node.type === "paragraph" && node.children?.some((child) => child.name === "figure" || captionNode(child)) ? node.children : [node]);
|
|
@@ -2476,14 +3363,14 @@ function figures(options = {}) {
|
|
|
2476
3363
|
const panels = nodes.filter((child) => child.name === "figure");
|
|
2477
3364
|
const captions = nodes.filter(captionNode);
|
|
2478
3365
|
const body = nodes.filter((child) => !captionNode(child));
|
|
2479
|
-
const limits =
|
|
2480
|
-
const grid =
|
|
2481
|
-
const [columns, setColumns] =
|
|
3366
|
+
const limits = useMemo4(() => figureLimits(node.attributes, defaults2), [node.attributes]);
|
|
3367
|
+
const grid = useRef13(null);
|
|
3368
|
+
const [columns, setColumns] = useState7(1);
|
|
2482
3369
|
const gap = Math.min(100, dimension(node.attributes?.gap, options.gap ?? 16));
|
|
2483
3370
|
const rows = dimension(node.attributes?.rows, options.rows ?? 0);
|
|
2484
3371
|
const requested = dimension(node.attributes?.columns ?? node.attributes?.cols, options.columns ?? 0) || (rows > 0 ? Math.ceil(panels.length / rows) : void 0);
|
|
2485
3372
|
const responsive = String(node.attributes?.responsive ?? options.responsive ?? true) !== "false";
|
|
2486
|
-
|
|
3373
|
+
useEffect8(() => {
|
|
2487
3374
|
const element = grid.current;
|
|
2488
3375
|
if (!element) return;
|
|
2489
3376
|
const measure = () => {
|
|
@@ -2506,22 +3393,22 @@ function figures(options = {}) {
|
|
|
2506
3393
|
element.removeEventListener("error", measure, true);
|
|
2507
3394
|
};
|
|
2508
3395
|
}, [node, limits, gap, requested, responsive]);
|
|
2509
|
-
return /* @__PURE__ */
|
|
2510
|
-
/* @__PURE__ */
|
|
2511
|
-
/* @__PURE__ */
|
|
2512
|
-
captions.length ? renderChildren(captions) : node.attributes?.caption ? /* @__PURE__ */
|
|
3396
|
+
return /* @__PURE__ */ jsxs15("figure", { id: identifier(node), className: "limr-figures", "data-limr-selection-order": "visual", "data-columns": columns, "data-responsive": responsive, children: [
|
|
3397
|
+
/* @__PURE__ */ jsx22(CopyButton, { value: source, label: locale.copyFigures, variant: "glass", className: "limr-figures-copy" }),
|
|
3398
|
+
/* @__PURE__ */ jsx22(FigureContext.Provider, { value: limits, children: /* @__PURE__ */ jsx22("div", { ref: grid, className: "limr-figures-grid", style: { gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`, gridTemplateRows: rows ? `repeat(${Math.max(1, Math.min(24, Math.floor(rows)))}, auto auto)` : void 0, gap }, children: renderChildren(body) }) }),
|
|
3399
|
+
captions.length ? renderChildren(captions) : node.attributes?.caption ? /* @__PURE__ */ jsx22("figcaption", { children: renderAttribute("caption") }) : null
|
|
2513
3400
|
] });
|
|
2514
3401
|
}
|
|
2515
3402
|
function Figure({ node, renderChildren, renderAttribute }) {
|
|
2516
3403
|
const locale = useLocale();
|
|
2517
3404
|
const inherited = useContext2(FigureContext);
|
|
2518
3405
|
const limits = figureLimits(node.attributes, inherited === defaultFigureLimits ? defaults2 : inherited);
|
|
2519
|
-
const media =
|
|
2520
|
-
const [ratio, setRatio] =
|
|
3406
|
+
const media = useRef13(null);
|
|
3407
|
+
const [ratio, setRatio] = useState7(ratioOf(node.attributes?.width, node.attributes?.height));
|
|
2521
3408
|
const nodes = flatten(node.children ?? []);
|
|
2522
3409
|
const captions = nodes.filter(captionNode);
|
|
2523
3410
|
const body = nodes.filter((child) => !captionNode(child));
|
|
2524
|
-
|
|
3411
|
+
useEffect8(() => {
|
|
2525
3412
|
const element = media.current;
|
|
2526
3413
|
if (!element) return;
|
|
2527
3414
|
const measure = () => {
|
|
@@ -2533,23 +3420,24 @@ function figures(options = {}) {
|
|
|
2533
3420
|
return () => element.removeEventListener("load", measure, true);
|
|
2534
3421
|
}, [node]);
|
|
2535
3422
|
const maximum = figureWidths({ ratio, limits }).maximum;
|
|
2536
|
-
return /* @__PURE__ */
|
|
3423
|
+
return /* @__PURE__ */ jsxs15("figure", { id: identifier(node), className: "limr-figure", "data-limr-selection-order": "visual", style: {
|
|
2537
3424
|
"--limr-figure-width": Number.isFinite(maximum) ? `${maximum}px` : "100%",
|
|
2538
3425
|
"--limr-figure-min-height": `${Math.min(limits.minHeight, limits.maxHeight)}px`,
|
|
2539
3426
|
"--limr-figure-max-height": Number.isFinite(limits.maxHeight) ? `${limits.maxHeight}px` : "none"
|
|
2540
3427
|
}, children: [
|
|
2541
|
-
/* @__PURE__ */
|
|
2542
|
-
/* @__PURE__ */
|
|
3428
|
+
/* @__PURE__ */ jsx22("div", { ref: media, className: "limr-figure-media", children: renderChildren(body) }),
|
|
3429
|
+
/* @__PURE__ */ jsx22(CopyButton, { onCopy: async () => {
|
|
2543
3430
|
const url = media.current?.querySelector("img")?.getAttribute("src");
|
|
2544
3431
|
if (!url) throw new Error("Image URL unavailable");
|
|
2545
3432
|
await navigator.clipboard.writeText(url);
|
|
2546
3433
|
}, label: locale.copyImage, variant: "glass", className: "limr-figure-copy" }),
|
|
2547
|
-
captions.length ? renderChildren(captions) : node.attributes?.caption ? /* @__PURE__ */
|
|
3434
|
+
captions.length ? renderChildren(captions) : node.attributes?.caption ? /* @__PURE__ */ jsx22("figcaption", { children: renderAttribute("caption") }) : null
|
|
2548
3435
|
] });
|
|
2549
3436
|
}
|
|
2550
|
-
const Caption = ({ children }) => /* @__PURE__ */
|
|
3437
|
+
const Caption = ({ children }) => /* @__PURE__ */ jsx22("figcaption", { children });
|
|
2551
3438
|
return {
|
|
2552
3439
|
name: "figures",
|
|
3440
|
+
streaming: { Loading: BlockLoading },
|
|
2553
3441
|
tags: ["figures", "figure", "figcaption", "caption", "img"],
|
|
2554
3442
|
directives: ["figures", "figure", "figcaption"],
|
|
2555
3443
|
scope: "local",
|
|
@@ -2559,7 +3447,7 @@ function figures(options = {}) {
|
|
|
2559
3447
|
figure: Figure,
|
|
2560
3448
|
figcaption: Caption,
|
|
2561
3449
|
caption: Caption,
|
|
2562
|
-
img: ({ node }) => /* @__PURE__ */
|
|
3450
|
+
img: ({ node }) => /* @__PURE__ */ jsx22("img", { src: safeUrl(node.attributes?.src, true), alt: String(node.attributes?.alt ?? ""), loading: "lazy", decoding: "async" })
|
|
2563
3451
|
},
|
|
2564
3452
|
transform(root) {
|
|
2565
3453
|
const visit = (node) => {
|
|
@@ -2579,7 +3467,7 @@ function figures(options = {}) {
|
|
|
2579
3467
|
}
|
|
2580
3468
|
|
|
2581
3469
|
// src/extensions/blocks.tsx
|
|
2582
|
-
import { Fragment as
|
|
3470
|
+
import { Fragment as Fragment9, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2583
3471
|
function parts(node, name) {
|
|
2584
3472
|
const result = [];
|
|
2585
3473
|
walk(node, (child) => {
|
|
@@ -2587,25 +3475,25 @@ function parts(node, name) {
|
|
|
2587
3475
|
});
|
|
2588
3476
|
return result;
|
|
2589
3477
|
}
|
|
2590
|
-
var PassThrough = ({ children }) => /* @__PURE__ */
|
|
3478
|
+
var PassThrough = ({ children }) => /* @__PURE__ */ jsx23(Fragment9, { children });
|
|
2591
3479
|
function definition(options = {}) {
|
|
2592
3480
|
function Definition({ node, children, renderChildren, renderAttribute }) {
|
|
2593
3481
|
const runtime = useRuntime();
|
|
2594
3482
|
const title = parts(node, "title")[0];
|
|
2595
3483
|
const content = parts(node, "content")[0];
|
|
2596
|
-
return /* @__PURE__ */
|
|
2597
|
-
/* @__PURE__ */
|
|
2598
|
-
(title || node.attributes?.title) && /* @__PURE__ */
|
|
2599
|
-
/* @__PURE__ */
|
|
3484
|
+
return /* @__PURE__ */ jsxs16("aside", { className: "limr-definition", children: [
|
|
3485
|
+
/* @__PURE__ */ jsx23("div", { className: "limr-card-label", "data-limr-ignore": "true", children: runtime.locale.definition }),
|
|
3486
|
+
(title || node.attributes?.title) && /* @__PURE__ */ jsx23("div", { className: "limr-definition-title", children: title ? renderChildren(title.children ?? []) : renderAttribute("title") }),
|
|
3487
|
+
/* @__PURE__ */ jsx23("div", { className: "limr-block-content", children: content ? renderChildren(content.children ?? []) : children })
|
|
2600
3488
|
] });
|
|
2601
3489
|
}
|
|
2602
|
-
return { ...defineBlock({ name: "definition", component: options.component ?? Definition }), tags: ["definition", "title", "content"], components: { definition: options.component ?? Definition, title: PassThrough, content: PassThrough } };
|
|
3490
|
+
return { ...defineBlock({ name: "definition", streaming: options.component ? void 0 : { Loading: BlockLoading }, component: options.component ?? Definition }), tags: ["definition", "title", "content"], components: { definition: options.component ?? Definition, title: PassThrough, content: PassThrough } };
|
|
2603
3491
|
}
|
|
2604
3492
|
function question(options = {}) {
|
|
2605
3493
|
function Question({ node, children, renderChildren, renderAttribute }) {
|
|
2606
3494
|
const runtime = useRuntime();
|
|
2607
|
-
const [showHint, setHint] =
|
|
2608
|
-
const [selected, setSelected] =
|
|
3495
|
+
const [showHint, setHint] = useState8(false), [showAnswer, setAnswer] = useState8(false);
|
|
3496
|
+
const [selected, setSelected] = useState8([]), [checked, setChecked] = useState8(false);
|
|
2609
3497
|
const content = parts(node, "question-content")[0];
|
|
2610
3498
|
const hint = parts(node, "question-hint")[0];
|
|
2611
3499
|
const answer = parts(node, "question-answer")[0];
|
|
@@ -2619,22 +3507,22 @@ function question(options = {}) {
|
|
|
2619
3507
|
} catch {
|
|
2620
3508
|
}
|
|
2621
3509
|
const success = correct.length === selected.length && correct.every((index) => selected.includes(index));
|
|
2622
|
-
return /* @__PURE__ */
|
|
2623
|
-
/* @__PURE__ */
|
|
2624
|
-
node.attributes?.title && /* @__PURE__ */
|
|
2625
|
-
/* @__PURE__ */
|
|
2626
|
-
selections.length > 0 && /* @__PURE__ */
|
|
2627
|
-
/* @__PURE__ */
|
|
2628
|
-
selections.map((selection, index) => /* @__PURE__ */
|
|
2629
|
-
/* @__PURE__ */
|
|
3510
|
+
return /* @__PURE__ */ jsxs16("section", { className: "limr-question", children: [
|
|
3511
|
+
/* @__PURE__ */ jsx23("div", { className: "limr-card-label", "data-limr-ignore": "true", children: runtime.locale.question }),
|
|
3512
|
+
node.attributes?.title && /* @__PURE__ */ jsx23("div", { className: "limr-question-title", children: renderAttribute("title") }),
|
|
3513
|
+
/* @__PURE__ */ jsx23("div", { className: "limr-block-content", children: content ? renderChildren(content.children ?? []) : !selections.length && !hint && !answer ? children : null }),
|
|
3514
|
+
selections.length > 0 && /* @__PURE__ */ jsxs16("fieldset", { className: "limr-question-options", children: [
|
|
3515
|
+
/* @__PURE__ */ jsx23("legend", { className: "limr-sr-only", children: String(node.attributes?.title ?? runtime.locale.question) }),
|
|
3516
|
+
selections.map((selection, index) => /* @__PURE__ */ jsxs16("label", { "data-selected": selected.includes(index) || void 0, "data-result": checked ? correct.includes(index) ? "correct" : selected.includes(index) ? "incorrect" : void 0 : void 0, children: [
|
|
3517
|
+
/* @__PURE__ */ jsx23("input", { type: multi ? "checkbox" : "radio", name: `${runtime.document.id}-question-${rangeOf(node).start}`, checked: selected.includes(index), disabled: checked, onChange: () => {
|
|
2630
3518
|
setSelected(multi ? selected.includes(index) ? selected.filter((item) => item !== index) : [...selected, index] : [index]);
|
|
2631
3519
|
} }),
|
|
2632
|
-
/* @__PURE__ */
|
|
2633
|
-
/* @__PURE__ */
|
|
3520
|
+
/* @__PURE__ */ jsx23(DiamondCheck, { checked: selected.includes(index) || checked && correct.includes(index) }),
|
|
3521
|
+
/* @__PURE__ */ jsx23("span", { className: "limr-choice-text", children: renderChildren(selection.children ?? []) })
|
|
2634
3522
|
] }, index))
|
|
2635
3523
|
] }),
|
|
2636
|
-
selections.length > 0 && correct.length > 0 && /* @__PURE__ */
|
|
2637
|
-
/* @__PURE__ */
|
|
3524
|
+
selections.length > 0 && correct.length > 0 && /* @__PURE__ */ jsxs16("div", { className: "limr-question-actions", "data-limr-ignore": "true", children: [
|
|
3525
|
+
/* @__PURE__ */ jsx23("button", { type: "button", "data-checked": checked || void 0, disabled: !checked && !selected.length, onClick: () => {
|
|
2638
3526
|
if (checked) {
|
|
2639
3527
|
setChecked(false);
|
|
2640
3528
|
setSelected([]);
|
|
@@ -2643,53 +3531,53 @@ function question(options = {}) {
|
|
|
2643
3531
|
setChecked(true);
|
|
2644
3532
|
setAnswer(true);
|
|
2645
3533
|
}
|
|
2646
|
-
}, children: /* @__PURE__ */
|
|
2647
|
-
/* @__PURE__ */
|
|
3534
|
+
}, children: /* @__PURE__ */ jsx23("span", { className: "limr-button-label", children: checked ? runtime.locale.retry : runtime.locale.submit }, checked ? "retry" : "submit") }),
|
|
3535
|
+
/* @__PURE__ */ jsx23(Collapse, { open: checked, children: /* @__PURE__ */ jsx23("span", { role: "status", className: `limr-question-result ${success ? "limr-success" : "limr-error"}`, children: success ? runtime.locale.correct : runtime.locale.incorrect }) })
|
|
2648
3536
|
] }),
|
|
2649
|
-
hint && /* @__PURE__ */
|
|
2650
|
-
answer && /* @__PURE__ */
|
|
3537
|
+
hint && /* @__PURE__ */ jsx23(Disclosure, { title: runtime.locale.hint, open: showHint, onChange: setHint, children: renderChildren(hint.children ?? []) }),
|
|
3538
|
+
answer && /* @__PURE__ */ jsx23(Disclosure, { title: runtime.locale.answer, open: showAnswer, onChange: setAnswer, children: renderChildren(answer.children ?? []) })
|
|
2651
3539
|
] });
|
|
2652
3540
|
}
|
|
2653
3541
|
const names2 = ["question-content", "question-hint", "question-answer", "question-sel-grp", "question-sel"];
|
|
2654
|
-
return { ...defineBlock({ name: "question", component: options.component ?? Question }), tags: ["question", ...names2], components: { question: options.component ?? Question, ...Object.fromEntries(names2.map((name) => [name, PassThrough])) } };
|
|
3542
|
+
return { ...defineBlock({ name: "question", streaming: options.component ? void 0 : { Loading: BlockLoading }, component: options.component ?? Question }), tags: ["question", ...names2], components: { question: options.component ?? Question, ...Object.fromEntries(names2.map((name) => [name, PassThrough])) } };
|
|
2655
3543
|
}
|
|
2656
3544
|
function extras(options = {}) {
|
|
2657
|
-
const Extra = ({ node, children, renderAttribute }) => /* @__PURE__ */
|
|
2658
|
-
/* @__PURE__ */
|
|
2659
|
-
/* @__PURE__ */
|
|
2660
|
-
node.attributes?.desc && /* @__PURE__ */
|
|
3545
|
+
const Extra = ({ node, children, renderAttribute }) => /* @__PURE__ */ jsxs16("div", { className: "limr-extra", children: [
|
|
3546
|
+
/* @__PURE__ */ jsxs16("a", { className: "limr-extra-link", href: safeUrl(node.attributes?.url), target: "_blank", rel: "noreferrer", children: [
|
|
3547
|
+
/* @__PURE__ */ jsx23("span", { className: "limr-underline", children: renderAttribute(node.attributes?.title ? "title" : "url") }),
|
|
3548
|
+
node.attributes?.desc && /* @__PURE__ */ jsx23("p", { children: /* @__PURE__ */ jsx23("span", { className: "limr-underline", children: renderAttribute("desc") }) })
|
|
2661
3549
|
] }),
|
|
2662
3550
|
children
|
|
2663
3551
|
] });
|
|
2664
3552
|
const Extras = ({ children }) => {
|
|
2665
3553
|
const runtime = useRuntime();
|
|
2666
|
-
return /* @__PURE__ */
|
|
2667
|
-
/* @__PURE__ */
|
|
3554
|
+
return /* @__PURE__ */ jsxs16("aside", { className: "limr-extras", children: [
|
|
3555
|
+
/* @__PURE__ */ jsx23("div", { className: "limr-card-label", "data-limr-ignore": "true", children: runtime.locale.extra }),
|
|
2668
3556
|
children
|
|
2669
3557
|
] });
|
|
2670
3558
|
};
|
|
2671
|
-
return { ...defineBlock({ name: "extras", component: options.component ?? Extras }), tags: ["extras", "extra"], components: { extras: options.component ?? Extras, extra: Extra } };
|
|
3559
|
+
return { ...defineBlock({ name: "extras", streaming: options.component ? void 0 : { Loading: BlockLoading }, component: options.component ?? Extras }), tags: ["extras", "extra"], components: { extras: options.component ?? Extras, extra: Extra } };
|
|
2672
3560
|
}
|
|
2673
3561
|
|
|
2674
3562
|
// src/extensions/standard.ts
|
|
2675
3563
|
function standard() {
|
|
2676
|
-
return [gfm(), math(), codeHighlight(), definition(), question(), extras(), video(), figures(), citation(), translations()];
|
|
3564
|
+
return [gfm(), math(), codeHighlight(), mermaid(), callout(), definition(), question(), extras(), video(), figures(), citation(), translations(), inlineHighlights(), footnotes()];
|
|
2677
3565
|
}
|
|
2678
3566
|
|
|
2679
3567
|
// src/react/context.tsx
|
|
2680
|
-
import { jsx as
|
|
3568
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
2681
3569
|
var defaults;
|
|
2682
3570
|
var RuntimeContext = createContext2(null);
|
|
2683
|
-
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect :
|
|
3571
|
+
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect9;
|
|
2684
3572
|
function DocumentProvider({ children, source = "", streaming = false, documentId, ...options }) {
|
|
2685
3573
|
const generatedId = useId();
|
|
2686
|
-
const extensions =
|
|
3574
|
+
const extensions = useMemo5(() => {
|
|
2687
3575
|
const base = options.extensions ?? (defaults ??= standard());
|
|
2688
3576
|
return options.plugins?.length ? [...base, ...options.plugins] : base;
|
|
2689
3577
|
}, [options.extensions, options.plugins]);
|
|
2690
3578
|
const config = { ...options, extensions };
|
|
2691
|
-
const [runtime] =
|
|
2692
|
-
const previous =
|
|
3579
|
+
const [runtime] = useState9(() => new ReaderRuntime(documentId ?? `limr-${generatedId.replace(/[^a-z\d_-]/gi, "")}`, source, streaming, config));
|
|
3580
|
+
const previous = useRef14({ source, streaming, config });
|
|
2693
3581
|
useIsomorphicLayoutEffect(() => {
|
|
2694
3582
|
const old = previous.current;
|
|
2695
3583
|
const changed = Object.keys({ ...old.config, ...config }).some((key) => old.config[key] !== config[key]);
|
|
@@ -2697,11 +3585,11 @@ function DocumentProvider({ children, source = "", streaming = false, documentId
|
|
|
2697
3585
|
if (old.source !== source || old.streaming !== streaming) runtime.document.update(source, { streaming });
|
|
2698
3586
|
previous.current = { source, streaming, config };
|
|
2699
3587
|
});
|
|
2700
|
-
|
|
3588
|
+
useEffect9(() => {
|
|
2701
3589
|
runtime.start();
|
|
2702
3590
|
return () => runtime.dispose();
|
|
2703
3591
|
}, [runtime]);
|
|
2704
|
-
return /* @__PURE__ */
|
|
3592
|
+
return /* @__PURE__ */ jsx24(RuntimeContext.Provider, { value: runtime, children });
|
|
2705
3593
|
}
|
|
2706
3594
|
function useRuntime() {
|
|
2707
3595
|
const runtime = useContext3(RuntimeContext);
|
|
@@ -2720,14 +3608,14 @@ function useRendererParameter(name) {
|
|
|
2720
3608
|
});
|
|
2721
3609
|
}
|
|
2722
3610
|
function useStoreSelector(store, select) {
|
|
2723
|
-
const selectRef =
|
|
3611
|
+
const selectRef = useRef14(select);
|
|
2724
3612
|
selectRef.current = select;
|
|
2725
|
-
const
|
|
2726
|
-
const get =
|
|
3613
|
+
const cache3 = useRef14(void 0);
|
|
3614
|
+
const get = useCallback3(() => {
|
|
2727
3615
|
const state = store.get();
|
|
2728
|
-
if (
|
|
3616
|
+
if (cache3.current && cache3.current.state === state && cache3.current.select === selectRef.current) return cache3.current.value;
|
|
2729
3617
|
const value = selectRef.current(state);
|
|
2730
|
-
|
|
3618
|
+
cache3.current = { state, select: selectRef.current, value };
|
|
2731
3619
|
return value;
|
|
2732
3620
|
}, [store]);
|
|
2733
3621
|
return useSyncExternalStore(store.subscribe, get, get);
|
|
@@ -2738,7 +3626,7 @@ function useDocument() {
|
|
|
2738
3626
|
}
|
|
2739
3627
|
function useDocumentSelector(select) {
|
|
2740
3628
|
const runtime = useRuntime();
|
|
2741
|
-
const store =
|
|
3629
|
+
const store = useMemo5(() => ({ subscribe: runtime.document.subscribe, get: runtime.document.getSnapshot }), [runtime]);
|
|
2742
3630
|
return useStoreSelector(store, select);
|
|
2743
3631
|
}
|
|
2744
3632
|
function useSelection() {
|
|
@@ -2760,7 +3648,7 @@ function useAnnotation(id) {
|
|
|
2760
3648
|
}
|
|
2761
3649
|
function useAnnotations() {
|
|
2762
3650
|
const state = useStoreSelector(useRuntime().decorations, (state2) => state2);
|
|
2763
|
-
return
|
|
3651
|
+
return useMemo5(() => ({ annotations: state.annotations, occurrences: state.occurrences }), [state.annotations, state.occurrences]);
|
|
2764
3652
|
}
|
|
2765
3653
|
function useAnnotationState() {
|
|
2766
3654
|
const runtime = useRuntime();
|
|
@@ -2777,7 +3665,7 @@ function useAnchor(id) {
|
|
|
2777
3665
|
}
|
|
2778
3666
|
function useLiMR() {
|
|
2779
3667
|
const runtime = useRuntime();
|
|
2780
|
-
return
|
|
3668
|
+
return useMemo5(() => ({
|
|
2781
3669
|
...runtime.commands,
|
|
2782
3670
|
document: runtime.document,
|
|
2783
3671
|
get signal() {
|
|
@@ -2791,14 +3679,14 @@ function useLiMR() {
|
|
|
2791
3679
|
}
|
|
2792
3680
|
|
|
2793
3681
|
// src/components/CopyButton.tsx
|
|
2794
|
-
import { jsx as
|
|
3682
|
+
import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2795
3683
|
function CopyButton({ value = "", onCopy, label, variant = "plain", className = "" }) {
|
|
2796
3684
|
const locale = useLocale();
|
|
2797
|
-
const [status, setStatus] =
|
|
2798
|
-
const timer =
|
|
2799
|
-
const mounted =
|
|
3685
|
+
const [status, setStatus] = useState10("idle");
|
|
3686
|
+
const timer = useRef15(void 0);
|
|
3687
|
+
const mounted = useRef15(true);
|
|
2800
3688
|
const title = status === "copied" ? locale.copied : status === "error" ? locale.copyFailed : label ?? locale.copy;
|
|
2801
|
-
|
|
3689
|
+
useEffect10(() => {
|
|
2802
3690
|
mounted.current = true;
|
|
2803
3691
|
return () => {
|
|
2804
3692
|
mounted.current = false;
|
|
@@ -2818,7 +3706,7 @@ function CopyButton({ value = "", onCopy, label, variant = "plain", className =
|
|
|
2818
3706
|
clearTimeout(timer.current);
|
|
2819
3707
|
timer.current = setTimeout(() => setStatus("idle"), 2200);
|
|
2820
3708
|
};
|
|
2821
|
-
return /* @__PURE__ */
|
|
3709
|
+
return /* @__PURE__ */ jsxs17(
|
|
2822
3710
|
"button",
|
|
2823
3711
|
{
|
|
2824
3712
|
type: "button",
|
|
@@ -2830,21 +3718,21 @@ function CopyButton({ value = "", onCopy, label, variant = "plain", className =
|
|
|
2830
3718
|
title,
|
|
2831
3719
|
onClick: copy,
|
|
2832
3720
|
children: [
|
|
2833
|
-
/* @__PURE__ */
|
|
2834
|
-
/* @__PURE__ */
|
|
2835
|
-
/* @__PURE__ */
|
|
2836
|
-
/* @__PURE__ */
|
|
3721
|
+
/* @__PURE__ */ jsxs17("svg", { className: "limr-copy-glyph", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
|
|
3722
|
+
/* @__PURE__ */ jsxs17("g", { className: "limr-copy-sheets", children: [
|
|
3723
|
+
/* @__PURE__ */ jsx25("rect", { x: "8.5", y: "8", width: "10.5", height: "12", rx: "3" }),
|
|
3724
|
+
/* @__PURE__ */ jsx25("path", { d: "M15.5 8V6.8A2.8 2.8 0 0 0 12.7 4H7A3 3 0 0 0 4 7v6a3 3 0 0 0 3 3h1.5" })
|
|
2837
3725
|
] }),
|
|
2838
|
-
/* @__PURE__ */
|
|
3726
|
+
/* @__PURE__ */ jsx25("path", { className: "limr-copy-check", d: "m5.5 12 4.2 4.2 8.8-9", pathLength: "1" })
|
|
2839
3727
|
] }),
|
|
2840
|
-
/* @__PURE__ */
|
|
3728
|
+
/* @__PURE__ */ jsx25("span", { className: status === "error" ? "limr-copy-error" : "limr-sr-only", role: "status", children: status === "copied" ? locale.copied : status === "error" ? locale.copyFailed : "" })
|
|
2841
3729
|
]
|
|
2842
3730
|
}
|
|
2843
3731
|
);
|
|
2844
3732
|
}
|
|
2845
3733
|
|
|
2846
3734
|
// src/extensions/math.tsx
|
|
2847
|
-
import { jsx as
|
|
3735
|
+
import { jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2848
3736
|
var loaded;
|
|
2849
3737
|
var loading;
|
|
2850
3738
|
var load = () => loading ??= import("./math-renderer-L6DOH4RX.js").then((module) => {
|
|
@@ -2858,74 +3746,21 @@ async function preloadMath() {
|
|
|
2858
3746
|
function math(options = {}) {
|
|
2859
3747
|
function MathNode({ node }) {
|
|
2860
3748
|
const display = node.type === "math";
|
|
2861
|
-
const fallback = /* @__PURE__ */
|
|
3749
|
+
const fallback = /* @__PURE__ */ jsx26("code", { className: "limr-math-source", children: node.value });
|
|
2862
3750
|
const Renderer = loaded ?? MathContent;
|
|
2863
|
-
const content = /* @__PURE__ */
|
|
2864
|
-
return display ? /* @__PURE__ */
|
|
3751
|
+
const content = /* @__PURE__ */ jsx26(Suspense, { fallback, children: /* @__PURE__ */ jsx26(Renderer, { value: node.value ?? "", display, options }) });
|
|
3752
|
+
return display ? /* @__PURE__ */ jsxs18("div", { className: "limr-math-block", children: [
|
|
2865
3753
|
content,
|
|
2866
|
-
/* @__PURE__ */
|
|
3754
|
+
/* @__PURE__ */ jsx26(CopyButton, { className: "limr-math-copy", variant: "glass", label: "Copy LaTeX", value: `$$
|
|
2867
3755
|
${node.value ?? ""}
|
|
2868
3756
|
$$` })
|
|
2869
3757
|
] }) : content;
|
|
2870
3758
|
}
|
|
2871
|
-
return { name: "math", micromark: [syntax2()], mdast: [mathFromMarkdown()], scope: "local", components: { math: MathNode, inlineMath: MathNode } };
|
|
2872
|
-
}
|
|
2873
|
-
|
|
2874
|
-
// src/components/ToolIcon.tsx
|
|
2875
|
-
import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2876
|
-
function ToolIcon({ name, ...props }) {
|
|
2877
|
-
return /* @__PURE__ */ jsx19("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsxs15("g", { transform: name === "highlight" ? "translate(0 -1.25)" : name === "comment" ? "translate(0 -.5)" : void 0, children: [
|
|
2878
|
-
(name === "eye" || name === "eye-off") && /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
2879
|
-
/* @__PURE__ */ jsx19("path", { d: "M3 12s3.3-6 9-6 9 6 9 6-3.3 6-9 6-9-6-9-6Z" }),
|
|
2880
|
-
/* @__PURE__ */ jsx19("circle", { cx: "12", cy: "12", r: "2.7" }),
|
|
2881
|
-
name === "eye-off" && /* @__PURE__ */ jsx19("path", { d: "m4 4 16 16" })
|
|
2882
|
-
] }),
|
|
2883
|
-
name === "question" && /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
2884
|
-
/* @__PURE__ */ jsx19("circle", { cx: "12", cy: "12", r: "8.5" }),
|
|
2885
|
-
/* @__PURE__ */ jsx19("path", { d: "M9.4 9a2.7 2.7 0 0 1 5.2 1c0 1.8-2.6 2-2.6 3.7M12 17h.01" })
|
|
2886
|
-
] }),
|
|
2887
|
-
name === "highlight" && /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
2888
|
-
/* @__PURE__ */ jsx19("path", { d: "m8 15 7.6-9a2 2 0 0 1 2.8-.2l.8.7a2 2 0 0 1 .2 2.8L12 18l-4-3Z" }),
|
|
2889
|
-
/* @__PURE__ */ jsx19("path", { d: "m8 15-2 3 3 1 3-1M4 21h10M14 8l4 3.5" })
|
|
2890
|
-
] }),
|
|
2891
|
-
name === "edit" && /* @__PURE__ */ jsx19(Fragment6, { children: /* @__PURE__ */ jsx19("path", { d: "m14.5 5.5 4 4M4.5 19.5l4.5-1 11-11a2.1 2.1 0 0 0 0-3 2.1 2.1 0 0 0-3 0l-11 11-1.5 4Z" }) }),
|
|
2892
|
-
name === "close" && /* @__PURE__ */ jsx19("path", { d: "m6 6 12 12M18 6 6 18" }),
|
|
2893
|
-
name === "copy" && /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
2894
|
-
/* @__PURE__ */ jsx19("rect", { x: "8.5", y: "8", width: "10.5", height: "12", rx: "3" }),
|
|
2895
|
-
/* @__PURE__ */ jsx19("path", { d: "M15.5 8V6.8A2.8 2.8 0 0 0 12.7 4H7A3 3 0 0 0 4 7v6a3 3 0 0 0 3 3h1.5" })
|
|
2896
|
-
] }),
|
|
2897
|
-
["background", "underline", "dotted", "wavy"].includes(name) && /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
2898
|
-
name === "background" && /* @__PURE__ */ jsx19("rect", { x: "3", y: "3", width: "18", height: "18", rx: "5", fill: "currentColor", fillOpacity: ".13", stroke: "none" }),
|
|
2899
|
-
/* @__PURE__ */ jsx19("path", { d: "m8 15 3-8a1.05 1.05 0 0 1 2 0l3 8M9.2 12h5.6" }),
|
|
2900
|
-
name === "background" && /* @__PURE__ */ jsx19("path", { d: "M7 19h10", strokeWidth: "2.5" }),
|
|
2901
|
-
name === "underline" && /* @__PURE__ */ jsx19("path", { d: "M5 20h14" }),
|
|
2902
|
-
name === "dotted" && /* @__PURE__ */ jsx19("path", { d: "M5 20h14", strokeDasharray: ".1 3.4", strokeWidth: "2.4" }),
|
|
2903
|
-
name === "wavy" && /* @__PURE__ */ jsx19("path", { d: "M4 20c1.3-2 2.7-2 4 0s2.7 2 4 0 2.7-2 4 0 2.7 2 4 0" })
|
|
2904
|
-
] }),
|
|
2905
|
-
name === "chevron" && /* @__PURE__ */ jsx19("path", { d: "m8 10 4 4 4-4" }),
|
|
2906
|
-
name === "check" && /* @__PURE__ */ jsx19("path", { d: "m5.5 12 4.2 4.2 8.8-9" }),
|
|
2907
|
-
name === "trash" && /* @__PURE__ */ jsx19(Fragment6, { children: /* @__PURE__ */ jsx19("path", { d: "M4.5 7h15M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2M7 7l.7 12a2 2 0 0 0 2 2h4.6a2 2 0 0 0 2-2L17 7M10 11v6M14 11v6" }) }),
|
|
2908
|
-
name === "note" && /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
2909
|
-
/* @__PURE__ */ jsx19("path", { d: "M14 3H7a3 3 0 0 0-3 3v12a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V9l-6-6Z" }),
|
|
2910
|
-
/* @__PURE__ */ jsx19("path", { d: "M14 3v4a2 2 0 0 0 2 2h4M8 13h8M8 17h5" })
|
|
2911
|
-
] }),
|
|
2912
|
-
name === "comment" && /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
2913
|
-
/* @__PURE__ */ jsx19("path", { d: "M8 19 4 21V7a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v9a3 3 0 0 1-3 3H8Z" }),
|
|
2914
|
-
/* @__PURE__ */ jsx19("path", { d: "M8 9h8M8 13h5" })
|
|
2915
|
-
] }),
|
|
2916
|
-
name === "footnote" && /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
2917
|
-
/* @__PURE__ */ jsx19("path", { d: "M5 7h9M5 11h12M5 15h8M5 20h14M18 4h2v5" }),
|
|
2918
|
-
/* @__PURE__ */ jsx19("path", { d: "M17.5 9h4" })
|
|
2919
|
-
] }),
|
|
2920
|
-
name === "sparkles" && /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
2921
|
-
/* @__PURE__ */ jsx19("path", { d: "m10.5 4 1.8 4.8 4.7 1.7-4.7 1.8-1.8 4.7-1.7-4.7L4 10.5l4.8-1.7L10.5 4Z" }),
|
|
2922
|
-
/* @__PURE__ */ jsx19("path", { d: "m19 15 .8 2.2L22 18l-2.2.8L19 21l-.8-2.2L16 18l2.2-.8L19 15ZM19 3v4M17 5h4" })
|
|
2923
|
-
] })
|
|
2924
|
-
] }) });
|
|
3759
|
+
return { name: "math", directives: ["math"], literal: true, micromark: [syntax2()], mdast: [mathFromMarkdown()], scope: "local", components: { math: MathNode, inlineMath: MathNode }, transform: (root, context) => literalDirective(root, context.source, "math") };
|
|
2925
3760
|
}
|
|
2926
3761
|
|
|
2927
3762
|
// src/extensions/selection-actions.tsx
|
|
2928
|
-
import { jsx as
|
|
3763
|
+
import { jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2929
3764
|
var highlightColors = [
|
|
2930
3765
|
{ color: "#E57373", label: "Rose", labelZh: "\u73AB\u7470" },
|
|
2931
3766
|
{ color: "#F2C744", label: "Gold", labelZh: "\u6696\u9EC4" },
|
|
@@ -2939,9 +3774,9 @@ function copyText(options = {}) {
|
|
|
2939
3774
|
return {
|
|
2940
3775
|
id: `copy-${options.format ?? "text"}`,
|
|
2941
3776
|
label: options.label ?? ((context) => context.locale.copy),
|
|
2942
|
-
icon: /* @__PURE__ */
|
|
3777
|
+
icon: /* @__PURE__ */ jsx27(ToolIcon, { name: "copy" }),
|
|
2943
3778
|
successLabel: (context) => context.locale.copied,
|
|
2944
|
-
successIcon: /* @__PURE__ */
|
|
3779
|
+
successIcon: /* @__PURE__ */ jsx27(ToolIcon, { name: "check" }),
|
|
2945
3780
|
run: async ({ selection }) => {
|
|
2946
3781
|
const format = options.format ?? "text";
|
|
2947
3782
|
await navigator.clipboard.writeText(format === "text" ? selection.text : selection[format].sourceText);
|
|
@@ -2963,17 +3798,17 @@ function HighlightSettings({ context, options }) {
|
|
|
2963
3798
|
context.setHighlightAppearance(appearance);
|
|
2964
3799
|
if (highlight) void context.run((current) => current.updateAnnotation(highlight.id, { data: appearance }));
|
|
2965
3800
|
};
|
|
2966
|
-
return /* @__PURE__ */
|
|
2967
|
-
/* @__PURE__ */
|
|
2968
|
-
/* @__PURE__ */
|
|
2969
|
-
/* @__PURE__ */
|
|
2970
|
-
/* @__PURE__ */
|
|
2971
|
-
/* @__PURE__ */
|
|
3801
|
+
return /* @__PURE__ */ jsxs19("div", { className: "limr-highlight-settings", children: [
|
|
3802
|
+
/* @__PURE__ */ jsxs19("fieldset", { disabled: context.busy, children: [
|
|
3803
|
+
/* @__PURE__ */ jsx27("legend", { children: locale.highlightStyle }),
|
|
3804
|
+
/* @__PURE__ */ jsx27("div", { className: "limr-highlight-styles", children: styles.map(([value, label]) => /* @__PURE__ */ jsxs19("button", { type: "button", "aria-pressed": style === value, onClick: () => change(color, value), children: [
|
|
3805
|
+
/* @__PURE__ */ jsx27(ToolIcon, { name: value }),
|
|
3806
|
+
/* @__PURE__ */ jsx27("span", { className: "limr-highlight-style-label", children: /* @__PURE__ */ jsx27("span", { className: "limr-underline", children: label }) })
|
|
2972
3807
|
] }, value)) })
|
|
2973
3808
|
] }),
|
|
2974
|
-
/* @__PURE__ */
|
|
2975
|
-
/* @__PURE__ */
|
|
2976
|
-
/* @__PURE__ */
|
|
3809
|
+
/* @__PURE__ */ jsxs19("fieldset", { disabled: context.busy, children: [
|
|
3810
|
+
/* @__PURE__ */ jsx27("legend", { children: locale.highlightColor }),
|
|
3811
|
+
/* @__PURE__ */ jsx27("div", { className: "limr-highlight-colors", children: (options.colors ?? highlightColors).map((item) => /* @__PURE__ */ jsx27("button", { type: "button", className: "limr-color-swatch", "aria-label": locale.highlight === "\u9AD8\u4EAE" ? item.labelZh ?? item.label : item.label, title: locale.highlight === "\u9AD8\u4EAE" ? item.labelZh ?? item.label : item.label, "aria-pressed": color.toLowerCase() === item.color.toLowerCase(), style: { "--swatch": item.color }, onClick: () => change(item.color, style), children: /* @__PURE__ */ jsx27(ToolIcon, { name: "check" }) }, item.color)) })
|
|
2977
3812
|
] })
|
|
2978
3813
|
] });
|
|
2979
3814
|
}
|
|
@@ -2981,17 +3816,17 @@ function highlightPalette(options = {}) {
|
|
|
2981
3816
|
return {
|
|
2982
3817
|
id: "highlight-palette",
|
|
2983
3818
|
label: (context) => context.locale.editHighlight,
|
|
2984
|
-
icon: /* @__PURE__ */
|
|
3819
|
+
icon: /* @__PURE__ */ jsx27(ToolIcon, { name: "background" }),
|
|
2985
3820
|
placement: "start",
|
|
2986
|
-
render: (context) => /* @__PURE__ */
|
|
2987
|
-
renderExpanded: (context) => /* @__PURE__ */
|
|
3821
|
+
render: (context) => /* @__PURE__ */ jsx27("button", { type: "button", className: "limr-toolbar-swatch", "aria-label": context.locale.editHighlight, "aria-expanded": context.expanded, disabled: context.busy, onClick: () => context.expanded ? context.collapse() : context.expand(), style: { "--swatch": context.highlightAppearance.color ?? defaultHighlight.color } }),
|
|
3822
|
+
renderExpanded: (context) => /* @__PURE__ */ jsx27(HighlightSettings, { context, options })
|
|
2988
3823
|
};
|
|
2989
3824
|
}
|
|
2990
3825
|
function highlightSelection() {
|
|
2991
3826
|
return {
|
|
2992
3827
|
id: "highlight",
|
|
2993
3828
|
label: (context) => !context.highlight ? context.locale.addHighlight : context.highlight.data?.hidden ? context.locale.showHighlight : context.locale.hideHighlight,
|
|
2994
|
-
icon: (context) => /* @__PURE__ */
|
|
3829
|
+
icon: (context) => /* @__PURE__ */ jsx27(ToolIcon, { name: !context.highlight ? "highlight" : context.highlight.data?.hidden ? "eye" : "eye-off" }),
|
|
2995
3830
|
visible: (context) => !context.highlight || context.annotations.some((annotation) => annotation.type !== "highlight"),
|
|
2996
3831
|
run: (context) => {
|
|
2997
3832
|
if (context.highlight) context.updateAnnotation(context.highlight.id, { data: { ...context.highlight.data, hidden: !context.highlight.data?.hidden } });
|
|
@@ -3006,7 +3841,7 @@ function deleteAnnotations() {
|
|
|
3006
3841
|
return {
|
|
3007
3842
|
id: "delete-annotations",
|
|
3008
3843
|
label: (context) => context.locale.deleteAnnotations,
|
|
3009
|
-
icon: /* @__PURE__ */
|
|
3844
|
+
icon: /* @__PURE__ */ jsx27(ToolIcon, { name: "trash" }),
|
|
3010
3845
|
placement: "end",
|
|
3011
3846
|
tone: "danger",
|
|
3012
3847
|
visible: (context) => context.annotations.length > 0,
|
|
@@ -3026,7 +3861,6 @@ export {
|
|
|
3026
3861
|
preloadMath,
|
|
3027
3862
|
math,
|
|
3028
3863
|
codeHighlight,
|
|
3029
|
-
sourceRangeStartRect,
|
|
3030
3864
|
Markdown,
|
|
3031
3865
|
OverlayScrollArea,
|
|
3032
3866
|
AnnotationCard,
|
|
@@ -3035,9 +3869,15 @@ export {
|
|
|
3035
3869
|
InlineMarker,
|
|
3036
3870
|
Collapse,
|
|
3037
3871
|
translations,
|
|
3872
|
+
ToolIcon,
|
|
3873
|
+
mermaid,
|
|
3038
3874
|
defineBlock,
|
|
3039
3875
|
defineAnnotation,
|
|
3040
3876
|
defineExtension,
|
|
3877
|
+
calloutType,
|
|
3878
|
+
callout,
|
|
3879
|
+
inlineHighlights,
|
|
3880
|
+
footnotes,
|
|
3041
3881
|
video,
|
|
3042
3882
|
figures,
|
|
3043
3883
|
definition,
|
|
@@ -3060,11 +3900,10 @@ export {
|
|
|
3060
3900
|
useAnnotationState,
|
|
3061
3901
|
useAnchor,
|
|
3062
3902
|
useLiMR,
|
|
3063
|
-
ToolIcon,
|
|
3064
3903
|
highlightColors,
|
|
3065
3904
|
copyText,
|
|
3066
3905
|
highlightPalette,
|
|
3067
3906
|
highlightSelection,
|
|
3068
3907
|
deleteAnnotations
|
|
3069
3908
|
};
|
|
3070
|
-
//# sourceMappingURL=chunk-
|
|
3909
|
+
//# sourceMappingURL=chunk-SUAAUGAX.js.map
|