tiptap-markdown-react 0.19.2 → 1.1.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.
Files changed (61) hide show
  1. package/README.md +24 -49
  2. package/THIRD_PARTY_LICENSES.md +155 -1
  3. package/dist/{ReportContent-B8jIzhy3.js → ReportContent-B7okwVW0.js} +18 -8
  4. package/dist/{ReportContent-B8jIzhy3.js.map → ReportContent-B7okwVW0.js.map} +1 -1
  5. package/dist/{scrollToTocHeading-B2QmL4wi.js → ReportContentWithCharts-CDwS4OH9.js} +27 -27
  6. package/dist/ReportContentWithCharts-CDwS4OH9.js.map +1 -0
  7. package/dist/blockDrag/actions.d.ts +30 -0
  8. package/dist/blockDrag/actions.test.d.ts +1 -0
  9. package/dist/blockDrag/listDrop.d.ts +21 -0
  10. package/dist/blockDrag/listDrop.test.d.ts +1 -0
  11. package/dist/blurSelection.dom.test.d.ts +1 -0
  12. package/dist/characterCount.d.ts +1 -0
  13. package/dist/characterCount.dom.test.d.ts +1 -0
  14. package/dist/characterCount.test.d.ts +1 -0
  15. package/dist/chart/createChart.d.ts +0 -3
  16. package/dist/components/BlockDragHandle.d.ts +14 -0
  17. package/dist/components/BlockDragHandle.dom.test.d.ts +1 -0
  18. package/dist/components/CodeBlockView.d.ts +2 -2
  19. package/dist/components/ColorPalette.d.ts +4 -3
  20. package/dist/components/EditorToc.d.ts +13 -0
  21. package/dist/components/EditorToolbar.d.ts +4 -3
  22. package/dist/components/FindReplaceBar.d.ts +4 -3
  23. package/dist/components/LinkPopover.d.ts +4 -3
  24. package/dist/components/MarkdownPreview.d.ts +4 -1
  25. package/dist/components/MarkdownWysiwygEditor.d.ts +39 -10
  26. package/dist/detailsMarkdown.d.ts +4 -0
  27. package/dist/detailsMarkdown.test.d.ts +1 -0
  28. package/dist/emoji/EmojiSuggestion.d.ts +23 -0
  29. package/dist/emoji/emojiCategories.d.ts +52 -0
  30. package/dist/emoji/emojiMarkdown.test.d.ts +1 -0
  31. package/dist/emoji/emojiSuggestion.dom.test.d.ts +1 -0
  32. package/dist/emoji/filterEmoji.d.ts +7 -0
  33. package/dist/emoji/markdownEmoji.d.ts +8 -0
  34. package/dist/{extractToc-CGrBMGvM.js → extractToc-B50WvHao.js} +659 -5
  35. package/dist/extractToc-B50WvHao.js.map +1 -0
  36. package/dist/fonts/OFL.txt +95 -0
  37. package/dist/i18n/index.d.ts +4 -0
  38. package/dist/i18n/store.d.ts +16 -0
  39. package/dist/i18n/types.d.ts +19 -0
  40. package/dist/i18n/zh.d.ts +3 -0
  41. package/dist/icons/index.d.ts +5 -0
  42. package/dist/imageUpload.d.ts +0 -3
  43. package/dist/index.d.ts +1 -2
  44. package/dist/index.js +2307 -652
  45. package/dist/index.js.map +1 -1
  46. package/dist/labels.d.ts +56 -2
  47. package/dist/numberingFormat.d.ts +67 -0
  48. package/dist/numberingFormat.test.d.ts +1 -0
  49. package/dist/reader.js +2 -2
  50. package/dist/server.js +4 -4
  51. package/dist/shortcuts/ShortcutPanel.d.ts +4 -4
  52. package/dist/shortcuts/types.d.ts +2 -2
  53. package/dist/slashMenu/SlashMenuExtension.d.ts +0 -3
  54. package/dist/slashMenu/items.d.ts +2 -2
  55. package/dist/style-inline.css +2141 -384
  56. package/dist/style.css +2141 -384
  57. package/dist/typography.test.d.ts +1 -0
  58. package/package.json +19 -3
  59. package/dist/components/TocPanel.d.ts +0 -20
  60. package/dist/extractToc-CGrBMGvM.js.map +0 -1
  61. package/dist/scrollToTocHeading-B2QmL4wi.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,29 +1,33 @@
1
1
  "use client";
2
2
  import { Markdown, MarkdownManager } from "@tiptap/markdown";
3
- import { c as renderOrUpdateChart, d as destroyChart } from "./scrollToTocHeading-B2QmL4wi.js";
4
- import { C, a, R, b, f, m, r, s } from "./scrollToTocHeading-B2QmL4wi.js";
3
+ import { c as renderOrUpdateChart, d as destroyChart, s as scrollToTocHeading } from "./ReportContentWithCharts-CDwS4OH9.js";
4
+ import { C, a, R, b, f, m, r } from "./ReportContentWithCharts-CDwS4OH9.js";
5
5
  import { jsx, jsxs, Fragment as Fragment$2 } from "react/jsx-runtime";
6
6
  import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
7
7
  import FindAndReplace, { FindAndReplacePluginKey, createSearchRegex } from "@tiptap/extension-find-and-replace";
8
8
  import { default as default2 } from "@tiptap/extension-find-and-replace";
9
+ import Typography from "@tiptap/extension-typography";
9
10
  import Image from "@tiptap/extension-image";
10
11
  import { TableOfContents } from "@tiptap/extension-table-of-contents";
11
- import { skipTrailingNodeMeta, Placeholder } from "@tiptap/extensions";
12
+ import { skipTrailingNodeMeta, Placeholder, Selection as Selection$1, CharacterCount } from "@tiptap/extensions";
12
13
  import { NodeViewWrapper, ReactNodeViewRenderer, useEditorState, ReactRenderer, NodeViewContent, useEditor, EditorContent } from "@tiptap/react";
13
14
  import { Extension, Node as Node$1, mergeAttributes } from "@tiptap/core";
14
15
  import { createPortal } from "react-dom";
15
- import { useState, useEffect, useCallback, useRef, useMemo, forwardRef, useImperativeHandle, Fragment as Fragment$1, useLayoutEffect, useId, useContext, createContext } from "react";
16
- import { e as enrichMarkdownCitations, c as styles$c } from "./ReportContent-B8jIzhy3.js";
17
- import { R as R2, a as a2, b as b2, s as s2 } from "./ReportContent-B8jIzhy3.js";
18
- import { C as CitationRef, i as mergeCommentIntervals, h as mapCommentAnchors, n as normalizeImageAlign, p as prepareChartMarkdown, j as reportChart, b as baseExtensions, f as CommentMark, l as lowlight, m as makeTocGetId, k as parseCodeTokenAsChartOrCodeBlock, o as imageMarkdownTokenizer, q as imageParseMarkdown, t as imageRenderMarkdown, u as imageNodeHtml, v as imageFigureParseRule, w as imageCaptionAttribute, x as imageAlignAttribute, y as normalizeImageCaption, a as pureCodeBlock, c as pureImage, z as renderMathInto, A as subscribeMathClick, d as pureChart } from "./extractToc-CGrBMGvM.js";
19
- import { P, g, e, s as s3 } from "./extractToc-CGrBMGvM.js";
16
+ import { useState, useEffect, useCallback, useRef, useMemo, useSyncExternalStore, useLayoutEffect, forwardRef, useId, useImperativeHandle, Fragment as Fragment$1, useContext, createContext } from "react";
17
+ import { e as enrichMarkdownCitations, c as styles$e } from "./ReportContent-B7okwVW0.js";
18
+ import { R as R2, a as a2, b as b2, s } from "./ReportContent-B7okwVW0.js";
19
+ import { C as CitationRef, i as mergeCommentIntervals, h as mapCommentAnchors, n as normalizeImageAlign, p as prepareChartMarkdown, j as reportChart, f as CommentMark, b as baseExtensions, l as lowlight, m as makeTocGetId, k as parseCodeTokenAsChartOrCodeBlock, o as imageMarkdownTokenizer, q as imageParseMarkdown, t as imageRenderMarkdown, u as imageNodeHtml, v as imageFigureParseRule, w as imageCaptionAttribute, x as imageAlignAttribute, y as normalizeImageCaption, a as pureCodeBlock, c as pureImage, z as renderMathInto, A as readCurrentNumberingFormat, B as subscribeMathClick, D as applyNumberingFormat, N as NUMBERING_FORMAT_IDS, E as NUMBERING_FORMAT_LABELS, F as NUMBERING_FORMAT_PREVIEWS, d as pureChart } from "./extractToc-B50WvHao.js";
20
+ import { P, g, e, s as s2 } from "./extractToc-B50WvHao.js";
20
21
  import { Slice, Fragment } from "@tiptap/pm/model";
21
22
  import { PluginKey, Plugin, Selection, TextSelection, NodeSelection } from "@tiptap/pm/state";
22
23
  import { DecorationSet, Decoration } from "@tiptap/pm/view";
24
+ import { EmojiSuggestionPluginKey } from "@tiptap/extension-emoji";
23
25
  import Suggestion from "@tiptap/suggestion";
24
26
  import { FileHandlePlugin } from "@tiptap/extension-file-handler";
25
27
  import { CellSelection, TableMap, isInTable, selectedRect, rowIsHeader, cellAround } from "@tiptap/pm/tables";
26
28
  import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
29
+ import { DragHandle } from "@tiptap/extension-drag-handle-react";
30
+ import { dropPoint } from "@tiptap/pm/transform";
27
31
  import * as Popover from "@radix-ui/react-popover";
28
32
  function CitationRefView({ node, extension }) {
29
33
  const index = String(node.attrs.index ?? "");
@@ -118,8 +122,8 @@ function sliceHasCommentMarks(slice, markType) {
118
122
  }
119
123
  function blockBounds(doc) {
120
124
  const bounds = [];
121
- doc.forEach((child, offset) => {
122
- bounds.push({ start: offset, end: offset + child.nodeSize });
125
+ doc.forEach((child, offset2) => {
126
+ bounds.push({ start: offset2, end: offset2 + child.nodeSize });
123
127
  });
124
128
  return bounds;
125
129
  }
@@ -173,8 +177,8 @@ function commentAnchorPlugin(options = {}) {
173
177
  state: {
174
178
  init: () => ({ activeCommentId: null }),
175
179
  apply: (tr, value) => {
176
- const active2 = tr.getMeta(COMMENT_ACTIVE_META);
177
- return active2 !== void 0 ? { activeCommentId: active2 } : value;
180
+ const active = tr.getMeta(COMMENT_ACTIVE_META);
181
+ return active !== void 0 ? { activeCommentId: active } : value;
178
182
  }
179
183
  },
180
184
  props: {
@@ -329,8 +333,8 @@ function focusComment(editor, commentId) {
329
333
  function nextComment(editor, dir = "next") {
330
334
  const ids = collectCommentIds(editor);
331
335
  if (ids.length === 0) return null;
332
- const active2 = getActive(editor);
333
- const current = active2 ? ids.indexOf(active2) : -1;
336
+ const active = getActive(editor);
337
+ const current = active ? ids.indexOf(active) : -1;
334
338
  const nextIdx = dir === "next" ? (current + 1) % ids.length : (current - 1 + ids.length) % ids.length;
335
339
  const target = ids[nextIdx];
336
340
  focusComment(editor, target);
@@ -511,6 +515,12 @@ const ListOrderedIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
511
515
  /* @__PURE__ */ jsx("path", { d: "M4 10h2" }),
512
516
  /* @__PURE__ */ jsx("path", { d: "M6 18H4c0-1 2-2 2-3s-1-1.5-2-1" })
513
517
  ] });
518
+ const DetailsIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
519
+ /* @__PURE__ */ jsx("path", { d: "m9 7 4 5-4 5" }),
520
+ /* @__PURE__ */ jsx("path", { d: "M15 7h5" }),
521
+ /* @__PURE__ */ jsx("path", { d: "M15 12h5" }),
522
+ /* @__PURE__ */ jsx("path", { d: "M15 17h5" })
523
+ ] });
514
524
  const ListChecksIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
515
525
  /* @__PURE__ */ jsx("path", { d: "m3 17 2 2 4-4" }),
516
526
  /* @__PURE__ */ jsx("path", { d: "m3 7 2 2 4-4" }),
@@ -624,6 +634,19 @@ const ChevronsUpDownIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
624
634
  /* @__PURE__ */ jsx("path", { d: "m7 15 5 5 5-5" }),
625
635
  /* @__PURE__ */ jsx("path", { d: "m7 9 5-5 5 5" })
626
636
  ] });
637
+ const GripIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, fill: "currentColor", strokeWidth: 0, children: [
638
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "6", r: "1.25" }),
639
+ /* @__PURE__ */ jsx("circle", { cx: "15", cy: "6", r: "1.25" }),
640
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "12", r: "1.25" }),
641
+ /* @__PURE__ */ jsx("circle", { cx: "15", cy: "12", r: "1.25" }),
642
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "18", r: "1.25" }),
643
+ /* @__PURE__ */ jsx("circle", { cx: "15", cy: "18", r: "1.25" })
644
+ ] });
645
+ const DownloadIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
646
+ /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
647
+ /* @__PURE__ */ jsx("polyline", { points: "7 10 12 15 17 10" }),
648
+ /* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "15", y2: "3" })
649
+ ] });
627
650
  const KeyboardIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
628
651
  /* @__PURE__ */ jsx("rect", { width: "20", height: "16", x: "2", y: "4", rx: "2" }),
629
652
  /* @__PURE__ */ jsx("path", { d: "M6 8h.01" }),
@@ -698,8 +721,10 @@ const defaultToolbarLabels = {
698
721
  importDocumentConverting: "Converting…",
699
722
  importDocumentFailed: "Import failed",
700
723
  blockquote: "Blockquote",
724
+ details: "Toggle",
701
725
  bulletList: "Bullet list",
702
726
  orderedList: "Ordered list",
727
+ numberingFormat: "Numbering format",
703
728
  taskList: "Task list",
704
729
  more: "More",
705
730
  search: "Find & replace",
@@ -735,6 +760,23 @@ const defaultToolbarLabels = {
735
760
  mathNewInline: "New equation",
736
761
  mathNewBlock: "Add a TeX equation"
737
762
  };
763
+ const defaultBlockDragLabels = {
764
+ dragHandle: "Drag to move",
765
+ menuLabel: "Block actions",
766
+ turnInto: "Turn into",
767
+ paragraph: "Normal text",
768
+ headingLabel: (level) => `Heading ${level}`,
769
+ bulletList: "Bullet list",
770
+ orderedList: "Ordered list",
771
+ taskList: "Task list",
772
+ blockquote: "Blockquote",
773
+ codeBlock: "Code block",
774
+ copy: "Copy",
775
+ duplicate: "Duplicate",
776
+ resetFormatting: "Reset formatting",
777
+ downloadImage: "Download image",
778
+ delete: "Delete"
779
+ };
738
780
  const defaultSlashMenuLabels = {
739
781
  menuLabel: "Insert block",
740
782
  groupText: "Text",
@@ -746,6 +788,7 @@ const defaultSlashMenuLabels = {
746
788
  orderedList: "Ordered list",
747
789
  taskList: "Task list",
748
790
  blockquote: "Blockquote",
791
+ details: "Toggle",
749
792
  codeBlock: "Code block",
750
793
  divider: "Divider",
751
794
  table: "Table",
@@ -783,7 +826,19 @@ const defaultShortcutLabels = {
783
826
  alignCenter: "Align center",
784
827
  alignRight: "Align right",
785
828
  alignJustify: "Justify",
786
- imageUpload: "Upload image"
829
+ imageUpload: "Upload image",
830
+ smartQuote: "Smart quotes",
831
+ ellipsis: "Ellipsis",
832
+ emDash: "Em dash",
833
+ emoji: "Emoji"
834
+ };
835
+ const defaultCharacterCountLabels = {
836
+ label: "Document statistics",
837
+ characters: (count) => `${count} ${count === 1 ? "character" : "characters"}`,
838
+ words: (count) => `${count} ${count === 1 ? "word" : "words"}`
839
+ };
840
+ const defaultEmojiSuggestionLabels = {
841
+ menuLabel: "Emoji"
787
842
  };
788
843
  const defaultLinkPopoverLabels = {
789
844
  field: "Enter URL",
@@ -806,16 +861,8 @@ const defaultCodeBlockLabels = {
806
861
  delete: "Delete code block",
807
862
  copy: "Copy code",
808
863
  expand: "Expand code",
809
- collapse: "Collapse code"
810
- };
811
- const defaultCommentLabels = {
812
- open: "Open",
813
- resolved: "Resolved",
814
- dismissed: "Dismissed",
815
- outdated: "Outdated",
816
- ambiguous: "Ambiguous",
817
- partial: "Partially matched",
818
- gutterTitle: "Comment"
864
+ collapse: "Collapse code",
865
+ language: "Code language"
819
866
  };
820
867
  const defaultFindLabels = {
821
868
  find: "Find",
@@ -845,7 +892,261 @@ const defaultImageUploadLabels = {
845
892
  failed: "Upload failed",
846
893
  fallbackAlt: "image"
847
894
  };
848
- const bar$1 = "_bar_1h61e_3";
895
+ const zh = {
896
+ toolbar: {
897
+ undo: "撤销",
898
+ redo: "重做",
899
+ style: "样式",
900
+ normalText: "正文",
901
+ headingLabel: (level) => `标题 ${level}`,
902
+ fontSize: "字号",
903
+ fontSizeDefault: "默认",
904
+ bold: "加粗",
905
+ italic: "斜体",
906
+ underline: "下划线",
907
+ strike: "删除线",
908
+ code: "行内代码",
909
+ textColor: "文字颜色",
910
+ highlight: "高亮",
911
+ colorNone: "无",
912
+ colorTheme: "主题色",
913
+ scriptMenu: "上标 / 下标",
914
+ scriptNormal: "常规",
915
+ superscript: "上标",
916
+ subscript: "下标",
917
+ link: "链接",
918
+ align: "对齐",
919
+ alignLeft: "左对齐",
920
+ alignCenter: "居中",
921
+ alignRight: "右对齐",
922
+ alignJustify: "两端对齐",
923
+ indent: "缩进",
924
+ indentIncrease: "增加缩进",
925
+ indentDecrease: "减少缩进",
926
+ lineHeight: "行高",
927
+ lineHeightDefault: "默认",
928
+ linkPrompt: "输入链接地址",
929
+ linkApply: "应用链接",
930
+ linkOpen: "在新窗口打开",
931
+ linkRemove: "移除链接",
932
+ linkInvalid: "编辑器不接受这个地址",
933
+ image: "图片",
934
+ imageUploadFailed: "图片上传失败",
935
+ imageAlign: "图片对齐",
936
+ imageAlignLeft: "左对齐",
937
+ imageAlignCenter: "居中",
938
+ imageAlignRight: "右对齐",
939
+ imageCaption: "图片描述",
940
+ imageCaptionPlaceholder: "添加描述…",
941
+ importMarkdownFailed: "Markdown 导入失败",
942
+ importDocument: "导入",
943
+ importDocumentHint: "导入文件",
944
+ importDocumentOther: "文档",
945
+ importDocumentBusy: "正在导入…",
946
+ importDocumentUploading: (percent) => `上传中 ${percent}%`,
947
+ importDocumentConverting: "正在转换…",
948
+ importDocumentFailed: "导入失败",
949
+ blockquote: "引用",
950
+ details: "折叠块",
951
+ bulletList: "无序列表",
952
+ orderedList: "有序列表",
953
+ numberingFormat: "编号格式",
954
+ taskList: "任务列表",
955
+ more: "更多",
956
+ search: "查找替换",
957
+ codeBlock: "代码块",
958
+ hr: "分隔线",
959
+ importMarkdown: "Markdown",
960
+ tableInsert: "插入表格",
961
+ tableRowMenu: "行操作",
962
+ tableColumnMenu: "列操作",
963
+ tableClearContent: "清空内容",
964
+ tableResetCellStyles: "重置单元格样式",
965
+ tableAppendRow: "添加行",
966
+ tableAppendColumn: "添加列",
967
+ tableSizeSelected: (cols, rows) => `${cols} × ${rows}`,
968
+ tableAddColumnBefore: "在左侧插入列",
969
+ tableAddColumnAfter: "在右侧插入列",
970
+ tableDeleteColumn: "删除列",
971
+ tableAddRowBefore: "在上方插入行",
972
+ tableAddRowAfter: "在下方插入行",
973
+ tableDeleteRow: "删除行",
974
+ tableAddColumnBeforeN: (n) => `在左侧插入 ${n} 列`,
975
+ tableAddColumnAfterN: (n) => `在右侧插入 ${n} 列`,
976
+ tableDeleteColumnN: (n) => `删除 ${n} 列`,
977
+ tableAddRowBeforeN: (n) => `在上方插入 ${n} 行`,
978
+ tableAddRowAfterN: (n) => `在下方插入 ${n} 行`,
979
+ tableDeleteRowN: (n) => `删除 ${n} 行`,
980
+ tableDeleteTable: "删除表格",
981
+ inlineMath: "行内公式",
982
+ blockMath: "块级公式",
983
+ mathPlaceholder: "E = mc^2",
984
+ mathDone: "完成",
985
+ mathCancel: "取消",
986
+ mathNewInline: "新建公式",
987
+ mathNewBlock: "插入 TeX 公式"
988
+ },
989
+ slashMenu: {
990
+ menuLabel: "插入块",
991
+ groupText: "文本",
992
+ groupList: "列表",
993
+ groupAdvanced: "高级",
994
+ normalText: "正文",
995
+ headingLabel: (level) => `标题 ${level}`,
996
+ bulletList: "无序列表",
997
+ orderedList: "有序列表",
998
+ taskList: "任务列表",
999
+ blockquote: "引用",
1000
+ details: "折叠块",
1001
+ codeBlock: "代码块",
1002
+ divider: "分隔线",
1003
+ table: "表格",
1004
+ inlineMath: "行内公式",
1005
+ blockMath: "块级公式"
1006
+ },
1007
+ chart: {
1008
+ tabLabel: (chartType, index) => `${chartType} ${index + 1}`,
1009
+ done: "完成",
1010
+ cancel: "取消",
1011
+ configLabel: "图表配置(JSON)",
1012
+ tableLabel: "数据表(Markdown)",
1013
+ editTitle: "编辑图表"
1014
+ },
1015
+ blockDrag: {
1016
+ dragHandle: "拖动以移动",
1017
+ menuLabel: "块操作",
1018
+ turnInto: "转换成",
1019
+ paragraph: "正文",
1020
+ headingLabel: (level) => `标题 ${level}`,
1021
+ bulletList: "无序列表",
1022
+ orderedList: "有序列表",
1023
+ taskList: "任务列表",
1024
+ blockquote: "引用",
1025
+ codeBlock: "代码块",
1026
+ copy: "复制",
1027
+ duplicate: "再制一份",
1028
+ resetFormatting: "清除格式",
1029
+ downloadImage: "下载图片",
1030
+ delete: "删除"
1031
+ },
1032
+ shortcut: {
1033
+ panelTitle: "快捷键",
1034
+ close: "关闭",
1035
+ colFormat: "格式",
1036
+ colShortcut: "快捷键",
1037
+ colMarkdown: "Markdown",
1038
+ formatGroup: "格式",
1039
+ insertGroup: "插入",
1040
+ editGroup: "编辑",
1041
+ bold: "加粗",
1042
+ italic: "斜体",
1043
+ strike: "删除线",
1044
+ underline: "下划线",
1045
+ inlineCode: "行内代码",
1046
+ highlight: "高亮",
1047
+ headingLabel: (level) => `标题 ${level}`,
1048
+ paragraph: "正文",
1049
+ blockquote: "引用",
1050
+ bulletList: "无序列表",
1051
+ orderedList: "有序列表",
1052
+ taskList: "任务列表",
1053
+ codeBlock: "代码块",
1054
+ divider: "分隔线",
1055
+ undo: "撤销",
1056
+ redo: "重做",
1057
+ hardBreak: "硬换行",
1058
+ findReplace: "查找替换",
1059
+ alignLeft: "左对齐",
1060
+ alignCenter: "居中",
1061
+ alignRight: "右对齐",
1062
+ alignJustify: "两端对齐",
1063
+ imageUpload: "上传图片",
1064
+ smartQuote: "智能引号",
1065
+ ellipsis: "省略号",
1066
+ emDash: "破折号",
1067
+ emoji: "表情"
1068
+ },
1069
+ characterCount: {
1070
+ label: "字数统计",
1071
+ characters: (count) => `${count} 字符`,
1072
+ words: (count) => `${count} 词`
1073
+ },
1074
+ emoji: {
1075
+ menuLabel: "表情"
1076
+ },
1077
+ link: {
1078
+ field: "输入链接地址",
1079
+ apply: "应用链接",
1080
+ open: "在新窗口打开",
1081
+ remove: "移除链接",
1082
+ invalid: "编辑器不接受这个地址"
1083
+ },
1084
+ palette: {
1085
+ none: "无",
1086
+ theme: "主题色"
1087
+ },
1088
+ toc: {
1089
+ title: "目录",
1090
+ expand: "展开",
1091
+ collapse: "收起"
1092
+ },
1093
+ codeBlock: {
1094
+ autoDetect: "自动识别",
1095
+ delete: "删除代码块",
1096
+ copy: "复制代码",
1097
+ expand: "展开代码",
1098
+ collapse: "收起代码",
1099
+ language: "代码语言"
1100
+ },
1101
+ find: {
1102
+ find: "查找",
1103
+ replace: "替换为",
1104
+ next: "下一处",
1105
+ previous: "上一处",
1106
+ replaceOne: "替换",
1107
+ replaceAll: "全部替换",
1108
+ close: "关闭",
1109
+ caseSensitive: "区分大小写",
1110
+ wholeWord: "全词匹配",
1111
+ useRegex: "正则表达式",
1112
+ counter: (current, total) => `${current} / ${total}`,
1113
+ invalidRegex: "正则无效",
1114
+ readOnly: "只读"
1115
+ },
1116
+ imageUpload: {
1117
+ dropzoneClick: "点击上传",
1118
+ dropzoneRest: ",或拖拽到此处",
1119
+ dropzoneLimits: (limit, maxSizeMb) => {
1120
+ const count = `最多 ${limit} 个文件`;
1121
+ return maxSizeMb == null ? `${count}。` : `${count},每个 ${maxSizeMb}MB。`;
1122
+ },
1123
+ uploadingCount: (count) => `正在上传 ${count} 个文件`,
1124
+ clearAll: "全部清除",
1125
+ remove: "移除",
1126
+ failed: "上传失败",
1127
+ fallbackAlt: "图片"
1128
+ }
1129
+ };
1130
+ const en = {
1131
+ toolbar: defaultToolbarLabels,
1132
+ slashMenu: defaultSlashMenuLabels,
1133
+ chart: defaultChartLabels,
1134
+ blockDrag: defaultBlockDragLabels,
1135
+ shortcut: defaultShortcutLabels,
1136
+ characterCount: defaultCharacterCountLabels,
1137
+ emoji: defaultEmojiSuggestionLabels,
1138
+ link: defaultLinkPopoverLabels,
1139
+ palette: defaultColorPaletteLabels,
1140
+ toc: defaultTocLabels,
1141
+ codeBlock: defaultCodeBlockLabels,
1142
+ find: defaultFindLabels,
1143
+ imageUpload: defaultImageUploadLabels
1144
+ };
1145
+ const bundles = { en, zh };
1146
+ function getLocaleBundle(locale = "en") {
1147
+ return bundles[locale] ?? en;
1148
+ }
1149
+ const bar$2 = "_bar_1h61e_3";
849
1150
  const row$1 = "_row_1h61e_25";
850
1151
  const field$1 = "_field_1h61e_43";
851
1152
  const fieldIcon = "_fieldIcon_1h61e_62";
@@ -858,8 +1159,8 @@ const toggleOn = "_toggleOn_1h61e_135";
858
1159
  const iconGroup = "_iconGroup_1h61e_29";
859
1160
  const spacer = "_spacer_1h61e_150";
860
1161
  const readOnly = "_readOnly_1h61e_155";
861
- const styles$b = {
862
- bar: bar$1,
1162
+ const styles$d = {
1163
+ bar: bar$2,
863
1164
  row: row$1,
864
1165
  field: field$1,
865
1166
  fieldIcon,
@@ -884,12 +1185,12 @@ function warnMissingExtensionOnce() {
884
1185
  function FindReplaceBar({
885
1186
  editor,
886
1187
  onClose,
887
- labels,
1188
+ locale = "en",
888
1189
  inputRef,
889
1190
  className,
890
1191
  style
891
1192
  }) {
892
- const t = { ...defaultFindLabels, ...labels };
1193
+ const t = getLocaleBundle(locale).find;
893
1194
  const [term, setTerm] = useState("");
894
1195
  const [replaceTerm, setReplaceTerm] = useState("");
895
1196
  const hasExtension = hasFindReplaceExtension(editor);
@@ -982,11 +1283,11 @@ function FindReplaceBar({
982
1283
  });
983
1284
  };
984
1285
  if (!hasExtension) return null;
985
- const toggleClass = (on) => `${styles$b.btn} ${styles$b.toggle}${on ? ` ${styles$b.toggleOn}` : ""}`;
1286
+ const toggleClass = (on) => `${styles$d.btn} ${styles$d.toggle}${on ? ` ${styles$d.toggleOn}` : ""}`;
986
1287
  return /* @__PURE__ */ jsxs(
987
1288
  "div",
988
1289
  {
989
- className: className ? `${styles$b.bar} ${className}` : styles$b.bar,
1290
+ className: className ? `${styles$d.bar} ${className}` : styles$d.bar,
990
1291
  style,
991
1292
  "data-find-bar": "",
992
1293
  role: "dialog",
@@ -999,14 +1300,14 @@ function FindReplaceBar({
999
1300
  onClose();
1000
1301
  },
1001
1302
  children: [
1002
- /* @__PURE__ */ jsxs("div", { className: styles$b.row, children: [
1003
- /* @__PURE__ */ jsxs("span", { className: styles$b.field, children: [
1004
- /* @__PURE__ */ jsx(SearchIcon, { size: 14, className: styles$b.fieldIcon }),
1303
+ /* @__PURE__ */ jsxs("div", { className: styles$d.row, children: [
1304
+ /* @__PURE__ */ jsxs("span", { className: styles$d.field, children: [
1305
+ /* @__PURE__ */ jsx(SearchIcon, { size: 14, className: styles$d.fieldIcon }),
1005
1306
  /* @__PURE__ */ jsx(
1006
1307
  "input",
1007
1308
  {
1008
1309
  ref: inputRef,
1009
- className: styles$b.input,
1310
+ className: styles$d.input,
1010
1311
  "data-find-field": "search",
1011
1312
  value: term,
1012
1313
  onChange: (e2) => setTerm(e2.target.value),
@@ -1020,7 +1321,7 @@ function FindReplaceBar({
1020
1321
  /* @__PURE__ */ jsx(
1021
1322
  "span",
1022
1323
  {
1023
- className: `${styles$b.counter}${invalidPattern ? ` ${styles$b.counterInvalid}` : ""}`,
1324
+ className: `${styles$d.counter}${invalidPattern ? ` ${styles$d.counterInvalid}` : ""}`,
1024
1325
  "data-find-counter": "",
1025
1326
  "aria-live": "polite",
1026
1327
  title: invalidPattern ? t.invalidRegex : void 0,
@@ -1056,13 +1357,13 @@ function FindReplaceBar({
1056
1357
  children: "ab"
1057
1358
  }
1058
1359
  ),
1059
- /* @__PURE__ */ jsx("span", { className: styles$b.spacer }),
1060
- /* @__PURE__ */ jsxs("span", { className: styles$b.iconGroup, children: [
1360
+ /* @__PURE__ */ jsx("span", { className: styles$d.spacer }),
1361
+ /* @__PURE__ */ jsxs("span", { className: styles$d.iconGroup, children: [
1061
1362
  /* @__PURE__ */ jsx(
1062
1363
  "button",
1063
1364
  {
1064
1365
  type: "button",
1065
- className: styles$b.btn,
1366
+ className: styles$d.btn,
1066
1367
  "data-find-action": "previous",
1067
1368
  title: t.previous,
1068
1369
  "aria-label": t.previous,
@@ -1076,7 +1377,7 @@ function FindReplaceBar({
1076
1377
  "button",
1077
1378
  {
1078
1379
  type: "button",
1079
- className: styles$b.btn,
1380
+ className: styles$d.btn,
1080
1381
  "data-find-action": "next",
1081
1382
  title: t.next,
1082
1383
  "aria-label": t.next,
@@ -1090,7 +1391,7 @@ function FindReplaceBar({
1090
1391
  "button",
1091
1392
  {
1092
1393
  type: "button",
1093
- className: styles$b.btn,
1394
+ className: styles$d.btn,
1094
1395
  "data-find-action": "close",
1095
1396
  title: t.close,
1096
1397
  "aria-label": t.close,
@@ -1100,11 +1401,11 @@ function FindReplaceBar({
1100
1401
  )
1101
1402
  ] })
1102
1403
  ] }),
1103
- editor.isEditable ? /* @__PURE__ */ jsxs("div", { className: styles$b.row, children: [
1104
- /* @__PURE__ */ jsx("span", { className: styles$b.field, children: /* @__PURE__ */ jsx(
1404
+ editor.isEditable ? /* @__PURE__ */ jsxs("div", { className: styles$d.row, children: [
1405
+ /* @__PURE__ */ jsx("span", { className: styles$d.field, children: /* @__PURE__ */ jsx(
1105
1406
  "input",
1106
1407
  {
1107
- className: styles$b.input,
1408
+ className: styles$d.input,
1108
1409
  "data-find-field": "replace",
1109
1410
  value: replaceTerm,
1110
1411
  onChange: (e2) => setReplaceTerm(e2.target.value),
@@ -1114,12 +1415,12 @@ function FindReplaceBar({
1114
1415
  spellCheck: false
1115
1416
  }
1116
1417
  ) }),
1117
- /* @__PURE__ */ jsx("span", { className: styles$b.spacer }),
1418
+ /* @__PURE__ */ jsx("span", { className: styles$d.spacer }),
1118
1419
  /* @__PURE__ */ jsx(
1119
1420
  "button",
1120
1421
  {
1121
1422
  type: "button",
1122
- className: styles$b.btn,
1423
+ className: styles$d.btn,
1123
1424
  "data-find-action": "replace",
1124
1425
  title: t.replaceOne,
1125
1426
  "aria-label": t.replaceOne,
@@ -1133,7 +1434,7 @@ function FindReplaceBar({
1133
1434
  "button",
1134
1435
  {
1135
1436
  type: "button",
1136
- className: styles$b.btn,
1437
+ className: styles$d.btn,
1137
1438
  "data-find-action": "replace-all",
1138
1439
  title: t.replaceAll,
1139
1440
  "aria-label": t.replaceAll,
@@ -1143,7 +1444,7 @@ function FindReplaceBar({
1143
1444
  children: /* @__PURE__ */ jsx(ReplaceAllIcon, { size: 16 })
1144
1445
  }
1145
1446
  )
1146
- ] }) : /* @__PURE__ */ jsx("div", { className: styles$b.row, children: /* @__PURE__ */ jsx("span", { className: styles$b.readOnly, children: t.readOnly }) })
1447
+ ] }) : /* @__PURE__ */ jsx("div", { className: styles$d.row, children: /* @__PURE__ */ jsx("span", { className: styles$d.readOnly, children: t.readOnly }) })
1147
1448
  ]
1148
1449
  }
1149
1450
  );
@@ -1230,6 +1531,65 @@ const ImportPlaceholder = Node$1.create({
1230
1531
  };
1231
1532
  }
1232
1533
  });
1534
+ const serverBundle = getLocaleBundle("en");
1535
+ const stores = /* @__PURE__ */ new WeakMap();
1536
+ function ensure(editor) {
1537
+ let entry = stores.get(editor);
1538
+ if (!entry) {
1539
+ entry = {
1540
+ locale: "en",
1541
+ bundle: serverBundle,
1542
+ listeners: /* @__PURE__ */ new Set(),
1543
+ pendingNotify: false
1544
+ };
1545
+ stores.set(editor, entry);
1546
+ }
1547
+ return entry;
1548
+ }
1549
+ function setEditorLocale(editor, locale) {
1550
+ const entry = ensure(editor);
1551
+ if (entry.locale === locale) return;
1552
+ entry.locale = locale;
1553
+ entry.bundle = getLocaleBundle(locale);
1554
+ entry.pendingNotify = true;
1555
+ }
1556
+ function flushEditorLocale(editor) {
1557
+ const entry = stores.get(editor);
1558
+ if (!(entry == null ? void 0 : entry.pendingNotify)) return;
1559
+ entry.pendingNotify = false;
1560
+ entry.listeners.forEach((listener) => listener());
1561
+ }
1562
+ function getEditorLocale(editor) {
1563
+ var _a;
1564
+ return ((_a = stores.get(editor)) == null ? void 0 : _a.locale) ?? "en";
1565
+ }
1566
+ function getEditorBundle(editor) {
1567
+ var _a;
1568
+ return ((_a = stores.get(editor)) == null ? void 0 : _a.bundle) ?? serverBundle;
1569
+ }
1570
+ function subscribeEditorLocale(editor, listener) {
1571
+ const entry = ensure(editor);
1572
+ entry.listeners.add(listener);
1573
+ return () => {
1574
+ entry.listeners.delete(listener);
1575
+ };
1576
+ }
1577
+ const useIsoLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
1578
+ function usePublishEditorLocale(editor, locale) {
1579
+ if (editor) setEditorLocale(editor, locale);
1580
+ useIsoLayoutEffect(() => {
1581
+ if (!editor || editor.isDestroyed) return;
1582
+ flushEditorLocale(editor);
1583
+ }, [editor, locale]);
1584
+ }
1585
+ function useEditorBundle(editor) {
1586
+ const subscribe = useCallback(
1587
+ (onStoreChange) => subscribeEditorLocale(editor, onStoreChange),
1588
+ [editor]
1589
+ );
1590
+ const getSnapshot = useCallback(() => getEditorBundle(editor), [editor]);
1591
+ return useSyncExternalStore(subscribe, getSnapshot, () => serverBundle);
1592
+ }
1233
1593
  const wrap = "_wrap_1k6n1_8";
1234
1594
  const dropzone = "_dropzone_1k6n1_24";
1235
1595
  const dragActive = "_dragActive_1k6n1_43";
@@ -1243,7 +1603,7 @@ const textMain = "_textMain_1k6n1_100";
1243
1603
  const textEm = "_textEm_1k6n1_107";
1244
1604
  const subtext = "_subtext_1k6n1_112";
1245
1605
  const previews = "_previews_1k6n1_121";
1246
- const header$2 = "_header_1k6n1_127";
1606
+ const header$1 = "_header_1k6n1_127";
1247
1607
  const clearAll = "_clearAll_1k6n1_139";
1248
1608
  const preview = "_preview_1k6n1_121";
1249
1609
  const progress = "_progress_1k6n1_161";
@@ -1255,7 +1615,7 @@ const fileName = "_fileName_1k6n1_205";
1255
1615
  const actions = "_actions_1k6n1_215";
1256
1616
  const progressText = "_progressText_1k6n1_222";
1257
1617
  const remove = "_remove_1k6n1_228";
1258
- const styles$a = {
1618
+ const styles$c = {
1259
1619
  wrap,
1260
1620
  dropzone,
1261
1621
  dragActive,
@@ -1269,7 +1629,7 @@ const styles$a = {
1269
1629
  textEm,
1270
1630
  subtext,
1271
1631
  previews,
1272
- header: header$2,
1632
+ header: header$1,
1273
1633
  clearAll,
1274
1634
  preview,
1275
1635
  progress,
@@ -1312,10 +1672,7 @@ function focusNextNode(editor) {
1312
1672
  function ImageUploadView(props) {
1313
1673
  const { node, extension, editor, getPos } = props;
1314
1674
  const options = extension.options;
1315
- const labels = {
1316
- ...defaultImageUploadLabels,
1317
- ...options.labels
1318
- };
1675
+ const labels = useEditorBundle(editor).imageUpload;
1319
1676
  const accept = String(node.attrs.accept ?? "image/*");
1320
1677
  const limit = Number(node.attrs.limit ?? 1) || 1;
1321
1678
  const maxSize = Number(node.attrs.maxSize ?? 0) || 0;
@@ -1387,7 +1744,7 @@ function ImageUploadView(props) {
1387
1744
  files.map(async (file) => ({ file, url: await uploadOne(file) }))
1388
1745
  );
1389
1746
  const uploaded = settled.filter(
1390
- (s4) => s4.url != null
1747
+ (s3) => s3.url != null
1391
1748
  );
1392
1749
  if (uploaded.length === 0) return;
1393
1750
  const pos = getPos();
@@ -1433,14 +1790,14 @@ function ImageUploadView(props) {
1433
1790
  const hasFiles = items.length > 0;
1434
1791
  const maxSizeMb = maxSize > 0 ? toMb(maxSize) : null;
1435
1792
  const dropzoneClass = [
1436
- styles$a.dropzone,
1437
- dragActive2 ? styles$a.dragActive : "",
1438
- dragOver2 ? styles$a.dragOver : ""
1793
+ styles$c.dropzone,
1794
+ dragActive2 ? styles$c.dragActive : "",
1795
+ dragOver2 ? styles$c.dragOver : ""
1439
1796
  ].filter(Boolean).join(" ");
1440
1797
  return /* @__PURE__ */ jsxs(
1441
1798
  NodeViewWrapper,
1442
1799
  {
1443
- className: styles$a.wrap,
1800
+ className: styles$c.wrap,
1444
1801
  "data-image-upload": "",
1445
1802
  tabIndex: editable ? 0 : void 0,
1446
1803
  onClick: openPicker,
@@ -1472,28 +1829,28 @@ function ImageUploadView(props) {
1472
1829
  },
1473
1830
  onDrop,
1474
1831
  children: [
1475
- /* @__PURE__ */ jsxs("span", { className: styles$a.fileShape, "aria-hidden": true, children: [
1832
+ /* @__PURE__ */ jsxs("span", { className: styles$c.fileShape, "aria-hidden": true, children: [
1476
1833
  /* @__PURE__ */ jsx(FileDocIcon, {}),
1477
1834
  /* @__PURE__ */ jsx(FileCornerIcon, {}),
1478
- /* @__PURE__ */ jsx("span", { className: styles$a.fileBadge, children: /* @__PURE__ */ jsx(CloudUploadIcon, {}) })
1835
+ /* @__PURE__ */ jsx("span", { className: styles$c.fileBadge, children: /* @__PURE__ */ jsx(CloudUploadIcon, {}) })
1479
1836
  ] }),
1480
- /* @__PURE__ */ jsxs("span", { className: styles$a.text, children: [
1481
- /* @__PURE__ */ jsxs("span", { className: styles$a.textMain, children: [
1482
- /* @__PURE__ */ jsx("em", { className: styles$a.textEm, children: labels.dropzoneClick }),
1837
+ /* @__PURE__ */ jsxs("span", { className: styles$c.text, children: [
1838
+ /* @__PURE__ */ jsxs("span", { className: styles$c.textMain, children: [
1839
+ /* @__PURE__ */ jsx("em", { className: styles$c.textEm, children: labels.dropzoneClick }),
1483
1840
  labels.dropzoneRest
1484
1841
  ] }),
1485
- /* @__PURE__ */ jsx("span", { className: styles$a.subtext, children: labels.dropzoneLimits(limit, maxSizeMb) })
1842
+ /* @__PURE__ */ jsx("span", { className: styles$c.subtext, children: labels.dropzoneLimits(limit, maxSizeMb) })
1486
1843
  ] })
1487
1844
  ]
1488
1845
  }
1489
- ) : /* @__PURE__ */ jsxs("div", { className: styles$a.previews, "data-image-upload-list": "", children: [
1490
- items.length > 1 && /* @__PURE__ */ jsxs("div", { className: styles$a.header, children: [
1846
+ ) : /* @__PURE__ */ jsxs("div", { className: styles$c.previews, "data-image-upload-list": "", children: [
1847
+ items.length > 1 && /* @__PURE__ */ jsxs("div", { className: styles$c.header, children: [
1491
1848
  /* @__PURE__ */ jsx("span", { children: labels.uploadingCount(items.length) }),
1492
1849
  /* @__PURE__ */ jsx(
1493
1850
  "button",
1494
1851
  {
1495
1852
  type: "button",
1496
- className: styles$a.clearAll,
1853
+ className: styles$c.clearAll,
1497
1854
  onClick: (e2) => {
1498
1855
  e2.stopPropagation();
1499
1856
  clearAll2();
@@ -1505,27 +1862,27 @@ function ImageUploadView(props) {
1505
1862
  items.map((it) => /* @__PURE__ */ jsxs(
1506
1863
  "div",
1507
1864
  {
1508
- className: styles$a.preview,
1865
+ className: styles$c.preview,
1509
1866
  "data-image-upload-item": "",
1510
1867
  children: [
1511
1868
  it.status === "uploading" && /* @__PURE__ */ jsx(
1512
1869
  "div",
1513
1870
  {
1514
- className: styles$a.progress,
1871
+ className: styles$c.progress,
1515
1872
  style: { width: `${it.progress}%` },
1516
1873
  "aria-hidden": true
1517
1874
  }
1518
1875
  ),
1519
- /* @__PURE__ */ jsxs("div", { className: styles$a.previewContent, children: [
1520
- /* @__PURE__ */ jsxs("span", { className: styles$a.fileInfo, children: [
1521
- /* @__PURE__ */ jsx("span", { className: styles$a.fileIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx(CloudUploadIcon, {}) }),
1522
- /* @__PURE__ */ jsxs("span", { className: styles$a.details, children: [
1523
- /* @__PURE__ */ jsx("span", { className: styles$a.fileName, children: it.file.name }),
1524
- /* @__PURE__ */ jsx("span", { className: styles$a.subtext, children: it.status === "error" ? labels.failed : formatFileSize(it.file.size) })
1876
+ /* @__PURE__ */ jsxs("div", { className: styles$c.previewContent, children: [
1877
+ /* @__PURE__ */ jsxs("span", { className: styles$c.fileInfo, children: [
1878
+ /* @__PURE__ */ jsx("span", { className: styles$c.fileIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx(CloudUploadIcon, {}) }),
1879
+ /* @__PURE__ */ jsxs("span", { className: styles$c.details, children: [
1880
+ /* @__PURE__ */ jsx("span", { className: styles$c.fileName, children: it.file.name }),
1881
+ /* @__PURE__ */ jsx("span", { className: styles$c.subtext, children: it.status === "error" ? labels.failed : formatFileSize(it.file.size) })
1525
1882
  ] })
1526
1883
  ] }),
1527
- /* @__PURE__ */ jsxs("span", { className: styles$a.actions, children: [
1528
- it.status === "uploading" && /* @__PURE__ */ jsxs("span", { className: styles$a.progressText, children: [
1884
+ /* @__PURE__ */ jsxs("span", { className: styles$c.actions, children: [
1885
+ it.status === "uploading" && /* @__PURE__ */ jsxs("span", { className: styles$c.progressText, children: [
1529
1886
  Math.round(it.progress),
1530
1887
  "%"
1531
1888
  ] }),
@@ -1533,7 +1890,7 @@ function ImageUploadView(props) {
1533
1890
  "button",
1534
1891
  {
1535
1892
  type: "button",
1536
- className: styles$a.remove,
1893
+ className: styles$c.remove,
1537
1894
  "data-image-upload-remove": "",
1538
1895
  title: labels.remove,
1539
1896
  "aria-label": labels.remove,
@@ -1592,7 +1949,7 @@ function FileDocIcon() {
1592
1949
  viewBox: "0 0 43 57",
1593
1950
  fill: "none",
1594
1951
  "aria-hidden": true,
1595
- className: styles$a.fileShapeDoc,
1952
+ className: styles$c.fileShapeDoc,
1596
1953
  children: /* @__PURE__ */ jsx(
1597
1954
  "path",
1598
1955
  {
@@ -1615,7 +1972,7 @@ function FileCornerIcon() {
1615
1972
  viewBox: "0 0 10 10",
1616
1973
  fill: "currentColor",
1617
1974
  "aria-hidden": true,
1618
- className: styles$a.fileShapeCorner,
1975
+ className: styles$c.fileShapeCorner,
1619
1976
  children: /* @__PURE__ */ jsx("path", { d: "M0 0.75H0.343146C1.40401 0.75 2.42143 1.17143 3.17157 1.92157L8.82843 7.57843C9.57857 8.32857 10 9.34599 10 10.4069V10.75H4C1.79086 10.75 0 8.95914 0 6.75V0.75Z" })
1620
1977
  }
1621
1978
  );
@@ -1639,8 +1996,7 @@ const ImageUploadNode = Node$1.create({
1639
1996
  maxSize: 0,
1640
1997
  type: "image",
1641
1998
  onError: void 0,
1642
- onSuccess: void 0,
1643
- labels: void 0
1999
+ onSuccess: void 0
1644
2000
  };
1645
2001
  },
1646
2002
  addAttributes() {
@@ -1739,23 +2095,305 @@ function setImageAlignAt(editor, imageElement, align) {
1739
2095
  return false;
1740
2096
  }
1741
2097
  }
2098
+ const popupHost$1 = "_popupHost_xhti8_5";
2099
+ const panel$1 = "_panel_xhti8_11";
2100
+ const menu$3 = "_menu_xhti8_22";
2101
+ const tabs = "_tabs_xhti8_32";
2102
+ const tab = "_tab_xhti8_32";
2103
+ const tabActive = "_tabActive_xhti8_40";
2104
+ const cell = "_cell_xhti8_71";
2105
+ const cellActive = "_cellActive_xhti8_72";
2106
+ const styles$b = {
2107
+ popupHost: popupHost$1,
2108
+ panel: panel$1,
2109
+ menu: menu$3,
2110
+ tabs,
2111
+ tab,
2112
+ tabActive,
2113
+ cell,
2114
+ cellActive
2115
+ };
2116
+ const EMOJI_CATEGORIES = [
2117
+ { id: "smileys", group: "", label: "Smileys", icon: "😀" },
2118
+ { id: "people", group: "people & body", label: "People", icon: "👋" },
2119
+ { id: "nature", group: "animals & nature", label: "Animals & nature", icon: "🐻" },
2120
+ { id: "food", group: "food & drink", label: "Food & drink", icon: "🍔" },
2121
+ { id: "travel", group: "travel & places", label: "Travel & places", icon: "✈️" },
2122
+ { id: "activities", group: "activities", label: "Activities", icon: "⚽" },
2123
+ { id: "objects", group: "objects", label: "Objects", icon: "💡" },
2124
+ { id: "symbols", group: "symbols", label: "Symbols", icon: "💯" },
2125
+ { id: "flags", group: "flags", label: "Flags", icon: "🏁" }
2126
+ ];
2127
+ function isEmojiComponent(item2) {
2128
+ return item2.group === "components";
2129
+ }
2130
+ function itemsInCategory(items, id) {
2131
+ const category = EMOJI_CATEGORIES.find((entry) => entry.id === id);
2132
+ if (!category) return [];
2133
+ return items.filter((item2) => (item2.group ?? "") === category.group);
2134
+ }
2135
+ function isRegionalIndicator(item2) {
2136
+ return item2.name.startsWith("regional_indicator_");
2137
+ }
2138
+ function filterEmojiItems(items, query) {
2139
+ const q = query.trim().toLowerCase();
2140
+ const usable = items.filter(
2141
+ (item2) => !!item2.emoji && !isRegionalIndicator(item2) && !isEmojiComponent(item2)
2142
+ );
2143
+ if (!q) return usable;
2144
+ const primary = [];
2145
+ const secondary = [];
2146
+ for (const item2 of usable) {
2147
+ const nameHit = item2.name.toLowerCase().startsWith(q) || item2.shortcodes.some((code) => code.toLowerCase().startsWith(q));
2148
+ if (nameHit) primary.push(item2);
2149
+ else if (item2.tags.some((tag) => tag.toLowerCase().startsWith(q))) {
2150
+ secondary.push(item2);
2151
+ }
2152
+ }
2153
+ return [...primary, ...secondary];
2154
+ }
2155
+ const COLUMNS = 8;
2156
+ function isComposing$1(event, view) {
2157
+ return view.composing || event.isComposing || event.keyCode === 229;
2158
+ }
2159
+ const themeVars = [
2160
+ "--tmr-text",
2161
+ "--tmr-accent",
2162
+ "--tmr-toolbar-border",
2163
+ "--tmr-toolbar-muted"
2164
+ ];
2165
+ function copyThemeVars(from, to) {
2166
+ const computed = getComputedStyle(from);
2167
+ for (const name of themeVars) {
2168
+ const value = computed.getPropertyValue(name);
2169
+ if (value) to.style.setProperty(name, value);
2170
+ }
2171
+ }
2172
+ function moveIndex(index, key, length, shiftKey) {
2173
+ if (key === "ArrowRight" || key === "Tab" && !shiftKey) {
2174
+ return (index + 1) % length;
2175
+ }
2176
+ if (key === "ArrowLeft" || key === "Tab" && shiftKey) {
2177
+ return (index - 1 + length) % length;
2178
+ }
2179
+ if (key === "ArrowDown") {
2180
+ const next = index + COLUMNS;
2181
+ return next < length ? next : null;
2182
+ }
2183
+ if (key === "ArrowUp") {
2184
+ const next = index - COLUMNS;
2185
+ return next >= 0 ? next : null;
2186
+ }
2187
+ return null;
2188
+ }
2189
+ function keepCellInView(menu2, cell2) {
2190
+ const menuRect = menu2.getBoundingClientRect();
2191
+ const cellRect = cell2.getBoundingClientRect();
2192
+ if (cellRect.top < menuRect.top) menu2.scrollTop -= menuRect.top - cellRect.top;
2193
+ else if (cellRect.bottom > menuRect.bottom) {
2194
+ menu2.scrollTop += cellRect.bottom - menuRect.bottom;
2195
+ }
2196
+ }
2197
+ const EmojiSuggestionPopup = forwardRef(function EmojiSuggestionPopup2({ items, query, menuLabel, command }, ref) {
2198
+ var _a;
2199
+ const gridId = useId();
2200
+ const browsing = !query.trim();
2201
+ const [categoryId, setCategoryId] = useState(EMOJI_CATEGORIES[0].id);
2202
+ const [index, setIndex] = useState(0);
2203
+ const menuRef = useRef(null);
2204
+ const cellRefs = useRef([]);
2205
+ const categories = useMemo(
2206
+ () => EMOJI_CATEGORIES.filter((category) => itemsInCategory(items, category.id).length > 0),
2207
+ [items]
2208
+ );
2209
+ const activeId = categories.some((category) => category.id === categoryId) ? categoryId : ((_a = categories[0]) == null ? void 0 : _a.id) ?? EMOJI_CATEGORIES[0].id;
2210
+ const visible = browsing ? itemsInCategory(items, activeId) : items;
2211
+ useEffect(() => {
2212
+ var _a2;
2213
+ setIndex(0);
2214
+ (_a2 = menuRef.current) == null ? void 0 : _a2.scrollTo(0, 0);
2215
+ }, [query, activeId]);
2216
+ useEffect(() => {
2217
+ const menu2 = menuRef.current;
2218
+ const cell2 = cellRefs.current[index];
2219
+ if (menu2 && cell2) keepCellInView(menu2, cell2);
2220
+ }, [index, activeId, query]);
2221
+ useImperativeHandle(
2222
+ ref,
2223
+ () => ({
2224
+ onKeyDown(event) {
2225
+ if (!visible.length) return false;
2226
+ const next = moveIndex(index, event.key, visible.length, event.shiftKey);
2227
+ if (next !== null) {
2228
+ setIndex(next);
2229
+ return true;
2230
+ }
2231
+ if (event.key === "ArrowUp" || event.key === "ArrowDown" || event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "Tab") {
2232
+ return true;
2233
+ }
2234
+ if (event.key === "Enter") {
2235
+ const item2 = visible[index];
2236
+ if (!item2) return false;
2237
+ command(item2);
2238
+ return true;
2239
+ }
2240
+ return false;
2241
+ }
2242
+ }),
2243
+ [visible, index, command]
2244
+ );
2245
+ if (!visible.length) return null;
2246
+ return /* @__PURE__ */ jsxs("div", { className: styles$b.panel, children: [
2247
+ /* @__PURE__ */ jsx(
2248
+ "div",
2249
+ {
2250
+ id: gridId,
2251
+ ref: menuRef,
2252
+ className: styles$b.menu,
2253
+ role: "listbox",
2254
+ "aria-label": menuLabel,
2255
+ children: visible.map((item2, i) => {
2256
+ const shortcode = `:${item2.name}:`;
2257
+ return /* @__PURE__ */ jsx(
2258
+ "button",
2259
+ {
2260
+ ref: (node) => {
2261
+ cellRefs.current[i] = node;
2262
+ },
2263
+ type: "button",
2264
+ role: "option",
2265
+ "aria-label": shortcode,
2266
+ "aria-selected": i === index,
2267
+ title: shortcode,
2268
+ className: i === index ? styles$b.cellActive : styles$b.cell,
2269
+ tabIndex: -1,
2270
+ onMouseEnter: () => setIndex(i),
2271
+ onMouseDown: (event) => {
2272
+ event.preventDefault();
2273
+ command(item2);
2274
+ },
2275
+ children: item2.emoji
2276
+ },
2277
+ item2.name
2278
+ );
2279
+ })
2280
+ }
2281
+ ),
2282
+ browsing ? /* @__PURE__ */ jsx("div", { className: styles$b.tabs, role: "tablist", "aria-label": menuLabel, children: categories.map((category) => {
2283
+ const selected = category.id === activeId;
2284
+ return /* @__PURE__ */ jsx(
2285
+ "button",
2286
+ {
2287
+ type: "button",
2288
+ role: "tab",
2289
+ "aria-selected": selected,
2290
+ "aria-controls": gridId,
2291
+ "aria-label": category.label,
2292
+ title: category.label,
2293
+ className: selected ? styles$b.tabActive : styles$b.tab,
2294
+ tabIndex: -1,
2295
+ onMouseDown: (event) => {
2296
+ event.preventDefault();
2297
+ setCategoryId(category.id);
2298
+ },
2299
+ children: category.icon
2300
+ },
2301
+ category.id
2302
+ );
2303
+ }) }) : null
2304
+ ] });
2305
+ });
2306
+ function configureEmojiSuggestion(extension, enabled) {
2307
+ if (!enabled) {
2308
+ return extension.configure({
2309
+ suggestion: { allow: () => false }
2310
+ });
2311
+ }
2312
+ return extension.configure({
2313
+ suggestion: {
2314
+ pluginKey: EmojiSuggestionPluginKey,
2315
+ items: ({ editor, query }) => filterEmojiItems(editor.storage.emoji.emojis, query),
2316
+ allow: ({
2317
+ editor,
2318
+ state,
2319
+ range
2320
+ }) => {
2321
+ if (!editor.isEditable) return false;
2322
+ if (editor.isActive("code") || editor.isActive("codeBlock")) return false;
2323
+ const type = state.schema.nodes.emoji;
2324
+ if (!type) return false;
2325
+ return !!state.doc.resolve(range.from).parent.type.contentMatch.matchType(type);
2326
+ },
2327
+ render: () => {
2328
+ let renderer = null;
2329
+ let unmountPopup = null;
2330
+ return {
2331
+ onStart: (props) => {
2332
+ renderer = new ReactRenderer(EmojiSuggestionPopup, {
2333
+ editor: props.editor,
2334
+ props: {
2335
+ items: props.items,
2336
+ query: props.query,
2337
+ menuLabel: getEditorBundle(props.editor).emoji.menuLabel,
2338
+ command: props.command
2339
+ },
2340
+ className: styles$b.popupHost
2341
+ });
2342
+ copyThemeVars(props.editor.view.dom, renderer.element);
2343
+ unmountPopup = props.mount(renderer.element);
2344
+ },
2345
+ onUpdate: (props) => {
2346
+ renderer == null ? void 0 : renderer.updateProps({
2347
+ items: props.items,
2348
+ query: props.query,
2349
+ menuLabel: getEditorBundle(props.editor).emoji.menuLabel,
2350
+ command: props.command
2351
+ });
2352
+ },
2353
+ onKeyDown: (props) => {
2354
+ var _a;
2355
+ if (!renderer || isComposing$1(props.event, props.view)) return false;
2356
+ return ((_a = renderer.ref) == null ? void 0 : _a.onKeyDown(props.event)) ?? false;
2357
+ },
2358
+ onExit: () => {
2359
+ unmountPopup == null ? void 0 : unmountPopup();
2360
+ unmountPopup = null;
2361
+ renderer == null ? void 0 : renderer.destroy();
2362
+ renderer = null;
2363
+ }
2364
+ };
2365
+ }
2366
+ }
2367
+ });
2368
+ }
2369
+ const CJK_IDEOGRAPH = /[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]/g;
2370
+ function countWords(text2) {
2371
+ let cjk = 0;
2372
+ const rest = text2.replace(CJK_IDEOGRAPH, () => {
2373
+ cjk += 1;
2374
+ return " ";
2375
+ });
2376
+ const words = rest.split(/\s+/).filter((word) => /[\p{L}\p{N}]/u.test(word));
2377
+ return cjk + words.length;
2378
+ }
1742
2379
  const popupHost = "_popupHost_1noza_11";
1743
- const menu$1 = "_menu_1noza_1";
1744
- const groupLabel = "_groupLabel_1noza_43";
1745
- const item$1 = "_item_1noza_53";
1746
- const itemActive = "_itemActive_1noza_54";
1747
- const itemIcon = "_itemIcon_1noza_79";
2380
+ const menu$2 = "_menu_1noza_1";
2381
+ const groupLabel$1 = "_groupLabel_1noza_43";
2382
+ const item$2 = "_item_1noza_53";
2383
+ const itemActive$2 = "_itemActive_1noza_54";
2384
+ const itemIcon$1 = "_itemIcon_1noza_79";
1748
2385
  const itemTitle = "_itemTitle_1noza_102";
1749
- const styles$9 = {
2386
+ const styles$a = {
1750
2387
  popupHost,
1751
- menu: menu$1,
1752
- groupLabel,
1753
- item: item$1,
1754
- itemActive,
1755
- itemIcon,
2388
+ menu: menu$2,
2389
+ groupLabel: groupLabel$1,
2390
+ item: item$2,
2391
+ itemActive: itemActive$2,
2392
+ itemIcon: itemIcon$1,
1756
2393
  itemTitle
1757
2394
  };
1758
- function createDefaultSlashMenuItems(labels = defaultSlashMenuLabels) {
2395
+ function createDefaultSlashMenuItems(locale = "en") {
2396
+ const labels = getLocaleBundle(locale).slashMenu;
1759
2397
  return [
1760
2398
  {
1761
2399
  id: "normal-text",
@@ -1823,6 +2461,17 @@ function createDefaultSlashMenuItems(labels = defaultSlashMenuLabels) {
1823
2461
  editor.chain().focus().deleteRange(range).toggleBlockquote().run();
1824
2462
  }
1825
2463
  },
2464
+ {
2465
+ id: "details",
2466
+ title: labels.details,
2467
+ group: labels.groupAdvanced,
2468
+ icon: "▸",
2469
+ aliases: ["zhedie", "折叠", "toggle", "details", "collapse"],
2470
+ order: 8,
2471
+ apply: (editor, range) => {
2472
+ editor.chain().focus().deleteRange(range).setDetails().run();
2473
+ }
2474
+ },
1826
2475
  {
1827
2476
  id: "code-block",
1828
2477
  title: labels.codeBlock,
@@ -1935,11 +2584,11 @@ const SlashMenuPopup = forwardRef(function SlashMenuPopup2({ items, query, menuL
1935
2584
  );
1936
2585
  if (!items.length) return null;
1937
2586
  let optionIndex = -1;
1938
- return /* @__PURE__ */ jsx("div", { className: styles$9.menu, role: "listbox", "aria-label": menuLabel, children: withGroupHeaders(items).map(([header2, item2]) => {
2587
+ return /* @__PURE__ */ jsx("div", { className: styles$a.menu, role: "listbox", "aria-label": menuLabel, children: withGroupHeaders(items).map(([header2, item2]) => {
1939
2588
  optionIndex += 1;
1940
2589
  const i = optionIndex;
1941
2590
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
1942
- header2 !== null ? /* @__PURE__ */ jsx("div", { className: styles$9.groupLabel, "aria-hidden": "true", children: header2 }) : null,
2591
+ header2 !== null ? /* @__PURE__ */ jsx("div", { className: styles$a.groupLabel, "aria-hidden": "true", children: header2 }) : null,
1943
2592
  /* @__PURE__ */ jsxs(
1944
2593
  "button",
1945
2594
  {
@@ -1947,7 +2596,7 @@ const SlashMenuPopup = forwardRef(function SlashMenuPopup2({ items, query, menuL
1947
2596
  role: "option",
1948
2597
  "aria-selected": i === index,
1949
2598
  title: item2.title,
1950
- className: i === index ? styles$9.itemActive : styles$9.item,
2599
+ className: i === index ? styles$a.itemActive : styles$a.item,
1951
2600
  tabIndex: -1,
1952
2601
  onMouseEnter: () => setIndex(i),
1953
2602
  onMouseDown: (e2) => {
@@ -1955,8 +2604,8 @@ const SlashMenuPopup = forwardRef(function SlashMenuPopup2({ items, query, menuL
1955
2604
  command(item2);
1956
2605
  },
1957
2606
  children: [
1958
- item2.icon != null ? /* @__PURE__ */ jsx("span", { className: styles$9.itemIcon, "aria-hidden": "true", children: item2.icon }) : /* @__PURE__ */ jsx("span", { className: styles$9.itemIcon, "aria-hidden": "true" }),
1959
- /* @__PURE__ */ jsx("span", { className: styles$9.itemTitle, children: item2.title })
2607
+ item2.icon != null ? /* @__PURE__ */ jsx("span", { className: styles$a.itemIcon, "aria-hidden": "true", children: item2.icon }) : /* @__PURE__ */ jsx("span", { className: styles$a.itemIcon, "aria-hidden": "true" }),
2608
+ /* @__PURE__ */ jsx("span", { className: styles$a.itemTitle, children: item2.title })
1960
2609
  ]
1961
2610
  }
1962
2611
  )
@@ -1969,14 +2618,10 @@ function isComposing(event, view) {
1969
2618
  const SlashMenu = Extension.create({
1970
2619
  name: "slashMenu",
1971
2620
  addOptions() {
1972
- return { items: void 0, labels: void 0 };
2621
+ return { items: void 0 };
1973
2622
  },
1974
2623
  addProseMirrorPlugins() {
1975
- const { items: extraItems, labels } = this.options;
1976
- const allItems = [
1977
- ...createDefaultSlashMenuItems({ ...defaultSlashMenuLabels, ...labels }),
1978
- ...extraItems ?? []
1979
- ];
2624
+ const { items: extraItems } = this.options;
1980
2625
  let renderer = null;
1981
2626
  let unmountPopup = null;
1982
2627
  return [
@@ -1989,14 +2634,19 @@ const SlashMenu = Extension.create({
1989
2634
  allowSpaces: false,
1990
2635
  decorationClass: "tmr-slash-suggestion",
1991
2636
  decorationEmptyClass: "tmr-slash-suggestion-empty",
1992
- items: ({ query }) => filterSlashItems(allItems, query),
2637
+ items: ({ editor, query }) => filterSlashItems(
2638
+ [
2639
+ ...createDefaultSlashMenuItems(getEditorLocale(editor)),
2640
+ ...extraItems ?? []
2641
+ ],
2642
+ query
2643
+ ),
1993
2644
  command: ({ editor, range, props: item2 }) => {
1994
2645
  item2.apply(editor, range);
1995
2646
  },
1996
2647
  allow: ({ editor }) => editor.isEditable && !editor.isActive("codeBlock"),
1997
2648
  render: () => ({
1998
2649
  onStart: (props) => {
1999
- var _a;
2000
2650
  renderer = new ReactRenderer(
2001
2651
  SlashMenuPopup,
2002
2652
  {
@@ -2004,10 +2654,10 @@ const SlashMenu = Extension.create({
2004
2654
  props: {
2005
2655
  items: props.items,
2006
2656
  query: props.query,
2007
- menuLabel: ((_a = this.options.labels) == null ? void 0 : _a.menuLabel) ?? defaultSlashMenuLabels.menuLabel,
2657
+ menuLabel: getEditorBundle(props.editor).slashMenu.menuLabel,
2008
2658
  command: props.command
2009
2659
  },
2010
- className: styles$9.popupHost
2660
+ className: styles$a.popupHost
2011
2661
  }
2012
2662
  );
2013
2663
  const pmStyle = getComputedStyle(props.editor.view.dom);
@@ -2026,6 +2676,7 @@ const SlashMenu = Extension.create({
2026
2676
  renderer == null ? void 0 : renderer.updateProps({
2027
2677
  items: props.items,
2028
2678
  query: props.query,
2679
+ menuLabel: getEditorBundle(props.editor).slashMenu.menuLabel,
2029
2680
  command: props.command
2030
2681
  });
2031
2682
  },
@@ -2059,7 +2710,7 @@ const rowKeys = "_rowKeys_ljnq6_127";
2059
2710
  const rowMd = "_rowMd_ljnq6_128";
2060
2711
  const keycap = "_keycap_ljnq6_138";
2061
2712
  const none = "_none_ljnq6_163";
2062
- const styles$8 = {
2713
+ const styles$9 = {
2063
2714
  drawer,
2064
2715
  closeBtn,
2065
2716
  head,
@@ -2075,7 +2726,8 @@ const styles$8 = {
2075
2726
  keycap,
2076
2727
  none
2077
2728
  };
2078
- function buildShortcutGroups(labels) {
2729
+ function buildShortcutGroups(locale = "en") {
2730
+ const labels = getLocaleBundle(locale).shortcut;
2079
2731
  return [
2080
2732
  {
2081
2733
  id: "format",
@@ -2087,6 +2739,9 @@ function buildShortcutGroups(labels) {
2087
2739
  { id: "underline", label: labels.underline, keys: ["Mod", "u"] },
2088
2740
  { id: "inline-code", label: labels.inlineCode, keys: ["Mod", "e"], markdown: { marker: "`x`" } },
2089
2741
  { id: "highlight", label: labels.highlight, keys: ["Mod", "Shift", "h"], markdown: { marker: "==x==" } },
2742
+ { id: "smart-quote", label: labels.smartQuote, markdown: { marker: '"' } },
2743
+ { id: "ellipsis", label: labels.ellipsis, markdown: { marker: "..." } },
2744
+ { id: "em-dash", label: labels.emDash, markdown: { marker: "--" } },
2090
2745
  { id: "align-left", label: labels.alignLeft, keys: ["Mod", "Shift", "l"] },
2091
2746
  { id: "align-center", label: labels.alignCenter, keys: ["Mod", "Shift", "e"] },
2092
2747
  { id: "align-right", label: labels.alignRight, keys: ["Mod", "Shift", "r"] },
@@ -2110,7 +2765,8 @@ function buildShortcutGroups(labels) {
2110
2765
  { id: "ordered-list", label: labels.orderedList, keys: ["Mod", "Shift", "7"], markdown: { marker: "1.", terminator: "Space" } },
2111
2766
  { id: "task-list", label: labels.taskList, markdown: { marker: "[]", terminator: "Space" } },
2112
2767
  { id: "code-block", label: labels.codeBlock, markdown: { marker: "```", terminator: "Space" } },
2113
- { id: "divider", label: labels.divider, markdown: { marker: "---", terminator: "Space" } }
2768
+ { id: "divider", label: labels.divider, markdown: { marker: "---", terminator: "Space" } },
2769
+ { id: "emoji", label: labels.emoji, markdown: { marker: ":smile:" } }
2114
2770
  ]
2115
2771
  },
2116
2772
  {
@@ -2135,11 +2791,12 @@ function keycapText(key, mac) {
2135
2791
  if (/^[a-z]$/.test(key)) return key.toUpperCase();
2136
2792
  return key;
2137
2793
  }
2138
- function ShortcutPanel({ open, onClose, labels }) {
2139
- const t = useMemo(
2140
- () => ({ ...defaultShortcutLabels, ...labels }),
2141
- [labels]
2142
- );
2794
+ function ShortcutPanel({
2795
+ open,
2796
+ onClose,
2797
+ locale = "en"
2798
+ }) {
2799
+ const t = getLocaleBundle(locale).shortcut;
2143
2800
  useEffect(() => {
2144
2801
  if (!open) return;
2145
2802
  const onKey = (e2) => {
@@ -2149,15 +2806,15 @@ function ShortcutPanel({ open, onClose, labels }) {
2149
2806
  return () => document.removeEventListener("keydown", onKey);
2150
2807
  }, [open, onClose]);
2151
2808
  const groups = useMemo(
2152
- () => open ? buildShortcutGroups(t) : [],
2153
- [open, t]
2809
+ () => open ? buildShortcutGroups(locale) : [],
2810
+ [open, locale]
2154
2811
  );
2155
2812
  const mac = useMemo(isMacPlatform, []);
2156
2813
  if (!open) return null;
2157
2814
  return /* @__PURE__ */ jsxs(
2158
2815
  "aside",
2159
2816
  {
2160
- className: styles$8.drawer,
2817
+ className: styles$9.drawer,
2161
2818
  role: "dialog",
2162
2819
  "aria-modal": "false",
2163
2820
  "aria-label": t.panelTitle,
@@ -2166,27 +2823,27 @@ function ShortcutPanel({ open, onClose, labels }) {
2166
2823
  "button",
2167
2824
  {
2168
2825
  type: "button",
2169
- className: styles$8.closeBtn,
2826
+ className: styles$9.closeBtn,
2170
2827
  title: t.close,
2171
2828
  "aria-label": t.close,
2172
2829
  onClick: onClose,
2173
2830
  children: /* @__PURE__ */ jsx(XIcon, { size: 16 })
2174
2831
  }
2175
2832
  ),
2176
- /* @__PURE__ */ jsxs("div", { className: styles$8.head, children: [
2177
- /* @__PURE__ */ jsx("span", { className: styles$8.colFormat, children: t.colFormat }),
2178
- /* @__PURE__ */ jsx("span", { className: styles$8.colShortcut, children: t.colShortcut }),
2179
- /* @__PURE__ */ jsx("span", { className: styles$8.colMarkdown, children: t.colMarkdown })
2833
+ /* @__PURE__ */ jsxs("div", { className: styles$9.head, children: [
2834
+ /* @__PURE__ */ jsx("span", { className: styles$9.colFormat, children: t.colFormat }),
2835
+ /* @__PURE__ */ jsx("span", { className: styles$9.colShortcut, children: t.colShortcut }),
2836
+ /* @__PURE__ */ jsx("span", { className: styles$9.colMarkdown, children: t.colMarkdown })
2180
2837
  ] }),
2181
- /* @__PURE__ */ jsx("div", { className: styles$8.body, children: groups.map((group2) => /* @__PURE__ */ jsxs("section", { className: styles$8.group, children: [
2182
- /* @__PURE__ */ jsx("h3", { className: styles$8.groupTitle, children: group2.title }),
2183
- group2.entries.map((entry) => /* @__PURE__ */ jsxs("div", { className: styles$8.row, children: [
2184
- /* @__PURE__ */ jsx("span", { className: styles$8.rowLabel, children: entry.label }),
2185
- /* @__PURE__ */ jsx("span", { className: styles$8.rowKeys, children: entry.keys ? entry.keys.map((key, i) => /* @__PURE__ */ jsx("kbd", { className: styles$8.keycap, children: keycapText(key, mac) }, i)) : /* @__PURE__ */ jsx("span", { className: styles$8.none, children: "—" }) }),
2186
- /* @__PURE__ */ jsx("span", { className: styles$8.rowMd, children: entry.markdown ? /* @__PURE__ */ jsxs(Fragment$2, { children: [
2187
- /* @__PURE__ */ jsx("kbd", { className: styles$8.keycap, children: entry.markdown.marker }),
2188
- entry.markdown.terminator ? /* @__PURE__ */ jsx("kbd", { className: styles$8.keycap, children: entry.markdown.terminator }) : null
2189
- ] }) : /* @__PURE__ */ jsx("span", { className: styles$8.none, children: "—" }) })
2838
+ /* @__PURE__ */ jsx("div", { className: styles$9.body, children: groups.map((group2) => /* @__PURE__ */ jsxs("section", { className: styles$9.group, children: [
2839
+ /* @__PURE__ */ jsx("h3", { className: styles$9.groupTitle, children: group2.title }),
2840
+ group2.entries.map((entry) => /* @__PURE__ */ jsxs("div", { className: styles$9.row, children: [
2841
+ /* @__PURE__ */ jsx("span", { className: styles$9.rowLabel, children: entry.label }),
2842
+ /* @__PURE__ */ jsx("span", { className: styles$9.rowKeys, children: entry.keys ? entry.keys.map((key, i) => /* @__PURE__ */ jsx("kbd", { className: styles$9.keycap, children: keycapText(key, mac) }, i)) : /* @__PURE__ */ jsx("span", { className: styles$9.none, children: "—" }) }),
2843
+ /* @__PURE__ */ jsx("span", { className: styles$9.rowMd, children: entry.markdown ? /* @__PURE__ */ jsxs(Fragment$2, { children: [
2844
+ /* @__PURE__ */ jsx("kbd", { className: styles$9.keycap, children: entry.markdown.marker }),
2845
+ entry.markdown.terminator ? /* @__PURE__ */ jsx("kbd", { className: styles$9.keycap, children: entry.markdown.terminator }) : null
2846
+ ] }) : /* @__PURE__ */ jsx("span", { className: styles$9.none, children: "—" }) })
2190
2847
  ] }, entry.id))
2191
2848
  ] }, group2.id)) })
2192
2849
  ]
@@ -2270,12 +2927,12 @@ function setPendingAnchors(editor, anchors) {
2270
2927
  }
2271
2928
  function buildDecorations(doc, anchors) {
2272
2929
  const bounds = [];
2273
- doc.forEach((child, offset) => {
2274
- bounds.push({ from: offset, to: offset + child.nodeSize });
2930
+ doc.forEach((child, offset2) => {
2931
+ bounds.push({ from: offset2, to: offset2 + child.nodeSize });
2275
2932
  });
2276
2933
  const decorations = [];
2277
- for (const anchor of anchors) {
2278
- for (const range of anchor.ranges) {
2934
+ for (const anchor2 of anchors) {
2935
+ for (const range of anchor2.ranges) {
2279
2936
  const from = Math.max(0, Math.min(range.from, range.to));
2280
2937
  const to = Math.min(doc.content.size, Math.max(range.from, range.to));
2281
2938
  if (from >= to) continue;
@@ -2283,7 +2940,7 @@ function buildDecorations(doc, anchors) {
2283
2940
  if (bound.to <= from || bound.from >= to) continue;
2284
2941
  const attrs = {
2285
2942
  class: PENDING_ANCHOR_CLASS,
2286
- "data-pending-id": anchor.id
2943
+ "data-pending-id": anchor2.id
2287
2944
  };
2288
2945
  if (from <= bound.from && to >= bound.to) {
2289
2946
  decorations.push(Decoration.node(bound.from, bound.to, attrs));
@@ -2362,7 +3019,8 @@ function ChartView({
2362
3019
  }) {
2363
3020
  const canvasRef = useRef(null);
2364
3021
  const chartRef = useRef(null);
2365
- const [active2, setActive2] = useState(0);
3022
+ const [active, setActive2] = useState(0);
3023
+ const labels = useEditorBundle(editor).chart;
2366
3024
  const payload = useMemo(
2367
3025
  () => ({
2368
3026
  config: node.attrs.config ?? [],
@@ -2373,7 +3031,7 @@ function ChartView({
2373
3031
  );
2374
3032
  const theme = extension.options.chartTheme ?? null;
2375
3033
  const configs = payload.config;
2376
- const safeIndex = Math.min(active2, Math.max(0, configs.length - 1));
3034
+ const safeIndex = Math.min(active, Math.max(0, configs.length - 1));
2377
3035
  const config = configs[safeIndex];
2378
3036
  const height = (config == null ? void 0 : config.height) ?? 320;
2379
3037
  const canSelect = Boolean(editor == null ? void 0 : editor.isEditable);
@@ -2407,10 +3065,6 @@ function ChartView({
2407
3065
  chart: null
2408
3066
  });
2409
3067
  }, [safeIndex]);
2410
- const labels = {
2411
- ...defaultChartLabels,
2412
- ...extension.options.chartLabels
2413
- };
2414
3068
  const selectChart = () => {
2415
3069
  if (!editor || !canSelect) return;
2416
3070
  const pos = getPos();
@@ -2456,14 +3110,13 @@ function ChartView({
2456
3110
  );
2457
3111
  }
2458
3112
  function createChart(options = {}) {
2459
- const { editable = false, chartTheme = null, chartLabels } = options;
3113
+ const { editable = false, chartTheme = null } = options;
2460
3114
  return reportChart.extend({
2461
3115
  addOptions() {
2462
3116
  return {
2463
3117
  HTMLAttributes: {},
2464
3118
  chartEditable: editable,
2465
- chartTheme,
2466
- chartLabels
3119
+ chartTheme
2467
3120
  };
2468
3121
  },
2469
3122
  addNodeView() {
@@ -2472,7 +3125,7 @@ function createChart(options = {}) {
2472
3125
  });
2473
3126
  }
2474
3127
  const wrapper = "_wrapper_k8th1_2";
2475
- const header$1 = "_header_k8th1_18";
3128
+ const header = "_header_k8th1_18";
2476
3129
  const langTrigger = "_langTrigger_k8th1_28";
2477
3130
  const langChevron = "_langChevron_k8th1_50";
2478
3131
  const readonlyHeader = "_readonlyHeader_k8th1_56";
@@ -2490,9 +3143,9 @@ const gutterLine = "_gutterLine_k8th1_184";
2490
3143
  const readonlyActions = "_readonlyActions_k8th1_188";
2491
3144
  const actionBtn = "_actionBtn_k8th1_194";
2492
3145
  const langBraces = "_langBraces_k8th1_213";
2493
- const styles$7 = {
3146
+ const styles$8 = {
2494
3147
  wrapper,
2495
- header: header$1,
3148
+ header,
2496
3149
  langTrigger,
2497
3150
  langChevron,
2498
3151
  readonlyHeader,
@@ -2535,14 +3188,9 @@ function CodeBlockView({
2535
3188
  node,
2536
3189
  updateAttributes,
2537
3190
  deleteNode,
2538
- extension,
2539
3191
  editor
2540
3192
  }) {
2541
- var _a;
2542
- const labels = {
2543
- ...defaultCodeBlockLabels,
2544
- ...((_a = extension == null ? void 0 : extension.options) == null ? void 0 : _a.codeBlockLabels) ?? {}
2545
- };
3193
+ const labels = useEditorBundle(editor).codeBlock;
2546
3194
  const language = node.attrs.language || "";
2547
3195
  const current = LANGUAGES.find((l) => l.value === language);
2548
3196
  const currentLabel = current ? current.value === "" ? labels.autoDetect : current.label : labels.autoDetect;
@@ -2567,13 +3215,13 @@ function CodeBlockView({
2567
3215
  return () => mo.disconnect();
2568
3216
  }, [readonly2]);
2569
3217
  const handleCopy = () => {
2570
- var _a2;
3218
+ var _a;
2571
3219
  const text2 = node.textContent ?? "";
2572
3220
  const done = () => {
2573
3221
  setCopied(true);
2574
3222
  window.setTimeout(() => setCopied(false), 1500);
2575
3223
  };
2576
- if ((_a2 = navigator.clipboard) == null ? void 0 : _a2.writeText) {
3224
+ if ((_a = navigator.clipboard) == null ? void 0 : _a.writeText) {
2577
3225
  navigator.clipboard.writeText(text2).then(done, () => {
2578
3226
  });
2579
3227
  return;
@@ -2590,29 +3238,29 @@ function CodeBlockView({
2590
3238
  ta.remove();
2591
3239
  };
2592
3240
  const wrapperClass = [
2593
- styles$7.wrapper,
2594
- readonly2 ? styles$7.readonly : "",
2595
- folded2 ? styles$7.folded : ""
3241
+ styles$8.wrapper,
3242
+ readonly2 ? styles$8.readonly : "",
3243
+ folded2 ? styles$8.folded : ""
2596
3244
  ].filter(Boolean).join(" ");
2597
3245
  return /* @__PURE__ */ jsxs(NodeViewWrapper, { className: wrapperClass, children: [
2598
- editable ? /* @__PURE__ */ jsxs("div", { className: styles$7.header, contentEditable: false, children: [
3246
+ editable ? /* @__PURE__ */ jsxs("div", { className: styles$8.header, contentEditable: false, children: [
2599
3247
  /* @__PURE__ */ jsxs(DropdownMenu.Root, { children: [
2600
3248
  /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2601
3249
  "button",
2602
3250
  {
2603
3251
  type: "button",
2604
- className: styles$7.langTrigger,
2605
- "aria-label": "Code language",
3252
+ className: styles$8.langTrigger,
3253
+ "aria-label": labels.language,
2606
3254
  children: [
2607
3255
  /* @__PURE__ */ jsx("span", { children: currentLabel }),
2608
- /* @__PURE__ */ jsx(ChevronDownIcon, { size: 14, className: styles$7.langChevron })
3256
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 14, className: styles$8.langChevron })
2609
3257
  ]
2610
3258
  }
2611
3259
  ) }),
2612
3260
  /* @__PURE__ */ jsx(DropdownMenu.Portal, { children: /* @__PURE__ */ jsx(
2613
3261
  DropdownMenu.Content,
2614
3262
  {
2615
- className: styles$7.langMenu,
3263
+ className: styles$8.langMenu,
2616
3264
  sideOffset: 4,
2617
3265
  align: "end",
2618
3266
  children: LANGUAGES.map((l) => {
@@ -2621,10 +3269,10 @@ function CodeBlockView({
2621
3269
  return /* @__PURE__ */ jsxs(
2622
3270
  DropdownMenu.Item,
2623
3271
  {
2624
- className: `${styles$7.langItem}${selected ? ` ${styles$7.langItemSelected}` : ""}`,
3272
+ className: `${styles$8.langItem}${selected ? ` ${styles$8.langItemSelected}` : ""}`,
2625
3273
  onSelect: () => updateAttributes({ language: l.value }),
2626
3274
  children: [
2627
- /* @__PURE__ */ jsx("span", { className: styles$7.langItemCheck, children: selected ? /* @__PURE__ */ jsx(CheckIcon, { size: 14 }) : null }),
3275
+ /* @__PURE__ */ jsx("span", { className: styles$8.langItemCheck, children: selected ? /* @__PURE__ */ jsx(CheckIcon, { size: 14 }) : null }),
2628
3276
  optionLabel
2629
3277
  ]
2630
3278
  },
@@ -2638,7 +3286,7 @@ function CodeBlockView({
2638
3286
  "button",
2639
3287
  {
2640
3288
  type: "button",
2641
- className: styles$7.deleteBtn,
3289
+ className: styles$8.deleteBtn,
2642
3290
  title: labels.delete,
2643
3291
  "aria-label": labels.delete,
2644
3292
  onClick: () => deleteNode(),
@@ -2647,17 +3295,17 @@ function CodeBlockView({
2647
3295
  )
2648
3296
  ] }) : (
2649
3297
  // 只读头部:左侧语言标签,右侧复制 + 展开收起(展开后按钮保留,供收回)
2650
- /* @__PURE__ */ jsxs("div", { className: styles$7.readonlyHeader, contentEditable: false, children: [
2651
- /* @__PURE__ */ jsxs("span", { className: styles$7.langBadge, children: [
2652
- /* @__PURE__ */ jsx("span", { className: styles$7.langBraces, children: "{}" }),
3298
+ /* @__PURE__ */ jsxs("div", { className: styles$8.readonlyHeader, contentEditable: false, children: [
3299
+ /* @__PURE__ */ jsxs("span", { className: styles$8.langBadge, children: [
3300
+ /* @__PURE__ */ jsx("span", { className: styles$8.langBraces, children: "{}" }),
2653
3301
  currentLabel
2654
3302
  ] }),
2655
- /* @__PURE__ */ jsxs("span", { className: styles$7.readonlyActions, children: [
3303
+ /* @__PURE__ */ jsxs("span", { className: styles$8.readonlyActions, children: [
2656
3304
  /* @__PURE__ */ jsx(
2657
3305
  "button",
2658
3306
  {
2659
3307
  type: "button",
2660
- className: styles$7.actionBtn,
3308
+ className: styles$8.actionBtn,
2661
3309
  onClick: handleCopy,
2662
3310
  "aria-label": labels.copy,
2663
3311
  title: labels.copy,
@@ -2668,7 +3316,7 @@ function CodeBlockView({
2668
3316
  "button",
2669
3317
  {
2670
3318
  type: "button",
2671
- className: styles$7.actionBtn,
3319
+ className: styles$8.actionBtn,
2672
3320
  onClick: () => setFolded((v) => !v),
2673
3321
  "aria-label": folded2 ? labels.expand : labels.collapse,
2674
3322
  title: folded2 ? labels.expand : labels.collapse,
@@ -2679,28 +3327,1005 @@ function CodeBlockView({
2679
3327
  ] })
2680
3328
  ] })
2681
3329
  ),
2682
- /* @__PURE__ */ jsxs("pre", { ref: preRef, className: styles$7.pre, children: [
3330
+ /* @__PURE__ */ jsxs("pre", { ref: preRef, className: styles$8.pre, children: [
2683
3331
  readonly2 ? /* @__PURE__ */ jsx(
2684
3332
  "span",
2685
3333
  {
2686
- className: styles$7.gutter,
3334
+ className: styles$8.gutter,
2687
3335
  contentEditable: false,
2688
3336
  "aria-hidden": "true",
2689
- children: Array.from({ length: lineCount }, (_, i) => /* @__PURE__ */ jsx("span", { className: styles$7.gutterLine, children: i + 1 }, i))
3337
+ children: Array.from({ length: lineCount }, (_, i) => /* @__PURE__ */ jsx("span", { className: styles$8.gutterLine, children: i + 1 }, i))
3338
+ }
3339
+ ) : null,
3340
+ /* @__PURE__ */ jsx(NodeViewContent, { as: "code" })
3341
+ ] })
3342
+ ] });
3343
+ }
3344
+ function evaluate(value, param) {
3345
+ return typeof value === "function" ? value(param) : value;
3346
+ }
3347
+ function getSide(placement) {
3348
+ return placement.split("-")[0];
3349
+ }
3350
+ function getAlignment(placement) {
3351
+ return placement.split("-")[1];
3352
+ }
3353
+ function getSideAxis(placement) {
3354
+ const firstChar = placement[0];
3355
+ return firstChar === "t" || firstChar === "b" ? "y" : "x";
3356
+ }
3357
+ const originSides = /* @__PURE__ */ new Set(["left", "top"]);
3358
+ async function convertValueToCoords(state, options) {
3359
+ const {
3360
+ placement,
3361
+ platform,
3362
+ elements
3363
+ } = state;
3364
+ const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
3365
+ const side = getSide(placement);
3366
+ const alignment = getAlignment(placement);
3367
+ const isVertical = getSideAxis(placement) === "y";
3368
+ const mainAxisMulti = originSides.has(side) ? -1 : 1;
3369
+ const crossAxisMulti = rtl && isVertical ? -1 : 1;
3370
+ const rawValue = evaluate(options, state);
3371
+ let {
3372
+ mainAxis,
3373
+ crossAxis,
3374
+ alignmentAxis
3375
+ } = typeof rawValue === "number" ? {
3376
+ mainAxis: rawValue,
3377
+ crossAxis: 0,
3378
+ alignmentAxis: null
3379
+ } : {
3380
+ mainAxis: rawValue.mainAxis || 0,
3381
+ crossAxis: rawValue.crossAxis || 0,
3382
+ alignmentAxis: rawValue.alignmentAxis
3383
+ };
3384
+ if (alignment && typeof alignmentAxis === "number") {
3385
+ crossAxis = alignment === "end" ? alignmentAxis * -1 : alignmentAxis;
3386
+ }
3387
+ return isVertical ? {
3388
+ x: crossAxis * crossAxisMulti,
3389
+ y: mainAxis * mainAxisMulti
3390
+ } : {
3391
+ x: mainAxis * mainAxisMulti,
3392
+ y: crossAxis * crossAxisMulti
3393
+ };
3394
+ }
3395
+ const offset$1 = function(options) {
3396
+ if (options === void 0) {
3397
+ options = 0;
3398
+ }
3399
+ return {
3400
+ name: "offset",
3401
+ options,
3402
+ async fn(state) {
3403
+ var _middlewareData$offse, _middlewareData$arrow;
3404
+ const {
3405
+ x,
3406
+ y,
3407
+ placement,
3408
+ middlewareData
3409
+ } = state;
3410
+ const diffCoords = await convertValueToCoords(state, options);
3411
+ if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
3412
+ return {};
3413
+ }
3414
+ return {
3415
+ x: x + diffCoords.x,
3416
+ y: y + diffCoords.y,
3417
+ data: {
3418
+ ...diffCoords,
3419
+ placement
3420
+ }
3421
+ };
3422
+ }
3423
+ };
3424
+ };
3425
+ const offset = offset$1;
3426
+ const TURN_INTO_KINDS = [
3427
+ "paragraph",
3428
+ "heading-1",
3429
+ "heading-2",
3430
+ "heading-3",
3431
+ "bulletList",
3432
+ "orderedList",
3433
+ "taskList",
3434
+ "blockquote",
3435
+ "codeBlock"
3436
+ ];
3437
+ const TURNABLE = /* @__PURE__ */ new Set([
3438
+ "paragraph",
3439
+ "heading",
3440
+ "bulletList",
3441
+ "orderedList",
3442
+ "taskList",
3443
+ "listItem",
3444
+ "taskItem",
3445
+ "blockquote",
3446
+ "codeBlock"
3447
+ ]);
3448
+ const LIFT_BEFORE_TURN = /* @__PURE__ */ new Set([
3449
+ "listItem",
3450
+ "taskItem",
3451
+ "bulletList",
3452
+ "orderedList",
3453
+ "taskList",
3454
+ "blockquote",
3455
+ "codeBlock"
3456
+ ]);
3457
+ function canTurnBlockInto(node) {
3458
+ return !!node && TURNABLE.has(node.type.name);
3459
+ }
3460
+ function currentTurnIntoKind(editor, pos, node) {
3461
+ const name = node.type.name;
3462
+ if (name === "paragraph") return "paragraph";
3463
+ if (name === "heading") {
3464
+ const level = Number(node.attrs.level);
3465
+ if (level === 1 || level === 2 || level === 3) {
3466
+ return `heading-${level}`;
3467
+ }
3468
+ return null;
3469
+ }
3470
+ if (name === "bulletList") return "bulletList";
3471
+ if (name === "orderedList") return "orderedList";
3472
+ if (name === "taskList") return "taskList";
3473
+ if (name === "blockquote") return "blockquote";
3474
+ if (name === "codeBlock") return "codeBlock";
3475
+ if (name === "listItem" || name === "taskItem") {
3476
+ const parent = editor.state.doc.resolve(pos).parent.type.name;
3477
+ if (parent === "bulletList") return "bulletList";
3478
+ if (parent === "orderedList") return "orderedList";
3479
+ if (parent === "taskList") return "taskList";
3480
+ }
3481
+ return null;
3482
+ }
3483
+ function firstTextPos(node, pos) {
3484
+ if (node.isTextblock) return pos + 1;
3485
+ let found = null;
3486
+ node.descendants((child, offset2) => {
3487
+ if (found != null) return false;
3488
+ if (child.isTextblock) {
3489
+ found = pos + 1 + offset2 + 1;
3490
+ return false;
3491
+ }
3492
+ return true;
3493
+ });
3494
+ return found;
3495
+ }
3496
+ function turnBlockInto(editor, pos, kind) {
3497
+ const node = editor.state.doc.nodeAt(pos);
3498
+ if (!node || !canTurnBlockInto(node)) return false;
3499
+ const textPos = firstTextPos(node, pos);
3500
+ if (textPos == null) return false;
3501
+ const chain = editor.chain().setTextSelection(textPos);
3502
+ if (LIFT_BEFORE_TURN.has(node.type.name)) chain.clearNodes();
3503
+ if (kind === "heading-1" || kind === "heading-2" || kind === "heading-3") {
3504
+ const level = Number(kind.slice(-1));
3505
+ chain.setHeading({ level });
3506
+ } else if (kind === "paragraph") {
3507
+ if (!LIFT_BEFORE_TURN.has(node.type.name)) chain.setParagraph();
3508
+ } else if (kind === "bulletList") {
3509
+ chain.toggleBulletList();
3510
+ } else if (kind === "orderedList") {
3511
+ chain.toggleOrderedList();
3512
+ } else if (kind === "taskList") {
3513
+ chain.toggleTaskList();
3514
+ } else if (kind === "blockquote") {
3515
+ chain.toggleBlockquote();
3516
+ } else if (kind === "codeBlock") {
3517
+ chain.setCodeBlock();
3518
+ }
3519
+ return chain.run();
3520
+ }
3521
+ function duplicateBlock(editor, pos) {
3522
+ const node = editor.state.doc.nodeAt(pos);
3523
+ if (!node) return false;
3524
+ return editor.chain().insertContentAt(pos + node.nodeSize, node.toJSON()).run();
3525
+ }
3526
+ function deleteBlock(editor, pos) {
3527
+ const node = editor.state.doc.nodeAt(pos);
3528
+ if (!node) return false;
3529
+ let from = pos;
3530
+ let to = pos + node.nodeSize;
3531
+ const $pos = editor.state.doc.resolve(pos);
3532
+ const parent = $pos.parent;
3533
+ if ((node.type.name === "listItem" || node.type.name === "taskItem") && parent.childCount === 1) {
3534
+ from = pos - $pos.parentOffset - 1;
3535
+ const list2 = editor.state.doc.nodeAt(from);
3536
+ if (list2) to = from + list2.nodeSize;
3537
+ }
3538
+ if (from <= 0 && to >= editor.state.doc.content.size) {
3539
+ return editor.chain().insertContentAt(
3540
+ { from: 0, to: editor.state.doc.content.size },
3541
+ { type: "paragraph" }
3542
+ ).run();
3543
+ }
3544
+ return editor.chain().deleteRange({ from, to }).run();
3545
+ }
3546
+ function blockMarkdown(editor, pos) {
3547
+ var _a;
3548
+ const node = editor.state.doc.nodeAt(pos);
3549
+ if (!node) return null;
3550
+ const serialized = (_a = editor.markdown) == null ? void 0 : _a.serialize(node.toJSON());
3551
+ if (typeof serialized === "string") return serialized;
3552
+ return node.textContent;
3553
+ }
3554
+ function canResetBlockFormatting(node) {
3555
+ if (!node || node.isAtom) return false;
3556
+ if (node.type.name === "image" || node.type.name === "horizontalRule") {
3557
+ return false;
3558
+ }
3559
+ if (node.isTextblock) return true;
3560
+ let found = false;
3561
+ node.descendants((child) => {
3562
+ if (child.isTextblock) {
3563
+ found = true;
3564
+ return false;
3565
+ }
3566
+ return true;
3567
+ });
3568
+ return found;
3569
+ }
3570
+ function withoutBlockStyles(node) {
3571
+ const next = { ...node.attrs };
3572
+ if ("textAlign" in next) next.textAlign = null;
3573
+ if ("indent" in next) next.indent = null;
3574
+ if ("lineHeight" in next) next.lineHeight = null;
3575
+ return next;
3576
+ }
3577
+ function resetBlockFormatting(editor, pos) {
3578
+ const node = editor.state.doc.nodeAt(pos);
3579
+ if (!node || !canResetBlockFormatting(node)) return false;
3580
+ const from = pos + 1;
3581
+ const to = pos + node.nodeSize - 1;
3582
+ let tr = editor.state.tr;
3583
+ if (to > from) {
3584
+ for (const mark of Object.values(editor.schema.marks)) {
3585
+ tr = tr.removeMark(from, to, mark);
3586
+ }
3587
+ }
3588
+ const markup = [];
3589
+ if (node.isTextblock) {
3590
+ markup.push({ pos, attrs: withoutBlockStyles(node) });
3591
+ }
3592
+ node.descendants((child, offset2) => {
3593
+ if (!child.isTextblock) return;
3594
+ markup.push({
3595
+ pos: pos + 1 + offset2,
3596
+ attrs: withoutBlockStyles(child)
3597
+ });
3598
+ });
3599
+ for (const item2 of markup) {
3600
+ tr = tr.setNodeMarkup(item2.pos, void 0, item2.attrs);
3601
+ }
3602
+ if (!tr.docChanged) return false;
3603
+ editor.view.dispatch(tr);
3604
+ return true;
3605
+ }
3606
+ function isImageBlock(node) {
3607
+ return (node == null ? void 0 : node.type.name) === "image" && typeof node.attrs.src === "string" && node.attrs.src.length > 0;
3608
+ }
3609
+ function downloadImageBlock(node) {
3610
+ var _a;
3611
+ if (!isImageBlock(node)) return;
3612
+ const src = node.attrs.src;
3613
+ const alt = typeof node.attrs.alt === "string" ? node.attrs.alt.trim() : "";
3614
+ const fromUrl = ((_a = src.split("/").pop()) == null ? void 0 : _a.split("?")[0]) ?? "";
3615
+ const a3 = document.createElement("a");
3616
+ a3.href = src;
3617
+ a3.download = alt || fromUrl || "image";
3618
+ a3.rel = "noopener";
3619
+ a3.target = "_blank";
3620
+ document.body.appendChild(a3);
3621
+ a3.click();
3622
+ a3.remove();
3623
+ }
3624
+ const LIST_NAMES = /* @__PURE__ */ new Set(["bulletList", "orderedList", "taskList"]);
3625
+ const draggingViews = /* @__PURE__ */ new WeakSet();
3626
+ const blockDragListGuardKey = new PluginKey("blockDragListGuard");
3627
+ function setBlockHandleDragging(view, dragging) {
3628
+ if (dragging) draggingViews.add(view);
3629
+ else draggingViews.delete(view);
3630
+ }
3631
+ function isBlockHandleDragging(view) {
3632
+ return draggingViews.has(view);
3633
+ }
3634
+ function outermostListDepth(doc, pos) {
3635
+ const safe = Math.max(0, Math.min(pos, doc.content.size));
3636
+ const $pos = doc.resolve(safe);
3637
+ let listDepth = -1;
3638
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
3639
+ if (LIST_NAMES.has($pos.node(depth).type.name)) listDepth = depth;
3640
+ }
3641
+ return listDepth;
3642
+ }
3643
+ function isPosInsideList(doc, pos) {
3644
+ return outermostListDepth(doc, pos) > 0;
3645
+ }
3646
+ function listEscapeEdge(view, pos, clientY) {
3647
+ const listDepth = outermostListDepth(view.state.doc, pos);
3648
+ if (listDepth < 0) return null;
3649
+ const $pos = view.state.doc.resolve(
3650
+ Math.max(0, Math.min(pos, view.state.doc.content.size))
3651
+ );
3652
+ const start = $pos.before(listDepth);
3653
+ const node = $pos.node(listDepth);
3654
+ const dom = view.nodeDOM(start);
3655
+ let after = pos >= start + node.nodeSize / 2;
3656
+ if (dom instanceof HTMLElement) {
3657
+ const rect = dom.getBoundingClientRect();
3658
+ if (rect.height > 0) after = clientY >= rect.top + rect.height / 2;
3659
+ }
3660
+ return after ? start + node.nodeSize : start;
3661
+ }
3662
+ function moveDraggedSlice(view, slice, insertPos) {
3663
+ const { state } = view;
3664
+ const { from, to } = state.selection;
3665
+ if (insertPos > from && insertPos < to) return true;
3666
+ const tr = state.tr;
3667
+ tr.deleteSelection();
3668
+ const pos = tr.mapping.map(insertPos, 1);
3669
+ const block = slice.openStart === 0 && slice.openEnd === 0 && slice.content.childCount === 1 ? slice.content.firstChild : null;
3670
+ if (block) tr.replaceRangeWith(pos, pos, block);
3671
+ else tr.replaceRange(pos, pos, slice);
3672
+ if (tr.doc.eq(state.doc)) return true;
3673
+ const $pos = tr.doc.resolve(Math.max(0, Math.min(pos, tr.doc.content.size)));
3674
+ const near = TextSelection.findFrom($pos, 1, true) ?? TextSelection.findFrom($pos, -1, true);
3675
+ if (near) tr.setSelection(near);
3676
+ try {
3677
+ view.focus();
3678
+ } catch {
3679
+ }
3680
+ view.dispatch(tr.setMeta("uiEvent", "drop").scrollIntoView());
3681
+ return true;
3682
+ }
3683
+ function snappedListEdge(view, clientX, clientY, slice) {
3684
+ const coords = view.posAtCoords({ left: clientX, top: clientY });
3685
+ if (!coords) return null;
3686
+ const natural = dropPoint(view.state.doc, coords.pos, slice);
3687
+ const probe = natural ?? coords.pos;
3688
+ if (!isPosInsideList(view.state.doc, probe)) return null;
3689
+ return listEscapeEdge(view, probe, clientY);
3690
+ }
3691
+ function placeBlockDropCursor(view, pos) {
3692
+ const parent = view.dom.offsetParent;
3693
+ if (!(parent instanceof HTMLElement)) return;
3694
+ const cursor = parent.querySelector(
3695
+ ".prosemirror-dropcursor-block, .prosemirror-dropcursor-inline"
3696
+ );
3697
+ if (!(cursor instanceof HTMLElement)) return;
3698
+ const $pos = view.state.doc.resolve(pos);
3699
+ const before = $pos.nodeBefore;
3700
+ const anchorPos = before ? pos - before.nodeSize : pos;
3701
+ const anchor2 = view.nodeDOM(anchorPos);
3702
+ if (!(anchor2 instanceof HTMLElement)) return;
3703
+ const anchorRect = anchor2.getBoundingClientRect();
3704
+ let lineTop = before ? anchorRect.bottom : anchorRect.top;
3705
+ if (before && $pos.nodeAfter) {
3706
+ const next = view.nodeDOM(pos);
3707
+ if (next instanceof HTMLElement) {
3708
+ lineTop = (anchorRect.bottom + next.getBoundingClientRect().top) / 2;
3709
+ }
3710
+ }
3711
+ const editorRect = view.dom.getBoundingClientRect();
3712
+ const scaleX = editorRect.width / view.dom.offsetWidth || 1;
3713
+ const scaleY = editorRect.height / view.dom.offsetHeight || 1;
3714
+ const parentRect = parent.getBoundingClientRect();
3715
+ const parentScaleX = parentRect.width / parent.offsetWidth || 1;
3716
+ const parentScaleY = parentRect.height / parent.offsetHeight || 1;
3717
+ const parentLeft = parentRect.left - parent.scrollLeft * parentScaleX;
3718
+ const parentTop = parentRect.top - parent.scrollTop * parentScaleY;
3719
+ const half = scaleY;
3720
+ cursor.classList.add("prosemirror-dropcursor-block");
3721
+ cursor.classList.remove("prosemirror-dropcursor-inline");
3722
+ cursor.style.left = `${(anchorRect.left - parentLeft) / scaleX}px`;
3723
+ cursor.style.top = `${(lineTop - half - parentTop) / scaleY}px`;
3724
+ cursor.style.width = `${(anchorRect.right - anchorRect.left) / scaleX}px`;
3725
+ cursor.style.height = `${2 * half / scaleY}px`;
3726
+ }
3727
+ function blockDragListGuardPlugin() {
3728
+ return new Plugin({
3729
+ key: blockDragListGuardKey,
3730
+ props: {
3731
+ handleDrop(view, event, slice, moved) {
3732
+ if (!moved || !isBlockHandleDragging(view)) return false;
3733
+ const edge = snappedListEdge(view, event.clientX, event.clientY, slice);
3734
+ if (edge == null) return false;
3735
+ moveDraggedSlice(view, slice, edge);
3736
+ return true;
3737
+ }
3738
+ },
3739
+ view(editorView) {
3740
+ const onDragOver = (event) => {
3741
+ var _a;
3742
+ const slice = (_a = editorView.dragging) == null ? void 0 : _a.slice;
3743
+ if (!slice || !isBlockHandleDragging(editorView)) return;
3744
+ const edge = snappedListEdge(
3745
+ editorView,
3746
+ event.clientX,
3747
+ event.clientY,
3748
+ slice
3749
+ );
3750
+ if (edge == null) return;
3751
+ placeBlockDropCursor(editorView, edge);
3752
+ };
3753
+ editorView.dom.addEventListener("dragover", onDragOver);
3754
+ return {
3755
+ destroy() {
3756
+ editorView.dom.removeEventListener("dragover", onDragOver);
3757
+ setBlockHandleDragging(editorView, false);
3758
+ }
3759
+ };
3760
+ }
3761
+ });
3762
+ }
3763
+ const cluster = "_cluster_5edcs_4";
3764
+ const clusterOnTable = "_clusterOnTable_5edcs_24";
3765
+ const button = "_button_5edcs_28";
3766
+ const grip = "_grip_5edcs_50";
3767
+ const menu$1 = "_menu_5edcs_61";
3768
+ const groupLabel = "_groupLabel_5edcs_84";
3769
+ const divider$3 = "_divider_5edcs_94";
3770
+ const item$1 = "_item_5edcs_100";
3771
+ const itemActive$1 = "_itemActive_5edcs_118";
3772
+ const itemDanger = "_itemDanger_5edcs_123";
3773
+ const itemIcon = "_itemIcon_5edcs_132";
3774
+ const styles$7 = {
3775
+ cluster,
3776
+ clusterOnTable,
3777
+ button,
3778
+ grip,
3779
+ menu: menu$1,
3780
+ groupLabel,
3781
+ divider: divider$3,
3782
+ item: item$1,
3783
+ itemActive: itemActive$1,
3784
+ itemDanger,
3785
+ itemIcon
3786
+ };
3787
+ const HANDLE_POSITION = {
3788
+ placement: "left-start",
3789
+ strategy: "absolute",
3790
+ middleware: [offset({ mainAxis: -6, crossAxis: 4 })]
3791
+ };
3792
+ const TABLE_ANCHOR_LIFT = 24;
3793
+ const THEME_VARS = [
3794
+ "--tmr-text",
3795
+ "--tmr-accent",
3796
+ "--tmr-toolbar-border",
3797
+ "--tmr-toolbar-muted",
3798
+ "--tmr-popover-bg",
3799
+ "--tmr-danger",
3800
+ "--tmr-code-bg"
3801
+ ];
3802
+ function lockDragHandle(editor, locked) {
3803
+ if (editor.isDestroyed) return;
3804
+ editor.view.dispatch(
3805
+ editor.state.tr.setMeta("lockDragHandle", locked).setMeta("addToHistory", false)
3806
+ );
3807
+ }
3808
+ async function copyMarkdown(markdown) {
3809
+ try {
3810
+ await navigator.clipboard.writeText(markdown);
3811
+ return;
3812
+ } catch {
3813
+ }
3814
+ const area = document.createElement("textarea");
3815
+ area.value = markdown;
3816
+ area.setAttribute("readonly", "");
3817
+ area.style.position = "fixed";
3818
+ area.style.left = "-9999px";
3819
+ document.body.appendChild(area);
3820
+ area.select();
3821
+ document.execCommand("copy");
3822
+ area.remove();
3823
+ }
3824
+ const TURN_ICON = {
3825
+ paragraph: "¶",
3826
+ "heading-1": "H1",
3827
+ "heading-2": "H2",
3828
+ "heading-3": "H3",
3829
+ bulletList: "•",
3830
+ orderedList: "1.",
3831
+ taskList: "✓",
3832
+ blockquote: "❝",
3833
+ codeBlock: "{ }"
3834
+ };
3835
+ function BlockDragHandle({ editor }) {
3836
+ const t = useEditorBundle(editor).blockDrag;
3837
+ const [target, setTarget] = useState(null);
3838
+ const [menu2, setMenu] = useState(null);
3839
+ const draggedRef = useRef(false);
3840
+ const targetRef = useRef(null);
3841
+ const menuRef = useRef(null);
3842
+ const closeMenu = useCallback(() => {
3843
+ setMenu(null);
3844
+ lockDragHandle(editor, false);
3845
+ }, [editor]);
3846
+ useEffect(() => {
3847
+ const plugin = blockDragListGuardPlugin();
3848
+ editor.registerPlugin(plugin);
3849
+ return () => {
3850
+ setBlockHandleDragging(editor.view, false);
3851
+ if (!editor.isDestroyed) editor.unregisterPlugin(blockDragListGuardKey);
3852
+ };
3853
+ }, [editor]);
3854
+ useEffect(() => {
3855
+ if (!menu2) return;
3856
+ const onKey = (event) => {
3857
+ if (event.key !== "Escape") return;
3858
+ event.preventDefault();
3859
+ closeMenu();
3860
+ };
3861
+ const onDown = (event) => {
3862
+ const el = event.target;
3863
+ if (!(el instanceof Element)) return;
3864
+ if (el.closest("[data-block-drag-menu], [data-block-drag-grip]")) return;
3865
+ closeMenu();
3866
+ };
3867
+ const onScroll = () => closeMenu();
3868
+ document.addEventListener("keydown", onKey);
3869
+ document.addEventListener("mousedown", onDown);
3870
+ document.addEventListener("scroll", onScroll, true);
3871
+ return () => {
3872
+ document.removeEventListener("keydown", onKey);
3873
+ document.removeEventListener("mousedown", onDown);
3874
+ document.removeEventListener("scroll", onScroll, true);
3875
+ };
3876
+ }, [menu2, closeMenu]);
3877
+ useEffect(() => {
3878
+ if (!menu2 || !menuRef.current) return;
3879
+ const style = getComputedStyle(editor.view.dom);
3880
+ for (const name of THEME_VARS) {
3881
+ const value = style.getPropertyValue(name);
3882
+ if (value) menuRef.current.style.setProperty(name, value);
3883
+ }
3884
+ }, [menu2, editor]);
3885
+ useEffect(() => () => lockDragHandle(editor, false), [editor, closeMenu]);
3886
+ const openMenu = (anchor2) => {
3887
+ if (!target) return;
3888
+ const rect = anchor2.getBoundingClientRect();
3889
+ const estimated = 380;
3890
+ const y = rect.top + estimated > window.innerHeight ? Math.max(8, window.innerHeight - estimated - 8) : rect.top;
3891
+ const x = Math.min(rect.right + 6, window.innerWidth - 220);
3892
+ lockDragHandle(editor, true);
3893
+ setMenu({ x, y, pos: target.pos, node: target.node });
3894
+ };
3895
+ const run = (action) => {
3896
+ action();
3897
+ editor.commands.focus();
3898
+ closeMenu();
3899
+ };
3900
+ const activeKind = menu2 ? currentTurnIntoKind(editor, menu2.pos, menu2.node) : null;
3901
+ const showTurn = menu2 ? canTurnBlockInto(menu2.node) : false;
3902
+ const showReset = menu2 ? canResetBlockFormatting(menu2.node) : false;
3903
+ const showDownload = menu2 ? isImageBlock(menu2.node) : false;
3904
+ const turnLabel = (kind) => {
3905
+ if (kind === "paragraph") return t.paragraph;
3906
+ if (kind === "heading-1") return t.headingLabel(1);
3907
+ if (kind === "heading-2") return t.headingLabel(2);
3908
+ if (kind === "heading-3") return t.headingLabel(3);
3909
+ if (kind === "bulletList") return t.bulletList;
3910
+ if (kind === "orderedList") return t.orderedList;
3911
+ if (kind === "taskList") return t.taskList;
3912
+ if (kind === "blockquote") return t.blockquote;
3913
+ return t.codeBlock;
3914
+ };
3915
+ return /* @__PURE__ */ jsxs(Fragment$2, { children: [
3916
+ /* @__PURE__ */ jsx(
3917
+ DragHandle,
3918
+ {
3919
+ editor,
3920
+ computePositionConfig: HANDLE_POSITION,
3921
+ onNodeChange: ({ node, pos }) => {
3922
+ if (!node || pos < 0) {
3923
+ targetRef.current = null;
3924
+ setTarget(null);
3925
+ return;
3926
+ }
3927
+ const next = { node, pos };
3928
+ targetRef.current = next;
3929
+ setTarget(next);
3930
+ },
3931
+ getReferencedVirtualElement: () => {
3932
+ const current = targetRef.current;
3933
+ if (!current || current.node.type.name !== "table") return null;
3934
+ const pos = current.pos;
3935
+ return {
3936
+ getBoundingClientRect: () => {
3937
+ let dom = null;
3938
+ try {
3939
+ dom = editor.view.nodeDOM(pos);
3940
+ } catch {
3941
+ dom = null;
3942
+ }
3943
+ if (!(dom instanceof HTMLElement)) return new DOMRect();
3944
+ const rect = dom.getBoundingClientRect();
3945
+ return new DOMRect(
3946
+ rect.x,
3947
+ rect.y - TABLE_ANCHOR_LIFT,
3948
+ rect.width,
3949
+ rect.height
3950
+ );
3951
+ }
3952
+ };
3953
+ },
3954
+ onElementDragStart: () => {
3955
+ draggedRef.current = true;
3956
+ setBlockHandleDragging(editor.view, true);
3957
+ },
3958
+ onElementDragEnd: () => {
3959
+ setBlockHandleDragging(editor.view, false);
3960
+ setTimeout(() => {
3961
+ draggedRef.current = false;
3962
+ }, 0);
3963
+ },
3964
+ children: /* @__PURE__ */ jsx(
3965
+ "div",
3966
+ {
3967
+ className: `${styles$7.cluster} ${(target == null ? void 0 : target.node.type.name) === "table" ? styles$7.clusterOnTable : ""}`,
3968
+ "data-block-drag": "",
3969
+ children: /* @__PURE__ */ jsx(
3970
+ "div",
3971
+ {
3972
+ role: "button",
3973
+ tabIndex: 0,
3974
+ className: `${styles$7.button} ${styles$7.grip}`,
3975
+ "data-block-drag-grip": "",
3976
+ title: t.dragHandle,
3977
+ "aria-label": t.dragHandle,
3978
+ "aria-haspopup": "menu",
3979
+ "aria-expanded": menu2 != null,
3980
+ onKeyDown: (event) => {
3981
+ if (event.key !== "Enter" && event.key !== " ") return;
3982
+ event.preventDefault();
3983
+ if (menu2) closeMenu();
3984
+ else openMenu(event.currentTarget);
3985
+ },
3986
+ onClick: (event) => {
3987
+ if (draggedRef.current) return;
3988
+ if (menu2) {
3989
+ closeMenu();
3990
+ return;
3991
+ }
3992
+ openMenu(event.currentTarget);
3993
+ },
3994
+ children: /* @__PURE__ */ jsx(GripIcon, { size: 14 })
3995
+ }
3996
+ )
3997
+ }
3998
+ )
3999
+ }
4000
+ ),
4001
+ menu2 ? createPortal(
4002
+ /* @__PURE__ */ jsxs(
4003
+ "div",
4004
+ {
4005
+ ref: menuRef,
4006
+ className: styles$7.menu,
4007
+ "data-block-drag-menu": "",
4008
+ role: "menu",
4009
+ "aria-label": t.menuLabel,
4010
+ style: { left: menu2.x, top: menu2.y },
4011
+ onMouseDown: (event) => event.stopPropagation(),
4012
+ children: [
4013
+ showTurn ? /* @__PURE__ */ jsxs(Fragment$2, { children: [
4014
+ /* @__PURE__ */ jsx("div", { className: styles$7.groupLabel, children: t.turnInto }),
4015
+ TURN_INTO_KINDS.map((kind) => /* @__PURE__ */ jsxs(
4016
+ "button",
4017
+ {
4018
+ type: "button",
4019
+ role: "menuitem",
4020
+ className: kind === activeKind ? `${styles$7.item} ${styles$7.itemActive}` : styles$7.item,
4021
+ "data-block-drag-action": kind,
4022
+ onClick: () => run(() => turnBlockInto(editor, menu2.pos, kind)),
4023
+ children: [
4024
+ /* @__PURE__ */ jsx("span", { className: styles$7.itemIcon, "aria-hidden": true, children: TURN_ICON[kind] }),
4025
+ /* @__PURE__ */ jsx("span", { children: turnLabel(kind) })
4026
+ ]
4027
+ },
4028
+ kind
4029
+ )),
4030
+ /* @__PURE__ */ jsx("div", { className: styles$7.divider })
4031
+ ] }) : null,
4032
+ /* @__PURE__ */ jsxs(
4033
+ "button",
4034
+ {
4035
+ type: "button",
4036
+ role: "menuitem",
4037
+ className: styles$7.item,
4038
+ "data-block-drag-action": "copy",
4039
+ onClick: () => run(() => {
4040
+ const markdown = blockMarkdown(editor, menu2.pos);
4041
+ if (markdown != null) void copyMarkdown(markdown);
4042
+ }),
4043
+ children: [
4044
+ /* @__PURE__ */ jsx("span", { className: styles$7.itemIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx(CopyIcon, {}) }),
4045
+ /* @__PURE__ */ jsx("span", { children: t.copy })
4046
+ ]
4047
+ }
4048
+ ),
4049
+ /* @__PURE__ */ jsxs(
4050
+ "button",
4051
+ {
4052
+ type: "button",
4053
+ role: "menuitem",
4054
+ className: styles$7.item,
4055
+ "data-block-drag-action": "duplicate",
4056
+ onClick: () => run(() => duplicateBlock(editor, menu2.pos)),
4057
+ children: [
4058
+ /* @__PURE__ */ jsx("span", { className: styles$7.itemIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx(CopyIcon, {}) }),
4059
+ /* @__PURE__ */ jsx("span", { children: t.duplicate })
4060
+ ]
4061
+ }
4062
+ ),
4063
+ showReset ? /* @__PURE__ */ jsxs(
4064
+ "button",
4065
+ {
4066
+ type: "button",
4067
+ role: "menuitem",
4068
+ className: styles$7.item,
4069
+ "data-block-drag-action": "reset",
4070
+ onClick: () => run(() => resetBlockFormatting(editor, menu2.pos)),
4071
+ children: [
4072
+ /* @__PURE__ */ jsx("span", { className: styles$7.itemIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx(EraserIcon, {}) }),
4073
+ /* @__PURE__ */ jsx("span", { children: t.resetFormatting })
4074
+ ]
4075
+ }
4076
+ ) : null,
4077
+ showDownload ? /* @__PURE__ */ jsxs(
4078
+ "button",
4079
+ {
4080
+ type: "button",
4081
+ role: "menuitem",
4082
+ className: styles$7.item,
4083
+ "data-block-drag-action": "download",
4084
+ onClick: () => run(() => downloadImageBlock(menu2.node)),
4085
+ children: [
4086
+ /* @__PURE__ */ jsx("span", { className: styles$7.itemIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx(DownloadIcon, {}) }),
4087
+ /* @__PURE__ */ jsx("span", { children: t.downloadImage })
4088
+ ]
4089
+ }
4090
+ ) : null,
4091
+ /* @__PURE__ */ jsx("div", { className: styles$7.divider }),
4092
+ /* @__PURE__ */ jsxs(
4093
+ "button",
4094
+ {
4095
+ type: "button",
4096
+ role: "menuitem",
4097
+ className: `${styles$7.item} ${styles$7.itemDanger}`,
4098
+ "data-block-drag-action": "delete",
4099
+ onClick: () => run(() => deleteBlock(editor, menu2.pos)),
4100
+ children: [
4101
+ /* @__PURE__ */ jsx("span", { className: styles$7.itemIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx(TrashIcon, {}) }),
4102
+ /* @__PURE__ */ jsx("span", { children: t.delete })
4103
+ ]
4104
+ }
4105
+ )
4106
+ ]
2690
4107
  }
2691
- ) : null,
2692
- /* @__PURE__ */ jsx(NodeViewContent, { as: "code" })
2693
- ] })
4108
+ ),
4109
+ document.body
4110
+ ) : null
2694
4111
  ] });
2695
4112
  }
2696
- const CodeBlock = CodeBlockLowlight.extend({
2697
- addOptions() {
2698
- var _a;
2699
- return {
2700
- ...(_a = this.parent) == null ? void 0 : _a.call(this),
2701
- codeBlockLabels: void 0
4113
+ const anchor = "_anchor_1b977_4";
4114
+ const nav = "_nav_1b977_15";
4115
+ const navOpen = "_navOpen_1b977_16";
4116
+ const list = "_list_1b977_58";
4117
+ const barButton = "_barButton_1b977_64";
4118
+ const bar$1 = "_bar_1b977_64";
4119
+ const barActive = "_barActive_1b977_78";
4120
+ const item = "_item_1b977_89";
4121
+ const itemActive = "_itemActive_1b977_110";
4122
+ const itemText = "_itemText_1b977_117";
4123
+ const styles$6 = {
4124
+ anchor,
4125
+ nav,
4126
+ navOpen,
4127
+ list,
4128
+ barButton,
4129
+ bar: bar$1,
4130
+ barActive,
4131
+ item,
4132
+ itemActive,
4133
+ itemText
4134
+ };
4135
+ function barWidth(level) {
4136
+ if (level <= 1) return 16;
4137
+ if (level === 2) return 12;
4138
+ if (level === 3) return 8;
4139
+ return 6;
4140
+ }
4141
+ function findScrollParent(start) {
4142
+ let node = start.parentElement;
4143
+ while (node && node !== document.documentElement) {
4144
+ const style = getComputedStyle(node);
4145
+ const overflowY = style.overflowY;
4146
+ const canScroll = overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay";
4147
+ if (canScroll && (node.scrollHeight > node.clientHeight + 1 || style.maxHeight !== "none")) {
4148
+ return node;
4149
+ }
4150
+ node = node.parentElement;
4151
+ }
4152
+ return document.scrollingElement ?? document.documentElement;
4153
+ }
4154
+ function isViewportScroller(node) {
4155
+ return node === document.documentElement || node === document.body || node === document.scrollingElement;
4156
+ }
4157
+ function EditorToc({ items, editorDom, locale = "en" }) {
4158
+ var _a;
4159
+ const t = getLocaleBundle(locale).toc;
4160
+ const [open, setOpen] = useState(false);
4161
+ const [activeId, setActiveId] = useState(((_a = items[0]) == null ? void 0 : _a.id) ?? "");
4162
+ const [roving, setRoving] = useState(0);
4163
+ const navRef = useRef(null);
4164
+ const itemRefs = useRef([]);
4165
+ const hideTimer = useRef(null);
4166
+ const clearHide = () => {
4167
+ if (hideTimer.current !== null) {
4168
+ window.clearTimeout(hideTimer.current);
4169
+ hideTimer.current = null;
4170
+ }
4171
+ };
4172
+ const show = () => {
4173
+ clearHide();
4174
+ setOpen(true);
4175
+ };
4176
+ const hideSoon = () => {
4177
+ clearHide();
4178
+ hideTimer.current = window.setTimeout(() => {
4179
+ var _a2;
4180
+ hideTimer.current = null;
4181
+ if ((_a2 = navRef.current) == null ? void 0 : _a2.contains(document.activeElement)) return;
4182
+ setOpen(false);
4183
+ }, 80);
4184
+ };
4185
+ useEffect(() => () => clearHide(), []);
4186
+ useEffect(() => {
4187
+ const headings = items.map(
4188
+ (item2) => editorDom.querySelector(
4189
+ `[data-toc-id="${CSS.escape(item2.id)}"]`
4190
+ )
4191
+ ).filter((el) => el !== null);
4192
+ if (!headings.length) return;
4193
+ const scrollParent = findScrollParent(editorDom);
4194
+ const viewport = isViewportScroller(scrollParent);
4195
+ const visible = /* @__PURE__ */ new Set();
4196
+ const apply2 = () => {
4197
+ const rootTop = viewport ? 0 : scrollParent.getBoundingClientRect().top;
4198
+ let best = null;
4199
+ let bestTop = Infinity;
4200
+ for (const el of visible) {
4201
+ const top = el.getBoundingClientRect().top;
4202
+ if (top < bestTop) {
4203
+ bestTop = top;
4204
+ best = el;
4205
+ }
4206
+ }
4207
+ if (!best) {
4208
+ let last = null;
4209
+ for (const heading of headings) {
4210
+ if (heading.getBoundingClientRect().top <= rootTop + 12) last = heading;
4211
+ }
4212
+ best = last ?? headings[0];
4213
+ }
4214
+ const id = best.getAttribute("data-toc-id");
4215
+ if (id) setActiveId(id);
2702
4216
  };
2703
- },
4217
+ const observer = new IntersectionObserver(
4218
+ (entries) => {
4219
+ for (const entry of entries) {
4220
+ if (entry.isIntersecting) visible.add(entry.target);
4221
+ else visible.delete(entry.target);
4222
+ }
4223
+ apply2();
4224
+ },
4225
+ {
4226
+ root: viewport ? null : scrollParent,
4227
+ rootMargin: "0px 0px -60% 0px",
4228
+ threshold: [0, 1]
4229
+ }
4230
+ );
4231
+ for (const heading of headings) observer.observe(heading);
4232
+ const onScroll = () => apply2();
4233
+ const scrollTarget = viewport ? window : scrollParent;
4234
+ scrollTarget.addEventListener("scroll", onScroll, { passive: true });
4235
+ apply2();
4236
+ return () => {
4237
+ observer.disconnect();
4238
+ scrollTarget.removeEventListener("scroll", onScroll);
4239
+ };
4240
+ }, [items, editorDom]);
4241
+ useEffect(() => {
4242
+ var _a2;
4243
+ if ((_a2 = navRef.current) == null ? void 0 : _a2.contains(document.activeElement)) return;
4244
+ const index = items.findIndex((item2) => item2.id === activeId);
4245
+ if (index >= 0) setRoving(index);
4246
+ }, [activeId, items]);
4247
+ useEffect(() => {
4248
+ var _a2, _b;
4249
+ if (!open || !activeId) return;
4250
+ const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
4251
+ (_b = (_a2 = navRef.current) == null ? void 0 : _a2.querySelector(`[data-toc-item="${CSS.escape(activeId)}"]`)) == null ? void 0 : _b.scrollIntoView({ block: "nearest", behavior: reduce ? "auto" : "smooth" });
4252
+ }, [activeId, open]);
4253
+ const jump = (item2) => {
4254
+ setActiveId(item2.id);
4255
+ scrollToTocHeading(item2.id, findScrollParent(editorDom));
4256
+ };
4257
+ const move = (delta) => {
4258
+ var _a2;
4259
+ const next = Math.min(items.length - 1, Math.max(0, roving + delta));
4260
+ setRoving(next);
4261
+ setOpen(true);
4262
+ (_a2 = itemRefs.current[next]) == null ? void 0 : _a2.focus();
4263
+ };
4264
+ return /* @__PURE__ */ jsx("div", { className: styles$6.anchor, children: /* @__PURE__ */ jsx(
4265
+ "nav",
4266
+ {
4267
+ ref: navRef,
4268
+ className: open ? styles$6.navOpen : styles$6.nav,
4269
+ "aria-label": t.title,
4270
+ "data-editor-toc": "",
4271
+ onMouseEnter: show,
4272
+ onMouseLeave: hideSoon,
4273
+ onFocus: show,
4274
+ onBlur: (event) => {
4275
+ if (!event.currentTarget.contains(event.relatedTarget)) hideSoon();
4276
+ },
4277
+ onKeyDown: (event) => {
4278
+ if (event.key === "ArrowDown") {
4279
+ event.preventDefault();
4280
+ move(1);
4281
+ } else if (event.key === "ArrowUp") {
4282
+ event.preventDefault();
4283
+ move(-1);
4284
+ } else if (event.key === "Escape") {
4285
+ setOpen(false);
4286
+ }
4287
+ },
4288
+ children: /* @__PURE__ */ jsx("ul", { className: styles$6.list, children: items.map((item2, index) => {
4289
+ const active = item2.id === activeId;
4290
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
4291
+ "button",
4292
+ {
4293
+ type: "button",
4294
+ ref: (node) => {
4295
+ itemRefs.current[index] = node;
4296
+ },
4297
+ "data-toc-item": item2.id,
4298
+ tabIndex: index === roving ? 0 : -1,
4299
+ className: open ? `${styles$6.item} ${active ? styles$6.itemActive : ""}` : styles$6.barButton,
4300
+ style: open ? { paddingLeft: `${(item2.level - 1) * 12 + 10}px` } : void 0,
4301
+ "aria-current": active ? "true" : void 0,
4302
+ "aria-label": item2.text,
4303
+ onClick: () => jump(item2),
4304
+ children: open ? /* @__PURE__ */ jsx("span", { className: styles$6.itemText, children: item2.text }) : /* @__PURE__ */ jsx(
4305
+ "span",
4306
+ {
4307
+ className: active ? styles$6.barActive : styles$6.bar,
4308
+ style: { width: barWidth(item2.level) }
4309
+ }
4310
+ )
4311
+ }
4312
+ ) }, item2.id);
4313
+ }) })
4314
+ }
4315
+ ) });
4316
+ }
4317
+ function useIsMobile(breakpoint = 768) {
4318
+ const [isMobile, setIsMobile] = useState(false);
4319
+ useEffect(() => {
4320
+ const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
4321
+ const update = () => setIsMobile(mq.matches);
4322
+ update();
4323
+ mq.addEventListener("change", update);
4324
+ return () => mq.removeEventListener("change", update);
4325
+ }, [breakpoint]);
4326
+ return isMobile;
4327
+ }
4328
+ const CodeBlock = CodeBlockLowlight.extend({
2704
4329
  // Built-in `code` tokens often win over chart's custom fence tokenizer;
2705
4330
  // upgrade ```tmr-chart here so the mid-column card editor renders ChartView.
2706
4331
  parseMarkdown: (token, helpers) => parseCodeTokenAsChartOrCodeBlock(token, helpers, "codeBlock"),
@@ -2846,35 +4471,74 @@ const ImageWithConfirmDelete = Image.extend({
2846
4471
  }
2847
4472
  });
2848
4473
  const DEFAULT_FIND_BAR_OFFSET = { top: 4, right: 4 };
2849
- function findBarOffsetStyle(offset) {
4474
+ function findBarOffsetStyle(offset2) {
2850
4475
  const px = (v) => typeof v === "number" ? `${v}px` : v;
2851
4476
  return {
2852
4477
  position: "absolute",
2853
- top: px(offset.top),
2854
- right: px(offset.right),
2855
- bottom: px(offset.bottom),
2856
- left: px(offset.left)
4478
+ top: px(offset2.top),
4479
+ right: px(offset2.right),
4480
+ bottom: px(offset2.bottom),
4481
+ left: px(offset2.left)
2857
4482
  };
2858
4483
  }
4484
+ function CharacterCountStatus({
4485
+ editor,
4486
+ locale
4487
+ }) {
4488
+ const t = getLocaleBundle(locale).characterCount;
4489
+ const counts = useEditorState({
4490
+ editor,
4491
+ selector: ({ editor: current }) => {
4492
+ const storage = current == null ? void 0 : current.storage.characterCount;
4493
+ if (!storage) return { characters: 0, words: 0 };
4494
+ return {
4495
+ characters: storage.characters(),
4496
+ words: storage.words()
4497
+ };
4498
+ }
4499
+ });
4500
+ return /* @__PURE__ */ jsxs(
4501
+ "div",
4502
+ {
4503
+ className: styles$e.charCount,
4504
+ role: "group",
4505
+ "aria-label": t.label,
4506
+ "data-characters": counts.characters,
4507
+ "data-words": counts.words,
4508
+ children: [
4509
+ /* @__PURE__ */ jsx("span", { children: t.characters(counts.characters) }),
4510
+ /* @__PURE__ */ jsx("span", { className: styles$e.charCountSep, "aria-hidden": "true", children: "·" }),
4511
+ /* @__PURE__ */ jsx("span", { children: t.words(counts.words) })
4512
+ ]
4513
+ }
4514
+ );
4515
+ }
2859
4516
  function editorOwnsKeyboard(editor) {
2860
- const active2 = document.activeElement;
2861
- const inEditor = !!active2 && editor.view.dom.contains(active2);
4517
+ const active = document.activeElement;
4518
+ const inEditor = !!active && editor.view.dom.contains(active);
2862
4519
  if (inEditor || editor.isFocused) return true;
2863
- const nothingFocused = active2 === null || active2 === document.body;
4520
+ const nothingFocused = active === null || active === document.body;
2864
4521
  return nothingFocused && document.querySelectorAll(".ProseMirror").length <= 1;
2865
4522
  }
4523
+ function sameTocItems(a3, b3) {
4524
+ if (a3.length !== b3.length) return false;
4525
+ return a3.every(
4526
+ (item2, index) => item2.id === b3[index].id && item2.level === b3[index].level && item2.text === b3[index].text
4527
+ );
4528
+ }
2866
4529
  const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
2867
4530
  initialMarkdown = "",
2868
4531
  editable = true,
4532
+ locale = "en",
2869
4533
  sources,
2870
4534
  renderCitation,
2871
4535
  placeholder,
2872
4536
  onEditorReady,
2873
4537
  onTocChange,
4538
+ toc = true,
2874
4539
  markdownPaste = true,
2875
4540
  markdownFileDrop = true,
2876
4541
  extraExtensions,
2877
- codeBlockLabels,
2878
4542
  className,
2879
4543
  comments,
2880
4544
  activeCommentId,
@@ -2890,26 +4554,35 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
2890
4554
  findBarContainer,
2891
4555
  findBarOffset = DEFAULT_FIND_BAR_OFFSET,
2892
4556
  findShortcut = true,
2893
- findLabels,
2894
4557
  onFindOpenChange,
2895
4558
  slashMenu = true,
2896
- slashMenuLabels,
4559
+ typography = true,
4560
+ emojiSuggestion = true,
4561
+ blockDrag = true,
2897
4562
  shortcutPanel = true,
2898
- shortcutLabels,
2899
4563
  shortcutFabContainer,
2900
4564
  imageUpload,
2901
- imageResize = true
4565
+ imageResize = true,
4566
+ characterCount = false
2902
4567
  }, ref) {
2903
4568
  const preparedInitial = prepareChartMarkdown(
2904
4569
  enrichMarkdownCitations(initialMarkdown, sources ?? [])
2905
4570
  );
4571
+ const blockDragMobile = useIsMobile(768);
4572
+ const showBlockDrag = blockDrag && editable && !blockDragMobile;
2906
4573
  const [findOpen, setFindOpen] = useState(false);
2907
4574
  const [shortcutsOpen, setShortcutsOpen] = useState(false);
4575
+ const [tocItems, setTocItems] = useState([]);
2908
4576
  const findInputRef = useRef(null);
4577
+ const onTocChangeRef = useRef(onTocChange);
4578
+ onTocChangeRef.current = onTocChange;
4579
+ const tocItemsRef = useRef([]);
2909
4580
  const editor = useEditor({
2910
4581
  extensions: [
2911
- ...baseExtensions,
2912
- CodeBlock.configure({ lowlight, codeBlockLabels }),
4582
+ ...baseExtensions.map(
4583
+ (ext) => ext.name === "emoji" ? configureEmojiSuggestion(ext, emojiSuggestion) : ext
4584
+ ),
4585
+ CodeBlock.configure({ lowlight }),
2913
4586
  ImageWithConfirmDelete.configure({
2914
4587
  inline: false,
2915
4588
  // 图片缩放(默认开、默认等比、默认左右两条手柄):false 关掉;对象透传官方配置
@@ -2950,18 +4623,36 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
2950
4623
  // - searchDebounceMs 关掉:官方防抖走 setTimeout,抛错会落在异步回调里兜不住;
2951
4624
  // 防抖改由浮动条自己做(见 findReplace.ts)。
2952
4625
  ...findReplace ? [FindAndReplace.configure({ injectCSS: false, searchDebounceMs: 0 })] : [],
4626
+ // 失焦选区:MIT 的 Selection。非空文本选区失焦后打上 .tmr-blur-selection,
4627
+ // 样式在 content.module.css。节点选区(图片、代码块整块)官方不保留。
4628
+ Selection$1.configure({ className: "tmr-blur-selection" }),
4629
+ // 字数统计:MIT 的 @tiptap/extensions CharacterCount(不是 @tiptap-pro)。
4630
+ // 只调用它的 storage,统计条是本库自绘。无 limit,不裁剪正文。
4631
+ // 词数换成自写的 countWords,否则整段中文会被默认的按空格切分算成 1 个词。
4632
+ ...characterCount ? [CharacterCount.configure({ wordCounter: countWords })] : [],
2953
4633
  TableOfContents.configure({
2954
4634
  getId: makeTocGetId(),
4635
+ // 官方扩展在滚动时也会 onUpdate(只为刷新 isActive)。目录项没变就不通知,
4636
+ // 否则每次滚动都 setState。回调走 ref:扩展只在创建时绑一次。
2955
4637
  onUpdate: (anchors) => {
2956
- onTocChange == null ? void 0 : onTocChange(
2957
- anchors.filter((a3) => a3.level <= 6).map((a3) => ({ id: a3.id, level: a3.level, text: a3.textContent }))
2958
- );
4638
+ var _a;
4639
+ const next = anchors.filter((a3) => a3.originalLevel <= 6 && a3.textContent.trim()).map((a3) => ({
4640
+ id: a3.id,
4641
+ level: a3.originalLevel,
4642
+ text: a3.textContent
4643
+ }));
4644
+ if (sameTocItems(tocItemsRef.current, next)) return;
4645
+ tocItemsRef.current = next;
4646
+ setTocItems(next);
4647
+ (_a = onTocChangeRef.current) == null ? void 0 : _a.call(onTocChangeRef, next);
2959
4648
  }
2960
4649
  }),
2961
4650
  ...markdownPaste ? [MarkdownPaste] : [],
2962
4651
  ...markdownFileDrop ? [MarkdownFileDrop] : [],
2963
4652
  // 斜杠菜单(键入 / 唤起):默认开,只读态由 suggestion 状态机自身短路
2964
- ...slashMenu ? [SlashMenu.configure({ labels: slashMenuLabels })] : [],
4653
+ ...slashMenu ? [SlashMenu] : [],
4654
+ // 智能标点:输入规则,不增加节点,所以不进 baseExtensions。
4655
+ ...typography ? [Typography] : [],
2965
4656
  ...extraExtensions ?? []
2966
4657
  ],
2967
4658
  content: preparedInitial,
@@ -2971,10 +4662,11 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
2971
4662
  immediatelyRender: false,
2972
4663
  editorProps: {
2973
4664
  attributes: {
2974
- class: styles$c.editorContent
4665
+ class: styles$e.editorContent
2975
4666
  }
2976
4667
  }
2977
4668
  });
4669
+ usePublishEditorLocale(editor, locale);
2978
4670
  useEffect(() => {
2979
4671
  onEditorReady == null ? void 0 : onEditorReady(editor);
2980
4672
  return () => onEditorReady == null ? void 0 : onEditorReady(null);
@@ -3167,22 +4859,19 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
3167
4859
  FindReplaceBar,
3168
4860
  {
3169
4861
  editor,
3170
- labels: findLabels,
4862
+ locale,
3171
4863
  onClose: closeFind,
3172
4864
  inputRef: findInputRef,
3173
- className: styles$c.findBar,
4865
+ className: styles$e.findBar,
3174
4866
  style: findBarOffsetStyle(findBarOffset)
3175
4867
  }
3176
4868
  ) : null;
3177
- const shortcutT = useMemo(
3178
- () => ({ ...defaultShortcutLabels, ...shortcutLabels }),
3179
- [shortcutLabels]
3180
- );
4869
+ const shortcutT = getLocaleBundle(locale).shortcut;
3181
4870
  const [shortcutFabTarget, setShortcutFabTarget] = useState(
3182
4871
  null
3183
4872
  );
3184
- const useIsoLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
3185
- useIsoLayoutEffect(() => {
4873
+ const useIsoLayoutEffect2 = typeof window === "undefined" ? useEffect : useLayoutEffect;
4874
+ useIsoLayoutEffect2(() => {
3186
4875
  const target = typeof shortcutFabContainer === "function" ? shortcutFabContainer() : shortcutFabContainer ?? null;
3187
4876
  setShortcutFabTarget((prev) => prev === target ? prev : target);
3188
4877
  });
@@ -3190,7 +4879,7 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
3190
4879
  "button",
3191
4880
  {
3192
4881
  type: "button",
3193
- className: shortcutFabTarget ? `${styles$c.shortcutFab} ${styles$c.shortcutFabHosted}` : styles$c.shortcutFab,
4882
+ className: shortcutFabTarget ? `${styles$e.shortcutFab} ${styles$e.shortcutFabHosted}` : styles$e.shortcutFab,
3194
4883
  title: shortcutT.panelTitle,
3195
4884
  "aria-label": shortcutT.panelTitle,
3196
4885
  "aria-expanded": shortcutsOpen,
@@ -3198,32 +4887,58 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
3198
4887
  children: /* @__PURE__ */ jsx(KeyboardIcon, { size: 18 })
3199
4888
  }
3200
4889
  ) : null;
3201
- return /* @__PURE__ */ jsxs("div", { className: styles$c.editorHost, children: [
3202
- findBarNode && !findBarTarget ? /* @__PURE__ */ jsx("div", { className: styles$c.findBarAnchor, children: findBarNode }) : null,
3203
- findBarNode && findBarTarget ? createPortal(findBarNode, findBarTarget) : null,
3204
- /* @__PURE__ */ jsx(
3205
- EditorContent,
3206
- {
3207
- editor,
3208
- className: className ? `${styles$c.editorScroll} ${className}` : styles$c.editorScroll
3209
- }
3210
- ),
3211
- shortcutFabNode && shortcutFabTarget ? createPortal(shortcutFabNode, shortcutFabTarget) : shortcutFabNode,
3212
- shortcutPanel && editable ? /* @__PURE__ */ jsx(
3213
- ShortcutPanel,
3214
- {
3215
- open: shortcutsOpen,
3216
- onClose: () => setShortcutsOpen(false),
3217
- labels: shortcutLabels
3218
- }
3219
- ) : null
3220
- ] });
4890
+ return /* @__PURE__ */ jsxs(
4891
+ "div",
4892
+ {
4893
+ className: styles$e.editorHost,
4894
+ "data-block-drag-gutter": showBlockDrag ? "" : void 0,
4895
+ children: [
4896
+ findBarNode && !findBarTarget ? /* @__PURE__ */ jsx("div", { className: styles$e.findBarAnchor, children: findBarNode }) : null,
4897
+ findBarNode && findBarTarget ? createPortal(findBarNode, findBarTarget) : null,
4898
+ editor && toc && !blockDragMobile && tocItems.length > 0 ? /* @__PURE__ */ jsx(
4899
+ EditorToc,
4900
+ {
4901
+ items: tocItems,
4902
+ editorDom: editor.view.dom,
4903
+ locale
4904
+ }
4905
+ ) : null,
4906
+ /* @__PURE__ */ jsx(
4907
+ EditorContent,
4908
+ {
4909
+ editor,
4910
+ className: [
4911
+ styles$e.editorScroll,
4912
+ showBlockDrag ? styles$e.withBlockDrag : "",
4913
+ toc && !blockDragMobile && tocItems.length > 0 ? styles$e.withToc : "",
4914
+ className ?? ""
4915
+ ].filter(Boolean).join(" ")
4916
+ }
4917
+ ),
4918
+ editor && showBlockDrag ? /* @__PURE__ */ jsx(BlockDragHandle, { editor }) : null,
4919
+ editor && characterCount ? /* @__PURE__ */ jsxs("div", { className: styles$e.editorStatus, children: [
4920
+ /* @__PURE__ */ jsx(CharacterCountStatus, { editor, locale }),
4921
+ shortcutFabNode && !shortcutFabTarget ? shortcutFabNode : null
4922
+ ] }) : shortcutFabNode && !shortcutFabTarget ? shortcutFabNode : null,
4923
+ shortcutFabNode && shortcutFabTarget ? createPortal(shortcutFabNode, shortcutFabTarget) : null,
4924
+ shortcutPanel && editable ? /* @__PURE__ */ jsx(
4925
+ ShortcutPanel,
4926
+ {
4927
+ open: shortcutsOpen,
4928
+ onClose: () => setShortcutsOpen(false),
4929
+ locale
4930
+ }
4931
+ ) : null
4932
+ ]
4933
+ }
4934
+ );
3221
4935
  });
3222
4936
  function MarkdownPreview({
3223
4937
  markdown,
3224
4938
  sources,
3225
4939
  renderCitation,
3226
- className
4940
+ className,
4941
+ locale = "en"
3227
4942
  }) {
3228
4943
  const prepared = useMemo(
3229
4944
  () => prepareChartMarkdown(
@@ -3258,11 +4973,12 @@ function MarkdownPreview({
3258
4973
  editable: false,
3259
4974
  immediatelyRender: false,
3260
4975
  editorProps: {
3261
- attributes: { class: styles$c.editorContent }
4976
+ attributes: { class: styles$e.editorContent }
3262
4977
  }
3263
4978
  },
3264
4979
  [extensions]
3265
4980
  );
4981
+ usePublishEditorLocale(editor, locale);
3266
4982
  useEffect(() => {
3267
4983
  if (!editor) return;
3268
4984
  editor.commands.setContent(prepared, { contentType: "markdown" });
@@ -3271,7 +4987,7 @@ function MarkdownPreview({
3271
4987
  EditorContent,
3272
4988
  {
3273
4989
  editor,
3274
- className: className ?? styles$c.editorScroll
4990
+ className: className ?? styles$e.editorScroll
3275
4991
  }
3276
4992
  );
3277
4993
  }
@@ -3343,46 +5059,58 @@ function splitTopLevelBlocks(markdown) {
3343
5059
  function stripToPlainText(markdown) {
3344
5060
  return markdown.replace(/!\[[^\]]*\]\([^)]+\)/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/^#{1,6}\s+/gm, "").replace(/^[ \t]*[-*+]\s+/gm, "").replace(/^[ \t]*\d+\.\s+/gm, "").replace(/[*_~`]+/g, "").replace(/<[^>]+>/g, "").replace(/\|/g, " ").replace(/\s+/g, " ").trim();
3345
5061
  }
3346
- const toolbar = "_toolbar_fvk6u_2";
3347
- const inner = "_inner_fvk6u_15";
3348
- const btn$2 = "_btn_fvk6u_35";
3349
- const btnActive$1 = "_btnActive_fvk6u_58";
3350
- const txtIcon = "_txtIcon_fvk6u_74";
3351
- const colorIcon = "_colorIcon_fvk6u_82";
3352
- const colorIconGlyph = "_colorIconGlyph_fvk6u_90";
3353
- const colorIconBar = "_colorIconBar_fvk6u_96";
3354
- const scriptTrigger = "_scriptTrigger_fvk6u_103";
3355
- const scriptTriggerGlyph = "_scriptTriggerGlyph_fvk6u_123";
3356
- const divider$2 = "_divider_fvk6u_131";
3357
- const styleTrigger = "_styleTrigger_fvk6u_140";
3358
- const styleTriggerLabel = "_styleTriggerLabel_fvk6u_174";
3359
- const styleTriggerCaret = "_styleTriggerCaret_fvk6u_183";
3360
- const iconTrigger = "_iconTrigger_fvk6u_190";
3361
- const styleItem = "_styleItem_fvk6u_198";
3362
- const styleIcon = "_styleIcon_fvk6u_204";
3363
- const scriptGlyph = "_scriptGlyph_fvk6u_214";
3364
- const menu = "_menu_fvk6u_226";
3365
- const menuItem = "_menuItem_fvk6u_237";
3366
- const menuItemSelected = "_menuItemSelected_fvk6u_264";
3367
- const tableInsertCaret = "_tableInsertCaret_fvk6u_277";
3368
- const tableSizePicker = "_tableSizePicker_fvk6u_285";
3369
- const tableSizeGrid = "_tableSizeGrid_fvk6u_295";
3370
- const tableSizeCell = "_tableSizeCell_fvk6u_300";
3371
- const tableSizeCellActive = "_tableSizeCellActive_fvk6u_310";
3372
- const tableSizeLabel = "_tableSizeLabel_fvk6u_315";
3373
- const popoverContent$1 = "_popoverContent_fvk6u_324";
3374
- const mathLayer = "_mathLayer_fvk6u_328";
3375
- const mathStack = "_mathStack_fvk6u_333";
3376
- const mathStackBlock = "_mathStackBlock_fvk6u_340";
3377
- const mathHint = "_mathHint_fvk6u_345";
3378
- const mathHintBlock = "_mathHintBlock_fvk6u_357";
3379
- const mathHintIcon = "_mathHintIcon_fvk6u_363";
3380
- const mathField = "_mathField_fvk6u_394";
3381
- const mathFieldBlock = "_mathFieldBlock_fvk6u_406";
3382
- const mathInput = "_mathInput_fvk6u_413";
3383
- const mathDone = "_mathDone_fvk6u_431";
3384
- const mathDoneKbd = "_mathDoneKbd_fvk6u_456";
3385
- const styles$6 = {
5062
+ const toolbar = "_toolbar_1l6t0_2";
5063
+ const inner = "_inner_1l6t0_15";
5064
+ const btn$2 = "_btn_1l6t0_35";
5065
+ const btnActive$1 = "_btnActive_1l6t0_58";
5066
+ const txtIcon = "_txtIcon_1l6t0_74";
5067
+ const colorIcon = "_colorIcon_1l6t0_82";
5068
+ const colorIconGlyph = "_colorIconGlyph_1l6t0_90";
5069
+ const colorIconBar = "_colorIconBar_1l6t0_96";
5070
+ const scriptTrigger = "_scriptTrigger_1l6t0_103";
5071
+ const scriptTriggerGlyph = "_scriptTriggerGlyph_1l6t0_123";
5072
+ const divider$2 = "_divider_1l6t0_131";
5073
+ const styleTrigger = "_styleTrigger_1l6t0_140";
5074
+ const styleTriggerLabel = "_styleTriggerLabel_1l6t0_174";
5075
+ const styleTriggerCaret = "_styleTriggerCaret_1l6t0_183";
5076
+ const iconTrigger = "_iconTrigger_1l6t0_190";
5077
+ const styleItem = "_styleItem_1l6t0_198";
5078
+ const styleIcon = "_styleIcon_1l6t0_204";
5079
+ const scriptGlyph = "_scriptGlyph_1l6t0_214";
5080
+ const menu = "_menu_1l6t0_226";
5081
+ const menuItem = "_menuItem_1l6t0_237";
5082
+ const menuItemSelected = "_menuItemSelected_1l6t0_264";
5083
+ const listSplit = "_listSplit_1l6t0_279";
5084
+ const listSplitActive = "_listSplitActive_1l6t0_285";
5085
+ const numberingCaret = "_numberingCaret_1l6t0_297";
5086
+ const numberingCaretActive = "_numberingCaretActive_1l6t0_327";
5087
+ const numberingMenu = "_numberingMenu_1l6t0_331";
5088
+ const numberingGrid = "_numberingGrid_1l6t0_341";
5089
+ const numberingOption = "_numberingOption_1l6t0_347";
5090
+ const numberingOptionActive = "_numberingOptionActive_1l6t0_362";
5091
+ const numberingPreview = "_numberingPreview_1l6t0_367";
5092
+ const numberingPreviewRow = "_numberingPreviewRow_1l6t0_373";
5093
+ const numberingPreviewMarker = "_numberingPreviewMarker_1l6t0_388";
5094
+ const numberingPreviewLine = "_numberingPreviewLine_1l6t0_396";
5095
+ const tableInsertCaret = "_tableInsertCaret_1l6t0_402";
5096
+ const tableSizePicker = "_tableSizePicker_1l6t0_410";
5097
+ const tableSizeGrid = "_tableSizeGrid_1l6t0_420";
5098
+ const tableSizeCell = "_tableSizeCell_1l6t0_425";
5099
+ const tableSizeCellActive = "_tableSizeCellActive_1l6t0_435";
5100
+ const tableSizeLabel = "_tableSizeLabel_1l6t0_440";
5101
+ const popoverContent$1 = "_popoverContent_1l6t0_449";
5102
+ const mathLayer = "_mathLayer_1l6t0_453";
5103
+ const mathStack = "_mathStack_1l6t0_458";
5104
+ const mathStackBlock = "_mathStackBlock_1l6t0_465";
5105
+ const mathHint = "_mathHint_1l6t0_470";
5106
+ const mathHintBlock = "_mathHintBlock_1l6t0_482";
5107
+ const mathHintIcon = "_mathHintIcon_1l6t0_488";
5108
+ const mathField = "_mathField_1l6t0_519";
5109
+ const mathFieldBlock = "_mathFieldBlock_1l6t0_531";
5110
+ const mathInput = "_mathInput_1l6t0_538";
5111
+ const mathDone = "_mathDone_1l6t0_556";
5112
+ const mathDoneKbd = "_mathDoneKbd_1l6t0_581";
5113
+ const styles$5 = {
3386
5114
  toolbar,
3387
5115
  inner,
3388
5116
  btn: btn$2,
@@ -3404,6 +5132,18 @@ const styles$6 = {
3404
5132
  menu,
3405
5133
  menuItem,
3406
5134
  menuItemSelected,
5135
+ listSplit,
5136
+ listSplitActive,
5137
+ numberingCaret,
5138
+ numberingCaretActive,
5139
+ numberingMenu,
5140
+ numberingGrid,
5141
+ numberingOption,
5142
+ numberingOptionActive,
5143
+ numberingPreview,
5144
+ numberingPreviewRow,
5145
+ numberingPreviewMarker,
5146
+ numberingPreviewLine,
3407
5147
  tableInsertCaret,
3408
5148
  tableSizePicker,
3409
5149
  tableSizeGrid,
@@ -3432,7 +5172,7 @@ const swatch = "_swatch_x5lrq_54";
3432
5172
  const swatchActive = "_swatchActive_x5lrq_70";
3433
5173
  const themeLabel = "_themeLabel_x5lrq_76";
3434
5174
  const themeRow = "_themeRow_x5lrq_84";
3435
- const styles$5 = {
5175
+ const styles$4 = {
3436
5176
  palette,
3437
5177
  noneRow,
3438
5178
  noneIcon,
@@ -3452,28 +5192,28 @@ const PALETTE = [
3452
5192
  ["#5c1010", "#700818", "#7c4808", "#7c6808", "#205818", "#10403c", "#183c78", "#0c3060", "#3c1460", "#601838"]
3453
5193
  ];
3454
5194
  const THEME_COLORS = ["#ff6719", "#ff5500"];
3455
- function ColorPalette({ value, onPick, labels }) {
3456
- const t = { ...defaultColorPaletteLabels, ...labels };
5195
+ function ColorPalette({ value, onPick, locale = "en" }) {
5196
+ const t = getLocaleBundle(locale).palette;
3457
5197
  const current = value == null ? void 0 : value.toLowerCase();
3458
- return /* @__PURE__ */ jsxs("div", { className: styles$5.palette, children: [
5198
+ return /* @__PURE__ */ jsxs("div", { className: styles$4.palette, children: [
3459
5199
  /* @__PURE__ */ jsxs(
3460
5200
  "button",
3461
5201
  {
3462
5202
  type: "button",
3463
- className: styles$5.noneRow,
5203
+ className: styles$4.noneRow,
3464
5204
  onMouseDown: (e2) => e2.preventDefault(),
3465
5205
  onClick: () => onPick(null),
3466
5206
  children: [
3467
- /* @__PURE__ */ jsx("span", { className: styles$5.noneIcon, "aria-hidden": true }),
3468
- /* @__PURE__ */ jsx("span", { className: styles$5.noneLabel, children: t.none })
5207
+ /* @__PURE__ */ jsx("span", { className: styles$4.noneIcon, "aria-hidden": true }),
5208
+ /* @__PURE__ */ jsx("span", { className: styles$4.noneLabel, children: t.none })
3469
5209
  ]
3470
5210
  }
3471
5211
  ),
3472
- /* @__PURE__ */ jsx("div", { className: styles$5.grid, children: PALETTE.flat().map((c) => /* @__PURE__ */ jsx(
5212
+ /* @__PURE__ */ jsx("div", { className: styles$4.grid, children: PALETTE.flat().map((c) => /* @__PURE__ */ jsx(
3473
5213
  "button",
3474
5214
  {
3475
5215
  type: "button",
3476
- className: `${styles$5.swatch} ${current === c.toLowerCase() ? styles$5.swatchActive : ""}`,
5216
+ className: `${styles$4.swatch} ${current === c.toLowerCase() ? styles$4.swatchActive : ""}`,
3477
5217
  style: { background: c },
3478
5218
  title: c,
3479
5219
  "aria-label": c,
@@ -3482,12 +5222,12 @@ function ColorPalette({ value, onPick, labels }) {
3482
5222
  },
3483
5223
  c
3484
5224
  )) }),
3485
- /* @__PURE__ */ jsx("div", { className: styles$5.themeLabel, children: t.theme }),
3486
- /* @__PURE__ */ jsx("div", { className: styles$5.themeRow, children: THEME_COLORS.map((c) => /* @__PURE__ */ jsx(
5225
+ /* @__PURE__ */ jsx("div", { className: styles$4.themeLabel, children: t.theme }),
5226
+ /* @__PURE__ */ jsx("div", { className: styles$4.themeRow, children: THEME_COLORS.map((c) => /* @__PURE__ */ jsx(
3487
5227
  "button",
3488
5228
  {
3489
5229
  type: "button",
3490
- className: `${styles$5.swatch} ${current === c.toLowerCase() ? styles$5.swatchActive : ""}`,
5230
+ className: `${styles$4.swatch} ${current === c.toLowerCase() ? styles$4.swatchActive : ""}`,
3491
5231
  style: { background: c },
3492
5232
  title: c,
3493
5233
  "aria-label": c,
@@ -3518,7 +5258,7 @@ const captionRow = "_captionRow_mp2o5_13";
3518
5258
  const captionInput = "_captionInput_mp2o5_40";
3519
5259
  const btn$1 = "_btn_mp2o5_58";
3520
5260
  const btnActive = "_btnActive_mp2o5_76";
3521
- const styles$4 = {
5261
+ const styles$3 = {
3522
5262
  bar,
3523
5263
  divider: divider$1,
3524
5264
  captionRow,
@@ -3636,7 +5376,7 @@ function ImageAlignTools({ editor, labels }) {
3636
5376
  if (!hover || !editor.isEditable) return null;
3637
5377
  const above = hover.top - TOOLBAR_HEIGHT - TOOLBAR_GAP >= 8;
3638
5378
  const nodeAttrs = (_a = editor.state.doc.nodeAt(hover.pos)) == null ? void 0 : _a.attrs;
3639
- const active2 = normalizeImageAlign(nodeAttrs == null ? void 0 : nodeAttrs.align);
5379
+ const active = normalizeImageAlign(nodeAttrs == null ? void 0 : nodeAttrs.align);
3640
5380
  const caption = normalizeImageCaption(nodeAttrs == null ? void 0 : nodeAttrs.caption);
3641
5381
  const labelOf = {
3642
5382
  left: labels.imageAlignLeft,
@@ -3654,7 +5394,7 @@ function ImageAlignTools({ editor, labels }) {
3654
5394
  "div",
3655
5395
  {
3656
5396
  "data-image-align": "",
3657
- className: styles$4.bar,
5397
+ className: styles$3.bar,
3658
5398
  role: "toolbar",
3659
5399
  "aria-label": labels.imageAlign,
3660
5400
  style: {
@@ -3674,10 +5414,10 @@ function ImageAlignTools({ editor, labels }) {
3674
5414
  {
3675
5415
  type: "button",
3676
5416
  "data-image-align-action": align,
3677
- className: `${styles$4.btn} ${active2 === align ? styles$4.btnActive : ""}`,
5417
+ className: `${styles$3.btn} ${active === align ? styles$3.btnActive : ""}`,
3678
5418
  title: labelOf[align],
3679
5419
  "aria-label": labelOf[align],
3680
- "aria-pressed": active2 === align,
5420
+ "aria-pressed": active === align,
3681
5421
  onClick: () => {
3682
5422
  setImageAlignAtPos(editor, hover.pos, align);
3683
5423
  remeasureHover();
@@ -3687,13 +5427,13 @@ function ImageAlignTools({ editor, labels }) {
3687
5427
  align
3688
5428
  );
3689
5429
  }),
3690
- /* @__PURE__ */ jsx("span", { className: styles$4.divider, "aria-hidden": true }),
5430
+ /* @__PURE__ */ jsx("span", { className: styles$3.divider, "aria-hidden": true }),
3691
5431
  /* @__PURE__ */ jsx(
3692
5432
  "button",
3693
5433
  {
3694
5434
  type: "button",
3695
5435
  "data-image-align-action": "caption",
3696
- className: `${styles$4.btn} ${caption ? styles$4.btnActive : ""}`,
5436
+ className: `${styles$3.btn} ${caption ? styles$3.btnActive : ""}`,
3697
5437
  title: labels.imageCaption,
3698
5438
  "aria-label": labels.imageCaption,
3699
5439
  "aria-pressed": !!caption,
@@ -3704,10 +5444,10 @@ function ImageAlignTools({ editor, labels }) {
3704
5444
  children: /* @__PURE__ */ jsx(CaptionsIcon, { size: 14 })
3705
5445
  }
3706
5446
  ),
3707
- captionDraft !== null ? /* @__PURE__ */ jsx("div", { className: styles$4.captionRow, children: /* @__PURE__ */ jsx(
5447
+ captionDraft !== null ? /* @__PURE__ */ jsx("div", { className: styles$3.captionRow, children: /* @__PURE__ */ jsx(
3708
5448
  "input",
3709
5449
  {
3710
- className: styles$4.captionInput,
5450
+ className: styles$3.captionInput,
3711
5451
  value: captionDraft,
3712
5452
  placeholder: labels.imageCaptionPlaceholder,
3713
5453
  "aria-label": labels.imageCaptionPlaceholder,
@@ -3818,7 +5558,7 @@ const input = "_input_qysb1_52";
3818
5558
  const divider = "_divider_qysb1_63";
3819
5559
  const btn = "_btn_qysb1_71";
3820
5560
  const apply = "_apply_qysb1_99";
3821
- const styles$3 = {
5561
+ const styles$2 = {
3822
5562
  panel,
3823
5563
  field,
3824
5564
  fieldInvalid,
@@ -3830,7 +5570,7 @@ const styles$3 = {
3830
5570
  function LinkPopover({
3831
5571
  editor,
3832
5572
  trigger,
3833
- labels,
5573
+ locale = "en",
3834
5574
  className,
3835
5575
  style
3836
5576
  }) {
@@ -3847,7 +5587,7 @@ function LinkPopover({
3847
5587
  LinkPanel,
3848
5588
  {
3849
5589
  editor,
3850
- labels,
5590
+ locale,
3851
5591
  className,
3852
5592
  style,
3853
5593
  onClose: () => setOpen(false)
@@ -3859,12 +5599,12 @@ function LinkPopover({
3859
5599
  }
3860
5600
  function LinkPanel({
3861
5601
  editor,
3862
- labels,
5602
+ locale,
3863
5603
  className,
3864
5604
  style,
3865
5605
  onClose
3866
5606
  }) {
3867
- const t = { ...defaultLinkPopoverLabels, ...labels };
5607
+ const t = getLocaleBundle(locale).link;
3868
5608
  const [url, setUrl] = useState(() => readLinkHref(editor));
3869
5609
  const [invalid, setInvalid] = useState(false);
3870
5610
  const canEdit = canSetLink(editor);
@@ -3893,16 +5633,16 @@ function LinkPanel({
3893
5633
  return /* @__PURE__ */ jsxs(
3894
5634
  "div",
3895
5635
  {
3896
- className: className ? `${styles$3.panel} ${className}` : styles$3.panel,
5636
+ className: className ? `${styles$2.panel} ${className}` : styles$2.panel,
3897
5637
  style,
3898
5638
  "data-link-popover": "",
3899
5639
  role: "dialog",
3900
5640
  "aria-label": t.field,
3901
5641
  children: [
3902
- /* @__PURE__ */ jsx("span", { className: `${styles$3.field}${invalid ? ` ${styles$3.fieldInvalid}` : ""}`, children: /* @__PURE__ */ jsx(
5642
+ /* @__PURE__ */ jsx("span", { className: `${styles$2.field}${invalid ? ` ${styles$2.fieldInvalid}` : ""}`, children: /* @__PURE__ */ jsx(
3903
5643
  "input",
3904
5644
  {
3905
- className: styles$3.input,
5645
+ className: styles$2.input,
3906
5646
  "data-link-field": "",
3907
5647
  "data-link-invalid": invalid ? "" : void 0,
3908
5648
  type: "url",
@@ -3927,7 +5667,7 @@ function LinkPanel({
3927
5667
  "button",
3928
5668
  {
3929
5669
  type: "button",
3930
- className: `${styles$3.btn} ${styles$3.apply}`,
5670
+ className: `${styles$2.btn} ${styles$2.apply}`,
3931
5671
  "data-link-action": "apply",
3932
5672
  title: t.apply,
3933
5673
  "aria-label": t.apply,
@@ -3937,12 +5677,12 @@ function LinkPanel({
3937
5677
  children: /* @__PURE__ */ jsx(CheckIcon, { size: 16 })
3938
5678
  }
3939
5679
  ),
3940
- /* @__PURE__ */ jsx("span", { className: styles$3.divider, "aria-hidden": "true" }),
5680
+ /* @__PURE__ */ jsx("span", { className: styles$2.divider, "aria-hidden": "true" }),
3941
5681
  /* @__PURE__ */ jsx(
3942
5682
  "button",
3943
5683
  {
3944
5684
  type: "button",
3945
- className: styles$3.btn,
5685
+ className: styles$2.btn,
3946
5686
  "data-link-action": "open",
3947
5687
  title: t.open,
3948
5688
  "aria-label": t.open,
@@ -3956,7 +5696,7 @@ function LinkPanel({
3956
5696
  "button",
3957
5697
  {
3958
5698
  type: "button",
3959
- className: styles$3.btn,
5699
+ className: styles$2.btn,
3960
5700
  "data-link-action": "remove",
3961
5701
  title: t.remove,
3962
5702
  "aria-label": t.remove,
@@ -4146,16 +5886,16 @@ function appendColumnToTable(editor) {
4146
5886
  selectLineAt(editor, table, "col", TableMap.get(table.node).width - 1);
4147
5887
  return addColumnsAfter(editor, 1);
4148
5888
  }
4149
- const handle = "_handle_qjreh_9";
4150
- const handleRow = "_handleRow_qjreh_30";
4151
- const handleCol = "_handleCol_qjreh_40";
4152
- const extend = "_extend_qjreh_71";
4153
- const tableBubble = "_tableBubble_qjreh_117";
4154
- const tableMenuItem = "_tableMenuItem_qjreh_130";
4155
- const tableMenuItemIcon = "_tableMenuItemIcon_qjreh_156";
4156
- const tableMenuItemLabel = "_tableMenuItemLabel_qjreh_166";
4157
- const tableMenuDivider = "_tableMenuDivider_qjreh_171";
4158
- const styles$2 = {
5889
+ const handle = "_handle_1m19y_9";
5890
+ const handleRow = "_handleRow_1m19y_30";
5891
+ const handleCol = "_handleCol_1m19y_40";
5892
+ const extend = "_extend_1m19y_71";
5893
+ const tableBubble = "_tableBubble_1m19y_117";
5894
+ const tableMenuItem = "_tableMenuItem_1m19y_130";
5895
+ const tableMenuItemIcon = "_tableMenuItemIcon_1m19y_156";
5896
+ const tableMenuItemLabel = "_tableMenuItemLabel_1m19y_166";
5897
+ const tableMenuDivider = "_tableMenuDivider_1m19y_171";
5898
+ const styles$1 = {
4159
5899
  handle,
4160
5900
  handleRow,
4161
5901
  handleCol,
@@ -4166,9 +5906,9 @@ const styles$2 = {
4166
5906
  tableMenuItemLabel,
4167
5907
  tableMenuDivider
4168
5908
  };
4169
- function edgeFlags(editor, cell) {
5909
+ function edgeFlags(editor, cell2) {
4170
5910
  try {
4171
- const $cell = cellAround(editor.state.doc.resolve(editor.view.posAtDOM(cell, 0)));
5911
+ const $cell = cellAround(editor.state.doc.resolve(editor.view.posAtDOM(cell2, 0)));
4172
5912
  if (!$cell) return { onLastRow: false, onLastCol: false };
4173
5913
  const map = TableMap.get($cell.node(-1));
4174
5914
  const rect = map.findCell($cell.pos - $cell.start(-1));
@@ -4180,26 +5920,28 @@ function edgeFlags(editor, cell) {
4180
5920
  return { onLastRow: false, onLastCol: false };
4181
5921
  }
4182
5922
  }
4183
- const COL_HANDLE_GAP = 22;
4184
- const ROW_HANDLE_GAP = 26;
5923
+ const COL_HANDLE_GAP = 18;
5924
+ const COL_HANDLE_HEIGHT = 12;
5925
+ const ROW_HANDLE_GAP = 20;
5926
+ const ROW_HANDLE_WIDTH = 12;
4185
5927
  const EXTEND_GAP = 6;
4186
- const EXTEND_THICKNESS = 16;
5928
+ const EXTEND_THICKNESS = 12;
4187
5929
  const HOVER_KEEP_MS = 160;
4188
- function measureCell(editor, cell) {
4189
- const table = cell.closest("table");
4190
- const row2 = cell.closest("tr");
5930
+ function measureCell(editor, cell2) {
5931
+ const table = cell2.closest("table");
5932
+ const row2 = cell2.closest("tr");
4191
5933
  if (!table || !row2) return null;
4192
5934
  try {
4193
- editor.view.posAtDOM(cell, 0);
5935
+ editor.view.posAtDOM(cell2, 0);
4194
5936
  } catch {
4195
5937
  return null;
4196
5938
  }
4197
- const cellRect = cell.getBoundingClientRect();
5939
+ const cellRect = cell2.getBoundingClientRect();
4198
5940
  const rowRect = row2.getBoundingClientRect();
4199
5941
  const tableRect = table.getBoundingClientRect();
4200
- const edges = edgeFlags(editor, cell);
5942
+ const edges = edgeFlags(editor, cell2);
4201
5943
  return {
4202
- cell,
5944
+ cell: cell2,
4203
5945
  ...edges,
4204
5946
  rowTop: rowRect.top,
4205
5947
  rowHeight: rowRect.height,
@@ -4211,10 +5953,10 @@ function measureCell(editor, cell) {
4211
5953
  tableBottom: tableRect.bottom
4212
5954
  };
4213
5955
  }
4214
- function selectRowOrColumn(editor, cell, kind) {
5956
+ function selectRowOrColumn(editor, cell2, kind) {
4215
5957
  let pos;
4216
5958
  try {
4217
- pos = editor.view.posAtDOM(cell, 0);
5959
+ pos = editor.view.posAtDOM(cell2, 0);
4218
5960
  } catch {
4219
5961
  return false;
4220
5962
  }
@@ -4317,9 +6059,9 @@ function TableHandles({ editor, labels }) {
4317
6059
  const closeMenu = useCallback(() => setMenu(null), []);
4318
6060
  const remeasureHover = useCallback(() => {
4319
6061
  var _a;
4320
- const cell = (_a = hoverRef.current) == null ? void 0 : _a.cell;
4321
- if (!cell) return;
4322
- const next = cell.isConnected ? measureCell(editor, cell) : null;
6062
+ const cell2 = (_a = hoverRef.current) == null ? void 0 : _a.cell;
6063
+ if (!cell2) return;
6064
+ const next = cell2.isConnected ? measureCell(editor, cell2) : null;
4323
6065
  hoverRef.current = next;
4324
6066
  setHover(next);
4325
6067
  }, [editor]);
@@ -4338,8 +6080,8 @@ function TableHandles({ editor, labels }) {
4338
6080
  cancelPendingClear();
4339
6081
  return;
4340
6082
  }
4341
- const cell = target && editor.view.dom.contains(target) ? target.closest("td, th") : null;
4342
- if (!cell) {
6083
+ const cell2 = target && editor.view.dom.contains(target) ? target.closest("td, th") : null;
6084
+ if (!cell2) {
4343
6085
  if (hoverRef.current && clearTimerRef.current === null) {
4344
6086
  clearTimerRef.current = setTimeout(() => {
4345
6087
  clearTimerRef.current = null;
@@ -4349,8 +6091,8 @@ function TableHandles({ editor, labels }) {
4349
6091
  return;
4350
6092
  }
4351
6093
  cancelPendingClear();
4352
- if (((_b = hoverRef.current) == null ? void 0 : _b.cell) === cell) return;
4353
- const next = measureCell(editor, cell);
6094
+ if (((_b = hoverRef.current) == null ? void 0 : _b.cell) === cell2) return;
6095
+ const next = measureCell(editor, cell2);
4354
6096
  hoverRef.current = next;
4355
6097
  setHover(next);
4356
6098
  };
@@ -4427,11 +6169,11 @@ function TableHandles({ editor, labels }) {
4427
6169
  {
4428
6170
  type: "button",
4429
6171
  "data-table-handle": "row",
4430
- className: `${styles$2.handle} ${styles$2.handleRow}`,
6172
+ className: `${styles$1.handle} ${styles$1.handleRow}`,
4431
6173
  style: {
4432
6174
  left: hover.tableLeft - ROW_HANDLE_GAP,
4433
- // 长度跟着行高走(原来固定 28px 居中,行高时就显得太短)
4434
6175
  top: hover.rowTop,
6176
+ width: ROW_HANDLE_WIDTH,
4435
6177
  height: hover.rowHeight
4436
6178
  },
4437
6179
  title: labels.tableRowMenu,
@@ -4446,12 +6188,12 @@ function TableHandles({ editor, labels }) {
4446
6188
  {
4447
6189
  type: "button",
4448
6190
  "data-table-handle": "col",
4449
- className: `${styles$2.handle} ${styles$2.handleCol}`,
6191
+ className: `${styles$1.handle} ${styles$1.handleCol}`,
4450
6192
  style: {
4451
- // 长度跟着列宽走,两端与单元格对齐
4452
6193
  left: hover.colLeft,
4453
6194
  top: hover.tableTop - COL_HANDLE_GAP,
4454
- width: hover.colWidth
6195
+ width: hover.colWidth,
6196
+ height: COL_HANDLE_HEIGHT
4455
6197
  },
4456
6198
  title: labels.tableColumnMenu,
4457
6199
  "aria-label": labels.tableColumnMenu,
@@ -4465,7 +6207,7 @@ function TableHandles({ editor, labels }) {
4465
6207
  {
4466
6208
  type: "button",
4467
6209
  "data-table-extend": "col",
4468
- className: styles$2.extend,
6210
+ className: styles$1.extend,
4469
6211
  style: {
4470
6212
  left: hover.tableRight + EXTEND_GAP,
4471
6213
  top: hover.tableTop,
@@ -4487,7 +6229,7 @@ function TableHandles({ editor, labels }) {
4487
6229
  {
4488
6230
  type: "button",
4489
6231
  "data-table-extend": "row",
4490
- className: styles$2.extend,
6232
+ className: styles$1.extend,
4491
6233
  style: {
4492
6234
  left: hover.tableLeft,
4493
6235
  top: hover.tableBottom + EXTEND_GAP,
@@ -4508,7 +6250,7 @@ function TableHandles({ editor, labels }) {
4508
6250
  menu2 ? /* @__PURE__ */ jsxs(
4509
6251
  "div",
4510
6252
  {
4511
- className: styles$2.tableBubble,
6253
+ className: styles$1.tableBubble,
4512
6254
  "data-table-menu": "",
4513
6255
  style: { left: menu2.x, top: menu2.y },
4514
6256
  role: "menu",
@@ -4516,39 +6258,39 @@ function TableHandles({ editor, labels }) {
4516
6258
  onContextMenu: (e2) => e2.preventDefault(),
4517
6259
  children: [
4518
6260
  items.map((item2, index) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
4519
- index > 0 && item2.group !== items[index - 1].group ? /* @__PURE__ */ jsx("span", { className: styles$2.tableMenuDivider, "aria-hidden": true }) : null,
6261
+ index > 0 && item2.group !== items[index - 1].group ? /* @__PURE__ */ jsx("span", { className: styles$1.tableMenuDivider, "aria-hidden": true }) : null,
4520
6262
  /* @__PURE__ */ jsxs(
4521
6263
  "button",
4522
6264
  {
4523
6265
  type: "button",
4524
6266
  role: "menuitem",
4525
- className: styles$2.tableMenuItem,
6267
+ className: styles$1.tableMenuItem,
4526
6268
  disabled: item2.disabled,
4527
6269
  onClick: () => {
4528
6270
  item2.run();
4529
6271
  closeMenu();
4530
6272
  },
4531
6273
  children: [
4532
- /* @__PURE__ */ jsx("span", { className: styles$2.tableMenuItemIcon, "aria-hidden": true, children: item2.icon }),
4533
- /* @__PURE__ */ jsx("span", { className: styles$2.tableMenuItemLabel, children: item2.label })
6274
+ /* @__PURE__ */ jsx("span", { className: styles$1.tableMenuItemIcon, "aria-hidden": true, children: item2.icon }),
6275
+ /* @__PURE__ */ jsx("span", { className: styles$1.tableMenuItemLabel, children: item2.label })
4534
6276
  ]
4535
6277
  }
4536
6278
  )
4537
6279
  ] }, item2.key)),
4538
- /* @__PURE__ */ jsx("span", { className: styles$2.tableMenuDivider, "aria-hidden": true }),
6280
+ /* @__PURE__ */ jsx("span", { className: styles$1.tableMenuDivider, "aria-hidden": true }),
4539
6281
  /* @__PURE__ */ jsxs(
4540
6282
  "button",
4541
6283
  {
4542
6284
  type: "button",
4543
6285
  role: "menuitem",
4544
- className: styles$2.tableMenuItem,
6286
+ className: styles$1.tableMenuItem,
4545
6287
  onClick: () => {
4546
6288
  editor.commands.deleteTable();
4547
6289
  closeMenu();
4548
6290
  },
4549
6291
  children: [
4550
- /* @__PURE__ */ jsx("span", { className: styles$2.tableMenuItemIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx(TableDeleteIcon, {}) }),
4551
- /* @__PURE__ */ jsx("span", { className: styles$2.tableMenuItemLabel, children: labels.tableDeleteTable })
6292
+ /* @__PURE__ */ jsx("span", { className: styles$1.tableMenuItemIcon, "aria-hidden": true, children: /* @__PURE__ */ jsx(TableDeleteIcon, {}) }),
6293
+ /* @__PURE__ */ jsx("span", { className: styles$1.tableMenuItemLabel, children: labels.tableDeleteTable })
4552
6294
  ]
4553
6295
  }
4554
6296
  )
@@ -4707,7 +6449,7 @@ function MathEditorPopover({
4707
6449
  "textarea",
4708
6450
  {
4709
6451
  ref: inputRef,
4710
- className: styles$6.mathInput,
6452
+ className: styles$5.mathInput,
4711
6453
  value: draft,
4712
6454
  placeholder,
4713
6455
  rows: Math.max(3, draft.split("\n").length),
@@ -4719,7 +6461,7 @@ function MathEditorPopover({
4719
6461
  "input",
4720
6462
  {
4721
6463
  ref: inputRef,
4722
- className: styles$6.mathInput,
6464
+ className: styles$5.mathInput,
4723
6465
  value: draft,
4724
6466
  placeholder,
4725
6467
  "aria-labelledby": titleId,
@@ -4733,7 +6475,7 @@ function MathEditorPopover({
4733
6475
  "div",
4734
6476
  {
4735
6477
  ref: rootRef,
4736
- className: styles$6.mathLayer,
6478
+ className: styles$5.mathLayer,
4737
6479
  style: layerStyle,
4738
6480
  role: "dialog",
4739
6481
  "aria-modal": "false",
@@ -4741,15 +6483,15 @@ function MathEditorPopover({
4741
6483
  children: /* @__PURE__ */ jsxs(
4742
6484
  "div",
4743
6485
  {
4744
- className: isBlock ? `${styles$6.mathStack} ${styles$6.mathStackBlock}` : styles$6.mathStack,
6486
+ className: isBlock ? `${styles$5.mathStack} ${styles$5.mathStackBlock}` : styles$5.mathStack,
4745
6487
  children: [
4746
6488
  showHint ? /* @__PURE__ */ jsxs(
4747
6489
  "div",
4748
6490
  {
4749
6491
  id: titleId,
4750
- className: isBlock ? `${styles$6.mathHint} ${styles$6.mathHintBlock}` : styles$6.mathHint,
6492
+ className: isBlock ? `${styles$5.mathHint} ${styles$5.mathHintBlock}` : styles$5.mathHint,
4751
6493
  children: [
4752
- /* @__PURE__ */ jsx("span", { className: styles$6.mathHintIcon, "aria-hidden": true, children: isBlock ? "TeX" : "√x" }),
6494
+ /* @__PURE__ */ jsx("span", { className: styles$5.mathHintIcon, "aria-hidden": true, children: isBlock ? "TeX" : "√x" }),
4753
6495
  newLabel
4754
6496
  ]
4755
6497
  }
@@ -4758,20 +6500,20 @@ function MathEditorPopover({
4758
6500
  "div",
4759
6501
  {
4760
6502
  id: showHint ? void 0 : titleId,
4761
- className: isBlock ? `${styles$6.mathField} ${styles$6.mathFieldBlock}` : styles$6.mathField,
6503
+ className: isBlock ? `${styles$5.mathField} ${styles$5.mathFieldBlock}` : styles$5.mathField,
4762
6504
  children: [
4763
6505
  field2,
4764
6506
  /* @__PURE__ */ jsxs(
4765
6507
  "button",
4766
6508
  {
4767
6509
  type: "button",
4768
- className: styles$6.mathDone,
6510
+ className: styles$5.mathDone,
4769
6511
  disabled: !canSubmit,
4770
6512
  title: isBlock ? `${doneLabel} (⌘/Ctrl+Enter)` : `${doneLabel} (Enter)`,
4771
6513
  onClick: submit,
4772
6514
  children: [
4773
6515
  doneLabel,
4774
- /* @__PURE__ */ jsx("span", { className: styles$6.mathDoneKbd, "aria-hidden": true, children: "↵" })
6516
+ /* @__PURE__ */ jsx("span", { className: styles$5.mathDoneKbd, "aria-hidden": true, children: "↵" })
4775
6517
  ]
4776
6518
  }
4777
6519
  )
@@ -4786,7 +6528,7 @@ function MathEditorPopover({
4786
6528
  host
4787
6529
  );
4788
6530
  }
4789
- const ToolbarButton = forwardRef(function ToolbarButton2({ title, active: active2, disabled, busy, onClick, children, className, ...rest }, ref) {
6531
+ const ToolbarButton = forwardRef(function ToolbarButton2({ title, active, disabled, busy, onClick, children, className, ...rest }, ref) {
4790
6532
  return /* @__PURE__ */ jsx(
4791
6533
  "button",
4792
6534
  {
@@ -4795,10 +6537,10 @@ const ToolbarButton = forwardRef(function ToolbarButton2({ title, active: active
4795
6537
  type: "button",
4796
6538
  title,
4797
6539
  "aria-label": title,
4798
- "aria-pressed": active2,
6540
+ "aria-pressed": active,
4799
6541
  "aria-busy": busy,
4800
6542
  disabled,
4801
- className: `${styles$6.btn} ${active2 ? styles$6.btnActive : ""}${className ? ` ${className}` : ""}`,
6543
+ className: `${styles$5.btn} ${active ? styles$5.btnActive : ""}${className ? ` ${className}` : ""}`,
4802
6544
  onMouseDown: (e2) => e2.preventDefault(),
4803
6545
  onClick,
4804
6546
  children
@@ -4806,7 +6548,7 @@ const ToolbarButton = forwardRef(function ToolbarButton2({ title, active: active
4806
6548
  );
4807
6549
  });
4808
6550
  function Divider() {
4809
- return /* @__PURE__ */ jsx("span", { className: styles$6.divider, "aria-hidden": true });
6551
+ return /* @__PURE__ */ jsx("span", { className: styles$5.divider, "aria-hidden": true });
4810
6552
  }
4811
6553
  const LINE_HEIGHTS = ["1", "1.15", "1.5", "2", "2.5", "3"];
4812
6554
  function readParaAttr(editor, name) {
@@ -4816,7 +6558,9 @@ const MenuCloseCtx = createContext(() => {
4816
6558
  });
4817
6559
  function MenuPopover({
4818
6560
  trigger,
4819
- children
6561
+ children,
6562
+ contentClassName,
6563
+ align = "start"
4820
6564
  }) {
4821
6565
  const [open, setOpen] = useState(false);
4822
6566
  const close = useCallback(() => setOpen(false), []);
@@ -4825,9 +6569,9 @@ function MenuPopover({
4825
6569
  /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(
4826
6570
  Popover.Content,
4827
6571
  {
4828
- className: styles$6.menu,
6572
+ className: contentClassName ? `${styles$5.menu} ${contentClassName}` : styles$5.menu,
4829
6573
  sideOffset: 4,
4830
- align: "start",
6574
+ align,
4831
6575
  onOpenAutoFocus: (e2) => e2.preventDefault(),
4832
6576
  onCloseAutoFocus: (e2) => e2.preventDefault(),
4833
6577
  children: /* @__PURE__ */ jsx(MenuCloseCtx.Provider, { value: close, children })
@@ -4847,7 +6591,7 @@ function MenuItem({
4847
6591
  {
4848
6592
  type: "button",
4849
6593
  disabled,
4850
- className: `${styles$6.menuItem} ${selected ? styles$6.menuItemSelected : ""}`,
6594
+ className: `${styles$5.menuItem} ${selected ? styles$5.menuItemSelected : ""}`,
4851
6595
  onMouseDown: (e2) => e2.preventDefault(),
4852
6596
  onClick: () => {
4853
6597
  onSelect();
@@ -4857,6 +6601,43 @@ function MenuItem({
4857
6601
  }
4858
6602
  );
4859
6603
  }
6604
+ function NumberingFormatGrid({
6605
+ current,
6606
+ onSelect
6607
+ }) {
6608
+ const close = useContext(MenuCloseCtx);
6609
+ return /* @__PURE__ */ jsx("div", { className: styles$5.numberingGrid, role: "group", "aria-label": "Numbering formats", children: NUMBERING_FORMAT_IDS.map((format) => {
6610
+ const active = current === format;
6611
+ return /* @__PURE__ */ jsx(
6612
+ "button",
6613
+ {
6614
+ type: "button",
6615
+ role: "menuitem",
6616
+ "aria-label": NUMBERING_FORMAT_LABELS[format],
6617
+ "aria-pressed": active,
6618
+ className: `${styles$5.numberingOption}${active ? ` ${styles$5.numberingOptionActive}` : ""}`,
6619
+ onMouseDown: (e2) => e2.preventDefault(),
6620
+ onClick: () => {
6621
+ onSelect(format);
6622
+ close();
6623
+ },
6624
+ children: /* @__PURE__ */ jsx("span", { className: styles$5.numberingPreview, children: NUMBERING_FORMAT_PREVIEWS[format].map((row2, index) => /* @__PURE__ */ jsxs(
6625
+ "span",
6626
+ {
6627
+ className: styles$5.numberingPreviewRow,
6628
+ "data-depth": row2.depth,
6629
+ children: [
6630
+ /* @__PURE__ */ jsx("span", { className: styles$5.numberingPreviewMarker, children: row2.marker }),
6631
+ /* @__PURE__ */ jsx("span", { className: styles$5.numberingPreviewLine })
6632
+ ]
6633
+ },
6634
+ `${format}-${index}`
6635
+ )) })
6636
+ },
6637
+ format
6638
+ );
6639
+ }) });
6640
+ }
4860
6641
  const TABLE_PICKER_COLS = 10;
4861
6642
  const TABLE_PICKER_ROWS = 8;
4862
6643
  function TableInsertItem({
@@ -4882,21 +6663,21 @@ function TableInsertItem({
4882
6663
  {
4883
6664
  type: "button",
4884
6665
  disabled,
4885
- className: `${styles$6.menuItem} ${open ? styles$6.menuItemSelected : ""}`,
6666
+ className: `${styles$5.menuItem} ${open ? styles$5.menuItemSelected : ""}`,
4886
6667
  onMouseDown: (e2) => e2.preventDefault(),
4887
6668
  children: [
4888
- /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
4889
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: "⊞" }),
6669
+ /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
6670
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: "⊞" }),
4890
6671
  labels.tableInsert
4891
6672
  ] }),
4892
- /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$6.tableInsertCaret })
6673
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$5.tableInsertCaret })
4893
6674
  ]
4894
6675
  }
4895
6676
  ) }),
4896
6677
  /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsxs(
4897
6678
  Popover.Content,
4898
6679
  {
4899
- className: styles$6.tableSizePicker,
6680
+ className: styles$5.tableSizePicker,
4900
6681
  side: "right",
4901
6682
  align: "start",
4902
6683
  sideOffset: 6,
@@ -4906,7 +6687,7 @@ function TableInsertItem({
4906
6687
  /* @__PURE__ */ jsx(
4907
6688
  "div",
4908
6689
  {
4909
- className: styles$6.tableSizeGrid,
6690
+ className: styles$5.tableSizeGrid,
4910
6691
  style: {
4911
6692
  gridTemplateColumns: `repeat(${TABLE_PICKER_COLS}, 1fr)`
4912
6693
  },
@@ -4914,13 +6695,13 @@ function TableInsertItem({
4914
6695
  children: Array.from({ length: TABLE_PICKER_ROWS * TABLE_PICKER_COLS }, (_, i) => {
4915
6696
  const col = i % TABLE_PICKER_COLS + 1;
4916
6697
  const row2 = Math.floor(i / TABLE_PICKER_COLS) + 1;
4917
- const active2 = hover.cols > 0 && col <= hover.cols && row2 <= hover.rows;
6698
+ const active = hover.cols > 0 && col <= hover.cols && row2 <= hover.rows;
4918
6699
  return /* @__PURE__ */ jsx(
4919
6700
  "button",
4920
6701
  {
4921
6702
  type: "button",
4922
6703
  "aria-label": labels.tableSizeSelected(col, row2),
4923
- className: `${styles$6.tableSizeCell} ${active2 ? styles$6.tableSizeCellActive : ""}`,
6704
+ className: `${styles$5.tableSizeCell} ${active ? styles$5.tableSizeCellActive : ""}`,
4924
6705
  onMouseDown: (e2) => e2.preventDefault(),
4925
6706
  onMouseEnter: () => setHover({ cols: col, rows: row2 }),
4926
6707
  onClick: () => {
@@ -4935,7 +6716,7 @@ function TableInsertItem({
4935
6716
  })
4936
6717
  }
4937
6718
  ),
4938
- /* @__PURE__ */ jsx("div", { className: styles$6.tableSizeLabel, children: hover.cols > 0 ? labels.tableSizeSelected(hover.cols, hover.rows) : labels.tableInsert })
6719
+ /* @__PURE__ */ jsx("div", { className: styles$5.tableSizeLabel, children: hover.cols > 0 ? labels.tableSizeSelected(hover.cols, hover.rows) : labels.tableInsert })
4939
6720
  ]
4940
6721
  }
4941
6722
  ) })
@@ -4949,7 +6730,7 @@ function ColorPopover({
4949
6730
  bar: bar2,
4950
6731
  value,
4951
6732
  onPick,
4952
- paletteLabels
6733
+ locale
4953
6734
  }) {
4954
6735
  const [open, setOpen] = useState(false);
4955
6736
  return /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: setOpen, children: [
@@ -4957,20 +6738,20 @@ function ColorPopover({
4957
6738
  "button",
4958
6739
  {
4959
6740
  type: "button",
4960
- className: styles$6.btn,
6741
+ className: styles$5.btn,
4961
6742
  title,
4962
6743
  "aria-label": title,
4963
6744
  onMouseDown: (e2) => e2.preventDefault(),
4964
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.colorIcon, children: [
4965
- /* @__PURE__ */ jsx("span", { className: styles$6.colorIconGlyph, children: glyph }),
4966
- /* @__PURE__ */ jsx("span", { className: styles$6.colorIconBar, style: { background: bar2 } })
6745
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.colorIcon, children: [
6746
+ /* @__PURE__ */ jsx("span", { className: styles$5.colorIconGlyph, children: glyph }),
6747
+ /* @__PURE__ */ jsx("span", { className: styles$5.colorIconBar, style: { background: bar2 } })
4967
6748
  ] })
4968
6749
  }
4969
6750
  ) }),
4970
6751
  /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(
4971
6752
  Popover.Content,
4972
6753
  {
4973
- className: styles$6.popoverContent,
6754
+ className: styles$5.popoverContent,
4974
6755
  sideOffset: 4,
4975
6756
  align: "start",
4976
6757
  onOpenAutoFocus: (e2) => e2.preventDefault(),
@@ -4983,7 +6764,7 @@ function ColorPopover({
4983
6764
  onPick(c);
4984
6765
  setOpen(false);
4985
6766
  },
4986
- labels: paletteLabels
6767
+ locale
4987
6768
  }
4988
6769
  )
4989
6770
  }
@@ -5000,13 +6781,13 @@ function EditorToolbar({
5000
6781
  importAccept,
5001
6782
  importMenuItems,
5002
6783
  showImport = true,
5003
- labels,
6784
+ locale = "en",
5004
6785
  onSearch,
5005
6786
  searchActive = false,
5006
6787
  extraToolbarItems,
5007
6788
  className
5008
6789
  }) {
5009
- const t = { ...defaultToolbarLabels, ...labels };
6790
+ const t = getLocaleBundle(locale).toolbar;
5010
6791
  const state = useEditorState({
5011
6792
  editor,
5012
6793
  selector: ({ editor: e2 }) => ({
@@ -5024,7 +6805,9 @@ function EditorToolbar({
5024
6805
  isParagraph: e2.isActive("paragraph"),
5025
6806
  bulletList: e2.isActive("bulletList"),
5026
6807
  orderedList: e2.isActive("orderedList"),
6808
+ numberingFormat: readCurrentNumberingFormat(e2),
5027
6809
  blockquote: e2.isActive("blockquote"),
6810
+ details: e2.isActive("details"),
5028
6811
  textColor: e2.getAttributes("textStyle").color || void 0,
5029
6812
  highlightColor: e2.getAttributes("highlight").color || void 0,
5030
6813
  superscript: e2.isActive("superscript"),
@@ -5234,8 +7017,8 @@ function EditorToolbar({
5234
7017
  /* @__PURE__ */ jsx(
5235
7018
  "div",
5236
7019
  {
5237
- className: className ? `${styles$6.toolbar} ${className}` : styles$6.toolbar,
5238
- children: /* @__PURE__ */ jsxs("div", { className: styles$6.inner, children: [
7020
+ className: className ? `${styles$5.toolbar} ${className}` : styles$5.toolbar,
7021
+ children: /* @__PURE__ */ jsxs("div", { className: styles$5.inner, children: [
5239
7022
  /* @__PURE__ */ jsx(
5240
7023
  ToolbarButton,
5241
7024
  {
@@ -5262,12 +7045,12 @@ function EditorToolbar({
5262
7045
  "button",
5263
7046
  {
5264
7047
  type: "button",
5265
- className: styles$6.styleTrigger,
7048
+ className: styles$5.styleTrigger,
5266
7049
  title: t.style,
5267
7050
  onMouseDown: (e2) => e2.preventDefault(),
5268
7051
  children: [
5269
- /* @__PURE__ */ jsx("span", { className: styles$6.styleTriggerLabel, children: t.style }),
5270
- /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$6.styleTriggerCaret })
7052
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleTriggerLabel, children: t.style }),
7053
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$5.styleTriggerCaret })
5271
7054
  ]
5272
7055
  }
5273
7056
  ),
@@ -5277,8 +7060,8 @@ function EditorToolbar({
5277
7060
  {
5278
7061
  selected: (state.headingLevel ?? 0) === 0,
5279
7062
  onSelect: () => setBlockStyle(0),
5280
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5281
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: "¶" }),
7063
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7064
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: "¶" }),
5282
7065
  t.normalText
5283
7066
  ] })
5284
7067
  }
@@ -5288,8 +7071,8 @@ function EditorToolbar({
5288
7071
  {
5289
7072
  selected: state.headingLevel === lv,
5290
7073
  onSelect: () => setBlockStyle(lv),
5291
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5292
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: `H${lv}` }),
7074
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7075
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: `H${lv}` }),
5293
7076
  t.headingLabel(lv)
5294
7077
  ] })
5295
7078
  },
@@ -5305,14 +7088,14 @@ function EditorToolbar({
5305
7088
  "button",
5306
7089
  {
5307
7090
  type: "button",
5308
- className: styles$6.styleTrigger,
7091
+ className: styles$5.styleTrigger,
5309
7092
  title: t.fontSize,
5310
7093
  "aria-label": t.fontSize,
5311
7094
  disabled: !canEditFontSize,
5312
7095
  onMouseDown: (e2) => e2.preventDefault(),
5313
7096
  children: [
5314
- /* @__PURE__ */ jsx("span", { className: styles$6.styleTriggerLabel, children: state.fontSize || t.fontSize }),
5315
- /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$6.styleTriggerCaret })
7097
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleTriggerLabel, children: state.fontSize || t.fontSize }),
7098
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$5.styleTriggerCaret })
5316
7099
  ]
5317
7100
  }
5318
7101
  ),
@@ -5322,8 +7105,8 @@ function EditorToolbar({
5322
7105
  {
5323
7106
  selected: !state.fontSize,
5324
7107
  onSelect: () => applyFontSize(""),
5325
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5326
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: "A" }),
7108
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7109
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: "A" }),
5327
7110
  t.fontSizeDefault
5328
7111
  ] })
5329
7112
  }
@@ -5333,8 +7116,8 @@ function EditorToolbar({
5333
7116
  {
5334
7117
  selected: state.fontSize === size,
5335
7118
  onSelect: () => applyFontSize(size),
5336
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5337
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: parseInt(size, 10) }),
7119
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7120
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: parseInt(size, 10) }),
5338
7121
  size
5339
7122
  ] })
5340
7123
  },
@@ -5397,7 +7180,7 @@ function EditorToolbar({
5397
7180
  bar: state.textColor || "#ff3b30",
5398
7181
  value: state.textColor,
5399
7182
  onPick: applyTextColor,
5400
- paletteLabels: { none: t.colorNone, theme: t.colorTheme }
7183
+ locale
5401
7184
  }
5402
7185
  ),
5403
7186
  /* @__PURE__ */ jsx(
@@ -5408,7 +7191,7 @@ function EditorToolbar({
5408
7191
  bar: state.highlightColor || "#ffd83d",
5409
7192
  value: state.highlightColor,
5410
7193
  onPick: applyHighlight,
5411
- paletteLabels: { none: t.colorNone, theme: t.colorTheme }
7194
+ locale
5412
7195
  }
5413
7196
  ),
5414
7197
  /* @__PURE__ */ jsxs(
@@ -5418,13 +7201,13 @@ function EditorToolbar({
5418
7201
  "button",
5419
7202
  {
5420
7203
  type: "button",
5421
- className: `${styles$6.scriptTrigger} ${scriptActive !== "normal" ? styles$6.btnActive : ""}`,
7204
+ className: `${styles$5.scriptTrigger} ${scriptActive !== "normal" ? styles$5.btnActive : ""}`,
5422
7205
  title: t.scriptMenu,
5423
7206
  "aria-label": t.scriptMenu,
5424
7207
  onMouseDown: (e2) => e2.preventDefault(),
5425
7208
  children: [
5426
- /* @__PURE__ */ jsx("span", { className: styles$6.scriptTriggerGlyph, children: "A" }),
5427
- /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$6.styleTriggerCaret })
7209
+ /* @__PURE__ */ jsx("span", { className: styles$5.scriptTriggerGlyph, children: "A" }),
7210
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$5.styleTriggerCaret })
5428
7211
  ]
5429
7212
  }
5430
7213
  ),
@@ -5434,8 +7217,8 @@ function EditorToolbar({
5434
7217
  {
5435
7218
  selected: scriptActive === "normal",
5436
7219
  onSelect: () => chain().unsetSuperscript().unsetSubscript().run(),
5437
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5438
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: "A" }),
7220
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7221
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: "A" }),
5439
7222
  t.scriptNormal
5440
7223
  ] })
5441
7224
  }
@@ -5445,8 +7228,8 @@ function EditorToolbar({
5445
7228
  {
5446
7229
  selected: scriptActive === "superscript",
5447
7230
  onSelect: () => chain().unsetSubscript().toggleSuperscript().run(),
5448
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5449
- /* @__PURE__ */ jsxs("span", { className: `${styles$6.styleIcon} ${styles$6.scriptGlyph}`, children: [
7231
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7232
+ /* @__PURE__ */ jsxs("span", { className: `${styles$5.styleIcon} ${styles$5.scriptGlyph}`, children: [
5450
7233
  "x",
5451
7234
  /* @__PURE__ */ jsx("sup", { children: "2" })
5452
7235
  ] }),
@@ -5459,8 +7242,8 @@ function EditorToolbar({
5459
7242
  {
5460
7243
  selected: scriptActive === "subscript",
5461
7244
  onSelect: () => chain().unsetSuperscript().toggleSubscript().run(),
5462
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5463
- /* @__PURE__ */ jsxs("span", { className: `${styles$6.styleIcon} ${styles$6.scriptGlyph}`, children: [
7245
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7246
+ /* @__PURE__ */ jsxs("span", { className: `${styles$5.styleIcon} ${styles$5.scriptGlyph}`, children: [
5464
7247
  "x",
5465
7248
  /* @__PURE__ */ jsx("sub", { children: "2" })
5466
7249
  ] }),
@@ -5476,13 +7259,7 @@ function EditorToolbar({
5476
7259
  LinkPopover,
5477
7260
  {
5478
7261
  editor,
5479
- labels: {
5480
- field: t.linkPrompt,
5481
- apply: t.linkApply,
5482
- open: t.linkOpen,
5483
- remove: t.linkRemove,
5484
- invalid: t.linkInvalid
5485
- },
7262
+ locale,
5486
7263
  trigger: /* @__PURE__ */ jsx(ToolbarButton, { title: t.link, active: state.link, children: /* @__PURE__ */ jsx(LinkIcon, {}) })
5487
7264
  }
5488
7265
  ),
@@ -5506,19 +7283,19 @@ function EditorToolbar({
5506
7283
  "button",
5507
7284
  {
5508
7285
  type: "button",
5509
- className: styles$6.styleTrigger,
7286
+ className: styles$5.styleTrigger,
5510
7287
  title: importTitle,
5511
7288
  "aria-label": importTitle,
5512
7289
  "aria-busy": !!importing,
5513
7290
  disabled: !!importing,
5514
7291
  onMouseDown: (e2) => e2.preventDefault(),
5515
7292
  children: [
5516
- /* @__PURE__ */ jsx("span", { className: styles$6.styleTriggerLabel, children: t.importDocument }),
7293
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleTriggerLabel, children: t.importDocument }),
5517
7294
  /* @__PURE__ */ jsx(
5518
7295
  ChevronDownIcon,
5519
7296
  {
5520
7297
  size: 12,
5521
- className: styles$6.styleTriggerCaret
7298
+ className: styles$5.styleTriggerCaret
5522
7299
  }
5523
7300
  )
5524
7301
  ]
@@ -5540,7 +7317,20 @@ function EditorToolbar({
5540
7317
  title: t.blockquote,
5541
7318
  active: state.blockquote,
5542
7319
  onClick: () => chain().toggleBlockquote().run(),
5543
- children: /* @__PURE__ */ jsx("span", { className: styles$6.txtIcon, children: "❝" })
7320
+ children: /* @__PURE__ */ jsx("span", { className: styles$5.txtIcon, children: "❝" })
7321
+ }
7322
+ ),
7323
+ /* @__PURE__ */ jsx(
7324
+ ToolbarButton,
7325
+ {
7326
+ title: t.details,
7327
+ active: state.details,
7328
+ onClick: () => {
7329
+ const next = editor.chain().focus();
7330
+ if (editor.isActive("details")) next.unsetDetails().run();
7331
+ else next.setDetails().run();
7332
+ },
7333
+ children: /* @__PURE__ */ jsx(DetailsIcon, {})
5544
7334
  }
5545
7335
  ),
5546
7336
  /* @__PURE__ */ jsx(Divider, {}),
@@ -5551,13 +7341,13 @@ function EditorToolbar({
5551
7341
  "button",
5552
7342
  {
5553
7343
  type: "button",
5554
- className: `${styles$6.styleTrigger} ${styles$6.iconTrigger}`,
7344
+ className: `${styles$5.styleTrigger} ${styles$5.iconTrigger}`,
5555
7345
  title: t.align,
5556
7346
  "aria-label": t.align,
5557
7347
  onMouseDown: (e2) => e2.preventDefault(),
5558
7348
  children: [
5559
7349
  state.textAlign === "center" ? /* @__PURE__ */ jsx(AlignCenterIcon, {}) : state.textAlign === "right" ? /* @__PURE__ */ jsx(AlignRightIcon, {}) : state.textAlign === "justify" ? /* @__PURE__ */ jsx(AlignJustifyIcon, {}) : /* @__PURE__ */ jsx(AlignLeftIcon, {}),
5560
- /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$6.styleTriggerCaret })
7350
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$5.styleTriggerCaret })
5561
7351
  ]
5562
7352
  }
5563
7353
  ),
@@ -5571,8 +7361,8 @@ function EditorToolbar({
5571
7361
  {
5572
7362
  selected: state.textAlign === value,
5573
7363
  onSelect: () => chain().setTextAlign(value).run(),
5574
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5575
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: /* @__PURE__ */ jsx(Icon, { size: 14 }) }),
7364
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7365
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: /* @__PURE__ */ jsx(Icon, { size: 14 }) }),
5576
7366
  label
5577
7367
  ] })
5578
7368
  },
@@ -5587,23 +7377,23 @@ function EditorToolbar({
5587
7377
  "button",
5588
7378
  {
5589
7379
  type: "button",
5590
- className: `${styles$6.styleTrigger} ${styles$6.iconTrigger}`,
7380
+ className: `${styles$5.styleTrigger} ${styles$5.iconTrigger}`,
5591
7381
  title: t.indent,
5592
7382
  "aria-label": t.indent,
5593
7383
  onMouseDown: (e2) => e2.preventDefault(),
5594
7384
  children: [
5595
7385
  /* @__PURE__ */ jsx(IndentIncreaseIcon, {}),
5596
- /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$6.styleTriggerCaret })
7386
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$5.styleTriggerCaret })
5597
7387
  ]
5598
7388
  }
5599
7389
  ),
5600
7390
  children: [
5601
- /* @__PURE__ */ jsx(MenuItem, { onSelect: () => chain().increaseIndent().run(), children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5602
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: /* @__PURE__ */ jsx(IndentIncreaseIcon, { size: 14 }) }),
7391
+ /* @__PURE__ */ jsx(MenuItem, { onSelect: () => chain().increaseIndent().run(), children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7392
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: /* @__PURE__ */ jsx(IndentIncreaseIcon, { size: 14 }) }),
5603
7393
  t.indentIncrease
5604
7394
  ] }) }),
5605
- /* @__PURE__ */ jsx(MenuItem, { onSelect: () => chain().decreaseIndent().run(), children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5606
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: /* @__PURE__ */ jsx(IndentDecreaseIcon, { size: 14 }) }),
7395
+ /* @__PURE__ */ jsx(MenuItem, { onSelect: () => chain().decreaseIndent().run(), children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7396
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: /* @__PURE__ */ jsx(IndentDecreaseIcon, { size: 14 }) }),
5607
7397
  t.indentDecrease
5608
7398
  ] }) })
5609
7399
  ]
@@ -5616,13 +7406,13 @@ function EditorToolbar({
5616
7406
  "button",
5617
7407
  {
5618
7408
  type: "button",
5619
- className: `${styles$6.styleTrigger} ${styles$6.iconTrigger}`,
7409
+ className: `${styles$5.styleTrigger} ${styles$5.iconTrigger}`,
5620
7410
  title: t.lineHeight,
5621
7411
  "aria-label": t.lineHeight,
5622
7412
  onMouseDown: (e2) => e2.preventDefault(),
5623
7413
  children: [
5624
7414
  /* @__PURE__ */ jsx(LineHeightIcon, {}),
5625
- /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$6.styleTriggerCaret })
7415
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$5.styleTriggerCaret })
5626
7416
  ]
5627
7417
  }
5628
7418
  ),
@@ -5632,8 +7422,8 @@ function EditorToolbar({
5632
7422
  {
5633
7423
  selected: !state.lineHeight,
5634
7424
  onSelect: () => chain().setLineHeight(null).run(),
5635
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5636
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: "—" }),
7425
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7426
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: "—" }),
5637
7427
  t.lineHeightDefault
5638
7428
  ] })
5639
7429
  }
@@ -5643,8 +7433,8 @@ function EditorToolbar({
5643
7433
  {
5644
7434
  selected: state.lineHeight === Number(value),
5645
7435
  onSelect: () => chain().setLineHeight(Number(value)).run(),
5646
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5647
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: "≡" }),
7436
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7437
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: "≡" }),
5648
7438
  value
5649
7439
  ] })
5650
7440
  },
@@ -5663,13 +7453,46 @@ function EditorToolbar({
5663
7453
  children: /* @__PURE__ */ jsx(ListUnorderedIcon, {})
5664
7454
  }
5665
7455
  ),
5666
- /* @__PURE__ */ jsx(
5667
- ToolbarButton,
7456
+ /* @__PURE__ */ jsxs(
7457
+ "span",
5668
7458
  {
5669
- title: t.orderedList,
5670
- active: state.orderedList,
5671
- onClick: () => chain().toggleOrderedList().run(),
5672
- children: /* @__PURE__ */ jsx(ListOrderedIcon, {})
7459
+ className: `${styles$5.listSplit}${state.orderedList ? ` ${styles$5.listSplitActive}` : ""}`,
7460
+ children: [
7461
+ /* @__PURE__ */ jsx(
7462
+ ToolbarButton,
7463
+ {
7464
+ title: t.orderedList,
7465
+ active: state.orderedList,
7466
+ onClick: () => chain().toggleOrderedList().run(),
7467
+ children: /* @__PURE__ */ jsx(ListOrderedIcon, {})
7468
+ }
7469
+ ),
7470
+ /* @__PURE__ */ jsx(
7471
+ MenuPopover,
7472
+ {
7473
+ align: "end",
7474
+ contentClassName: styles$5.numberingMenu,
7475
+ trigger: /* @__PURE__ */ jsx(
7476
+ "button",
7477
+ {
7478
+ type: "button",
7479
+ className: `${styles$5.numberingCaret}${state.numberingFormat ? ` ${styles$5.numberingCaretActive}` : ""}`,
7480
+ title: t.numberingFormat,
7481
+ "aria-label": t.numberingFormat,
7482
+ onMouseDown: (e2) => e2.preventDefault(),
7483
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12 })
7484
+ }
7485
+ ),
7486
+ children: /* @__PURE__ */ jsx(
7487
+ NumberingFormatGrid,
7488
+ {
7489
+ current: state.numberingFormat,
7490
+ onSelect: (format) => applyNumberingFormat(editor, format)
7491
+ }
7492
+ )
7493
+ }
7494
+ )
7495
+ ]
5673
7496
  }
5674
7497
  ),
5675
7498
  /* @__PURE__ */ jsx(
@@ -5698,30 +7521,30 @@ function EditorToolbar({
5698
7521
  "button",
5699
7522
  {
5700
7523
  type: "button",
5701
- className: styles$6.styleTrigger,
7524
+ className: styles$5.styleTrigger,
5702
7525
  title: t.more,
5703
7526
  onMouseDown: (e2) => e2.preventDefault(),
5704
7527
  children: [
5705
- /* @__PURE__ */ jsx("span", { className: styles$6.styleTriggerLabel, children: t.more }),
5706
- /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$6.styleTriggerCaret })
7528
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleTriggerLabel, children: t.more }),
7529
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$5.styleTriggerCaret })
5707
7530
  ]
5708
7531
  }
5709
7532
  ),
5710
7533
  children: [
5711
- /* @__PURE__ */ jsx(MenuItem, { onSelect: () => chain().toggleCodeBlock().run(), children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5712
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: "{ }" }),
7534
+ /* @__PURE__ */ jsx(MenuItem, { onSelect: () => chain().toggleCodeBlock().run(), children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7535
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: "{ }" }),
5713
7536
  t.codeBlock
5714
7537
  ] }) }),
5715
- /* @__PURE__ */ jsx(MenuItem, { onSelect: () => openInsertMath("inline"), children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5716
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: "√x" }),
7538
+ /* @__PURE__ */ jsx(MenuItem, { onSelect: () => openInsertMath("inline"), children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7539
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: "√x" }),
5717
7540
  t.inlineMath
5718
7541
  ] }) }),
5719
- /* @__PURE__ */ jsx(MenuItem, { onSelect: () => openInsertMath("block"), children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5720
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: "∑" }),
7542
+ /* @__PURE__ */ jsx(MenuItem, { onSelect: () => openInsertMath("block"), children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7543
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: "∑" }),
5721
7544
  t.blockMath
5722
7545
  ] }) }),
5723
- /* @__PURE__ */ jsx(MenuItem, { onSelect: () => chain().setHorizontalRule().run(), children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5724
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: "—" }),
7546
+ /* @__PURE__ */ jsx(MenuItem, { onSelect: () => chain().setHorizontalRule().run(), children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7547
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: "—" }),
5725
7548
  t.hr
5726
7549
  ] }) }),
5727
7550
  /* @__PURE__ */ jsx(
@@ -5737,8 +7560,8 @@ function EditorToolbar({
5737
7560
  {
5738
7561
  disabled: item2.disabled,
5739
7562
  onSelect: () => item2.onSelect(editor),
5740
- children: /* @__PURE__ */ jsxs("span", { className: styles$6.styleItem, children: [
5741
- /* @__PURE__ */ jsx("span", { className: styles$6.styleIcon, children: item2.icon }),
7563
+ children: /* @__PURE__ */ jsxs("span", { className: styles$5.styleItem, children: [
7564
+ /* @__PURE__ */ jsx("span", { className: styles$5.styleIcon, children: item2.icon }),
5742
7565
  item2.label
5743
7566
  ] })
5744
7567
  },
@@ -5779,165 +7602,6 @@ function EditorToolbar({
5779
7602
  /* @__PURE__ */ jsx(ImageAlignTools, { editor, labels: t })
5780
7603
  ] });
5781
7604
  }
5782
- function useIsMobile(breakpoint = 768) {
5783
- const [isMobile, setIsMobile] = useState(false);
5784
- useEffect(() => {
5785
- const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
5786
- const update = () => setIsMobile(mq.matches);
5787
- update();
5788
- mq.addEventListener("change", update);
5789
- return () => mq.removeEventListener("change", update);
5790
- }, [breakpoint]);
5791
- return isMobile;
5792
- }
5793
- const desktop = "_desktop_euqdt_3";
5794
- const header = "_header_euqdt_19";
5795
- const headerTitle = "_headerTitle_euqdt_27";
5796
- const collapseBtn = "_collapseBtn_euqdt_35";
5797
- const collapsedRail = "_collapsedRail_euqdt_55";
5798
- const list = "_list_euqdt_75";
5799
- const item = "_item_euqdt_81";
5800
- const itemText = "_itemText_euqdt_102";
5801
- const active = "_active_euqdt_109";
5802
- const locked = "_locked_euqdt_116";
5803
- const lockIcon = "_lockIcon_euqdt_126";
5804
- const mobile = "_mobile_euqdt_133";
5805
- const mobileBar = "_mobileBar_euqdt_138";
5806
- const mobileBarIcon = "_mobileBarIcon_euqdt_154";
5807
- const chevron = "_chevron_euqdt_159";
5808
- const chevronUp = "_chevronUp_euqdt_166";
5809
- const mobilePanel = "_mobilePanel_euqdt_170";
5810
- const mobilePanelOpen = "_mobilePanelOpen_euqdt_176";
5811
- const styles$1 = {
5812
- desktop,
5813
- header,
5814
- headerTitle,
5815
- collapseBtn,
5816
- collapsedRail,
5817
- list,
5818
- item,
5819
- itemText,
5820
- active,
5821
- locked,
5822
- lockIcon,
5823
- mobile,
5824
- mobileBar,
5825
- mobileBarIcon,
5826
- chevron,
5827
- chevronUp,
5828
- mobilePanel,
5829
- mobilePanelOpen
5830
- };
5831
- function TocPanel({ items, activeId, onItemClick, labels }) {
5832
- const t = { ...defaultTocLabels, ...labels };
5833
- const isMobile = useIsMobile();
5834
- const [collapsed, setCollapsed] = useState(false);
5835
- const [mobileOpen, setMobileOpen] = useState(false);
5836
- const desktopNavRef = useRef(null);
5837
- const mobilePanelRef = useRef(null);
5838
- useEffect(() => {
5839
- if (!activeId) return;
5840
- const reduce = window.matchMedia(
5841
- "(prefers-reduced-motion: reduce)"
5842
- ).matches;
5843
- const container = desktopNavRef.current || mobilePanelRef.current;
5844
- if (!container) return;
5845
- const el = container.querySelector(`a[href="#${CSS.escape(activeId)}"]`);
5846
- if (!el) return;
5847
- el.scrollIntoView({
5848
- block: "nearest",
5849
- behavior: reduce ? "auto" : "smooth"
5850
- });
5851
- }, [activeId]);
5852
- if (!items.length) return null;
5853
- const minLevel = Math.min(...items.map((i) => i.level));
5854
- const handleClick = (item2) => {
5855
- if (item2.locked) return;
5856
- onItemClick == null ? void 0 : onItemClick(item2);
5857
- if (isMobile) setMobileOpen(false);
5858
- };
5859
- const list2 = /* @__PURE__ */ jsx("ul", { className: styles$1.list, children: items.map((item2) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
5860
- "a",
5861
- {
5862
- href: item2.locked ? void 0 : `#${item2.id}`,
5863
- className: `${styles$1.item} ${item2.id === activeId ? styles$1.active : ""} ${item2.locked ? styles$1.locked : ""}`,
5864
- style: { paddingLeft: `${(item2.level - minLevel) * 12 + 12}px` },
5865
- "aria-current": item2.id === activeId ? "true" : void 0,
5866
- "aria-disabled": item2.locked ? "true" : void 0,
5867
- onClick: (e2) => {
5868
- e2.preventDefault();
5869
- handleClick(item2);
5870
- },
5871
- children: [
5872
- /* @__PURE__ */ jsx("span", { className: styles$1.itemText, children: item2.text }),
5873
- item2.locked ? /* @__PURE__ */ jsx(LockIcon, { className: styles$1.lockIcon, "aria-hidden": true }) : null
5874
- ]
5875
- }
5876
- ) }, item2.id)) });
5877
- if (isMobile) {
5878
- return /* @__PURE__ */ jsxs("nav", { className: styles$1.mobile, "aria-label": t.title, children: [
5879
- /* @__PURE__ */ jsxs(
5880
- "button",
5881
- {
5882
- type: "button",
5883
- className: styles$1.mobileBar,
5884
- "aria-expanded": mobileOpen,
5885
- onClick: () => setMobileOpen((v) => !v),
5886
- children: [
5887
- /* @__PURE__ */ jsx(MenuIcon, { className: styles$1.mobileBarIcon, "aria-hidden": true }),
5888
- /* @__PURE__ */ jsx("span", { children: t.title }),
5889
- /* @__PURE__ */ jsx(
5890
- "span",
5891
- {
5892
- className: `${styles$1.chevron} ${mobileOpen ? styles$1.chevronUp : ""}`,
5893
- "aria-hidden": true,
5894
- children: /* @__PURE__ */ jsx(ChevronDownIcon, { size: 16 })
5895
- }
5896
- )
5897
- ]
5898
- }
5899
- ),
5900
- /* @__PURE__ */ jsx(
5901
- "div",
5902
- {
5903
- ref: mobilePanelRef,
5904
- className: `${styles$1.mobilePanel} ${mobileOpen ? styles$1.mobilePanelOpen : ""}`,
5905
- children: list2
5906
- }
5907
- )
5908
- ] });
5909
- }
5910
- if (collapsed) {
5911
- return /* @__PURE__ */ jsx(
5912
- "button",
5913
- {
5914
- type: "button",
5915
- className: styles$1.collapsedRail,
5916
- "aria-label": t.expand,
5917
- title: t.expand,
5918
- onClick: () => setCollapsed(false),
5919
- children: /* @__PURE__ */ jsx(ListUnorderedIcon, {})
5920
- }
5921
- );
5922
- }
5923
- return /* @__PURE__ */ jsxs("nav", { className: styles$1.desktop, "aria-label": t.title, ref: desktopNavRef, children: [
5924
- /* @__PURE__ */ jsxs("div", { className: styles$1.header, children: [
5925
- /* @__PURE__ */ jsx("span", { className: styles$1.headerTitle, children: t.title }),
5926
- /* @__PURE__ */ jsx(
5927
- "button",
5928
- {
5929
- type: "button",
5930
- className: styles$1.collapseBtn,
5931
- "aria-label": t.collapse,
5932
- title: t.collapse,
5933
- onClick: () => setCollapsed(true),
5934
- children: "«"
5935
- }
5936
- )
5937
- ] }),
5938
- list2
5939
- ] });
5940
- }
5941
7605
  function resetImageSize(editor) {
5942
7606
  const pos = findImagePos(editor);
5943
7607
  if (pos == null) return false;
@@ -5982,10 +7646,10 @@ function CommentPopover({
5982
7646
  ] });
5983
7647
  }
5984
7648
  const PROBE_ID = "__anchor-range-probe__";
5985
- function findRangeByAnchor(editor, anchor) {
5986
- if (!anchor || !anchor.exact) return null;
7649
+ function findRangeByAnchor(editor, anchor2) {
7650
+ if (!anchor2 || !anchor2.exact) return null;
5987
7651
  const [result] = mapCommentAnchors(editor.state.doc, [
5988
- { commentId: PROBE_ID, segments: [anchor] }
7652
+ { commentId: PROBE_ID, segments: [anchor2] }
5989
7653
  ]);
5990
7654
  const range = result == null ? void 0 : result.ranges[0];
5991
7655
  if (!range) return null;
@@ -6000,11 +7664,11 @@ function findRangeByAnchor(editor, anchor) {
6000
7664
  const BLOCK_SEPARATOR = "\n\n";
6001
7665
  function topLevelBlocks(editor) {
6002
7666
  const blocks = [];
6003
- editor.state.doc.forEach((node, offset) => {
7667
+ editor.state.doc.forEach((node, offset2) => {
6004
7668
  blocks.push({
6005
7669
  json: node.toJSON(),
6006
- from: offset,
6007
- to: offset + node.nodeSize
7670
+ from: offset2,
7671
+ to: offset2 + node.nodeSize
6008
7672
  });
6009
7673
  });
6010
7674
  return blocks;
@@ -6134,12 +7798,15 @@ export {
6134
7798
  CommentMark,
6135
7799
  CommentPopover,
6136
7800
  CopyIcon,
7801
+ DetailsIcon,
7802
+ DownloadIcon,
6137
7803
  EditorToolbar,
6138
7804
  EraserIcon,
6139
7805
  ExternalLinkIcon,
6140
7806
  FIND_DEBOUNCE_MS,
6141
7807
  default2 as FindAndReplace,
6142
7808
  FindReplaceBar,
7809
+ GripIcon,
6143
7810
  ImageAlignTools,
6144
7811
  ImageIcon,
6145
7812
  ImageUploadNode,
@@ -6178,7 +7845,6 @@ export {
6178
7845
  SlashMenu,
6179
7846
  StrikethroughIcon,
6180
7847
  TableDeleteIcon,
6181
- TocPanel,
6182
7848
  TrashIcon,
6183
7849
  UnderlineIcon,
6184
7850
  UndoIcon,
@@ -6198,17 +7864,6 @@ export {
6198
7864
  createChart,
6199
7865
  createCitationRef,
6200
7866
  createDefaultSlashMenuItems,
6201
- defaultChartLabels,
6202
- defaultCodeBlockLabels,
6203
- defaultColorPaletteLabels,
6204
- defaultCommentLabels,
6205
- defaultFindLabels,
6206
- defaultImageUploadLabels,
6207
- defaultLinkPopoverLabels,
6208
- defaultShortcutLabels,
6209
- defaultSlashMenuLabels,
6210
- defaultTocLabels,
6211
- defaultToolbarLabels,
6212
7867
  enrichMarkdownCitations,
6213
7868
  b2 as extractFootnoteSources,
6214
7869
  e as extractToc,
@@ -6249,14 +7904,14 @@ export {
6249
7904
  resetImageSize,
6250
7905
  runFindCommand,
6251
7906
  sanitizeLinkUrl,
6252
- s as scrollToTocHeading,
7907
+ scrollToTocHeading,
6253
7908
  selectionKind,
6254
- s2 as serializeChartPayload,
7909
+ s as serializeChartPayload,
6255
7910
  setImageAlign,
6256
7911
  setImageAlignAt,
6257
7912
  setImageCaption,
6258
7913
  setImageCaptionAtPos,
6259
- s3 as stabilizeMarkdown,
7914
+ s2 as stabilizeMarkdown,
6260
7915
  stripCommentAnchorMarks,
6261
7916
  useIsMobile
6262
7917
  };