@milkdown/crepe 7.11.0 → 7.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/lib/cjs/builder/builder.js +107 -0
  2. package/lib/cjs/builder/builder.js.map +1 -0
  3. package/lib/cjs/{index-oVztbsWz.js → feature/block-edit/index.js} +165 -61
  4. package/lib/cjs/feature/block-edit/index.js.map +1 -0
  5. package/lib/cjs/feature/code-mirror/index.js +161 -0
  6. package/lib/cjs/feature/code-mirror/index.js.map +1 -0
  7. package/lib/cjs/feature/cursor/index.js +57 -0
  8. package/lib/cjs/feature/cursor/index.js.map +1 -0
  9. package/lib/cjs/feature/image-block/index.js +123 -0
  10. package/lib/cjs/feature/image-block/index.js.map +1 -0
  11. package/lib/cjs/{index-DdWGHNC3.js → feature/latex/index.js} +111 -24
  12. package/lib/cjs/feature/latex/index.js.map +1 -0
  13. package/lib/cjs/feature/link-tooltip/index.js +124 -0
  14. package/lib/cjs/feature/link-tooltip/index.js.map +1 -0
  15. package/lib/cjs/{index-Dw6lXgs6.js → feature/list-item/index.js} +39 -8
  16. package/lib/cjs/feature/list-item/index.js.map +1 -0
  17. package/lib/cjs/{index-B91KhPew.js → feature/placeholder/index.js} +46 -6
  18. package/lib/cjs/feature/placeholder/index.js.map +1 -0
  19. package/lib/cjs/{index-DEs_IHHy.js → feature/table/index.js} +78 -16
  20. package/lib/cjs/feature/table/index.js.map +1 -0
  21. package/lib/cjs/{index-CqC8Inzm.js → feature/toolbar/index.js} +133 -31
  22. package/lib/cjs/feature/toolbar/index.js.map +1 -0
  23. package/lib/cjs/index/index.js +2464 -0
  24. package/lib/cjs/index/index.js.map +1 -0
  25. package/lib/esm/builder/builder.js +105 -0
  26. package/lib/esm/builder/builder.js.map +1 -0
  27. package/lib/esm/{index-BUOhiAN3.js → feature/block-edit/index.js} +161 -57
  28. package/lib/esm/feature/block-edit/index.js.map +1 -0
  29. package/lib/esm/feature/code-mirror/index.js +159 -0
  30. package/lib/esm/feature/code-mirror/index.js.map +1 -0
  31. package/lib/esm/feature/cursor/index.js +55 -0
  32. package/lib/esm/feature/cursor/index.js.map +1 -0
  33. package/lib/esm/feature/image-block/index.js +121 -0
  34. package/lib/esm/feature/image-block/index.js.map +1 -0
  35. package/lib/esm/{index-CQOlw1Xn.js → feature/latex/index.js} +107 -20
  36. package/lib/esm/feature/latex/index.js.map +1 -0
  37. package/lib/esm/feature/link-tooltip/index.js +122 -0
  38. package/lib/esm/feature/link-tooltip/index.js.map +1 -0
  39. package/lib/esm/{index-E8UgFLeN.js → feature/list-item/index.js} +39 -8
  40. package/lib/esm/feature/list-item/index.js.map +1 -0
  41. package/lib/esm/{index-BCvtgOeI.js → feature/placeholder/index.js} +45 -5
  42. package/lib/esm/feature/placeholder/index.js.map +1 -0
  43. package/lib/esm/{index-CwMVnVeI.js → feature/table/index.js} +78 -16
  44. package/lib/esm/feature/table/index.js.map +1 -0
  45. package/lib/esm/{index-B69WyZeK.js → feature/toolbar/index.js} +128 -26
  46. package/lib/esm/feature/toolbar/index.js.map +1 -0
  47. package/lib/esm/index/index.js +2458 -0
  48. package/lib/esm/index/index.js.map +1 -0
  49. package/lib/theme/common/code-mirror.css +69 -1
  50. package/lib/theme/common/style.css +1 -0
  51. package/lib/theme/crepe/style.css +0 -2
  52. package/lib/theme/crepe-dark/style.css +0 -2
  53. package/lib/theme/frame/style.css +0 -2
  54. package/lib/theme/frame-dark/style.css +0 -2
  55. package/lib/theme/nord/style.css +0 -2
  56. package/lib/theme/nord-dark/style.css +0 -2
  57. package/lib/tsconfig.tsbuildinfo +1 -1
  58. package/lib/types/builder.d.ts +2 -0
  59. package/lib/types/builder.d.ts.map +1 -0
  60. package/lib/types/core/builder.d.ts +23 -0
  61. package/lib/types/core/builder.d.ts.map +1 -0
  62. package/lib/types/core/crepe.d.ts +4 -15
  63. package/lib/types/core/crepe.d.ts.map +1 -1
  64. package/lib/types/core/index.d.ts +2 -1
  65. package/lib/types/core/index.d.ts.map +1 -1
  66. package/lib/types/core/slice.d.ts +6 -4
  67. package/lib/types/core/slice.d.ts.map +1 -1
  68. package/lib/types/default-config/index.d.ts +3 -0
  69. package/lib/types/default-config/index.d.ts.map +1 -0
  70. package/lib/types/feature/block-edit/handle/component.d.ts +2 -3
  71. package/lib/types/feature/block-edit/handle/component.d.ts.map +1 -1
  72. package/lib/types/feature/block-edit/index.d.ts +20 -20
  73. package/lib/types/feature/block-edit/index.d.ts.map +1 -1
  74. package/lib/types/feature/code-mirror/index.d.ts +7 -7
  75. package/lib/types/feature/code-mirror/index.d.ts.map +1 -1
  76. package/lib/types/feature/cursor/index.d.ts +1 -1
  77. package/lib/types/feature/cursor/index.d.ts.map +1 -1
  78. package/lib/types/feature/image-block/index.d.ts +9 -9
  79. package/lib/types/feature/image-block/index.d.ts.map +1 -1
  80. package/lib/types/feature/index.d.ts +2 -4
  81. package/lib/types/feature/index.d.ts.map +1 -1
  82. package/lib/types/feature/latex/index.d.ts +3 -3
  83. package/lib/types/feature/latex/index.d.ts.map +1 -1
  84. package/lib/types/feature/link-tooltip/index.d.ts +6 -6
  85. package/lib/types/feature/link-tooltip/index.d.ts.map +1 -1
  86. package/lib/types/feature/list-item/index.d.ts +5 -5
  87. package/lib/types/feature/list-item/index.d.ts.map +1 -1
  88. package/lib/types/feature/loader.d.ts +4 -0
  89. package/lib/types/feature/loader.d.ts.map +1 -0
  90. package/lib/types/feature/placeholder/index.d.ts +2 -2
  91. package/lib/types/feature/placeholder/index.d.ts.map +1 -1
  92. package/lib/types/feature/shared.d.ts +1 -2
  93. package/lib/types/feature/shared.d.ts.map +1 -1
  94. package/lib/types/feature/table/index.d.ts +11 -11
  95. package/lib/types/feature/table/index.d.ts.map +1 -1
  96. package/lib/types/feature/toolbar/index.d.ts +8 -8
  97. package/lib/types/feature/toolbar/index.d.ts.map +1 -1
  98. package/lib/types/icons/index.d.ts +1 -0
  99. package/lib/types/icons/index.d.ts.map +1 -1
  100. package/lib/types/index.d.ts +1 -1
  101. package/lib/types/index.d.ts.map +1 -1
  102. package/lib/types/utils/index.d.ts +0 -1
  103. package/lib/types/utils/index.d.ts.map +1 -1
  104. package/package.json +60 -3
  105. package/src/builder.ts +1 -0
  106. package/src/core/builder.ts +143 -0
  107. package/src/core/crepe.ts +23 -110
  108. package/src/core/index.ts +2 -1
  109. package/src/core/slice.ts +47 -7
  110. package/src/default-config/index.ts +25 -0
  111. package/src/feature/block-edit/handle/component.tsx +6 -8
  112. package/src/feature/block-edit/handle/index.ts +2 -2
  113. package/src/feature/block-edit/index.ts +23 -20
  114. package/src/feature/block-edit/menu/config.ts +19 -19
  115. package/src/feature/code-mirror/index.ts +32 -28
  116. package/src/feature/cursor/index.ts +10 -6
  117. package/src/feature/image-block/index.ts +19 -16
  118. package/src/feature/index.ts +24 -53
  119. package/src/feature/latex/index.ts +8 -10
  120. package/src/feature/latex/inline-tooltip/component.tsx +1 -1
  121. package/src/feature/link-tooltip/index.ts +13 -10
  122. package/src/feature/list-item/index.ts +11 -8
  123. package/src/feature/loader.ts +52 -0
  124. package/src/feature/placeholder/index.ts +5 -2
  125. package/src/feature/shared.ts +1 -3
  126. package/src/feature/table/index.ts +23 -23
  127. package/src/feature/toolbar/component.tsx +9 -9
  128. package/src/feature/toolbar/index.ts +14 -11
  129. package/src/icons/index.ts +1 -0
  130. package/src/index.ts +1 -1
  131. package/src/theme/common/code-mirror.css +61 -1
  132. package/src/theme/common/style.css +1 -0
  133. package/src/theme/crepe/style.css +0 -2
  134. package/src/theme/crepe-dark/style.css +0 -2
  135. package/src/theme/frame/style.css +0 -2
  136. package/src/theme/frame-dark/style.css +0 -2
  137. package/src/theme/nord/style.css +0 -2
  138. package/src/theme/nord-dark/style.css +0 -2
  139. package/src/utils/index.ts +0 -8
  140. package/lib/cjs/confirm-CNveM9QH.js +0 -26
  141. package/lib/cjs/confirm-CNveM9QH.js.map +0 -1
  142. package/lib/cjs/edit-BUtBJHpV.js +0 -24
  143. package/lib/cjs/edit-BUtBJHpV.js.map +0 -1
  144. package/lib/cjs/functions-BAY51plB.js +0 -39
  145. package/lib/cjs/functions-BAY51plB.js.map +0 -1
  146. package/lib/cjs/image-BXLkOVnO.js +0 -24
  147. package/lib/cjs/image-BXLkOVnO.js.map +0 -1
  148. package/lib/cjs/index-B91KhPew.js.map +0 -1
  149. package/lib/cjs/index-BsrJn8Jp.js +0 -41
  150. package/lib/cjs/index-BsrJn8Jp.js.map +0 -1
  151. package/lib/cjs/index-C2CAbC2F.js +0 -26
  152. package/lib/cjs/index-C2CAbC2F.js.map +0 -1
  153. package/lib/cjs/index-CqC8Inzm.js.map +0 -1
  154. package/lib/cjs/index-DEs_IHHy.js.map +0 -1
  155. package/lib/cjs/index-DLIudQKW.js +0 -126
  156. package/lib/cjs/index-DLIudQKW.js.map +0 -1
  157. package/lib/cjs/index-DRKcvY0k.js +0 -188
  158. package/lib/cjs/index-DRKcvY0k.js.map +0 -1
  159. package/lib/cjs/index-DdWGHNC3.js.map +0 -1
  160. package/lib/cjs/index-Dw6lXgs6.js.map +0 -1
  161. package/lib/cjs/index-oVztbsWz.js.map +0 -1
  162. package/lib/cjs/index-xbwf60wt.js +0 -15
  163. package/lib/cjs/index-xbwf60wt.js.map +0 -1
  164. package/lib/cjs/index-xbxqAqH2.js +0 -52
  165. package/lib/cjs/index-xbxqAqH2.js.map +0 -1
  166. package/lib/cjs/index.js +0 -20
  167. package/lib/cjs/index.js.map +0 -1
  168. package/lib/cjs/inline-latex-D0G71cGk.js +0 -54
  169. package/lib/cjs/inline-latex-D0G71cGk.js.map +0 -1
  170. package/lib/cjs/plus-XLomtlXf.js +0 -24
  171. package/lib/cjs/plus-XLomtlXf.js.map +0 -1
  172. package/lib/cjs/remove-Ba-ypwBf.js +0 -17
  173. package/lib/cjs/remove-Ba-ypwBf.js.map +0 -1
  174. package/lib/esm/confirm-DtE-HkVd.js +0 -24
  175. package/lib/esm/confirm-DtE-HkVd.js.map +0 -1
  176. package/lib/esm/edit-D--t_JAb.js +0 -22
  177. package/lib/esm/edit-D--t_JAb.js.map +0 -1
  178. package/lib/esm/functions-DlJPkGmE.js +0 -36
  179. package/lib/esm/functions-DlJPkGmE.js.map +0 -1
  180. package/lib/esm/image-DoB1o1sl.js +0 -22
  181. package/lib/esm/image-DoB1o1sl.js.map +0 -1
  182. package/lib/esm/index-B69WyZeK.js.map +0 -1
  183. package/lib/esm/index-BCvtgOeI.js.map +0 -1
  184. package/lib/esm/index-BPG8iO8t.js +0 -12
  185. package/lib/esm/index-BPG8iO8t.js.map +0 -1
  186. package/lib/esm/index-BUBXHhHG.js +0 -39
  187. package/lib/esm/index-BUBXHhHG.js.map +0 -1
  188. package/lib/esm/index-BUOhiAN3.js.map +0 -1
  189. package/lib/esm/index-Bvz1Yyiz.js +0 -24
  190. package/lib/esm/index-Bvz1Yyiz.js.map +0 -1
  191. package/lib/esm/index-C1aVAv1l.js +0 -124
  192. package/lib/esm/index-C1aVAv1l.js.map +0 -1
  193. package/lib/esm/index-CQOlw1Xn.js.map +0 -1
  194. package/lib/esm/index-CdjziarM.js +0 -183
  195. package/lib/esm/index-CdjziarM.js.map +0 -1
  196. package/lib/esm/index-ChR5Qhyf.js +0 -50
  197. package/lib/esm/index-ChR5Qhyf.js.map +0 -1
  198. package/lib/esm/index-CwMVnVeI.js.map +0 -1
  199. package/lib/esm/index-E8UgFLeN.js.map +0 -1
  200. package/lib/esm/index.js +0 -12
  201. package/lib/esm/index.js.map +0 -1
  202. package/lib/esm/inline-latex-C9IGAXXQ.js +0 -51
  203. package/lib/esm/inline-latex-C9IGAXXQ.js.map +0 -1
  204. package/lib/esm/plus-lrX0Q75O.js +0 -22
  205. package/lib/esm/plus-lrX0Q75O.js.map +0 -1
  206. package/lib/esm/remove-D3g0Cd6_.js +0 -15
  207. package/lib/esm/remove-D3g0Cd6_.js.map +0 -1
  208. /package/lib/theme/{_internal/classic-common.css → common/reset.css} +0 -0
  209. /package/src/theme/{_internal/classic-common.css → common/reset.css} +0 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@milkdown/crepe",
3
3
  "type": "module",
4
- "version": "7.11.0",
4
+ "version": "7.12.0",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -21,6 +21,61 @@
21
21
  "require": "./lib/cjs/index.js",
22
22
  "types": "./lib/types/index.d.ts"
23
23
  },
24
+ "./builder": {
25
+ "import": "./lib/esm/builder.js",
26
+ "require": "./lib/cjs/builder.js",
27
+ "types": "./lib/types/builder.d.ts"
28
+ },
29
+ "./feature/block-edit": {
30
+ "import": "./lib/esm/feature/block-edit/index.js",
31
+ "require": "./lib/cjs/feature/block-edit/index.js",
32
+ "types": "./lib/types/feature/block-edit/index.d.ts"
33
+ },
34
+ "./feature/code-mirror": {
35
+ "import": "./lib/esm/feature/code-mirror/index.js",
36
+ "require": "./lib/cjs/feature/code-mirror/index.js",
37
+ "types": "./lib/types/feature/code-mirror/index.d.ts"
38
+ },
39
+ "./feature/cursor": {
40
+ "import": "./lib/esm/feature/cursor/index.js",
41
+ "require": "./lib/cjs/feature/cursor/index.js",
42
+ "types": "./lib/types/feature/cursor/index.d.ts"
43
+ },
44
+ "./feature/image-block": {
45
+ "import": "./lib/esm/feature/image-block/index.js",
46
+ "require": "./lib/cjs/feature/image-block/index.js",
47
+ "types": "./lib/types/feature/image-block/index.d.ts"
48
+ },
49
+ "./feature/latex": {
50
+ "import": "./lib/esm/feature/latex/index.js",
51
+ "require": "./lib/cjs/feature/latex/index.js",
52
+ "types": "./lib/types/feature/latex/index.d.ts"
53
+ },
54
+ "./feature/link-tooltip": {
55
+ "import": "./lib/esm/feature/link-tooltip/index.js",
56
+ "require": "./lib/cjs/feature/link-tooltip/index.js",
57
+ "types": "./lib/types/feature/link-tooltip/index.d.ts"
58
+ },
59
+ "./feature/list-item": {
60
+ "import": "./lib/esm/feature/list-item/index.js",
61
+ "require": "./lib/cjs/feature/list-item/index.js",
62
+ "types": "./lib/types/feature/list-item/index.d.ts"
63
+ },
64
+ "./feature/placeholder": {
65
+ "import": "./lib/esm/feature/placeholder/index.js",
66
+ "require": "./lib/cjs/feature/placeholder/index.js",
67
+ "types": "./lib/types/feature/placeholder/index.d.ts"
68
+ },
69
+ "./feature/table": {
70
+ "import": "./lib/esm/feature/table/index.js",
71
+ "require": "./lib/cjs/feature/table/index.js",
72
+ "types": "./lib/types/feature/table/index.d.ts"
73
+ },
74
+ "./feature/toolbar": {
75
+ "import": "./lib/esm/feature/toolbar/index.js",
76
+ "require": "./lib/cjs/feature/toolbar/index.js",
77
+ "types": "./lib/types/feature/toolbar/index.d.ts"
78
+ },
24
79
  "./theme/common/*": "./lib/theme/common/*",
25
80
  "./theme/classic.css": "./lib/theme/classic/style.css",
26
81
  "./theme/classic-dark.css": "./lib/theme/classic-dark/style.css",
@@ -41,21 +96,23 @@
41
96
  "@codemirror/state": "^6.4.1",
42
97
  "@codemirror/theme-one-dark": "^6.1.2",
43
98
  "@codemirror/view": "^6.16.0",
99
+ "@types/lodash-es": "^4.17.12",
44
100
  "clsx": "^2.0.0",
45
101
  "codemirror": "^6.0.1",
46
102
  "katex": "^0.16.0",
103
+ "lodash-es": "^4.17.21",
47
104
  "nanoid": "^5.0.9",
48
105
  "prosemirror-virtual-cursor": "^0.4.2",
49
106
  "remark-math": "^6.0.0",
50
107
  "tslib": "^2.8.1",
51
108
  "unist-util-visit": "^5.0.0",
52
109
  "vue": "^3.5.13",
53
- "@milkdown/kit": "7.11.0"
110
+ "@milkdown/kit": "7.12.0"
54
111
  },
55
112
  "scripts": {
56
113
  "build": "pnpm run build:es && pnpm run build:theme && echo",
57
114
  "build:es": "rollup -c",
58
- "build:theme": "postcss 'src/theme' --base 'src/theme' --dir 'lib/theme'"
115
+ "build:theme": "postcss src/theme --base src/theme --dir lib/theme"
59
116
  },
60
117
  "types": "./lib/types/index.d.ts"
61
118
  }
package/src/builder.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './core/builder'
@@ -0,0 +1,143 @@
1
+ import {
2
+ type DefaultValue,
3
+ defaultValueCtx,
4
+ Editor,
5
+ EditorStatus,
6
+ editorViewCtx,
7
+ editorViewOptionsCtx,
8
+ rootCtx,
9
+ } from '@milkdown/kit/core'
10
+ import { clipboard } from '@milkdown/kit/plugin/clipboard'
11
+ import { history } from '@milkdown/kit/plugin/history'
12
+ import { indent, indentConfig } from '@milkdown/kit/plugin/indent'
13
+ import {
14
+ listener,
15
+ listenerCtx,
16
+ type ListenerManager,
17
+ } from '@milkdown/kit/plugin/listener'
18
+ import { trailing } from '@milkdown/kit/plugin/trailing'
19
+ import { commonmark } from '@milkdown/kit/preset/commonmark'
20
+ import { gfm } from '@milkdown/kit/preset/gfm'
21
+ import { getMarkdown } from '@milkdown/kit/utils'
22
+
23
+ import type { CrepeFeature, CrepeFeatureConfig } from '../feature'
24
+ import type { DefineFeature } from '../feature/shared'
25
+
26
+ import { CrepeCtx, FeaturesCtx } from './slice'
27
+
28
+ /// The crepe builder configuration.
29
+ export interface CrepeBuilderConfig {
30
+ /// The root element for the editor.
31
+ /// Supports both DOM nodes and CSS selectors,
32
+ /// If not provided, the editor will be appended to the body.
33
+ root?: Node | string | null
34
+
35
+ /// The default value for the editor.
36
+ defaultValue?: DefaultValue
37
+ }
38
+
39
+ /// The crepe builder class.
40
+ /// This class allows users to manually add features to the editor.
41
+ export class CrepeBuilder {
42
+ /// @internal
43
+ readonly #editor: Editor
44
+
45
+ /// @internal
46
+ readonly #rootElement: Node
47
+
48
+ /// @internal
49
+ #editable = true
50
+
51
+ /// The constructor of the crepe builder.
52
+ /// You can pass configs to the builder to configure the editor.
53
+ constructor({ root, defaultValue = '' }: CrepeBuilderConfig) {
54
+ this.#rootElement =
55
+ (typeof root === 'string' ? document.querySelector(root) : root) ??
56
+ document.body
57
+ this.#editor = Editor.make()
58
+ .config((ctx) => {
59
+ ctx.inject(CrepeCtx, this)
60
+ ctx.inject(FeaturesCtx, [])
61
+ })
62
+ .config((ctx) => {
63
+ ctx.set(rootCtx, this.#rootElement)
64
+ ctx.set(defaultValueCtx, defaultValue)
65
+ ctx.set(editorViewOptionsCtx, {
66
+ editable: () => this.#editable,
67
+ })
68
+ ctx.update(indentConfig.key, (value) => ({
69
+ ...value,
70
+ size: 4,
71
+ }))
72
+ })
73
+ .use(commonmark)
74
+ .use(listener)
75
+ .use(history)
76
+ .use(indent)
77
+ .use(trailing)
78
+ .use(clipboard)
79
+ .use(gfm)
80
+ }
81
+
82
+ /// Add a feature to the editor.
83
+ addFeature: {
84
+ <T extends CrepeFeature>(
85
+ feature: DefineFeature<CrepeFeatureConfig[T]>,
86
+ config?: CrepeFeatureConfig[T]
87
+ ): CrepeBuilder
88
+ <C>(feature: DefineFeature<C>, config?: C): CrepeBuilder
89
+ } = (feature: DefineFeature, config?: never) => {
90
+ feature(this.#editor, config)
91
+ return this
92
+ }
93
+
94
+ /// Create the editor.
95
+ create = () => {
96
+ return this.#editor.create()
97
+ }
98
+
99
+ /// Destroy the editor.
100
+ destroy = () => {
101
+ return this.#editor.destroy()
102
+ }
103
+
104
+ /// Get the milkdown editor instance.
105
+ get editor(): Editor {
106
+ return this.#editor
107
+ }
108
+
109
+ /// Set the readonly mode of the editor.
110
+ setReadonly = (value: boolean) => {
111
+ this.#editable = !value
112
+ this.#editor.action((ctx) => {
113
+ if (this.#editor.status === EditorStatus.Created) {
114
+ const view = ctx.get(editorViewCtx)
115
+ view.setProps({
116
+ editable: () => !value,
117
+ })
118
+ }
119
+ })
120
+ return this
121
+ }
122
+
123
+ /// Get the markdown content of the editor.
124
+ getMarkdown = () => {
125
+ return this.#editor.action(getMarkdown())
126
+ }
127
+
128
+ /// Register event listeners.
129
+ on = (fn: (api: ListenerManager) => void) => {
130
+ if (this.#editor.status !== EditorStatus.Created) {
131
+ this.#editor.config((ctx) => {
132
+ const listener = ctx.get(listenerCtx)
133
+ fn(listener)
134
+ })
135
+ return this
136
+ }
137
+ this.#editor.action((ctx) => {
138
+ const listener = ctx.get(listenerCtx)
139
+ fn(listener)
140
+ })
141
+ return this
142
+ }
143
+ }
package/src/core/crepe.ts CHANGED
@@ -1,48 +1,38 @@
1
- import type { DefaultValue } from '@milkdown/kit/core'
2
- import type { ListenerManager } from '@milkdown/kit/plugin/listener'
3
-
4
- import {
5
- Editor,
6
- EditorStatus,
7
- defaultValueCtx,
8
- editorViewCtx,
9
- editorViewOptionsCtx,
10
- rootCtx,
11
- } from '@milkdown/kit/core'
12
- import { clipboard } from '@milkdown/kit/plugin/clipboard'
13
- import { history } from '@milkdown/kit/plugin/history'
14
- import { indent, indentConfig } from '@milkdown/kit/plugin/indent'
15
- import { listener, listenerCtx } from '@milkdown/kit/plugin/listener'
16
- import { trailing } from '@milkdown/kit/plugin/trailing'
17
- import { commonmark } from '@milkdown/kit/preset/commonmark'
18
- import { gfm } from '@milkdown/kit/preset/gfm'
19
- import { getMarkdown } from '@milkdown/kit/utils'
1
+ import { defaultsDeep } from 'lodash-es'
20
2
 
21
3
  import type { CrepeFeatureConfig } from '../feature'
22
4
 
23
- import { CrepeFeature, defaultFeatures, loadFeature } from '../feature'
24
- import { configureFeatures, crepeCtx } from './slice'
5
+ import { defaultConfig } from '../default-config'
6
+ import { CrepeFeature, defaultFeatures } from '../feature'
7
+ import { loadFeature } from '../feature/loader'
8
+ import { CrepeBuilder, type CrepeBuilderConfig } from './builder'
25
9
 
26
- export interface CrepeConfig {
10
+ /// The crepe editor configuration.
11
+ export interface CrepeConfig extends CrepeBuilderConfig {
12
+ /// Enable/disable specific features.
27
13
  features?: Partial<Record<CrepeFeature, boolean>>
14
+
15
+ /// Configure individual features.
28
16
  featureConfigs?: CrepeFeatureConfig
29
- root?: Node | string | null
30
- defaultValue?: DefaultValue
31
17
  }
32
18
 
33
- export class Crepe {
19
+ /// The crepe editor class.
20
+ export class Crepe extends CrepeBuilder {
21
+ /// This is an alias for the `CrepeFeature` enum.
34
22
  static Feature = CrepeFeature
35
- readonly #editor: Editor
36
- readonly #initPromise: Promise<unknown>
37
- readonly #rootElement: Node
38
- #editable = true
39
23
 
24
+ /// The constructor of the crepe editor.
25
+ /// You can pass configs to the editor to configure the editor.
26
+ /// Calling the constructor will not create the editor, you need to call `create` to create the editor.
40
27
  constructor({
41
- root,
42
28
  features = {},
43
29
  featureConfigs = {},
44
- defaultValue = '',
30
+ ...crepeBuilderConfig
45
31
  }: CrepeConfig) {
32
+ super(crepeBuilderConfig)
33
+
34
+ const finalConfigs = defaultsDeep(featureConfigs, defaultConfig)
35
+
46
36
  const enabledFeatures = Object.entries({
47
37
  ...defaultFeatures,
48
38
  ...features,
@@ -50,88 +40,11 @@ export class Crepe {
50
40
  .filter(([, enabled]) => enabled)
51
41
  .map(([feature]) => feature as CrepeFeature)
52
42
 
53
- this.#rootElement =
54
- (typeof root === 'string' ? document.querySelector(root) : root) ??
55
- document.body
56
- this.#editor = Editor.make()
57
- .config((ctx) => {
58
- ctx.inject(crepeCtx, this)
59
- })
60
- .config(configureFeatures(enabledFeatures))
61
- .config((ctx) => {
62
- ctx.set(rootCtx, this.#rootElement)
63
- ctx.set(defaultValueCtx, defaultValue)
64
- ctx.set(editorViewOptionsCtx, {
65
- editable: () => this.#editable,
66
- })
67
- ctx.update(indentConfig.key, (value) => ({
68
- ...value,
69
- size: 4,
70
- }))
71
- })
72
- .use(commonmark)
73
- .use(listener)
74
- .use(history)
75
- .use(indent)
76
- .use(trailing)
77
- .use(clipboard)
78
- .use(gfm)
79
-
80
- const promiseList: Promise<unknown>[] = []
81
-
82
43
  enabledFeatures.forEach((feature) => {
83
- const config = (featureConfigs as Partial<Record<CrepeFeature, never>>)[
44
+ const config = (finalConfigs as Partial<Record<CrepeFeature, never>>)[
84
45
  feature
85
46
  ]
86
- promiseList.push(loadFeature(feature, this.#editor, config))
87
- })
88
-
89
- this.#initPromise = Promise.all(promiseList)
90
- }
91
-
92
- create = async () => {
93
- await this.#initPromise
94
- return this.#editor.create()
95
- }
96
-
97
- destroy = async () => {
98
- await this.#initPromise
99
- return this.#editor.destroy()
100
- }
101
-
102
- get editor(): Editor {
103
- return this.#editor
104
- }
105
-
106
- setReadonly = (value: boolean) => {
107
- this.#editable = !value
108
- this.#editor.action((ctx) => {
109
- if (this.#editor.status === EditorStatus.Created) {
110
- const view = ctx.get(editorViewCtx)
111
- view.setProps({
112
- editable: () => !value,
113
- })
114
- }
115
- })
116
- return this
117
- }
118
-
119
- getMarkdown = () => {
120
- return this.#editor.action(getMarkdown())
121
- }
122
-
123
- on = (fn: (api: ListenerManager) => void) => {
124
- if (this.#editor.status !== EditorStatus.Created) {
125
- this.#editor.config((ctx) => {
126
- const listener = ctx.get(listenerCtx)
127
- fn(listener)
128
- })
129
- return this
130
- }
131
- this.#editor.action((ctx) => {
132
- const listener = ctx.get(listenerCtx)
133
- fn(listener)
47
+ loadFeature(feature, this.editor, config)
134
48
  })
135
- return this
136
49
  }
137
50
  }
package/src/core/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { Crepe, type CrepeConfig } from './crepe'
2
- export { crepeCtx } from './slice'
2
+ export { CrepeBuilder, type CrepeBuilderConfig } from './builder'
3
+ export { useCrepe, useCrepeFeatures } from './slice'
package/src/core/slice.ts CHANGED
@@ -1,16 +1,56 @@
1
- import type { Ctx } from '@milkdown/kit/ctx'
2
-
3
- import { createSlice } from '@milkdown/kit/ctx'
1
+ import { createSlice, type Ctx } from '@milkdown/kit/ctx'
4
2
 
5
3
  import type { CrepeFeature } from '../feature'
6
- import type { Crepe } from './crepe'
4
+ import type { CrepeBuilder } from './builder'
7
5
 
6
+ /// @internal
7
+ /// The feature flags context.
8
+ /// ⚠️ Most of the time, you should use `useCrepeFeatures` to get the features.
8
9
  export const FeaturesCtx = createSlice([] as CrepeFeature[], 'FeaturesCtx')
9
10
 
10
- export const crepeCtx = createSlice({} as Crepe, 'CrepeCtx')
11
+ /// @internal
12
+ /// The crepe editor context.
13
+ /// ⚠️ Most of the time, you should use `useCrepe` to get the crepe editor instance.
14
+ export const CrepeCtx = createSlice({} as CrepeBuilder, 'CrepeCtx')
15
+
16
+ /// The crepe editor context.
17
+ /// You can use this context to access the crepe editor instance within Milkdown plugins.
18
+ /// ```ts
19
+ /// import { crepeCtx } from '@milkdown/crepe'
20
+ /// const plugin = (ctx: Ctx) => {
21
+ /// return () => {
22
+ /// const crepe = useCrepe(ctx)
23
+ /// crepe.setReadonly(true)
24
+ /// }
25
+ /// }
26
+ /// ```
27
+ export function useCrepe(ctx: Ctx) {
28
+ // We should use string slice here to avoid the slice to be bundled in multiple entries
29
+ return ctx.get<CrepeBuilder, 'CrepeCtx'>('CrepeCtx')
30
+ }
31
+
32
+ /// Check the enabled FeatureFlags
33
+ /// ```ts
34
+ /// import { useCrepeFeatures } from '@milkdown/crepe'
35
+ /// const plugin = (ctx: Ctx) => {
36
+ /// const features = useCrepeFeatures(ctx)
37
+ /// if (features.get().includes(CrepeFeature.CodeMirror)) {
38
+ /// // Do something with CodeMirror
39
+ /// }
40
+ /// }
41
+ export function useCrepeFeatures(ctx: Ctx) {
42
+ // We should use string slice here to avoid the slice to be bundled in multiple entries
43
+ return ctx.use<CrepeFeature[], 'FeaturesCtx'>('FeaturesCtx')
44
+ }
11
45
 
12
- export function configureFeatures(features: CrepeFeature[]) {
46
+ /// @internal
47
+ export function crepeFeatureConfig(feature: CrepeFeature) {
13
48
  return (ctx: Ctx) => {
14
- ctx.inject(FeaturesCtx, features)
49
+ useCrepeFeatures(ctx).update((features) => {
50
+ if (features.includes(feature)) {
51
+ return features
52
+ }
53
+ return [...features, feature]
54
+ })
15
55
  }
16
56
  }
@@ -0,0 +1,25 @@
1
+ import { languages } from '@codemirror/language-data'
2
+ import { oneDark } from '@codemirror/theme-one-dark'
3
+
4
+ import { CrepeFeature, type CrepeFeatureConfig } from '../feature'
5
+ import {
6
+ chevronDownIcon,
7
+ clearIcon,
8
+ editIcon,
9
+ searchIcon,
10
+ visibilityOffIcon,
11
+ } from '../icons'
12
+
13
+ export const defaultConfig: CrepeFeatureConfig = {
14
+ [CrepeFeature.CodeMirror]: {
15
+ theme: oneDark,
16
+ languages,
17
+ expandIcon: chevronDownIcon,
18
+ searchIcon: searchIcon,
19
+ clearSearchIcon: clearIcon,
20
+ searchPlaceholder: 'Search language',
21
+ noResultText: 'No result',
22
+ previewToggleIcon: (previewOnlyMode) =>
23
+ previewOnlyMode ? editIcon : visibilityOffIcon,
24
+ },
25
+ }
@@ -1,15 +1,13 @@
1
1
  import { Icon } from '@milkdown/kit/component'
2
2
  import { defineComponent, ref, h, Fragment } from 'vue'
3
3
 
4
- import type { Icon as IconType } from '../../shared'
5
-
6
4
  h
7
5
  Fragment
8
6
 
9
7
  export interface BlockHandleProps {
10
8
  onAdd: () => void
11
- addIcon: IconType
12
- handleIcon: IconType
9
+ addIcon: string
10
+ handleIcon: string
13
11
  }
14
12
 
15
13
  export const BlockHandle = defineComponent<BlockHandleProps>({
@@ -19,11 +17,11 @@ export const BlockHandle = defineComponent<BlockHandleProps>({
19
17
  required: true,
20
18
  },
21
19
  addIcon: {
22
- type: Function,
20
+ type: String,
23
21
  required: true,
24
22
  },
25
23
  handleIcon: {
26
- type: Function,
24
+ type: String,
27
25
  required: true,
28
26
  },
29
27
  },
@@ -48,10 +46,10 @@ export const BlockHandle = defineComponent<BlockHandleProps>({
48
46
  props.onAdd()
49
47
  }}
50
48
  >
51
- <Icon icon={props.addIcon()} />
49
+ <Icon icon={props.addIcon} />
52
50
  </div>
53
51
  <div class="operation-item">
54
- <Icon icon={props.handleIcon()} />
52
+ <Icon icon={props.handleIcon} />
55
53
  </div>
56
54
  </>
57
55
  )
@@ -26,8 +26,8 @@ export class BlockHandleView implements PluginView {
26
26
  content.classList.add('milkdown-block-handle')
27
27
  const app = createApp(BlockHandle, {
28
28
  onAdd: this.onAdd,
29
- addIcon: config?.handleAddIcon ?? (() => plusIcon),
30
- handleIcon: config?.handleDragIcon ?? (() => menuIcon),
29
+ addIcon: config?.handleAddIcon ?? plusIcon,
30
+ handleIcon: config?.handleDragIcon ?? menuIcon,
31
31
  })
32
32
  app.mount(content)
33
33
  this.#app = app
@@ -1,62 +1,65 @@
1
1
  import { block } from '@milkdown/kit/plugin/block'
2
2
 
3
- import type { DefineFeature, Icon } from '../shared'
3
+ import type { DefineFeature } from '../shared'
4
4
  import type { GroupBuilder } from './menu/group-builder'
5
5
 
6
+ import { crepeFeatureConfig } from '../../core/slice'
7
+ import { CrepeFeature } from '../index'
6
8
  import { configureBlockHandle } from './handle'
7
9
  import { configureMenu, menu, menuAPI } from './menu'
8
10
 
9
11
  interface BlockEditConfig {
10
- handleAddIcon: Icon
11
- handleDragIcon: Icon
12
+ handleAddIcon: string
13
+ handleDragIcon: string
12
14
  buildMenu: (builder: GroupBuilder) => void
13
15
 
14
16
  slashMenuTextGroupLabel: string
15
- slashMenuTextIcon: Icon
17
+ slashMenuTextIcon: string
16
18
  slashMenuTextLabel: string
17
- slashMenuH1Icon: Icon
19
+ slashMenuH1Icon: string
18
20
  slashMenuH1Label: string
19
- slashMenuH2Icon: Icon
21
+ slashMenuH2Icon: string
20
22
  slashMenuH2Label: string
21
- slashMenuH3Icon: Icon
23
+ slashMenuH3Icon: string
22
24
  slashMenuH3Label: string
23
- slashMenuH4Icon: Icon
25
+ slashMenuH4Icon: string
24
26
  slashMenuH4Label: string
25
- slashMenuH5Icon: Icon
27
+ slashMenuH5Icon: string
26
28
  slashMenuH5Label: string
27
- slashMenuH6Icon: Icon
29
+ slashMenuH6Icon: string
28
30
  slashMenuH6Label: string
29
- slashMenuQuoteIcon: Icon
31
+ slashMenuQuoteIcon: string
30
32
  slashMenuQuoteLabel: string
31
- slashMenuDividerIcon: Icon
33
+ slashMenuDividerIcon: string
32
34
  slashMenuDividerLabel: string
33
35
 
34
36
  slashMenuListGroupLabel: string
35
- slashMenuBulletListIcon: Icon
37
+ slashMenuBulletListIcon: string
36
38
  slashMenuBulletListLabel: string
37
- slashMenuOrderedListIcon: Icon
39
+ slashMenuOrderedListIcon: string
38
40
  slashMenuOrderedListLabel: string
39
- slashMenuTaskListIcon: Icon
41
+ slashMenuTaskListIcon: string
40
42
  slashMenuTaskListLabel: string
41
43
 
42
44
  slashMenuAdvancedGroupLabel: string
43
- slashMenuImageIcon: Icon
45
+ slashMenuImageIcon: string
44
46
  slashMenuImageLabel: string
45
- slashMenuCodeBlockIcon: Icon
47
+ slashMenuCodeBlockIcon: string
46
48
  slashMenuCodeBlockLabel: string
47
- slashMenuTableIcon: Icon
49
+ slashMenuTableIcon: string
48
50
  slashMenuTableLabel: string
49
- slashMenuMathIcon: Icon
51
+ slashMenuMathIcon: string
50
52
  slashMenuMathLabel: string
51
53
  }
52
54
 
53
55
  export type BlockEditFeatureConfig = Partial<BlockEditConfig>
54
56
 
55
- export const defineFeature: DefineFeature<BlockEditFeatureConfig> = (
57
+ export const blockEdit: DefineFeature<BlockEditFeatureConfig> = (
56
58
  editor,
57
59
  config
58
60
  ) => {
59
61
  editor
62
+ .config(crepeFeatureConfig(CrepeFeature.BlockEdit))
60
63
  .config((ctx) => configureBlockHandle(ctx, config))
61
64
  .config((ctx) => configureMenu(ctx, config))
62
65
  .use(menuAPI)