tiptap-markdown-react 0.10.4 → 0.12.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 +84 -1
- package/THIRD_PARTY_LICENSES.md +2 -0
- package/dist/{ReportContent-DQKBSQmm.js → ReportContent-CfvE4CYH.js} +9 -3
- package/dist/{ReportContent-DQKBSQmm.js.map → ReportContent-CfvE4CYH.js.map} +1 -1
- package/dist/components/FindReplaceBar.d.ts +27 -0
- package/dist/components/FindReplaceBar.dom.test.d.ts +1 -0
- package/dist/components/MarkdownWysiwygEditor.d.ts +48 -1
- package/dist/{extractToc-CKTMdT0a.js → extractToc-BT3OquOq.js} +2 -2
- package/dist/{extractToc-CKTMdT0a.js.map → extractToc-BT3OquOq.js.map} +1 -1
- package/dist/findReplace.d.ts +30 -0
- package/dist/findReplace.test.d.ts +1 -0
- package/dist/icons/index.d.ts +5 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +840 -419
- package/dist/index.js.map +1 -1
- package/dist/labels.d.ts +21 -0
- package/dist/reader.js +2 -2
- package/dist/{scrollToTocHeading-DIAd_fIC.js → scrollToTocHeading-DVdii3VR.js} +2 -2
- package/dist/{scrollToTocHeading-DIAd_fIC.js.map → scrollToTocHeading-DVdii3VR.js.map} +1 -1
- package/dist/server.js +4 -4
- package/dist/style.css +242 -49
- package/package.json +30 -29
package/dist/index.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
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-DVdii3VR.js";
|
|
4
|
+
import { C, a, R, b, f, m, r, s } from "./scrollToTocHeading-DVdii3VR.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
|
+
import FindAndReplace, { FindAndReplacePluginKey, createSearchRegex } from "@tiptap/extension-find-and-replace";
|
|
8
|
+
import { default as default2 } from "@tiptap/extension-find-and-replace";
|
|
7
9
|
import Image from "@tiptap/extension-image";
|
|
8
10
|
import { TableOfContents } from "@tiptap/extension-table-of-contents";
|
|
9
|
-
import { NodeViewWrapper, ReactNodeViewRenderer, NodeViewContent, useEditor, EditorContent
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
11
|
+
import { NodeViewWrapper, ReactNodeViewRenderer, useEditorState, NodeViewContent, useEditor, EditorContent } from "@tiptap/react";
|
|
12
|
+
import { createPortal } from "react-dom";
|
|
13
|
+
import { useState, useEffect, useCallback, useRef, useMemo, forwardRef, useImperativeHandle, useId, useContext, createContext } from "react";
|
|
14
|
+
import { e as enrichMarkdownCitations, b as styles$6 } from "./ReportContent-CfvE4CYH.js";
|
|
15
|
+
import { R as R2, a as a2, s as s2 } from "./ReportContent-CfvE4CYH.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-BT3OquOq.js";
|
|
17
|
+
import { g, e, s as s3 } from "./extractToc-BT3OquOq.js";
|
|
15
18
|
import { Slice, Fragment } from "@tiptap/pm/model";
|
|
16
19
|
import { Extension, Node as Node$1 } from "@tiptap/core";
|
|
17
20
|
import { PluginKey, Plugin, NodeSelection, TextSelection } from "@tiptap/pm/state";
|
|
@@ -21,7 +24,6 @@ import { skipTrailingNodeMeta } from "@tiptap/extensions";
|
|
|
21
24
|
import { CellSelection, isInTable, selectedRect, rowIsHeader } from "@tiptap/pm/tables";
|
|
22
25
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
|
23
26
|
import * as Popover from "@radix-ui/react-popover";
|
|
24
|
-
import { createPortal } from "react-dom";
|
|
25
27
|
function CitationRefView({ node, extension }) {
|
|
26
28
|
const index = String(node.attrs.index ?? "");
|
|
27
29
|
const url = node.attrs.url || null;
|
|
@@ -333,247 +335,179 @@ function nextComment(editor, dir = "next") {
|
|
|
333
335
|
focusComment(editor, target);
|
|
334
336
|
return target;
|
|
335
337
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
338
|
+
const FIND_DEBOUNCE_MS = 120;
|
|
339
|
+
const MISMATCH_RE = /Applying a mismatched transaction/;
|
|
340
|
+
function runFindCommand(run) {
|
|
341
|
+
try {
|
|
342
|
+
run();
|
|
343
|
+
} catch (error) {
|
|
344
|
+
if (error instanceof RangeError && MISMATCH_RE.test(error.message)) {
|
|
345
|
+
run();
|
|
346
|
+
return;
|
|
342
347
|
}
|
|
343
|
-
|
|
344
|
-
return found;
|
|
345
|
-
}
|
|
346
|
-
const ImportPlaceholder = Node$1.create({
|
|
347
|
-
name: "importPlaceholder",
|
|
348
|
-
group: "block",
|
|
349
|
-
atom: true,
|
|
350
|
-
selectable: false,
|
|
351
|
-
draggable: false,
|
|
352
|
-
addAttributes() {
|
|
353
|
-
return {
|
|
354
|
-
label: {
|
|
355
|
-
default: "",
|
|
356
|
-
parseHTML: (el) => el.getAttribute("data-label") ?? "",
|
|
357
|
-
renderHTML: (attrs) => attrs.label ? { "data-label": attrs.label } : {}
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
},
|
|
361
|
-
parseHTML() {
|
|
362
|
-
return [{ tag: 'div[data-type="import-placeholder"]' }];
|
|
363
|
-
},
|
|
364
|
-
renderHTML({ node, HTMLAttributes }) {
|
|
365
|
-
const label = String(node.attrs.label ?? "");
|
|
366
|
-
return [
|
|
367
|
-
"div",
|
|
368
|
-
{
|
|
369
|
-
...HTMLAttributes,
|
|
370
|
-
"data-type": "import-placeholder",
|
|
371
|
-
class: "tmr-import-placeholder",
|
|
372
|
-
contenteditable: "false",
|
|
373
|
-
"aria-live": "polite",
|
|
374
|
-
"aria-busy": "true"
|
|
375
|
-
},
|
|
376
|
-
["span", { class: "tmr-import-placeholder-spin", "aria-hidden": "true" }],
|
|
377
|
-
["span", { class: "tmr-import-placeholder-label" }, label]
|
|
378
|
-
];
|
|
379
|
-
},
|
|
380
|
-
renderMarkdown() {
|
|
381
|
-
return "";
|
|
382
|
-
},
|
|
383
|
-
addCommands() {
|
|
384
|
-
return {
|
|
385
|
-
insertImportPlaceholder: (label) => ({ chain }) => chain().focus().insertContent({
|
|
386
|
-
type: this.name,
|
|
387
|
-
attrs: { label }
|
|
388
|
-
}).command(({ tr }) => {
|
|
389
|
-
tr.setMeta("addToHistory", false);
|
|
390
|
-
tr.setMeta("preventUpdate", true);
|
|
391
|
-
return true;
|
|
392
|
-
}).run(),
|
|
393
|
-
updateImportPlaceholder: (label) => ({ tr, dispatch, state }) => {
|
|
394
|
-
const pos = findPlaceholderPos(state.doc);
|
|
395
|
-
if (pos == null) return false;
|
|
396
|
-
if (dispatch) {
|
|
397
|
-
dispatch(
|
|
398
|
-
tr.setNodeMarkup(pos, void 0, { label }).setMeta("addToHistory", false).setMeta("preventUpdate", true)
|
|
399
|
-
);
|
|
400
|
-
}
|
|
401
|
-
return true;
|
|
402
|
-
},
|
|
403
|
-
removeImportPlaceholder: () => ({ tr, dispatch, state }) => {
|
|
404
|
-
const pos = findPlaceholderPos(state.doc);
|
|
405
|
-
if (pos == null) return false;
|
|
406
|
-
const node = state.doc.nodeAt(pos);
|
|
407
|
-
if (!node) return false;
|
|
408
|
-
if (dispatch) {
|
|
409
|
-
dispatch(
|
|
410
|
-
tr.delete(pos, pos + node.nodeSize).setMeta("addToHistory", false).setMeta("preventUpdate", true)
|
|
411
|
-
);
|
|
412
|
-
}
|
|
413
|
-
return true;
|
|
414
|
-
}
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
});
|
|
418
|
-
const MD_FILE_RE$1 = /\.(md|markdown)$/i;
|
|
419
|
-
const MD_MIME_TYPES = ["text/markdown", "text/x-markdown", ""];
|
|
420
|
-
async function insertMarkdownFiles(editor, files, pos) {
|
|
421
|
-
const mdFiles = files.filter((f2) => MD_FILE_RE$1.test(f2.name));
|
|
422
|
-
if (mdFiles.length === 0) return;
|
|
423
|
-
const markdown = editor.markdown;
|
|
424
|
-
if (!markdown) return;
|
|
425
|
-
const texts = await Promise.all(mdFiles.map((f2) => f2.text()));
|
|
426
|
-
const json = markdown.parse(texts.join("\n\n"));
|
|
427
|
-
if (pos != null) {
|
|
428
|
-
editor.chain().focus().insertContentAt(pos, json).run();
|
|
429
|
-
} else {
|
|
430
|
-
editor.chain().focus().insertContent(json).run();
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
const MarkdownFileDrop = Extension.create({
|
|
434
|
-
name: "markdownFileDrop",
|
|
435
|
-
addProseMirrorPlugins() {
|
|
436
|
-
const { editor } = this;
|
|
437
|
-
return [
|
|
438
|
-
FileHandlePlugin({
|
|
439
|
-
key: new PluginKey("markdownFileDrop"),
|
|
440
|
-
editor,
|
|
441
|
-
allowedMimeTypes: MD_MIME_TYPES,
|
|
442
|
-
onDrop: (ed, files, pos) => {
|
|
443
|
-
insertMarkdownFiles(ed, files, pos).catch((err) => {
|
|
444
|
-
console.error("markdown file drop failed:", err);
|
|
445
|
-
});
|
|
446
|
-
},
|
|
447
|
-
onPaste: (ed, files) => {
|
|
448
|
-
insertMarkdownFiles(ed, files).catch((err) => {
|
|
449
|
-
console.error("markdown file paste failed:", err);
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
})
|
|
453
|
-
];
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
const PENDING_ANCHOR_META = "tmr:pendingAnchor";
|
|
457
|
-
const pendingAnchorPluginKey = new PluginKey(
|
|
458
|
-
"tmrPendingAnchor"
|
|
459
|
-
);
|
|
460
|
-
const PENDING_ANCHOR_CLASS = "tmr-pending-anchor";
|
|
461
|
-
const pendingAnchorExtension = Extension.create({
|
|
462
|
-
name: "pendingAnchor",
|
|
463
|
-
addProseMirrorPlugins() {
|
|
464
|
-
return [
|
|
465
|
-
new Plugin({
|
|
466
|
-
key: pendingAnchorPluginKey,
|
|
467
|
-
state: {
|
|
468
|
-
init: () => ({ decorations: DecorationSet.empty }),
|
|
469
|
-
apply(tr, value) {
|
|
470
|
-
const next = tr.getMeta(PENDING_ANCHOR_META);
|
|
471
|
-
if (next) return { decorations: buildDecorations(tr.doc, next) };
|
|
472
|
-
if (tr.docChanged) {
|
|
473
|
-
return { decorations: value.decorations.map(tr.mapping, tr.doc) };
|
|
474
|
-
}
|
|
475
|
-
return value;
|
|
476
|
-
}
|
|
477
|
-
},
|
|
478
|
-
props: {
|
|
479
|
-
decorations(state) {
|
|
480
|
-
var _a;
|
|
481
|
-
return ((_a = pendingAnchorPluginKey.getState(state)) == null ? void 0 : _a.decorations) ?? null;
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
})
|
|
485
|
-
];
|
|
348
|
+
throw error;
|
|
486
349
|
}
|
|
487
|
-
});
|
|
488
|
-
function setPendingAnchors(editor, anchors) {
|
|
489
|
-
editor.view.dispatch(
|
|
490
|
-
editor.state.tr.setMeta(PENDING_ANCHOR_META, anchors).setMeta(skipTrailingNodeMeta, true).setMeta("addToHistory", false)
|
|
491
|
-
);
|
|
492
350
|
}
|
|
493
|
-
function
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
if (from <= bound.from && to >= bound.to) {
|
|
511
|
-
decorations.push(Decoration.node(bound.from, bound.to, attrs));
|
|
512
|
-
} else {
|
|
513
|
-
decorations.push(
|
|
514
|
-
Decoration.inline(Math.max(from, bound.from), Math.min(to, bound.to), attrs)
|
|
515
|
-
);
|
|
516
|
-
}
|
|
517
|
-
}
|
|
351
|
+
function Svg({ size = "1em", children, ...rest }) {
|
|
352
|
+
return /* @__PURE__ */ jsx(
|
|
353
|
+
"svg",
|
|
354
|
+
{
|
|
355
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
356
|
+
width: size,
|
|
357
|
+
height: size,
|
|
358
|
+
viewBox: "0 0 24 24",
|
|
359
|
+
fill: "none",
|
|
360
|
+
stroke: "currentColor",
|
|
361
|
+
strokeWidth: 2,
|
|
362
|
+
strokeLinecap: "round",
|
|
363
|
+
strokeLinejoin: "round",
|
|
364
|
+
"aria-hidden": "true",
|
|
365
|
+
focusable: "false",
|
|
366
|
+
...rest,
|
|
367
|
+
children
|
|
518
368
|
}
|
|
519
|
-
|
|
520
|
-
return decorations.length ? DecorationSet.create(doc, decorations) : DecorationSet.empty;
|
|
521
|
-
}
|
|
522
|
-
function selectionKind(selection) {
|
|
523
|
-
if (selection instanceof CellSelection) return "cell";
|
|
524
|
-
if (selection instanceof NodeSelection) return "node";
|
|
525
|
-
if (selection instanceof TextSelection) return "text";
|
|
526
|
-
return "text";
|
|
527
|
-
}
|
|
528
|
-
function looksLikeMarkdown(text) {
|
|
529
|
-
return /^#{1,6}\s/m.test(text) || // 标题
|
|
530
|
-
/\*\*[^*\n]+\*\*/.test(text) || // 加粗
|
|
531
|
-
/(^|[^!])\[[^\]\n]+\]\([^)\n]+\)/.test(text) || // 链接
|
|
532
|
-
/!\[[^\]\n]*\]\([^)\n]+\)/.test(text) || // 图片
|
|
533
|
-
/^[-*+]\s+\S/m.test(text) || // 无序列表
|
|
534
|
-
/^\d+\.\s+\S/m.test(text) || // 有序列表
|
|
535
|
-
/^>\s/m.test(text) || // 引用
|
|
536
|
-
/^```/m.test(text) || // 代码围栏
|
|
537
|
-
/^\|.+\|\s*$/m.test(text) || // 表格行
|
|
538
|
-
/^(-{3,}|\*{3,})\s*$/m.test(text) || // 分割线
|
|
539
|
-
/<!--\s*[\[{][\s\S]*?"chartType"[\s\S]*?-->/.test(text);
|
|
369
|
+
);
|
|
540
370
|
}
|
|
541
|
-
const
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
})
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
371
|
+
const BoldIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
372
|
+
/* @__PURE__ */ jsx("path", { d: "M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" }),
|
|
373
|
+
/* @__PURE__ */ jsx("path", { d: "M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" })
|
|
374
|
+
] });
|
|
375
|
+
const ItalicIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
376
|
+
/* @__PURE__ */ jsx("line", { x1: "19", x2: "10", y1: "4", y2: "4" }),
|
|
377
|
+
/* @__PURE__ */ jsx("line", { x1: "14", x2: "5", y1: "20", y2: "20" }),
|
|
378
|
+
/* @__PURE__ */ jsx("line", { x1: "15", x2: "9", y1: "4", y2: "20" })
|
|
379
|
+
] });
|
|
380
|
+
const UnderlineIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
381
|
+
/* @__PURE__ */ jsx("path", { d: "M6 4v6a6 6 0 0 0 12 0V4" }),
|
|
382
|
+
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "20", y2: "20" })
|
|
383
|
+
] });
|
|
384
|
+
const StrikethroughIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
385
|
+
/* @__PURE__ */ jsx("path", { d: "M16 4H9a3 3 0 0 0-2.83 4" }),
|
|
386
|
+
/* @__PURE__ */ jsx("path", { d: "M14 12a4 4 0 0 1 0 8H6" }),
|
|
387
|
+
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "12", y2: "12" })
|
|
388
|
+
] });
|
|
389
|
+
const CodeIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
390
|
+
/* @__PURE__ */ jsx("polyline", { points: "16 18 22 12 16 6" }),
|
|
391
|
+
/* @__PURE__ */ jsx("polyline", { points: "8 6 2 12 8 18" })
|
|
392
|
+
] });
|
|
393
|
+
const LinkIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
394
|
+
/* @__PURE__ */ jsx("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
|
|
395
|
+
/* @__PURE__ */ jsx("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
|
|
396
|
+
] });
|
|
397
|
+
const ImageIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
398
|
+
/* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
|
|
399
|
+
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "2" }),
|
|
400
|
+
/* @__PURE__ */ jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
|
|
401
|
+
] });
|
|
402
|
+
const ImportIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
403
|
+
/* @__PURE__ */ jsx("path", { d: "M12 3v12" }),
|
|
404
|
+
/* @__PURE__ */ jsx("path", { d: "m8 11 4 4 4-4" }),
|
|
405
|
+
/* @__PURE__ */ jsx("path", { d: "M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4" })
|
|
406
|
+
] });
|
|
407
|
+
const ListUnorderedIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
408
|
+
/* @__PURE__ */ jsx("line", { x1: "8", x2: "21", y1: "6", y2: "6" }),
|
|
409
|
+
/* @__PURE__ */ jsx("line", { x1: "8", x2: "21", y1: "12", y2: "12" }),
|
|
410
|
+
/* @__PURE__ */ jsx("line", { x1: "8", x2: "21", y1: "18", y2: "18" }),
|
|
411
|
+
/* @__PURE__ */ jsx("line", { x1: "3", x2: "3.01", y1: "6", y2: "6" }),
|
|
412
|
+
/* @__PURE__ */ jsx("line", { x1: "3", x2: "3.01", y1: "12", y2: "12" }),
|
|
413
|
+
/* @__PURE__ */ jsx("line", { x1: "3", x2: "3.01", y1: "18", y2: "18" })
|
|
414
|
+
] });
|
|
415
|
+
const ListOrderedIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
416
|
+
/* @__PURE__ */ jsx("line", { x1: "10", x2: "21", y1: "6", y2: "6" }),
|
|
417
|
+
/* @__PURE__ */ jsx("line", { x1: "10", x2: "21", y1: "12", y2: "12" }),
|
|
418
|
+
/* @__PURE__ */ jsx("line", { x1: "10", x2: "21", y1: "18", y2: "18" }),
|
|
419
|
+
/* @__PURE__ */ jsx("path", { d: "M4 6h1v4" }),
|
|
420
|
+
/* @__PURE__ */ jsx("path", { d: "M4 10h2" }),
|
|
421
|
+
/* @__PURE__ */ jsx("path", { d: "M6 18H4c0-1 2-2 2-3s-1-1.5-2-1" })
|
|
422
|
+
] });
|
|
423
|
+
const ListChecksIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
424
|
+
/* @__PURE__ */ jsx("path", { d: "m3 17 2 2 4-4" }),
|
|
425
|
+
/* @__PURE__ */ jsx("path", { d: "m3 7 2 2 4-4" }),
|
|
426
|
+
/* @__PURE__ */ jsx("path", { d: "M13 6h8" }),
|
|
427
|
+
/* @__PURE__ */ jsx("path", { d: "M13 12h8" }),
|
|
428
|
+
/* @__PURE__ */ jsx("path", { d: "M13 18h8" })
|
|
429
|
+
] });
|
|
430
|
+
const UndoIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
431
|
+
/* @__PURE__ */ jsx("path", { d: "M9 14 4 9l5-5" }),
|
|
432
|
+
/* @__PURE__ */ jsx("path", { d: "M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5 5.5 5.5 0 0 1-5.5 5.5H11" })
|
|
433
|
+
] });
|
|
434
|
+
const RedoIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
435
|
+
/* @__PURE__ */ jsx("path", { d: "m15 14 5-5-5-5" }),
|
|
436
|
+
/* @__PURE__ */ jsx("path", { d: "M20 9H9.5A5.5 5.5 0 0 0 4 14.5 5.5 5.5 0 0 0 9.5 20H13" })
|
|
437
|
+
] });
|
|
438
|
+
const ChevronDownIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) });
|
|
439
|
+
const CheckIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
|
|
440
|
+
const TrashIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
441
|
+
/* @__PURE__ */ jsx("path", { d: "M3 6h18" }),
|
|
442
|
+
/* @__PURE__ */ jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
|
|
443
|
+
/* @__PURE__ */ jsx("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }),
|
|
444
|
+
/* @__PURE__ */ jsx("line", { x1: "10", x2: "10", y1: "11", y2: "17" }),
|
|
445
|
+
/* @__PURE__ */ jsx("line", { x1: "14", x2: "14", y1: "11", y2: "17" })
|
|
446
|
+
] });
|
|
447
|
+
const LockIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
448
|
+
/* @__PURE__ */ jsx("rect", { width: "18", height: "11", x: "3", y: "11", rx: "2", ry: "2" }),
|
|
449
|
+
/* @__PURE__ */ jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
|
|
450
|
+
] });
|
|
451
|
+
const MenuIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
452
|
+
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "12", y2: "12" }),
|
|
453
|
+
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "6", y2: "6" }),
|
|
454
|
+
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "18", y2: "18" })
|
|
455
|
+
] });
|
|
456
|
+
const SearchIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
457
|
+
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
|
|
458
|
+
/* @__PURE__ */ jsx("path", { d: "m21 21-4.3-4.3" })
|
|
459
|
+
] });
|
|
460
|
+
const XIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
461
|
+
/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
|
|
462
|
+
/* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
|
|
463
|
+
] });
|
|
464
|
+
const ChevronUpIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "m18 15-6-6-6 6" }) });
|
|
465
|
+
const ColumnBeforeIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
466
|
+
/* @__PURE__ */ jsx("rect", { x: "10", y: "4", width: "11", height: "16", rx: "1" }),
|
|
467
|
+
/* @__PURE__ */ jsx("path", { d: "M14 4v16" }),
|
|
468
|
+
/* @__PURE__ */ jsx("path", { d: "M5 9v6" }),
|
|
469
|
+
/* @__PURE__ */ jsx("path", { d: "M2 12h6" })
|
|
470
|
+
] });
|
|
471
|
+
const ColumnAfterIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
472
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "11", height: "16", rx: "1" }),
|
|
473
|
+
/* @__PURE__ */ jsx("path", { d: "M10 4v16" }),
|
|
474
|
+
/* @__PURE__ */ jsx("path", { d: "M19 9v6" }),
|
|
475
|
+
/* @__PURE__ */ jsx("path", { d: "M16 12h6" })
|
|
476
|
+
] });
|
|
477
|
+
const ColumnDeleteIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
478
|
+
/* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "1" }),
|
|
479
|
+
/* @__PURE__ */ jsx("path", { d: "M12 4v16" }),
|
|
480
|
+
/* @__PURE__ */ jsx("path", { d: "m8 9 8 6" }),
|
|
481
|
+
/* @__PURE__ */ jsx("path", { d: "m16 9-8 6" })
|
|
482
|
+
] });
|
|
483
|
+
const RowBeforeIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
484
|
+
/* @__PURE__ */ jsx("rect", { x: "4", y: "10", width: "16", height: "11", rx: "1" }),
|
|
485
|
+
/* @__PURE__ */ jsx("path", { d: "M4 14h16" }),
|
|
486
|
+
/* @__PURE__ */ jsx("path", { d: "M9 5h6" }),
|
|
487
|
+
/* @__PURE__ */ jsx("path", { d: "M12 2v6" })
|
|
488
|
+
] });
|
|
489
|
+
const RowAfterIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
490
|
+
/* @__PURE__ */ jsx("rect", { x: "4", y: "3", width: "16", height: "11", rx: "1" }),
|
|
491
|
+
/* @__PURE__ */ jsx("path", { d: "M4 10h16" }),
|
|
492
|
+
/* @__PURE__ */ jsx("path", { d: "M9 19h6" }),
|
|
493
|
+
/* @__PURE__ */ jsx("path", { d: "M12 16v6" })
|
|
494
|
+
] });
|
|
495
|
+
const RowDeleteIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
496
|
+
/* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "1" }),
|
|
497
|
+
/* @__PURE__ */ jsx("path", { d: "M4 12h16" }),
|
|
498
|
+
/* @__PURE__ */ jsx("path", { d: "m9 8 6 8" }),
|
|
499
|
+
/* @__PURE__ */ jsx("path", { d: "m15 8-6 8" })
|
|
500
|
+
] });
|
|
501
|
+
const TableDeleteIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
502
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "5", width: "18", height: "14", rx: "1" }),
|
|
503
|
+
/* @__PURE__ */ jsx("path", { d: "M3 9h18" }),
|
|
504
|
+
/* @__PURE__ */ jsx("path", { d: "M9 5v14" }),
|
|
505
|
+
/* @__PURE__ */ jsx("path", { d: "M15 5v14" }),
|
|
506
|
+
/* @__PURE__ */ jsx("path", { d: "m7 2 10 20" })
|
|
507
|
+
] });
|
|
508
|
+
const defaultChartLabels = {
|
|
509
|
+
tabLabel: (chartType, index) => `${chartType} ${index + 1}`,
|
|
510
|
+
done: "Done",
|
|
577
511
|
cancel: "Cancel",
|
|
578
512
|
configLabel: "Chart config (JSON)",
|
|
579
513
|
tableLabel: "Data table (Markdown)",
|
|
@@ -665,6 +599,556 @@ const defaultCommentLabels = {
|
|
|
665
599
|
partial: "Partially matched",
|
|
666
600
|
gutterTitle: "Comment"
|
|
667
601
|
};
|
|
602
|
+
const defaultFindLabels = {
|
|
603
|
+
find: "Find",
|
|
604
|
+
replace: "Replace with",
|
|
605
|
+
next: "Next match",
|
|
606
|
+
previous: "Previous match",
|
|
607
|
+
replaceOne: "Replace",
|
|
608
|
+
replaceAll: "Replace all",
|
|
609
|
+
close: "Close",
|
|
610
|
+
caseSensitive: "Match case",
|
|
611
|
+
wholeWord: "Whole word",
|
|
612
|
+
useRegex: "Use regular expression",
|
|
613
|
+
counter: (current, total) => `${current} / ${total}`,
|
|
614
|
+
invalidRegex: "Invalid pattern",
|
|
615
|
+
readOnly: "Read-only"
|
|
616
|
+
};
|
|
617
|
+
const bar = "_bar_1lvby_3";
|
|
618
|
+
const row = "_row_1lvby_25";
|
|
619
|
+
const field = "_field_1lvby_40";
|
|
620
|
+
const fieldIcon = "_fieldIcon_1lvby_59";
|
|
621
|
+
const input = "_input_1lvby_64";
|
|
622
|
+
const counter = "_counter_1lvby_75";
|
|
623
|
+
const counterInvalid = "_counterInvalid_1lvby_84";
|
|
624
|
+
const btn$1 = "_btn_1lvby_88";
|
|
625
|
+
const toggle = "_toggle_1lvby_116";
|
|
626
|
+
const toggleOn = "_toggleOn_1lvby_128";
|
|
627
|
+
const closeBtn = "_closeBtn_1lvby_136";
|
|
628
|
+
const textBtn = "_textBtn_1lvby_140";
|
|
629
|
+
const spacer = "_spacer_1lvby_145";
|
|
630
|
+
const readOnly = "_readOnly_1lvby_150";
|
|
631
|
+
const styles$5 = {
|
|
632
|
+
bar,
|
|
633
|
+
row,
|
|
634
|
+
field,
|
|
635
|
+
fieldIcon,
|
|
636
|
+
input,
|
|
637
|
+
counter,
|
|
638
|
+
counterInvalid,
|
|
639
|
+
btn: btn$1,
|
|
640
|
+
toggle,
|
|
641
|
+
toggleOn,
|
|
642
|
+
closeBtn,
|
|
643
|
+
textBtn,
|
|
644
|
+
spacer,
|
|
645
|
+
readOnly
|
|
646
|
+
};
|
|
647
|
+
function FindReplaceBar({
|
|
648
|
+
editor,
|
|
649
|
+
onClose,
|
|
650
|
+
labels,
|
|
651
|
+
inputRef,
|
|
652
|
+
className,
|
|
653
|
+
style
|
|
654
|
+
}) {
|
|
655
|
+
const t = { ...defaultFindLabels, ...labels };
|
|
656
|
+
const [term, setTerm] = useState("");
|
|
657
|
+
const [replaceTerm, setReplaceTerm] = useState("");
|
|
658
|
+
const hasExtension = typeof editor.commands.setSearchTerm === "function";
|
|
659
|
+
useEffect(() => {
|
|
660
|
+
if (!hasExtension) {
|
|
661
|
+
console.warn(
|
|
662
|
+
"[tiptap-markdown-react] FindReplaceBar 需要官方 find 扩展:请让 <MarkdownWysiwygEditor findReplace> 保持开启(默认 true),否则 setSearchTerm / replaceAll 等命令不存在。"
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
}, [hasExtension]);
|
|
666
|
+
const state = useEditorState({
|
|
667
|
+
editor,
|
|
668
|
+
selector: ({ editor: instance }) => {
|
|
669
|
+
const plugin = FindAndReplacePluginKey.getState(instance.state);
|
|
670
|
+
return {
|
|
671
|
+
currentIndex: (plugin == null ? void 0 : plugin.currentIndex) ?? null,
|
|
672
|
+
total: (plugin == null ? void 0 : plugin.results.length) ?? 0,
|
|
673
|
+
caseSensitive: (plugin == null ? void 0 : plugin.caseSensitive) ?? false,
|
|
674
|
+
wholeWord: (plugin == null ? void 0 : plugin.wholeWord) ?? false,
|
|
675
|
+
useRegex: (plugin == null ? void 0 : plugin.useRegex) ?? false
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
});
|
|
679
|
+
const runCommand = useCallback(
|
|
680
|
+
(run) => {
|
|
681
|
+
if (!hasExtension) return;
|
|
682
|
+
runFindCommand(run);
|
|
683
|
+
},
|
|
684
|
+
[hasExtension]
|
|
685
|
+
);
|
|
686
|
+
const appliedTermRef = useRef(null);
|
|
687
|
+
const pushTerm = useCallback(
|
|
688
|
+
(value) => {
|
|
689
|
+
appliedTermRef.current = value;
|
|
690
|
+
runCommand(() => editor.commands.setSearchTerm(value));
|
|
691
|
+
},
|
|
692
|
+
[editor, runCommand]
|
|
693
|
+
);
|
|
694
|
+
const flushTerm = useCallback(() => {
|
|
695
|
+
if (appliedTermRef.current !== term) pushTerm(term);
|
|
696
|
+
}, [pushTerm, term]);
|
|
697
|
+
useEffect(() => {
|
|
698
|
+
if (appliedTermRef.current === term) return;
|
|
699
|
+
const timer = setTimeout(() => pushTerm(term), FIND_DEBOUNCE_MS);
|
|
700
|
+
return () => clearTimeout(timer);
|
|
701
|
+
}, [term, pushTerm]);
|
|
702
|
+
useEffect(() => {
|
|
703
|
+
runCommand(() => editor.commands.setReplaceTerm(replaceTerm));
|
|
704
|
+
}, [editor, replaceTerm, runCommand]);
|
|
705
|
+
useEffect(() => {
|
|
706
|
+
return () => {
|
|
707
|
+
if (!editor.isDestroyed) runCommand(() => editor.commands.clearSearch());
|
|
708
|
+
};
|
|
709
|
+
}, [editor, runCommand]);
|
|
710
|
+
const runAction = useCallback(
|
|
711
|
+
(action) => {
|
|
712
|
+
flushTerm();
|
|
713
|
+
runCommand(action);
|
|
714
|
+
},
|
|
715
|
+
[flushTerm, runCommand]
|
|
716
|
+
);
|
|
717
|
+
const invalidPattern = useMemo(
|
|
718
|
+
() => term !== "" && state.useRegex && createSearchRegex(term, {
|
|
719
|
+
caseSensitive: state.caseSensitive,
|
|
720
|
+
useRegex: true,
|
|
721
|
+
wholeWord: false
|
|
722
|
+
}) === null,
|
|
723
|
+
[term, state.useRegex, state.caseSensitive]
|
|
724
|
+
);
|
|
725
|
+
const counter2 = t.counter(
|
|
726
|
+
state.total === 0 ? 0 : (state.currentIndex ?? 0) + 1,
|
|
727
|
+
state.total
|
|
728
|
+
);
|
|
729
|
+
const keepFocus = (e2) => e2.preventDefault();
|
|
730
|
+
const onFindKeyDown = (e2) => {
|
|
731
|
+
if (e2.key === "Enter") {
|
|
732
|
+
e2.preventDefault();
|
|
733
|
+
runAction(() => {
|
|
734
|
+
if (e2.shiftKey) editor.commands.goToPreviousResult();
|
|
735
|
+
else editor.commands.goToNextResult();
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
const onReplaceKeyDown = (e2) => {
|
|
740
|
+
if (e2.key === "Enter") {
|
|
741
|
+
e2.preventDefault();
|
|
742
|
+
runAction(() => editor.commands.replace());
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
const toggle2 = (key, value) => {
|
|
746
|
+
runCommand(() => {
|
|
747
|
+
if (key === "caseSensitive") editor.commands.setCaseSensitive(value);
|
|
748
|
+
else if (key === "wholeWord") editor.commands.setWholeWord(value);
|
|
749
|
+
else editor.commands.setUseRegex(value);
|
|
750
|
+
});
|
|
751
|
+
};
|
|
752
|
+
if (!hasExtension) return null;
|
|
753
|
+
const toggleClass = (on) => `${styles$5.btn} ${styles$5.toggle}${on ? ` ${styles$5.toggleOn}` : ""}`;
|
|
754
|
+
return /* @__PURE__ */ jsxs(
|
|
755
|
+
"div",
|
|
756
|
+
{
|
|
757
|
+
className: className ? `${styles$5.bar} ${className}` : styles$5.bar,
|
|
758
|
+
style,
|
|
759
|
+
role: "dialog",
|
|
760
|
+
"aria-label": t.find,
|
|
761
|
+
onKeyDown: (e2) => {
|
|
762
|
+
if (e2.key === "Escape") {
|
|
763
|
+
e2.preventDefault();
|
|
764
|
+
onClose();
|
|
765
|
+
}
|
|
766
|
+
},
|
|
767
|
+
children: [
|
|
768
|
+
/* @__PURE__ */ jsxs("div", { className: styles$5.row, children: [
|
|
769
|
+
/* @__PURE__ */ jsxs("span", { className: styles$5.field, children: [
|
|
770
|
+
/* @__PURE__ */ jsx(SearchIcon, { size: 14, className: styles$5.fieldIcon }),
|
|
771
|
+
/* @__PURE__ */ jsx(
|
|
772
|
+
"input",
|
|
773
|
+
{
|
|
774
|
+
ref: inputRef,
|
|
775
|
+
className: styles$5.input,
|
|
776
|
+
value: term,
|
|
777
|
+
onChange: (e2) => setTerm(e2.target.value),
|
|
778
|
+
onKeyDown: onFindKeyDown,
|
|
779
|
+
placeholder: t.find,
|
|
780
|
+
"aria-label": t.find,
|
|
781
|
+
autoFocus: true,
|
|
782
|
+
spellCheck: false
|
|
783
|
+
}
|
|
784
|
+
)
|
|
785
|
+
] }),
|
|
786
|
+
/* @__PURE__ */ jsx(
|
|
787
|
+
"button",
|
|
788
|
+
{
|
|
789
|
+
type: "button",
|
|
790
|
+
className: toggleClass(state.caseSensitive),
|
|
791
|
+
title: t.caseSensitive,
|
|
792
|
+
"aria-label": t.caseSensitive,
|
|
793
|
+
"aria-pressed": state.caseSensitive,
|
|
794
|
+
onMouseDown: keepFocus,
|
|
795
|
+
onClick: () => toggle2("caseSensitive", !state.caseSensitive),
|
|
796
|
+
children: "Aa"
|
|
797
|
+
}
|
|
798
|
+
),
|
|
799
|
+
/* @__PURE__ */ jsx(
|
|
800
|
+
"button",
|
|
801
|
+
{
|
|
802
|
+
type: "button",
|
|
803
|
+
className: toggleClass(state.wholeWord),
|
|
804
|
+
title: t.wholeWord,
|
|
805
|
+
"aria-label": t.wholeWord,
|
|
806
|
+
"aria-pressed": state.wholeWord,
|
|
807
|
+
onMouseDown: keepFocus,
|
|
808
|
+
onClick: () => toggle2("wholeWord", !state.wholeWord),
|
|
809
|
+
children: "ab"
|
|
810
|
+
}
|
|
811
|
+
),
|
|
812
|
+
/* @__PURE__ */ jsx(
|
|
813
|
+
"button",
|
|
814
|
+
{
|
|
815
|
+
type: "button",
|
|
816
|
+
className: toggleClass(state.useRegex),
|
|
817
|
+
title: t.useRegex,
|
|
818
|
+
"aria-label": t.useRegex,
|
|
819
|
+
"aria-pressed": state.useRegex,
|
|
820
|
+
onMouseDown: keepFocus,
|
|
821
|
+
onClick: () => toggle2("useRegex", !state.useRegex),
|
|
822
|
+
children: ".*"
|
|
823
|
+
}
|
|
824
|
+
),
|
|
825
|
+
/* @__PURE__ */ jsx("span", { className: styles$5.spacer }),
|
|
826
|
+
/* @__PURE__ */ jsx(
|
|
827
|
+
"span",
|
|
828
|
+
{
|
|
829
|
+
className: `${styles$5.counter}${invalidPattern ? ` ${styles$5.counterInvalid}` : ""}`,
|
|
830
|
+
"aria-live": "polite",
|
|
831
|
+
title: invalidPattern ? t.invalidRegex : void 0,
|
|
832
|
+
children: invalidPattern ? t.invalidRegex : counter2
|
|
833
|
+
}
|
|
834
|
+
),
|
|
835
|
+
/* @__PURE__ */ jsx(
|
|
836
|
+
"button",
|
|
837
|
+
{
|
|
838
|
+
type: "button",
|
|
839
|
+
className: styles$5.btn,
|
|
840
|
+
title: t.previous,
|
|
841
|
+
"aria-label": t.previous,
|
|
842
|
+
disabled: state.total === 0,
|
|
843
|
+
onMouseDown: keepFocus,
|
|
844
|
+
onClick: () => runAction(() => editor.commands.goToPreviousResult()),
|
|
845
|
+
children: /* @__PURE__ */ jsx(ChevronUpIcon, { size: 16 })
|
|
846
|
+
}
|
|
847
|
+
),
|
|
848
|
+
/* @__PURE__ */ jsx(
|
|
849
|
+
"button",
|
|
850
|
+
{
|
|
851
|
+
type: "button",
|
|
852
|
+
className: styles$5.btn,
|
|
853
|
+
title: t.next,
|
|
854
|
+
"aria-label": t.next,
|
|
855
|
+
disabled: state.total === 0,
|
|
856
|
+
onMouseDown: keepFocus,
|
|
857
|
+
onClick: () => runAction(() => editor.commands.goToNextResult()),
|
|
858
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, { size: 16 })
|
|
859
|
+
}
|
|
860
|
+
),
|
|
861
|
+
/* @__PURE__ */ jsx(
|
|
862
|
+
"button",
|
|
863
|
+
{
|
|
864
|
+
type: "button",
|
|
865
|
+
className: `${styles$5.btn} ${styles$5.closeBtn}`,
|
|
866
|
+
title: t.close,
|
|
867
|
+
"aria-label": t.close,
|
|
868
|
+
onClick: onClose,
|
|
869
|
+
children: /* @__PURE__ */ jsx(XIcon, { size: 16 })
|
|
870
|
+
}
|
|
871
|
+
)
|
|
872
|
+
] }),
|
|
873
|
+
editor.isEditable ? /* @__PURE__ */ jsxs("div", { className: styles$5.row, children: [
|
|
874
|
+
/* @__PURE__ */ jsx("span", { className: styles$5.field, children: /* @__PURE__ */ jsx(
|
|
875
|
+
"input",
|
|
876
|
+
{
|
|
877
|
+
className: styles$5.input,
|
|
878
|
+
value: replaceTerm,
|
|
879
|
+
onChange: (e2) => setReplaceTerm(e2.target.value),
|
|
880
|
+
onKeyDown: onReplaceKeyDown,
|
|
881
|
+
placeholder: t.replace,
|
|
882
|
+
"aria-label": t.replace,
|
|
883
|
+
spellCheck: false
|
|
884
|
+
}
|
|
885
|
+
) }),
|
|
886
|
+
/* @__PURE__ */ jsx("span", { className: styles$5.spacer }),
|
|
887
|
+
/* @__PURE__ */ jsx(
|
|
888
|
+
"button",
|
|
889
|
+
{
|
|
890
|
+
type: "button",
|
|
891
|
+
className: `${styles$5.btn} ${styles$5.textBtn}`,
|
|
892
|
+
disabled: state.total === 0,
|
|
893
|
+
onMouseDown: keepFocus,
|
|
894
|
+
onClick: () => runAction(() => editor.commands.replace()),
|
|
895
|
+
children: t.replaceOne
|
|
896
|
+
}
|
|
897
|
+
),
|
|
898
|
+
/* @__PURE__ */ jsx(
|
|
899
|
+
"button",
|
|
900
|
+
{
|
|
901
|
+
type: "button",
|
|
902
|
+
className: `${styles$5.btn} ${styles$5.textBtn}`,
|
|
903
|
+
disabled: state.total === 0,
|
|
904
|
+
onMouseDown: keepFocus,
|
|
905
|
+
onClick: () => runAction(() => editor.commands.replaceAll()),
|
|
906
|
+
children: t.replaceAll
|
|
907
|
+
}
|
|
908
|
+
)
|
|
909
|
+
] }) : /* @__PURE__ */ jsx("div", { className: styles$5.row, children: /* @__PURE__ */ jsx("span", { className: styles$5.readOnly, children: t.readOnly }) })
|
|
910
|
+
]
|
|
911
|
+
}
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
function findPlaceholderPos(doc) {
|
|
915
|
+
let found = null;
|
|
916
|
+
doc.descendants((node, pos) => {
|
|
917
|
+
if (node.type.name === "importPlaceholder") {
|
|
918
|
+
found = pos;
|
|
919
|
+
return false;
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
return found;
|
|
923
|
+
}
|
|
924
|
+
const ImportPlaceholder = Node$1.create({
|
|
925
|
+
name: "importPlaceholder",
|
|
926
|
+
group: "block",
|
|
927
|
+
atom: true,
|
|
928
|
+
selectable: false,
|
|
929
|
+
draggable: false,
|
|
930
|
+
addAttributes() {
|
|
931
|
+
return {
|
|
932
|
+
label: {
|
|
933
|
+
default: "",
|
|
934
|
+
parseHTML: (el) => el.getAttribute("data-label") ?? "",
|
|
935
|
+
renderHTML: (attrs) => attrs.label ? { "data-label": attrs.label } : {}
|
|
936
|
+
}
|
|
937
|
+
};
|
|
938
|
+
},
|
|
939
|
+
parseHTML() {
|
|
940
|
+
return [{ tag: 'div[data-type="import-placeholder"]' }];
|
|
941
|
+
},
|
|
942
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
943
|
+
const label = String(node.attrs.label ?? "");
|
|
944
|
+
return [
|
|
945
|
+
"div",
|
|
946
|
+
{
|
|
947
|
+
...HTMLAttributes,
|
|
948
|
+
"data-type": "import-placeholder",
|
|
949
|
+
class: "tmr-import-placeholder",
|
|
950
|
+
contenteditable: "false",
|
|
951
|
+
"aria-live": "polite",
|
|
952
|
+
"aria-busy": "true"
|
|
953
|
+
},
|
|
954
|
+
["span", { class: "tmr-import-placeholder-spin", "aria-hidden": "true" }],
|
|
955
|
+
["span", { class: "tmr-import-placeholder-label" }, label]
|
|
956
|
+
];
|
|
957
|
+
},
|
|
958
|
+
renderMarkdown() {
|
|
959
|
+
return "";
|
|
960
|
+
},
|
|
961
|
+
addCommands() {
|
|
962
|
+
return {
|
|
963
|
+
insertImportPlaceholder: (label) => ({ chain }) => chain().focus().insertContent({
|
|
964
|
+
type: this.name,
|
|
965
|
+
attrs: { label }
|
|
966
|
+
}).command(({ tr }) => {
|
|
967
|
+
tr.setMeta("addToHistory", false);
|
|
968
|
+
tr.setMeta("preventUpdate", true);
|
|
969
|
+
return true;
|
|
970
|
+
}).run(),
|
|
971
|
+
updateImportPlaceholder: (label) => ({ tr, dispatch, state }) => {
|
|
972
|
+
const pos = findPlaceholderPos(state.doc);
|
|
973
|
+
if (pos == null) return false;
|
|
974
|
+
if (dispatch) {
|
|
975
|
+
dispatch(
|
|
976
|
+
tr.setNodeMarkup(pos, void 0, { label }).setMeta("addToHistory", false).setMeta("preventUpdate", true)
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
return true;
|
|
980
|
+
},
|
|
981
|
+
removeImportPlaceholder: () => ({ tr, dispatch, state }) => {
|
|
982
|
+
const pos = findPlaceholderPos(state.doc);
|
|
983
|
+
if (pos == null) return false;
|
|
984
|
+
const node = state.doc.nodeAt(pos);
|
|
985
|
+
if (!node) return false;
|
|
986
|
+
if (dispatch) {
|
|
987
|
+
dispatch(
|
|
988
|
+
tr.delete(pos, pos + node.nodeSize).setMeta("addToHistory", false).setMeta("preventUpdate", true)
|
|
989
|
+
);
|
|
990
|
+
}
|
|
991
|
+
return true;
|
|
992
|
+
}
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
const MD_FILE_RE$1 = /\.(md|markdown)$/i;
|
|
997
|
+
const MD_MIME_TYPES = ["text/markdown", "text/x-markdown", ""];
|
|
998
|
+
async function insertMarkdownFiles(editor, files, pos) {
|
|
999
|
+
const mdFiles = files.filter((f2) => MD_FILE_RE$1.test(f2.name));
|
|
1000
|
+
if (mdFiles.length === 0) return;
|
|
1001
|
+
const markdown = editor.markdown;
|
|
1002
|
+
if (!markdown) return;
|
|
1003
|
+
const texts = await Promise.all(mdFiles.map((f2) => f2.text()));
|
|
1004
|
+
const json = markdown.parse(texts.join("\n\n"));
|
|
1005
|
+
if (pos != null) {
|
|
1006
|
+
editor.chain().focus().insertContentAt(pos, json).run();
|
|
1007
|
+
} else {
|
|
1008
|
+
editor.chain().focus().insertContent(json).run();
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
const MarkdownFileDrop = Extension.create({
|
|
1012
|
+
name: "markdownFileDrop",
|
|
1013
|
+
addProseMirrorPlugins() {
|
|
1014
|
+
const { editor } = this;
|
|
1015
|
+
return [
|
|
1016
|
+
FileHandlePlugin({
|
|
1017
|
+
key: new PluginKey("markdownFileDrop"),
|
|
1018
|
+
editor,
|
|
1019
|
+
allowedMimeTypes: MD_MIME_TYPES,
|
|
1020
|
+
onDrop: (ed, files, pos) => {
|
|
1021
|
+
insertMarkdownFiles(ed, files, pos).catch((err) => {
|
|
1022
|
+
console.error("markdown file drop failed:", err);
|
|
1023
|
+
});
|
|
1024
|
+
},
|
|
1025
|
+
onPaste: (ed, files) => {
|
|
1026
|
+
insertMarkdownFiles(ed, files).catch((err) => {
|
|
1027
|
+
console.error("markdown file paste failed:", err);
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
})
|
|
1031
|
+
];
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
const PENDING_ANCHOR_META = "tmr:pendingAnchor";
|
|
1035
|
+
const pendingAnchorPluginKey = new PluginKey(
|
|
1036
|
+
"tmrPendingAnchor"
|
|
1037
|
+
);
|
|
1038
|
+
const PENDING_ANCHOR_CLASS = "tmr-pending-anchor";
|
|
1039
|
+
const pendingAnchorExtension = Extension.create({
|
|
1040
|
+
name: "pendingAnchor",
|
|
1041
|
+
addProseMirrorPlugins() {
|
|
1042
|
+
return [
|
|
1043
|
+
new Plugin({
|
|
1044
|
+
key: pendingAnchorPluginKey,
|
|
1045
|
+
state: {
|
|
1046
|
+
init: () => ({ decorations: DecorationSet.empty }),
|
|
1047
|
+
apply(tr, value) {
|
|
1048
|
+
const next = tr.getMeta(PENDING_ANCHOR_META);
|
|
1049
|
+
if (next) return { decorations: buildDecorations(tr.doc, next) };
|
|
1050
|
+
if (tr.docChanged) {
|
|
1051
|
+
return { decorations: value.decorations.map(tr.mapping, tr.doc) };
|
|
1052
|
+
}
|
|
1053
|
+
return value;
|
|
1054
|
+
}
|
|
1055
|
+
},
|
|
1056
|
+
props: {
|
|
1057
|
+
decorations(state) {
|
|
1058
|
+
var _a;
|
|
1059
|
+
return ((_a = pendingAnchorPluginKey.getState(state)) == null ? void 0 : _a.decorations) ?? null;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
})
|
|
1063
|
+
];
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1066
|
+
function setPendingAnchors(editor, anchors) {
|
|
1067
|
+
editor.view.dispatch(
|
|
1068
|
+
editor.state.tr.setMeta(PENDING_ANCHOR_META, anchors).setMeta(skipTrailingNodeMeta, true).setMeta("addToHistory", false)
|
|
1069
|
+
);
|
|
1070
|
+
}
|
|
1071
|
+
function buildDecorations(doc, anchors) {
|
|
1072
|
+
const bounds = [];
|
|
1073
|
+
doc.forEach((child, offset) => {
|
|
1074
|
+
bounds.push({ from: offset, to: offset + child.nodeSize });
|
|
1075
|
+
});
|
|
1076
|
+
const decorations = [];
|
|
1077
|
+
for (const anchor of anchors) {
|
|
1078
|
+
for (const range of anchor.ranges) {
|
|
1079
|
+
const from = Math.max(0, Math.min(range.from, range.to));
|
|
1080
|
+
const to = Math.min(doc.content.size, Math.max(range.from, range.to));
|
|
1081
|
+
if (from >= to) continue;
|
|
1082
|
+
for (const bound of bounds) {
|
|
1083
|
+
if (bound.to <= from || bound.from >= to) continue;
|
|
1084
|
+
const attrs = {
|
|
1085
|
+
class: PENDING_ANCHOR_CLASS,
|
|
1086
|
+
"data-pending-id": anchor.id
|
|
1087
|
+
};
|
|
1088
|
+
if (from <= bound.from && to >= bound.to) {
|
|
1089
|
+
decorations.push(Decoration.node(bound.from, bound.to, attrs));
|
|
1090
|
+
} else {
|
|
1091
|
+
decorations.push(
|
|
1092
|
+
Decoration.inline(Math.max(from, bound.from), Math.min(to, bound.to), attrs)
|
|
1093
|
+
);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
return decorations.length ? DecorationSet.create(doc, decorations) : DecorationSet.empty;
|
|
1099
|
+
}
|
|
1100
|
+
function selectionKind(selection) {
|
|
1101
|
+
if (selection instanceof CellSelection) return "cell";
|
|
1102
|
+
if (selection instanceof NodeSelection) return "node";
|
|
1103
|
+
if (selection instanceof TextSelection) return "text";
|
|
1104
|
+
return "text";
|
|
1105
|
+
}
|
|
1106
|
+
function looksLikeMarkdown(text) {
|
|
1107
|
+
return /^#{1,6}\s/m.test(text) || // 标题
|
|
1108
|
+
/\*\*[^*\n]+\*\*/.test(text) || // 加粗
|
|
1109
|
+
/(^|[^!])\[[^\]\n]+\]\([^)\n]+\)/.test(text) || // 链接
|
|
1110
|
+
/!\[[^\]\n]*\]\([^)\n]+\)/.test(text) || // 图片
|
|
1111
|
+
/^[-*+]\s+\S/m.test(text) || // 无序列表
|
|
1112
|
+
/^\d+\.\s+\S/m.test(text) || // 有序列表
|
|
1113
|
+
/^>\s/m.test(text) || // 引用
|
|
1114
|
+
/^```/m.test(text) || // 代码围栏
|
|
1115
|
+
/^\|.+\|\s*$/m.test(text) || // 表格行
|
|
1116
|
+
/^(-{3,}|\*{3,})\s*$/m.test(text) || // 分割线
|
|
1117
|
+
/<!--\s*[\[{][\s\S]*?"chartType"[\s\S]*?-->/.test(text);
|
|
1118
|
+
}
|
|
1119
|
+
const MarkdownPaste = Extension.create({
|
|
1120
|
+
name: "markdownPaste",
|
|
1121
|
+
addProseMirrorPlugins() {
|
|
1122
|
+
const { editor } = this;
|
|
1123
|
+
return [
|
|
1124
|
+
new Plugin({
|
|
1125
|
+
key: new PluginKey("markdownPaste"),
|
|
1126
|
+
props: {
|
|
1127
|
+
handlePaste(view, event) {
|
|
1128
|
+
const clipboard = event.clipboardData;
|
|
1129
|
+
if (!clipboard) return false;
|
|
1130
|
+
const text = clipboard.getData("text/plain");
|
|
1131
|
+
if (!text) return false;
|
|
1132
|
+
const input2 = view.input;
|
|
1133
|
+
if (input2 == null ? void 0 : input2.shiftKey) return false;
|
|
1134
|
+
if (view.state.selection.$from.parent.type.spec.code) return false;
|
|
1135
|
+
if (!looksLikeMarkdown(text)) return false;
|
|
1136
|
+
const markdown = editor.markdown;
|
|
1137
|
+
if (!markdown) return false;
|
|
1138
|
+
try {
|
|
1139
|
+
const json = markdown.parse(prepareChartMarkdown(text));
|
|
1140
|
+
editor.commands.insertContent(json);
|
|
1141
|
+
return true;
|
|
1142
|
+
} catch (err) {
|
|
1143
|
+
console.error("markdown paste parse failed:", err);
|
|
1144
|
+
return false;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
})
|
|
1149
|
+
];
|
|
1150
|
+
}
|
|
1151
|
+
});
|
|
668
1152
|
function tabLabel(chartType, title, index, fallback) {
|
|
669
1153
|
if (title == null ? void 0 : title.trim()) return title;
|
|
670
1154
|
return fallback(chartType, index);
|
|
@@ -787,154 +1271,6 @@ function createChart(options = {}) {
|
|
|
787
1271
|
}
|
|
788
1272
|
});
|
|
789
1273
|
}
|
|
790
|
-
function Svg({ size = "1em", children, ...rest }) {
|
|
791
|
-
return /* @__PURE__ */ jsx(
|
|
792
|
-
"svg",
|
|
793
|
-
{
|
|
794
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
795
|
-
width: size,
|
|
796
|
-
height: size,
|
|
797
|
-
viewBox: "0 0 24 24",
|
|
798
|
-
fill: "none",
|
|
799
|
-
stroke: "currentColor",
|
|
800
|
-
strokeWidth: 2,
|
|
801
|
-
strokeLinecap: "round",
|
|
802
|
-
strokeLinejoin: "round",
|
|
803
|
-
"aria-hidden": "true",
|
|
804
|
-
focusable: "false",
|
|
805
|
-
...rest,
|
|
806
|
-
children
|
|
807
|
-
}
|
|
808
|
-
);
|
|
809
|
-
}
|
|
810
|
-
const BoldIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
811
|
-
/* @__PURE__ */ jsx("path", { d: "M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" }),
|
|
812
|
-
/* @__PURE__ */ jsx("path", { d: "M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" })
|
|
813
|
-
] });
|
|
814
|
-
const ItalicIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
815
|
-
/* @__PURE__ */ jsx("line", { x1: "19", x2: "10", y1: "4", y2: "4" }),
|
|
816
|
-
/* @__PURE__ */ jsx("line", { x1: "14", x2: "5", y1: "20", y2: "20" }),
|
|
817
|
-
/* @__PURE__ */ jsx("line", { x1: "15", x2: "9", y1: "4", y2: "20" })
|
|
818
|
-
] });
|
|
819
|
-
const UnderlineIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
820
|
-
/* @__PURE__ */ jsx("path", { d: "M6 4v6a6 6 0 0 0 12 0V4" }),
|
|
821
|
-
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "20", y2: "20" })
|
|
822
|
-
] });
|
|
823
|
-
const StrikethroughIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
824
|
-
/* @__PURE__ */ jsx("path", { d: "M16 4H9a3 3 0 0 0-2.83 4" }),
|
|
825
|
-
/* @__PURE__ */ jsx("path", { d: "M14 12a4 4 0 0 1 0 8H6" }),
|
|
826
|
-
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "12", y2: "12" })
|
|
827
|
-
] });
|
|
828
|
-
const CodeIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
829
|
-
/* @__PURE__ */ jsx("polyline", { points: "16 18 22 12 16 6" }),
|
|
830
|
-
/* @__PURE__ */ jsx("polyline", { points: "8 6 2 12 8 18" })
|
|
831
|
-
] });
|
|
832
|
-
const LinkIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
833
|
-
/* @__PURE__ */ jsx("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
|
|
834
|
-
/* @__PURE__ */ jsx("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
|
|
835
|
-
] });
|
|
836
|
-
const ImageIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
837
|
-
/* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
|
|
838
|
-
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "2" }),
|
|
839
|
-
/* @__PURE__ */ jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
|
|
840
|
-
] });
|
|
841
|
-
const ImportIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
842
|
-
/* @__PURE__ */ jsx("path", { d: "M12 3v12" }),
|
|
843
|
-
/* @__PURE__ */ jsx("path", { d: "m8 11 4 4 4-4" }),
|
|
844
|
-
/* @__PURE__ */ jsx("path", { d: "M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4" })
|
|
845
|
-
] });
|
|
846
|
-
const ListUnorderedIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
847
|
-
/* @__PURE__ */ jsx("line", { x1: "8", x2: "21", y1: "6", y2: "6" }),
|
|
848
|
-
/* @__PURE__ */ jsx("line", { x1: "8", x2: "21", y1: "12", y2: "12" }),
|
|
849
|
-
/* @__PURE__ */ jsx("line", { x1: "8", x2: "21", y1: "18", y2: "18" }),
|
|
850
|
-
/* @__PURE__ */ jsx("line", { x1: "3", x2: "3.01", y1: "6", y2: "6" }),
|
|
851
|
-
/* @__PURE__ */ jsx("line", { x1: "3", x2: "3.01", y1: "12", y2: "12" }),
|
|
852
|
-
/* @__PURE__ */ jsx("line", { x1: "3", x2: "3.01", y1: "18", y2: "18" })
|
|
853
|
-
] });
|
|
854
|
-
const ListOrderedIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
855
|
-
/* @__PURE__ */ jsx("line", { x1: "10", x2: "21", y1: "6", y2: "6" }),
|
|
856
|
-
/* @__PURE__ */ jsx("line", { x1: "10", x2: "21", y1: "12", y2: "12" }),
|
|
857
|
-
/* @__PURE__ */ jsx("line", { x1: "10", x2: "21", y1: "18", y2: "18" }),
|
|
858
|
-
/* @__PURE__ */ jsx("path", { d: "M4 6h1v4" }),
|
|
859
|
-
/* @__PURE__ */ jsx("path", { d: "M4 10h2" }),
|
|
860
|
-
/* @__PURE__ */ jsx("path", { d: "M6 18H4c0-1 2-2 2-3s-1-1.5-2-1" })
|
|
861
|
-
] });
|
|
862
|
-
const ListChecksIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
863
|
-
/* @__PURE__ */ jsx("path", { d: "m3 17 2 2 4-4" }),
|
|
864
|
-
/* @__PURE__ */ jsx("path", { d: "m3 7 2 2 4-4" }),
|
|
865
|
-
/* @__PURE__ */ jsx("path", { d: "M13 6h8" }),
|
|
866
|
-
/* @__PURE__ */ jsx("path", { d: "M13 12h8" }),
|
|
867
|
-
/* @__PURE__ */ jsx("path", { d: "M13 18h8" })
|
|
868
|
-
] });
|
|
869
|
-
const UndoIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
870
|
-
/* @__PURE__ */ jsx("path", { d: "M9 14 4 9l5-5" }),
|
|
871
|
-
/* @__PURE__ */ jsx("path", { d: "M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5 5.5 5.5 0 0 1-5.5 5.5H11" })
|
|
872
|
-
] });
|
|
873
|
-
const RedoIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
874
|
-
/* @__PURE__ */ jsx("path", { d: "m15 14 5-5-5-5" }),
|
|
875
|
-
/* @__PURE__ */ jsx("path", { d: "M20 9H9.5A5.5 5.5 0 0 0 4 14.5 5.5 5.5 0 0 0 9.5 20H13" })
|
|
876
|
-
] });
|
|
877
|
-
const ChevronDownIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) });
|
|
878
|
-
const CheckIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
|
|
879
|
-
const TrashIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
880
|
-
/* @__PURE__ */ jsx("path", { d: "M3 6h18" }),
|
|
881
|
-
/* @__PURE__ */ jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
|
|
882
|
-
/* @__PURE__ */ jsx("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }),
|
|
883
|
-
/* @__PURE__ */ jsx("line", { x1: "10", x2: "10", y1: "11", y2: "17" }),
|
|
884
|
-
/* @__PURE__ */ jsx("line", { x1: "14", x2: "14", y1: "11", y2: "17" })
|
|
885
|
-
] });
|
|
886
|
-
const LockIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
887
|
-
/* @__PURE__ */ jsx("rect", { width: "18", height: "11", x: "3", y: "11", rx: "2", ry: "2" }),
|
|
888
|
-
/* @__PURE__ */ jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
|
|
889
|
-
] });
|
|
890
|
-
const MenuIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
891
|
-
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "12", y2: "12" }),
|
|
892
|
-
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "6", y2: "6" }),
|
|
893
|
-
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "18", y2: "18" })
|
|
894
|
-
] });
|
|
895
|
-
const ColumnBeforeIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
896
|
-
/* @__PURE__ */ jsx("rect", { x: "10", y: "4", width: "11", height: "16", rx: "1" }),
|
|
897
|
-
/* @__PURE__ */ jsx("path", { d: "M14 4v16" }),
|
|
898
|
-
/* @__PURE__ */ jsx("path", { d: "M5 9v6" }),
|
|
899
|
-
/* @__PURE__ */ jsx("path", { d: "M2 12h6" })
|
|
900
|
-
] });
|
|
901
|
-
const ColumnAfterIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
902
|
-
/* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "11", height: "16", rx: "1" }),
|
|
903
|
-
/* @__PURE__ */ jsx("path", { d: "M10 4v16" }),
|
|
904
|
-
/* @__PURE__ */ jsx("path", { d: "M19 9v6" }),
|
|
905
|
-
/* @__PURE__ */ jsx("path", { d: "M16 12h6" })
|
|
906
|
-
] });
|
|
907
|
-
const ColumnDeleteIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
908
|
-
/* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "1" }),
|
|
909
|
-
/* @__PURE__ */ jsx("path", { d: "M12 4v16" }),
|
|
910
|
-
/* @__PURE__ */ jsx("path", { d: "m8 9 8 6" }),
|
|
911
|
-
/* @__PURE__ */ jsx("path", { d: "m16 9-8 6" })
|
|
912
|
-
] });
|
|
913
|
-
const RowBeforeIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
914
|
-
/* @__PURE__ */ jsx("rect", { x: "4", y: "10", width: "16", height: "11", rx: "1" }),
|
|
915
|
-
/* @__PURE__ */ jsx("path", { d: "M4 14h16" }),
|
|
916
|
-
/* @__PURE__ */ jsx("path", { d: "M9 5h6" }),
|
|
917
|
-
/* @__PURE__ */ jsx("path", { d: "M12 2v6" })
|
|
918
|
-
] });
|
|
919
|
-
const RowAfterIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
920
|
-
/* @__PURE__ */ jsx("rect", { x: "4", y: "3", width: "16", height: "11", rx: "1" }),
|
|
921
|
-
/* @__PURE__ */ jsx("path", { d: "M4 10h16" }),
|
|
922
|
-
/* @__PURE__ */ jsx("path", { d: "M9 19h6" }),
|
|
923
|
-
/* @__PURE__ */ jsx("path", { d: "M12 16v6" })
|
|
924
|
-
] });
|
|
925
|
-
const RowDeleteIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
926
|
-
/* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "1" }),
|
|
927
|
-
/* @__PURE__ */ jsx("path", { d: "M4 12h16" }),
|
|
928
|
-
/* @__PURE__ */ jsx("path", { d: "m9 8 6 8" }),
|
|
929
|
-
/* @__PURE__ */ jsx("path", { d: "m15 8-6 8" })
|
|
930
|
-
] });
|
|
931
|
-
const TableDeleteIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
|
|
932
|
-
/* @__PURE__ */ jsx("rect", { x: "3", y: "5", width: "18", height: "14", rx: "1" }),
|
|
933
|
-
/* @__PURE__ */ jsx("path", { d: "M3 9h18" }),
|
|
934
|
-
/* @__PURE__ */ jsx("path", { d: "M9 5v14" }),
|
|
935
|
-
/* @__PURE__ */ jsx("path", { d: "M15 5v14" }),
|
|
936
|
-
/* @__PURE__ */ jsx("path", { d: "m7 2 10 20" })
|
|
937
|
-
] });
|
|
938
1274
|
const wrapper = "_wrapper_5i2vi_2";
|
|
939
1275
|
const header$1 = "_header_5i2vi_18";
|
|
940
1276
|
const langTrigger = "_langTrigger_5i2vi_28";
|
|
@@ -1110,6 +1446,17 @@ const ImageWithConfirmDelete = Image.extend({
|
|
|
1110
1446
|
};
|
|
1111
1447
|
}
|
|
1112
1448
|
});
|
|
1449
|
+
const DEFAULT_FIND_BAR_OFFSET = { top: 4, right: 4 };
|
|
1450
|
+
function findBarOffsetStyle(offset) {
|
|
1451
|
+
const px = (v) => typeof v === "number" ? `${v}px` : v;
|
|
1452
|
+
return {
|
|
1453
|
+
position: "absolute",
|
|
1454
|
+
top: px(offset.top),
|
|
1455
|
+
right: px(offset.right),
|
|
1456
|
+
bottom: px(offset.bottom),
|
|
1457
|
+
left: px(offset.left)
|
|
1458
|
+
};
|
|
1459
|
+
}
|
|
1113
1460
|
const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
|
|
1114
1461
|
initialMarkdown = "",
|
|
1115
1462
|
editable = true,
|
|
@@ -1131,11 +1478,19 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
|
|
|
1131
1478
|
commentInteractive = true,
|
|
1132
1479
|
pendingAnchors,
|
|
1133
1480
|
onAnchorClick,
|
|
1134
|
-
onSelectionChange
|
|
1481
|
+
onSelectionChange,
|
|
1482
|
+
findReplace = true,
|
|
1483
|
+
findBar = findReplace,
|
|
1484
|
+
findBarContainer,
|
|
1485
|
+
findBarOffset = DEFAULT_FIND_BAR_OFFSET,
|
|
1486
|
+
findShortcut = true,
|
|
1487
|
+
findLabels
|
|
1135
1488
|
}, ref) {
|
|
1136
1489
|
const preparedInitial = prepareChartMarkdown(
|
|
1137
1490
|
enrichMarkdownCitations(initialMarkdown, sources ?? [])
|
|
1138
1491
|
);
|
|
1492
|
+
const [findOpen, setFindOpen] = useState(false);
|
|
1493
|
+
const findInputRef = useRef(null);
|
|
1139
1494
|
const editor = useEditor({
|
|
1140
1495
|
extensions: [
|
|
1141
1496
|
...baseExtensions,
|
|
@@ -1151,6 +1506,12 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
|
|
|
1151
1506
|
}),
|
|
1152
1507
|
Markdown,
|
|
1153
1508
|
pendingAnchorExtension,
|
|
1509
|
+
// 官方查找替换:只出命令 / storage / 装饰,UI 自绘(见 FindReplaceBar)。
|
|
1510
|
+
// - injectCSS 关掉:它默认会往页面插一个 <style>,绕开宿主的 --tmr-* 主题与 style.css,
|
|
1511
|
+
// 命中样式改由 src/styles/find.css 承担。
|
|
1512
|
+
// - searchDebounceMs 关掉:官方防抖走 setTimeout,抛错会落在异步回调里兜不住;
|
|
1513
|
+
// 防抖改由浮动条自己做(见 findReplace.ts)。
|
|
1514
|
+
...findReplace ? [FindAndReplace.configure({ injectCSS: false, searchDebounceMs: 0 })] : [],
|
|
1154
1515
|
TableOfContents.configure({
|
|
1155
1516
|
getId: makeTocGetId(),
|
|
1156
1517
|
onUpdate: (anchors) => {
|
|
@@ -1170,7 +1531,7 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
|
|
|
1170
1531
|
immediatelyRender: false,
|
|
1171
1532
|
editorProps: {
|
|
1172
1533
|
attributes: {
|
|
1173
|
-
class: styles$
|
|
1534
|
+
class: styles$6.editorContent,
|
|
1174
1535
|
"data-placeholder": placeholder ?? ""
|
|
1175
1536
|
}
|
|
1176
1537
|
}
|
|
@@ -1182,6 +1543,34 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
|
|
|
1182
1543
|
useEffect(() => {
|
|
1183
1544
|
editor == null ? void 0 : editor.setEditable(editable);
|
|
1184
1545
|
}, [editor, editable]);
|
|
1546
|
+
const closeFind = useCallback(() => {
|
|
1547
|
+
setFindOpen(false);
|
|
1548
|
+
editor == null ? void 0 : editor.commands.focus();
|
|
1549
|
+
}, [editor]);
|
|
1550
|
+
useEffect(() => {
|
|
1551
|
+
if (!editor || !findReplace || !findBar || !findShortcut) return;
|
|
1552
|
+
const onKeyDown = (event) => {
|
|
1553
|
+
if (!(event.metaKey || event.ctrlKey) || event.altKey || event.shiftKey) {
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
if (event.key !== "f" && event.key !== "F") return;
|
|
1557
|
+
const active2 = document.activeElement;
|
|
1558
|
+
const inEditor = !!active2 && editor.view.dom.contains(active2);
|
|
1559
|
+
const nothingFocused = active2 === null || active2 === document.body;
|
|
1560
|
+
const soleEditor = document.querySelectorAll(".ProseMirror").length <= 1;
|
|
1561
|
+
if (!inEditor && !editor.isFocused && !(nothingFocused && soleEditor)) {
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
event.preventDefault();
|
|
1565
|
+
setFindOpen(true);
|
|
1566
|
+
requestAnimationFrame(() => {
|
|
1567
|
+
var _a;
|
|
1568
|
+
return (_a = findInputRef.current) == null ? void 0 : _a.select();
|
|
1569
|
+
});
|
|
1570
|
+
};
|
|
1571
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
1572
|
+
return () => document.removeEventListener("keydown", onKeyDown, true);
|
|
1573
|
+
}, [editor, findReplace, findBar, findShortcut]);
|
|
1185
1574
|
const commentsSignatureRef = useRef("");
|
|
1186
1575
|
useEffect(() => {
|
|
1187
1576
|
if (!editor || !editable) return;
|
|
@@ -1288,17 +1677,41 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
|
|
|
1288
1677
|
getEditor: () => editor ?? null,
|
|
1289
1678
|
focusComment: (commentId) => editor ? focusComment(editor, commentId) : false,
|
|
1290
1679
|
nextComment: (dir) => editor ? nextComment(editor, dir ?? "next") : null,
|
|
1291
|
-
getCommentIds: () => editor ? collectCommentIds(editor) : []
|
|
1680
|
+
getCommentIds: () => editor ? collectCommentIds(editor) : [],
|
|
1681
|
+
openFind: () => setFindOpen(true),
|
|
1682
|
+
closeFind
|
|
1292
1683
|
}),
|
|
1293
|
-
[editor]
|
|
1684
|
+
[editor, closeFind]
|
|
1294
1685
|
);
|
|
1295
|
-
|
|
1296
|
-
|
|
1686
|
+
const findBarTarget = typeof findBarContainer === "function" ? findBarContainer() : findBarContainer ?? null;
|
|
1687
|
+
useEffect(() => {
|
|
1688
|
+
if (!findBarTarget) return;
|
|
1689
|
+
if (getComputedStyle(findBarTarget).position === "static") {
|
|
1690
|
+
findBarTarget.style.position = "relative";
|
|
1691
|
+
}
|
|
1692
|
+
}, [findBarTarget]);
|
|
1693
|
+
const findBarNode = editor && findBar && findOpen ? /* @__PURE__ */ jsx(
|
|
1694
|
+
FindReplaceBar,
|
|
1297
1695
|
{
|
|
1298
1696
|
editor,
|
|
1299
|
-
|
|
1697
|
+
labels: findLabels,
|
|
1698
|
+
onClose: closeFind,
|
|
1699
|
+
inputRef: findInputRef,
|
|
1700
|
+
className: styles$6.findBar,
|
|
1701
|
+
style: findBarOffsetStyle(findBarOffset)
|
|
1300
1702
|
}
|
|
1301
|
-
);
|
|
1703
|
+
) : null;
|
|
1704
|
+
return /* @__PURE__ */ jsxs("div", { className: styles$6.editorHost, children: [
|
|
1705
|
+
findBarNode && !findBarTarget ? /* @__PURE__ */ jsx("div", { className: styles$6.findBarAnchor, children: findBarNode }) : null,
|
|
1706
|
+
findBarNode && findBarTarget ? createPortal(findBarNode, findBarTarget) : null,
|
|
1707
|
+
/* @__PURE__ */ jsx(
|
|
1708
|
+
EditorContent,
|
|
1709
|
+
{
|
|
1710
|
+
editor,
|
|
1711
|
+
className: className ? `${styles$6.editorScroll} ${className}` : styles$6.editorScroll
|
|
1712
|
+
}
|
|
1713
|
+
)
|
|
1714
|
+
] });
|
|
1302
1715
|
});
|
|
1303
1716
|
function MarkdownPreview({
|
|
1304
1717
|
markdown,
|
|
@@ -1331,7 +1744,7 @@ function MarkdownPreview({
|
|
|
1331
1744
|
editable: false,
|
|
1332
1745
|
immediatelyRender: false,
|
|
1333
1746
|
editorProps: {
|
|
1334
|
-
attributes: { class: styles$
|
|
1747
|
+
attributes: { class: styles$6.editorContent }
|
|
1335
1748
|
}
|
|
1336
1749
|
},
|
|
1337
1750
|
[extensions]
|
|
@@ -1344,7 +1757,7 @@ function MarkdownPreview({
|
|
|
1344
1757
|
EditorContent,
|
|
1345
1758
|
{
|
|
1346
1759
|
editor,
|
|
1347
|
-
className: className ?? styles$
|
|
1760
|
+
className: className ?? styles$6.editorScroll
|
|
1348
1761
|
}
|
|
1349
1762
|
);
|
|
1350
1763
|
}
|
|
@@ -1422,8 +1835,8 @@ function getTableSelectionInfo(state) {
|
|
|
1422
1835
|
const rowCount = Math.max(1, rect.bottom - rect.top);
|
|
1423
1836
|
const colCount = Math.max(1, rect.right - rect.left);
|
|
1424
1837
|
let includesHeaderRow = false;
|
|
1425
|
-
for (let
|
|
1426
|
-
if (rowIsHeader(rect.map, rect.table,
|
|
1838
|
+
for (let row2 = rect.top; row2 < rect.bottom; row2++) {
|
|
1839
|
+
if (rowIsHeader(rect.map, rect.table, row2)) {
|
|
1427
1840
|
includesHeaderRow = true;
|
|
1428
1841
|
break;
|
|
1429
1842
|
}
|
|
@@ -1804,7 +2217,7 @@ function MathEditorPopover({
|
|
|
1804
2217
|
e2.preventDefault();
|
|
1805
2218
|
submit();
|
|
1806
2219
|
};
|
|
1807
|
-
const
|
|
2220
|
+
const field2 = isBlock ? /* @__PURE__ */ jsx(
|
|
1808
2221
|
"textarea",
|
|
1809
2222
|
{
|
|
1810
2223
|
ref: inputRef,
|
|
@@ -1861,7 +2274,7 @@ function MathEditorPopover({
|
|
|
1861
2274
|
id: showHint ? void 0 : titleId,
|
|
1862
2275
|
className: isBlock ? `${styles$3.mathField} ${styles$3.mathFieldBlock}` : styles$3.mathField,
|
|
1863
2276
|
children: [
|
|
1864
|
-
|
|
2277
|
+
field2,
|
|
1865
2278
|
/* @__PURE__ */ jsxs(
|
|
1866
2279
|
"button",
|
|
1867
2280
|
{
|
|
@@ -2039,18 +2452,18 @@ function TableInsertItem({
|
|
|
2039
2452
|
onMouseLeave: resetHover,
|
|
2040
2453
|
children: Array.from({ length: TABLE_PICKER_ROWS * TABLE_PICKER_COLS }, (_, i) => {
|
|
2041
2454
|
const col = i % TABLE_PICKER_COLS + 1;
|
|
2042
|
-
const
|
|
2043
|
-
const active2 = hover.cols > 0 && col <= hover.cols &&
|
|
2455
|
+
const row2 = Math.floor(i / TABLE_PICKER_COLS) + 1;
|
|
2456
|
+
const active2 = hover.cols > 0 && col <= hover.cols && row2 <= hover.rows;
|
|
2044
2457
|
return /* @__PURE__ */ jsx(
|
|
2045
2458
|
"button",
|
|
2046
2459
|
{
|
|
2047
2460
|
type: "button",
|
|
2048
|
-
"aria-label": labels.tableSizeSelected(col,
|
|
2461
|
+
"aria-label": labels.tableSizeSelected(col, row2),
|
|
2049
2462
|
className: `${styles$3.tableSizeCell} ${active2 ? styles$3.tableSizeCellActive : ""}`,
|
|
2050
2463
|
onMouseDown: (e2) => e2.preventDefault(),
|
|
2051
|
-
onMouseEnter: () => setHover({ cols: col, rows:
|
|
2464
|
+
onMouseEnter: () => setHover({ cols: col, rows: row2 }),
|
|
2052
2465
|
onClick: () => {
|
|
2053
|
-
onInsert(
|
|
2466
|
+
onInsert(row2, col);
|
|
2054
2467
|
setOpen(false);
|
|
2055
2468
|
resetHover();
|
|
2056
2469
|
closeMenu();
|
|
@@ -2072,7 +2485,7 @@ function TableInsertItem({
|
|
|
2072
2485
|
function ColorPopover({
|
|
2073
2486
|
title,
|
|
2074
2487
|
glyph,
|
|
2075
|
-
bar,
|
|
2488
|
+
bar: bar2,
|
|
2076
2489
|
value,
|
|
2077
2490
|
onPick,
|
|
2078
2491
|
paletteLabels
|
|
@@ -2089,7 +2502,7 @@ function ColorPopover({
|
|
|
2089
2502
|
onMouseDown: (e2) => e2.preventDefault(),
|
|
2090
2503
|
children: /* @__PURE__ */ jsxs("span", { className: styles$3.colorIcon, children: [
|
|
2091
2504
|
/* @__PURE__ */ jsx("span", { className: styles$3.colorIconGlyph, children: glyph }),
|
|
2092
|
-
/* @__PURE__ */ jsx("span", { className: styles$3.colorIconBar, style: { background:
|
|
2505
|
+
/* @__PURE__ */ jsx("span", { className: styles$3.colorIconBar, style: { background: bar2 } })
|
|
2093
2506
|
] })
|
|
2094
2507
|
}
|
|
2095
2508
|
) }),
|
|
@@ -2306,11 +2719,11 @@ function EditorToolbar({
|
|
|
2306
2719
|
importMenuItems
|
|
2307
2720
|
});
|
|
2308
2721
|
const pickImport = (accept) => {
|
|
2309
|
-
const
|
|
2310
|
-
if (!
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2722
|
+
const input2 = importInputRef.current;
|
|
2723
|
+
if (!input2) return;
|
|
2724
|
+
input2.accept = accept;
|
|
2725
|
+
input2.value = "";
|
|
2726
|
+
input2.click();
|
|
2314
2727
|
};
|
|
2315
2728
|
const importTitle = importing ? t.importDocumentBusy : t.importDocumentHint;
|
|
2316
2729
|
const applyTextColor = (color) => {
|
|
@@ -3226,6 +3639,7 @@ export {
|
|
|
3226
3639
|
C as ChartMount,
|
|
3227
3640
|
CheckIcon,
|
|
3228
3641
|
ChevronDownIcon,
|
|
3642
|
+
ChevronUpIcon,
|
|
3229
3643
|
a as CitationInteractive,
|
|
3230
3644
|
CitationRef,
|
|
3231
3645
|
CodeBlockView,
|
|
@@ -3237,6 +3651,9 @@ export {
|
|
|
3237
3651
|
CommentMark,
|
|
3238
3652
|
CommentPopover,
|
|
3239
3653
|
EditorToolbar,
|
|
3654
|
+
FIND_DEBOUNCE_MS,
|
|
3655
|
+
default2 as FindAndReplace,
|
|
3656
|
+
FindReplaceBar,
|
|
3240
3657
|
ImageIcon,
|
|
3241
3658
|
ImportIcon,
|
|
3242
3659
|
ImportPlaceholder,
|
|
@@ -3259,12 +3676,14 @@ export {
|
|
|
3259
3676
|
RowAfterIcon,
|
|
3260
3677
|
RowBeforeIcon,
|
|
3261
3678
|
RowDeleteIcon,
|
|
3679
|
+
SearchIcon,
|
|
3262
3680
|
StrikethroughIcon,
|
|
3263
3681
|
TableDeleteIcon,
|
|
3264
3682
|
TocPanel,
|
|
3265
3683
|
TrashIcon,
|
|
3266
3684
|
UnderlineIcon,
|
|
3267
3685
|
UndoIcon,
|
|
3686
|
+
XIcon,
|
|
3268
3687
|
a2 as applyCitationSources,
|
|
3269
3688
|
applyCommentAnchorsToEditor,
|
|
3270
3689
|
baseExtensions,
|
|
@@ -3280,6 +3699,7 @@ export {
|
|
|
3280
3699
|
defaultCodeBlockLabels,
|
|
3281
3700
|
defaultColorPaletteLabels,
|
|
3282
3701
|
defaultCommentLabels,
|
|
3702
|
+
defaultFindLabels,
|
|
3283
3703
|
defaultTocLabels,
|
|
3284
3704
|
defaultToolbarLabels,
|
|
3285
3705
|
enrichMarkdownCitations,
|
|
@@ -3304,6 +3724,7 @@ export {
|
|
|
3304
3724
|
r as readCitationAttrs,
|
|
3305
3725
|
replaceRangeWithMarkdown,
|
|
3306
3726
|
reportChart,
|
|
3727
|
+
runFindCommand,
|
|
3307
3728
|
s as scrollToTocHeading,
|
|
3308
3729
|
selectionKind,
|
|
3309
3730
|
s2 as serializeChartPayload,
|