@jvs-milkdown/crepe 1.2.17 → 1.2.18

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 (89) 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 +9 -2
  24. package/lib/cjs/feature/toolbar/index.js.map +1 -1
  25. package/lib/cjs/index.js +394 -96
  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 +9 -2
  50. package/lib/esm/feature/toolbar/index.js.map +1 -1
  51. package/lib/esm/index.js +393 -95
  52. package/lib/esm/index.js.map +1 -1
  53. package/lib/theme/common/toolbar.css +6 -0
  54. package/lib/tsconfig.tsbuildinfo +1 -1
  55. package/lib/types/core/crepe.d.ts +1 -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/package.json +4 -4
  77. package/src/core/crepe.ts +60 -7
  78. package/src/core/locale.ts +4 -0
  79. package/src/feature/fixed-toolbar/component.tsx +155 -51
  80. package/src/feature/fixed-toolbar/config.ts +70 -2
  81. package/src/feature/fixed-toolbar/index.ts +86 -1
  82. package/src/feature/fixed-toolbar/menu-bar.tsx +18 -3
  83. package/src/feature/toolbar/component.tsx +6 -2
  84. package/src/icons/export.ts +5 -0
  85. package/src/icons/import.ts +6 -0
  86. package/src/icons/index.ts +4 -0
  87. package/src/icons/redo.ts +5 -0
  88. package/src/icons/undo.ts +5 -0
  89. package/src/theme/common/toolbar.css +16 -0
@@ -7,6 +7,6 @@ export interface CrepeConfig extends CrepeBuilderConfig {
7
7
  }
8
8
  export declare class Crepe extends CrepeBuilder {
9
9
  static Feature: typeof CrepeFeature;
10
- constructor({ features, featureConfigs, ...crepeBuilderConfig }?: CrepeConfig);
10
+ constructor(config?: CrepeConfig);
11
11
  }
12
12
  //# sourceMappingURL=crepe.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"crepe.d.ts","sourceRoot":"","sources":["../../../src/core/crepe.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAGpD,OAAO,EAAE,YAAY,EAAmB,MAAM,YAAY,CAAA;AAE1D,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAGjE,MAAM,WAAW,WAAY,SAAQ,kBAAkB;IAErD,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAA;IAGjD,cAAc,CAAC,EAAE,kBAAkB,CAAA;CACpC;AAGD,qBAAa,KAAM,SAAQ,YAAY;IAErC,MAAM,CAAC,OAAO,sBAAe;gBAKjB,EACV,QAAa,EACb,cAAmB,EACnB,GAAG,kBAAkB,EACtB,GAAE,WAAgB;CAmBpB"}
1
+ {"version":3,"file":"crepe.d.ts","sourceRoot":"","sources":["../../../src/core/crepe.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAGpD,OAAO,EAAE,YAAY,EAAmB,MAAM,YAAY,CAAA;AAE1D,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAGjE,MAAM,WAAW,WAAY,SAAQ,kBAAkB;IAErD,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAA;IAGjD,cAAc,CAAC,EAAE,kBAAkB,CAAA;CACpC;AAGD,qBAAa,KAAM,SAAQ,YAAY;IAErC,MAAM,CAAC,OAAO,sBAAe;gBAKjB,MAAM,GAAE,WAAgB;CA2ErC"}
@@ -106,6 +106,8 @@ export declare const zhCN: {
106
106
  'customMenu.colorPurple': string;
107
107
  'customMenu.colorGray': string;
108
108
  'customMenu.insertTable': string;
109
+ 'customMenu.export': string;
110
+ 'customMenu.import': string;
109
111
  'customMenu.fontDefault': string;
110
112
  'font.fangSong': string;
111
113
  'font.stFangsong': string;
@@ -252,6 +254,8 @@ export declare const translationsCtx: import("@jvs-milkdown/ctx").SliceType<Reco
252
254
  'customMenu.colorPurple': string;
253
255
  'customMenu.colorGray': string;
254
256
  'customMenu.insertTable': string;
257
+ 'customMenu.export': string;
258
+ 'customMenu.import': string;
255
259
  'customMenu.fontDefault': string;
256
260
  'font.fangSong': string;
257
261
  'font.stFangsong': string;
@@ -1 +1 @@
1
- {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../../src/core/locale.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAIhD,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+KhB,CAAA;AAED,eAAO,MAAM,IAAI,EAAE,OAAO,IA+JzB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,IAAI,CAAA;AAE3C,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAQ3B,CAAA;AAED,eAAO,MAAM,SAAS,4DAAoC,CAAA;AAE1D,wBAAgB,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,iBAAiB,GAAG,MAAM,CASnE"}
1
+ {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../../src/core/locale.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAIhD,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiLhB,CAAA;AAED,eAAO,MAAM,IAAI,EAAE,OAAO,IAiKzB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,IAAI,CAAA;AAE3C,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAQ3B,CAAA;AAED,eAAO,MAAM,SAAS,4DAAoC,CAAA;AAE1D,wBAAgB,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,iBAAiB,GAAG,MAAM,CASnE"}
@@ -8,6 +8,8 @@ type FixedToolbarProps = {
8
8
  show: Ref<boolean>;
9
9
  selection: ShallowRef<Selection>;
10
10
  config?: FixedToolbarFeatureConfig;
11
+ canUndo: Ref<boolean>;
12
+ canRedo: Ref<boolean>;
11
13
  };
12
14
  export declare const FixedToolbarComponent: import("@vue/runtime-core").DefineComponent<FixedToolbarProps, {}, {}, {}, {}, import("@vue/runtime-core").ComponentOptionsMixin, import("@vue/runtime-core").ComponentOptionsMixin, {}, string, import("@vue/runtime-core").PublicProps, Readonly<FixedToolbarProps> & Readonly<{}>, {}, {}, {}, {}, string, import("@vue/runtime-core").ComponentProvideOptions, false, {}, any>;
13
15
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../../src/feature/fixed-toolbar/component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAI9D,OAAO,EAAmB,KAAK,UAAU,EAAE,KAAK,GAAG,EAAU,MAAM,KAAK,CAAA;AAExE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,GAAG,CAAA;AAQlD,KAAK,iBAAiB,GAAG;IACvB,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IAClB,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,CAAA;IAChC,MAAM,CAAC,EAAE,yBAAyB,CAAA;CACnC,CAAA;AAED,eAAO,MAAM,qBAAqB,oXAiEhC,CAAA"}
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../../src/feature/fixed-toolbar/component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAO9D,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,GAAG,EAKT,MAAM,KAAK,CAAA;AAEZ,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,GAAG,CAAA;AAQlD,KAAK,iBAAiB,GAAG;IACvB,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IAClB,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,CAAA;IAChC,MAAM,CAAC,EAAE,yBAAyB,CAAA;IAClC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACrB,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;CACtB,CAAA;AAED,eAAO,MAAM,qBAAqB,oXA4JhC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/feature/fixed-toolbar/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAgChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAkDxD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,YAAY,CAAC,WAAW,CAAC,EAClC,OAAO,CAAC,EAAE,yBAAyB,EACnC,GAAG,CAAC,EAAE,GAAG;;;;;;;;IAodV"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/feature/fixed-toolbar/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAkChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAqDxD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,YAAY,CAAC,WAAW,CAAC,EAClC,OAAO,CAAC,EAAE,yBAAyB,EACnC,GAAG,CAAC,EAAE,GAAG;;;;;;;;IAmhBV"}
@@ -1,3 +1,4 @@
1
+ import type { Ctx } from '@jvs-milkdown/kit/ctx';
1
2
  import { PluginKey } from '@jvs-milkdown/kit/prose/state';
2
3
  import type { GroupBuilder } from '../../utils';
3
4
  import type { DefineFeature } from '../shared';
@@ -16,6 +17,21 @@ export interface FixedToolbarConfig {
16
17
  outlinePosition?: 'left' | 'right';
17
18
  onUploadCover?: (file: File) => Promise<string>;
18
19
  defaultCoverImages?: string[];
20
+ showMenuBar?: boolean;
21
+ menuBarItems?: {
22
+ file?: boolean;
23
+ edit?: boolean;
24
+ view?: boolean;
25
+ insert?: boolean;
26
+ format?: boolean;
27
+ };
28
+ showHistory?: boolean;
29
+ showExport?: boolean;
30
+ onExport?: (markdown: string, ctx: Ctx) => void;
31
+ showImport?: boolean;
32
+ onImport?: (replaceContent: (markdown: string) => void, ctx: Ctx) => void;
33
+ useLocalStorage?: boolean;
34
+ id?: string;
19
35
  }
20
36
  export type FixedToolbarFeatureConfig = Partial<FixedToolbarConfig>;
21
37
  export declare const fixedToolbarConfig: import("@jvs-milkdown/utils").$Ctx<Partial<FixedToolbarConfig>, "fixedToolbarConfigCtx">;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/feature/fixed-toolbar/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAU,SAAS,EAAiB,MAAM,+BAA+B,CAAA;AAchF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAYpD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC,WAAW,CAAC,KAAK,IAAI,CAAA;IAC3D,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAClC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC/C,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC9B;AAED,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;AAEnE,eAAO,MAAM,kBAAkB,0FAG9B,CAAA;AAED,eAAO,MAAM,eAAe,gBAA0C,CAAA;AAiStE,eAAO,MAAM,kBAAkB,sCAK7B,CAAA;AAEF,eAAO,MAAM,YAAY,EAAE,aAAa,CAAC,yBAAyB,CA6BjE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/feature/fixed-toolbar/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAIhD,OAAO,EAAU,SAAS,EAAiB,MAAM,+BAA+B,CAAA;AAehF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAYpD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC,WAAW,CAAC,KAAK,IAAI,CAAA;IAC3D,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAClC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC/C,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,CAAC,EAAE;QACb,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,MAAM,CAAC,EAAE,OAAO,CAAA;KACjB,CAAA;IACD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC/C,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IACzE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;AAEnE,eAAO,MAAM,kBAAkB,0FAG9B,CAAA;AAED,eAAO,MAAM,eAAe,gBAA0C,CAAA;AAsWtE,eAAO,MAAM,kBAAkB,sCAK7B,CAAA;AAEF,eAAO,MAAM,YAAY,EAAE,aAAa,CAAC,yBAAyB,CA6BjE,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"menu-bar.d.ts","sourceRoot":"","sources":["../../../../src/feature/fixed-toolbar/menu-bar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAMhD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAsDjD,eAAO,MAAM,OAAO;;cAEO,MAAM,GAAG;;;;cACN,MAAM,kBAAkB;;;;;cAD3B,MAAM,GAAG;;;;cACN,MAAM,kBAAkB;;;+GA2fpD,CAAA"}
1
+ {"version":3,"file":"menu-bar.d.ts","sourceRoot":"","sources":["../../../../src/feature/fixed-toolbar/menu-bar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAchD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAsDjD,eAAO,MAAM,OAAO;;cAEO,MAAM,GAAG;;;;cACN,MAAM,kBAAkB;;;;;cAD3B,MAAM,GAAG;;;;cACN,MAAM,kBAAkB;;;+GAkgBpD,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../../src/feature/toolbar/component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAgBhD,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,+BAA+B,CAAA;AAUtC,OAAO,EAEL,KAAK,GAAG,EACR,KAAK,UAAU,EAQhB,MAAM,KAAK,CAAA;AAEZ,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,GAAG,CAAA;AAmG7C,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IAClB,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,CAAA;IAChC,MAAM,CAAC,EAAE,oBAAoB,CAAA;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAeD,eAAO,MAAM,OAAO,0WA2+ElB,CAAA"}
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../../src/feature/toolbar/component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAgBhD,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,+BAA+B,CAAA;AAUtC,OAAO,EAEL,KAAK,GAAG,EACR,KAAK,UAAU,EAQhB,MAAM,KAAK,CAAA;AAEZ,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,GAAG,CAAA;AAmG7C,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IAClB,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,CAAA;IAChC,MAAM,CAAC,EAAE,oBAAoB,CAAA;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAeD,eAAO,MAAM,OAAO,0WA++ElB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare const exportIcon = "\n<svg viewBox=\"0 0 1024 1024\" version=\"1.1\" width=\"20\" height=\"20\">\n <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>\n</svg>\n";
2
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/icons/export.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,2tDAItB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare const importIcon = "\n<svg viewBox=\"0 0 1024 1024\" version=\"1.1\" width=\"20\" height=\"20\">\n <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>\n <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>\n</svg>\n";
2
+ //# sourceMappingURL=import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../../src/icons/import.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,qjCAKtB,CAAA"}
@@ -53,4 +53,8 @@ export * from './word-wrap';
53
53
  export * from './crop';
54
54
  export * from './border';
55
55
  export * from './format-painter';
56
+ export * from './undo';
57
+ export * from './redo';
58
+ export * from './export';
59
+ export * from './import';
56
60
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/icons/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,QAAQ,CAAA;AACtB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,WAAW,CAAA;AACzB,cAAc,QAAQ,CAAA;AACtB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,QAAQ,CAAA;AACtB,cAAc,MAAM,CAAA;AACpB,cAAc,MAAM,CAAA;AACpB,cAAc,MAAM,CAAA;AACpB,cAAc,MAAM,CAAA;AACpB,cAAc,MAAM,CAAA;AACpB,cAAc,MAAM,CAAA;AACpB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,QAAQ,CAAA;AACtB,cAAc,QAAQ,CAAA;AACtB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,QAAQ,CAAA;AACtB,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,QAAQ,CAAA;AACtB,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,QAAQ,CAAA;AACtB,cAAc,UAAU,CAAA;AACxB,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/icons/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,QAAQ,CAAA;AACtB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,WAAW,CAAA;AACzB,cAAc,QAAQ,CAAA;AACtB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,QAAQ,CAAA;AACtB,cAAc,MAAM,CAAA;AACpB,cAAc,MAAM,CAAA;AACpB,cAAc,MAAM,CAAA;AACpB,cAAc,MAAM,CAAA;AACpB,cAAc,MAAM,CAAA;AACpB,cAAc,MAAM,CAAA;AACpB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,QAAQ,CAAA;AACtB,cAAc,QAAQ,CAAA;AACtB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,QAAQ,CAAA;AACtB,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,QAAQ,CAAA;AACtB,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,QAAQ,CAAA;AACtB,cAAc,UAAU,CAAA;AACxB,cAAc,kBAAkB,CAAA;AAChC,cAAc,QAAQ,CAAA;AACtB,cAAc,QAAQ,CAAA;AACtB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare const redoIcon = "\n<svg viewBox=\"0 0 1024 1024\" version=\"1.1\" width=\"20\" height=\"20\">\n <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>\n</svg>\n";
2
+ //# sourceMappingURL=redo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redo.d.ts","sourceRoot":"","sources":["../../../src/icons/redo.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,saAIpB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare const undoIcon = "\n<svg viewBox=\"0 0 1024 1024\" version=\"1.1\" width=\"20\" height=\"20\">\n <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>\n</svg>\n";
2
+ //# sourceMappingURL=undo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undo.d.ts","sourceRoot":"","sources":["../../../src/icons/undo.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,qcAIpB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jvs-milkdown/crepe",
3
- "version": "1.2.17",
3
+ "version": "1.2.18",
4
4
  "keywords": [
5
5
  "crepe",
6
6
  "editor",
@@ -107,9 +107,9 @@
107
107
  "@codemirror/theme-one-dark": "^6.1.2",
108
108
  "@codemirror/view": "^6.26.0",
109
109
  "@floating-ui/dom": "^1.7.6",
110
- "@jvs-milkdown/kit": "^1.2.17",
111
- "@jvs-milkdown/prose": "^1.2.17",
112
- "@jvs-milkdown/utils": "^1.2.17",
110
+ "@jvs-milkdown/kit": "^1.2.18",
111
+ "@jvs-milkdown/prose": "^1.2.18",
112
+ "@jvs-milkdown/utils": "^1.2.18",
113
113
  "@types/lodash-es": "^4.17.12",
114
114
  "clsx": "^2.0.0",
115
115
  "codemirror": "^6.0.1",
package/src/core/crepe.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { getHTML } from '@jvs-milkdown/utils'
1
2
  import { defaultsDeep } from 'lodash-es'
2
3
 
3
4
  import type { CrepeFeatureConfig } from '../feature'
@@ -24,14 +25,29 @@ export class Crepe extends CrepeBuilder {
24
25
  /// The constructor of the crepe editor.
25
26
  /// You can pass configs to the editor to configure the editor.
26
27
  /// Calling the constructor will not create the editor, you need to call `create` to create the editor.
27
- constructor({
28
- features = {},
29
- featureConfigs = {},
30
- ...crepeBuilderConfig
31
- }: CrepeConfig = {}) {
32
- super(crepeBuilderConfig)
33
-
28
+ constructor(config: CrepeConfig = {}) {
29
+ const { features = {}, featureConfigs = {}, ...crepeBuilderConfig } = config
34
30
  const finalConfigs = defaultsDeep(featureConfigs, defaultConfig)
31
+ const fixedToolbarConfig = finalConfigs[CrepeFeature.FixedToolbar]
32
+ if (fixedToolbarConfig?.useLocalStorage) {
33
+ try {
34
+ const stored = localStorage.getItem('jvs-milkdown-data')
35
+ if (stored) {
36
+ const parsed = JSON.parse(stored)
37
+ const docId = fixedToolbarConfig.id || 'default'
38
+ if (parsed.content && parsed.content[docId] !== undefined) {
39
+ const entry = parsed.content[docId]
40
+ const defaultValue =
41
+ typeof entry === 'string' ? entry : (entry?.markdown ?? '')
42
+ crepeBuilderConfig.defaultValue = defaultValue
43
+ }
44
+ }
45
+ } catch (e) {
46
+ console.error('Error loading content from localStorage:', e)
47
+ }
48
+ }
49
+
50
+ super(crepeBuilderConfig)
35
51
 
36
52
  const enabledFeatures = Object.entries({
37
53
  ...defaultFeatures,
@@ -46,5 +62,42 @@ export class Crepe extends CrepeBuilder {
46
62
  ]
47
63
  loadFeature(feature, this.editor, config)
48
64
  })
65
+
66
+ if (fixedToolbarConfig?.useLocalStorage) {
67
+ this.on((listener) => {
68
+ listener.markdownUpdated((_, markdown) => {
69
+ try {
70
+ const stored = localStorage.getItem('jvs-milkdown-data')
71
+ let parsed: any = {}
72
+ if (stored) {
73
+ parsed = JSON.parse(stored)
74
+ }
75
+ if (!parsed.content) {
76
+ parsed.content = {}
77
+ }
78
+ const html = this.editor.action(getHTML())
79
+ const docId = fixedToolbarConfig.id || 'default'
80
+
81
+ const currentEntry = parsed.content[docId]
82
+ const hasChanged =
83
+ !currentEntry ||
84
+ (typeof currentEntry === 'string' && currentEntry !== markdown) ||
85
+ (typeof currentEntry === 'object' &&
86
+ (currentEntry.markdown !== markdown ||
87
+ currentEntry.html !== html))
88
+
89
+ if (hasChanged) {
90
+ parsed.content[docId] = {
91
+ markdown,
92
+ html,
93
+ }
94
+ localStorage.setItem('jvs-milkdown-data', JSON.stringify(parsed))
95
+ }
96
+ } catch (e) {
97
+ console.error('Error saving content to localStorage:', e)
98
+ }
99
+ })
100
+ })
101
+ }
49
102
  }
50
103
  }
@@ -134,6 +134,8 @@ export const zhCN = {
134
134
  'customMenu.colorPurple': '紫色',
135
135
  'customMenu.colorGray': '灰色',
136
136
  'customMenu.insertTable': '插入支持富文本的表格',
137
+ 'customMenu.export': '导出',
138
+ 'customMenu.import': '导入',
137
139
 
138
140
  'customMenu.fontDefault': '默认',
139
141
  'font.fangSong': '仿宋',
@@ -298,6 +300,8 @@ export const enUS: typeof zhCN = {
298
300
  'customMenu.colorPurple': 'Purple',
299
301
  'customMenu.colorGray': 'Gray',
300
302
  'customMenu.insertTable': 'Insert Table',
303
+ 'customMenu.export': 'Export',
304
+ 'customMenu.import': 'Import',
301
305
 
302
306
  'customMenu.fontDefault': 'Default',
303
307
  'font.fangSong': 'FangSong',
@@ -2,13 +2,24 @@ import type { Ctx } from '@jvs-milkdown/kit/ctx'
2
2
  import type { Selection } from '@jvs-milkdown/kit/prose/state'
3
3
 
4
4
  import { Icon } from '@jvs-milkdown/kit/component'
5
+ import { commandsCtx, editorViewCtx } from '@jvs-milkdown/kit/core'
6
+ import { getMarkdown } from '@jvs-milkdown/kit/utils'
7
+ import { replaceAll } from '@jvs-milkdown/utils'
5
8
  // @ts-ignore
6
- import { defineComponent, type ShallowRef, type Ref, ref, h } from 'vue'
9
+ import {
10
+ defineComponent,
11
+ type ShallowRef,
12
+ type Ref,
13
+ ref,
14
+ h,
15
+ onMounted,
16
+ onUnmounted,
17
+ } from 'vue'
7
18
 
8
19
  import type { FixedToolbarFeatureConfig } from '.'
9
20
 
10
21
  import { i18n } from '../../core/locale'
11
- import { keyboardIcon } from '../../icons'
22
+ import { undoIcon, redoIcon } from '../../icons'
12
23
  import { Toolbar } from '../toolbar/component'
13
24
  import { MenuBar } from './menu-bar'
14
25
  import { ShortcutHelpModal } from './shortcut-help-modal'
@@ -19,6 +30,8 @@ type FixedToolbarProps = {
19
30
  show: Ref<boolean>
20
31
  selection: ShallowRef<Selection>
21
32
  config?: FixedToolbarFeatureConfig
33
+ canUndo: Ref<boolean>
34
+ canRedo: Ref<boolean>
22
35
  }
23
36
 
24
37
  export const FixedToolbarComponent = defineComponent<FixedToolbarProps>({
@@ -28,62 +41,153 @@ export const FixedToolbarComponent = defineComponent<FixedToolbarProps>({
28
41
  show: { type: Object, required: true },
29
42
  selection: { type: Object, required: true },
30
43
  config: { type: Object, required: false },
44
+ canUndo: { type: Object, required: true },
45
+ canRedo: { type: Object, required: true },
31
46
  },
32
47
  setup(props: any) {
33
48
  const showShortcuts = ref(false)
34
49
 
35
- return () => (
36
- <div
37
- style={{
38
- display: 'flex',
39
- alignItems: 'center',
40
- justifyContent: 'center',
41
- width: '100%',
42
- gap: '0px',
43
- }}
44
- >
45
- <MenuBar ctx={props.ctx} config={props.config} />
46
- <div
47
- style={{
48
- width: '1px',
49
- minWidth: '1px',
50
- height: '20px',
51
- backgroundColor:
52
- 'var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))',
53
- }}
54
- />
55
- <Toolbar
56
- ctx={props.ctx}
57
- hide={props.hide}
58
- show={props.show}
59
- selection={props.selection}
60
- config={props.config as any}
61
- isFixed={true}
62
- />
50
+ onMounted(() => {
51
+ const handleShowShortcuts = () => {
52
+ showShortcuts.value = true
53
+ }
54
+ window.addEventListener('milkdown-show-shortcuts', handleShowShortcuts)
55
+ onUnmounted(() => {
56
+ window.removeEventListener(
57
+ 'milkdown-show-shortcuts',
58
+ handleShowShortcuts
59
+ )
60
+ })
61
+ })
62
+
63
+ return () => {
64
+ // Access selection.value to register reactivity dependency for Vue on editor transactions
65
+ const _selection = props.selection.value
66
+ void _selection
67
+
68
+ const canUndo =
69
+ (typeof props.canUndo === 'boolean'
70
+ ? props.canUndo
71
+ : props.canUndo?.value) || false
72
+ const canRedo =
73
+ (typeof props.canRedo === 'boolean'
74
+ ? props.canRedo
75
+ : props.canRedo?.value) || false
76
+
77
+ return (
63
78
  <div
64
79
  style={{
65
- width: '1px',
66
- minWidth: '1px',
67
- height: '20px',
68
- flexShrink: 0,
69
- backgroundColor:
70
- 'var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))',
71
- }}
72
- />
73
- <button
74
- type="button"
75
- class="toolbar-shortcut-btn"
76
- title={i18n(props.ctx, 'shortcuts.title')}
77
- onClick={() => {
78
- showShortcuts.value = true
80
+ display: 'flex',
81
+ alignItems: 'center',
82
+ justifyContent: 'center',
83
+ width: '100%',
84
+ gap: '0px',
79
85
  }}
80
86
  >
81
- <Icon icon={keyboardIcon} />
82
- </button>
83
- {showShortcuts.value && (
84
- <ShortcutHelpModal ctx={props.ctx} visible={showShortcuts} />
85
- )}
86
- </div>
87
- )
87
+ {props.config?.showMenuBar !== false && [
88
+ <MenuBar ctx={props.ctx} config={props.config} />,
89
+ <div
90
+ style={{
91
+ width: '1px',
92
+ minWidth: '1px',
93
+ height: '20px',
94
+ backgroundColor:
95
+ 'var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))',
96
+ }}
97
+ />,
98
+ ]}
99
+ {props.config?.showHistory !== false && [
100
+ <button
101
+ type="button"
102
+ class={['toolbar-item', !canUndo && 'disabled']}
103
+ disabled={!canUndo}
104
+ title="撤销"
105
+ onPointerdown={(e: PointerEvent) => {
106
+ e.preventDefault()
107
+ e.stopPropagation()
108
+ }}
109
+ onClick={(e: MouseEvent) => {
110
+ e.preventDefault()
111
+ e.stopPropagation()
112
+ if (canUndo) {
113
+ props.ctx.get(commandsCtx).call('Undo')
114
+ }
115
+ }}
116
+ style={{
117
+ display: 'flex',
118
+ alignItems: 'center',
119
+ justifyContent: 'center',
120
+ border: 'none',
121
+ background: 'transparent',
122
+ cursor: canUndo ? 'pointer' : 'default',
123
+ padding: '6px',
124
+ borderRadius: '4px',
125
+ color: canUndo ? '#363b4c' : '#c0c4cc',
126
+ '--toolbar-icon-color': canUndo ? '#363b4c' : '#c0c4cc',
127
+ }}
128
+ >
129
+ <span
130
+ style={{ display: 'inline-flex', alignItems: 'center' }}
131
+ innerHTML={undoIcon}
132
+ />
133
+ </button>,
134
+ <button
135
+ type="button"
136
+ class={['toolbar-item', !canRedo && 'disabled']}
137
+ disabled={!canRedo}
138
+ title="恢复"
139
+ onPointerdown={(e: PointerEvent) => {
140
+ e.preventDefault()
141
+ e.stopPropagation()
142
+ }}
143
+ onClick={(e: MouseEvent) => {
144
+ e.preventDefault()
145
+ e.stopPropagation()
146
+ if (canRedo) {
147
+ props.ctx.get(commandsCtx).call('Redo')
148
+ }
149
+ }}
150
+ style={{
151
+ display: 'flex',
152
+ alignItems: 'center',
153
+ justifyContent: 'center',
154
+ border: 'none',
155
+ background: 'transparent',
156
+ cursor: canRedo ? 'pointer' : 'default',
157
+ padding: '6px',
158
+ borderRadius: '4px',
159
+ color: canRedo ? '#363b4c' : '#c0c4cc',
160
+ '--toolbar-icon-color': canRedo ? '#363b4c' : '#c0c4cc',
161
+ }}
162
+ >
163
+ <span
164
+ style={{ display: 'inline-flex', alignItems: 'center' }}
165
+ innerHTML={redoIcon}
166
+ />
167
+ </button>,
168
+ <div
169
+ style={{
170
+ width: '1px',
171
+ minWidth: '1px',
172
+ height: '20px',
173
+ backgroundColor:
174
+ 'var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))',
175
+ }}
176
+ />,
177
+ ]}
178
+ <Toolbar
179
+ ctx={props.ctx}
180
+ hide={props.hide}
181
+ show={props.show}
182
+ selection={props.selection}
183
+ config={props.config as any}
184
+ isFixed={true}
185
+ />
186
+ {showShortcuts.value && (
187
+ <ShortcutHelpModal ctx={props.ctx} visible={showShortcuts} />
188
+ )}
189
+ </div>
190
+ )
191
+ }
88
192
  },
89
193
  })
@@ -29,6 +29,8 @@ import { createTable } from '@jvs-milkdown/kit/preset/gfm'
29
29
  import { findNodeInSelection } from '@jvs-milkdown/kit/prose'
30
30
  import { lift } from '@jvs-milkdown/kit/prose/commands'
31
31
  import { wrapInList } from '@jvs-milkdown/kit/prose/schema-list'
32
+ import { getMarkdown } from '@jvs-milkdown/kit/utils'
33
+ import { replaceAll } from '@jvs-milkdown/utils'
32
34
 
33
35
  import type { GroupBuilder } from '../../utils'
34
36
  import type { ToolbarItem } from '../toolbar/config'
@@ -50,6 +52,9 @@ import {
50
52
  highLineCodeIcon,
51
53
  linCodeIcon,
52
54
  linkIcon,
55
+ exportIcon,
56
+ importIcon,
57
+ keyboardIcon,
53
58
  } from '../../icons'
54
59
  import { attachmentSchema } from '../attachment/schema'
55
60
  import { CrepeFeature } from '../index'
@@ -472,7 +477,6 @@ export function buildDefaultFixedToolbar(
472
477
  },
473
478
  })
474
479
 
475
-
476
480
  if (isAttachmentEnabled) {
477
481
  blockGroup.addItem('attachment', {
478
482
  label: ctx ? i18n(ctx, 'menu.item.attachment') : 'Video or File',
@@ -532,7 +536,6 @@ export function buildDefaultFixedToolbar(
532
536
  },
533
537
  })
534
538
 
535
-
536
539
  if (isLatexEnabled) {
537
540
  blockGroup.addItem('math-block', {
538
541
  label: ctx ? i18n(ctx, 'menu.item.math') : 'Math Block',
@@ -552,5 +555,70 @@ export function buildDefaultFixedToolbar(
552
555
  })
553
556
  }
554
557
 
558
+ const documentGroup = builder.addGroup('document', 'Document')
559
+
560
+ if (_config?.showExport !== false) {
561
+ documentGroup.addItem('export', {
562
+ label: ctx ? i18n(ctx, 'customMenu.export' as any) || '导出' : '导出',
563
+ icon: exportIcon,
564
+ active: () => false,
565
+ onRun: (ctx) => {
566
+ const markdown = getMarkdown()(ctx)
567
+ if (_config?.onExport) {
568
+ _config.onExport(markdown, ctx)
569
+ } else {
570
+ const blob = new Blob([markdown], {
571
+ type: 'text/markdown;charset=utf-8;',
572
+ })
573
+ const url = URL.createObjectURL(blob)
574
+ const link = document.createElement('a')
575
+ link.href = url
576
+ link.download = 'document.md'
577
+ link.click()
578
+ URL.revokeObjectURL(url)
579
+ }
580
+ },
581
+ })
582
+ }
583
+
584
+ if (_config?.showImport !== false) {
585
+ documentGroup.addItem('import', {
586
+ label: ctx ? i18n(ctx, 'customMenu.import' as any) || '导入' : '导入',
587
+ icon: importIcon,
588
+ active: () => false,
589
+ onRun: (ctx) => {
590
+ if (_config?.onImport) {
591
+ _config.onImport((markdown) => replaceAll(markdown)(ctx), ctx)
592
+ } else {
593
+ const input = document.createElement('input')
594
+ input.type = 'file'
595
+ input.accept = '.md'
596
+ input.onchange = (e) => {
597
+ const file = (e.target as HTMLInputElement).files?.[0]
598
+ if (!file) return
599
+ file
600
+ .text()
601
+ .then((text) => {
602
+ replaceAll(text)(ctx)
603
+ })
604
+ .catch((err) => {
605
+ console.error('Failed to read file:', err)
606
+ })
607
+ }
608
+ input.click()
609
+ }
610
+ },
611
+ })
612
+ }
613
+
614
+ documentGroup.addItem('shortcuts', {
615
+ label: ctx ? i18n(ctx, 'shortcuts.title') : 'Shortcuts',
616
+ icon: keyboardIcon,
617
+ active: () => false,
618
+ onRun: () => {
619
+ window.dispatchEvent(new CustomEvent('milkdown-show-shortcuts'))
620
+ },
621
+ })
622
+
555
623
  return builder.build()
556
624
  }