tiptap-markdown-react 0.12.1 → 0.14.0
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.md +2 -0
- package/dist/{ReportContent-CfvE4CYH.js → ReportContent-DxldXfpO.js} +84 -2
- package/dist/ReportContent-DxldXfpO.js.map +1 -0
- package/dist/citationUtils.d.ts +30 -0
- package/dist/components/CodeBlockView.d.ts +5 -0
- package/dist/components/codeBlockReadonly.dom.test.d.ts +1 -0
- package/dist/{extractToc-BT3OquOq.js → extractToc-C2zqDjSP.js} +2 -2
- package/dist/{extractToc-BT3OquOq.js.map → extractToc-C2zqDjSP.js.map} +1 -1
- package/dist/icons/index.d.ts +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +171 -39
- package/dist/index.js.map +1 -1
- package/dist/labels.d.ts +6 -0
- package/dist/reader.d.ts +1 -1
- package/dist/reader.js +3 -2
- package/dist/{scrollToTocHeading-DVdii3VR.js → scrollToTocHeading-DKL19FQG.js} +2 -2
- package/dist/{scrollToTocHeading-DVdii3VR.js.map → scrollToTocHeading-DKL19FQG.js.map} +1 -1
- package/dist/server.js +4 -4
- package/dist/style.css +120 -42
- package/package.json +1 -1
- package/dist/ReportContent-CfvE4CYH.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Markdown, MarkdownManager } from "@tiptap/markdown";
|
|
3
|
-
import { c as renderOrUpdateChart, d as destroyChart } from "./scrollToTocHeading-
|
|
4
|
-
import { C, a, R, b, f, m, r, s } from "./scrollToTocHeading-
|
|
3
|
+
import { c as renderOrUpdateChart, d as destroyChart } from "./scrollToTocHeading-DKL19FQG.js";
|
|
4
|
+
import { C, a, R, b, f, m, r, s } from "./scrollToTocHeading-DKL19FQG.js";
|
|
5
5
|
import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime";
|
|
6
6
|
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
|
|
7
7
|
import FindAndReplace, { FindAndReplacePluginKey, createSearchRegex } from "@tiptap/extension-find-and-replace";
|
|
@@ -11,10 +11,10 @@ import { TableOfContents } from "@tiptap/extension-table-of-contents";
|
|
|
11
11
|
import { NodeViewWrapper, ReactNodeViewRenderer, useEditorState, NodeViewContent, useEditor, EditorContent } from "@tiptap/react";
|
|
12
12
|
import { createPortal } from "react-dom";
|
|
13
13
|
import { useState, useEffect, useCallback, useRef, useMemo, forwardRef, useImperativeHandle, useId, useContext, createContext } from "react";
|
|
14
|
-
import { e as enrichMarkdownCitations,
|
|
15
|
-
import { R as R2, a as a2, s as s2 } from "./ReportContent-
|
|
16
|
-
import { C as CitationRef, i as mergeCommentIntervals, h as mapCommentAnchors, p as prepareChartMarkdown, j as reportChart, b as baseExtensions, f as CommentMark, l as lowlight, m as makeTocGetId, k as parseCodeTokenAsChartOrCodeBlock, a as pureCodeBlock, c as pureImage, n as renderMathInto, o as subscribeMathClick, d as pureChart } from "./extractToc-
|
|
17
|
-
import { g, e, s as s3 } from "./extractToc-
|
|
14
|
+
import { e as enrichMarkdownCitations, c as styles$6 } from "./ReportContent-DxldXfpO.js";
|
|
15
|
+
import { R as R2, a as a2, b as b2, s as s2 } from "./ReportContent-DxldXfpO.js";
|
|
16
|
+
import { C as CitationRef, i as mergeCommentIntervals, h as mapCommentAnchors, p as prepareChartMarkdown, j as reportChart, b as baseExtensions, f as CommentMark, l as lowlight, m as makeTocGetId, k as parseCodeTokenAsChartOrCodeBlock, a as pureCodeBlock, c as pureImage, n as renderMathInto, o as subscribeMathClick, d as pureChart } from "./extractToc-C2zqDjSP.js";
|
|
17
|
+
import { g, e, s as s3 } from "./extractToc-C2zqDjSP.js";
|
|
18
18
|
import { Slice, Fragment } from "@tiptap/pm/model";
|
|
19
19
|
import { Extension, Node as Node$1 } from "@tiptap/core";
|
|
20
20
|
import { PluginKey, Plugin, NodeSelection, TextSelection } from "@tiptap/pm/state";
|
|
@@ -184,19 +184,19 @@ function commentAnchorPlugin(options = {}) {
|
|
|
184
184
|
const decos = [];
|
|
185
185
|
const bounds = blockBounds(state.doc);
|
|
186
186
|
if (showGutter) {
|
|
187
|
-
for (const
|
|
187
|
+
for (const b3 of bounds) {
|
|
188
188
|
const idsInBlock = [];
|
|
189
189
|
for (const [id, ranges] of byId) {
|
|
190
|
-
if (rangesIntersectBlock(ranges,
|
|
190
|
+
if (rangesIntersectBlock(ranges, b3.start, b3.end)) {
|
|
191
191
|
idsInBlock.push(id);
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
if (idsInBlock.length > 0) {
|
|
195
195
|
decos.push(
|
|
196
196
|
Decoration.widget(
|
|
197
|
-
|
|
198
|
-
(view) => gutterDom(idsInBlock, view,
|
|
199
|
-
{ side: -1, key: `tmr-gutter:${
|
|
197
|
+
b3.start,
|
|
198
|
+
(view) => gutterDom(idsInBlock, view, b3.start),
|
|
199
|
+
{ side: -1, key: `tmr-gutter:${b3.start}` }
|
|
200
200
|
)
|
|
201
201
|
);
|
|
202
202
|
}
|
|
@@ -210,10 +210,10 @@ function commentAnchorPlugin(options = {}) {
|
|
|
210
210
|
Decoration.inline(r2.from, r2.to, { class: "tmr-comment-active" })
|
|
211
211
|
);
|
|
212
212
|
}
|
|
213
|
-
for (const
|
|
214
|
-
if (rangesIntersectBlock(ranges,
|
|
213
|
+
for (const b3 of bounds) {
|
|
214
|
+
if (rangesIntersectBlock(ranges, b3.start, b3.end)) {
|
|
215
215
|
decos.push(
|
|
216
|
-
Decoration.node(
|
|
216
|
+
Decoration.node(b3.start, b3.end, {
|
|
217
217
|
class: "tmr-comment-block-active"
|
|
218
218
|
})
|
|
219
219
|
);
|
|
@@ -525,6 +525,14 @@ const TableDeleteIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
|
525
525
|
/* @__PURE__ */ jsx("path", { d: "M15 5v14" }),
|
|
526
526
|
/* @__PURE__ */ jsx("path", { d: "m7 2 10 20" })
|
|
527
527
|
] });
|
|
528
|
+
const CopyIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
529
|
+
/* @__PURE__ */ jsx("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
|
|
530
|
+
/* @__PURE__ */ jsx("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
|
|
531
|
+
] });
|
|
532
|
+
const ChevronsUpDownIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
533
|
+
/* @__PURE__ */ jsx("path", { d: "m7 15 5 5 5-5" }),
|
|
534
|
+
/* @__PURE__ */ jsx("path", { d: "m7 9 5-5 5 5" })
|
|
535
|
+
] });
|
|
528
536
|
const defaultChartLabels = {
|
|
529
537
|
tabLabel: (chartType, index) => `${chartType} ${index + 1}`,
|
|
530
538
|
done: "Done",
|
|
@@ -608,7 +616,10 @@ const defaultTocLabels = {
|
|
|
608
616
|
};
|
|
609
617
|
const defaultCodeBlockLabels = {
|
|
610
618
|
autoDetect: "Auto-detect",
|
|
611
|
-
delete: "Delete code block"
|
|
619
|
+
delete: "Delete code block",
|
|
620
|
+
copy: "Copy code",
|
|
621
|
+
expand: "Expand code",
|
|
622
|
+
collapse: "Collapse code"
|
|
612
623
|
};
|
|
613
624
|
const defaultCommentLabels = {
|
|
614
625
|
open: "Open",
|
|
@@ -1281,29 +1292,45 @@ function createChart(options = {}) {
|
|
|
1281
1292
|
}
|
|
1282
1293
|
});
|
|
1283
1294
|
}
|
|
1284
|
-
const wrapper = "
|
|
1285
|
-
const header$1 = "
|
|
1286
|
-
const langTrigger = "
|
|
1287
|
-
const langChevron = "
|
|
1288
|
-
const
|
|
1289
|
-
const
|
|
1290
|
-
const
|
|
1291
|
-
const
|
|
1292
|
-
const
|
|
1293
|
-
const
|
|
1294
|
-
const
|
|
1295
|
+
const wrapper = "_wrapper_16490_2";
|
|
1296
|
+
const header$1 = "_header_16490_18";
|
|
1297
|
+
const langTrigger = "_langTrigger_16490_28";
|
|
1298
|
+
const langChevron = "_langChevron_16490_50";
|
|
1299
|
+
const readonlyHeader = "_readonlyHeader_16490_56";
|
|
1300
|
+
const langBadge = "_langBadge_16490_64";
|
|
1301
|
+
const langMenu = "_langMenu_16490_78";
|
|
1302
|
+
const langItem = "_langItem_16490_91";
|
|
1303
|
+
const langItemSelected = "_langItemSelected_16490_110";
|
|
1304
|
+
const langItemCheck = "_langItemCheck_16490_115";
|
|
1305
|
+
const deleteBtn = "_deleteBtn_16490_123";
|
|
1306
|
+
const pre = "_pre_16490_143";
|
|
1307
|
+
const readonly = "_readonly_16490_56";
|
|
1308
|
+
const expanded = "_expanded_16490_162";
|
|
1309
|
+
const gutter = "_gutter_16490_168";
|
|
1310
|
+
const gutterLine = "_gutterLine_16490_185";
|
|
1311
|
+
const readonlyActions = "_readonlyActions_16490_189";
|
|
1312
|
+
const actionBtn = "_actionBtn_16490_195";
|
|
1313
|
+
const langBraces = "_langBraces_16490_214";
|
|
1295
1314
|
const styles$4 = {
|
|
1296
1315
|
wrapper,
|
|
1297
1316
|
header: header$1,
|
|
1298
1317
|
langTrigger,
|
|
1299
1318
|
langChevron,
|
|
1319
|
+
readonlyHeader,
|
|
1300
1320
|
langBadge,
|
|
1301
1321
|
langMenu,
|
|
1302
1322
|
langItem,
|
|
1303
1323
|
langItemSelected,
|
|
1304
1324
|
langItemCheck,
|
|
1305
1325
|
deleteBtn,
|
|
1306
|
-
pre
|
|
1326
|
+
pre,
|
|
1327
|
+
readonly,
|
|
1328
|
+
expanded,
|
|
1329
|
+
gutter,
|
|
1330
|
+
gutterLine,
|
|
1331
|
+
readonlyActions,
|
|
1332
|
+
actionBtn,
|
|
1333
|
+
langBraces
|
|
1307
1334
|
};
|
|
1308
1335
|
const LANGUAGES = [
|
|
1309
1336
|
{ value: "", label: "Auto-detect" },
|
|
@@ -1341,7 +1368,60 @@ function CodeBlockView({
|
|
|
1341
1368
|
const current = LANGUAGES.find((l) => l.value === language);
|
|
1342
1369
|
const currentLabel = current ? current.value === "" ? labels.autoDetect : current.label : labels.autoDetect;
|
|
1343
1370
|
const editable = editor.isEditable;
|
|
1344
|
-
|
|
1371
|
+
const readonly2 = !editable;
|
|
1372
|
+
const [copied, setCopied] = useState(false);
|
|
1373
|
+
const [expanded2, setExpanded] = useState(false);
|
|
1374
|
+
const [scrollable, setScrollable] = useState(false);
|
|
1375
|
+
const [lineCount, setLineCount] = useState(
|
|
1376
|
+
() => Math.max((node.textContent ?? "").split("\n").length, 1)
|
|
1377
|
+
);
|
|
1378
|
+
const preRef = useRef(null);
|
|
1379
|
+
useEffect(() => {
|
|
1380
|
+
if (!readonly2) return;
|
|
1381
|
+
const pre2 = preRef.current;
|
|
1382
|
+
if (!pre2) return;
|
|
1383
|
+
const update = () => {
|
|
1384
|
+
setLineCount(Math.max((pre2.textContent ?? "").split("\n").length, 1));
|
|
1385
|
+
setScrollable(pre2.scrollHeight > pre2.clientHeight + 2);
|
|
1386
|
+
};
|
|
1387
|
+
update();
|
|
1388
|
+
const mo = new MutationObserver(update);
|
|
1389
|
+
mo.observe(pre2, { childList: true, subtree: true, characterData: true });
|
|
1390
|
+
window.addEventListener("resize", update);
|
|
1391
|
+
return () => {
|
|
1392
|
+
mo.disconnect();
|
|
1393
|
+
window.removeEventListener("resize", update);
|
|
1394
|
+
};
|
|
1395
|
+
}, [readonly2, expanded2]);
|
|
1396
|
+
const handleCopy = () => {
|
|
1397
|
+
var _a2;
|
|
1398
|
+
const text = node.textContent ?? "";
|
|
1399
|
+
const done = () => {
|
|
1400
|
+
setCopied(true);
|
|
1401
|
+
window.setTimeout(() => setCopied(false), 1500);
|
|
1402
|
+
};
|
|
1403
|
+
if ((_a2 = navigator.clipboard) == null ? void 0 : _a2.writeText) {
|
|
1404
|
+
navigator.clipboard.writeText(text).then(done, () => {
|
|
1405
|
+
});
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
const ta = document.createElement("textarea");
|
|
1409
|
+
ta.value = text;
|
|
1410
|
+
document.body.appendChild(ta);
|
|
1411
|
+
ta.select();
|
|
1412
|
+
try {
|
|
1413
|
+
document.execCommand("copy");
|
|
1414
|
+
done();
|
|
1415
|
+
} catch {
|
|
1416
|
+
}
|
|
1417
|
+
ta.remove();
|
|
1418
|
+
};
|
|
1419
|
+
const wrapperClass = [
|
|
1420
|
+
styles$4.wrapper,
|
|
1421
|
+
readonly2 ? styles$4.readonly : "",
|
|
1422
|
+
expanded2 ? styles$4.expanded : ""
|
|
1423
|
+
].filter(Boolean).join(" ");
|
|
1424
|
+
return /* @__PURE__ */ jsxs(NodeViewWrapper, { className: wrapperClass, children: [
|
|
1345
1425
|
editable ? /* @__PURE__ */ jsxs("div", { className: styles$4.header, contentEditable: false, children: [
|
|
1346
1426
|
/* @__PURE__ */ jsxs(DropdownMenu.Root, { children: [
|
|
1347
1427
|
/* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
@@ -1393,10 +1473,51 @@ function CodeBlockView({
|
|
|
1393
1473
|
}
|
|
1394
1474
|
)
|
|
1395
1475
|
] }) : (
|
|
1396
|
-
//
|
|
1397
|
-
/* @__PURE__ */
|
|
1476
|
+
// 只读头部:左侧语言标签,右侧复制 + 展开收起(内容不超限高时隐藏展开钮)
|
|
1477
|
+
/* @__PURE__ */ jsxs("div", { className: styles$4.readonlyHeader, contentEditable: false, children: [
|
|
1478
|
+
/* @__PURE__ */ jsxs("span", { className: styles$4.langBadge, children: [
|
|
1479
|
+
/* @__PURE__ */ jsx("span", { className: styles$4.langBraces, children: "{}" }),
|
|
1480
|
+
currentLabel
|
|
1481
|
+
] }),
|
|
1482
|
+
/* @__PURE__ */ jsxs("span", { className: styles$4.readonlyActions, children: [
|
|
1483
|
+
/* @__PURE__ */ jsx(
|
|
1484
|
+
"button",
|
|
1485
|
+
{
|
|
1486
|
+
type: "button",
|
|
1487
|
+
className: styles$4.actionBtn,
|
|
1488
|
+
onClick: handleCopy,
|
|
1489
|
+
"aria-label": labels.copy,
|
|
1490
|
+
title: labels.copy,
|
|
1491
|
+
children: copied ? /* @__PURE__ */ jsx(CheckIcon, { size: 14 }) : /* @__PURE__ */ jsx(CopyIcon, { size: 14 })
|
|
1492
|
+
}
|
|
1493
|
+
),
|
|
1494
|
+
scrollable ? /* @__PURE__ */ jsx(
|
|
1495
|
+
"button",
|
|
1496
|
+
{
|
|
1497
|
+
type: "button",
|
|
1498
|
+
className: styles$4.actionBtn,
|
|
1499
|
+
onClick: () => setExpanded((v) => !v),
|
|
1500
|
+
"aria-label": expanded2 ? labels.collapse : labels.expand,
|
|
1501
|
+
title: expanded2 ? labels.collapse : labels.expand,
|
|
1502
|
+
"aria-expanded": expanded2,
|
|
1503
|
+
children: /* @__PURE__ */ jsx(ChevronsUpDownIcon, { size: 14 })
|
|
1504
|
+
}
|
|
1505
|
+
) : null
|
|
1506
|
+
] })
|
|
1507
|
+
] })
|
|
1398
1508
|
),
|
|
1399
|
-
/* @__PURE__ */
|
|
1509
|
+
/* @__PURE__ */ jsxs("pre", { ref: preRef, className: styles$4.pre, children: [
|
|
1510
|
+
readonly2 ? /* @__PURE__ */ jsx(
|
|
1511
|
+
"span",
|
|
1512
|
+
{
|
|
1513
|
+
className: styles$4.gutter,
|
|
1514
|
+
contentEditable: false,
|
|
1515
|
+
"aria-hidden": "true",
|
|
1516
|
+
children: Array.from({ length: lineCount }, (_, i) => /* @__PURE__ */ jsx("span", { className: styles$4.gutterLine, children: i + 1 }, i))
|
|
1517
|
+
}
|
|
1518
|
+
) : null,
|
|
1519
|
+
/* @__PURE__ */ jsx(NodeViewContent, { as: "code" })
|
|
1520
|
+
] })
|
|
1400
1521
|
] });
|
|
1401
1522
|
}
|
|
1402
1523
|
const CodeBlock = CodeBlockLowlight.extend({
|
|
@@ -1654,14 +1775,14 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
|
|
|
1654
1775
|
(_a = onCommentClickRef.current) == null ? void 0 : _a.call(onCommentClickRef, click);
|
|
1655
1776
|
(_b = onActiveCommentChangeRef.current) == null ? void 0 : _b.call(onActiveCommentChangeRef, click.commentIds[0] ?? null);
|
|
1656
1777
|
}
|
|
1657
|
-
const
|
|
1658
|
-
if (
|
|
1778
|
+
const gutter2 = transaction.getMeta(COMMENT_GUTTER_META);
|
|
1779
|
+
if (gutter2) {
|
|
1659
1780
|
(_c = onCommentClickRef.current) == null ? void 0 : _c.call(onCommentClickRef, {
|
|
1660
|
-
commentIds:
|
|
1781
|
+
commentIds: gutter2.commentIds,
|
|
1661
1782
|
anchorEl: null,
|
|
1662
|
-
pos:
|
|
1783
|
+
pos: gutter2.pos
|
|
1663
1784
|
});
|
|
1664
|
-
(_d = onActiveCommentChangeRef.current) == null ? void 0 : _d.call(onActiveCommentChangeRef,
|
|
1785
|
+
(_d = onActiveCommentChangeRef.current) == null ? void 0 : _d.call(onActiveCommentChangeRef, gutter2.commentIds[0] ?? null);
|
|
1665
1786
|
}
|
|
1666
1787
|
};
|
|
1667
1788
|
editor.on("transaction", onTransaction);
|
|
@@ -1735,10 +1856,18 @@ function MarkdownPreview({
|
|
|
1735
1856
|
),
|
|
1736
1857
|
[markdown, sources]
|
|
1737
1858
|
);
|
|
1859
|
+
const previewCodeBlock = useMemo(
|
|
1860
|
+
() => pureCodeBlock.extend({
|
|
1861
|
+
addNodeView() {
|
|
1862
|
+
return ReactNodeViewRenderer(CodeBlockView);
|
|
1863
|
+
}
|
|
1864
|
+
}),
|
|
1865
|
+
[]
|
|
1866
|
+
);
|
|
1738
1867
|
const extensions = useMemo(
|
|
1739
1868
|
() => [
|
|
1740
1869
|
...baseExtensions,
|
|
1741
|
-
|
|
1870
|
+
previewCodeBlock,
|
|
1742
1871
|
pureImage,
|
|
1743
1872
|
createChart({ editable: false }),
|
|
1744
1873
|
createCitationRef({ renderCitation }),
|
|
@@ -3566,7 +3695,7 @@ function getMarkdownForRange(editor, from, to, options = {}) {
|
|
|
3566
3695
|
let first = 0;
|
|
3567
3696
|
let last = blocks.length - 1;
|
|
3568
3697
|
if (expand) {
|
|
3569
|
-
first = blocks.findIndex((
|
|
3698
|
+
first = blocks.findIndex((b3) => b3.to > start);
|
|
3570
3699
|
if (first < 0) return null;
|
|
3571
3700
|
for (let i = blocks.length - 1; i >= first; i -= 1) {
|
|
3572
3701
|
if (blocks[i].from < end) {
|
|
@@ -3577,7 +3706,7 @@ function getMarkdownForRange(editor, from, to, options = {}) {
|
|
|
3577
3706
|
start = blocks[first].from;
|
|
3578
3707
|
end = blocks[last].to;
|
|
3579
3708
|
}
|
|
3580
|
-
const parts = blocks.map((
|
|
3709
|
+
const parts = blocks.map((b3) => manager.serialize({ type: "doc", content: [b3.json] }));
|
|
3581
3710
|
const full = editor.getMarkdown();
|
|
3582
3711
|
if (expand && parts.join(BLOCK_SEPARATOR) === full) {
|
|
3583
3712
|
const markdown2 = parts.slice(first, last + 1).join(BLOCK_SEPARATOR);
|
|
@@ -3650,6 +3779,7 @@ export {
|
|
|
3650
3779
|
CheckIcon,
|
|
3651
3780
|
ChevronDownIcon,
|
|
3652
3781
|
ChevronUpIcon,
|
|
3782
|
+
ChevronsUpDownIcon,
|
|
3653
3783
|
a as CitationInteractive,
|
|
3654
3784
|
CitationRef,
|
|
3655
3785
|
CodeBlockView,
|
|
@@ -3660,6 +3790,7 @@ export {
|
|
|
3660
3790
|
ColumnDeleteIcon,
|
|
3661
3791
|
CommentMark,
|
|
3662
3792
|
CommentPopover,
|
|
3793
|
+
CopyIcon,
|
|
3663
3794
|
EditorToolbar,
|
|
3664
3795
|
FIND_DEBOUNCE_MS,
|
|
3665
3796
|
default2 as FindAndReplace,
|
|
@@ -3715,6 +3846,7 @@ export {
|
|
|
3715
3846
|
defaultTocLabels,
|
|
3716
3847
|
defaultToolbarLabels,
|
|
3717
3848
|
enrichMarkdownCitations,
|
|
3849
|
+
b2 as extractFootnoteSources,
|
|
3718
3850
|
e as extractToc,
|
|
3719
3851
|
f as findCitationRefElement,
|
|
3720
3852
|
findRangeByAnchor,
|