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/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-DIAd_fIC.js";
4
- import { C, a, R, b, f, m, r, s } from "./scrollToTocHeading-DIAd_fIC.js";
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, useEditorState } from "@tiptap/react";
10
- import { useRef, useState, useMemo, useEffect, forwardRef, useImperativeHandle, useId, useCallback, useContext, createContext } from "react";
11
- import { e as enrichMarkdownCitations, b as styles$5 } from "./ReportContent-DQKBSQmm.js";
12
- import { R as R2, a as a2, s as s2 } from "./ReportContent-DQKBSQmm.js";
13
- 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-CKTMdT0a.js";
14
- import { g, e, s as s3 } from "./extractToc-CKTMdT0a.js";
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
- function findPlaceholderPos(doc) {
337
- let found = null;
338
- doc.descendants((node, pos) => {
339
- if (node.type.name === "importPlaceholder") {
340
- found = pos;
341
- return false;
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 buildDecorations(doc, anchors) {
494
- const bounds = [];
495
- doc.forEach((child, offset) => {
496
- bounds.push({ from: offset, to: offset + child.nodeSize });
497
- });
498
- const decorations = [];
499
- for (const anchor of anchors) {
500
- for (const range of anchor.ranges) {
501
- const from = Math.max(0, Math.min(range.from, range.to));
502
- const to = Math.min(doc.content.size, Math.max(range.from, range.to));
503
- if (from >= to) continue;
504
- for (const bound of bounds) {
505
- if (bound.to <= from || bound.from >= to) continue;
506
- const attrs = {
507
- class: PENDING_ANCHOR_CLASS,
508
- "data-pending-id": anchor.id
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 MarkdownPaste = Extension.create({
542
- name: "markdownPaste",
543
- addProseMirrorPlugins() {
544
- const { editor } = this;
545
- return [
546
- new Plugin({
547
- key: new PluginKey("markdownPaste"),
548
- props: {
549
- handlePaste(view, event) {
550
- const clipboard = event.clipboardData;
551
- if (!clipboard) return false;
552
- const text = clipboard.getData("text/plain");
553
- if (!text) return false;
554
- const input = view.input;
555
- if (input == null ? void 0 : input.shiftKey) return false;
556
- if (view.state.selection.$from.parent.type.spec.code) return false;
557
- if (!looksLikeMarkdown(text)) return false;
558
- const markdown = editor.markdown;
559
- if (!markdown) return false;
560
- try {
561
- const json = markdown.parse(prepareChartMarkdown(text));
562
- editor.commands.insertContent(json);
563
- return true;
564
- } catch (err) {
565
- console.error("markdown paste parse failed:", err);
566
- return false;
567
- }
568
- }
569
- }
570
- })
571
- ];
572
- }
573
- });
574
- const defaultChartLabels = {
575
- tabLabel: (chartType, index) => `${chartType} ${index + 1}`,
576
- done: "Done",
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$5.editorContent,
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
- return /* @__PURE__ */ jsx(
1296
- EditorContent,
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
- className: className ? `${styles$5.editorScroll} ${className}` : styles$5.editorScroll
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$5.editorContent }
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$5.editorScroll
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 row = rect.top; row < rect.bottom; row++) {
1426
- if (rowIsHeader(rect.map, rect.table, row)) {
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 field = isBlock ? /* @__PURE__ */ jsx(
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
- field,
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 row = Math.floor(i / TABLE_PICKER_COLS) + 1;
2043
- const active2 = hover.cols > 0 && col <= hover.cols && row <= hover.rows;
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, row),
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: row }),
2464
+ onMouseEnter: () => setHover({ cols: col, rows: row2 }),
2052
2465
  onClick: () => {
2053
- onInsert(row, col);
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: bar } })
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 input = importInputRef.current;
2310
- if (!input) return;
2311
- input.accept = accept;
2312
- input.value = "";
2313
- input.click();
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,