@jvs-milkdown/crepe 1.2.17 → 1.2.20

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 (93) hide show
  1. package/lib/cjs/builder.js +4 -0
  2. package/lib/cjs/builder.js.map +1 -1
  3. package/lib/cjs/feature/block-edit/index.js +4 -0
  4. package/lib/cjs/feature/block-edit/index.js.map +1 -1
  5. package/lib/cjs/feature/code-mirror/index.js +4 -0
  6. package/lib/cjs/feature/code-mirror/index.js.map +1 -1
  7. package/lib/cjs/feature/cursor/index.js +4 -0
  8. package/lib/cjs/feature/cursor/index.js.map +1 -1
  9. package/lib/cjs/feature/image-block/index.js +4 -0
  10. package/lib/cjs/feature/image-block/index.js.map +1 -1
  11. package/lib/cjs/feature/inline-diff/index.js +4 -0
  12. package/lib/cjs/feature/inline-diff/index.js.map +1 -1
  13. package/lib/cjs/feature/latex/index.js +4 -0
  14. package/lib/cjs/feature/latex/index.js.map +1 -1
  15. package/lib/cjs/feature/link-tooltip/index.js +4 -0
  16. package/lib/cjs/feature/link-tooltip/index.js.map +1 -1
  17. package/lib/cjs/feature/list-item/index.js +4 -0
  18. package/lib/cjs/feature/list-item/index.js.map +1 -1
  19. package/lib/cjs/feature/placeholder/index.js +4 -0
  20. package/lib/cjs/feature/placeholder/index.js.map +1 -1
  21. package/lib/cjs/feature/table/index.js +4 -0
  22. package/lib/cjs/feature/table/index.js.map +1 -1
  23. package/lib/cjs/feature/toolbar/index.js +56 -22
  24. package/lib/cjs/feature/toolbar/index.js.map +1 -1
  25. package/lib/cjs/index.js +533 -151
  26. package/lib/cjs/index.js.map +1 -1
  27. package/lib/esm/builder.js +4 -0
  28. package/lib/esm/builder.js.map +1 -1
  29. package/lib/esm/feature/block-edit/index.js +4 -0
  30. package/lib/esm/feature/block-edit/index.js.map +1 -1
  31. package/lib/esm/feature/code-mirror/index.js +4 -0
  32. package/lib/esm/feature/code-mirror/index.js.map +1 -1
  33. package/lib/esm/feature/cursor/index.js +4 -0
  34. package/lib/esm/feature/cursor/index.js.map +1 -1
  35. package/lib/esm/feature/image-block/index.js +4 -0
  36. package/lib/esm/feature/image-block/index.js.map +1 -1
  37. package/lib/esm/feature/inline-diff/index.js +4 -0
  38. package/lib/esm/feature/inline-diff/index.js.map +1 -1
  39. package/lib/esm/feature/latex/index.js +4 -0
  40. package/lib/esm/feature/latex/index.js.map +1 -1
  41. package/lib/esm/feature/link-tooltip/index.js +4 -0
  42. package/lib/esm/feature/link-tooltip/index.js.map +1 -1
  43. package/lib/esm/feature/list-item/index.js +4 -0
  44. package/lib/esm/feature/list-item/index.js.map +1 -1
  45. package/lib/esm/feature/placeholder/index.js +4 -0
  46. package/lib/esm/feature/placeholder/index.js.map +1 -1
  47. package/lib/esm/feature/table/index.js +4 -0
  48. package/lib/esm/feature/table/index.js.map +1 -1
  49. package/lib/esm/feature/toolbar/index.js +56 -22
  50. package/lib/esm/feature/toolbar/index.js.map +1 -1
  51. package/lib/esm/index.js +700 -318
  52. package/lib/esm/index.js.map +1 -1
  53. package/lib/theme/common/toolbar.css +9 -0
  54. package/lib/tsconfig.tsbuildinfo +1 -1
  55. package/lib/types/core/crepe.d.ts +2 -1
  56. package/lib/types/core/crepe.d.ts.map +1 -1
  57. package/lib/types/core/locale.d.ts +4 -0
  58. package/lib/types/core/locale.d.ts.map +1 -1
  59. package/lib/types/feature/fixed-toolbar/component.d.ts +2 -0
  60. package/lib/types/feature/fixed-toolbar/component.d.ts.map +1 -1
  61. package/lib/types/feature/fixed-toolbar/config.d.ts.map +1 -1
  62. package/lib/types/feature/fixed-toolbar/index.d.ts +16 -0
  63. package/lib/types/feature/fixed-toolbar/index.d.ts.map +1 -1
  64. package/lib/types/feature/fixed-toolbar/menu-bar.d.ts.map +1 -1
  65. package/lib/types/feature/toolbar/component.d.ts.map +1 -1
  66. package/lib/types/icons/export.d.ts +2 -0
  67. package/lib/types/icons/export.d.ts.map +1 -0
  68. package/lib/types/icons/import.d.ts +2 -0
  69. package/lib/types/icons/import.d.ts.map +1 -0
  70. package/lib/types/icons/index.d.ts +4 -0
  71. package/lib/types/icons/index.d.ts.map +1 -1
  72. package/lib/types/icons/redo.d.ts +2 -0
  73. package/lib/types/icons/redo.d.ts.map +1 -0
  74. package/lib/types/icons/undo.d.ts +2 -0
  75. package/lib/types/icons/undo.d.ts.map +1 -0
  76. package/lib/types/utils/fixed-toolbar-popup-state.d.ts +1 -0
  77. package/lib/types/utils/fixed-toolbar-popup-state.d.ts.map +1 -1
  78. package/package.json +116 -62
  79. package/src/core/crepe.ts +122 -7
  80. package/src/core/locale.ts +4 -0
  81. package/src/feature/fixed-toolbar/component.tsx +154 -53
  82. package/src/feature/fixed-toolbar/config.ts +70 -2
  83. package/src/feature/fixed-toolbar/index.ts +85 -0
  84. package/src/feature/fixed-toolbar/menu-bar.tsx +17 -3
  85. package/src/feature/toolbar/component.tsx +61 -23
  86. package/src/icons/export.ts +5 -0
  87. package/src/icons/import.ts +6 -0
  88. package/src/icons/index.ts +4 -0
  89. package/src/icons/redo.ts +5 -0
  90. package/src/icons/undo.ts +5 -0
  91. package/src/theme/common/toolbar.css +19 -0
  92. package/src/utils/fixed-toolbar-popup-state.ts +5 -0
  93. package/LICENSE +0 -21
package/lib/cjs/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var utils$1 = require('@jvs-milkdown/utils');
3
4
  var lodashEs = require('lodash-es');
4
5
  var languageData = require('@codemirror/language-data');
5
6
  var themeOneDark = require('@codemirror/theme-one-dark');
@@ -27,16 +28,16 @@ var codemirror = require('codemirror');
27
28
  var cursor$1 = require('@jvs-milkdown/kit/plugin/cursor');
28
29
  var prosemirrorVirtualCursor = require('prosemirror-virtual-cursor');
29
30
  var diffBlock = require('@jvs-milkdown/kit/component/diff-block');
31
+ var history = require('@jvs-milkdown/prose/history');
30
32
  var view$1 = require('@jvs-milkdown/kit/prose/view');
31
33
  var tables = require('@jvs-milkdown/kit/prose/tables');
32
34
  var clsx = require('clsx');
33
35
  var linkTooltip$1 = require('@jvs-milkdown/kit/component/link-tooltip');
34
36
  var imageInline = require('@jvs-milkdown/kit/component/image-inline');
35
37
  var state$1 = require('@jvs-milkdown/prose/state');
36
- var utils$1 = require('@jvs-milkdown/utils');
37
38
  var Diff = require('diff');
38
39
  var tooltip = require('@jvs-milkdown/kit/plugin/tooltip');
39
- var history = require('@jvs-milkdown/kit/prose/history');
40
+ var history$1 = require('@jvs-milkdown/kit/prose/history');
40
41
  var keymap = require('@jvs-milkdown/kit/prose/keymap');
41
42
  var model = require('@jvs-milkdown/kit/prose/model');
42
43
  var inputrules = require('@jvs-milkdown/kit/prose/inputrules');
@@ -44,7 +45,7 @@ var remarkMath = require('remark-math');
44
45
  var listItemBlock = require('@jvs-milkdown/kit/component/list-item-block');
45
46
  var tableBlock = require('@jvs-milkdown/kit/component/table-block');
46
47
  var clipboard = require('@jvs-milkdown/kit/plugin/clipboard');
47
- var history$1 = require('@jvs-milkdown/kit/plugin/history');
48
+ var history$2 = require('@jvs-milkdown/kit/plugin/history');
48
49
  var indent = require('@jvs-milkdown/kit/plugin/indent');
49
50
  var listener = require('@jvs-milkdown/kit/plugin/listener');
50
51
  var trailing = require('@jvs-milkdown/kit/plugin/trailing');
@@ -670,6 +671,31 @@ const formatPainterIcon = `
670
671
  </svg>
671
672
  `;
672
673
 
674
+ const undoIcon = `
675
+ <svg viewBox="0 0 1024 1024" version="1.1" width="20" height="20">
676
+ <path d="M328.768 243.52a42.688 42.688 0 0 0-60.352-60.352L97.92 353.664A43.008 43.008 0 0 0 85.248 384a42.56 42.56 0 0 0 12.48 30.208l170.688 170.624a42.688 42.688 0 1 0 60.352-60.288l-97.92-97.92h451.712a170.688 170.688 0 1 1 0 341.376H469.248a42.688 42.688 0 1 0 0 85.312h213.312a256 256 0 1 0 0-512H230.912l97.856-97.792z" fill="currentColor"></path>
677
+ </svg>
678
+ `;
679
+
680
+ const redoIcon = `
681
+ <svg viewBox="0 0 1024 1024" version="1.1" width="20" height="20">
682
+ <path d="M755.584 183.168a42.688 42.688 0 0 0-60.352 60.352l97.856 97.792H341.44a256 256 0 0 0 0 512h213.312a42.688 42.688 0 0 0 0-85.312H341.44a170.688 170.688 0 0 1 0-341.312h451.648l-97.856 97.856a42.688 42.688 0 0 0 60.352 60.288l170.048-170.048a42.56 42.56 0 0 0 0-61.568l-170.048-170.048z" fill="currentColor"></path>
683
+ </svg>
684
+ `;
685
+
686
+ const exportIcon = `
687
+ <svg viewBox="0 0 1024 1024" version="1.1" width="20" height="20">
688
+ <path d="M452.288 725.12L246.016 537.6c-4.928-4.48-10.432-8.832-14.72-13.696-20.8-23.232-21.312-42.944-2.304-59.52 17.664-15.36 43.392-14.976 65.536 4.48 49.088 43.328 32.256 27.712 80.512 71.744l69.376 63.36 11.968 10.688v-173.44c0-33.92-0.128-80.96-0.32-128.448-0.192-51.52-0.32-103.616-0.32-140.16L455.68 163.84a183.04 183.04 0 0 1 0.704-24.896c3.52-29.248 19.328-43.712 45.248-42.88 25.344 0.768 41.088 15.872 42.688 45.504 1.28 22.848 1.024 45.888 0.768 68.864l-0.128 27.136c0 50.048 0.128 112.832 0.256 176.384 0.192 71.552 0.384 144.192 0.32 200.704 74.432-68.224 131.968-119.68 162.688-147.584 7.424-6.72 14.912-14.272 24-18.304 18.688-8.448 37.76-7.808 52.8 7.36 14.72 14.72 16.384 31.36 3.968 48.192-3.84 5.248-8.64 10.112-13.44 14.656-45.76 41.92-189.76 173.248-236.16 214.464a62.336 62.336 0 0 1-8.064 6.016 43.712 43.712 0 0 1-15.872 9.792c-20.544 7.104-37.504-0.512-51.968-13.952l-11.2-10.24z m430.784-37.248c24-0.576 42.176 13.44 43.328 39.04 1.728 38.208 2.944 76.992-1.088 115.136-5.312 50.752-51.52 84.16-114.752 85.312-50.112 0.832-100.224 0.64-150.4 0.512l-64.832-0.128H422.272a26252.8 26252.8 0 0 1-194.432-0.192c-90.624-0.512-130.752-37.696-131.392-120.64l-0.192-17.408c-0.32-19.84-0.576-39.68 0.768-59.392 1.92-27.904 20.48-43.648 45.76-42.368 23.488 1.152 37.312 15.296 40.064 42.368 0.896 9.152 0.832 18.432 0.704 27.648l-0.064 10.816c0.384 71.744 7.36 78.208 88.128 78.272 117.248 0.128 234.432 0.128 351.68 0l43.968 0.192c36.096 0.064 72.192 0.192 108.288-0.448 52.672-0.96 64-12.096 65.152-60.288a494.464 494.464 0 0 0 0-21.76 365.632 365.632 0 0 1 0.704-35.84c2.24-26.048 17.92-40.32 41.664-40.832z" fill="currentColor"></path>
689
+ </svg>
690
+ `;
691
+
692
+ const importIcon = `
693
+ <svg viewBox="0 0 1024 1024" version="1.1" width="20" height="20">
694
+ <path d="M838.656 594.432a41.152 41.152 0 0 0-40.768 41.472v176.128c0 0.384-0.384 0.96-1.216 0.96H210.688c-0.768 0-1.216-0.576-1.216-0.96V275.968c0-0.384 0.448-0.96 1.216-0.96h143.616a41.088 41.088 0 0 0 41.28-41.472A41.088 41.088 0 0 0 354.304 192H210.688C165.12 192 128 229.76 128 275.968v536.064C128 858.368 165.12 896 210.688 896h585.984c45.632 0 82.688-37.632 82.688-83.968V635.904a41.152 41.152 0 0 0-40.704-41.472z" fill="currentColor"></path>
695
+ <path d="M895.744 229.056a40.896 40.896 0 0 0-44.864-36.8c-4.032 0.448-99.456 11.52-200.576 68.352-106.24 59.776-179.2 147.648-214.656 257.28l-44.672-131.584a40.576 40.576 0 0 0-51.84-25.792 41.664 41.664 0 0 0-25.152 52.928l80.064 235.968a40.576 40.576 0 0 0 51.84 25.6l0.512-0.128 232.192-85.312a41.728 41.728 0 0 0 24-52.928 40.576 40.576 0 0 0-51.648-25.152l-144 52.928c26.048-99.2 86.464-176.256 180.416-229.76a508.672 508.672 0 0 1 172.416-59.904c22.336-2.56 38.4-22.976 35.968-45.696z" fill="currentColor"></path>
696
+ </svg>
697
+ `;
698
+
673
699
  const defaultConfig = {
674
700
  [CrepeFeature.CodeMirror]: {
675
701
  theme: themeOneDark.oneDark,
@@ -801,6 +827,8 @@ const zhCN = {
801
827
  "customMenu.colorPurple": "\u7D2B\u8272",
802
828
  "customMenu.colorGray": "\u7070\u8272",
803
829
  "customMenu.insertTable": "\u63D2\u5165\u652F\u6301\u5BCC\u6587\u672C\u7684\u8868\u683C",
830
+ "customMenu.export": "\u5BFC\u51FA",
831
+ "customMenu.import": "\u5BFC\u5165",
804
832
  "customMenu.fontDefault": "\u9ED8\u8BA4",
805
833
  "font.fangSong": "\u4EFF\u5B8B",
806
834
  "font.stFangsong": "\u534E\u6587\u4EFF\u5B8B",
@@ -948,6 +976,8 @@ const enUS = {
948
976
  "customMenu.colorPurple": "Purple",
949
977
  "customMenu.colorGray": "Gray",
950
978
  "customMenu.insertTable": "Insert Table",
979
+ "customMenu.export": "Export",
980
+ "customMenu.import": "Import",
951
981
  "customMenu.fontDefault": "Default",
952
982
  "font.fangSong": "FangSong",
953
983
  "font.stFangsong": "STFangsong",
@@ -4872,6 +4902,10 @@ function decrementPopupCount() {
4872
4902
  listeners.forEach((fn) => fn());
4873
4903
  }
4874
4904
  }
4905
+ function resetPopupCount() {
4906
+ _popupCount = 0;
4907
+ listeners.forEach((fn) => fn());
4908
+ }
4875
4909
 
4876
4910
  function getGroups(config, ctx) {
4877
4911
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
@@ -5727,7 +5761,8 @@ const Toolbar = vue.defineComponent({
5727
5761
  const container = toolbarContainerRef.value;
5728
5762
  if (!isFixed) {
5729
5763
  const view = ctx.get(core.editorViewCtx);
5730
- container.style.maxWidth = `${view.dom.clientWidth - 32}px`;
5764
+ const containerDOM = view.dom.closest(".milkdown-editor-container") || view.dom.closest(".milkdown") || view.dom;
5765
+ container.style.maxWidth = `${containerDOM.clientWidth - 32}px`;
5731
5766
  }
5732
5767
  let containerWidth;
5733
5768
  if (isFixed) {
@@ -5747,16 +5782,13 @@ const Toolbar = vue.defineComponent({
5747
5782
  }
5748
5783
  } else {
5749
5784
  const view = ctx.get(core.editorViewCtx);
5750
- containerWidth = view.dom.clientWidth - 32;
5785
+ const containerDOM = view.dom.closest(".milkdown-editor-container") || view.dom.closest(".milkdown") || view.dom;
5786
+ containerWidth = containerDOM.clientWidth - 32;
5751
5787
  }
5752
- if (containerWidth === lastContainerWidth) {
5753
- return;
5754
- }
5755
- lastContainerWidth = containerWidth;
5756
5788
  if (showOverflowMenu.value) {
5757
5789
  showOverflowMenu.value = false;
5758
5790
  }
5759
- const MORE_BUTTON_WIDTH = 44;
5791
+ const MORE_BUTTON_WIDTH = 56;
5760
5792
  const children = Array.from(container.children);
5761
5793
  const toolbarChildren = children.filter(
5762
5794
  (el) => el.style.position !== "fixed" && el.dataset.overflowButton !== "true"
@@ -5766,6 +5798,13 @@ const Toolbar = vue.defineComponent({
5766
5798
  const child = toolbarChildren[i];
5767
5799
  totalWidth += measureChild(child, i);
5768
5800
  }
5801
+ if (totalWidth === 0) {
5802
+ return;
5803
+ }
5804
+ if (containerWidth === lastContainerWidth) {
5805
+ return;
5806
+ }
5807
+ lastContainerWidth = containerWidth;
5769
5808
  if (totalWidth <= containerWidth) {
5770
5809
  overflowVisibleCount.value = Infinity;
5771
5810
  totalSectionCount.value = toolbarChildren.length;
@@ -5958,6 +5997,14 @@ const Toolbar = vue.defineComponent({
5958
5997
  } else {
5959
5998
  const view = ctx.get(core.editorViewCtx);
5960
5999
  overflowResizeObserver.observe(view.dom);
6000
+ const containerDOM = view.dom.closest(".milkdown-editor-container");
6001
+ if (containerDOM) {
6002
+ overflowResizeObserver.observe(containerDOM);
6003
+ }
6004
+ const rootDOM = view.dom.closest(".milkdown");
6005
+ if (rootDOM) {
6006
+ overflowResizeObserver.observe(rootDOM);
6007
+ }
5961
6008
  }
5962
6009
  computeOverflow();
5963
6010
  };
@@ -5986,6 +6033,20 @@ const Toolbar = vue.defineComponent({
5986
6033
  lastContainerWidth = 0;
5987
6034
  setTimeout(computeOverflow, 0);
5988
6035
  });
6036
+ vue.watch(
6037
+ () => {
6038
+ var _a;
6039
+ return (_a = props.show) == null ? void 0 : _a.value;
6040
+ },
6041
+ (val) => {
6042
+ if (val) {
6043
+ cachedWidths.clear();
6044
+ overflowVisibleCount.value = Infinity;
6045
+ lastContainerWidth = 0;
6046
+ setTimeout(computeOverflow, 0);
6047
+ }
6048
+ }
6049
+ );
5989
6050
  const onClick = (fn) => (e) => {
5990
6051
  e.preventDefault();
5991
6052
  if (ctx) fn(ctx);
@@ -6444,7 +6505,7 @@ const Toolbar = vue.defineComponent({
6444
6505
  {
6445
6506
  style: {
6446
6507
  position: "relative",
6447
- display: isSectionOverflowed(0) ? "none" : "flex",
6508
+ display: isSectionOverflowed(1) ? "none" : "flex",
6448
6509
  flexShrink: 0
6449
6510
  }
6450
6511
  },
@@ -6489,7 +6550,7 @@ const Toolbar = vue.defineComponent({
6489
6550
  style: {
6490
6551
  margin: "0 4px",
6491
6552
  alignSelf: "center",
6492
- display: isSectionOverflowed(1) ? "none" : void 0,
6553
+ display: isSectionOverflowed(2) ? "none" : void 0,
6493
6554
  flexShrink: 0
6494
6555
  }
6495
6556
  }
@@ -6502,7 +6563,7 @@ const Toolbar = vue.defineComponent({
6502
6563
  onMouseleave: handleFontFamilyLeave,
6503
6564
  style: {
6504
6565
  position: "relative",
6505
- display: isSectionOverflowed(2) ? "none" : "flex",
6566
+ display: isSectionOverflowed(3) ? "none" : "flex",
6506
6567
  alignItems: "center",
6507
6568
  padding: "0 6px",
6508
6569
  minWidth: "50px",
@@ -6544,7 +6605,7 @@ const Toolbar = vue.defineComponent({
6544
6605
  onMouseleave: handleFontSizeLeave,
6545
6606
  style: {
6546
6607
  position: "relative",
6547
- display: isSectionOverflowed(3) ? "none" : "flex",
6608
+ display: isSectionOverflowed(4) ? "none" : "flex",
6548
6609
  alignItems: "center",
6549
6610
  padding: "0 6px",
6550
6611
  minWidth: "40px",
@@ -6572,7 +6633,7 @@ const Toolbar = vue.defineComponent({
6572
6633
  style: {
6573
6634
  margin: "0 4px",
6574
6635
  alignSelf: "center",
6575
- display: isSectionOverflowed(4) ? "none" : void 0,
6636
+ display: isSectionOverflowed(5) ? "none" : void 0,
6576
6637
  flexShrink: 0
6577
6638
  }
6578
6639
  }
@@ -6585,7 +6646,7 @@ const Toolbar = vue.defineComponent({
6585
6646
  onMouseleave: handleAlignLeave,
6586
6647
  style: {
6587
6648
  position: "relative",
6588
- display: isSectionOverflowed(5) ? "none" : "flex",
6649
+ display: isSectionOverflowed(6) ? "none" : "flex",
6589
6650
  alignItems: "center",
6590
6651
  padding: "0 6px",
6591
6652
  flexShrink: 0
@@ -6614,7 +6675,7 @@ const Toolbar = vue.defineComponent({
6614
6675
  onMouseleave: handleColorLeave,
6615
6676
  style: {
6616
6677
  position: "relative",
6617
- display: isSectionOverflowed(6) ? "none" : "flex",
6678
+ display: isSectionOverflowed(7) ? "none" : "flex",
6618
6679
  alignItems: "center",
6619
6680
  padding: "0 4px",
6620
6681
  flexShrink: 0
@@ -6642,7 +6703,7 @@ const Toolbar = vue.defineComponent({
6642
6703
  )
6643
6704
  ),
6644
6705
  (() => {
6645
- let sectionIdx = 7;
6706
+ let sectionIdx = 8;
6646
6707
  return nonHeadingGroups.map((group, groupIndex) => {
6647
6708
  const items = group.items.map((item) => {
6648
6709
  const idx = sectionIdx;
@@ -6668,6 +6729,7 @@ const Toolbar = vue.defineComponent({
6668
6729
  "toolbar-item",
6669
6730
  ctx && checkActive(item.active) && "active"
6670
6731
  ),
6732
+ "data-key": item.key,
6671
6733
  onPointerdown: (e) => {
6672
6734
  if (isTable) {
6673
6735
  e.preventDefault();
@@ -7504,11 +7566,12 @@ const Toolbar = vue.defineComponent({
7504
7566
  (() => {
7505
7567
  const cutoff = overflowVisibleCount.value;
7506
7568
  const items = [];
7507
- const renderIconButton = (iconHtml, title, isActive, onClick2, hasDropdown = false, onMouseEnter, onMouseLeave) => /* @__PURE__ */ vue.h(
7569
+ const renderIconButton = (iconHtml, title, isActive, onClick2, hasDropdown = false, onMouseEnter, onMouseLeave, key) => /* @__PURE__ */ vue.h(
7508
7570
  "button",
7509
7571
  {
7510
7572
  type: "button",
7511
7573
  class: clsx("toolbar-item", isActive && "active"),
7574
+ "data-key": key,
7512
7575
  title,
7513
7576
  onPointerdown: (e) => {
7514
7577
  e.preventDefault();
@@ -7560,7 +7623,7 @@ const Toolbar = vue.defineComponent({
7560
7623
  )
7561
7624
  );
7562
7625
  }
7563
- if (2 >= cutoff) {
7626
+ if (3 >= cutoff) {
7564
7627
  items.push(
7565
7628
  renderIconButton(
7566
7629
  textIcon,
@@ -7573,7 +7636,7 @@ const Toolbar = vue.defineComponent({
7573
7636
  )
7574
7637
  );
7575
7638
  }
7576
- if (3 >= cutoff) {
7639
+ if (4 >= cutoff) {
7577
7640
  items.push(
7578
7641
  renderIconButton(
7579
7642
  textIcon,
@@ -7586,7 +7649,7 @@ const Toolbar = vue.defineComponent({
7586
7649
  )
7587
7650
  );
7588
7651
  }
7589
- if (5 >= cutoff) {
7652
+ if (6 >= cutoff) {
7590
7653
  items.push(
7591
7654
  renderIconButton(
7592
7655
  currentAlignIndent.value.align === "center" ? alignCenterIcon : currentAlignIndent.value.align === "right" ? alignRightIcon : alignLeftIcon,
@@ -7599,7 +7662,7 @@ const Toolbar = vue.defineComponent({
7599
7662
  )
7600
7663
  );
7601
7664
  }
7602
- if (6 >= cutoff) {
7665
+ if (7 >= cutoff) {
7603
7666
  items.push(
7604
7667
  renderIconButton(
7605
7668
  fontColorIcon,
@@ -7612,7 +7675,7 @@ const Toolbar = vue.defineComponent({
7612
7675
  )
7613
7676
  );
7614
7677
  }
7615
- let fmtIdx = 7;
7678
+ let fmtIdx = 8;
7616
7679
  for (const group of nonHeadingGroups) {
7617
7680
  for (const item of group.items) {
7618
7681
  const idx = fmtIdx;
@@ -7630,7 +7693,8 @@ const Toolbar = vue.defineComponent({
7630
7693
  },
7631
7694
  isTable,
7632
7695
  isTable ? handleTableEnter : void 0,
7633
- isTable ? handleTableLeave : void 0
7696
+ isTable ? handleTableLeave : void 0,
7697
+ item.key
7634
7698
  )
7635
7699
  );
7636
7700
  }
@@ -7706,7 +7770,7 @@ const ToggleSwitch = vue.defineComponent({
7706
7770
  },
7707
7771
  emits: ["update:modelValue"],
7708
7772
  setup(props, { emit }) {
7709
- return () => /* @__PURE__ */ vue.h(
7773
+ return () => /* @__PURE__ */ h(
7710
7774
  "div",
7711
7775
  {
7712
7776
  onClick: (e) => {
@@ -7723,7 +7787,7 @@ const ToggleSwitch = vue.defineComponent({
7723
7787
  transition: "background-color 0.2s"
7724
7788
  }
7725
7789
  },
7726
- /* @__PURE__ */ vue.h(
7790
+ /* @__PURE__ */ h(
7727
7791
  "div",
7728
7792
  {
7729
7793
  style: {
@@ -7810,11 +7874,19 @@ const MenuBar = vue.defineComponent({
7810
7874
  { name: "\u6D45\u7D2B", value: "#F0E6FA" },
7811
7875
  { name: "\u6D45\u7C89", value: "#FDE8E9" }
7812
7876
  ];
7813
- const menuKeys = ["file", "edit", "view", "insert", "format"];
7877
+ const menuKeys = vue.computed(() => {
7878
+ var _a;
7879
+ const allKeys = ["file", "edit", "view", "insert", "format"];
7880
+ const itemsConfig = (_a = props.config) == null ? void 0 : _a.menuBarItems;
7881
+ if (!itemsConfig) return allKeys;
7882
+ return allKeys.filter(
7883
+ (key) => itemsConfig[key] !== false
7884
+ );
7885
+ });
7814
7886
  const hasSubmenu = (key) => key === "view";
7815
7887
  return () => {
7816
7888
  const state = viewState.value;
7817
- return /* @__PURE__ */ vue.h(
7889
+ return /* @__PURE__ */ h(
7818
7890
  "div",
7819
7891
  {
7820
7892
  class: "milkdown-menu-bar",
@@ -7826,7 +7898,7 @@ const MenuBar = vue.defineComponent({
7826
7898
  position: "relative"
7827
7899
  }
7828
7900
  },
7829
- /* @__PURE__ */ vue.h(
7901
+ /* @__PURE__ */ h(
7830
7902
  "div",
7831
7903
  {
7832
7904
  ref: buttonRef,
@@ -7849,7 +7921,7 @@ const MenuBar = vue.defineComponent({
7849
7921
  e.currentTarget.style.backgroundColor = "transparent";
7850
7922
  }
7851
7923
  },
7852
- /* @__PURE__ */ vue.h(
7924
+ /* @__PURE__ */ h(
7853
7925
  "span",
7854
7926
  {
7855
7927
  style: {
@@ -7860,9 +7932,9 @@ const MenuBar = vue.defineComponent({
7860
7932
  justifyContent: "center"
7861
7933
  }
7862
7934
  },
7863
- /* @__PURE__ */ vue.h(component.Icon, { icon: menuIcon })
7935
+ /* @__PURE__ */ h(component.Icon, { icon: menuIcon })
7864
7936
  ),
7865
- /* @__PURE__ */ vue.h(
7937
+ /* @__PURE__ */ h(
7866
7938
  "span",
7867
7939
  {
7868
7940
  style: {
@@ -7875,7 +7947,7 @@ const MenuBar = vue.defineComponent({
7875
7947
  "\u83DC\u5355"
7876
7948
  )
7877
7949
  ),
7878
- showMenu.value ? /* @__PURE__ */ vue.h(
7950
+ showMenu.value ? /* @__PURE__ */ h(
7879
7951
  "div",
7880
7952
  {
7881
7953
  ref: mainRef,
@@ -7899,10 +7971,10 @@ const MenuBar = vue.defineComponent({
7899
7971
  e.stopPropagation();
7900
7972
  }
7901
7973
  },
7902
- menuKeys.map((menuKey) => {
7974
+ menuKeys.value.map((menuKey) => {
7903
7975
  const isHovered = activeSubmenu.value === menuKey;
7904
7976
  const label = i18n(props.ctx, `menuBar.${menuKey}`) || menuKey;
7905
- return /* @__PURE__ */ vue.h(
7977
+ return /* @__PURE__ */ h(
7906
7978
  "div",
7907
7979
  {
7908
7980
  key: menuKey,
@@ -7924,7 +7996,7 @@ const MenuBar = vue.defineComponent({
7924
7996
  backgroundColor: isHovered ? "var(--crepe-color-hover, #f5f5f5)" : "transparent"
7925
7997
  }
7926
7998
  },
7927
- /* @__PURE__ */ vue.h(
7999
+ /* @__PURE__ */ h(
7928
8000
  "span",
7929
8001
  {
7930
8002
  style: {
@@ -7934,7 +8006,7 @@ const MenuBar = vue.defineComponent({
7934
8006
  },
7935
8007
  label
7936
8008
  ),
7937
- hasSubmenu(menuKey) ? /* @__PURE__ */ vue.h(
8009
+ hasSubmenu(menuKey) ? /* @__PURE__ */ h(
7938
8010
  "span",
7939
8011
  {
7940
8012
  style: {
@@ -7943,7 +8015,7 @@ const MenuBar = vue.defineComponent({
7943
8015
  display: "flex"
7944
8016
  }
7945
8017
  },
7946
- /* @__PURE__ */ vue.h(
8018
+ /* @__PURE__ */ h(
7947
8019
  "svg",
7948
8020
  {
7949
8021
  width: "12",
@@ -7955,10 +8027,10 @@ const MenuBar = vue.defineComponent({
7955
8027
  "stroke-linecap": "round",
7956
8028
  "stroke-linejoin": "round"
7957
8029
  },
7958
- /* @__PURE__ */ vue.h("polyline", { points: "9 18 15 12 9 6" })
8030
+ /* @__PURE__ */ h("polyline", { points: "9 18 15 12 9 6" })
7959
8031
  )
7960
8032
  ) : null,
7961
- menuKey === "view" && isHovered ? /* @__PURE__ */ vue.h(
8033
+ menuKey === "view" && isHovered ? /* @__PURE__ */ h(
7962
8034
  "div",
7963
8035
  {
7964
8036
  style: {
@@ -7976,7 +8048,7 @@ const MenuBar = vue.defineComponent({
7976
8048
  cursor: "default"
7977
8049
  }
7978
8050
  },
7979
- /* @__PURE__ */ vue.h(
8051
+ /* @__PURE__ */ h(
7980
8052
  "div",
7981
8053
  {
7982
8054
  style: {
@@ -7986,7 +8058,7 @@ const MenuBar = vue.defineComponent({
7986
8058
  alignItems: "center"
7987
8059
  }
7988
8060
  },
7989
- /* @__PURE__ */ vue.h(
8061
+ /* @__PURE__ */ h(
7990
8062
  "span",
7991
8063
  {
7992
8064
  style: {
@@ -7996,7 +8068,7 @@ const MenuBar = vue.defineComponent({
7996
8068
  },
7997
8069
  i18n(props.ctx, "view.title") || "\u6807\u9898"
7998
8070
  ),
7999
- /* @__PURE__ */ vue.h(
8071
+ /* @__PURE__ */ h(
8000
8072
  ToggleSwitch,
8001
8073
  {
8002
8074
  modelValue: state.showTitle,
@@ -8004,7 +8076,7 @@ const MenuBar = vue.defineComponent({
8004
8076
  }
8005
8077
  )
8006
8078
  ),
8007
- /* @__PURE__ */ vue.h(
8079
+ /* @__PURE__ */ h(
8008
8080
  "div",
8009
8081
  {
8010
8082
  style: {
@@ -8014,7 +8086,7 @@ const MenuBar = vue.defineComponent({
8014
8086
  alignItems: "center"
8015
8087
  }
8016
8088
  },
8017
- /* @__PURE__ */ vue.h(
8089
+ /* @__PURE__ */ h(
8018
8090
  "span",
8019
8091
  {
8020
8092
  style: {
@@ -8024,7 +8096,7 @@ const MenuBar = vue.defineComponent({
8024
8096
  },
8025
8097
  i18n(props.ctx, "view.outline") || "\u5927\u7EB2"
8026
8098
  ),
8027
- /* @__PURE__ */ vue.h(
8099
+ /* @__PURE__ */ h(
8028
8100
  ToggleSwitch,
8029
8101
  {
8030
8102
  modelValue: state.outlineVisible,
@@ -8032,7 +8104,7 @@ const MenuBar = vue.defineComponent({
8032
8104
  }
8033
8105
  )
8034
8106
  ),
8035
- /* @__PURE__ */ vue.h(
8107
+ /* @__PURE__ */ h(
8036
8108
  "div",
8037
8109
  {
8038
8110
  style: {
@@ -8042,7 +8114,7 @@ const MenuBar = vue.defineComponent({
8042
8114
  alignItems: "center"
8043
8115
  }
8044
8116
  },
8045
- /* @__PURE__ */ vue.h(
8117
+ /* @__PURE__ */ h(
8046
8118
  "span",
8047
8119
  {
8048
8120
  style: {
@@ -8052,7 +8124,7 @@ const MenuBar = vue.defineComponent({
8052
8124
  },
8053
8125
  i18n(props.ctx, "view.cover") || "\u5C01\u9762"
8054
8126
  ),
8055
- /* @__PURE__ */ vue.h(
8127
+ /* @__PURE__ */ h(
8056
8128
  ToggleSwitch,
8057
8129
  {
8058
8130
  modelValue: state.showCover,
@@ -8068,7 +8140,7 @@ const MenuBar = vue.defineComponent({
8068
8140
  }
8069
8141
  )
8070
8142
  ),
8071
- /* @__PURE__ */ vue.h(
8143
+ /* @__PURE__ */ h(
8072
8144
  "div",
8073
8145
  {
8074
8146
  style: {
@@ -8078,7 +8150,7 @@ const MenuBar = vue.defineComponent({
8078
8150
  }
8079
8151
  }
8080
8152
  ),
8081
- /* @__PURE__ */ vue.h(
8153
+ /* @__PURE__ */ h(
8082
8154
  "div",
8083
8155
  {
8084
8156
  style: {
@@ -8088,7 +8160,7 @@ const MenuBar = vue.defineComponent({
8088
8160
  alignItems: "center"
8089
8161
  }
8090
8162
  },
8091
- /* @__PURE__ */ vue.h(
8163
+ /* @__PURE__ */ h(
8092
8164
  "span",
8093
8165
  {
8094
8166
  style: {
@@ -8099,7 +8171,7 @@ const MenuBar = vue.defineComponent({
8099
8171
  i18n(props.ctx, "view.docBackground") || "\u6587\u6863\u80CC\u666F"
8100
8172
  )
8101
8173
  ),
8102
- /* @__PURE__ */ vue.h(
8174
+ /* @__PURE__ */ h(
8103
8175
  "div",
8104
8176
  {
8105
8177
  style: {
@@ -8109,7 +8181,7 @@ const MenuBar = vue.defineComponent({
8109
8181
  gap: "6px"
8110
8182
  }
8111
8183
  },
8112
- bgColors.map((bg) => /* @__PURE__ */ vue.h(
8184
+ bgColors.map((bg) => /* @__PURE__ */ h(
8113
8185
  "div",
8114
8186
  {
8115
8187
  key: bg.value || "default",
@@ -8131,7 +8203,7 @@ const MenuBar = vue.defineComponent({
8131
8203
  justifyContent: "center"
8132
8204
  }
8133
8205
  },
8134
- bg.value === null ? /* @__PURE__ */ vue.h(
8206
+ bg.value === null ? /* @__PURE__ */ h(
8135
8207
  "div",
8136
8208
  {
8137
8209
  style: {
@@ -8144,7 +8216,7 @@ const MenuBar = vue.defineComponent({
8144
8216
  borderRadius: "3px"
8145
8217
  }
8146
8218
  },
8147
- /* @__PURE__ */ vue.h(
8219
+ /* @__PURE__ */ h(
8148
8220
  "div",
8149
8221
  {
8150
8222
  style: {
@@ -8162,7 +8234,7 @@ const MenuBar = vue.defineComponent({
8162
8234
  ) : null
8163
8235
  ))
8164
8236
  ),
8165
- /* @__PURE__ */ vue.h(
8237
+ /* @__PURE__ */ h(
8166
8238
  "div",
8167
8239
  {
8168
8240
  style: {
@@ -8172,7 +8244,7 @@ const MenuBar = vue.defineComponent({
8172
8244
  }
8173
8245
  }
8174
8246
  ),
8175
- /* @__PURE__ */ vue.h(
8247
+ /* @__PURE__ */ h(
8176
8248
  "div",
8177
8249
  {
8178
8250
  style: {
@@ -8182,7 +8254,7 @@ const MenuBar = vue.defineComponent({
8182
8254
  alignItems: "center"
8183
8255
  }
8184
8256
  },
8185
- /* @__PURE__ */ vue.h(
8257
+ /* @__PURE__ */ h(
8186
8258
  "span",
8187
8259
  {
8188
8260
  style: {
@@ -8193,7 +8265,7 @@ const MenuBar = vue.defineComponent({
8193
8265
  i18n(props.ctx, "view.editorWidth") || "\u5185\u5BB9\u5BBD\u5EA6"
8194
8266
  )
8195
8267
  ),
8196
- /* @__PURE__ */ vue.h(
8268
+ /* @__PURE__ */ h(
8197
8269
  "div",
8198
8270
  {
8199
8271
  style: {
@@ -8215,7 +8287,7 @@ const MenuBar = vue.defineComponent({
8215
8287
  key: "full",
8216
8288
  labelKey: "view.widthFull"
8217
8289
  }
8218
- ].map(({ key, labelKey }) => /* @__PURE__ */ vue.h(
8290
+ ].map(({ key, labelKey }) => /* @__PURE__ */ h(
8219
8291
  "button",
8220
8292
  {
8221
8293
  key,
@@ -8438,70 +8510,161 @@ const FixedToolbarComponent = vue.defineComponent({
8438
8510
  hide: { type: Function, required: true },
8439
8511
  show: { type: Object, required: true },
8440
8512
  selection: { type: Object, required: true },
8441
- config: { type: Object, required: false }
8513
+ config: { type: Object, required: false },
8514
+ canUndo: { type: Object, required: true },
8515
+ canRedo: { type: Object, required: true }
8442
8516
  },
8443
8517
  setup(props) {
8444
8518
  const showShortcuts = vue.ref(false);
8445
- return () => /* @__PURE__ */ vue.h(
8446
- "div",
8447
- {
8448
- style: {
8449
- display: "flex",
8450
- alignItems: "center",
8451
- justifyContent: "center",
8452
- width: "100%",
8453
- gap: "0px"
8454
- }
8455
- },
8456
- /* @__PURE__ */ vue.h(MenuBar, { ctx: props.ctx, config: props.config }),
8457
- /* @__PURE__ */ vue.h(
8458
- "div",
8459
- {
8460
- style: {
8461
- width: "1px",
8462
- minWidth: "1px",
8463
- height: "20px",
8464
- backgroundColor: "var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))"
8465
- }
8466
- }
8467
- ),
8468
- /* @__PURE__ */ vue.h(
8469
- Toolbar,
8470
- {
8471
- ctx: props.ctx,
8472
- hide: props.hide,
8473
- show: props.show,
8474
- selection: props.selection,
8475
- config: props.config,
8476
- isFixed: true
8477
- }
8478
- ),
8479
- /* @__PURE__ */ vue.h(
8519
+ vue.onMounted(() => {
8520
+ const handleShowShortcuts = () => {
8521
+ showShortcuts.value = true;
8522
+ };
8523
+ window.addEventListener("milkdown-show-shortcuts", handleShowShortcuts);
8524
+ vue.onUnmounted(() => {
8525
+ window.removeEventListener(
8526
+ "milkdown-show-shortcuts",
8527
+ handleShowShortcuts
8528
+ );
8529
+ });
8530
+ });
8531
+ return () => {
8532
+ var _a, _b, _c, _d;
8533
+ props.selection.value;
8534
+ const canUndo = (typeof props.canUndo === "boolean" ? props.canUndo : (_a = props.canUndo) == null ? void 0 : _a.value) || false;
8535
+ const canRedo = (typeof props.canRedo === "boolean" ? props.canRedo : (_b = props.canRedo) == null ? void 0 : _b.value) || false;
8536
+ return /* @__PURE__ */ h(
8480
8537
  "div",
8481
8538
  {
8482
8539
  style: {
8483
- width: "1px",
8484
- minWidth: "1px",
8485
- height: "20px",
8486
- flexShrink: 0,
8487
- backgroundColor: "var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))"
8488
- }
8489
- }
8490
- ),
8491
- /* @__PURE__ */ vue.h(
8492
- "button",
8493
- {
8494
- type: "button",
8495
- class: "toolbar-shortcut-btn",
8496
- title: i18n(props.ctx, "shortcuts.title"),
8497
- onClick: () => {
8498
- showShortcuts.value = true;
8540
+ display: "flex",
8541
+ alignItems: "center",
8542
+ justifyContent: "center",
8543
+ width: "100%",
8544
+ gap: "0px",
8545
+ minWidth: "0",
8546
+ overflow: "hidden"
8499
8547
  }
8500
8548
  },
8501
- /* @__PURE__ */ vue.h(component.Icon, { icon: keyboardIcon })
8502
- ),
8503
- showShortcuts.value && /* @__PURE__ */ vue.h(ShortcutHelpModal, { ctx: props.ctx, visible: showShortcuts })
8504
- );
8549
+ ((_c = props.config) == null ? void 0 : _c.showMenuBar) !== false && [
8550
+ /* @__PURE__ */ h(MenuBar, { ctx: props.ctx, config: props.config }),
8551
+ /* @__PURE__ */ h(
8552
+ "div",
8553
+ {
8554
+ style: {
8555
+ width: "1px",
8556
+ minWidth: "1px",
8557
+ height: "20px",
8558
+ backgroundColor: "var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))"
8559
+ }
8560
+ }
8561
+ )
8562
+ ],
8563
+ ((_d = props.config) == null ? void 0 : _d.showHistory) !== false && [
8564
+ /* @__PURE__ */ h(
8565
+ "button",
8566
+ {
8567
+ type: "button",
8568
+ class: ["toolbar-item", !canUndo && "disabled"],
8569
+ disabled: !canUndo,
8570
+ title: "\u64A4\u9500",
8571
+ onPointerdown: (e) => {
8572
+ e.preventDefault();
8573
+ e.stopPropagation();
8574
+ },
8575
+ onClick: (e) => {
8576
+ e.preventDefault();
8577
+ e.stopPropagation();
8578
+ if (canUndo) {
8579
+ props.ctx.get(core.commandsCtx).call("Undo");
8580
+ }
8581
+ },
8582
+ style: {
8583
+ display: "flex",
8584
+ alignItems: "center",
8585
+ justifyContent: "center",
8586
+ border: "none",
8587
+ background: "transparent",
8588
+ cursor: canUndo ? "pointer" : "default",
8589
+ padding: "6px",
8590
+ borderRadius: "4px",
8591
+ color: canUndo ? "#363b4c" : "#c0c4cc",
8592
+ "--toolbar-icon-color": canUndo ? "#363b4c" : "#c0c4cc"
8593
+ }
8594
+ },
8595
+ /* @__PURE__ */ h(
8596
+ "span",
8597
+ {
8598
+ style: { display: "inline-flex", alignItems: "center" },
8599
+ innerHTML: undoIcon
8600
+ }
8601
+ )
8602
+ ),
8603
+ /* @__PURE__ */ h(
8604
+ "button",
8605
+ {
8606
+ type: "button",
8607
+ class: ["toolbar-item", !canRedo && "disabled"],
8608
+ disabled: !canRedo,
8609
+ title: "\u6062\u590D",
8610
+ onPointerdown: (e) => {
8611
+ e.preventDefault();
8612
+ e.stopPropagation();
8613
+ },
8614
+ onClick: (e) => {
8615
+ e.preventDefault();
8616
+ e.stopPropagation();
8617
+ if (canRedo) {
8618
+ props.ctx.get(core.commandsCtx).call("Redo");
8619
+ }
8620
+ },
8621
+ style: {
8622
+ display: "flex",
8623
+ alignItems: "center",
8624
+ justifyContent: "center",
8625
+ border: "none",
8626
+ background: "transparent",
8627
+ cursor: canRedo ? "pointer" : "default",
8628
+ padding: "6px",
8629
+ borderRadius: "4px",
8630
+ color: canRedo ? "#363b4c" : "#c0c4cc",
8631
+ "--toolbar-icon-color": canRedo ? "#363b4c" : "#c0c4cc"
8632
+ }
8633
+ },
8634
+ /* @__PURE__ */ h(
8635
+ "span",
8636
+ {
8637
+ style: { display: "inline-flex", alignItems: "center" },
8638
+ innerHTML: redoIcon
8639
+ }
8640
+ )
8641
+ ),
8642
+ /* @__PURE__ */ h(
8643
+ "div",
8644
+ {
8645
+ style: {
8646
+ width: "1px",
8647
+ minWidth: "1px",
8648
+ height: "20px",
8649
+ backgroundColor: "var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))"
8650
+ }
8651
+ }
8652
+ )
8653
+ ],
8654
+ /* @__PURE__ */ h(
8655
+ Toolbar,
8656
+ {
8657
+ ctx: props.ctx,
8658
+ hide: props.hide,
8659
+ show: props.show,
8660
+ selection: props.selection,
8661
+ config: props.config,
8662
+ isFixed: true
8663
+ }
8664
+ ),
8665
+ showShortcuts.value && /* @__PURE__ */ h(ShortcutHelpModal, { ctx: props.ctx, visible: showShortcuts })
8666
+ );
8667
+ };
8505
8668
  }
8506
8669
  });
8507
8670
 
@@ -8927,6 +9090,65 @@ function buildDefaultFixedToolbar(builder, _config, ctx) {
8927
9090
  }
8928
9091
  });
8929
9092
  }
9093
+ const documentGroup = builder.addGroup("document", "Document");
9094
+ if ((_config == null ? void 0 : _config.showExport) !== false) {
9095
+ documentGroup.addItem("export", {
9096
+ label: ctx ? i18n(ctx, "customMenu.export") || "\u5BFC\u51FA" : "\u5BFC\u51FA",
9097
+ icon: exportIcon,
9098
+ active: () => false,
9099
+ onRun: (ctx2) => {
9100
+ const markdown = utils.getMarkdown()(ctx2);
9101
+ if (_config == null ? void 0 : _config.onExport) {
9102
+ _config.onExport(markdown, ctx2);
9103
+ } else {
9104
+ const blob = new Blob([markdown], {
9105
+ type: "text/markdown;charset=utf-8;"
9106
+ });
9107
+ const url = URL.createObjectURL(blob);
9108
+ const link = document.createElement("a");
9109
+ link.href = url;
9110
+ link.download = "document.md";
9111
+ link.click();
9112
+ URL.revokeObjectURL(url);
9113
+ }
9114
+ }
9115
+ });
9116
+ }
9117
+ if ((_config == null ? void 0 : _config.showImport) !== false) {
9118
+ documentGroup.addItem("import", {
9119
+ label: ctx ? i18n(ctx, "customMenu.import") || "\u5BFC\u5165" : "\u5BFC\u5165",
9120
+ icon: importIcon,
9121
+ active: () => false,
9122
+ onRun: (ctx2) => {
9123
+ if (_config == null ? void 0 : _config.onImport) {
9124
+ _config.onImport((markdown) => utils$1.replaceAll(markdown)(ctx2), ctx2);
9125
+ } else {
9126
+ const input = document.createElement("input");
9127
+ input.type = "file";
9128
+ input.accept = ".md";
9129
+ input.onchange = (e) => {
9130
+ var _a;
9131
+ const file = (_a = e.target.files) == null ? void 0 : _a[0];
9132
+ if (!file) return;
9133
+ file.text().then((text) => {
9134
+ utils$1.replaceAll(text)(ctx2);
9135
+ }).catch((err) => {
9136
+ console.error("Failed to read file:", err);
9137
+ });
9138
+ };
9139
+ input.click();
9140
+ }
9141
+ }
9142
+ });
9143
+ }
9144
+ documentGroup.addItem("shortcuts", {
9145
+ label: ctx ? i18n(ctx, "shortcuts.title") : "Shortcuts",
9146
+ icon: keyboardIcon,
9147
+ active: () => false,
9148
+ onRun: () => {
9149
+ window.dispatchEvent(new CustomEvent("milkdown-show-shortcuts"));
9150
+ }
9151
+ });
8930
9152
  return builder.build();
8931
9153
  }
8932
9154
 
@@ -9756,7 +9978,7 @@ var __accessCheck$4 = (obj, member, msg) => member.has(obj) || __typeError$4("Ca
9756
9978
  var __privateGet$4 = (obj, member, getter) => (__accessCheck$4(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
9757
9979
  var __privateAdd$4 = (obj, member, value) => member.has(obj) ? __typeError$4("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
9758
9980
  var __privateSet$4 = (obj, member, value, setter) => (__accessCheck$4(obj, member, "write to private field"), member.set(obj, value), value);
9759
- var _content$2, _app$2, _headerContent, _headerApp, _outlineContent, _outlineApp, _watcher, _selection$1, _show$1, _resizeObserver$1, _updateOutlineGeometry, _scrollContainers$1, _onDblClick, _view$1, _editorContainer;
9981
+ var _content$2, _app$2, _headerContent, _headerApp, _outlineContent, _outlineApp, _watcher, _selection$1, _show$1, _canUndo, _canRedo, _resizeObserver$1, _updateOutlineGeometry, _scrollContainers$1, _onDblClick, _view$1, _editorContainer;
9760
9982
  const fixedToolbarConfig = utils.$ctx(
9761
9983
  {},
9762
9984
  "fixedToolbarConfigCtx"
@@ -9773,6 +9995,8 @@ class FixedToolbarView {
9773
9995
  __privateAdd$4(this, _watcher);
9774
9996
  __privateAdd$4(this, _selection$1);
9775
9997
  __privateAdd$4(this, _show$1, vue.ref(true));
9998
+ __privateAdd$4(this, _canUndo, vue.ref(false));
9999
+ __privateAdd$4(this, _canRedo, vue.ref(false));
9776
10000
  __privateAdd$4(this, _resizeObserver$1);
9777
10001
  __privateAdd$4(this, _updateOutlineGeometry);
9778
10002
  __privateAdd$4(this, _scrollContainers$1, []);
@@ -9781,6 +10005,11 @@ class FixedToolbarView {
9781
10005
  __privateAdd$4(this, _editorContainer);
9782
10006
  this.update = (view) => {
9783
10007
  __privateGet$4(this, _selection$1).value = view.state.selection;
10008
+ try {
10009
+ __privateGet$4(this, _canUndo).value = history.undo(view.state);
10010
+ __privateGet$4(this, _canRedo).value = history.redo(view.state);
10011
+ } catch (e) {
10012
+ }
9784
10013
  };
9785
10014
  this.destroy = () => {
9786
10015
  if (__privateGet$4(this, _watcher)) __privateGet$4(this, _watcher).call(this);
@@ -9805,6 +10034,60 @@ class FixedToolbarView {
9805
10034
  };
9806
10035
  __privateSet$4(this, _view$1, view);
9807
10036
  const config = ctx.get(fixedToolbarConfig.key);
10037
+ const viewState = ctx.get(viewMenuStateCtx.key);
10038
+ if (config == null ? void 0 : config.useLocalStorage) {
10039
+ try {
10040
+ const stored = localStorage.getItem("jvs-milkdown-data");
10041
+ if (stored) {
10042
+ const parsed = JSON.parse(stored);
10043
+ if (parsed.outlineVisible !== void 0)
10044
+ viewState.outlineVisible = parsed.outlineVisible;
10045
+ if (parsed.outlinePosition !== void 0)
10046
+ viewState.outlinePosition = parsed.outlinePosition;
10047
+ if (parsed.outlineWidth !== void 0)
10048
+ viewState.outlineWidth = parsed.outlineWidth;
10049
+ if (parsed.documentBackground !== void 0)
10050
+ viewState.documentBackground = parsed.documentBackground;
10051
+ if (parsed.showTitle !== void 0)
10052
+ viewState.showTitle = parsed.showTitle;
10053
+ if (parsed.showCover !== void 0)
10054
+ viewState.showCover = parsed.showCover;
10055
+ if (parsed.coverUrl !== void 0)
10056
+ viewState.coverUrl = parsed.coverUrl;
10057
+ if (parsed.editorWidth !== void 0)
10058
+ viewState.editorWidth = parsed.editorWidth;
10059
+ }
10060
+ } catch (e) {
10061
+ console.error("Error loading view state from localStorage:", e);
10062
+ }
10063
+ vue.watch(
10064
+ viewState,
10065
+ (newState) => {
10066
+ try {
10067
+ const stored = localStorage.getItem("jvs-milkdown-data");
10068
+ let parsed = {};
10069
+ if (stored) {
10070
+ parsed = JSON.parse(stored);
10071
+ }
10072
+ const merged = {
10073
+ ...parsed,
10074
+ outlineVisible: newState.outlineVisible,
10075
+ outlinePosition: newState.outlinePosition,
10076
+ outlineWidth: newState.outlineWidth,
10077
+ documentBackground: newState.documentBackground,
10078
+ showTitle: newState.showTitle,
10079
+ showCover: newState.showCover,
10080
+ coverUrl: newState.coverUrl,
10081
+ editorWidth: newState.editorWidth
10082
+ };
10083
+ localStorage.setItem("jvs-milkdown-data", JSON.stringify(merged));
10084
+ } catch (e) {
10085
+ console.error("Error saving view state to localStorage:", e);
10086
+ }
10087
+ },
10088
+ { deep: true }
10089
+ );
10090
+ }
9808
10091
  const content = document.createElement("div");
9809
10092
  content.className = "milkdown-fixed-toolbar";
9810
10093
  __privateSet$4(this, _selection$1, vue.shallowRef(view.state.selection));
@@ -9815,7 +10098,9 @@ class FixedToolbarView {
9815
10098
  // No-op for fixed toolbar
9816
10099
  config,
9817
10100
  selection: __privateGet$4(this, _selection$1),
9818
- show: __privateGet$4(this, _show$1)
10101
+ show: __privateGet$4(this, _show$1),
10102
+ canUndo: __privateGet$4(this, _canUndo),
10103
+ canRedo: __privateGet$4(this, _canRedo)
9819
10104
  });
9820
10105
  app.mount(content);
9821
10106
  __privateSet$4(this, _content$2, content);
@@ -9872,9 +10157,9 @@ class FixedToolbarView {
9872
10157
  });
9873
10158
  view.dom.addEventListener("dblclick", __privateGet$4(this, _onDblClick));
9874
10159
  __privateGet$4(this, _content$2).style.transition = "margin 0.1s ease-out, width 0.1s ease-out";
9875
- const viewState = ctx.get(viewMenuStateCtx.key);
10160
+ const viewState2 = ctx.get(viewMenuStateCtx.key);
9876
10161
  if (config.outlinePosition) {
9877
- viewState.outlinePosition = config.outlinePosition;
10162
+ viewState2.outlinePosition = config.outlinePosition;
9878
10163
  }
9879
10164
  __privateSet$4(this, _updateOutlineGeometry, () => {
9880
10165
  const rootRect = root.getBoundingClientRect();
@@ -9883,7 +10168,7 @@ class FixedToolbarView {
9883
10168
  const toolbarRect = __privateGet$4(this, _content$2).getBoundingClientRect();
9884
10169
  outlineTop = Math.max(outlineTop, toolbarRect.bottom);
9885
10170
  }
9886
- if (viewState.showCover && __privateGet$4(this, _headerContent)) {
10171
+ if (viewState2.showCover && __privateGet$4(this, _headerContent)) {
9887
10172
  const coverEl = __privateGet$4(this, _headerContent).querySelector(
9888
10173
  ".milkdown-document-cover"
9889
10174
  );
@@ -9900,8 +10185,8 @@ class FixedToolbarView {
9900
10185
  }
9901
10186
  outlineContent.style.top = `${outlineTop}px`;
9902
10187
  outlineContent.style.height = `${height}px`;
9903
- if (viewState.outlineVisible) {
9904
- if (viewState.outlinePosition === "left") {
10188
+ if (viewState2.outlineVisible) {
10189
+ if (viewState2.outlinePosition === "left") {
9905
10190
  outlineContent.style.left = `${rootRect.left}px`;
9906
10191
  outlineContent.style.right = "auto";
9907
10192
  } else {
@@ -9951,16 +10236,16 @@ class FixedToolbarView {
9951
10236
  }
9952
10237
  __privateSet$4(this, _watcher, vue.watch(
9953
10238
  () => [
9954
- viewState.outlineVisible,
9955
- viewState.outlinePosition,
9956
- viewState.outlineWidth,
9957
- viewState.documentBackground,
9958
- viewState.showCover,
9959
- viewState.editorWidth
10239
+ viewState2.outlineVisible,
10240
+ viewState2.outlinePosition,
10241
+ viewState2.outlineWidth,
10242
+ viewState2.documentBackground,
10243
+ viewState2.showCover,
10244
+ viewState2.editorWidth
9960
10245
  ],
9961
10246
  () => {
9962
- if (viewState.documentBackground) {
9963
- root.style.backgroundColor = viewState.documentBackground;
10247
+ if (viewState2.documentBackground) {
10248
+ root.style.backgroundColor = viewState2.documentBackground;
9964
10249
  } else {
9965
10250
  root.style.backgroundColor = "";
9966
10251
  }
@@ -9970,20 +10255,20 @@ class FixedToolbarView {
9970
10255
  __privateGet$4(this, _content$2).style.marginLeft = "0";
9971
10256
  __privateGet$4(this, _content$2).style.marginRight = "0";
9972
10257
  if (__privateGet$4(this, _editorContainer)) {
9973
- if (viewState.outlineVisible) {
9974
- if (viewState.outlinePosition === "left") {
9975
- __privateGet$4(this, _editorContainer).style.paddingLeft = `${viewState.outlineWidth}px`;
10258
+ if (viewState2.outlineVisible) {
10259
+ if (viewState2.outlinePosition === "left") {
10260
+ __privateGet$4(this, _editorContainer).style.paddingLeft = `${viewState2.outlineWidth}px`;
9976
10261
  __privateGet$4(this, _editorContainer).style.paddingRight = "0";
9977
10262
  } else {
9978
10263
  __privateGet$4(this, _editorContainer).style.paddingLeft = "0";
9979
- __privateGet$4(this, _editorContainer).style.paddingRight = `${viewState.outlineWidth}px`;
10264
+ __privateGet$4(this, _editorContainer).style.paddingRight = `${viewState2.outlineWidth}px`;
9980
10265
  }
9981
10266
  } else {
9982
10267
  __privateGet$4(this, _editorContainer).style.paddingLeft = "0";
9983
10268
  __privateGet$4(this, _editorContainer).style.paddingRight = "0";
9984
10269
  }
9985
10270
  }
9986
- const maxWidth = editorWidthMap[viewState.editorWidth];
10271
+ const maxWidth = editorWidthMap[viewState2.editorWidth];
9987
10272
  const isFull = maxWidth === "none";
9988
10273
  const px = isFull ? "80px" : "0";
9989
10274
  __privateGet$4(this, _view$1).dom.style.maxWidth = maxWidth;
@@ -9991,7 +10276,7 @@ class FixedToolbarView {
9991
10276
  __privateGet$4(this, _view$1).dom.style.margin = isFull ? "0" : "0 auto";
9992
10277
  __privateGet$4(this, _view$1).dom.style.padding = `20px ${px} 36px`;
9993
10278
  if (__privateGet$4(this, _headerContent)) {
9994
- __privateGet$4(this, _headerContent).style.margin = isFull && !viewState.showCover ? "0 auto" : "0";
10279
+ __privateGet$4(this, _headerContent).style.margin = isFull && !viewState2.showCover ? "0 auto" : "0";
9995
10280
  __privateGet$4(this, _headerContent).style.padding = `0px`;
9996
10281
  }
9997
10282
  void vue.nextTick(() => {
@@ -10017,6 +10302,8 @@ _outlineApp = new WeakMap();
10017
10302
  _watcher = new WeakMap();
10018
10303
  _selection$1 = new WeakMap();
10019
10304
  _show$1 = new WeakMap();
10305
+ _canUndo = new WeakMap();
10306
+ _canRedo = new WeakMap();
10020
10307
  _resizeObserver$1 = new WeakMap();
10021
10308
  _updateOutlineGeometry = new WeakMap();
10022
10309
  _scrollContainers$1 = new WeakMap();
@@ -11212,9 +11499,9 @@ class LatexInlineTooltip {
11212
11499
  doc: innerDoc,
11213
11500
  plugins: [
11214
11501
  keymap.keymap({
11215
- "Mod-z": history.undo,
11216
- "Mod-Z": history.redo,
11217
- "Mod-y": history.redo,
11502
+ "Mod-z": history$1.undo,
11503
+ "Mod-Z": history$1.redo,
11504
+ "Mod-y": history$1.redo,
11218
11505
  Enter: () => {
11219
11506
  if (__privateGet$2(this, _debounceTimer)) {
11220
11507
  clearTimeout(__privateGet$2(this, _debounceTimer));
@@ -11872,7 +12159,7 @@ class CrepeBuilder {
11872
12159
  return nodes.filter((n) => n !== null);
11873
12160
  }
11874
12161
  }));
11875
- }).use(commonmark.commonmark).use(listener.listener).use(history$1.history).use(indent.indent).use(trailing.trailing).use(clipboard.clipboard).use(upload.upload).use(gfm.gfm));
12162
+ }).use(commonmark.commonmark).use(listener.listener).use(history$2.history).use(indent.indent).use(trailing.trailing).use(clipboard.clipboard).use(upload.upload).use(gfm.gfm));
11876
12163
  }
11877
12164
  /// Get the milkdown editor instance.
11878
12165
  get editor() {
@@ -11891,25 +12178,120 @@ class Crepe extends CrepeBuilder {
11891
12178
  /// The constructor of the crepe editor.
11892
12179
  /// You can pass configs to the editor to configure the editor.
11893
12180
  /// Calling the constructor will not create the editor, you need to call `create` to create the editor.
11894
- constructor({
11895
- features = {},
11896
- featureConfigs = {},
11897
- ...crepeBuilderConfig
11898
- } = {}) {
11899
- super(crepeBuilderConfig);
12181
+ constructor(config = {}) {
12182
+ var _a;
12183
+ resetPopupCount();
12184
+ const { features = {}, featureConfigs = {}, ...crepeBuilderConfig } = config;
11900
12185
  const finalConfigs = lodashEs.defaultsDeep(featureConfigs, defaultConfig);
12186
+ const fixedToolbarConfig = finalConfigs[CrepeFeature.FixedToolbar];
12187
+ if (fixedToolbarConfig == null ? void 0 : fixedToolbarConfig.useLocalStorage) {
12188
+ try {
12189
+ const stored = localStorage.getItem("jvs-milkdown-data");
12190
+ if (stored) {
12191
+ const parsed = JSON.parse(stored);
12192
+ const docId = fixedToolbarConfig.id || "default";
12193
+ if (parsed.content && parsed.content[docId] !== void 0) {
12194
+ const entry = parsed.content[docId];
12195
+ const defaultValue = typeof entry === "string" ? entry : (_a = entry == null ? void 0 : entry.markdown) != null ? _a : "";
12196
+ crepeBuilderConfig.defaultValue = defaultValue;
12197
+ }
12198
+ }
12199
+ } catch (e) {
12200
+ console.error("Error loading content from localStorage:", e);
12201
+ }
12202
+ }
12203
+ super(crepeBuilderConfig);
12204
+ this.destroy = () => {
12205
+ resetPopupCount();
12206
+ return this.editor.destroy();
12207
+ };
11901
12208
  const enabledFeatures = Object.entries({
11902
12209
  ...defaultFeatures,
11903
12210
  ...features
11904
12211
  }).filter(([, enabled]) => enabled).map(([feature]) => feature);
11905
12212
  enabledFeatures.forEach((feature) => {
11906
- const config = finalConfigs[feature];
11907
- loadFeature(feature, this.editor, config);
12213
+ const config2 = finalConfigs[feature];
12214
+ loadFeature(feature, this.editor, config2);
11908
12215
  });
12216
+ if (fixedToolbarConfig == null ? void 0 : fixedToolbarConfig.useLocalStorage) {
12217
+ this.on((listener) => {
12218
+ listener.markdownUpdated((_, markdown) => {
12219
+ try {
12220
+ const html = this.editor.action(utils$1.getHTML());
12221
+ const docId = fixedToolbarConfig.id || "default";
12222
+ const saveToLocalStorage = (mdVal, htmlVal) => {
12223
+ try {
12224
+ const stored = localStorage.getItem("jvs-milkdown-data");
12225
+ let parsed = {};
12226
+ if (stored) {
12227
+ parsed = JSON.parse(stored);
12228
+ }
12229
+ if (!parsed.content) {
12230
+ parsed.content = {};
12231
+ }
12232
+ const currentEntry = parsed.content[docId];
12233
+ const hasChanged = !currentEntry || typeof currentEntry === "string" && currentEntry !== mdVal || typeof currentEntry === "object" && (currentEntry.markdown !== mdVal || currentEntry.html !== htmlVal);
12234
+ if (hasChanged) {
12235
+ parsed.content[docId] = {
12236
+ markdown: mdVal,
12237
+ html: htmlVal
12238
+ };
12239
+ localStorage.setItem(
12240
+ "jvs-milkdown-data",
12241
+ JSON.stringify(parsed)
12242
+ );
12243
+ }
12244
+ } catch (e) {
12245
+ console.error("Error saving content to localStorage:", e);
12246
+ }
12247
+ };
12248
+ const hasBlobUrl = /blob:https?:\/\//.test(markdown) || /blob:https?:\/\//.test(html);
12249
+ if (hasBlobUrl) {
12250
+ Promise.all([
12251
+ replaceBlobUrlsWithBase64(markdown),
12252
+ replaceBlobUrlsWithBase64(html)
12253
+ ]).then(([base64Markdown, base64Html]) => {
12254
+ saveToLocalStorage(base64Markdown, base64Html);
12255
+ }).catch((e) => {
12256
+ console.error("Error converting blob URLs:", e);
12257
+ saveToLocalStorage(markdown, html);
12258
+ });
12259
+ } else {
12260
+ saveToLocalStorage(markdown, html);
12261
+ }
12262
+ } catch (e) {
12263
+ console.error("Error saving content to localStorage:", e);
12264
+ }
12265
+ });
12266
+ });
12267
+ }
11909
12268
  }
11910
12269
  }
11911
12270
  /// This is an alias for the `CrepeFeature` enum.
11912
12271
  Crepe.Feature = CrepeFeature;
12272
+ async function replaceBlobUrlsWithBase64(content) {
12273
+ const blobRegex = /blob:https?:\/\/[^\s'")>]+/g;
12274
+ const matches = content.match(blobRegex);
12275
+ if (!matches) return content;
12276
+ let result = content;
12277
+ const uniqueBlobs = Array.from(new Set(matches));
12278
+ for (const blobUrl of uniqueBlobs) {
12279
+ try {
12280
+ const response = await fetch(blobUrl);
12281
+ const blob = await response.blob();
12282
+ const base64 = await new Promise((resolve, reject) => {
12283
+ const reader = new FileReader();
12284
+ reader.onloadend = () => resolve(reader.result);
12285
+ reader.onerror = reject;
12286
+ reader.readAsDataURL(blob);
12287
+ });
12288
+ result = result.replaceAll(blobUrl, base64);
12289
+ } catch (e) {
12290
+ console.error("Failed to convert blob URL to base64:", blobUrl, e);
12291
+ }
12292
+ }
12293
+ return result;
12294
+ }
11913
12295
 
11914
12296
  exports.Crepe = Crepe;
11915
12297
  exports.CrepeBuilder = CrepeBuilder;