@milkdown/crepe 7.19.2 → 7.21.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.js +44 -1
  2. package/lib/cjs/builder.js.map +1 -1
  3. package/lib/cjs/feature/ai/index.js +1492 -0
  4. package/lib/cjs/feature/ai/index.js.map +1 -0
  5. package/lib/cjs/feature/block-edit/index.js +9 -2
  6. package/lib/cjs/feature/block-edit/index.js.map +1 -1
  7. package/lib/cjs/feature/code-mirror/index.js +2 -0
  8. package/lib/cjs/feature/code-mirror/index.js.map +1 -1
  9. package/lib/cjs/feature/cursor/index.js +2 -0
  10. package/lib/cjs/feature/cursor/index.js.map +1 -1
  11. package/lib/cjs/feature/image-block/index.js +5 -1
  12. package/lib/cjs/feature/image-block/index.js.map +1 -1
  13. package/lib/cjs/feature/latex/index.js +7 -0
  14. package/lib/cjs/feature/latex/index.js.map +1 -1
  15. package/lib/cjs/feature/link-tooltip/index.js +2 -0
  16. package/lib/cjs/feature/link-tooltip/index.js.map +1 -1
  17. package/lib/cjs/feature/list-item/index.js +2 -0
  18. package/lib/cjs/feature/list-item/index.js.map +1 -1
  19. package/lib/cjs/feature/placeholder/index.js +2 -0
  20. package/lib/cjs/feature/placeholder/index.js.map +1 -1
  21. package/lib/cjs/feature/table/index.js +2 -0
  22. package/lib/cjs/feature/table/index.js.map +1 -1
  23. package/lib/cjs/feature/toolbar/index.js +497 -5
  24. package/lib/cjs/feature/toolbar/index.js.map +1 -1
  25. package/lib/cjs/feature/top-bar/index.js +791 -0
  26. package/lib/cjs/feature/top-bar/index.js.map +1 -0
  27. package/lib/cjs/index.js +2047 -160
  28. package/lib/cjs/index.js.map +1 -1
  29. package/lib/cjs/llm-providers/anthropic/index.js +147 -0
  30. package/lib/cjs/llm-providers/anthropic/index.js.map +1 -0
  31. package/lib/cjs/llm-providers/openai/index.js +138 -0
  32. package/lib/cjs/llm-providers/openai/index.js.map +1 -0
  33. package/lib/esm/builder.js +44 -1
  34. package/lib/esm/builder.js.map +1 -1
  35. package/lib/esm/feature/ai/index.js +1487 -0
  36. package/lib/esm/feature/ai/index.js.map +1 -0
  37. package/lib/esm/feature/block-edit/index.js +9 -2
  38. package/lib/esm/feature/block-edit/index.js.map +1 -1
  39. package/lib/esm/feature/code-mirror/index.js +2 -0
  40. package/lib/esm/feature/code-mirror/index.js.map +1 -1
  41. package/lib/esm/feature/cursor/index.js +2 -0
  42. package/lib/esm/feature/cursor/index.js.map +1 -1
  43. package/lib/esm/feature/image-block/index.js +5 -1
  44. package/lib/esm/feature/image-block/index.js.map +1 -1
  45. package/lib/esm/feature/latex/index.js +7 -0
  46. package/lib/esm/feature/latex/index.js.map +1 -1
  47. package/lib/esm/feature/link-tooltip/index.js +2 -0
  48. package/lib/esm/feature/link-tooltip/index.js.map +1 -1
  49. package/lib/esm/feature/list-item/index.js +2 -0
  50. package/lib/esm/feature/list-item/index.js.map +1 -1
  51. package/lib/esm/feature/placeholder/index.js +2 -0
  52. package/lib/esm/feature/placeholder/index.js.map +1 -1
  53. package/lib/esm/feature/table/index.js +2 -0
  54. package/lib/esm/feature/table/index.js.map +1 -1
  55. package/lib/esm/feature/toolbar/index.js +499 -7
  56. package/lib/esm/feature/toolbar/index.js.map +1 -1
  57. package/lib/esm/feature/top-bar/index.js +789 -0
  58. package/lib/esm/feature/top-bar/index.js.map +1 -0
  59. package/lib/esm/index.js +2040 -153
  60. package/lib/esm/index.js.map +1 -1
  61. package/lib/esm/llm-providers/anthropic/index.js +145 -0
  62. package/lib/esm/llm-providers/anthropic/index.js.map +1 -0
  63. package/lib/esm/llm-providers/openai/index.js +136 -0
  64. package/lib/esm/llm-providers/openai/index.js.map +1 -0
  65. package/lib/theme/common/ai.css +446 -0
  66. package/lib/theme/common/code-mirror.css +14 -0
  67. package/lib/theme/common/diff.css +177 -0
  68. package/lib/theme/common/style.css +3 -0
  69. package/lib/theme/common/top-bar.css +152 -0
  70. package/lib/tsconfig.tsbuildinfo +1 -1
  71. package/lib/types/core/builder.d.ts +2 -1
  72. package/lib/types/core/builder.d.ts.map +1 -1
  73. package/lib/types/feature/ai/ai.spec.d.ts +2 -0
  74. package/lib/types/feature/ai/ai.spec.d.ts.map +1 -0
  75. package/lib/types/feature/ai/commands.d.ts +24 -0
  76. package/lib/types/feature/ai/commands.d.ts.map +1 -0
  77. package/lib/types/feature/ai/context.d.ts +4 -0
  78. package/lib/types/feature/ai/context.d.ts.map +1 -0
  79. package/lib/types/feature/ai/diff-actions/index.d.ts +12 -0
  80. package/lib/types/feature/ai/diff-actions/index.d.ts.map +1 -0
  81. package/lib/types/feature/ai/diff-actions/view.d.ts +21 -0
  82. package/lib/types/feature/ai/diff-actions/view.d.ts.map +1 -0
  83. package/lib/types/feature/ai/index.d.ts +7 -0
  84. package/lib/types/feature/ai/index.d.ts.map +1 -0
  85. package/lib/types/feature/ai/instruction-tooltip/component.d.ts +26 -0
  86. package/lib/types/feature/ai/instruction-tooltip/component.d.ts.map +1 -0
  87. package/lib/types/feature/ai/instruction-tooltip/index.d.ts +17 -0
  88. package/lib/types/feature/ai/instruction-tooltip/index.d.ts.map +1 -0
  89. package/lib/types/feature/ai/instruction-tooltip/suggestions.d.ts +50 -0
  90. package/lib/types/feature/ai/instruction-tooltip/suggestions.d.ts.map +1 -0
  91. package/lib/types/feature/ai/instruction-tooltip/view.d.ts +19 -0
  92. package/lib/types/feature/ai/instruction-tooltip/view.d.ts.map +1 -0
  93. package/lib/types/feature/ai/streaming-indicator.d.ts +9 -0
  94. package/lib/types/feature/ai/streaming-indicator.d.ts.map +1 -0
  95. package/lib/types/feature/ai/types.d.ts +58 -0
  96. package/lib/types/feature/ai/types.d.ts.map +1 -0
  97. package/lib/types/feature/block-edit/handle/component.d.ts.map +1 -1
  98. package/lib/types/feature/block-edit/menu/component.d.ts.map +1 -1
  99. package/lib/types/feature/image-block/index.d.ts +2 -0
  100. package/lib/types/feature/image-block/index.d.ts.map +1 -1
  101. package/lib/types/feature/index.d.ts +7 -1
  102. package/lib/types/feature/index.d.ts.map +1 -1
  103. package/lib/types/feature/latex/inline-tooltip/component.d.ts.map +1 -1
  104. package/lib/types/feature/latex/inline-tooltip/inline-tooltip.spec.d.ts +2 -0
  105. package/lib/types/feature/latex/inline-tooltip/inline-tooltip.spec.d.ts.map +1 -0
  106. package/lib/types/feature/latex/inline-tooltip/view.d.ts.map +1 -1
  107. package/lib/types/feature/loader.d.ts.map +1 -1
  108. package/lib/types/feature/toolbar/component.d.ts.map +1 -1
  109. package/lib/types/feature/toolbar/config.d.ts +1 -1
  110. package/lib/types/feature/toolbar/config.d.ts.map +1 -1
  111. package/lib/types/feature/toolbar/index.d.ts +1 -0
  112. package/lib/types/feature/toolbar/index.d.ts.map +1 -1
  113. package/lib/types/feature/top-bar/component.d.ts +11 -0
  114. package/lib/types/feature/top-bar/component.d.ts.map +1 -0
  115. package/lib/types/feature/top-bar/config.d.ts +34 -0
  116. package/lib/types/feature/top-bar/config.d.ts.map +1 -0
  117. package/lib/types/feature/top-bar/index.d.ts +26 -0
  118. package/lib/types/feature/top-bar/index.d.ts.map +1 -0
  119. package/lib/types/icons/ai.d.ts +2 -0
  120. package/lib/types/icons/ai.d.ts.map +1 -0
  121. package/lib/types/icons/chevron-left.d.ts +2 -0
  122. package/lib/types/icons/chevron-left.d.ts.map +1 -0
  123. package/lib/types/icons/chevron-right.d.ts +2 -0
  124. package/lib/types/icons/chevron-right.d.ts.map +1 -0
  125. package/lib/types/icons/code-block.d.ts +2 -0
  126. package/lib/types/icons/code-block.d.ts.map +1 -0
  127. package/lib/types/icons/enter-key.d.ts +2 -0
  128. package/lib/types/icons/enter-key.d.ts.map +1 -0
  129. package/lib/types/icons/grammar-check.d.ts +2 -0
  130. package/lib/types/icons/grammar-check.d.ts.map +1 -0
  131. package/lib/types/icons/index.d.ts +12 -0
  132. package/lib/types/icons/index.d.ts.map +1 -1
  133. package/lib/types/icons/longer.d.ts +2 -0
  134. package/lib/types/icons/longer.d.ts.map +1 -0
  135. package/lib/types/icons/retry.d.ts +2 -0
  136. package/lib/types/icons/retry.d.ts.map +1 -0
  137. package/lib/types/icons/send-prompt.d.ts +2 -0
  138. package/lib/types/icons/send-prompt.d.ts.map +1 -0
  139. package/lib/types/icons/send.d.ts +2 -0
  140. package/lib/types/icons/send.d.ts.map +1 -0
  141. package/lib/types/icons/shorter.d.ts +2 -0
  142. package/lib/types/icons/shorter.d.ts.map +1 -0
  143. package/lib/types/icons/translate.d.ts +2 -0
  144. package/lib/types/icons/translate.d.ts.map +1 -0
  145. package/lib/types/llm-providers/anthropic/index.d.ts +21 -0
  146. package/lib/types/llm-providers/anthropic/index.d.ts.map +1 -0
  147. package/lib/types/llm-providers/openai/index.d.ts +15 -0
  148. package/lib/types/llm-providers/openai/index.d.ts.map +1 -0
  149. package/lib/types/llm-providers/providers.spec.d.ts +2 -0
  150. package/lib/types/llm-providers/providers.spec.d.ts.map +1 -0
  151. package/lib/types/llm-providers/shared.d.ts +16 -0
  152. package/lib/types/llm-providers/shared.d.ts.map +1 -0
  153. package/lib/types/utils/group-builder.d.ts +1 -1
  154. package/lib/types/utils/group-builder.d.ts.map +1 -1
  155. package/lib/types/utils/keep-alive.d.ts +2 -0
  156. package/lib/types/utils/keep-alive.d.ts.map +1 -0
  157. package/package.json +34 -13
  158. package/src/core/builder.ts +39 -2
  159. package/src/feature/ai/ai.spec.ts +742 -0
  160. package/src/feature/ai/commands.ts +257 -0
  161. package/src/feature/ai/context.ts +45 -0
  162. package/src/feature/ai/diff-actions/index.ts +95 -0
  163. package/src/feature/ai/diff-actions/view.ts +237 -0
  164. package/src/feature/ai/index.ts +118 -0
  165. package/src/feature/ai/instruction-tooltip/component.tsx +414 -0
  166. package/src/feature/ai/instruction-tooltip/index.ts +101 -0
  167. package/src/feature/ai/instruction-tooltip/suggestions.ts +249 -0
  168. package/src/feature/ai/instruction-tooltip/view.ts +159 -0
  169. package/src/feature/ai/streaming-indicator.ts +183 -0
  170. package/src/feature/ai/types.ts +178 -0
  171. package/src/feature/block-edit/handle/component.tsx +3 -2
  172. package/src/feature/block-edit/menu/component.tsx +3 -2
  173. package/src/feature/block-edit/menu/config.ts +1 -1
  174. package/src/feature/image-block/index.ts +4 -0
  175. package/src/feature/index.ts +14 -2
  176. package/src/feature/latex/inline-tooltip/component.tsx +4 -2
  177. package/src/feature/latex/inline-tooltip/inline-tooltip.spec.ts +81 -0
  178. package/src/feature/latex/inline-tooltip/view.ts +2 -0
  179. package/src/feature/loader.ts +8 -0
  180. package/src/feature/toolbar/component.tsx +7 -5
  181. package/src/feature/toolbar/config.ts +27 -1
  182. package/src/feature/toolbar/index.ts +1 -0
  183. package/src/feature/top-bar/component.tsx +198 -0
  184. package/src/feature/top-bar/config.ts +367 -0
  185. package/src/feature/top-bar/index.ts +113 -0
  186. package/src/icons/ai.ts +14 -0
  187. package/src/icons/chevron-left.ts +15 -0
  188. package/src/icons/chevron-right.ts +15 -0
  189. package/src/icons/code-block.ts +12 -0
  190. package/src/icons/enter-key.ts +13 -0
  191. package/src/icons/grammar-check.ts +13 -0
  192. package/src/icons/index.ts +12 -0
  193. package/src/icons/longer.ts +13 -0
  194. package/src/icons/retry.ts +13 -0
  195. package/src/icons/send-prompt.ts +13 -0
  196. package/src/icons/send.ts +13 -0
  197. package/src/icons/shorter.ts +13 -0
  198. package/src/icons/translate.ts +13 -0
  199. package/src/llm-providers/anthropic/index.ts +132 -0
  200. package/src/llm-providers/openai/index.ts +109 -0
  201. package/src/llm-providers/providers.spec.ts +472 -0
  202. package/src/llm-providers/shared.ts +160 -0
  203. package/src/theme/common/ai.css +430 -0
  204. package/src/theme/common/code-mirror.css +14 -0
  205. package/src/theme/common/diff.css +196 -0
  206. package/src/theme/common/style.css +3 -0
  207. package/src/theme/common/top-bar.css +156 -0
  208. package/src/utils/group-builder.ts +1 -1
  209. package/src/utils/keep-alive.ts +3 -0
package/lib/cjs/index.js CHANGED
@@ -3,31 +3,36 @@
3
3
  var lodashEs = require('lodash-es');
4
4
  var languageData = require('@codemirror/language-data');
5
5
  var themeOneDark = require('@codemirror/theme-one-dark');
6
- var block = require('@milkdown/kit/plugin/block');
6
+ var diff$1 = require('@milkdown/kit/component/diff');
7
+ var diff = require('@milkdown/kit/plugin/diff');
8
+ var streaming = require('@milkdown/kit/plugin/streaming');
7
9
  var ctx = require('@milkdown/kit/ctx');
8
10
  var core = require('@milkdown/kit/core');
9
- var commonmark = require('@milkdown/kit/preset/commonmark');
10
- var prose = require('@milkdown/kit/prose');
11
+ var exception = require('@milkdown/kit/exception');
12
+ var utils = require('@milkdown/kit/utils');
11
13
  var state = require('@milkdown/kit/prose/state');
14
+ var DOMPurify = require('dompurify');
15
+ var tooltip = require('@milkdown/kit/plugin/tooltip');
16
+ var prose = require('@milkdown/kit/prose');
12
17
  var vue = require('vue');
13
- var slash = require('@milkdown/kit/plugin/slash');
14
- var utils = require('@milkdown/kit/utils');
15
18
  var component = require('@milkdown/kit/component');
19
+ var view = require('@milkdown/kit/prose/view');
20
+ var block = require('@milkdown/kit/plugin/block');
21
+ var commonmark = require('@milkdown/kit/preset/commonmark');
22
+ var slash = require('@milkdown/kit/plugin/slash');
16
23
  var imageBlock$1 = require('@milkdown/kit/component/image-block');
17
24
  var gfm = require('@milkdown/kit/preset/gfm');
18
25
  var commands = require('@codemirror/commands');
19
- var view = require('@codemirror/view');
26
+ var view$1 = require('@codemirror/view');
20
27
  var codeBlock = require('@milkdown/kit/component/code-block');
21
28
  var codemirror = require('codemirror');
22
29
  var cursor$1 = require('@milkdown/kit/plugin/cursor');
23
30
  var prosemirrorVirtualCursor = require('prosemirror-virtual-cursor');
24
31
  var imageInline = require('@milkdown/kit/component/image-inline');
25
32
  var katex = require('katex');
26
- var tooltip = require('@milkdown/kit/plugin/tooltip');
27
33
  var history = require('@milkdown/kit/prose/history');
28
34
  var keymap = require('@milkdown/kit/prose/keymap');
29
35
  var model = require('@milkdown/kit/prose/model');
30
- var view$1 = require('@milkdown/kit/prose/view');
31
36
  var inputrules = require('@milkdown/kit/prose/inputrules');
32
37
  var remarkMath = require('remark-math');
33
38
  var unistUtilVisit = require('unist-util-visit');
@@ -40,6 +45,7 @@ var history$1 = require('@milkdown/kit/plugin/history');
40
45
  var indent = require('@milkdown/kit/plugin/indent');
41
46
  var listener = require('@milkdown/kit/plugin/listener');
42
47
  var trailing = require('@milkdown/kit/plugin/trailing');
48
+ var upload = require('@milkdown/kit/plugin/upload');
43
49
 
44
50
  var CrepeFeature = /* @__PURE__ */ ((CrepeFeature2) => {
45
51
  CrepeFeature2["CodeMirror"] = "code-mirror";
@@ -52,6 +58,8 @@ var CrepeFeature = /* @__PURE__ */ ((CrepeFeature2) => {
52
58
  CrepeFeature2["Placeholder"] = "placeholder";
53
59
  CrepeFeature2["Table"] = "table";
54
60
  CrepeFeature2["Latex"] = "latex";
61
+ CrepeFeature2["TopBar"] = "top-bar";
62
+ CrepeFeature2["AI"] = "ai";
55
63
  return CrepeFeature2;
56
64
  })(CrepeFeature || {});
57
65
  const defaultFeatures = {
@@ -64,9 +72,26 @@ const defaultFeatures = {
64
72
  ["toolbar" /* Toolbar */]: true,
65
73
  ["code-mirror" /* CodeMirror */]: true,
66
74
  ["table" /* Table */]: true,
67
- ["latex" /* Latex */]: true
75
+ ["latex" /* Latex */]: true,
76
+ ["top-bar" /* TopBar */]: false,
77
+ ["ai" /* AI */]: false
68
78
  };
69
79
 
80
+ const aiIcon = `
81
+ <svg
82
+ xmlns="http://www.w3.org/2000/svg"
83
+ width="24"
84
+ height="24"
85
+ viewBox="0 0 24 24"
86
+ >
87
+ <path
88
+ fill="currentColor"
89
+ d="M19 9l1.25-2.75L23 5l-2.75-1.25L19 1l-1.25 2.75L15 5l2.75 1.25zm0 14l1.25-2.75L23 19l-2.75-1.25L19 15l-1.25 2.75L15 19l2.75 1.25zM9 20l3-6.5L18 10l-6-3.5L9 0L6 6.5L0 10l6 3.5z"
90
+ transform="translate(3 3) scale(0.75)"
91
+ />
92
+ </svg>
93
+ `;
94
+
70
95
  const alignCenterIcon = `
71
96
  <svg
72
97
  xmlns="http://www.w3.org/2000/svg"
@@ -228,6 +253,38 @@ const chevronDownIcon = `
228
253
  </svg>
229
254
  `;
230
255
 
256
+ const chevronLeftIcon = `
257
+ <svg
258
+ xmlns="http://www.w3.org/2000/svg"
259
+ fill="none"
260
+ viewBox="0 0 24 24"
261
+ stroke-width="1.5"
262
+ stroke="currentColor"
263
+ >
264
+ <path
265
+ stroke-linecap="round"
266
+ stroke-linejoin="round"
267
+ d="M15.75 19.5L8.25 12l7.5-7.5"
268
+ />
269
+ </svg>
270
+ `;
271
+
272
+ const chevronRightIcon = `
273
+ <svg
274
+ xmlns="http://www.w3.org/2000/svg"
275
+ fill="none"
276
+ viewBox="0 0 24 24"
277
+ stroke-width="1.5"
278
+ stroke="currentColor"
279
+ >
280
+ <path
281
+ stroke-linecap="round"
282
+ stroke-linejoin="round"
283
+ d="M8.25 4.5l7.5 7.5-7.5 7.5"
284
+ />
285
+ </svg>
286
+ `;
287
+
231
288
  const clearIcon = `
232
289
  <svg
233
290
  xmlns="http://www.w3.org/2000/svg"
@@ -268,6 +325,19 @@ const codeIcon = `
268
325
  </svg>
269
326
  `;
270
327
 
328
+ const codeBlockIcon = `
329
+ <svg
330
+ xmlns="http://www.w3.org/2000/svg"
331
+ width="24"
332
+ height="24"
333
+ viewBox="0 0 24 24"
334
+ >
335
+ <path
336
+ d="M3 3h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm1 2v14h16V5H4zm8 10h6v2h-6v-2zm-3.333-3L5.838 9.172l1.415-1.415L11.495 12l-4.242 4.243-1.415-1.415L8.667 12z"
337
+ />
338
+ </svg>
339
+ `;
340
+
271
341
  const confirmIcon = `
272
342
  <svg
273
343
  xmlns="http://www.w3.org/2000/svg"
@@ -359,6 +429,34 @@ const editIcon = `
359
429
  </svg>
360
430
  `;
361
431
 
432
+ const enterKeyIcon = `
433
+ <svg
434
+ xmlns="http://www.w3.org/2000/svg"
435
+ width="24"
436
+ height="24"
437
+ viewBox="0 0 24 24"
438
+ >
439
+ <path
440
+ fill="currentColor"
441
+ d="M9 16l-5-5l5-5l1.4 1.4L7.825 10H18V6h2v6H7.825l2.575 2.6z"
442
+ />
443
+ </svg>
444
+ `;
445
+
446
+ const grammarCheckIcon = `
447
+ <svg
448
+ xmlns="http://www.w3.org/2000/svg"
449
+ width="24"
450
+ height="24"
451
+ viewBox="0 0 24 24"
452
+ >
453
+ <path
454
+ fill="currentColor"
455
+ d="M9.55 17.575L4.225 12.25l1.4-1.425L9.55 14.75l8.825-8.825l1.4 1.425z"
456
+ />
457
+ </svg>
458
+ `;
459
+
362
460
  const h1Icon = `
363
461
  <svg
364
462
  xmlns="http://www.w3.org/2000/svg"
@@ -525,6 +623,20 @@ const linkIcon = `
525
623
  </svg>
526
624
  `;
527
625
 
626
+ const longerIcon = `
627
+ <svg
628
+ xmlns="http://www.w3.org/2000/svg"
629
+ width="24"
630
+ height="24"
631
+ viewBox="0 0 24 24"
632
+ >
633
+ <path
634
+ fill="currentColor"
635
+ d="M3 18v-2h13v2zm0-5v-2h18v2zm0-5V6h18v2zm15 13v-3h-3v-2h3v-3h2v3h3v2h-3v3z"
636
+ />
637
+ </svg>
638
+ `;
639
+
528
640
  const menuIcon = `
529
641
  <svg
530
642
  xmlns="http://www.w3.org/2000/svg"
@@ -618,6 +730,20 @@ const removeIcon = `
618
730
  </svg>
619
731
  `;
620
732
 
733
+ const retryIcon = `
734
+ <svg
735
+ xmlns="http://www.w3.org/2000/svg"
736
+ width="24"
737
+ height="24"
738
+ viewBox="0 0 24 24"
739
+ >
740
+ <path
741
+ fill="currentColor"
742
+ d="M12 20q-3.35 0-5.675-2.325T4 12q0-3.35 2.325-5.675T12 4q1.725 0 3.3.713T18 6.75V4h2v7h-7V9h4.2q-.8-1.4-2.187-2.2T12 6Q9.5 6 7.75 7.75T6 12q0 2.5 1.75 4.25T12 18q1.925 0 3.475-1.1T17.65 14h2.1q-.7 2.65-2.85 4.325T12 20"
743
+ />
744
+ </svg>
745
+ `;
746
+
621
747
  const searchIcon = `
622
748
  <svg
623
749
  xmlns="http://www.w3.org/2000/svg"
@@ -635,6 +761,48 @@ const searchIcon = `
635
761
  </svg>
636
762
  `;
637
763
 
764
+ const sendIcon = `
765
+ <svg
766
+ xmlns="http://www.w3.org/2000/svg"
767
+ width="24"
768
+ height="24"
769
+ viewBox="0 0 24 24"
770
+ >
771
+ <path
772
+ fill="currentColor"
773
+ d="M11 20V7.825l-5.6 5.6L4 12l8-8l8 8l-1.4 1.425l-5.6-5.6V20z"
774
+ />
775
+ </svg>
776
+ `;
777
+
778
+ const sendPromptIcon = `
779
+ <svg
780
+ xmlns="http://www.w3.org/2000/svg"
781
+ width="24"
782
+ height="24"
783
+ viewBox="0 0 24 24"
784
+ >
785
+ <path
786
+ fill="currentColor"
787
+ d="M3 20v-6l8-2l-8-2V4l19 8z"
788
+ />
789
+ </svg>
790
+ `;
791
+
792
+ const shorterIcon = `
793
+ <svg
794
+ xmlns="http://www.w3.org/2000/svg"
795
+ width="24"
796
+ height="24"
797
+ viewBox="0 0 24 24"
798
+ >
799
+ <path
800
+ fill="currentColor"
801
+ d="M5 13v-2h14v2z"
802
+ />
803
+ </svg>
804
+ `;
805
+
638
806
  const strikethroughIcon = `
639
807
  <svg
640
808
  xmlns="http://www.w3.org/2000/svg"
@@ -701,6 +869,20 @@ const todoListIcon = `
701
869
  </svg>
702
870
  `;
703
871
 
872
+ const translateIcon = `
873
+ <svg
874
+ xmlns="http://www.w3.org/2000/svg"
875
+ width="24"
876
+ height="24"
877
+ viewBox="0 0 24 24"
878
+ >
879
+ <path
880
+ fill="currentColor"
881
+ d="m12.9 16l-2.55-2.5l.05-.05q1.45-1.6 2.262-3.117T13.95 7H16V5h-6V3H8v2H2v2h9.1q-.5 1.2-1.225 2.387T8 11.7q-.6-.6-1.187-1.412T5.85 8.6H3.85q.5 1.4 1.3 2.7T6.95 13.7L2.85 17.75L4.25 19.15L8 15.4L10.55 17.95zM18.5 22h-2L21 10h2l4.5 12h-2l-1.05-3h-4.9zm1.6-5h3.6l-1.8-5.1z"
882
+ />
883
+ </svg>
884
+ `;
885
+
704
886
  const functionsIcon = `
705
887
  <svg
706
888
  xmlns="http://www.w3.org/2000/svg"
@@ -760,6 +942,1223 @@ function crepeFeatureConfig(feature) {
760
942
  };
761
943
  }
762
944
 
945
+ function defaultBuildContext(ctx, instruction) {
946
+ var _a;
947
+ const view = ctx.get(core.editorViewCtx);
948
+ const serializer = ctx.get(core.serializerCtx);
949
+ const { state } = view;
950
+ const document = serializer(state.doc);
951
+ let selection = "";
952
+ if (!state.selection.empty) {
953
+ const { from, to } = state.selection;
954
+ const slice = state.doc.slice(from, to);
955
+ const { schema } = state.doc.type;
956
+ let wrapper = schema.topNodeType.createAndFill(null, slice.content);
957
+ if (!wrapper) {
958
+ const paragraph = (_a = schema.nodes.paragraph) == null ? void 0 : _a.createAndFill(
959
+ null,
960
+ slice.content
961
+ );
962
+ if (paragraph) wrapper = schema.topNodeType.createAndFill(null, paragraph);
963
+ }
964
+ selection = wrapper ? serializer(wrapper) : state.doc.textBetween(from, to);
965
+ }
966
+ return { document, selection, instruction };
967
+ }
968
+
969
+ const aiProviderConfig = utils.$ctx(
970
+ {
971
+ provider: void 0,
972
+ buildContext: void 0,
973
+ diffReviewOnEnd: true,
974
+ onError: (error) => {
975
+ console.error(`[milkdown/ai] [${error.code}]`, error);
976
+ },
977
+ aiIcon: void 0
978
+ },
979
+ "aiProviderConfig"
980
+ );
981
+ const aiSessionCtx = utils.$ctx(
982
+ {
983
+ abortController: null,
984
+ label: "",
985
+ lastInstruction: "",
986
+ lastLabel: void 0,
987
+ lastFrom: -1,
988
+ lastTo: -1,
989
+ diffOwnedByAI: false
990
+ },
991
+ "aiSession"
992
+ );
993
+ function emitAIError(ctx, error) {
994
+ const config = ctx.get(aiProviderConfig.key);
995
+ try {
996
+ config.onError(error);
997
+ } catch (handlerError) {
998
+ console.error("[milkdown/ai] onError handler failed:", handlerError);
999
+ }
1000
+ }
1001
+ function clearActiveSession(ctx) {
1002
+ const current = ctx.get(aiSessionCtx.key);
1003
+ ctx.set(aiSessionCtx.key, {
1004
+ ...current,
1005
+ abortController: null,
1006
+ label: ""
1007
+ });
1008
+ }
1009
+ async function runProvider(ctx, provider, promptContext, abortController) {
1010
+ try {
1011
+ const iterable = provider(promptContext, abortController.signal);
1012
+ const commands = ctx.get(core.commandsCtx);
1013
+ for await (const chunk of iterable) {
1014
+ if (abortController.signal.aborted) break;
1015
+ commands.call(streaming.pushChunkCmd.key, chunk);
1016
+ }
1017
+ if (abortController.signal.aborted) return;
1018
+ const config = ctx.get(aiProviderConfig.key);
1019
+ if (config.diffReviewOnEnd) {
1020
+ const cur = ctx.get(aiSessionCtx.key);
1021
+ ctx.set(aiSessionCtx.key, { ...cur, diffOwnedByAI: true });
1022
+ }
1023
+ const dispatched = commands.call(streaming.endStreamingCmd.key, {
1024
+ diffReview: config.diffReviewOnEnd
1025
+ });
1026
+ if (config.diffReviewOnEnd && !dispatched) {
1027
+ const cur = ctx.get(aiSessionCtx.key);
1028
+ ctx.set(aiSessionCtx.key, { ...cur, diffOwnedByAI: false });
1029
+ }
1030
+ } catch (error) {
1031
+ if (abortController.signal.aborted) return;
1032
+ const milkdownError = exception.aiProviderError(error);
1033
+ emitAIError(ctx, milkdownError);
1034
+ const commands = ctx.get(core.commandsCtx);
1035
+ commands.call(streaming.abortStreamingCmd.key, { keep: false });
1036
+ } finally {
1037
+ const current = ctx.get(aiSessionCtx.key);
1038
+ if (current.abortController === abortController) {
1039
+ clearActiveSession(ctx);
1040
+ }
1041
+ }
1042
+ }
1043
+ const runAICmd = utils.$command("RunAI", (ctx) => {
1044
+ return (options) => (state, dispatch) => {
1045
+ var _a, _b, _c, _d;
1046
+ if (!(options == null ? void 0 : options.instruction)) return false;
1047
+ const config = ctx.get(aiProviderConfig.key);
1048
+ if (!config.provider) return false;
1049
+ const session = ctx.get(aiSessionCtx.key);
1050
+ if (session.abortController) return false;
1051
+ if ((_a = streaming.streamingPluginKey.getState(state)) == null ? void 0 : _a.active) return false;
1052
+ if ((_b = diff.diffPluginKey.getState(state)) == null ? void 0 : _b.active) return false;
1053
+ if (!dispatch) return true;
1054
+ const abortController = new AbortController();
1055
+ const { from, to } = state.selection;
1056
+ ctx.set(aiSessionCtx.key, {
1057
+ abortController,
1058
+ label: (_c = options.label) != null ? _c : "",
1059
+ lastInstruction: options.instruction,
1060
+ lastLabel: options.label,
1061
+ lastFrom: from,
1062
+ lastTo: to,
1063
+ // Reset every run; only the success path that hands off to diff
1064
+ // review flips it back on.
1065
+ diffOwnedByAI: false
1066
+ });
1067
+ const commands = ctx.get(core.commandsCtx);
1068
+ const insertAt = state.selection.empty ? "cursor" : "selection";
1069
+ if (!commands.call(streaming.startStreamingCmd.key, { insertAt })) {
1070
+ clearActiveSession(ctx);
1071
+ return false;
1072
+ }
1073
+ let promptContext;
1074
+ try {
1075
+ const buildContext = (_d = config.buildContext) != null ? _d : defaultBuildContext;
1076
+ promptContext = buildContext(ctx, options.instruction);
1077
+ } catch (error) {
1078
+ const milkdownError = exception.aiBuildContextError(error);
1079
+ emitAIError(ctx, milkdownError);
1080
+ commands.call(streaming.abortStreamingCmd.key, { keep: false });
1081
+ clearActiveSession(ctx);
1082
+ return false;
1083
+ }
1084
+ void runProvider(ctx, config.provider, promptContext, abortController);
1085
+ return true;
1086
+ };
1087
+ });
1088
+ const abortAICmd = utils.$command("AbortAI", (ctx) => {
1089
+ return (options) => (state, dispatch) => {
1090
+ var _a;
1091
+ const session = ctx.get(aiSessionCtx.key);
1092
+ if (!dispatch) return !!session.abortController;
1093
+ if (!session.abortController) return false;
1094
+ session.abortController.abort();
1095
+ clearActiveSession(ctx);
1096
+ if ((_a = streaming.streamingPluginKey.getState(state)) == null ? void 0 : _a.active) {
1097
+ const commands = ctx.get(core.commandsCtx);
1098
+ commands.call(streaming.abortStreamingCmd.key, options);
1099
+ }
1100
+ return true;
1101
+ };
1102
+ });
1103
+
1104
+ var __typeError$a = (msg) => {
1105
+ throw TypeError(msg);
1106
+ };
1107
+ var __accessCheck$a = (obj, member, msg) => member.has(obj) || __typeError$a("Cannot " + msg);
1108
+ var __privateGet$a = (obj, member, getter) => (__accessCheck$a(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
1109
+ var __privateAdd$a = (obj, member, value) => member.has(obj) ? __typeError$a("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1110
+ var __privateSet$a = (obj, member, value, setter) => (__accessCheck$a(obj, member, "write to private field"), member.set(obj, value), value);
1111
+ var __privateMethod = (obj, member, method) => (__accessCheck$a(obj, member, "access private method"), method);
1112
+ var _panel, _host, _retryBtn, _config, _visible, _diffActive, _diffStartDoc, _ownedByAI, _DiffActionsPanelView_instances, findHost_fn, makeButton_fn, makeShortcutChip_fn, _retry, canRetry_fn, _rejectAll, _acceptAll;
1113
+ const PANEL_CLASS = "milkdown-ai-diff-actions";
1114
+ function setSanitizedIcon(host, svg) {
1115
+ host.innerHTML = DOMPurify.sanitize(svg.trim());
1116
+ }
1117
+ function createIcon(svg) {
1118
+ const span = document.createElement("span");
1119
+ span.className = `${PANEL_CLASS}-icon`;
1120
+ setSanitizedIcon(span, svg);
1121
+ return span;
1122
+ }
1123
+ class DiffActionsPanelView {
1124
+ constructor(ctx, view, config) {
1125
+ this.ctx = ctx;
1126
+ __privateAdd$a(this, _DiffActionsPanelView_instances);
1127
+ __privateAdd$a(this, _panel);
1128
+ __privateAdd$a(this, _host);
1129
+ __privateAdd$a(this, _retryBtn);
1130
+ __privateAdd$a(this, _config);
1131
+ __privateAdd$a(this, _visible, false);
1132
+ /// Tracks the diff plugin's `active` flag across transactions so we
1133
+ /// can detect false→true / true→false edges independently of whether
1134
+ /// the panel is actually being shown.
1135
+ __privateAdd$a(this, _diffActive, false);
1136
+ /// Doc snapshot at the moment diff review activated. If the live doc
1137
+ /// drifts from this snapshot the user has accepted some per-change
1138
+ /// diffs and the stored `lastFrom`/`lastTo` no longer point at the
1139
+ /// original range — Retry is unsafe at that point.
1140
+ __privateAdd$a(this, _diffStartDoc, null);
1141
+ /// Whether the active diff review came from this AI session's
1142
+ /// streaming hand-off (vs being started manually via
1143
+ /// `startDiffReviewCmd`). Captured at the false→true transition.
1144
+ /// The panel only renders when this is true so it doesn't take over
1145
+ /// non-AI diff flows that exist independently of the AI feature.
1146
+ __privateAdd$a(this, _ownedByAI, false);
1147
+ __privateAdd$a(this, _retry, () => {
1148
+ const session = this.ctx.get(aiSessionCtx.key);
1149
+ if (!session.lastInstruction) return;
1150
+ if (!__privateGet$a(this, _ownedByAI) || !__privateMethod(this, _DiffActionsPanelView_instances, canRetry_fn).call(this)) return;
1151
+ const commands = this.ctx.get(core.commandsCtx);
1152
+ commands.call(diff.clearDiffReviewCmd.key);
1153
+ const editorView = this.ctx.get(core.editorViewCtx);
1154
+ const { doc } = editorView.state;
1155
+ const from = Math.min(Math.max(session.lastFrom, 0), doc.content.size);
1156
+ const to = Math.min(Math.max(session.lastTo, 0), doc.content.size);
1157
+ editorView.dispatch(
1158
+ editorView.state.tr.setSelection(
1159
+ state.TextSelection.create(editorView.state.doc, from, to)
1160
+ )
1161
+ );
1162
+ commands.call(runAICmd.key, {
1163
+ instruction: session.lastInstruction,
1164
+ label: session.lastLabel
1165
+ });
1166
+ });
1167
+ __privateAdd$a(this, _rejectAll, () => {
1168
+ this.ctx.get(core.commandsCtx).call(diff.clearDiffReviewCmd.key);
1169
+ });
1170
+ __privateAdd$a(this, _acceptAll, () => {
1171
+ this.ctx.get(core.commandsCtx).call(diff.acceptAllDiffsCmd.key);
1172
+ });
1173
+ __privateSet$a(this, _config, config);
1174
+ __privateSet$a(this, _host, __privateMethod(this, _DiffActionsPanelView_instances, findHost_fn).call(this, view));
1175
+ const panel = document.createElement("div");
1176
+ panel.className = PANEL_CLASS;
1177
+ panel.dataset.show = "false";
1178
+ __privateSet$a(this, _retryBtn, __privateMethod(this, _DiffActionsPanelView_instances, makeButton_fn).call(this, "retry", config.retryIcon, config.retryLabel, __privateGet$a(this, _retry)));
1179
+ panel.appendChild(__privateGet$a(this, _retryBtn));
1180
+ panel.appendChild(
1181
+ __privateMethod(this, _DiffActionsPanelView_instances, makeButton_fn).call(this, "reject", config.rejectIcon, config.rejectAllLabel, __privateGet$a(this, _rejectAll))
1182
+ );
1183
+ const acceptBtn = __privateMethod(this, _DiffActionsPanelView_instances, makeButton_fn).call(this, "accept", config.acceptIcon, config.acceptAllLabel, __privateGet$a(this, _acceptAll));
1184
+ acceptBtn.appendChild(__privateMethod(this, _DiffActionsPanelView_instances, makeShortcutChip_fn).call(this));
1185
+ panel.appendChild(acceptBtn);
1186
+ __privateSet$a(this, _panel, panel);
1187
+ __privateGet$a(this, _host).appendChild(panel);
1188
+ this.update(view);
1189
+ }
1190
+ update(view) {
1191
+ var _a;
1192
+ const diffActive = !!((_a = diff.diffPluginKey.getState(view.state)) == null ? void 0 : _a.active);
1193
+ if (diffActive !== __privateGet$a(this, _diffActive)) {
1194
+ __privateSet$a(this, _diffActive, diffActive);
1195
+ if (diffActive) {
1196
+ const session = this.ctx.get(aiSessionCtx.key);
1197
+ __privateSet$a(this, _ownedByAI, session.diffOwnedByAI);
1198
+ __privateSet$a(this, _diffStartDoc, view.state.doc);
1199
+ } else {
1200
+ __privateSet$a(this, _ownedByAI, false);
1201
+ __privateSet$a(this, _diffStartDoc, null);
1202
+ const session = this.ctx.get(aiSessionCtx.key);
1203
+ if (session.diffOwnedByAI) {
1204
+ this.ctx.set(aiSessionCtx.key, {
1205
+ ...session,
1206
+ diffOwnedByAI: false
1207
+ });
1208
+ }
1209
+ }
1210
+ }
1211
+ const shouldShow = diffActive && __privateGet$a(this, _ownedByAI);
1212
+ if (shouldShow !== __privateGet$a(this, _visible)) {
1213
+ __privateSet$a(this, _visible, shouldShow);
1214
+ __privateGet$a(this, _panel).dataset.show = shouldShow ? "true" : "false";
1215
+ }
1216
+ if (shouldShow) {
1217
+ const session = this.ctx.get(aiSessionCtx.key);
1218
+ const docUntouched = !!__privateGet$a(this, _diffStartDoc) && view.state.doc.eq(__privateGet$a(this, _diffStartDoc));
1219
+ __privateGet$a(this, _retryBtn).disabled = !session.lastInstruction || !docUntouched;
1220
+ }
1221
+ }
1222
+ destroy() {
1223
+ __privateGet$a(this, _panel).remove();
1224
+ }
1225
+ }
1226
+ _panel = new WeakMap();
1227
+ _host = new WeakMap();
1228
+ _retryBtn = new WeakMap();
1229
+ _config = new WeakMap();
1230
+ _visible = new WeakMap();
1231
+ _diffActive = new WeakMap();
1232
+ _diffStartDoc = new WeakMap();
1233
+ _ownedByAI = new WeakMap();
1234
+ _DiffActionsPanelView_instances = new WeakSet();
1235
+ findHost_fn = function(view) {
1236
+ var _a;
1237
+ return (_a = view.dom.closest(".milkdown")) != null ? _a : document.body;
1238
+ };
1239
+ makeButton_fn = function(variant, icon, label, onClick) {
1240
+ const btn = document.createElement("button");
1241
+ btn.type = "button";
1242
+ btn.className = `${PANEL_CLASS}-btn ${PANEL_CLASS}-btn-${variant}`;
1243
+ btn.appendChild(createIcon(icon));
1244
+ const text = document.createElement("span");
1245
+ text.textContent = label;
1246
+ btn.appendChild(text);
1247
+ btn.addEventListener("mousedown", (e) => e.preventDefault());
1248
+ btn.addEventListener("click", (e) => {
1249
+ e.preventDefault();
1250
+ e.stopPropagation();
1251
+ onClick();
1252
+ });
1253
+ return btn;
1254
+ };
1255
+ makeShortcutChip_fn = function() {
1256
+ const shortcut = document.createElement("span");
1257
+ shortcut.className = `${PANEL_CLASS}-shortcut`;
1258
+ const cmd = document.createElement("span");
1259
+ cmd.textContent = __privateGet$a(this, _config).modSymbol;
1260
+ const enter = document.createElement("span");
1261
+ enter.className = `${PANEL_CLASS}-shortcut-icon`;
1262
+ setSanitizedIcon(enter, __privateGet$a(this, _config).enterKeyIcon);
1263
+ shortcut.append(cmd, enter);
1264
+ return shortcut;
1265
+ };
1266
+ _retry = new WeakMap();
1267
+ canRetry_fn = function() {
1268
+ if (!__privateGet$a(this, _diffStartDoc)) return false;
1269
+ const editorView = this.ctx.get(core.editorViewCtx);
1270
+ return editorView.state.doc.eq(__privateGet$a(this, _diffStartDoc));
1271
+ };
1272
+ _rejectAll = new WeakMap();
1273
+ _acceptAll = new WeakMap();
1274
+
1275
+ const diffActionsPanelKey = new state.PluginKey("CREPE_AI_DIFF_ACTIONS_PANEL");
1276
+ const DEFAULT_DIFF_ACTIONS_RETRY_LABEL = "Retry";
1277
+ const DEFAULT_DIFF_ACTIONS_REJECT_ALL_LABEL = "Reject all";
1278
+ const DEFAULT_DIFF_ACTIONS_ACCEPT_ALL_LABEL = "Accept all";
1279
+ function detectModSymbol() {
1280
+ var _a, _b, _c, _d;
1281
+ if (typeof navigator === "undefined") return "\u2318";
1282
+ const ua = navigator;
1283
+ const platform = (_d = (_c = (_b = (_a = ua.userAgentData) == null ? void 0 : _a.platform) != null ? _b : ua.platform) != null ? _c : ua.userAgent) != null ? _d : "";
1284
+ return /mac|iphone|ipad|ipod/i.test(platform) ? "\u2318" : "Ctrl";
1285
+ }
1286
+ const DEFAULT_DIFF_ACTIONS_MOD_SYMBOL = detectModSymbol();
1287
+ function resolveDiffActionsConfig(options) {
1288
+ var _a, _b, _c, _d, _e, _f, _g;
1289
+ const { config, enterKeyIcon: enterKeyIcon$1 } = options;
1290
+ return {
1291
+ retryLabel: (_a = config == null ? void 0 : config.retryLabel) != null ? _a : DEFAULT_DIFF_ACTIONS_RETRY_LABEL,
1292
+ rejectAllLabel: (_b = config == null ? void 0 : config.rejectAllLabel) != null ? _b : DEFAULT_DIFF_ACTIONS_REJECT_ALL_LABEL,
1293
+ acceptAllLabel: (_c = config == null ? void 0 : config.acceptAllLabel) != null ? _c : DEFAULT_DIFF_ACTIONS_ACCEPT_ALL_LABEL,
1294
+ retryIcon: (_d = config == null ? void 0 : config.retryIcon) != null ? _d : retryIcon,
1295
+ rejectIcon: (_e = config == null ? void 0 : config.rejectIcon) != null ? _e : clearIcon,
1296
+ acceptIcon: (_f = config == null ? void 0 : config.acceptIcon) != null ? _f : confirmIcon,
1297
+ enterKeyIcon: enterKeyIcon$1 != null ? enterKeyIcon$1 : enterKeyIcon,
1298
+ modSymbol: (_g = config == null ? void 0 : config.modSymbol) != null ? _g : DEFAULT_DIFF_ACTIONS_MOD_SYMBOL
1299
+ };
1300
+ }
1301
+ function diffActionsPanelPlugin(options = {}) {
1302
+ const resolved = resolveDiffActionsConfig(options);
1303
+ return utils.$prose((ctx) => {
1304
+ return new state.Plugin({
1305
+ key: diffActionsPanelKey,
1306
+ view(view) {
1307
+ return new DiffActionsPanelView(ctx, view, resolved);
1308
+ },
1309
+ props: {
1310
+ handleKeyDown(view, event) {
1311
+ var _a;
1312
+ if (event.key !== "Enter") return false;
1313
+ if (!(event.metaKey || event.ctrlKey)) return false;
1314
+ if (!((_a = diff.diffPluginKey.getState(view.state)) == null ? void 0 : _a.active)) return false;
1315
+ if (!ctx.get(aiSessionCtx.key).diffOwnedByAI) return false;
1316
+ event.preventDefault();
1317
+ const commands = ctx.get(core.commandsCtx);
1318
+ commands.call(diff.acceptAllDiffsCmd.key);
1319
+ return true;
1320
+ }
1321
+ }
1322
+ });
1323
+ });
1324
+ }
1325
+
1326
+ var __typeError$9 = (msg) => {
1327
+ throw TypeError(msg);
1328
+ };
1329
+ var __accessCheck$9 = (obj, member, msg) => member.has(obj) || __typeError$9("Cannot " + msg);
1330
+ var __privateGet$9 = (obj, member, getter) => (__accessCheck$9(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
1331
+ var __privateAdd$9 = (obj, member, value) => member.has(obj) ? __typeError$9("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1332
+ var __privateSet$9 = (obj, member, value, setter) => (__accessCheck$9(obj, member, "write to private field"), member.set(obj, value), value);
1333
+ var _nodes, _removeById;
1334
+ function createSubmenuBuilder(node) {
1335
+ const builder = {
1336
+ addItem: (id, item) => {
1337
+ node.items.set(id, item);
1338
+ return builder;
1339
+ },
1340
+ removeItem: (id) => {
1341
+ node.items.delete(id);
1342
+ return builder;
1343
+ },
1344
+ getItem: (id) => node.items.get(id),
1345
+ clear: () => {
1346
+ node.items.clear();
1347
+ return builder;
1348
+ }
1349
+ };
1350
+ return builder;
1351
+ }
1352
+ class AISuggestionsBuilder {
1353
+ constructor() {
1354
+ __privateAdd$9(this, _nodes, []);
1355
+ this.addItem = (id, item) => {
1356
+ __privateGet$9(this, _removeById).call(this, id);
1357
+ __privateGet$9(this, _nodes).push({ kind: "item", id, item });
1358
+ return this;
1359
+ };
1360
+ /// Add a submenu. Populate items via the optional `build` callback,
1361
+ /// or call `getSubmenu(id)` afterward. Returns `this` so calls can be
1362
+ /// chained at the parent level alongside `addItem`.
1363
+ this.addSubmenu = (id, def, build) => {
1364
+ __privateGet$9(this, _removeById).call(this, id);
1365
+ const node = { def, items: /* @__PURE__ */ new Map() };
1366
+ if (build) build(createSubmenuBuilder(node));
1367
+ __privateGet$9(this, _nodes).push({ kind: "submenu", id, node });
1368
+ return this;
1369
+ };
1370
+ this.removeItem = (id) => {
1371
+ __privateGet$9(this, _removeById).call(this, id);
1372
+ return this;
1373
+ };
1374
+ this.getItem = (id) => {
1375
+ const node = __privateGet$9(this, _nodes).find((n) => n.kind === "item" && n.id === id);
1376
+ return (node == null ? void 0 : node.kind) === "item" ? node.item : void 0;
1377
+ };
1378
+ /// Return a builder that mutates the submenu's items in place.
1379
+ /// Multiple calls return distinct builder objects backed by the same
1380
+ /// underlying node, so changes are always visible.
1381
+ this.getSubmenu = (id) => {
1382
+ const node = __privateGet$9(this, _nodes).find((n) => n.kind === "submenu" && n.id === id);
1383
+ return (node == null ? void 0 : node.kind) === "submenu" ? createSubmenuBuilder(node.node) : void 0;
1384
+ };
1385
+ this.clear = () => {
1386
+ __privateSet$9(this, _nodes, []);
1387
+ return this;
1388
+ };
1389
+ this.build = () => {
1390
+ const main = [];
1391
+ const submenus = {};
1392
+ for (const node of __privateGet$9(this, _nodes)) {
1393
+ if (node.kind === "item") {
1394
+ main.push({ kind: "item", id: node.id, item: node.item });
1395
+ } else {
1396
+ main.push({ kind: "submenu", id: node.id, def: node.node.def });
1397
+ submenus[node.id] = {
1398
+ def: node.node.def,
1399
+ items: Array.from(node.node.items.entries()).map(([id, item]) => ({
1400
+ id,
1401
+ item
1402
+ }))
1403
+ };
1404
+ }
1405
+ }
1406
+ return { main, submenus };
1407
+ };
1408
+ __privateAdd$9(this, _removeById, (id) => {
1409
+ __privateSet$9(this, _nodes, __privateGet$9(this, _nodes).filter((n) => n.id !== id));
1410
+ });
1411
+ }
1412
+ }
1413
+ _nodes = new WeakMap();
1414
+ _removeById = new WeakMap();
1415
+ function applyDefaultSuggestions(builder) {
1416
+ builder.addItem("improve", {
1417
+ icon: aiIcon,
1418
+ label: "Improve writing",
1419
+ streamingLabel: "Improving writing",
1420
+ prompt: "Improve the writing while preserving the original meaning."
1421
+ }).addItem("grammar", {
1422
+ icon: grammarCheckIcon,
1423
+ label: "Fix grammar & spelling",
1424
+ streamingLabel: "Fixing grammar & spelling",
1425
+ prompt: "Fix any grammar and spelling errors without changing the meaning."
1426
+ }).addItem("shorter", {
1427
+ icon: shorterIcon,
1428
+ label: "Make shorter",
1429
+ streamingLabel: "Making shorter",
1430
+ prompt: "Make this shorter while preserving the key information."
1431
+ }).addItem("longer", {
1432
+ icon: longerIcon,
1433
+ label: "Make longer",
1434
+ streamingLabel: "Expanding",
1435
+ prompt: "Expand this with more detail and examples."
1436
+ });
1437
+ builder.addSubmenu(
1438
+ "tone",
1439
+ {
1440
+ icon: editIcon,
1441
+ label: "Change tone\u2026",
1442
+ title: "Change tone",
1443
+ searchPlaceholder: "Search tones\u2026"
1444
+ },
1445
+ (sub) => {
1446
+ const tones = [
1447
+ ["professional", "Professional"],
1448
+ ["casual", "Casual"],
1449
+ ["confident", "Confident"],
1450
+ ["friendly", "Friendly"],
1451
+ ["direct", "Direct"],
1452
+ ["formal", "Formal"]
1453
+ ];
1454
+ for (const [id, label] of tones) {
1455
+ sub.addItem(id, {
1456
+ icon: editIcon,
1457
+ label,
1458
+ streamingLabel: "Adjusting tone",
1459
+ prompt: `Rewrite this in a ${label.toLowerCase()} tone.`
1460
+ });
1461
+ }
1462
+ }
1463
+ );
1464
+ builder.addSubmenu(
1465
+ "translate",
1466
+ {
1467
+ icon: translateIcon,
1468
+ label: "Translate\u2026",
1469
+ title: "Translate",
1470
+ searchPlaceholder: "Search languages\u2026"
1471
+ },
1472
+ (sub) => {
1473
+ const languages = [
1474
+ ["english", "English", "English"],
1475
+ ["chinese", "Chinese", "Chinese (Simplified)"],
1476
+ ["japanese", "Japanese", "Japanese"],
1477
+ ["korean", "Korean", "Korean"],
1478
+ ["spanish", "Spanish", "Spanish"],
1479
+ ["french", "French", "French"],
1480
+ ["german", "German", "German"]
1481
+ ];
1482
+ for (const [id, label, promptName] of languages) {
1483
+ sub.addItem(id, {
1484
+ icon: translateIcon,
1485
+ label,
1486
+ streamingLabel: `Translating to ${label}`,
1487
+ prompt: `Translate this to ${promptName}.`
1488
+ });
1489
+ }
1490
+ }
1491
+ );
1492
+ }
1493
+
1494
+ function keepAlive(..._args) {
1495
+ }
1496
+
1497
+ keepAlive(vue.h);
1498
+ function renderHighlighted(label, query) {
1499
+ const q = query.trim();
1500
+ if (!q) return [label];
1501
+ const lower = label.toLowerCase();
1502
+ const lq = q.toLowerCase();
1503
+ const idx = lower.indexOf(lq);
1504
+ if (idx === -1) return [label];
1505
+ return [
1506
+ label.slice(0, idx),
1507
+ vue.h("mark", null, label.slice(idx, idx + q.length)),
1508
+ label.slice(idx + q.length)
1509
+ ];
1510
+ }
1511
+ const AIInstructionInput = vue.defineComponent({
1512
+ props: {
1513
+ placeholder: { type: Object, required: true },
1514
+ resetSignal: { type: Object, required: true },
1515
+ suggestions: { type: Object, required: true },
1516
+ chrome: { type: Object, required: true },
1517
+ onConfirm: { type: Function, required: true },
1518
+ onCancel: { type: Function, required: true }
1519
+ },
1520
+ setup({
1521
+ placeholder,
1522
+ resetSignal,
1523
+ suggestions,
1524
+ chrome,
1525
+ onConfirm,
1526
+ onCancel
1527
+ }) {
1528
+ const inputValue = vue.ref("");
1529
+ const view = vue.ref({ kind: "main" });
1530
+ const selectedIndex = vue.ref(0);
1531
+ const inputRef = vue.ref(null);
1532
+ const listRef = vue.ref(null);
1533
+ const listboxId = `ai-instruction-list-${Math.random().toString(36).slice(2, 9)}`;
1534
+ const optionId = (idx) => `${listboxId}-opt-${idx}`;
1535
+ vue.watch(resetSignal, () => {
1536
+ inputValue.value = "";
1537
+ view.value = { kind: "main" };
1538
+ selectedIndex.value = 0;
1539
+ });
1540
+ const allItems = vue.computed(() => {
1541
+ if (view.value.kind === "submenu") {
1542
+ const submenu = suggestions.submenus[view.value.id];
1543
+ if (!submenu) return [];
1544
+ return submenu.items.map(({ id, item }) => ({
1545
+ id,
1546
+ icon: item.icon,
1547
+ label: item.label,
1548
+ hasSubmenu: false,
1549
+ prompt: { text: item.prompt, streamingLabel: item.streamingLabel }
1550
+ }));
1551
+ }
1552
+ return suggestions.main.map((entry) => {
1553
+ if (entry.kind === "item") {
1554
+ return {
1555
+ id: entry.id,
1556
+ icon: entry.item.icon,
1557
+ label: entry.item.label,
1558
+ hasSubmenu: false,
1559
+ prompt: {
1560
+ text: entry.item.prompt,
1561
+ streamingLabel: entry.item.streamingLabel
1562
+ }
1563
+ };
1564
+ }
1565
+ return {
1566
+ id: entry.id,
1567
+ icon: entry.def.icon,
1568
+ label: entry.def.label,
1569
+ hasSubmenu: true
1570
+ };
1571
+ });
1572
+ });
1573
+ const currentSubmenuDef = vue.computed(() => {
1574
+ var _a, _b;
1575
+ if (view.value.kind !== "submenu") return null;
1576
+ return (_b = (_a = suggestions.submenus[view.value.id]) == null ? void 0 : _a.def) != null ? _b : null;
1577
+ });
1578
+ const filteredItems = vue.computed(() => {
1579
+ const q = inputValue.value.trim().toLowerCase();
1580
+ if (!q) return allItems.value;
1581
+ return allItems.value.filter(
1582
+ (item) => item.label.toLowerCase().includes(q)
1583
+ );
1584
+ });
1585
+ const showSendAsPrompt = vue.computed(() => inputValue.value.trim().length > 0);
1586
+ const totalItems = vue.computed(
1587
+ () => filteredItems.value.length + (showSendAsPrompt.value ? 1 : 0)
1588
+ );
1589
+ vue.watch([filteredItems, view, showSendAsPrompt], () => {
1590
+ selectedIndex.value = showSendAsPrompt.value ? filteredItems.value.length : 0;
1591
+ });
1592
+ const focusInput = () => {
1593
+ void vue.nextTick(() => {
1594
+ var _a;
1595
+ return (_a = inputRef.value) == null ? void 0 : _a.focus();
1596
+ });
1597
+ };
1598
+ const enterSubmenu = (id) => {
1599
+ view.value = { kind: "submenu", id };
1600
+ inputValue.value = "";
1601
+ selectedIndex.value = 0;
1602
+ focusInput();
1603
+ };
1604
+ const exitSubmenu = () => {
1605
+ view.value = { kind: "main" };
1606
+ inputValue.value = "";
1607
+ selectedIndex.value = 0;
1608
+ focusInput();
1609
+ };
1610
+ const runItem = (item) => {
1611
+ if (item.hasSubmenu) {
1612
+ enterSubmenu(item.id);
1613
+ } else if (item.prompt) {
1614
+ onConfirm(item.prompt.text, item.prompt.streamingLabel);
1615
+ inputValue.value = "";
1616
+ }
1617
+ };
1618
+ const submitRaw = () => {
1619
+ const v = inputValue.value.trim();
1620
+ if (!v) return;
1621
+ onConfirm(v);
1622
+ inputValue.value = "";
1623
+ };
1624
+ const onSelectCurrent = () => {
1625
+ const idx = selectedIndex.value;
1626
+ const items = filteredItems.value;
1627
+ if (idx < items.length) {
1628
+ runItem(items[idx]);
1629
+ } else if (showSendAsPrompt.value) {
1630
+ submitRaw();
1631
+ }
1632
+ };
1633
+ const scrollToSelected = () => {
1634
+ void vue.nextTick(() => {
1635
+ const list = listRef.value;
1636
+ if (!list) return;
1637
+ const el = list.querySelector(
1638
+ `[data-index="${selectedIndex.value}"]`
1639
+ );
1640
+ el == null ? void 0 : el.scrollIntoView({ block: "nearest" });
1641
+ });
1642
+ };
1643
+ const onKeydown = (e) => {
1644
+ e.stopPropagation();
1645
+ if (e.key === "ArrowDown") {
1646
+ e.preventDefault();
1647
+ if (totalItems.value === 0) return;
1648
+ selectedIndex.value = (selectedIndex.value + 1) % totalItems.value;
1649
+ scrollToSelected();
1650
+ return;
1651
+ }
1652
+ if (e.key === "ArrowUp") {
1653
+ e.preventDefault();
1654
+ if (totalItems.value === 0) return;
1655
+ selectedIndex.value = (selectedIndex.value - 1 + totalItems.value) % totalItems.value;
1656
+ scrollToSelected();
1657
+ return;
1658
+ }
1659
+ if (e.key === "Enter") {
1660
+ e.preventDefault();
1661
+ onSelectCurrent();
1662
+ return;
1663
+ }
1664
+ if (e.key === "Escape") {
1665
+ e.preventDefault();
1666
+ if (view.value.kind === "submenu") exitSubmenu();
1667
+ else onCancel();
1668
+ return;
1669
+ }
1670
+ if (e.key === "Backspace" && inputValue.value === "" && view.value.kind === "submenu") {
1671
+ e.preventDefault();
1672
+ exitSubmenu();
1673
+ }
1674
+ };
1675
+ const onItemPointerDown = (e) => {
1676
+ e.preventDefault();
1677
+ };
1678
+ return () => {
1679
+ const items = filteredItems.value;
1680
+ const showPrompt = showSendAsPrompt.value;
1681
+ const submenuDef = currentSubmenuDef.value;
1682
+ return /* @__PURE__ */ vue.h("div", { class: "ai-instruction" }, /* @__PURE__ */ vue.h("div", { class: "ai-instruction-input" }, /* @__PURE__ */ vue.h("span", { class: "ai-instruction-input-prefix" }, /* @__PURE__ */ vue.h(component.Icon, { icon: chrome.aiIcon })), /* @__PURE__ */ vue.h(
1683
+ "input",
1684
+ {
1685
+ ref: inputRef,
1686
+ class: "ai-instruction-input-field",
1687
+ role: "combobox",
1688
+ "aria-expanded": "true",
1689
+ "aria-autocomplete": "list",
1690
+ "aria-controls": listboxId,
1691
+ "aria-activedescendant": totalItems.value > 0 ? optionId(selectedIndex.value) : void 0,
1692
+ placeholder: submenuDef ? submenuDef.searchPlaceholder : placeholder.value,
1693
+ value: inputValue.value,
1694
+ onInput: (e) => {
1695
+ inputValue.value = e.target.value;
1696
+ },
1697
+ onKeydown
1698
+ }
1699
+ ), /* @__PURE__ */ vue.h(
1700
+ "button",
1701
+ {
1702
+ type: "button",
1703
+ class: "ai-instruction-submit",
1704
+ "aria-label": chrome.submitButtonLabel,
1705
+ disabled: !showPrompt,
1706
+ onMousedown: onItemPointerDown,
1707
+ onClick: submitRaw
1708
+ },
1709
+ /* @__PURE__ */ vue.h(component.Icon, { icon: chrome.sendIcon })
1710
+ )), /* @__PURE__ */ vue.h(
1711
+ "div",
1712
+ {
1713
+ class: "ai-instruction-list",
1714
+ ref: listRef,
1715
+ id: listboxId,
1716
+ role: "listbox",
1717
+ "aria-label": chrome.listboxLabel
1718
+ },
1719
+ submenuDef && /* @__PURE__ */ vue.h(
1720
+ "button",
1721
+ {
1722
+ type: "button",
1723
+ class: "ai-instruction-back",
1724
+ onMousedown: onItemPointerDown,
1725
+ onClick: exitSubmenu
1726
+ },
1727
+ /* @__PURE__ */ vue.h("span", { class: "ai-instruction-back-icon", "aria-hidden": "true" }, /* @__PURE__ */ vue.h(component.Icon, { icon: chrome.chevronLeftIcon })),
1728
+ /* @__PURE__ */ vue.h("span", null, submenuDef.title)
1729
+ ),
1730
+ items.length > 0 && /* @__PURE__ */ vue.h("div", { class: "ai-instruction-section" }, /* @__PURE__ */ vue.h("div", { class: "ai-instruction-section-header" }, chrome.suggestionsHeaderLabel), items.map((item, idx) => /* @__PURE__ */ vue.h(
1731
+ "div",
1732
+ {
1733
+ key: item.id,
1734
+ id: optionId(idx),
1735
+ "data-index": idx,
1736
+ role: "option",
1737
+ "aria-selected": idx === selectedIndex.value,
1738
+ class: [
1739
+ "ai-instruction-item",
1740
+ idx === selectedIndex.value ? "active" : ""
1741
+ ],
1742
+ onMousedown: onItemPointerDown,
1743
+ onClick: () => runItem(item),
1744
+ onPointerenter: () => {
1745
+ selectedIndex.value = idx;
1746
+ }
1747
+ },
1748
+ /* @__PURE__ */ vue.h("span", { class: "ai-instruction-item-icon" }, /* @__PURE__ */ vue.h(component.Icon, { icon: item.icon })),
1749
+ /* @__PURE__ */ vue.h("span", { class: "ai-instruction-item-label" }, renderHighlighted(item.label, inputValue.value)),
1750
+ item.hasSubmenu && /* @__PURE__ */ vue.h("span", { class: "ai-instruction-item-arrow" }, /* @__PURE__ */ vue.h(component.Icon, { icon: chrome.chevronRightIcon }))
1751
+ ))),
1752
+ showPrompt && /* @__PURE__ */ vue.h("div", { class: "ai-instruction-section" }, /* @__PURE__ */ vue.h("div", { class: "ai-instruction-section-header" }, chrome.sendAsPromptHeaderLabel), /* @__PURE__ */ vue.h(
1753
+ "div",
1754
+ {
1755
+ id: optionId(items.length),
1756
+ "data-index": items.length,
1757
+ role: "option",
1758
+ "aria-selected": selectedIndex.value === items.length,
1759
+ class: [
1760
+ "ai-instruction-item",
1761
+ "ai-instruction-item-prompt",
1762
+ selectedIndex.value === items.length ? "active" : ""
1763
+ ],
1764
+ onMousedown: onItemPointerDown,
1765
+ onClick: submitRaw,
1766
+ onPointerenter: () => {
1767
+ selectedIndex.value = items.length;
1768
+ }
1769
+ },
1770
+ /* @__PURE__ */ vue.h("span", { class: "ai-instruction-item-icon" }, /* @__PURE__ */ vue.h(component.Icon, { icon: chrome.sendPromptIcon })),
1771
+ /* @__PURE__ */ vue.h("span", { class: "ai-instruction-item-label" }, chrome.sendAsPromptLabel, " ", /* @__PURE__ */ vue.h("span", { class: "ai-instruction-item-quote" }, '"', inputValue.value, '"')),
1772
+ /* @__PURE__ */ vue.h("span", { class: "ai-instruction-item-shortcut" }, /* @__PURE__ */ vue.h(component.Icon, { icon: chrome.enterKeyIcon }))
1773
+ ))
1774
+ ));
1775
+ };
1776
+ }
1777
+ });
1778
+
1779
+ var __typeError$8 = (msg) => {
1780
+ throw TypeError(msg);
1781
+ };
1782
+ var __accessCheck$8 = (obj, member, msg) => member.has(obj) || __typeError$8("Cannot " + msg);
1783
+ var __privateGet$8 = (obj, member, getter) => (__accessCheck$8(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
1784
+ var __privateAdd$8 = (obj, member, value) => member.has(obj) ? __typeError$8("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1785
+ var __privateSet$8 = (obj, member, value, setter) => (__accessCheck$8(obj, member, "write to private field"), member.set(obj, value), value);
1786
+ var _content$4, _provider$2, _app$5, _placeholder, _resetSignal, _from, _to, _wantsShow, _onConfirm, _onCancel;
1787
+ class AIInstructionTooltipView {
1788
+ constructor(ctx, view, config) {
1789
+ this.ctx = ctx;
1790
+ __privateAdd$8(this, _content$4);
1791
+ __privateAdd$8(this, _provider$2);
1792
+ __privateAdd$8(this, _app$5);
1793
+ __privateAdd$8(this, _placeholder);
1794
+ __privateAdd$8(this, _resetSignal);
1795
+ __privateAdd$8(this, _from, -1);
1796
+ __privateAdd$8(this, _to, -1);
1797
+ /// Source of truth for "should the palette currently be showing".
1798
+ /// `TooltipProvider.shouldShow` reads this so that forwarding `update()`
1799
+ /// to the provider on every editor transition (needed to keep the
1800
+ /// floating position in sync with layout changes) doesn't dismiss the
1801
+ /// palette behind our back.
1802
+ __privateAdd$8(this, _wantsShow, false);
1803
+ __privateAdd$8(this, _onConfirm, (instruction, label) => {
1804
+ if (!instruction.trim()) return;
1805
+ const commands = this.ctx.get(core.commandsCtx);
1806
+ const accepted = commands.call(runAICmd.key, { instruction, label });
1807
+ if (!accepted) return;
1808
+ __privateSet$8(this, _wantsShow, false);
1809
+ __privateGet$8(this, _provider$2).hide();
1810
+ });
1811
+ __privateAdd$8(this, _onCancel, () => {
1812
+ __privateSet$8(this, _wantsShow, false);
1813
+ __privateGet$8(this, _provider$2).hide();
1814
+ });
1815
+ this.show = (from, to) => {
1816
+ __privateSet$8(this, _from, from);
1817
+ __privateSet$8(this, _to, to);
1818
+ __privateGet$8(this, _resetSignal).value++;
1819
+ __privateSet$8(this, _wantsShow, true);
1820
+ const view = this.ctx.get(core.editorViewCtx);
1821
+ __privateGet$8(this, _provider$2).show(
1822
+ { getBoundingClientRect: () => prose.posToDOMRect(view, from, to) },
1823
+ view
1824
+ );
1825
+ requestAnimationFrame(() => {
1826
+ var _a;
1827
+ (_a = __privateGet$8(this, _content$4).querySelector("input")) == null ? void 0 : _a.focus();
1828
+ });
1829
+ };
1830
+ this.update = (view, prevState) => {
1831
+ const { selection } = view.state;
1832
+ const isTextSelection = selection instanceof state.TextSelection;
1833
+ const movedRange = selection.from !== __privateGet$8(this, _from) || selection.to !== __privateGet$8(this, _to);
1834
+ if (!isTextSelection || movedRange) {
1835
+ __privateSet$8(this, _wantsShow, false);
1836
+ __privateGet$8(this, _provider$2).hide();
1837
+ return;
1838
+ }
1839
+ __privateGet$8(this, _provider$2).update(view, prevState);
1840
+ };
1841
+ this.destroy = () => {
1842
+ __privateGet$8(this, _app$5).unmount();
1843
+ __privateGet$8(this, _provider$2).destroy();
1844
+ __privateGet$8(this, _content$4).remove();
1845
+ };
1846
+ __privateSet$8(this, _placeholder, vue.ref(config.placeholder));
1847
+ __privateSet$8(this, _resetSignal, vue.ref(0));
1848
+ const content = document.createElement("div");
1849
+ content.className = "milkdown-ai-instruction";
1850
+ const app = vue.createApp(AIInstructionInput, {
1851
+ placeholder: __privateGet$8(this, _placeholder),
1852
+ resetSignal: __privateGet$8(this, _resetSignal),
1853
+ suggestions: config.suggestions,
1854
+ chrome: config.chrome,
1855
+ onConfirm: __privateGet$8(this, _onConfirm),
1856
+ onCancel: __privateGet$8(this, _onCancel)
1857
+ });
1858
+ app.mount(content);
1859
+ __privateSet$8(this, _app$5, app);
1860
+ __privateSet$8(this, _content$4, content);
1861
+ __privateSet$8(this, _provider$2, new tooltip.TooltipProvider({
1862
+ content,
1863
+ debounce: 0,
1864
+ offset: 10,
1865
+ shouldShow: () => __privateGet$8(this, _wantsShow),
1866
+ floatingUIOptions: {
1867
+ placement: "bottom"
1868
+ }
1869
+ }));
1870
+ __privateGet$8(this, _provider$2).onHide = () => {
1871
+ __privateSet$8(this, _wantsShow, false);
1872
+ requestAnimationFrame(() => {
1873
+ try {
1874
+ const root = __privateGet$8(this, _content$4).getRootNode();
1875
+ const active = root.activeElement;
1876
+ if (!active || !__privateGet$8(this, _content$4).contains(active)) return;
1877
+ const v = this.ctx.get(core.editorViewCtx);
1878
+ v.dom.focus({ preventScroll: true });
1879
+ } catch (e) {
1880
+ }
1881
+ });
1882
+ };
1883
+ __privateGet$8(this, _provider$2).update(view);
1884
+ }
1885
+ }
1886
+ _content$4 = new WeakMap();
1887
+ _provider$2 = new WeakMap();
1888
+ _app$5 = new WeakMap();
1889
+ _placeholder = new WeakMap();
1890
+ _resetSignal = new WeakMap();
1891
+ _from = new WeakMap();
1892
+ _to = new WeakMap();
1893
+ _wantsShow = new WeakMap();
1894
+ _onConfirm = new WeakMap();
1895
+ _onCancel = new WeakMap();
1896
+
1897
+ const defaultAPI = {
1898
+ show: () => {
1899
+ }
1900
+ };
1901
+ const aiInstructionTooltipAPI = utils.$ctx(
1902
+ { ...defaultAPI },
1903
+ "aiInstructionTooltipAPI"
1904
+ );
1905
+ const aiInstructionTooltip = tooltip.tooltipFactory("CREPE_AI_INSTRUCTION");
1906
+ const DEFAULT_SUGGESTIONS_HEADER_LABEL = "SUGGESTIONS";
1907
+ const DEFAULT_SEND_AS_PROMPT_HEADER_LABEL = "SEND AS PROMPT";
1908
+ const DEFAULT_SEND_AS_PROMPT_LABEL = "Ask AI:";
1909
+ const DEFAULT_SUBMIT_BUTTON_LABEL = "Send prompt";
1910
+ const DEFAULT_LISTBOX_LABEL = "AI suggestions";
1911
+ const DEFAULT_INSTRUCTION_PLACEHOLDER = "Tell AI what to do with the selection\u2026";
1912
+ function resolveChrome(config) {
1913
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1914
+ return {
1915
+ aiIcon: (_a = config == null ? void 0 : config.aiIcon) != null ? _a : aiIcon,
1916
+ sendIcon: (_b = config == null ? void 0 : config.sendIcon) != null ? _b : sendIcon,
1917
+ sendPromptIcon: (_c = config == null ? void 0 : config.sendPromptIcon) != null ? _c : sendPromptIcon,
1918
+ enterKeyIcon: (_d = config == null ? void 0 : config.enterKeyIcon) != null ? _d : enterKeyIcon,
1919
+ chevronLeftIcon: (_e = config == null ? void 0 : config.chevronLeftIcon) != null ? _e : chevronLeftIcon,
1920
+ chevronRightIcon: (_f = config == null ? void 0 : config.chevronRightIcon) != null ? _f : chevronRightIcon,
1921
+ suggestionsHeaderLabel: (_g = config == null ? void 0 : config.suggestionsHeaderLabel) != null ? _g : DEFAULT_SUGGESTIONS_HEADER_LABEL,
1922
+ sendAsPromptHeaderLabel: (_h = config == null ? void 0 : config.sendAsPromptHeaderLabel) != null ? _h : DEFAULT_SEND_AS_PROMPT_HEADER_LABEL,
1923
+ sendAsPromptLabel: (_i = config == null ? void 0 : config.sendAsPromptLabel) != null ? _i : DEFAULT_SEND_AS_PROMPT_LABEL,
1924
+ submitButtonLabel: (_j = config == null ? void 0 : config.submitButtonLabel) != null ? _j : DEFAULT_SUBMIT_BUTTON_LABEL,
1925
+ listboxLabel: (_k = config == null ? void 0 : config.listboxLabel) != null ? _k : DEFAULT_LISTBOX_LABEL
1926
+ };
1927
+ }
1928
+ function resolveViewConfig(config) {
1929
+ var _a, _b;
1930
+ const builder = new AISuggestionsBuilder();
1931
+ applyDefaultSuggestions(builder);
1932
+ (_a = config == null ? void 0 : config.buildAISuggestions) == null ? void 0 : _a.call(config, builder);
1933
+ return {
1934
+ placeholder: (_b = config == null ? void 0 : config.instructionPlaceholder) != null ? _b : DEFAULT_INSTRUCTION_PLACEHOLDER,
1935
+ chrome: resolveChrome(config),
1936
+ suggestions: builder.build()
1937
+ };
1938
+ }
1939
+ function configureAIInstructionTooltip(config) {
1940
+ return (ctx) => {
1941
+ const viewConfig = resolveViewConfig(config);
1942
+ let tooltipView = null;
1943
+ ctx.update(aiInstructionTooltipAPI.key, (api) => ({
1944
+ ...api,
1945
+ show: (from, to) => {
1946
+ tooltipView == null ? void 0 : tooltipView.show(from, to);
1947
+ }
1948
+ }));
1949
+ ctx.set(aiInstructionTooltip.key, {
1950
+ view: (view) => {
1951
+ tooltipView = new AIInstructionTooltipView(ctx, view, viewConfig);
1952
+ return tooltipView;
1953
+ }
1954
+ });
1955
+ };
1956
+ }
1957
+
1958
+ var __typeError$7 = (msg) => {
1959
+ throw TypeError(msg);
1960
+ };
1961
+ var __accessCheck$7 = (obj, member, msg) => member.has(obj) || __typeError$7("Cannot " + msg);
1962
+ var __privateGet$7 = (obj, member, getter) => (__accessCheck$7(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
1963
+ var __privateAdd$7 = (obj, member, value) => member.has(obj) ? __typeError$7("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1964
+ var __privateSet$7 = (obj, member, value, setter) => (__accessCheck$7(obj, member, "write to private field"), member.set(obj, value), value);
1965
+ var _spinner, _label, _fallbackLabel, _start, _lastLabelText, _rafId, _tick;
1966
+ const CLASS_PREFIX = "milkdown-ai-streaming";
1967
+ const SPINNER_PERIOD_MS = 800;
1968
+ const DEFAULT_STREAMING_FALLBACK_LABEL = "Generating";
1969
+ const DEFAULT_STREAMING_CANCEL_HINT = "Esc to cancel";
1970
+ const indicatorKey = new state.PluginKey(
1971
+ "CREPE_AI_STREAMING_INDICATOR"
1972
+ );
1973
+ class IndicatorWidget {
1974
+ constructor(ctx, fallbackLabel, cancelHint) {
1975
+ __privateAdd$7(this, _spinner);
1976
+ __privateAdd$7(this, _label);
1977
+ __privateAdd$7(this, _fallbackLabel);
1978
+ __privateAdd$7(this, _start, performance.now());
1979
+ __privateAdd$7(this, _lastLabelText, "");
1980
+ __privateAdd$7(this, _rafId, 0);
1981
+ __privateAdd$7(this, _tick, () => {
1982
+ const elapsed = performance.now() - __privateGet$7(this, _start);
1983
+ const angle = elapsed / SPINNER_PERIOD_MS * 360;
1984
+ __privateGet$7(this, _spinner).style.transform = `rotate(${angle}deg)`;
1985
+ __privateSet$7(this, _rafId, requestAnimationFrame(__privateGet$7(this, _tick)));
1986
+ });
1987
+ __privateSet$7(this, _fallbackLabel, fallbackLabel);
1988
+ const dom = document.createElement("span");
1989
+ dom.className = `${CLASS_PREFIX}-indicator`;
1990
+ dom.contentEditable = "false";
1991
+ dom.setAttribute("role", "status");
1992
+ dom.setAttribute("aria-live", "polite");
1993
+ const spinner = document.createElement("span");
1994
+ spinner.className = `${CLASS_PREFIX}-spinner`;
1995
+ spinner.setAttribute("aria-hidden", "true");
1996
+ dom.appendChild(spinner);
1997
+ const label = document.createElement("span");
1998
+ label.className = `${CLASS_PREFIX}-label`;
1999
+ dom.appendChild(label);
2000
+ const escHint = document.createElement("span");
2001
+ escHint.className = `${CLASS_PREFIX}-esc`;
2002
+ escHint.textContent = cancelHint;
2003
+ dom.appendChild(escHint);
2004
+ this.dom = dom;
2005
+ __privateSet$7(this, _spinner, spinner);
2006
+ __privateSet$7(this, _label, label);
2007
+ this.setLabel(ctx);
2008
+ __privateGet$7(this, _tick).call(this);
2009
+ }
2010
+ setLabel(ctx) {
2011
+ const session = ctx.get(aiSessionCtx.key);
2012
+ const text = `${session.label || __privateGet$7(this, _fallbackLabel)}\u2026`;
2013
+ if (text === __privateGet$7(this, _lastLabelText)) return;
2014
+ __privateSet$7(this, _lastLabelText, text);
2015
+ __privateGet$7(this, _label).textContent = text;
2016
+ }
2017
+ destroy() {
2018
+ if (__privateGet$7(this, _rafId)) cancelAnimationFrame(__privateGet$7(this, _rafId));
2019
+ __privateSet$7(this, _rafId, 0);
2020
+ }
2021
+ }
2022
+ _spinner = new WeakMap();
2023
+ _label = new WeakMap();
2024
+ _fallbackLabel = new WeakMap();
2025
+ _start = new WeakMap();
2026
+ _lastLabelText = new WeakMap();
2027
+ _rafId = new WeakMap();
2028
+ _tick = new WeakMap();
2029
+ function streamingIndicatorPlugin(options = {}) {
2030
+ var _a, _b;
2031
+ const { config } = options;
2032
+ const fallbackLabel = (_a = config == null ? void 0 : config.fallbackLabel) != null ? _a : DEFAULT_STREAMING_FALLBACK_LABEL;
2033
+ const cancelHint = (_b = config == null ? void 0 : config.cancelHint) != null ? _b : DEFAULT_STREAMING_CANCEL_HINT;
2034
+ return utils.$prose((ctx) => {
2035
+ let widget = null;
2036
+ function ensureWidget() {
2037
+ if (!widget) widget = new IndicatorWidget(ctx, fallbackLabel, cancelHint);
2038
+ else widget.setLabel(ctx);
2039
+ return widget;
2040
+ }
2041
+ function dropWidget() {
2042
+ if (widget) {
2043
+ widget.destroy();
2044
+ widget = null;
2045
+ }
2046
+ }
2047
+ function buildSet(doc, insertEndPos) {
2048
+ const pos = Math.min(insertEndPos, doc.content.size);
2049
+ const decoration = view.Decoration.widget(pos, ensureWidget().dom, {
2050
+ side: 1,
2051
+ key: "ai-streaming-indicator"
2052
+ });
2053
+ return view.DecorationSet.create(doc, [decoration]);
2054
+ }
2055
+ return new state.Plugin({
2056
+ key: indicatorKey,
2057
+ state: {
2058
+ init: () => view.DecorationSet.empty,
2059
+ apply(tr, decorations, _oldState, newState) {
2060
+ const streaming$1 = streaming.streamingPluginKey.getState(newState);
2061
+ if (!(streaming$1 == null ? void 0 : streaming$1.active) || streaming$1.insertEndPos == null) {
2062
+ dropWidget();
2063
+ return view.DecorationSet.empty;
2064
+ }
2065
+ if (tr.getMeta(streaming.streamingPluginKey) || tr.docChanged) {
2066
+ return buildSet(newState.doc, streaming$1.insertEndPos);
2067
+ }
2068
+ return decorations.map(tr.mapping, tr.doc);
2069
+ }
2070
+ },
2071
+ view() {
2072
+ return {
2073
+ destroy() {
2074
+ dropWidget();
2075
+ }
2076
+ };
2077
+ },
2078
+ props: {
2079
+ decorations(state) {
2080
+ var _a2;
2081
+ return (_a2 = indicatorKey.getState(state)) != null ? _a2 : view.DecorationSet.empty;
2082
+ },
2083
+ handleKeyDown(view, event) {
2084
+ var _a2;
2085
+ if (event.key !== "Escape") return false;
2086
+ const commands = ctx.get(core.commandsCtx);
2087
+ if (ctx.get(aiSessionCtx.key).abortController) {
2088
+ event.preventDefault();
2089
+ commands.call(abortAICmd.key, { keep: true });
2090
+ return true;
2091
+ }
2092
+ if ((_a2 = streaming.streamingPluginKey.getState(view.state)) == null ? void 0 : _a2.active) {
2093
+ event.preventDefault();
2094
+ commands.call(streaming.abortStreamingCmd.key, { keep: true });
2095
+ return true;
2096
+ }
2097
+ return false;
2098
+ }
2099
+ }
2100
+ });
2101
+ });
2102
+ }
2103
+
2104
+ const CREPE_CUSTOM_BLOCK_TYPES = ["table", "image-block", "code_block"];
2105
+ const CREPE_IGNORE_ATTRS = { heading: ["id"] };
2106
+ const ai = (editor, config) => {
2107
+ var _a, _b;
2108
+ const diffCfg = (_a = config == null ? void 0 : config.diff) != null ? _a : {};
2109
+ const streamingCfg = (_b = config == null ? void 0 : config.streaming) != null ? _b : {};
2110
+ editor.config(crepeFeatureConfig(CrepeFeature.AI)).config((ctx) => {
2111
+ ctx.update(diff.diffConfig.key, (prev) => {
2112
+ var _a2;
2113
+ return {
2114
+ ...prev,
2115
+ ignoreAttrs: (_a2 = diffCfg.ignoreAttrs) != null ? _a2 : CREPE_IGNORE_ATTRS
2116
+ };
2117
+ });
2118
+ const { ignoreAttrs: _, ...componentConfig } = diffCfg;
2119
+ ctx.update(diff$1.diffComponentConfig.key, (prev) => {
2120
+ var _a2;
2121
+ return {
2122
+ ...prev,
2123
+ customBlockTypes: (_a2 = componentConfig.customBlockTypes) != null ? _a2 : CREPE_CUSTOM_BLOCK_TYPES,
2124
+ ...componentConfig
2125
+ };
2126
+ });
2127
+ }).use(diff.diff).use(diff$1.diffComponent).config((ctx) => {
2128
+ ctx.update(streaming.streamingConfig.key, (prev) => {
2129
+ var _a2;
2130
+ return {
2131
+ ...prev,
2132
+ ...streamingCfg,
2133
+ ignoreAttrs: (_a2 = streamingCfg.ignoreAttrs) != null ? _a2 : CREPE_IGNORE_ATTRS,
2134
+ // Wire diffReviewOnEnd into the streaming plugin so manual
2135
+ // endStreamingCmd calls (outside runAICmd) also respect it.
2136
+ // Only override if the user explicitly set it — otherwise
2137
+ // keep the streaming plugin's own default so tests and
2138
+ // manual-streaming use cases aren't surprised.
2139
+ ...(config == null ? void 0 : config.diffReviewOnEnd) !== void 0 ? { diffReviewOnEnd: config.diffReviewOnEnd } : {}
2140
+ };
2141
+ });
2142
+ }).use(streaming.streaming).config((ctx) => {
2143
+ ctx.update(aiProviderConfig.key, (prev) => {
2144
+ var _a2;
2145
+ return {
2146
+ ...prev,
2147
+ ...(config == null ? void 0 : config.provider) !== void 0 ? { provider: config.provider } : {},
2148
+ ...(config == null ? void 0 : config.buildContext) !== void 0 ? { buildContext: config.buildContext } : {},
2149
+ diffReviewOnEnd: (_a2 = config == null ? void 0 : config.diffReviewOnEnd) != null ? _a2 : prev.diffReviewOnEnd,
2150
+ ...(config == null ? void 0 : config.onError) !== void 0 ? { onError: config.onError } : {},
2151
+ ...(config == null ? void 0 : config.aiIcon) !== void 0 ? { aiIcon: config.aiIcon } : {}
2152
+ };
2153
+ });
2154
+ }).use(aiProviderConfig).use(aiSessionCtx).use(runAICmd).use(abortAICmd).config(configureAIInstructionTooltip(config)).use(aiInstructionTooltipAPI).use(aiInstructionTooltip).use(streamingIndicatorPlugin({ config: config == null ? void 0 : config.streamingIndicator })).use(
2155
+ diffActionsPanelPlugin({
2156
+ config: config == null ? void 0 : config.diffActions,
2157
+ enterKeyIcon: config == null ? void 0 : config.enterKeyIcon
2158
+ })
2159
+ );
2160
+ };
2161
+
763
2162
  function isInCodeBlock(selection) {
764
2163
  const type = selection.$from.parent.type;
765
2164
  return type.name === "code_block";
@@ -770,22 +2169,22 @@ function isInList(selection) {
770
2169
  return (type == null ? void 0 : type.name) === "list_item";
771
2170
  }
772
2171
 
773
- var __typeError$5 = (msg) => {
2172
+ var __typeError$6 = (msg) => {
774
2173
  throw TypeError(msg);
775
2174
  };
776
- var __accessCheck$5 = (obj, member, msg) => member.has(obj) || __typeError$5("Cannot " + msg);
777
- var __privateGet$5 = (obj, member, getter) => (__accessCheck$5(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
778
- var __privateAdd$5 = (obj, member, value) => member.has(obj) ? __typeError$5("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
779
- var __privateSet$5 = (obj, member, value, setter) => (__accessCheck$5(obj, member, "write to private field"), member.set(obj, value), value);
2175
+ var __accessCheck$6 = (obj, member, msg) => member.has(obj) || __typeError$6("Cannot " + msg);
2176
+ var __privateGet$6 = (obj, member, getter) => (__accessCheck$6(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
2177
+ var __privateAdd$6 = (obj, member, value) => member.has(obj) ? __typeError$6("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
2178
+ var __privateSet$6 = (obj, member, value, setter) => (__accessCheck$6(obj, member, "write to private field"), member.set(obj, value), value);
780
2179
  var _groups, _getGroupInstance;
781
2180
  class GroupBuilder {
782
2181
  constructor() {
783
- __privateAdd$5(this, _groups, []);
2182
+ __privateAdd$6(this, _groups, []);
784
2183
  this.clear = () => {
785
- __privateSet$5(this, _groups, []);
2184
+ __privateSet$6(this, _groups, []);
786
2185
  return this;
787
2186
  };
788
- __privateAdd$5(this, _getGroupInstance, (group) => {
2187
+ __privateAdd$6(this, _getGroupInstance, (group) => {
789
2188
  const groupInstance = {
790
2189
  group,
791
2190
  addItem: (key, item) => {
@@ -807,23 +2206,23 @@ class GroupBuilder {
807
2206
  label,
808
2207
  items
809
2208
  };
810
- __privateGet$5(this, _groups).push(group);
811
- return __privateGet$5(this, _getGroupInstance).call(this, group);
2209
+ __privateGet$6(this, _groups).push(group);
2210
+ return __privateGet$6(this, _getGroupInstance).call(this, group);
812
2211
  };
813
2212
  this.getGroup = (key) => {
814
- const group = __privateGet$5(this, _groups).find((group2) => group2.key === key);
2213
+ const group = __privateGet$6(this, _groups).find((group2) => group2.key === key);
815
2214
  if (!group) throw new Error(`Group with key ${key} not found`);
816
- return __privateGet$5(this, _getGroupInstance).call(this, group);
2215
+ return __privateGet$6(this, _getGroupInstance).call(this, group);
817
2216
  };
818
2217
  this.build = () => {
819
- return __privateGet$5(this, _groups);
2218
+ return __privateGet$6(this, _groups);
820
2219
  };
821
2220
  }
822
2221
  }
823
2222
  _groups = new WeakMap();
824
2223
  _getGroupInstance = new WeakMap();
825
2224
 
826
- function getGroups$1(filter, config, ctx) {
2225
+ function getGroups$2(filter, config, ctx) {
827
2226
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa, _pa, _qa, _ra, _sa, _ta, _ua, _va, _wa, _xa, _ya, _za, _Aa, _Ba, _Ca, _Da, _Ea, _Fa, _Ga, _Ha, _Ia, _Ja, _Ka, _La, _Ma, _Na, _Oa, _Pa, _Qa, _Ra, _Sa, _Ta, _Ua, _Va, _Wa, _Xa, _Ya, _Za, __a, _$a, _ab, _bb, _cb, _db, _eb, _fb, _gb, _hb, _ib, _jb, _kb;
828
2227
  const flags = ctx && useCrepeFeatures(ctx).get();
829
2228
  const isLatexEnabled = flags == null ? void 0 : flags.includes(CrepeFeature.Latex);
@@ -1090,7 +2489,7 @@ function getGroups$1(filter, config, ctx) {
1090
2489
  commands.call(commonmark.clearTextInCurrentBlockCommand.key);
1091
2490
  commands.call(commonmark.addBlockTypeCommand.key, {
1092
2491
  nodeType: codeBlock,
1093
- attrs: { language: "LaTex" }
2492
+ attrs: { language: "LaTeX" }
1094
2493
  });
1095
2494
  }
1096
2495
  });
@@ -1126,6 +2525,7 @@ function getGroups$1(filter, config, ctx) {
1126
2525
  };
1127
2526
  }
1128
2527
 
2528
+ keepAlive(vue.h);
1129
2529
  const Menu = vue.defineComponent({
1130
2530
  props: {
1131
2531
  ctx: {
@@ -1151,7 +2551,7 @@ const Menu = vue.defineComponent({
1151
2551
  },
1152
2552
  setup({ ctx, show, filter, hide, config }) {
1153
2553
  const host = vue.ref();
1154
- const groupInfo = vue.computed(() => getGroups$1(filter.value, config, ctx));
2554
+ const groupInfo = vue.computed(() => getGroups$2(filter.value, config, ctx));
1155
2555
  const hoverIndex = vue.ref(0);
1156
2556
  const prevMousePosition = vue.ref({ x: -999, y: -999 });
1157
2557
  const onPointerMove = (e) => {
@@ -1180,7 +2580,7 @@ const Menu = vue.defineComponent({
1180
2580
  };
1181
2581
  const runByIndex = (index) => {
1182
2582
  const item = groupInfo.value.groups.flatMap((group) => group.items).at(index);
1183
- if (item && ctx) item.onRun(ctx);
2583
+ if ((item == null ? void 0 : item.onRun) && ctx) item.onRun(ctx);
1184
2584
  hide();
1185
2585
  };
1186
2586
  const onKeydown = (e) => {
@@ -1284,14 +2684,14 @@ const Menu = vue.defineComponent({
1284
2684
  }
1285
2685
  });
1286
2686
 
1287
- var __typeError$4 = (msg) => {
2687
+ var __typeError$5 = (msg) => {
1288
2688
  throw TypeError(msg);
1289
2689
  };
1290
- var __accessCheck$4 = (obj, member, msg) => member.has(obj) || __typeError$4("Cannot " + msg);
1291
- var __privateGet$4 = (obj, member, getter) => (__accessCheck$4(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
1292
- 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);
1293
- var __privateSet$4 = (obj, member, value, setter) => (__accessCheck$4(obj, member, "write to private field"), member.set(obj, value), value);
1294
- var _content$3, _app$3, _filter, _slashProvider, _programmaticallyPos;
2690
+ var __accessCheck$5 = (obj, member, msg) => member.has(obj) || __typeError$5("Cannot " + msg);
2691
+ var __privateGet$5 = (obj, member, getter) => (__accessCheck$5(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
2692
+ var __privateAdd$5 = (obj, member, value) => member.has(obj) ? __typeError$5("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
2693
+ var __privateSet$5 = (obj, member, value, setter) => (__accessCheck$5(obj, member, "write to private field"), member.set(obj, value), value);
2694
+ var _content$3, _app$4, _filter, _slashProvider, _programmaticallyPos;
1295
2695
  const menu = slash.slashFactory("CREPE_MENU");
1296
2696
  const menuAPI = utils.$ctx(
1297
2697
  {
@@ -1309,33 +2709,33 @@ function configureMenu(ctx, config) {
1309
2709
  }
1310
2710
  class MenuView {
1311
2711
  constructor(ctx, view, config) {
1312
- __privateAdd$4(this, _content$3);
1313
- __privateAdd$4(this, _app$3);
1314
- __privateAdd$4(this, _filter);
1315
- __privateAdd$4(this, _slashProvider);
1316
- __privateAdd$4(this, _programmaticallyPos, null);
2712
+ __privateAdd$5(this, _content$3);
2713
+ __privateAdd$5(this, _app$4);
2714
+ __privateAdd$5(this, _filter);
2715
+ __privateAdd$5(this, _slashProvider);
2716
+ __privateAdd$5(this, _programmaticallyPos, null);
1317
2717
  this.update = (view) => {
1318
- __privateGet$4(this, _slashProvider).update(view);
2718
+ __privateGet$5(this, _slashProvider).update(view);
1319
2719
  };
1320
2720
  this.show = (pos) => {
1321
- __privateSet$4(this, _programmaticallyPos, pos);
1322
- __privateGet$4(this, _filter).value = "";
1323
- __privateGet$4(this, _slashProvider).show();
2721
+ __privateSet$5(this, _programmaticallyPos, pos);
2722
+ __privateGet$5(this, _filter).value = "";
2723
+ __privateGet$5(this, _slashProvider).show();
1324
2724
  };
1325
2725
  this.hide = () => {
1326
- __privateSet$4(this, _programmaticallyPos, null);
1327
- __privateGet$4(this, _slashProvider).hide();
2726
+ __privateSet$5(this, _programmaticallyPos, null);
2727
+ __privateGet$5(this, _slashProvider).hide();
1328
2728
  };
1329
2729
  this.destroy = () => {
1330
- __privateGet$4(this, _slashProvider).destroy();
1331
- __privateGet$4(this, _app$3).unmount();
1332
- __privateGet$4(this, _content$3).remove();
2730
+ __privateGet$5(this, _slashProvider).destroy();
2731
+ __privateGet$5(this, _app$4).unmount();
2732
+ __privateGet$5(this, _content$3).remove();
1333
2733
  };
1334
2734
  const content = document.createElement("div");
1335
2735
  content.classList.add("milkdown-slash-menu");
1336
2736
  const show = vue.ref(false);
1337
2737
  const filter = vue.ref("");
1338
- __privateSet$4(this, _filter, filter);
2738
+ __privateSet$5(this, _filter, filter);
1339
2739
  const hide = this.hide;
1340
2740
  const app = vue.createApp(Menu, {
1341
2741
  ctx,
@@ -1344,12 +2744,12 @@ class MenuView {
1344
2744
  filter,
1345
2745
  hide
1346
2746
  });
1347
- __privateSet$4(this, _app$3, app);
2747
+ __privateSet$5(this, _app$4, app);
1348
2748
  app.mount(content);
1349
- __privateSet$4(this, _content$3, content);
2749
+ __privateSet$5(this, _content$3, content);
1350
2750
  const self = this;
1351
- __privateSet$4(this, _slashProvider, new slash.SlashProvider({
1352
- content: __privateGet$4(this, _content$3),
2751
+ __privateSet$5(this, _slashProvider, new slash.SlashProvider({
2752
+ content: __privateGet$5(this, _content$3),
1353
2753
  debounce: 20,
1354
2754
  shouldShow(view2) {
1355
2755
  if (isInCodeBlock(view2.state.selection) || isInList(view2.state.selection))
@@ -1362,13 +2762,13 @@ class MenuView {
1362
2762
  if (!isSelectionAtEndOfNode(view2.state.selection)) {
1363
2763
  return false;
1364
2764
  }
1365
- const pos = __privateGet$4(self, _programmaticallyPos);
2765
+ const pos = __privateGet$5(self, _programmaticallyPos);
1366
2766
  filter.value = currentText.startsWith("/") ? currentText.slice(1) : currentText;
1367
2767
  if (typeof pos === "number") {
1368
2768
  const maxSize = view2.state.doc.nodeSize - 2;
1369
2769
  const validPos = Math.min(pos, maxSize);
1370
2770
  if (view2.state.doc.resolve(validPos).node() !== view2.state.doc.resolve(view2.state.selection.from).node()) {
1371
- __privateSet$4(self, _programmaticallyPos, null);
2771
+ __privateSet$5(self, _programmaticallyPos, null);
1372
2772
  return false;
1373
2773
  }
1374
2774
  return true;
@@ -1378,10 +2778,10 @@ class MenuView {
1378
2778
  },
1379
2779
  offset: 10
1380
2780
  }));
1381
- __privateGet$4(this, _slashProvider).onShow = () => {
2781
+ __privateGet$5(this, _slashProvider).onShow = () => {
1382
2782
  show.value = true;
1383
2783
  };
1384
- __privateGet$4(this, _slashProvider).onHide = () => {
2784
+ __privateGet$5(this, _slashProvider).onHide = () => {
1385
2785
  show.value = false;
1386
2786
  };
1387
2787
  this.update(view);
@@ -1392,7 +2792,7 @@ class MenuView {
1392
2792
  }
1393
2793
  }
1394
2794
  _content$3 = new WeakMap();
1395
- _app$3 = new WeakMap();
2795
+ _app$4 = new WeakMap();
1396
2796
  _filter = new WeakMap();
1397
2797
  _slashProvider = new WeakMap();
1398
2798
  _programmaticallyPos = new WeakMap();
@@ -1404,6 +2804,7 @@ function isSelectionAtEndOfNode(selection) {
1404
2804
  return offset === parent.content.size;
1405
2805
  }
1406
2806
 
2807
+ keepAlive(vue.h, vue.Fragment);
1407
2808
  const BlockHandle = vue.defineComponent({
1408
2809
  props: {
1409
2810
  onAdd: {
@@ -1447,45 +2848,45 @@ const BlockHandle = vue.defineComponent({
1447
2848
  }
1448
2849
  });
1449
2850
 
1450
- var __typeError$3 = (msg) => {
2851
+ var __typeError$4 = (msg) => {
1451
2852
  throw TypeError(msg);
1452
2853
  };
1453
- var __accessCheck$3 = (obj, member, msg) => member.has(obj) || __typeError$3("Cannot " + msg);
1454
- var __privateGet$3 = (obj, member, getter) => (__accessCheck$3(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
1455
- var __privateAdd$3 = (obj, member, value) => member.has(obj) ? __typeError$3("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1456
- var __privateSet$3 = (obj, member, value, setter) => (__accessCheck$3(obj, member, "write to private field"), member.set(obj, value), value);
1457
- var _content$2, _provider$1, _app$2, _ctx;
2854
+ var __accessCheck$4 = (obj, member, msg) => member.has(obj) || __typeError$4("Cannot " + msg);
2855
+ var __privateGet$4 = (obj, member, getter) => (__accessCheck$4(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
2856
+ 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);
2857
+ var __privateSet$4 = (obj, member, value, setter) => (__accessCheck$4(obj, member, "write to private field"), member.set(obj, value), value);
2858
+ var _content$2, _provider$1, _app$3, _ctx;
1458
2859
  class BlockHandleView {
1459
2860
  constructor(ctx, config) {
1460
- __privateAdd$3(this, _content$2);
1461
- __privateAdd$3(this, _provider$1);
1462
- __privateAdd$3(this, _app$2);
1463
- __privateAdd$3(this, _ctx);
2861
+ __privateAdd$4(this, _content$2);
2862
+ __privateAdd$4(this, _provider$1);
2863
+ __privateAdd$4(this, _app$3);
2864
+ __privateAdd$4(this, _ctx);
1464
2865
  this.update = () => {
1465
- __privateGet$3(this, _provider$1).update();
2866
+ __privateGet$4(this, _provider$1).update();
1466
2867
  };
1467
2868
  this.destroy = () => {
1468
- __privateGet$3(this, _provider$1).destroy();
1469
- __privateGet$3(this, _content$2).remove();
1470
- __privateGet$3(this, _app$2).unmount();
2869
+ __privateGet$4(this, _provider$1).destroy();
2870
+ __privateGet$4(this, _content$2).remove();
2871
+ __privateGet$4(this, _app$3).unmount();
1471
2872
  };
1472
2873
  this.onAdd = () => {
1473
- const ctx = __privateGet$3(this, _ctx);
2874
+ const ctx = __privateGet$4(this, _ctx);
1474
2875
  const view = ctx.get(core.editorViewCtx);
1475
2876
  if (!view.hasFocus()) view.focus();
1476
2877
  const { state: state$1, dispatch } = view;
1477
- const active = __privateGet$3(this, _provider$1).active;
2878
+ const active = __privateGet$4(this, _provider$1).active;
1478
2879
  if (!active) return;
1479
2880
  const $pos = active.$pos;
1480
2881
  const pos = $pos.pos + active.node.nodeSize;
1481
2882
  let tr = state$1.tr.insert(pos, commonmark.paragraphSchema.type(ctx).create());
1482
2883
  tr = tr.setSelection(state.TextSelection.near(tr.doc.resolve(pos)));
1483
2884
  dispatch(tr.scrollIntoView());
1484
- __privateGet$3(this, _provider$1).hide();
2885
+ __privateGet$4(this, _provider$1).hide();
1485
2886
  ctx.get(menuAPI.key).show(tr.selection.from);
1486
2887
  };
1487
2888
  var _a, _b, _c;
1488
- __privateSet$3(this, _ctx, ctx);
2889
+ __privateSet$4(this, _ctx, ctx);
1489
2890
  const content = document.createElement("div");
1490
2891
  content.classList.add("milkdown-block-handle");
1491
2892
  const app = vue.createApp(BlockHandle, {
@@ -1494,10 +2895,10 @@ class BlockHandleView {
1494
2895
  handleIcon: (_b = config == null ? void 0 : config.handleDragIcon) != null ? _b : menuIcon
1495
2896
  });
1496
2897
  app.mount(content);
1497
- __privateSet$3(this, _app$2, app);
1498
- __privateSet$3(this, _content$2, content);
2898
+ __privateSet$4(this, _app$3, app);
2899
+ __privateSet$4(this, _content$2, content);
1499
2900
  const blockProviderOptions = (_c = config == null ? void 0 : config.blockHandle) != null ? _c : {};
1500
- __privateSet$3(this, _provider$1, new block.BlockProvider({
2901
+ __privateSet$4(this, _provider$1, new block.BlockProvider({
1501
2902
  ctx,
1502
2903
  content,
1503
2904
  getOffset: () => 16,
@@ -1524,7 +2925,7 @@ class BlockHandleView {
1524
2925
  }
1525
2926
  _content$2 = new WeakMap();
1526
2927
  _provider$1 = new WeakMap();
1527
- _app$2 = new WeakMap();
2928
+ _app$3 = new WeakMap();
1528
2929
  _ctx = new WeakMap();
1529
2930
  function configureBlockHandle(ctx, config) {
1530
2931
  ctx.set(block.blockConfig.key, {
@@ -1549,7 +2950,7 @@ const codeMirror = (editor, config = {}) => {
1549
2950
  editor.config(crepeFeatureConfig(CrepeFeature.CodeMirror)).config((ctx) => {
1550
2951
  const { languages = [], theme } = config;
1551
2952
  const extensions = [
1552
- view.keymap.of(commands.defaultKeymap.concat(commands.indentWithTab)),
2953
+ view$1.keymap.of(commands.defaultKeymap.concat(commands.indentWithTab)),
1553
2954
  codemirror.basicSetup
1554
2955
  ];
1555
2956
  if (theme) {
@@ -1630,7 +3031,9 @@ const imageBlock = (editor, config) => {
1630
3031
  uploadPlaceholderText: (_f = config == null ? void 0 : config.blockUploadPlaceholderText) != null ? _f : "or paste link",
1631
3032
  onUpload: (_h = (_g = config == null ? void 0 : config.blockOnUpload) != null ? _g : config == null ? void 0 : config.onUpload) != null ? _h : value.onUpload,
1632
3033
  proxyDomURL: config == null ? void 0 : config.proxyDomURL,
1633
- onImageLoadError: (_i = config == null ? void 0 : config.onImageLoadError) != null ? _i : value.onImageLoadError
3034
+ onImageLoadError: (_i = config == null ? void 0 : config.onImageLoadError) != null ? _i : value.onImageLoadError,
3035
+ maxWidth: config == null ? void 0 : config.maxWidth,
3036
+ maxHeight: config == null ? void 0 : config.maxHeight
1634
3037
  };
1635
3038
  });
1636
3039
  }).use(imageBlock$1.imageBlockComponent).use(imageInline.imageInlineComponent);
@@ -1747,6 +3150,7 @@ const toggleLatexCommand = utils.$command("ToggleLatex", (ctx) => {
1747
3150
 
1748
3151
  const inlineLatexTooltip = tooltip.tooltipFactory("INLINE_LATEX");
1749
3152
 
3153
+ keepAlive(vue.h);
1750
3154
  const LatexTooltip = vue.defineComponent({
1751
3155
  props: {
1752
3156
  config: {
@@ -1782,33 +3186,34 @@ const LatexTooltip = vue.defineComponent({
1782
3186
  }
1783
3187
  });
1784
3188
 
1785
- var __typeError$2 = (msg) => {
3189
+ var __typeError$3 = (msg) => {
1786
3190
  throw TypeError(msg);
1787
3191
  };
1788
- var __accessCheck$2 = (obj, member, msg) => member.has(obj) || __typeError$2("Cannot " + msg);
1789
- var __privateGet$2 = (obj, member, getter) => (__accessCheck$2(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
1790
- var __privateAdd$2 = (obj, member, value) => member.has(obj) ? __typeError$2("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1791
- var __privateSet$2 = (obj, member, value, setter) => (__accessCheck$2(obj, member, "write to private field"), member.set(obj, value), value);
1792
- var _content$1, _provider, _dom, _innerView, _updateValue, _app$1, _onHide, _shouldShow;
3192
+ var __accessCheck$3 = (obj, member, msg) => member.has(obj) || __typeError$3("Cannot " + msg);
3193
+ var __privateGet$3 = (obj, member, getter) => (__accessCheck$3(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
3194
+ var __privateAdd$3 = (obj, member, value) => member.has(obj) ? __typeError$3("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
3195
+ var __privateSet$3 = (obj, member, value, setter) => (__accessCheck$3(obj, member, "write to private field"), member.set(obj, value), value);
3196
+ var _content$1, _provider, _dom, _innerView, _updateValue, _app$2, _onHide, _shouldShow;
1793
3197
  class LatexInlineTooltip {
1794
- constructor(ctx, view, config) {
3198
+ constructor(ctx, view$1, config) {
1795
3199
  this.ctx = ctx;
1796
- __privateAdd$2(this, _content$1);
1797
- __privateAdd$2(this, _provider);
1798
- __privateAdd$2(this, _dom);
1799
- __privateAdd$2(this, _innerView, vue.shallowRef(null));
1800
- __privateAdd$2(this, _updateValue, vue.shallowRef(() => {
3200
+ __privateAdd$3(this, _content$1);
3201
+ __privateAdd$3(this, _provider);
3202
+ __privateAdd$3(this, _dom);
3203
+ __privateAdd$3(this, _innerView, vue.shallowRef(null));
3204
+ __privateAdd$3(this, _updateValue, vue.shallowRef(() => {
1801
3205
  }));
1802
- __privateAdd$2(this, _app$1);
1803
- __privateAdd$2(this, _onHide, () => {
1804
- if (__privateGet$2(this, _innerView).value) {
1805
- __privateGet$2(this, _innerView).value.destroy();
1806
- __privateGet$2(this, _innerView).value = null;
3206
+ __privateAdd$3(this, _app$2);
3207
+ __privateAdd$3(this, _onHide, () => {
3208
+ if (__privateGet$3(this, _innerView).value) {
3209
+ __privateGet$3(this, _innerView).value.destroy();
3210
+ __privateGet$3(this, _innerView).value = null;
1807
3211
  }
1808
3212
  });
1809
- __privateAdd$2(this, _shouldShow, (view) => {
3213
+ __privateAdd$3(this, _shouldShow, (view$1) => {
1810
3214
  const shouldShow = () => {
1811
- const { selection, schema } = view.state;
3215
+ if (!view$1.editable) return false;
3216
+ const { selection, schema } = view$1.state;
1812
3217
  if (selection.empty) return false;
1813
3218
  if (!(selection instanceof state.NodeSelection)) return false;
1814
3219
  const node = selection.node;
@@ -1818,7 +3223,7 @@ class LatexInlineTooltip {
1818
3223
  null,
1819
3224
  schema.text(node.attrs.value)
1820
3225
  );
1821
- const innerView = new view$1.EditorView(__privateGet$2(this, _dom), {
3226
+ const innerView = new view.EditorView(__privateGet$3(this, _dom), {
1822
3227
  state: state.EditorState.create({
1823
3228
  doc: paragraph,
1824
3229
  schema: new model.Schema({
@@ -1845,56 +3250,56 @@ class LatexInlineTooltip {
1845
3250
  "Mod-Z": history.redo,
1846
3251
  "Mod-y": history.redo,
1847
3252
  Enter: () => {
1848
- __privateGet$2(this, _updateValue).value();
3253
+ __privateGet$3(this, _updateValue).value();
1849
3254
  return true;
1850
3255
  }
1851
3256
  })
1852
3257
  ]
1853
3258
  })
1854
3259
  });
1855
- __privateGet$2(this, _innerView).value = innerView;
1856
- __privateGet$2(this, _updateValue).value = () => {
1857
- const { tr } = view.state;
3260
+ __privateGet$3(this, _innerView).value = innerView;
3261
+ __privateGet$3(this, _updateValue).value = () => {
3262
+ const { tr } = view$1.state;
1858
3263
  tr.setNodeAttribute(textFrom, "value", innerView.state.doc.textContent);
1859
- view.dispatch(tr);
3264
+ view$1.dispatch(tr);
1860
3265
  requestAnimationFrame(() => {
1861
- view.focus();
3266
+ view$1.focus();
1862
3267
  });
1863
3268
  };
1864
3269
  return true;
1865
3270
  };
1866
3271
  const show = shouldShow();
1867
- if (!show) __privateGet$2(this, _onHide).call(this);
3272
+ if (!show) __privateGet$3(this, _onHide).call(this);
1868
3273
  return show;
1869
3274
  });
1870
3275
  this.update = (view, prevState) => {
1871
- __privateGet$2(this, _provider).update(view, prevState);
3276
+ __privateGet$3(this, _provider).update(view, prevState);
1872
3277
  };
1873
3278
  this.destroy = () => {
1874
- __privateGet$2(this, _app$1).unmount();
1875
- __privateGet$2(this, _provider).destroy();
1876
- __privateGet$2(this, _content$1).remove();
3279
+ __privateGet$3(this, _app$2).unmount();
3280
+ __privateGet$3(this, _provider).destroy();
3281
+ __privateGet$3(this, _content$1).remove();
1877
3282
  };
1878
3283
  const content = document.createElement("div");
1879
3284
  content.className = "milkdown-latex-inline-edit";
1880
- __privateSet$2(this, _content$1, content);
1881
- __privateSet$2(this, _app$1, vue.createApp(LatexTooltip, {
3285
+ __privateSet$3(this, _content$1, content);
3286
+ __privateSet$3(this, _app$2, vue.createApp(LatexTooltip, {
1882
3287
  config,
1883
- innerView: __privateGet$2(this, _innerView),
1884
- updateValue: __privateGet$2(this, _updateValue)
3288
+ innerView: __privateGet$3(this, _innerView),
3289
+ updateValue: __privateGet$3(this, _updateValue)
1885
3290
  }));
1886
- __privateGet$2(this, _app$1).mount(content);
1887
- __privateSet$2(this, _provider, new tooltip.TooltipProvider({
3291
+ __privateGet$3(this, _app$2).mount(content);
3292
+ __privateSet$3(this, _provider, new tooltip.TooltipProvider({
1888
3293
  debounce: 0,
1889
- content: __privateGet$2(this, _content$1),
1890
- shouldShow: __privateGet$2(this, _shouldShow),
3294
+ content: __privateGet$3(this, _content$1),
3295
+ shouldShow: __privateGet$3(this, _shouldShow),
1891
3296
  offset: 10,
1892
3297
  floatingUIOptions: {
1893
3298
  placement: "bottom"
1894
3299
  }
1895
3300
  }));
1896
- __privateGet$2(this, _provider).update(view);
1897
- __privateSet$2(this, _dom, document.createElement("div"));
3301
+ __privateGet$3(this, _provider).update(view$1);
3302
+ __privateSet$3(this, _dom, document.createElement("div"));
1898
3303
  }
1899
3304
  }
1900
3305
  _content$1 = new WeakMap();
@@ -1902,7 +3307,7 @@ _provider = new WeakMap();
1902
3307
  _dom = new WeakMap();
1903
3308
  _innerView = new WeakMap();
1904
3309
  _updateValue = new WeakMap();
1905
- _app$1 = new WeakMap();
3310
+ _app$2 = new WeakMap();
1906
3311
  _onHide = new WeakMap();
1907
3312
  _shouldShow = new WeakMap();
1908
3313
 
@@ -2031,7 +3436,7 @@ function createPlaceholderDecoration(state, placeholderText) {
2031
3436
  const inTable = prose.findParent((node2) => node2.type.name === "table")($pos);
2032
3437
  if (inTable) return null;
2033
3438
  const before = $pos.before();
2034
- return view$1.Decoration.node(before, before + node.nodeSize, {
3439
+ return view.Decoration.node(before, before + node.nodeSize, {
2035
3440
  class: "crepe-placeholder",
2036
3441
  "data-placeholder": placeholderText
2037
3442
  });
@@ -2058,7 +3463,7 @@ const placeholderPlugin = utils.$prose((ctx) => {
2058
3463
  const placeholderText = (_a = config.text) != null ? _a : "Please enter...";
2059
3464
  const deco = createPlaceholderDecoration(state, placeholderText);
2060
3465
  if (!deco) return null;
2061
- return view$1.DecorationSet.create(state.doc, [deco]);
3466
+ return view.DecorationSet.create(state.doc, [deco]);
2062
3467
  }
2063
3468
  }
2064
3469
  });
@@ -2107,8 +3512,8 @@ const table = (editor, config) => {
2107
3512
  }).use(tableBlock.tableBlock);
2108
3513
  };
2109
3514
 
2110
- function getGroups(config, ctx) {
2111
- var _a, _b, _c, _d, _e, _f, _g;
3515
+ function getGroups$1(config, ctx) {
3516
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2112
3517
  const groupBuilder = new GroupBuilder();
2113
3518
  groupBuilder.addGroup("formatting", "Formatting").addItem("bold", {
2114
3519
  icon: (_a = config == null ? void 0 : config.boldIcon) != null ? _a : boldIcon,
@@ -2191,10 +3596,26 @@ function getGroups(config, ctx) {
2191
3596
  commands.call(linkTooltip$1.toggleLinkCommand.key);
2192
3597
  }
2193
3598
  });
2194
- (_g = config == null ? void 0 : config.buildToolbar) == null ? void 0 : _g.call(config, groupBuilder);
3599
+ if (ctx && (flags == null ? void 0 : flags.includes(CrepeFeature.AI))) {
3600
+ const aiCfg = ctx.get(aiProviderConfig.key);
3601
+ if (aiCfg.provider) {
3602
+ functionGroup.addItem("ai", {
3603
+ icon: (_h = (_g = config == null ? void 0 : config.aiIcon) != null ? _g : aiCfg.aiIcon) != null ? _h : aiIcon,
3604
+ active: () => false,
3605
+ onRun: (ctx2) => {
3606
+ const api = ctx2.get(aiInstructionTooltipAPI.key);
3607
+ const view = ctx2.get(core.editorViewCtx);
3608
+ const { from, to } = view.state.selection;
3609
+ api.show(from, to);
3610
+ }
3611
+ });
3612
+ }
3613
+ }
3614
+ (_i = config == null ? void 0 : config.buildToolbar) == null ? void 0 : _i.call(config, groupBuilder);
2195
3615
  return groupBuilder.build();
2196
3616
  }
2197
3617
 
3618
+ keepAlive(vue.h, vue.Fragment);
2198
3619
  const Toolbar = vue.defineComponent({
2199
3620
  props: {
2200
3621
  ctx: {
@@ -2222,15 +3643,17 @@ const Toolbar = vue.defineComponent({
2222
3643
  const { ctx, config } = props;
2223
3644
  const onClick = (fn) => (e) => {
2224
3645
  e.preventDefault();
2225
- ctx && fn(ctx);
3646
+ if (ctx) {
3647
+ fn == null ? void 0 : fn(ctx);
3648
+ }
2226
3649
  };
2227
3650
  function checkActive(checker) {
2228
- props.selection.value;
3651
+ keepAlive(props.selection.value);
2229
3652
  const status = ctx.get(core.editorCtx).status;
2230
3653
  if (status !== core.EditorStatus.Created) return false;
2231
3654
  return checker(ctx);
2232
3655
  }
2233
- const groupInfo = vue.computed(() => getGroups(config, ctx));
3656
+ const groupInfo = vue.computed(() => getGroups$1(config, ctx));
2234
3657
  return () => {
2235
3658
  return /* @__PURE__ */ vue.h(vue.Fragment, null, groupInfo.value.map((group) => {
2236
3659
  return group.items.map((item) => {
@@ -2259,49 +3682,49 @@ const Toolbar = vue.defineComponent({
2259
3682
  }
2260
3683
  });
2261
3684
 
2262
- var __typeError$1 = (msg) => {
3685
+ var __typeError$2 = (msg) => {
2263
3686
  throw TypeError(msg);
2264
3687
  };
2265
- var __accessCheck$1 = (obj, member, msg) => member.has(obj) || __typeError$1("Cannot " + msg);
2266
- var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
2267
- var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
2268
- var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
2269
- var _tooltipProvider, _content, _app, _selection, _show;
3688
+ var __accessCheck$2 = (obj, member, msg) => member.has(obj) || __typeError$2("Cannot " + msg);
3689
+ var __privateGet$2 = (obj, member, getter) => (__accessCheck$2(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
3690
+ var __privateAdd$2 = (obj, member, value) => member.has(obj) ? __typeError$2("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
3691
+ var __privateSet$2 = (obj, member, value, setter) => (__accessCheck$2(obj, member, "write to private field"), member.set(obj, value), value);
3692
+ var _tooltipProvider, _content, _app$1, _selection, _show;
2270
3693
  const toolbarTooltip = tooltip.tooltipFactory("CREPE_TOOLBAR");
2271
3694
  class ToolbarView {
2272
3695
  constructor(ctx, view, config) {
2273
- __privateAdd$1(this, _tooltipProvider);
2274
- __privateAdd$1(this, _content);
2275
- __privateAdd$1(this, _app);
2276
- __privateAdd$1(this, _selection);
2277
- __privateAdd$1(this, _show, vue.ref(false));
3696
+ __privateAdd$2(this, _tooltipProvider);
3697
+ __privateAdd$2(this, _content);
3698
+ __privateAdd$2(this, _app$1);
3699
+ __privateAdd$2(this, _selection);
3700
+ __privateAdd$2(this, _show, vue.ref(false));
2278
3701
  this.update = (view, prevState) => {
2279
- __privateGet$1(this, _tooltipProvider).update(view, prevState);
2280
- __privateGet$1(this, _selection).value = view.state.selection;
3702
+ __privateGet$2(this, _tooltipProvider).update(view, prevState);
3703
+ __privateGet$2(this, _selection).value = view.state.selection;
2281
3704
  };
2282
3705
  this.destroy = () => {
2283
- __privateGet$1(this, _tooltipProvider).destroy();
2284
- __privateGet$1(this, _app).unmount();
2285
- __privateGet$1(this, _content).remove();
3706
+ __privateGet$2(this, _tooltipProvider).destroy();
3707
+ __privateGet$2(this, _app$1).unmount();
3708
+ __privateGet$2(this, _content).remove();
2286
3709
  };
2287
3710
  this.hide = () => {
2288
- __privateGet$1(this, _tooltipProvider).hide();
3711
+ __privateGet$2(this, _tooltipProvider).hide();
2289
3712
  };
2290
3713
  const content = document.createElement("div");
2291
3714
  content.className = "milkdown-toolbar";
2292
- __privateSet$1(this, _selection, vue.shallowRef(view.state.selection));
3715
+ __privateSet$2(this, _selection, vue.shallowRef(view.state.selection));
2293
3716
  const app = vue.createApp(Toolbar, {
2294
3717
  ctx,
2295
3718
  hide: this.hide,
2296
3719
  config,
2297
- selection: __privateGet$1(this, _selection),
2298
- show: __privateGet$1(this, _show)
3720
+ selection: __privateGet$2(this, _selection),
3721
+ show: __privateGet$2(this, _show)
2299
3722
  });
2300
3723
  app.mount(content);
2301
- __privateSet$1(this, _content, content);
2302
- __privateSet$1(this, _app, app);
2303
- __privateSet$1(this, _tooltipProvider, new tooltip.TooltipProvider({
2304
- content: __privateGet$1(this, _content),
3724
+ __privateSet$2(this, _content, content);
3725
+ __privateSet$2(this, _app$1, app);
3726
+ __privateSet$2(this, _tooltipProvider, new tooltip.TooltipProvider({
3727
+ content: __privateGet$2(this, _content),
2305
3728
  debounce: 20,
2306
3729
  offset: 10,
2307
3730
  shouldShow(view2) {
@@ -2318,18 +3741,18 @@ class ToolbarView {
2318
3741
  return true;
2319
3742
  }
2320
3743
  }));
2321
- __privateGet$1(this, _tooltipProvider).onShow = () => {
2322
- __privateGet$1(this, _show).value = true;
3744
+ __privateGet$2(this, _tooltipProvider).onShow = () => {
3745
+ __privateGet$2(this, _show).value = true;
2323
3746
  };
2324
- __privateGet$1(this, _tooltipProvider).onHide = () => {
2325
- __privateGet$1(this, _show).value = false;
3747
+ __privateGet$2(this, _tooltipProvider).onHide = () => {
3748
+ __privateGet$2(this, _show).value = false;
2326
3749
  };
2327
3750
  this.update(view);
2328
3751
  }
2329
3752
  }
2330
3753
  _tooltipProvider = new WeakMap();
2331
3754
  _content = new WeakMap();
2332
- _app = new WeakMap();
3755
+ _app$1 = new WeakMap();
2333
3756
  _selection = new WeakMap();
2334
3757
  _show = new WeakMap();
2335
3758
  const toolbar = (editor, config) => {
@@ -2340,6 +3763,442 @@ const toolbar = (editor, config) => {
2340
3763
  }).use(toolbarTooltip);
2341
3764
  };
2342
3765
 
3766
+ const defaultHeadingOptions = [
3767
+ { label: "Paragraph", level: null },
3768
+ { label: "Heading 1", level: 1 },
3769
+ { label: "Heading 2", level: 2 },
3770
+ { label: "Heading 3", level: 3 },
3771
+ { label: "Heading 4", level: 4 },
3772
+ { label: "Heading 5", level: 5 },
3773
+ { label: "Heading 6", level: 6 }
3774
+ ];
3775
+ function getCurrentHeading(ctx, options) {
3776
+ var _a, _b;
3777
+ const headingOptions = options != null ? options : defaultHeadingOptions;
3778
+ const view = ctx.get(core.editorViewCtx);
3779
+ const { $from } = view.state.selection;
3780
+ const node = $from.parent;
3781
+ const paragraphOption = (_a = headingOptions.find((o) => o.level === null)) != null ? _a : headingOptions[0];
3782
+ if (node.type === commonmark.headingSchema.type(ctx)) {
3783
+ const level = node.attrs.level;
3784
+ return (_b = headingOptions.find((o) => o.level === level)) != null ? _b : paragraphOption;
3785
+ }
3786
+ return paragraphOption;
3787
+ }
3788
+ function setHeading(ctx, level) {
3789
+ const commands = ctx.get(core.commandsCtx);
3790
+ if (level === null || level === void 0) {
3791
+ const paragraph = commonmark.paragraphSchema.type(ctx);
3792
+ commands.call(commonmark.setBlockTypeCommand.key, { nodeType: paragraph });
3793
+ } else {
3794
+ const heading = commonmark.headingSchema.type(ctx);
3795
+ commands.call(commonmark.setBlockTypeCommand.key, {
3796
+ nodeType: heading,
3797
+ attrs: { level }
3798
+ });
3799
+ }
3800
+ }
3801
+ function isMarkActive(ctx, markType) {
3802
+ const commands = ctx.get(core.commandsCtx);
3803
+ const selected = commands.call(commonmark.isMarkSelectedCommand.key, markType);
3804
+ if (selected) return true;
3805
+ const view = ctx.get(core.editorViewCtx);
3806
+ const { state: state$1 } = view;
3807
+ if (state$1.storedMarks) {
3808
+ return state$1.storedMarks.some((m) => m.type === markType);
3809
+ }
3810
+ if (state$1.selection instanceof state.TextSelection) {
3811
+ const { $cursor } = state$1.selection;
3812
+ if ($cursor) {
3813
+ return $cursor.marks().some((m) => m.type === markType);
3814
+ }
3815
+ }
3816
+ return false;
3817
+ }
3818
+ function buildHeadingSelector(headingOptions, chevronIcon) {
3819
+ const options = headingOptions != null ? headingOptions : defaultHeadingOptions;
3820
+ return {
3821
+ icon: "",
3822
+ active: () => false,
3823
+ selector: {
3824
+ chevronIcon: chevronIcon != null ? chevronIcon : chevronDownIcon,
3825
+ activeLabel: (ctx) => getCurrentHeading(ctx, options).label,
3826
+ options: options.map((opt) => ({
3827
+ label: opt.label,
3828
+ onSelect: (ctx) => setHeading(ctx, opt.level)
3829
+ }))
3830
+ }
3831
+ };
3832
+ }
3833
+ function getGroups(config, ctx) {
3834
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
3835
+ const flags = ctx && useCrepeFeatures(ctx).get();
3836
+ const isLatexEnabled = flags == null ? void 0 : flags.includes(CrepeFeature.Latex);
3837
+ const isImageBlockEnabled = flags == null ? void 0 : flags.includes(CrepeFeature.ImageBlock);
3838
+ const isTableEnabled = flags == null ? void 0 : flags.includes(CrepeFeature.Table);
3839
+ const groupBuilder = new GroupBuilder();
3840
+ groupBuilder.addGroup("heading", "Heading").addItem("heading-selector", {
3841
+ ...buildHeadingSelector(config == null ? void 0 : config.headingOptions, config == null ? void 0 : config.chevronDownIcon)
3842
+ });
3843
+ groupBuilder.addGroup("formatting", "Formatting").addItem("bold", {
3844
+ icon: (_a = config == null ? void 0 : config.boldIcon) != null ? _a : boldIcon,
3845
+ active: (ctx2) => isMarkActive(ctx2, commonmark.strongSchema.type(ctx2)),
3846
+ onRun: (ctx2) => {
3847
+ const commands = ctx2.get(core.commandsCtx);
3848
+ commands.call(commonmark.toggleStrongCommand.key);
3849
+ }
3850
+ }).addItem("italic", {
3851
+ icon: (_b = config == null ? void 0 : config.italicIcon) != null ? _b : italicIcon,
3852
+ active: (ctx2) => isMarkActive(ctx2, commonmark.emphasisSchema.type(ctx2)),
3853
+ onRun: (ctx2) => {
3854
+ const commands = ctx2.get(core.commandsCtx);
3855
+ commands.call(commonmark.toggleEmphasisCommand.key);
3856
+ }
3857
+ }).addItem("strikethrough", {
3858
+ icon: (_c = config == null ? void 0 : config.strikethroughIcon) != null ? _c : strikethroughIcon,
3859
+ active: (ctx2) => isMarkActive(ctx2, gfm.strikethroughSchema.type(ctx2)),
3860
+ onRun: (ctx2) => {
3861
+ const commands = ctx2.get(core.commandsCtx);
3862
+ commands.call(gfm.toggleStrikethroughCommand.key);
3863
+ }
3864
+ }).addItem("code", {
3865
+ icon: (_d = config == null ? void 0 : config.codeIcon) != null ? _d : codeIcon,
3866
+ active: (ctx2) => isMarkActive(ctx2, commonmark.inlineCodeSchema.type(ctx2)),
3867
+ onRun: (ctx2) => {
3868
+ const view = ctx2.get(core.editorViewCtx);
3869
+ const { state } = view;
3870
+ if (state.selection.empty) {
3871
+ const markType = commonmark.inlineCodeSchema.type(ctx2);
3872
+ const has = isMarkActive(ctx2, markType);
3873
+ if (has) {
3874
+ view.dispatch(state.tr.removeStoredMark(markType));
3875
+ } else {
3876
+ view.dispatch(state.tr.addStoredMark(markType.create()));
3877
+ }
3878
+ } else {
3879
+ const commands = ctx2.get(core.commandsCtx);
3880
+ commands.call(commonmark.toggleInlineCodeCommand.key);
3881
+ }
3882
+ }
3883
+ });
3884
+ groupBuilder.addGroup("list", "List").addItem("bullet-list", {
3885
+ icon: (_e = config == null ? void 0 : config.bulletListIcon) != null ? _e : bulletListIcon,
3886
+ active: () => false,
3887
+ onRun: (ctx2) => {
3888
+ const commands = ctx2.get(core.commandsCtx);
3889
+ const bulletList = commonmark.bulletListSchema.type(ctx2);
3890
+ commands.call(commonmark.wrapInBlockTypeCommand.key, { nodeType: bulletList });
3891
+ }
3892
+ }).addItem("ordered-list", {
3893
+ icon: (_f = config == null ? void 0 : config.orderedListIcon) != null ? _f : orderedListIcon,
3894
+ active: () => false,
3895
+ onRun: (ctx2) => {
3896
+ const commands = ctx2.get(core.commandsCtx);
3897
+ const orderedList = commonmark.orderedListSchema.type(ctx2);
3898
+ commands.call(commonmark.wrapInBlockTypeCommand.key, { nodeType: orderedList });
3899
+ }
3900
+ }).addItem("task-list", {
3901
+ icon: (_g = config == null ? void 0 : config.taskListIcon) != null ? _g : todoListIcon,
3902
+ active: () => false,
3903
+ onRun: (ctx2) => {
3904
+ const commands = ctx2.get(core.commandsCtx);
3905
+ const listItem = commonmark.listItemSchema.type(ctx2);
3906
+ commands.call(commonmark.wrapInBlockTypeCommand.key, {
3907
+ nodeType: listItem,
3908
+ attrs: { checked: false }
3909
+ });
3910
+ }
3911
+ });
3912
+ const insertGroup = groupBuilder.addGroup("insert", "Insert");
3913
+ insertGroup.addItem("link", {
3914
+ icon: (_h = config == null ? void 0 : config.linkIcon) != null ? _h : linkIcon,
3915
+ active: (ctx2) => isMarkActive(ctx2, commonmark.linkSchema.type(ctx2)),
3916
+ onRun: (ctx2) => {
3917
+ const view = ctx2.get(core.editorViewCtx);
3918
+ const { state } = view;
3919
+ const markType = commonmark.linkSchema.type(ctx2);
3920
+ if (state.selection.empty && isMarkActive(ctx2, markType)) {
3921
+ view.dispatch(state.tr.removeStoredMark(markType));
3922
+ return;
3923
+ }
3924
+ const commands = ctx2.get(core.commandsCtx);
3925
+ commands.call(linkTooltip$1.toggleLinkCommand.key);
3926
+ }
3927
+ });
3928
+ if (isImageBlockEnabled) {
3929
+ insertGroup.addItem("image", {
3930
+ icon: (_i = config == null ? void 0 : config.imageIcon) != null ? _i : imageIcon,
3931
+ active: () => false,
3932
+ onRun: (ctx2) => {
3933
+ const commands = ctx2.get(core.commandsCtx);
3934
+ const imageBlock = imageBlock$1.imageBlockSchema.type(ctx2);
3935
+ commands.call(commonmark.addBlockTypeCommand.key, { nodeType: imageBlock });
3936
+ }
3937
+ });
3938
+ }
3939
+ if (isTableEnabled) {
3940
+ insertGroup.addItem("table", {
3941
+ icon: (_j = config == null ? void 0 : config.tableIcon) != null ? _j : tableIcon,
3942
+ active: () => false,
3943
+ onRun: (ctx2) => {
3944
+ const commands = ctx2.get(core.commandsCtx);
3945
+ const view = ctx2.get(core.editorViewCtx);
3946
+ const { from } = view.state.selection;
3947
+ commands.call(commonmark.addBlockTypeCommand.key, {
3948
+ nodeType: gfm.createTable(ctx2, 3, 3)
3949
+ });
3950
+ commands.call(commonmark.selectTextNearPosCommand.key, { pos: from });
3951
+ }
3952
+ });
3953
+ }
3954
+ const blockGroup = groupBuilder.addGroup("block", "Block");
3955
+ blockGroup.addItem("code-block", {
3956
+ icon: (_k = config == null ? void 0 : config.codeBlockIcon) != null ? _k : codeBlockIcon,
3957
+ active: () => false,
3958
+ onRun: (ctx2) => {
3959
+ const commands = ctx2.get(core.commandsCtx);
3960
+ const codeBlock = commonmark.codeBlockSchema.type(ctx2);
3961
+ commands.call(commonmark.setBlockTypeCommand.key, { nodeType: codeBlock });
3962
+ }
3963
+ });
3964
+ if (isLatexEnabled) {
3965
+ blockGroup.addItem("math", {
3966
+ icon: (_l = config == null ? void 0 : config.mathIcon) != null ? _l : functionsIcon,
3967
+ active: () => false,
3968
+ onRun: (ctx2) => {
3969
+ const commands = ctx2.get(core.commandsCtx);
3970
+ const codeBlock = commonmark.codeBlockSchema.type(ctx2);
3971
+ commands.call(commonmark.addBlockTypeCommand.key, {
3972
+ nodeType: codeBlock,
3973
+ attrs: { language: "LaTeX" }
3974
+ });
3975
+ }
3976
+ });
3977
+ }
3978
+ groupBuilder.addGroup("more", "More").addItem("quote", {
3979
+ icon: (_m = config == null ? void 0 : config.quoteIcon) != null ? _m : quoteIcon,
3980
+ active: () => false,
3981
+ onRun: (ctx2) => {
3982
+ const commands = ctx2.get(core.commandsCtx);
3983
+ const blockquote = commonmark.blockquoteSchema.type(ctx2);
3984
+ commands.call(commonmark.wrapInBlockTypeCommand.key, { nodeType: blockquote });
3985
+ }
3986
+ }).addItem("hr", {
3987
+ icon: (_n = config == null ? void 0 : config.hrIcon) != null ? _n : dividerIcon,
3988
+ active: () => false,
3989
+ onRun: (ctx2) => {
3990
+ const commands = ctx2.get(core.commandsCtx);
3991
+ const hr = commonmark.hrSchema.type(ctx2);
3992
+ commands.call(commonmark.addBlockTypeCommand.key, { nodeType: hr });
3993
+ }
3994
+ });
3995
+ (_o = config == null ? void 0 : config.buildTopBar) == null ? void 0 : _o.call(config, groupBuilder);
3996
+ return groupBuilder.build();
3997
+ }
3998
+
3999
+ keepAlive(vue.h, vue.Fragment);
4000
+ const TopBar = vue.defineComponent({
4001
+ props: {
4002
+ ctx: {
4003
+ type: Object,
4004
+ required: true
4005
+ },
4006
+ version: {
4007
+ type: Object,
4008
+ required: true
4009
+ },
4010
+ config: {
4011
+ type: Object,
4012
+ required: false
4013
+ }
4014
+ },
4015
+ setup(props) {
4016
+ const { ctx, config } = props;
4017
+ const openSelectorKey = vue.ref(null);
4018
+ const onClick = (fn) => (e) => {
4019
+ e.preventDefault();
4020
+ if (ctx) {
4021
+ fn(ctx);
4022
+ }
4023
+ };
4024
+ function isReady() {
4025
+ const status = ctx.get(core.editorCtx).status;
4026
+ return status === core.EditorStatus.Created;
4027
+ }
4028
+ function subscribeState() {
4029
+ keepAlive(props.version.value);
4030
+ }
4031
+ function checkActive(checker) {
4032
+ subscribeState();
4033
+ if (!isReady()) return false;
4034
+ return checker(ctx);
4035
+ }
4036
+ function getSelectorLabel(selector) {
4037
+ var _a, _b;
4038
+ subscribeState();
4039
+ if (!isReady()) return (_b = (_a = selector.options[0]) == null ? void 0 : _a.label) != null ? _b : "";
4040
+ return selector.activeLabel(ctx);
4041
+ }
4042
+ function onToggleSelector(key, e) {
4043
+ e.preventDefault();
4044
+ e.stopPropagation();
4045
+ openSelectorKey.value = openSelectorKey.value === key ? null : key;
4046
+ }
4047
+ const clickOutsideHandler = (e) => {
4048
+ const target = e.target;
4049
+ if (target.closest(".top-bar-heading-selector")) return;
4050
+ openSelectorKey.value = null;
4051
+ };
4052
+ vue.onMounted(() => {
4053
+ window.addEventListener("pointerdown", clickOutsideHandler);
4054
+ });
4055
+ vue.onUnmounted(() => {
4056
+ window.removeEventListener("pointerdown", clickOutsideHandler);
4057
+ });
4058
+ const groupInfo = vue.computed(() => getGroups(config, ctx));
4059
+ function renderSelector(itemKey, selector) {
4060
+ const isOpen = openSelectorKey.value === itemKey;
4061
+ const activeLabel = getSelectorLabel(selector);
4062
+ return /* @__PURE__ */ vue.h("div", { key: itemKey, class: "top-bar-heading-selector" }, /* @__PURE__ */ vue.h(
4063
+ "button",
4064
+ {
4065
+ type: "button",
4066
+ class: "top-bar-heading-button",
4067
+ onPointerdown: (e) => onToggleSelector(itemKey, e)
4068
+ },
4069
+ /* @__PURE__ */ vue.h("span", { class: "top-bar-heading-label" }, activeLabel),
4070
+ selector.chevronIcon && /* @__PURE__ */ vue.h("span", { class: "top-bar-chevron" }, /* @__PURE__ */ vue.h(component.Icon, { icon: selector.chevronIcon }))
4071
+ ), isOpen && /* @__PURE__ */ vue.h("div", { class: "top-bar-heading-dropdown" }, selector.options.map((option, index) => /* @__PURE__ */ vue.h(
4072
+ "button",
4073
+ {
4074
+ key: `${itemKey}-${index}`,
4075
+ type: "button",
4076
+ class: clsx(
4077
+ "top-bar-heading-option",
4078
+ activeLabel === option.label && "active"
4079
+ ),
4080
+ onPointerdown: (e) => {
4081
+ e.preventDefault();
4082
+ e.stopPropagation();
4083
+ openSelectorKey.value = null;
4084
+ option.onSelect(ctx);
4085
+ }
4086
+ },
4087
+ option.label
4088
+ ))));
4089
+ }
4090
+ function renderButton(item) {
4091
+ return /* @__PURE__ */ vue.h(
4092
+ "button",
4093
+ {
4094
+ key: item.key,
4095
+ type: "button",
4096
+ class: clsx("top-bar-item", checkActive(item.active) && "active"),
4097
+ onPointerdown: onClick(item.onRun)
4098
+ },
4099
+ /* @__PURE__ */ vue.h(component.Icon, { icon: item.icon })
4100
+ );
4101
+ }
4102
+ return () => {
4103
+ const view = isReady() ? ctx.get(core.editorViewCtx) : null;
4104
+ const isReadonly = view ? !view.editable : false;
4105
+ if (isReadonly) return null;
4106
+ return /* @__PURE__ */ vue.h("div", { class: "top-bar-inner" }, groupInfo.value.map((group) => {
4107
+ return group.items.map((item) => {
4108
+ if (item.selector) {
4109
+ return renderSelector(item.key, item.selector);
4110
+ }
4111
+ if (!item.onRun) return null;
4112
+ return renderButton(
4113
+ item
4114
+ );
4115
+ });
4116
+ }).reduce((acc, curr, index) => {
4117
+ var _a, _b;
4118
+ if (index === 0) {
4119
+ acc.push(...curr);
4120
+ } else {
4121
+ const groupKey = (_b = (_a = groupInfo.value[index]) == null ? void 0 : _a.key) != null ? _b : index;
4122
+ acc.push(
4123
+ /* @__PURE__ */ vue.h("div", { key: `divider-${groupKey}`, class: "top-bar-divider" }),
4124
+ ...curr
4125
+ );
4126
+ }
4127
+ return acc;
4128
+ }, []));
4129
+ };
4130
+ }
4131
+ });
4132
+
4133
+ var __typeError$1 = (msg) => {
4134
+ throw TypeError(msg);
4135
+ };
4136
+ var __accessCheck$1 = (obj, member, msg) => member.has(obj) || __typeError$1("Cannot " + msg);
4137
+ var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
4138
+ var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
4139
+ var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
4140
+ var _container, _app, _version;
4141
+ const topBarPluginKey = new state.PluginKey("CREPE_TOP_BAR");
4142
+ class TopBarView {
4143
+ constructor(ctx, view, config) {
4144
+ __privateAdd$1(this, _container);
4145
+ __privateAdd$1(this, _app);
4146
+ __privateAdd$1(this, _version);
4147
+ this.update = (view, _prevState) => {
4148
+ __privateGet$1(this, _container).style.display = view.editable ? "" : "none";
4149
+ __privateGet$1(this, _version).value++;
4150
+ };
4151
+ this.destroy = () => {
4152
+ __privateGet$1(this, _app).unmount();
4153
+ __privateGet$1(this, _container).remove();
4154
+ };
4155
+ __privateSet$1(this, _version, vue.ref(0));
4156
+ const container = document.createElement("div");
4157
+ container.className = "milkdown-top-bar";
4158
+ const app = vue.createApp(TopBar, {
4159
+ ctx,
4160
+ config,
4161
+ version: __privateGet$1(this, _version)
4162
+ });
4163
+ app.mount(container);
4164
+ __privateSet$1(this, _container, container);
4165
+ __privateSet$1(this, _app, app);
4166
+ const editorRoot = view.dom.parentElement;
4167
+ if (editorRoot) {
4168
+ editorRoot.insertBefore(container, editorRoot.firstChild);
4169
+ }
4170
+ this.update(view);
4171
+ }
4172
+ }
4173
+ _container = new WeakMap();
4174
+ _app = new WeakMap();
4175
+ _version = new WeakMap();
4176
+ const topBarSlice = utils.$ctx(
4177
+ {
4178
+ view: () => ({
4179
+ update: () => {
4180
+ },
4181
+ destroy: () => {
4182
+ }
4183
+ })
4184
+ },
4185
+ "topBarConfig"
4186
+ );
4187
+ const topBarPlugin = utils.$prose((ctx) => {
4188
+ const config = ctx.get(topBarSlice.key);
4189
+ return new state.Plugin({
4190
+ key: topBarPluginKey,
4191
+ view: config.view
4192
+ });
4193
+ });
4194
+ const topBar = (editor, config) => {
4195
+ editor.config(crepeFeatureConfig(CrepeFeature.TopBar)).config((ctx) => {
4196
+ ctx.set(topBarSlice.key, {
4197
+ view: (view) => new TopBarView(ctx, view, config)
4198
+ });
4199
+ }).use(topBarSlice).use(topBarPlugin);
4200
+ };
4201
+
2343
4202
  function loadFeature(feature, editor, config) {
2344
4203
  switch (feature) {
2345
4204
  case CrepeFeature.CodeMirror: {
@@ -2372,6 +4231,12 @@ function loadFeature(feature, editor, config) {
2372
4231
  case CrepeFeature.Latex: {
2373
4232
  return latex(editor, config);
2374
4233
  }
4234
+ case CrepeFeature.TopBar: {
4235
+ return topBar(editor, config);
4236
+ }
4237
+ case CrepeFeature.AI: {
4238
+ return ai(editor, config);
4239
+ }
2375
4240
  }
2376
4241
  }
2377
4242
 
@@ -2453,7 +4318,29 @@ class CrepeBuilder {
2453
4318
  ...value,
2454
4319
  size: 4
2455
4320
  }));
2456
- }).use(commonmark.commonmark).use(listener.listener).use(history$1.history).use(indent.indent).use(trailing.trailing).use(clipboard.clipboard).use(gfm.gfm));
4321
+ ctx.update(upload.uploadConfig.key, (prev) => ({
4322
+ ...prev,
4323
+ uploader: async (files, schema, ctx2) => {
4324
+ const features = useCrepeFeatures(ctx2).get();
4325
+ const hasImageBlock = features.includes(CrepeFeature.ImageBlock);
4326
+ const nodeType = hasImageBlock ? schema.nodes["image-block"] : schema.nodes["image"];
4327
+ if (!nodeType) return [];
4328
+ const onUpload = hasImageBlock ? ctx2.get(imageBlock$1.imageBlockConfig.key).onUpload : void 0;
4329
+ const images = [];
4330
+ for (let i = 0; i < files.length; i++) {
4331
+ const file = files.item(i);
4332
+ if (file && file.type.includes("image")) images.push(file);
4333
+ }
4334
+ const nodes = await Promise.all(
4335
+ images.map(async (file) => {
4336
+ const src = onUpload ? await onUpload(file) : URL.createObjectURL(file);
4337
+ return nodeType.createAndFill({ src });
4338
+ })
4339
+ );
4340
+ return nodes;
4341
+ }
4342
+ }));
4343
+ }).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));
2457
4344
  }
2458
4345
  /// Get the milkdown editor instance.
2459
4346
  get editor() {