@ecsplico/editor 3.6.0 → 4.0.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 (578) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/dist/adapters/direct-ai.d.ts +4 -4
  3. package/dist/adapters/direct-ai.js +2 -2
  4. package/dist/adapters/direct-ai.js.map +1 -1
  5. package/dist/adapters/document-state.d.ts +1 -1
  6. package/dist/adapters/document-state.js.map +1 -1
  7. package/dist/adapters/forge.d.ts +2 -2
  8. package/dist/adapters/forge.js.map +1 -1
  9. package/dist/adapters/nitro.d.ts +11 -3
  10. package/dist/adapters/nitro.js +3 -1
  11. package/dist/adapters/nitro.js.map +1 -1
  12. package/dist/adapters/shared.d.ts +6 -6
  13. package/dist/adapters/shared.js.map +1 -1
  14. package/dist/config/index.d.ts +14 -14
  15. package/dist/config/index.js +8 -8
  16. package/dist/config/index.js.map +1 -1
  17. package/dist/core/backend-types.d.ts +3 -3
  18. package/dist/core/backend-types.js.map +1 -1
  19. package/dist/core/backend.d.ts +4 -4
  20. package/dist/core/backend.js.map +1 -1
  21. package/dist/core/block-convert.d.ts +1 -1
  22. package/dist/core/block-convert.js +5 -5
  23. package/dist/core/block-convert.js.map +1 -1
  24. package/dist/core/block-transfer.d.ts +8 -4
  25. package/dist/core/block-transfer.js +23 -14
  26. package/dist/core/block-transfer.js.map +1 -1
  27. package/dist/core/capabilities.d.ts +113 -0
  28. package/dist/core/capabilities.js +155 -0
  29. package/dist/core/capabilities.js.map +1 -0
  30. package/dist/core/command-types.d.ts +1 -1
  31. package/dist/core/context.js.map +1 -1
  32. package/dist/core/convert.d.ts +5 -5
  33. package/dist/core/convert.js +5 -5
  34. package/dist/core/convert.js.map +1 -1
  35. package/dist/core/core-feature.js +1 -1
  36. package/dist/core/define-editor.d.ts +2 -2
  37. package/dist/core/define-editor.js +34 -6
  38. package/dist/core/define-editor.js.map +1 -1
  39. package/dist/core/derivation.d.ts +119 -0
  40. package/dist/core/derivation.js +187 -0
  41. package/dist/core/derivation.js.map +1 -0
  42. package/dist/core/derive.d.ts +61 -0
  43. package/dist/core/derive.js +69 -0
  44. package/dist/core/derive.js.map +1 -0
  45. package/dist/core/extension-points.d.ts +16 -0
  46. package/dist/core/feature-context.d.ts +5 -1
  47. package/dist/core/feature-context.js +10 -3
  48. package/dist/core/feature-context.js.map +1 -1
  49. package/dist/core/feature.d.ts +41 -19
  50. package/dist/core/feature.js.map +1 -1
  51. package/dist/core/fences.js +1 -1
  52. package/dist/core/fences.js.map +1 -1
  53. package/dist/core/index.d.ts +6 -2
  54. package/dist/core/index.js +5 -1
  55. package/dist/core/pipeline.d.ts +14 -5
  56. package/dist/core/pipeline.js +19 -7
  57. package/dist/core/pipeline.js.map +1 -1
  58. package/dist/core/properties.d.ts +22 -0
  59. package/dist/core/properties.js +17 -0
  60. package/dist/core/properties.js.map +1 -0
  61. package/dist/core/schema/block-ids.js +5 -5
  62. package/dist/core/schema/block-ids.js.map +1 -1
  63. package/dist/core/schema/index.d.ts +2 -1
  64. package/dist/core/schema/index.js +2 -1
  65. package/dist/core/schema/index.js.map +1 -1
  66. package/dist/core/schema/opaque-fence.d.ts +4 -4
  67. package/dist/core/schema/opaque-fence.js +7 -7
  68. package/dist/core/schema/opaque-fence.js.map +1 -1
  69. package/dist/core/schema/persisted-names.d.ts +58 -0
  70. package/dist/core/schema/persisted-names.js +96 -0
  71. package/dist/core/schema/persisted-names.js.map +1 -0
  72. package/dist/core/toolbar-items.js +1 -1
  73. package/dist/core/toolbar-items.js.map +1 -1
  74. package/dist/core/util.js +5 -1
  75. package/dist/core/util.js.map +1 -1
  76. package/dist/features/ai/agent-ops.js +1 -1
  77. package/dist/features/ai/ai-review.js +1 -1
  78. package/dist/features/ai/assistant.d.ts +4 -4
  79. package/dist/features/ai/assistant.js +1 -1
  80. package/dist/features/ai/assistant.js.map +1 -1
  81. package/dist/features/ai/components/AiSelectionMenu.js +1 -1
  82. package/dist/features/ai/components/AiSelectionMenu.js.map +1 -1
  83. package/dist/features/ai/components/ModelQuickSwitch.js +7 -7
  84. package/dist/features/ai/components/ModelQuickSwitch.js.map +1 -1
  85. package/dist/features/ai/components/ModelQuickSwitch.vue.d.ts +4 -4
  86. package/dist/features/ai/components/SettingsAiTab.js +8 -8
  87. package/dist/features/ai/components/SettingsAiTab.js.map +1 -1
  88. package/dist/features/ai/components/SettingsModelProfiles.js +1 -1
  89. package/dist/features/ai/components/SettingsModelProfiles.js.map +1 -1
  90. package/dist/features/ai/document-chat-model.d.ts +2 -2
  91. package/dist/features/ai/document-chat-model.js +5 -5
  92. package/dist/features/ai/document-chat-model.js.map +1 -1
  93. package/dist/features/ai/document-chat.js +2 -2
  94. package/dist/features/ai/document-chat.js.map +1 -1
  95. package/dist/features/ai/feature.d.ts +2 -2
  96. package/dist/features/ai/feature.js +2 -2
  97. package/dist/features/ai/feature.js.map +1 -1
  98. package/dist/features/ai/ghost-autocomplete.d.ts +4 -4
  99. package/dist/features/ai/ghost-autocomplete.js +1 -1
  100. package/dist/features/ai/ghost-autocomplete.js.map +1 -1
  101. package/dist/features/ai/index.d.ts +3 -3
  102. package/dist/features/ai/index.js +2 -2
  103. package/dist/features/ai/model-profiles.d.ts +9 -9
  104. package/dist/features/ai/model-profiles.js +13 -13
  105. package/dist/features/ai/model-profiles.js.map +1 -1
  106. package/dist/features/ai/protocol/agent-ops.d.ts +2 -2
  107. package/dist/features/ai/protocol/agent-ops.js +1 -1
  108. package/dist/features/ai/protocol/agent-ops.js.map +1 -1
  109. package/dist/features/ai/protocol/block-lines.d.ts +7 -7
  110. package/dist/features/ai/protocol/block-lines.js +10 -10
  111. package/dist/features/ai/protocol/block-lines.js.map +1 -1
  112. package/dist/features/ai/protocol/chat.d.ts +5 -5
  113. package/dist/features/ai/protocol/chat.js +12 -12
  114. package/dist/features/ai/protocol/chat.js.map +1 -1
  115. package/dist/features/ai/protocol/generate.d.ts +1 -1
  116. package/dist/features/ai/protocol/generate.js +1 -1
  117. package/dist/features/ai/protocol/generate.js.map +1 -1
  118. package/dist/features/ai/protocol/index.d.ts +3 -3
  119. package/dist/features/ai/protocol/index.js +2 -2
  120. package/dist/features/ai/protocol/models.d.ts +3 -3
  121. package/dist/features/ai/protocol/models.js +3 -3
  122. package/dist/features/ai/protocol/models.js.map +1 -1
  123. package/dist/features/ai/protocol/schemas.d.ts +1 -1
  124. package/dist/features/ai/protocol/schemas.js +1 -1
  125. package/dist/features/ai/protocol/schemas.js.map +1 -1
  126. package/dist/features/ai/protocol/tasks.d.ts +5 -5
  127. package/dist/features/ai/protocol/tasks.js +12 -12
  128. package/dist/features/ai/protocol/tasks.js.map +1 -1
  129. package/dist/features/ai/react/AiSelectionMenu.js.map +1 -1
  130. package/dist/features/ai/react/ModelQuickSwitch.d.ts +4 -4
  131. package/dist/features/ai/react/ModelQuickSwitch.js +6 -6
  132. package/dist/features/ai/react/ModelQuickSwitch.js.map +1 -1
  133. package/dist/features/ai/react/SettingsAiTab.d.ts +1 -1
  134. package/dist/features/ai/react/SettingsAiTab.js +8 -8
  135. package/dist/features/ai/react/SettingsAiTab.js.map +1 -1
  136. package/dist/features/ai/react/SettingsModelProfiles.d.ts +1 -1
  137. package/dist/features/ai/react/SettingsModelProfiles.js +1 -1
  138. package/dist/features/ai/react/SettingsModelProfiles.js.map +1 -1
  139. package/dist/features/ai/react/use-ai-assistant.d.ts +1 -1
  140. package/dist/features/ai/react/use-ai-assistant.js +1 -1
  141. package/dist/features/ai/react/use-ai-assistant.js.map +1 -1
  142. package/dist/features/ai/react/use-model-profiles.d.ts +5 -5
  143. package/dist/features/ai/react/use-model-profiles.js +2 -2
  144. package/dist/features/ai/react/use-model-profiles.js.map +1 -1
  145. package/dist/features/ai/use-ai-assistant.d.ts +1 -1
  146. package/dist/features/ai/use-ai-assistant.js +1 -1
  147. package/dist/features/ai/use-ai-assistant.js.map +1 -1
  148. package/dist/features/ai/use-model-profiles.d.ts +4 -4
  149. package/dist/features/ai/use-model-profiles.js +2 -2
  150. package/dist/features/ai/use-model-profiles.js.map +1 -1
  151. package/dist/features/block-ui/block-actions.d.ts +8 -4
  152. package/dist/features/block-ui/block-actions.js +38 -22
  153. package/dist/features/block-ui/block-actions.js.map +1 -1
  154. package/dist/features/block-ui/block-target.d.ts +29 -0
  155. package/dist/features/block-ui/block-target.js +63 -0
  156. package/dist/features/block-ui/block-target.js.map +1 -0
  157. package/dist/features/block-ui/components/BlockHandles.js +3 -3
  158. package/dist/features/block-ui/components/BlockHandles.js.map +1 -1
  159. package/dist/features/block-ui/components/BlockUi.js +11 -23
  160. package/dist/features/block-ui/components/BlockUi.js.map +1 -1
  161. package/dist/features/block-ui/feature.d.ts +3 -2
  162. package/dist/features/block-ui/feature.js +3 -2
  163. package/dist/features/block-ui/feature.js.map +1 -1
  164. package/dist/features/block-ui/handle-geometry.js +12 -23
  165. package/dist/features/block-ui/handle-geometry.js.map +1 -1
  166. package/dist/features/block-ui/index.d.ts +2 -1
  167. package/dist/features/block-ui/index.js +2 -1
  168. package/dist/features/block-ui/react/BlockHandles.d.ts +1 -1
  169. package/dist/features/block-ui/react/BlockHandles.js +4 -4
  170. package/dist/features/block-ui/react/BlockHandles.js.map +1 -1
  171. package/dist/features/block-ui/react/BlockUi.js +13 -25
  172. package/dist/features/block-ui/react/BlockUi.js.map +1 -1
  173. package/dist/features/comments/model.js +1 -1
  174. package/dist/features/composites/accepted-children.d.ts +5 -4
  175. package/dist/features/composites/accepted-children.js +26 -26
  176. package/dist/features/composites/accepted-children.js.map +1 -1
  177. package/dist/features/composites/ai-brief.d.ts +4 -4
  178. package/dist/features/composites/ai-brief.js +14 -12
  179. package/dist/features/composites/ai-brief.js.map +1 -1
  180. package/dist/features/composites/anchors.d.ts +1 -1
  181. package/dist/features/composites/anchors.js.map +1 -1
  182. package/dist/features/composites/baskets.d.ts +1 -1
  183. package/dist/features/composites/baskets.js.map +1 -1
  184. package/dist/features/composites/bibliography-command.d.ts +1 -1
  185. package/dist/features/composites/bibliography-form.js +1 -1
  186. package/dist/features/composites/bibliography-form.js.map +1 -1
  187. package/dist/features/composites/bibliography.js.map +1 -1
  188. package/dist/features/composites/block-types-json.d.ts +38 -0
  189. package/dist/features/composites/block-types-json.js +122 -0
  190. package/dist/features/composites/block-types-json.js.map +1 -0
  191. package/dist/features/composites/block-types.d.ts +119 -0
  192. package/dist/features/composites/block-types.js +343 -0
  193. package/dist/features/composites/block-types.js.map +1 -0
  194. package/dist/features/composites/capabilities.js +109 -0
  195. package/dist/features/composites/capabilities.js.map +1 -0
  196. package/dist/features/composites/components/BibliographyEditor.js +5 -5
  197. package/dist/features/composites/components/BibliographyEditor.js.map +1 -1
  198. package/dist/features/composites/components/CompositeBasketMenu.js +2 -2
  199. package/dist/features/composites/components/CompositeBasketMenu.js.map +1 -1
  200. package/dist/features/composites/components/CompositeChrome.js +18 -8
  201. package/dist/features/composites/components/CompositeChrome.js.map +1 -1
  202. package/dist/features/composites/components/CompositeChrome.vue.d.ts +1 -1
  203. package/dist/features/composites/components/CompositeDetails.js +11 -10
  204. package/dist/features/composites/components/CompositeDetails.js.map +1 -1
  205. package/dist/features/composites/components/CompositeDetails.vue.d.ts +1 -1
  206. package/dist/features/composites/components/CompositeFieldEditor.js +7 -7
  207. package/dist/features/composites/components/CompositeFieldEditor.js.map +1 -1
  208. package/dist/features/composites/components/CompositeFieldEditor.vue.d.ts +5 -5
  209. package/dist/features/composites/components/CompositeInspector.js +136 -113
  210. package/dist/features/composites/components/CompositeInspector.js.map +1 -1
  211. package/dist/features/composites/components/CompositeInspector.vue.d.ts +3 -3
  212. package/dist/features/composites/components/CompositeStatusMenu.js +2 -2
  213. package/dist/features/composites/components/CompositeStatusMenu.js.map +1 -1
  214. package/dist/features/composites/components/CompositeSummaryEditor.js +1 -1
  215. package/dist/features/composites/components/CompositeSummaryEditor.js.map +1 -1
  216. package/dist/features/composites/components/CompositeSummaryEditor.vue.d.ts +1 -1
  217. package/dist/features/composites/components/CompositeTable.js +2 -2
  218. package/dist/features/composites/components/CompositeTable.js.map +1 -1
  219. package/dist/features/composites/components/CompositeTagsEditor.js +1 -1
  220. package/dist/features/composites/components/CompositeTagsEditor.js.map +1 -1
  221. package/dist/features/composites/components/CompositeTagsEditor.vue.d.ts +1 -1
  222. package/dist/features/composites/components/CompositeView.js +19 -17
  223. package/dist/features/composites/components/CompositeView.js.map +1 -1
  224. package/dist/features/composites/components/DerivationBadge.js +15 -6
  225. package/dist/features/composites/components/DerivationBadge.js.map +1 -1
  226. package/dist/features/composites/components/FocusChip.js +1 -1
  227. package/dist/features/composites/components/FocusChip.js.map +1 -1
  228. package/dist/features/composites/components/FocusChip.vue.d.ts +1 -1
  229. package/dist/features/composites/components/ReferenceFieldSelect.js +3 -3
  230. package/dist/features/composites/components/ReferenceFieldSelect.js.map +1 -1
  231. package/dist/features/composites/components/ReferenceView.js +1 -1
  232. package/dist/features/composites/components/ReferenceView.js.map +1 -1
  233. package/dist/features/composites/components/SettingsEditingTab.js +18 -18
  234. package/dist/features/composites/components/SettingsEditingTab.js.map +1 -1
  235. package/dist/features/composites/components/SettingsEditingTab.vue.d.ts +3 -3
  236. package/dist/features/composites/convert.d.ts +4 -4
  237. package/dist/features/composites/convert.js +27 -28
  238. package/dist/features/composites/convert.js.map +1 -1
  239. package/dist/features/composites/derived-chrome.js +34 -28
  240. package/dist/features/composites/derived-chrome.js.map +1 -1
  241. package/dist/features/composites/editing-settings-keys.js +6 -6
  242. package/dist/features/composites/editing-settings-keys.js.map +1 -1
  243. package/dist/features/composites/feature.d.ts +10 -10
  244. package/dist/features/composites/feature.js +58 -46
  245. package/dist/features/composites/feature.js.map +1 -1
  246. package/dist/features/composites/fences.d.ts +3 -3
  247. package/dist/features/composites/fences.js +18 -13
  248. package/dist/features/composites/fences.js.map +1 -1
  249. package/dist/features/composites/focus.d.ts +10 -10
  250. package/dist/features/composites/focus.js +11 -11
  251. package/dist/features/composites/focus.js.map +1 -1
  252. package/dist/features/composites/heading-composites.d.ts +5 -5
  253. package/dist/features/composites/heading-composites.js +13 -16
  254. package/dist/features/composites/heading-composites.js.map +1 -1
  255. package/dist/features/composites/index.d.ts +20 -18
  256. package/dist/features/composites/index.js +9 -7
  257. package/dist/features/composites/inspector-model.d.ts +45 -22
  258. package/dist/features/composites/inspector-model.js +53 -14
  259. package/dist/features/composites/inspector-model.js.map +1 -1
  260. package/dist/features/composites/legacy.d.ts +5 -4
  261. package/dist/features/composites/legacy.js +16 -23
  262. package/dist/features/composites/legacy.js.map +1 -1
  263. package/dist/features/composites/markdown-export.js +3 -3
  264. package/dist/features/composites/markdown-export.js.map +1 -1
  265. package/dist/features/composites/merge.d.ts +8 -8
  266. package/dist/features/composites/merge.js +23 -22
  267. package/dist/features/composites/merge.js.map +1 -1
  268. package/dist/features/composites/meta-display.js +5 -5
  269. package/dist/features/composites/meta-display.js.map +1 -1
  270. package/dist/features/composites/meta-keys.d.ts +5 -5
  271. package/dist/features/composites/meta-keys.js +8 -8
  272. package/dist/features/composites/meta-keys.js.map +1 -1
  273. package/dist/features/composites/node-views.d.ts +3 -3
  274. package/dist/features/composites/node-views.js +2 -2
  275. package/dist/features/composites/node-views.js.map +1 -1
  276. package/dist/features/composites/nodes.d.ts +13 -13
  277. package/dist/features/composites/nodes.js +100 -77
  278. package/dist/features/composites/nodes.js.map +1 -1
  279. package/dist/features/composites/outline.d.ts +15 -12
  280. package/dist/features/composites/outline.js +24 -21
  281. package/dist/features/composites/outline.js.map +1 -1
  282. package/dist/features/composites/properties.d.ts +51 -0
  283. package/dist/features/composites/properties.js +89 -0
  284. package/dist/features/composites/properties.js.map +1 -0
  285. package/dist/features/composites/react/BibliographyEditor.js +5 -5
  286. package/dist/features/composites/react/BibliographyEditor.js.map +1 -1
  287. package/dist/features/composites/react/CompositeBasketMenu.js +2 -2
  288. package/dist/features/composites/react/CompositeBasketMenu.js.map +1 -1
  289. package/dist/features/composites/react/CompositeChrome.d.ts +1 -1
  290. package/dist/features/composites/react/CompositeChrome.js +15 -6
  291. package/dist/features/composites/react/CompositeChrome.js.map +1 -1
  292. package/dist/features/composites/react/CompositeDetails.d.ts +1 -1
  293. package/dist/features/composites/react/CompositeDetails.js +11 -10
  294. package/dist/features/composites/react/CompositeDetails.js.map +1 -1
  295. package/dist/features/composites/react/CompositeFieldEditor.d.ts +5 -5
  296. package/dist/features/composites/react/CompositeFieldEditor.js +6 -6
  297. package/dist/features/composites/react/CompositeFieldEditor.js.map +1 -1
  298. package/dist/features/composites/react/CompositeInspector.d.ts +3 -3
  299. package/dist/features/composites/react/CompositeInspector.js +142 -128
  300. package/dist/features/composites/react/CompositeInspector.js.map +1 -1
  301. package/dist/features/composites/react/CompositeStatusMenu.js +2 -2
  302. package/dist/features/composites/react/CompositeStatusMenu.js.map +1 -1
  303. package/dist/features/composites/react/CompositeSummaryEditor.d.ts +1 -1
  304. package/dist/features/composites/react/CompositeSummaryEditor.js +1 -1
  305. package/dist/features/composites/react/CompositeSummaryEditor.js.map +1 -1
  306. package/dist/features/composites/react/CompositeTable.d.ts +1 -1
  307. package/dist/features/composites/react/CompositeTable.js +3 -3
  308. package/dist/features/composites/react/CompositeTable.js.map +1 -1
  309. package/dist/features/composites/react/CompositeTagsEditor.d.ts +1 -1
  310. package/dist/features/composites/react/CompositeTagsEditor.js +1 -1
  311. package/dist/features/composites/react/CompositeTagsEditor.js.map +1 -1
  312. package/dist/features/composites/react/CompositeView.js +17 -15
  313. package/dist/features/composites/react/CompositeView.js.map +1 -1
  314. package/dist/features/composites/react/DerivationBadge.js +13 -4
  315. package/dist/features/composites/react/DerivationBadge.js.map +1 -1
  316. package/dist/features/composites/react/FocusChip.d.ts +1 -1
  317. package/dist/features/composites/react/FocusChip.js +1 -1
  318. package/dist/features/composites/react/FocusChip.js.map +1 -1
  319. package/dist/features/composites/react/ReferenceFieldSelect.js +3 -3
  320. package/dist/features/composites/react/ReferenceFieldSelect.js.map +1 -1
  321. package/dist/features/composites/react/ReferenceView.d.ts +1 -1
  322. package/dist/features/composites/react/ReferenceView.js +1 -1
  323. package/dist/features/composites/react/ReferenceView.js.map +1 -1
  324. package/dist/features/composites/react/SettingsEditingTab.d.ts +4 -4
  325. package/dist/features/composites/react/SettingsEditingTab.js +20 -20
  326. package/dist/features/composites/react/SettingsEditingTab.js.map +1 -1
  327. package/dist/features/composites/react.js +1 -1
  328. package/dist/features/composites/react.js.map +1 -1
  329. package/dist/features/composites/reference-ai.js +1 -1
  330. package/dist/features/composites/reference-ai.js.map +1 -1
  331. package/dist/features/composites/reference-label.d.ts +3 -3
  332. package/dist/features/composites/reference-label.js +6 -6
  333. package/dist/features/composites/reference-label.js.map +1 -1
  334. package/dist/features/composites/reference-suggestion.d.ts +1 -1
  335. package/dist/features/composites/reference-suggestion.js +3 -3
  336. package/dist/features/composites/reference-suggestion.js.map +1 -1
  337. package/dist/features/composites/reference-text.d.ts +2 -2
  338. package/dist/features/composites/reference-text.js +4 -4
  339. package/dist/features/composites/reference-text.js.map +1 -1
  340. package/dist/features/composites/reference.d.ts +3 -3
  341. package/dist/features/composites/reference.js +1 -1
  342. package/dist/features/composites/reference.js.map +1 -1
  343. package/dist/features/composites/reveal-source.d.ts +3 -3
  344. package/dist/features/composites/reveal-source.js +6 -6
  345. package/dist/features/composites/reveal-source.js.map +1 -1
  346. package/dist/features/composites/rows-model.d.ts +2 -2
  347. package/dist/features/composites/rows-model.js +4 -3
  348. package/dist/features/composites/rows-model.js.map +1 -1
  349. package/dist/features/composites/rows.d.ts +16 -28
  350. package/dist/features/composites/rows.js +20 -54
  351. package/dist/features/composites/rows.js.map +1 -1
  352. package/dist/features/composites/schema.d.ts +12 -11
  353. package/dist/features/composites/schema.js +10 -9
  354. package/dist/features/composites/schema.js.map +1 -1
  355. package/dist/features/composites/source.d.ts +20 -0
  356. package/dist/features/composites/source.js +40 -0
  357. package/dist/features/composites/source.js.map +1 -0
  358. package/dist/features/composites/split.d.ts +11 -11
  359. package/dist/features/composites/split.js +20 -20
  360. package/dist/features/composites/split.js.map +1 -1
  361. package/dist/features/composites/structure-mode.js +3 -3
  362. package/dist/features/composites/structure-mode.js.map +1 -1
  363. package/dist/features/composites/table-model.js +2 -2
  364. package/dist/features/composites/table-model.js.map +1 -1
  365. package/dist/features/composites/use-composite-inspector.js +3 -1
  366. package/dist/features/composites/use-composite-inspector.js.map +1 -1
  367. package/dist/features/composites/use-composite-rows.d.ts +2 -2
  368. package/dist/features/composites/use-composite-rows.js.map +1 -1
  369. package/dist/features/composites/vue.js +1 -1
  370. package/dist/features/composites/vue.js.map +1 -1
  371. package/dist/features/image-studio/components/ImageStudioDialog.js +1 -1
  372. package/dist/features/image-studio/components/ImageStudioDialog.js.map +1 -1
  373. package/dist/features/image-studio/components/ImageStudioDialog.vue.d.ts +1 -1
  374. package/dist/features/image-studio/components/ImageStudioView.js.map +1 -1
  375. package/dist/features/image-studio/feature.d.ts +1 -1
  376. package/dist/features/image-studio/feature.js +1 -1
  377. package/dist/features/image-studio/feature.js.map +1 -1
  378. package/dist/features/image-studio/node-core.d.ts +3 -3
  379. package/dist/features/image-studio/node-core.js +1 -1
  380. package/dist/features/image-studio/node-core.js.map +1 -1
  381. package/dist/features/image-studio/node-store.d.ts +1 -1
  382. package/dist/features/image-studio/node-store.js +1 -1
  383. package/dist/features/image-studio/node-store.js.map +1 -1
  384. package/dist/features/image-studio/react/ImageStudioDialog.d.ts +1 -1
  385. package/dist/features/image-studio/react/ImageStudioDialog.js +1 -1
  386. package/dist/features/image-studio/react/ImageStudioDialog.js.map +1 -1
  387. package/dist/features/image-studio/react/ImageStudioView.js +1 -1
  388. package/dist/features/image-studio/react/ImageStudioView.js.map +1 -1
  389. package/dist/features/image-studio/react/store.d.ts +3 -3
  390. package/dist/features/image-studio/react/store.js.map +1 -1
  391. package/dist/features/image-studio/react.d.ts +1 -1
  392. package/dist/features/image-studio/react.js +1 -1
  393. package/dist/features/image-studio/react.js.map +1 -1
  394. package/dist/features/image-studio/schema.d.ts +1 -1
  395. package/dist/features/image-studio/schema.js +1 -1
  396. package/dist/features/image-studio/schema.js.map +1 -1
  397. package/dist/features/image-studio/state.d.ts +3 -3
  398. package/dist/features/image-studio/state.js +2 -2
  399. package/dist/features/image-studio/state.js.map +1 -1
  400. package/dist/features/image-studio/store.d.ts +3 -3
  401. package/dist/features/image-studio/vue.d.ts +1 -1
  402. package/dist/features/image-studio/vue.js +1 -1
  403. package/dist/features/image-studio/vue.js.map +1 -1
  404. package/dist/features/media/index.js +1 -1
  405. package/dist/features/media/react/AudioRecorderModal.js +1 -1
  406. package/dist/features/media/react.js +1 -1
  407. package/dist/features/mentions/tag.js +2 -1
  408. package/dist/features/mentions/tag.js.map +1 -1
  409. package/dist/features/themes/components/SettingsAppearanceTab.js +1 -1
  410. package/dist/features/themes/components/SettingsAppearanceTab.js.map +1 -1
  411. package/dist/features/themes/feature.d.ts +1 -1
  412. package/dist/features/themes/feature.js.map +1 -1
  413. package/dist/features/themes/react/SettingsAppearanceTab.d.ts +1 -1
  414. package/dist/features/themes/react/SettingsAppearanceTab.js +1 -1
  415. package/dist/features/themes/react/SettingsAppearanceTab.js.map +1 -1
  416. package/dist/features/themes/theme-runtime.js +1 -1
  417. package/dist/features/themes/theme-runtime.js.map +1 -1
  418. package/dist/features/transcript/TranscriptSegmentView.js +1 -1
  419. package/dist/features/transcript/TranscriptSegmentView.js.map +1 -1
  420. package/dist/features/transcript/react/TranscriptSegmentView.js +1 -1
  421. package/dist/features/transcript/react/TranscriptSegmentView.js.map +1 -1
  422. package/dist/features/transcript/segment-node.js.map +1 -1
  423. package/dist/features/transfer/feature.js +1 -1
  424. package/dist/features/transfer/feature.js.map +1 -1
  425. package/dist/features/transfer/transforms.d.ts +4 -4
  426. package/dist/features/transfer/transforms.js +12 -12
  427. package/dist/features/transfer/transforms.js.map +1 -1
  428. package/dist/i18n/de/ai.js +4 -4
  429. package/dist/i18n/de/ai.js.map +1 -1
  430. package/dist/i18n/de/authors.js +1 -1
  431. package/dist/i18n/de/authors.js.map +1 -1
  432. package/dist/i18n/de/comments.js +1 -1
  433. package/dist/i18n/de/comments.js.map +1 -1
  434. package/dist/i18n/de/composites.js +62 -59
  435. package/dist/i18n/de/composites.js.map +1 -1
  436. package/dist/i18n/de/image-studio.js +2 -2
  437. package/dist/i18n/de/image-studio.js.map +1 -1
  438. package/dist/i18n/de/integrations.js +20 -20
  439. package/dist/i18n/de/integrations.js.map +1 -1
  440. package/dist/i18n/de/markdown.js +1 -1
  441. package/dist/i18n/de/markdown.js.map +1 -1
  442. package/dist/i18n/de/palette.js +1 -1
  443. package/dist/i18n/de/palette.js.map +1 -1
  444. package/dist/i18n/de/themes.js +3 -3
  445. package/dist/i18n/de/themes.js.map +1 -1
  446. package/dist/i18n/de/transfer.js +2 -2
  447. package/dist/i18n/de/transfer.js.map +1 -1
  448. package/dist/i18n/de/tree.js +6 -6
  449. package/dist/i18n/de/tree.js.map +1 -1
  450. package/dist/i18n/de.d.ts +101 -98
  451. package/dist/i18n/en/ai.js +2 -2
  452. package/dist/i18n/en/ai.js.map +1 -1
  453. package/dist/i18n/en/composites.js +64 -61
  454. package/dist/i18n/en/composites.js.map +1 -1
  455. package/dist/i18n/en/integrations.js +9 -9
  456. package/dist/i18n/en/integrations.js.map +1 -1
  457. package/dist/i18n/en/markdown.js +1 -1
  458. package/dist/i18n/en/markdown.js.map +1 -1
  459. package/dist/i18n/en/palette.js +1 -1
  460. package/dist/i18n/en/palette.js.map +1 -1
  461. package/dist/i18n/en/themes.js +4 -4
  462. package/dist/i18n/en/themes.js.map +1 -1
  463. package/dist/i18n/en/tree.js +5 -5
  464. package/dist/i18n/en/tree.js.map +1 -1
  465. package/dist/index.d.ts +4 -1
  466. package/dist/integrations/composite-ai/bibliography-fetch.d.ts +6 -6
  467. package/dist/integrations/composite-ai/bibliography-fetch.js +19 -19
  468. package/dist/integrations/composite-ai/bibliography-fetch.js.map +1 -1
  469. package/dist/integrations/composite-ai/composite-fill.d.ts +4 -4
  470. package/dist/integrations/composite-ai/composite-fill.js +5 -5
  471. package/dist/integrations/composite-ai/composite-fill.js.map +1 -1
  472. package/dist/integrations/composite-ai/composite-summary.d.ts +2 -2
  473. package/dist/integrations/composite-ai/composite-summary.js +5 -5
  474. package/dist/integrations/composite-ai/composite-summary.js.map +1 -1
  475. package/dist/integrations/composite-ai/derive.d.ts +17 -17
  476. package/dist/integrations/composite-ai/derive.js +27 -26
  477. package/dist/integrations/composite-ai/derive.js.map +1 -1
  478. package/dist/integrations/composite-ai/index.d.ts +14 -15
  479. package/dist/integrations/composite-ai/index.js +98 -77
  480. package/dist/integrations/composite-ai/index.js.map +1 -1
  481. package/dist/integrations/composite-ai/outline-sanitize.d.ts +1 -1
  482. package/dist/integrations/composite-ai/outline-sanitize.js +1 -1
  483. package/dist/integrations/composite-ai/outline-sanitize.js.map +1 -1
  484. package/dist/integrations/composite-ai/rendition.d.ts +9 -9
  485. package/dist/integrations/composite-ai/rendition.js +27 -27
  486. package/dist/integrations/composite-ai/rendition.js.map +1 -1
  487. package/dist/integrations/composite-ai/split.d.ts +8 -8
  488. package/dist/integrations/composite-ai/split.js +12 -12
  489. package/dist/integrations/composite-ai/split.js.map +1 -1
  490. package/dist/integrations/composite-ai/transfer-transforms.d.ts +2 -2
  491. package/dist/integrations/composite-ai/transfer-transforms.js +12 -12
  492. package/dist/integrations/composite-ai/transfer-transforms.js.map +1 -1
  493. package/dist/integrations/composite-media/index.d.ts +4 -3
  494. package/dist/integrations/composite-media/index.js +20 -14
  495. package/dist/integrations/composite-media/index.js.map +1 -1
  496. package/dist/markdown/document.js +1 -1
  497. package/dist/markdown/document.js.map +1 -1
  498. package/dist/nuxt/module.d.ts +30 -24
  499. package/dist/nuxt/module.js.map +1 -1
  500. package/dist/nuxt/runtime/server/plugins/editor-server.js +3 -2
  501. package/dist/nuxt/runtime/server/plugins/editor-server.js.map +1 -1
  502. package/dist/presets/compose.d.ts +6 -6
  503. package/dist/presets/compose.js +8 -5
  504. package/dist/presets/compose.js.map +1 -1
  505. package/dist/react/AdvancedEditor.d.ts +2 -2
  506. package/dist/react/AdvancedEditor.js +1 -1
  507. package/dist/react/AdvancedEditor.js.map +1 -1
  508. package/dist/react/compose.d.ts +1 -1
  509. package/dist/react/compose.js +2 -2
  510. package/dist/react/compose.js.map +1 -1
  511. package/dist/react/composed-surface.d.ts +5 -5
  512. package/dist/react/composed-surface.js +2 -2
  513. package/dist/react/composed-surface.js.map +1 -1
  514. package/dist/server/ai.d.ts +7 -7
  515. package/dist/server/ai.js +1 -1
  516. package/dist/server/ai.js.map +1 -1
  517. package/dist/server/auth.d.ts +1 -1
  518. package/dist/server/collab-state.d.ts +1 -1
  519. package/dist/server/collab-state.js.map +1 -1
  520. package/dist/server/collab.d.ts +4 -4
  521. package/dist/server/collab.js +22 -17
  522. package/dist/server/collab.js.map +1 -1
  523. package/dist/server/handlers/ai.d.ts +7 -4
  524. package/dist/server/handlers/ai.js +13 -17
  525. package/dist/server/handlers/ai.js.map +1 -1
  526. package/dist/server/handlers/context.d.ts +4 -0
  527. package/dist/server/handlers/context.js.map +1 -1
  528. package/dist/server/handlers/editor.d.ts +33 -32
  529. package/dist/server/handlers/editor.js +13 -8
  530. package/dist/server/handlers/editor.js.map +1 -1
  531. package/dist/server/handlers/images.d.ts +1 -1
  532. package/dist/server/handlers/images.js +1 -1
  533. package/dist/server/handlers/images.js.map +1 -1
  534. package/dist/server/host.d.ts +4 -0
  535. package/dist/server/host.js +10 -2
  536. package/dist/server/host.js.map +1 -1
  537. package/dist/server/index.d.ts +3 -3
  538. package/dist/server/ports.d.ts +8 -8
  539. package/dist/server/ports.js.map +1 -1
  540. package/dist/settings/index.d.ts +20 -19
  541. package/dist/settings/index.js +25 -24
  542. package/dist/settings/index.js.map +1 -1
  543. package/dist/settings/migrate.d.ts +18 -0
  544. package/dist/settings/migrate.js +46 -0
  545. package/dist/settings/migrate.js.map +1 -0
  546. package/dist/settings/values.d.ts +12 -12
  547. package/dist/settings/values.js +11 -11
  548. package/dist/settings/values.js.map +1 -1
  549. package/dist/styles/composites.css +10 -10
  550. package/dist/tree/DocumentTree.js +12 -5
  551. package/dist/tree/DocumentTree.js.map +1 -1
  552. package/dist/tree/drop-rules.js +5 -5
  553. package/dist/tree/drop-rules.js.map +1 -1
  554. package/dist/tree/react/DocumentTree.js +14 -5
  555. package/dist/tree/react/DocumentTree.js.map +1 -1
  556. package/dist/tree/tree-host.js +6 -6
  557. package/dist/tree/tree-host.js.map +1 -1
  558. package/dist/tree/tree-items.js +34 -28
  559. package/dist/tree/tree-items.js.map +1 -1
  560. package/dist/tree/tree-model.js +16 -16
  561. package/dist/tree/tree-model.js.map +1 -1
  562. package/dist/tree/tree-rows.js +2 -2
  563. package/dist/tree/tree-rows.js.map +1 -1
  564. package/dist/tree/tree-view-model.d.ts +2 -2
  565. package/dist/tree/tree-view-model.js.map +1 -1
  566. package/dist/vue/AdvancedEditor.js +2 -2
  567. package/dist/vue/AdvancedEditor.js.map +1 -1
  568. package/dist/vue/AdvancedEditor.vue.d.ts +6 -6
  569. package/dist/vue/compose.d.ts +1 -1
  570. package/dist/vue/compose.js +2 -2
  571. package/dist/vue/compose.js.map +1 -1
  572. package/package.json +1 -1
  573. package/dist/features/composites/derivation.d.ts +0 -62
  574. package/dist/features/composites/derivation.js +0 -102
  575. package/dist/features/composites/derivation.js.map +0 -1
  576. package/dist/features/composites/kinds.d.ts +0 -89
  577. package/dist/features/composites/kinds.js +0 -285
  578. package/dist/features/composites/kinds.js.map +0 -1
@@ -1,8 +1,9 @@
1
1
  import { ABILITY } from "../../core/schema/abilities.js";
2
2
  import { blockIdOf, findBlockById } from "../../core/schema/block-ids.js";
3
3
  import { fetchErrorMessage } from "../../core/fetch-error.js";
4
- import { sourceOf } from "../../features/composites/derivation.js";
5
- import { compositeJSON, compositeKindsOf } from "../../features/composites/nodes.js";
4
+ import { importTypeOf } from "../../features/composites/block-types.js";
5
+ import { blockTypesOf, compositeJSON } from "../../features/composites/nodes.js";
6
+ import { sourceOf } from "../../features/composites/source.js";
6
7
  import { acceptFor, mediaKindOf, mediaMime } from "../../features/media/schema.js";
7
8
  import { pickFiles } from "../../features/media/upload.js";
8
9
  import { isTextFile } from "../../features/media/file-import.js";
@@ -12,13 +13,12 @@ function stemOf(name) {
12
13
  const dot = name.lastIndexOf(".");
13
14
  return dot > 0 ? name.slice(0, dot) : name;
14
15
  }
15
- /** The kind an imported `file` becomes: audio and video a `recording`, an image a `figure`, anything else (PDFs, office files, text) a `document`. */
16
+ /** The Block type an imported `file` becomes: the type whose `import` capability takes the file's media (`importTypeOf`); undefined when no Block type takes it. */
16
17
  function importKindOf(editor, file, text) {
17
- const kind = text ? null : mediaKindOf(file.type);
18
- const id = kind === "audio" || kind === "video" ? "recording" : kind === "image" ? "figure" : "document";
19
- return compositeKindsOf(editor).some((k) => k.id === id) ? id : "document";
18
+ const media = text ? null : mediaKindOf(file.type);
19
+ return importTypeOf(blockTypesOf(editor), media);
20
20
  }
21
- /** A composite of kind `kind` titled with the stem of `file`'s name, holding its original name, type, size and import date. */
21
+ /** A Typed block of Block type `kind` titled with the stem of `file`'s name, holding its original name, type, size and import date. */
22
22
  function documentComposite(kind, file, text, body) {
23
23
  const composite = compositeJSON(kind, body);
24
24
  const [title, ...rest] = composite.content;
@@ -26,7 +26,7 @@ function documentComposite(kind, file, text, body) {
26
26
  return {
27
27
  ...composite,
28
28
  attrs: {
29
- kind,
29
+ blockType: kind,
30
30
  meta: {
31
31
  filename: file.name,
32
32
  mimeType: mediaMime(file.type) || (text ? "text/markdown" : "application/octet-stream"),
@@ -49,7 +49,7 @@ function documentComposite(kind, file, text, body) {
49
49
  * block keeps its attributes otherwise, its id included, and so do the composite and every reference to either.
50
50
  */
51
51
  async function replaceSource(editor, composite, ctx) {
52
- const source = sourceOf(composite, compositeKindsOf(editor));
52
+ const source = sourceOf(composite, blockTypesOf(editor));
53
53
  const sourceId = source && blockIdOf(source.node);
54
54
  if (!source || !sourceId) return;
55
55
  const type = source.node.type.name;
@@ -96,7 +96,8 @@ function sourceActions(ctx) {
96
96
  icon: "i-lucide-file-input",
97
97
  ability: ABILITY.media,
98
98
  order: 420,
99
- isVisible: ({ editor, node }) => node.type.name === "composite" && sourceOf(node, compositeKindsOf(editor)) !== null,
99
+ requires: ["source"],
100
+ isVisible: ({ editor, node }) => sourceOf(node, blockTypesOf(editor)) !== null,
100
101
  run: ({ editor, node }) => {
101
102
  replaceSource(editor, node, ctx);
102
103
  }
@@ -107,9 +108,10 @@ function sourceActions(ctx) {
107
108
  *
108
109
  * - **Wrapping:** the `wrapImport` stage puts the blocks of every imported file (parsed text or Markdown, or the
109
110
  * uploaded media or file block; drop, paste, picker and recorder alike) into one composite titled with the
110
- * file's name stem and carrying its filename, type, size and import date as meta. The kind follows the MIME type:
111
- * audio and video become a `recording`, images a `figure`, everything else (PDFs, office files, text) a `document`.
112
- * Without this feature the blocks are inserted as they are.
111
+ * file's name stem and carrying its filename, type, size and import date as meta. The Block type is the one whose
112
+ * `import` capability takes the file's media: by default audio and video become a `recording`, images a `figure`, everything
113
+ * else (PDFs, office files, text) a `document`. Without a Block type that takes the file, or without this feature, the
114
+ * blocks are inserted as they are.
113
115
  * - **Actions:** the `/` command „Datei importieren“ (`datei`, ability `composite`) picks any files and imports them
114
116
  * through `editor.storage.media.importFiles` at the caret; the block action „Quelle ersetzen“ (`source-replace`, on
115
117
  * composites with a source block) uploads a new file into the existing source block, keeping its id.
@@ -122,7 +124,11 @@ function compositeMediaFeature() {
122
124
  id: "composite-media",
123
125
  dimension: "content",
124
126
  requires: ["composites", "media"],
125
- blocks: { wrapImport: (editor, file, blocks) => [documentComposite(importKindOf(editor, file, isTextFile(file)), file, isTextFile(file), blocks)] },
127
+ blocks: { wrapImport: (editor, file, blocks) => {
128
+ const text = isTextFile(file);
129
+ const kind = importKindOf(editor, file, text);
130
+ return kind ? [documentComposite(kind, file, text, blocks)] : blocks;
131
+ } },
126
132
  blockActions: sourceActions,
127
133
  commands: (ctx) => [{
128
134
  id: "datei",
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/integrations/composite-media/index.ts"],"sourcesContent":["import type { Editor, JSONContent } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { type BlockAction, type EditorFeature, type FeatureContext, fetchErrorMessage } from '../../core'\nimport { ABILITY, blockIdOf, findBlockById } from '../../core/schema'\nimport { compositeJSON, compositeKindsOf, sourceOf } from '../../features/composites/schema'\nimport { isTextFile, pickFiles } from '../../features/media'\nimport { acceptFor, type MediaKind, mediaKindOf, mediaMime } from '../../features/media/schema'\n\n/** The file name without its last extension; the whole name when nothing else is left (`.env`). */\nfunction stemOf(name: string): string {\n const dot = name.lastIndexOf('.')\n return dot > 0 ? name.slice(0, dot) : name\n}\n\n/** The kind an imported `file` becomes: audio and video a `recording`, an image a `figure`, anything else (PDFs, office files, text) a `document`. */\nfunction importKindOf(editor: Editor, file: File, text: boolean): string {\n const kind = text ? null : mediaKindOf(file.type)\n const id = kind === 'audio' || kind === 'video' ? 'recording' : kind === 'image' ? 'figure' : 'document'\n return compositeKindsOf(editor).some(k => k.id === id) ? id : 'document'\n}\n\n/** A composite of kind `kind` titled with the stem of `file`'s name, holding its original name, type, size and import date. */\nfunction documentComposite(kind: string, file: File, text: boolean, body: JSONContent[]): JSONContent {\n const composite = compositeJSON(kind, body)\n const [title, ...rest] = composite.content!\n const stem = stemOf(file.name)\n return {\n ...composite,\n attrs: {\n kind,\n meta: {\n filename: file.name,\n mimeType: mediaMime(file.type) || (text ? 'text/markdown' : 'application/octet-stream'),\n size: file.size,\n importedAt: new Date().toISOString().slice(0, 10),\n },\n },\n content: [stem ? { ...title!, content: [{ type: 'text', text: stem }] } : title!, ...rest],\n }\n}\n\n/**\n * Swaps the source file of `composite` in place: picks a file of the source block's media type, uploads it and rewrites\n * `src`, `hash`, `mimeType`, `title` and `size` of the existing source block (those of them its node type has). The\n * block keeps its attributes otherwise, its id included, and so do the composite and every reference to either.\n */\nasync function replaceSource(editor: Editor, composite: PMNode, ctx: FeatureContext): Promise<void> {\n const source = sourceOf(composite, compositeKindsOf(editor))\n const sourceId = source && blockIdOf(source.node)\n if (!source || !sourceId) return\n const type = source.node.type.name\n const [file] = await pickFiles(acceptFor(type as MediaKind), false)\n if (!file || editor.isDestroyed) return\n try {\n if ((mediaKindOf(file.type) ?? 'file') !== type) throw new Error(`${file.type || file.name}: ${type}`)\n const { url, sha256 } = await editor.storage.media.upload(file)\n if (editor.isDestroyed) return\n // The upload takes a while: the source block is found again by its id.\n const target = findBlockById(editor.state.doc, sourceId)\n if (!target) {\n ctx.notify({ title: ctx.t('integrations.sourceReplace.gone'), kind: 'error' })\n return\n }\n const next: Record<string, unknown> = {\n src: url,\n hash: sha256 ?? null,\n mimeType: mediaMime(file.type) || 'application/octet-stream',\n title: file.name,\n size: file.size,\n }\n const attrs: Record<string, unknown> = { ...target.node.attrs }\n for (const [key, value] of Object.entries(next)) if (key in attrs) attrs[key] = value\n editor.view.dispatch(editor.state.tr.setNodeMarkup(target.pos, undefined, attrs))\n ctx.notify({ title: ctx.t('integrations.sourceReplace.done'), kind: 'success' })\n }\n catch (error) {\n ctx.notify({ title: ctx.t('integrations.sourceReplace.failed'), description: fetchErrorMessage(error), kind: 'error' })\n }\n}\n\nfunction sourceActions(ctx: FeatureContext): BlockAction[] {\n return [{\n id: 'source-replace',\n label: ctx.t('integrations.sourceReplace.action'),\n icon: 'i-lucide-file-input',\n ability: ABILITY.media,\n order: 420,\n isVisible: ({ editor, node }) => node.type.name === 'composite' && sourceOf(node, compositeKindsOf(editor)) !== null,\n run: ({ editor, node }) => {\n void replaceSource(editor, node, ctx)\n },\n }]\n}\n\n/**\n * File import into composites. Needs the `composites` and `media` features; neither imports this one.\n *\n * - **Wrapping:** the `wrapImport` stage puts the blocks of every imported file (parsed text or Markdown, or the\n * uploaded media or file block; drop, paste, picker and recorder alike) into one composite titled with the\n * file's name stem and carrying its filename, type, size and import date as meta. The kind follows the MIME type:\n * audio and video become a `recording`, images a `figure`, everything else (PDFs, office files, text) a `document`.\n * Without this feature the blocks are inserted as they are.\n * - **Actions:** the `/` command „Datei importieren“ (`datei`, ability `composite`) picks any files and imports them\n * through `editor.storage.media.importFiles` at the caret; the block action „Quelle ersetzen“ (`source-replace`, on\n * composites with a source block) uploads a new file into the existing source block, keeping its id.\n *\n * Install it anywhere after `composites` and `media`; the `/` entry follows the order of the feature list. Framework-free\n * (`EditorFeature<never>`: no component slots), so one instance serves the Vue and the React surface.\n */\nexport function compositeMediaFeature(): EditorFeature<never> {\n return {\n id: 'composite-media',\n dimension: 'content',\n requires: ['composites', 'media'],\n blocks: { wrapImport: (editor, file, blocks) => [documentComposite(importKindOf(editor, file, isTextFile(file)), file, isTextFile(file), blocks)] },\n blockActions: sourceActions,\n commands: ctx => [{\n id: 'datei',\n slash: {},\n label: ctx.t('integrations.compositeMedia.import'),\n icon: 'i-lucide-file-up',\n ability: ABILITY.composite,\n run: (editor) => {\n const pos = editor.state.selection.from\n void pickFiles('*/*').then((files) => {\n if (files.length && !editor.isDestroyed) return editor.storage.media.importFiles(editor, files, pos)\n })\n },\n }],\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/integrations/composite-media/index.ts"],"sourcesContent":["import type { Editor, JSONContent } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { type BlockAction, type EditorFeature, type FeatureContext, fetchErrorMessage } from '../../core'\nimport { ABILITY, blockIdOf, findBlockById } from '../../core/schema'\nimport { blockTypesOf, compositeJSON, importTypeOf, sourceOf } from '../../features/composites/schema'\nimport { isTextFile, pickFiles } from '../../features/media'\nimport { acceptFor, type MediaKind, mediaKindOf, mediaMime } from '../../features/media/schema'\n\n/** The file name without its last extension; the whole name when nothing else is left (`.env`). */\nfunction stemOf(name: string): string {\n const dot = name.lastIndexOf('.')\n return dot > 0 ? name.slice(0, dot) : name\n}\n\n/** The Block type an imported `file` becomes: the type whose `import` capability takes the file's media (`importTypeOf`); undefined when no Block type takes it. */\nfunction importKindOf(editor: Editor, file: File, text: boolean): string | undefined {\n const media = text ? null : mediaKindOf(file.type)\n return importTypeOf(blockTypesOf(editor), media)\n}\n\n/** A Typed block of Block type `kind` titled with the stem of `file`'s name, holding its original name, type, size and import date. */\nfunction documentComposite(kind: string, file: File, text: boolean, body: JSONContent[]): JSONContent {\n const composite = compositeJSON(kind, body)\n const [title, ...rest] = composite.content!\n const stem = stemOf(file.name)\n return {\n ...composite,\n attrs: {\n blockType: kind,\n meta: {\n filename: file.name,\n mimeType: mediaMime(file.type) || (text ? 'text/markdown' : 'application/octet-stream'),\n size: file.size,\n importedAt: new Date().toISOString().slice(0, 10),\n },\n },\n content: [stem ? { ...title!, content: [{ type: 'text', text: stem }] } : title!, ...rest],\n }\n}\n\n/**\n * Swaps the source file of `composite` in place: picks a file of the source block's media type, uploads it and rewrites\n * `src`, `hash`, `mimeType`, `title` and `size` of the existing source block (those of them its node type has). The\n * block keeps its attributes otherwise, its id included, and so do the composite and every reference to either.\n */\nasync function replaceSource(editor: Editor, composite: PMNode, ctx: FeatureContext): Promise<void> {\n const source = sourceOf(composite, blockTypesOf(editor))\n const sourceId = source && blockIdOf(source.node)\n if (!source || !sourceId) return\n const type = source.node.type.name\n const [file] = await pickFiles(acceptFor(type as MediaKind), false)\n if (!file || editor.isDestroyed) return\n try {\n if ((mediaKindOf(file.type) ?? 'file') !== type) throw new Error(`${file.type || file.name}: ${type}`)\n const { url, sha256 } = await editor.storage.media.upload(file)\n if (editor.isDestroyed) return\n // The upload takes a while: the source block is found again by its id.\n const target = findBlockById(editor.state.doc, sourceId)\n if (!target) {\n ctx.notify({ title: ctx.t('integrations.sourceReplace.gone'), kind: 'error' })\n return\n }\n const next: Record<string, unknown> = {\n src: url,\n hash: sha256 ?? null,\n mimeType: mediaMime(file.type) || 'application/octet-stream',\n title: file.name,\n size: file.size,\n }\n const attrs: Record<string, unknown> = { ...target.node.attrs }\n for (const [key, value] of Object.entries(next)) if (key in attrs) attrs[key] = value\n editor.view.dispatch(editor.state.tr.setNodeMarkup(target.pos, undefined, attrs))\n ctx.notify({ title: ctx.t('integrations.sourceReplace.done'), kind: 'success' })\n }\n catch (error) {\n ctx.notify({ title: ctx.t('integrations.sourceReplace.failed'), description: fetchErrorMessage(error), kind: 'error' })\n }\n}\n\nfunction sourceActions(ctx: FeatureContext): BlockAction[] {\n return [{\n id: 'source-replace',\n label: ctx.t('integrations.sourceReplace.action'),\n icon: 'i-lucide-file-input',\n ability: ABILITY.media,\n order: 420,\n requires: ['source'],\n isVisible: ({ editor, node }) => sourceOf(node, blockTypesOf(editor)) !== null,\n run: ({ editor, node }) => {\n void replaceSource(editor, node, ctx)\n },\n }]\n}\n\n/**\n * File import into composites. Needs the `composites` and `media` features; neither imports this one.\n *\n * - **Wrapping:** the `wrapImport` stage puts the blocks of every imported file (parsed text or Markdown, or the\n * uploaded media or file block; drop, paste, picker and recorder alike) into one composite titled with the\n * file's name stem and carrying its filename, type, size and import date as meta. The Block type is the one whose\n * `import` capability takes the file's media: by default audio and video become a `recording`, images a `figure`, everything\n * else (PDFs, office files, text) a `document`. Without a Block type that takes the file, or without this feature, the\n * blocks are inserted as they are.\n * - **Actions:** the `/` command „Datei importieren“ (`datei`, ability `composite`) picks any files and imports them\n * through `editor.storage.media.importFiles` at the caret; the block action „Quelle ersetzen“ (`source-replace`, on\n * composites with a source block) uploads a new file into the existing source block, keeping its id.\n *\n * Install it anywhere after `composites` and `media`; the `/` entry follows the order of the feature list. Framework-free\n * (`EditorFeature<never>`: no component slots), so one instance serves the Vue and the React surface.\n */\nexport function compositeMediaFeature(): EditorFeature<never> {\n return {\n id: 'composite-media',\n dimension: 'content',\n requires: ['composites', 'media'],\n blocks: {\n wrapImport: (editor, file, blocks) => {\n const text = isTextFile(file)\n const kind = importKindOf(editor, file, text)\n return kind ? [documentComposite(kind, file, text, blocks)] : blocks\n },\n },\n blockActions: sourceActions,\n commands: ctx => [{\n id: 'datei',\n slash: {},\n label: ctx.t('integrations.compositeMedia.import'),\n icon: 'i-lucide-file-up',\n ability: ABILITY.composite,\n run: (editor) => {\n const pos = editor.state.selection.from\n void pickFiles('*/*').then((files) => {\n if (files.length && !editor.isDestroyed) return editor.storage.media.importFiles(editor, files, pos)\n })\n },\n }],\n }\n}\n"],"mappings":"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"}
@@ -76,7 +76,7 @@ function markdownToContent(editor, body, options = {}) {
76
76
  diagnostics.push({
77
77
  code: "unknown-fence",
78
78
  severity: "info",
79
- message: t("markdown.diagnostic.unknownFence", { kind: String(fence.attrs?.kind) }),
79
+ message: t("markdown.diagnostic.unknownFence", { kind: String(fence.attrs?.blockType) }),
80
80
  ...line && { line }
81
81
  });
82
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"document.js","names":[],"sources":["../../src/markdown/document.ts"],"sourcesContent":["import type { Editor, JSONContent } from '@tiptap/core'\nimport { splitFences } from '../core/fences'\nimport { parseBlocks, pipelineOf } from '../core/pipeline'\nimport { EMPTY_EDITOR_CONTENT } from '../core/schema'\nimport { editorEntryOf } from '../core/editor-ui'\nimport { createTranslator, type Translate } from '../i18n'\nimport { enforceUrlPolicy, locate, type MarkdownDiagnostic, type MarkdownPolicy } from './policy'\n\n/** A Markdown body as document JSON, with what the parse dropped or could not understand. */\nexport interface MarkdownContent {\n content: JSONContent\n diagnostics: MarkdownDiagnostic[]\n}\n\n/** The part of `@tiptap/markdown`'s manager the HTML policy swaps out for the duration of one parse. */\ninterface HtmlParsing {\n parseHTMLToken: (token: { raw?: string, text?: string }) => unknown\n}\n\n/**\n * Runs `parse` with raw HTML tokens (block and inline, tags and comments) dropped instead of handed to the schema's\n * `parseHTML` rules, and reports each in `diagnostics`.\n */\nfunction withoutRawHtml<T>(editor: Editor, source: string, diagnostics: MarkdownDiagnostic[], t: Translate, parse: () => T): T {\n const manager = editor.markdown as unknown as HtmlParsing | undefined\n if (!manager) return parse()\n const own = Object.hasOwn(manager, 'parseHTMLToken')\n const original = manager.parseHTMLToken\n let from = 0\n manager.parseHTMLToken = (token) => {\n const html = (token.raw ?? token.text ?? '').trim()\n if (html) {\n const { line, next } = locate(source, html, from)\n from = next\n diagnostics.push({ code: 'raw-html', severity: 'warning', message: t('markdown.diagnostic.rawHtml', { html: JSON.stringify(html.length > 60 ? `${html.slice(0, 57)}…` : html) }), ...(line && { line }) })\n }\n return null\n }\n try {\n return parse()\n }\n finally {\n if (own) manager.parseHTMLToken = original\n else delete (manager as Partial<HtmlParsing>).parseHTMLToken\n }\n}\n\nconst opaqueFences = (node: JSONContent): JSONContent[] => [...(node.type === 'opaqueFence' ? [node] : []), ...(node.content ?? []).flatMap(opaqueFences)]\n\n/**\n * `body` (Markdown without frontmatter) as the document JSON of `editor`, plus `diagnostics`: the preset's block\n * pipeline parses it (`parseBlocks`: Markdown tokens, then the features' normalize and segment stages), the blocks\n * become the children of a `doc`, `policy` is enforced and the preset's `migrateContent` stage runs. An empty body is\n * the empty document (one empty paragraph). Nothing is applied to the editor.\n *\n * The diagnostics' `message` is in the language of `options.t`, by default that of the editor's registered surface, else\n * the default locale.\n *\n * Diagnostics: `raw-html` (dropped unless `policy.allowHtml`), `unsafe-url` (links and media with a scheme other than\n * http(s), mailto and tel are dropped; base64 `data:image` URLs are kept only with `policy.allowDataUrls`),\n * `unknown-fence` (a `:::` fence of a kind no feature registered, kept verbatim as an `opaqueFence`), and the fatal\n * `unclosed-fence` and `invalid-fence-meta` (a fence opener that stayed plain text).\n */\nexport function markdownToContent(editor: Editor, body: string, options: { policy?: MarkdownPolicy, t?: Translate } = {}): MarkdownContent {\n const policy = options.policy ?? {}\n const t = options.t ?? editorEntryOf(editor)?.ctx.t ?? createTranslator()\n const diagnostics: MarkdownDiagnostic[] = []\n\n const { blocks } = policy.allowHtml ? parseBlocks(editor, body) : withoutRawHtml(editor, body, diagnostics, t, () => parseBlocks(editor, body))\n let content: JSONContent = blocks.length ? { type: 'doc', content: blocks } : EMPTY_EDITOR_CONTENT\n content = enforceUrlPolicy(content, policy, body, diagnostics, t)\n if (!content.content?.length) content = EMPTY_EDITOR_CONTENT\n\n for (const problem of splitFences(body).problems) {\n diagnostics.push({\n code: problem.code,\n severity: 'error',\n line: problem.line,\n message: t(problem.code === 'unclosed-fence' ? 'markdown.diagnostic.unclosedFence' : 'markdown.diagnostic.invalidFenceMeta', { kind: problem.kind }),\n })\n }\n let from = 0\n for (const fence of opaqueFences(content)) {\n const raw = String(fence.attrs?.raw ?? '')\n const { line, next } = locate(body, raw, from)\n from = next\n diagnostics.push({ code: 'unknown-fence', severity: 'info', message: t('markdown.diagnostic.unknownFence', { kind: String(fence.attrs?.kind) }), ...(line && { line }) })\n }\n\n return { content: pipelineOf(editor).migrateContent(content), diagnostics }\n}\n\n/**\n * The document of `editor` as Markdown (`editor.getMarkdown()`: the registered Markdown handlers render every node,\n * tables as pipe tables and task items as `- [ ]`/`- [x]`), without trailing line breaks: Tiptap keeps an empty\n * paragraph after a last block that is not a paragraph, and it is not content. Callers that write files add their own\n * final line break.\n */\nexport function contentToMarkdown(editor: Editor): string {\n return editor.getMarkdown().replace(/\\n+$/, '')\n}\n"],"mappings":";;;;;;;;;;;AAuBA,SAAS,eAAkB,QAAgB,QAAgB,aAAmC,GAAc,OAAmB;CAC7H,MAAM,UAAU,OAAO;CACvB,IAAI,CAAC,SAAS,OAAO,MAAM;CAC3B,MAAM,MAAM,OAAO,OAAO,SAAS,gBAAgB;CACnD,MAAM,WAAW,QAAQ;CACzB,IAAI,OAAO;CACX,QAAQ,kBAAkB,UAAU;EAClC,MAAM,QAAQ,MAAM,OAAO,MAAM,QAAQ,GAAA,CAAI,KAAK;EAClD,IAAI,MAAM;GACR,MAAM,EAAE,MAAM,SAAS,OAAO,QAAQ,MAAM,IAAI;GAChD,OAAO;GACP,YAAY,KAAK;IAAE,MAAM;IAAY,UAAU;IAAW,SAAS,EAAE,+BAA+B,EAAE,MAAM,KAAK,UAAU,KAAK,SAAS,KAAK,GAAG,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC;IAAG,GAAI,QAAQ,EAAE,KAAK;GAAG,CAAC;EAC3M;EACA,OAAO;CACT;CACA,IAAI;EACF,OAAO,MAAM;CACf,UACQ;EACN,IAAI,KAAK,QAAQ,iBAAiB;OAC7B,OAAQ,QAAiC;CAChD;AACF;AAEA,MAAM,gBAAgB,SAAqC,CAAC,GAAI,KAAK,SAAS,gBAAgB,CAAC,IAAI,IAAI,CAAC,GAAI,IAAI,KAAK,WAAW,CAAC,EAAA,CAAG,QAAQ,YAAY,CAAC;;;;;;;;;;;;;;;AAgBzJ,SAAgB,kBAAkB,QAAgB,MAAc,UAAsD,CAAC,GAAoB;CACzI,MAAM,SAAS,QAAQ,UAAU,CAAC;CAClC,MAAM,IAAI,QAAQ,KAAK,cAAc,MAAM,CAAC,EAAE,IAAI,KAAK,iBAAiB;CACxE,MAAM,cAAoC,CAAC;CAE3C,MAAM,EAAE,WAAW,OAAO,YAAY,YAAY,QAAQ,IAAI,IAAI,eAAe,QAAQ,MAAM,aAAa,SAAS,YAAY,QAAQ,IAAI,CAAC;CAC9I,IAAI,UAAuB,OAAO,SAAS;EAAE,MAAM;EAAO,SAAS;CAAO,IAAI;CAC9E,UAAU,iBAAiB,SAAS,QAAQ,MAAM,aAAa,CAAC;CAChE,IAAI,CAAC,QAAQ,SAAS,QAAQ,UAAU;CAExC,KAAK,MAAM,WAAW,YAAY,IAAI,CAAC,CAAC,UACtC,YAAY,KAAK;EACf,MAAM,QAAQ;EACd,UAAU;EACV,MAAM,QAAQ;EACd,SAAS,EAAE,QAAQ,SAAS,mBAAmB,sCAAsC,wCAAwC,EAAE,MAAM,QAAQ,KAAK,CAAC;CACrJ,CAAC;CAEH,IAAI,OAAO;CACX,KAAK,MAAM,SAAS,aAAa,OAAO,GAAG;EACzC,MAAM,MAAM,OAAO,MAAM,OAAO,OAAO,EAAE;EACzC,MAAM,EAAE,MAAM,SAAS,OAAO,MAAM,KAAK,IAAI;EAC7C,OAAO;EACP,YAAY,KAAK;GAAE,MAAM;GAAiB,UAAU;GAAQ,SAAS,EAAE,oCAAoC,EAAE,MAAM,OAAO,MAAM,OAAO,IAAI,EAAE,CAAC;GAAG,GAAI,QAAQ,EAAE,KAAK;EAAG,CAAC;CAC1K;CAEA,OAAO;EAAE,SAAS,WAAW,MAAM,CAAC,CAAC,eAAe,OAAO;EAAG;CAAY;AAC5E;;;;;;;AAQA,SAAgB,kBAAkB,QAAwB;CACxD,OAAO,OAAO,YAAY,CAAC,CAAC,QAAQ,QAAQ,EAAE;AAChD"}
1
+ {"version":3,"file":"document.js","names":[],"sources":["../../src/markdown/document.ts"],"sourcesContent":["import type { Editor, JSONContent } from '@tiptap/core'\nimport { splitFences } from '../core/fences'\nimport { parseBlocks, pipelineOf } from '../core/pipeline'\nimport { EMPTY_EDITOR_CONTENT } from '../core/schema'\nimport { editorEntryOf } from '../core/editor-ui'\nimport { createTranslator, type Translate } from '../i18n'\nimport { enforceUrlPolicy, locate, type MarkdownDiagnostic, type MarkdownPolicy } from './policy'\n\n/** A Markdown body as document JSON, with what the parse dropped or could not understand. */\nexport interface MarkdownContent {\n content: JSONContent\n diagnostics: MarkdownDiagnostic[]\n}\n\n/** The part of `@tiptap/markdown`'s manager the HTML policy swaps out for the duration of one parse. */\ninterface HtmlParsing {\n parseHTMLToken: (token: { raw?: string, text?: string }) => unknown\n}\n\n/**\n * Runs `parse` with raw HTML tokens (block and inline, tags and comments) dropped instead of handed to the schema's\n * `parseHTML` rules, and reports each in `diagnostics`.\n */\nfunction withoutRawHtml<T>(editor: Editor, source: string, diagnostics: MarkdownDiagnostic[], t: Translate, parse: () => T): T {\n const manager = editor.markdown as unknown as HtmlParsing | undefined\n if (!manager) return parse()\n const own = Object.hasOwn(manager, 'parseHTMLToken')\n const original = manager.parseHTMLToken\n let from = 0\n manager.parseHTMLToken = (token) => {\n const html = (token.raw ?? token.text ?? '').trim()\n if (html) {\n const { line, next } = locate(source, html, from)\n from = next\n diagnostics.push({ code: 'raw-html', severity: 'warning', message: t('markdown.diagnostic.rawHtml', { html: JSON.stringify(html.length > 60 ? `${html.slice(0, 57)}…` : html) }), ...(line && { line }) })\n }\n return null\n }\n try {\n return parse()\n }\n finally {\n if (own) manager.parseHTMLToken = original\n else delete (manager as Partial<HtmlParsing>).parseHTMLToken\n }\n}\n\nconst opaqueFences = (node: JSONContent): JSONContent[] => [...(node.type === 'opaqueFence' ? [node] : []), ...(node.content ?? []).flatMap(opaqueFences)]\n\n/**\n * `body` (Markdown without frontmatter) as the document JSON of `editor`, plus `diagnostics`: the preset's block\n * pipeline parses it (`parseBlocks`: Markdown tokens, then the features' normalize and segment stages), the blocks\n * become the children of a `doc`, `policy` is enforced and the preset's `migrateContent` stage runs. An empty body is\n * the empty document (one empty paragraph). Nothing is applied to the editor.\n *\n * The diagnostics' `message` is in the language of `options.t`, by default that of the editor's registered surface, else\n * the default locale.\n *\n * Diagnostics: `raw-html` (dropped unless `policy.allowHtml`), `unsafe-url` (links and media with a scheme other than\n * http(s), mailto and tel are dropped; base64 `data:image` URLs are kept only with `policy.allowDataUrls`),\n * `unknown-fence` (a `:::` fence of a kind no feature registered, kept verbatim as an `opaqueFence`), and the fatal\n * `unclosed-fence` and `invalid-fence-meta` (a fence opener that stayed plain text).\n */\nexport function markdownToContent(editor: Editor, body: string, options: { policy?: MarkdownPolicy, t?: Translate } = {}): MarkdownContent {\n const policy = options.policy ?? {}\n const t = options.t ?? editorEntryOf(editor)?.ctx.t ?? createTranslator()\n const diagnostics: MarkdownDiagnostic[] = []\n\n const { blocks } = policy.allowHtml ? parseBlocks(editor, body) : withoutRawHtml(editor, body, diagnostics, t, () => parseBlocks(editor, body))\n let content: JSONContent = blocks.length ? { type: 'doc', content: blocks } : EMPTY_EDITOR_CONTENT\n content = enforceUrlPolicy(content, policy, body, diagnostics, t)\n if (!content.content?.length) content = EMPTY_EDITOR_CONTENT\n\n for (const problem of splitFences(body).problems) {\n diagnostics.push({\n code: problem.code,\n severity: 'error',\n line: problem.line,\n message: t(problem.code === 'unclosed-fence' ? 'markdown.diagnostic.unclosedFence' : 'markdown.diagnostic.invalidFenceMeta', { kind: problem.kind }),\n })\n }\n let from = 0\n for (const fence of opaqueFences(content)) {\n const raw = String(fence.attrs?.raw ?? '')\n const { line, next } = locate(body, raw, from)\n from = next\n diagnostics.push({ code: 'unknown-fence', severity: 'info', message: t('markdown.diagnostic.unknownFence', { kind: String(fence.attrs?.blockType) }), ...(line && { line }) })\n }\n\n return { content: pipelineOf(editor).migrateContent(content), diagnostics }\n}\n\n/**\n * The document of `editor` as Markdown (`editor.getMarkdown()`: the registered Markdown handlers render every node,\n * tables as pipe tables and task items as `- [ ]`/`- [x]`), without trailing line breaks: Tiptap keeps an empty\n * paragraph after a last block that is not a paragraph, and it is not content. Callers that write files add their own\n * final line break.\n */\nexport function contentToMarkdown(editor: Editor): string {\n return editor.getMarkdown().replace(/\\n+$/, '')\n}\n"],"mappings":";;;;;;;;;;;AAuBA,SAAS,eAAkB,QAAgB,QAAgB,aAAmC,GAAc,OAAmB;CAC7H,MAAM,UAAU,OAAO;CACvB,IAAI,CAAC,SAAS,OAAO,MAAM;CAC3B,MAAM,MAAM,OAAO,OAAO,SAAS,gBAAgB;CACnD,MAAM,WAAW,QAAQ;CACzB,IAAI,OAAO;CACX,QAAQ,kBAAkB,UAAU;EAClC,MAAM,QAAQ,MAAM,OAAO,MAAM,QAAQ,GAAA,CAAI,KAAK;EAClD,IAAI,MAAM;GACR,MAAM,EAAE,MAAM,SAAS,OAAO,QAAQ,MAAM,IAAI;GAChD,OAAO;GACP,YAAY,KAAK;IAAE,MAAM;IAAY,UAAU;IAAW,SAAS,EAAE,+BAA+B,EAAE,MAAM,KAAK,UAAU,KAAK,SAAS,KAAK,GAAG,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC;IAAG,GAAI,QAAQ,EAAE,KAAK;GAAG,CAAC;EAC3M;EACA,OAAO;CACT;CACA,IAAI;EACF,OAAO,MAAM;CACf,UACQ;EACN,IAAI,KAAK,QAAQ,iBAAiB;OAC7B,OAAQ,QAAiC;CAChD;AACF;AAEA,MAAM,gBAAgB,SAAqC,CAAC,GAAI,KAAK,SAAS,gBAAgB,CAAC,IAAI,IAAI,CAAC,GAAI,IAAI,KAAK,WAAW,CAAC,EAAA,CAAG,QAAQ,YAAY,CAAC;;;;;;;;;;;;;;;AAgBzJ,SAAgB,kBAAkB,QAAgB,MAAc,UAAsD,CAAC,GAAoB;CACzI,MAAM,SAAS,QAAQ,UAAU,CAAC;CAClC,MAAM,IAAI,QAAQ,KAAK,cAAc,MAAM,CAAC,EAAE,IAAI,KAAK,iBAAiB;CACxE,MAAM,cAAoC,CAAC;CAE3C,MAAM,EAAE,WAAW,OAAO,YAAY,YAAY,QAAQ,IAAI,IAAI,eAAe,QAAQ,MAAM,aAAa,SAAS,YAAY,QAAQ,IAAI,CAAC;CAC9I,IAAI,UAAuB,OAAO,SAAS;EAAE,MAAM;EAAO,SAAS;CAAO,IAAI;CAC9E,UAAU,iBAAiB,SAAS,QAAQ,MAAM,aAAa,CAAC;CAChE,IAAI,CAAC,QAAQ,SAAS,QAAQ,UAAU;CAExC,KAAK,MAAM,WAAW,YAAY,IAAI,CAAC,CAAC,UACtC,YAAY,KAAK;EACf,MAAM,QAAQ;EACd,UAAU;EACV,MAAM,QAAQ;EACd,SAAS,EAAE,QAAQ,SAAS,mBAAmB,sCAAsC,wCAAwC,EAAE,MAAM,QAAQ,KAAK,CAAC;CACrJ,CAAC;CAEH,IAAI,OAAO;CACX,KAAK,MAAM,SAAS,aAAa,OAAO,GAAG;EACzC,MAAM,MAAM,OAAO,MAAM,OAAO,OAAO,EAAE;EACzC,MAAM,EAAE,MAAM,SAAS,OAAO,MAAM,KAAK,IAAI;EAC7C,OAAO;EACP,YAAY,KAAK;GAAE,MAAM;GAAiB,UAAU;GAAQ,SAAS,EAAE,oCAAoC,EAAE,MAAM,OAAO,MAAM,OAAO,SAAS,EAAE,CAAC;GAAG,GAAI,QAAQ,EAAE,KAAK;EAAG,CAAC;CAC/K;CAEA,OAAO;EAAE,SAAS,WAAW,MAAM,CAAC,CAAC,eAAe,OAAO;EAAG;CAAY;AAC5E;;;;;;;AAQA,SAAgB,kBAAkB,QAAwB;CACxD,OAAO,OAAO,YAAY,CAAC,CAAC,QAAQ,QAAQ,EAAE;AAChD"}
@@ -416,6 +416,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
416
416
  "composites.derivation.badge"?: string | undefined;
417
417
  "composites.derivation.stale"?: string | undefined;
418
418
  "composites.derivation.foreign"?: string | undefined;
419
+ "composites.derivation.sourceMissing"?: string | undefined;
419
420
  "composites.derivation.edited"?: string | undefined;
420
421
  "composites.derivation.expand"?: string | undefined;
421
422
  "composites.derivation.collapse"?: string | undefined;
@@ -443,6 +444,8 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
443
444
  "composites.inspector.mentions"?: string | undefined;
444
445
  "composites.inspector.composite"?: string | undefined;
445
446
  "composites.inspector.kind"?: string | undefined;
447
+ "composites.inspector.properties"?: string | undefined;
448
+ "composites.inspector.derivation"?: string | undefined;
446
449
  "composites.inspector.title"?: string | undefined;
447
450
  "composites.inspector.titleHelp"?: string | undefined;
448
451
  "composites.inspector.untitled"?: string | undefined;
@@ -475,8 +478,8 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
475
478
  "composites.settings.structure.legend"?: string | undefined;
476
479
  "composites.settings.structure.flat.label"?: string | undefined;
477
480
  "composites.settings.structure.flat.description"?: string | undefined;
478
- "composites.settings.structure.composite.label"?: string | undefined;
479
- "composites.settings.structure.composite.description"?: string | undefined;
481
+ "composites.settings.structure.structured.label"?: string | undefined;
482
+ "composites.settings.structure.structured.description"?: string | undefined;
480
483
  "composites.settings.scope.legend"?: string | undefined;
481
484
  "composites.settings.scope.container.label"?: string | undefined;
482
485
  "composites.settings.scope.container.description"?: string | undefined;
@@ -491,13 +494,13 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
491
494
  "composites.settings.treeRoot.file.label"?: string | undefined;
492
495
  "composites.settings.treeRoot.file.description"?: string | undefined;
493
496
  "composites.settings.composites.title"?: string | undefined;
494
- "composites.settings.defaultKind.label"?: string | undefined;
495
- "composites.settings.defaultKind.description"?: string | undefined;
496
- "composites.settings.kindIcon.legend"?: string | undefined;
497
- "composites.settings.kindIcon.always.label"?: string | undefined;
498
- "composites.settings.kindIcon.always.description"?: string | undefined;
499
- "composites.settings.kindIcon.hover.label"?: string | undefined;
500
- "composites.settings.kindIcon.hover.description"?: string | undefined;
497
+ "composites.settings.defaultBlockType.label"?: string | undefined;
498
+ "composites.settings.defaultBlockType.description"?: string | undefined;
499
+ "composites.settings.blockTypeIcon.legend"?: string | undefined;
500
+ "composites.settings.blockTypeIcon.always.label"?: string | undefined;
501
+ "composites.settings.blockTypeIcon.always.description"?: string | undefined;
502
+ "composites.settings.blockTypeIcon.hover.label"?: string | undefined;
503
+ "composites.settings.blockTypeIcon.hover.description"?: string | undefined;
501
504
  "composites.settings.dragHandle.legend"?: string | undefined;
502
505
  "composites.settings.dragHandle.hover.label"?: string | undefined;
503
506
  "composites.settings.dragHandle.hover.description"?: string | undefined;
@@ -709,8 +712,8 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
709
712
  "ai.settings.autocomplete.description"?: string | undefined;
710
713
  "ai.settings.language.label"?: string | undefined;
711
714
  "ai.settings.language.description"?: string | undefined;
712
- "ai.settings.slots.title"?: string | undefined;
713
- "ai.settings.slots.description"?: string | undefined;
715
+ "ai.settings.roles.title"?: string | undefined;
716
+ "ai.settings.roles.description"?: string | undefined;
714
717
  "ai.settings.profiles.title"?: string | undefined;
715
718
  "ai.settings.profiles.description"?: string | undefined;
716
719
  "ai.profiles.server"?: string | undefined;
@@ -775,7 +778,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
775
778
  } | undefined;
776
779
  } | undefined;
777
780
  apiKey?: string | undefined;
778
- slots?: {
781
+ roles?: {
779
782
  complete?: string | undefined;
780
783
  rewrite?: string | undefined;
781
784
  generate?: string | undefined;
@@ -1203,6 +1206,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
1203
1206
  "composites.derivation.badge"?: string | undefined;
1204
1207
  "composites.derivation.stale"?: string | undefined;
1205
1208
  "composites.derivation.foreign"?: string | undefined;
1209
+ "composites.derivation.sourceMissing"?: string | undefined;
1206
1210
  "composites.derivation.edited"?: string | undefined;
1207
1211
  "composites.derivation.expand"?: string | undefined;
1208
1212
  "composites.derivation.collapse"?: string | undefined;
@@ -1230,6 +1234,8 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
1230
1234
  "composites.inspector.mentions"?: string | undefined;
1231
1235
  "composites.inspector.composite"?: string | undefined;
1232
1236
  "composites.inspector.kind"?: string | undefined;
1237
+ "composites.inspector.properties"?: string | undefined;
1238
+ "composites.inspector.derivation"?: string | undefined;
1233
1239
  "composites.inspector.title"?: string | undefined;
1234
1240
  "composites.inspector.titleHelp"?: string | undefined;
1235
1241
  "composites.inspector.untitled"?: string | undefined;
@@ -1262,8 +1268,8 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
1262
1268
  "composites.settings.structure.legend"?: string | undefined;
1263
1269
  "composites.settings.structure.flat.label"?: string | undefined;
1264
1270
  "composites.settings.structure.flat.description"?: string | undefined;
1265
- "composites.settings.structure.composite.label"?: string | undefined;
1266
- "composites.settings.structure.composite.description"?: string | undefined;
1271
+ "composites.settings.structure.structured.label"?: string | undefined;
1272
+ "composites.settings.structure.structured.description"?: string | undefined;
1267
1273
  "composites.settings.scope.legend"?: string | undefined;
1268
1274
  "composites.settings.scope.container.label"?: string | undefined;
1269
1275
  "composites.settings.scope.container.description"?: string | undefined;
@@ -1278,13 +1284,13 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
1278
1284
  "composites.settings.treeRoot.file.label"?: string | undefined;
1279
1285
  "composites.settings.treeRoot.file.description"?: string | undefined;
1280
1286
  "composites.settings.composites.title"?: string | undefined;
1281
- "composites.settings.defaultKind.label"?: string | undefined;
1282
- "composites.settings.defaultKind.description"?: string | undefined;
1283
- "composites.settings.kindIcon.legend"?: string | undefined;
1284
- "composites.settings.kindIcon.always.label"?: string | undefined;
1285
- "composites.settings.kindIcon.always.description"?: string | undefined;
1286
- "composites.settings.kindIcon.hover.label"?: string | undefined;
1287
- "composites.settings.kindIcon.hover.description"?: string | undefined;
1287
+ "composites.settings.defaultBlockType.label"?: string | undefined;
1288
+ "composites.settings.defaultBlockType.description"?: string | undefined;
1289
+ "composites.settings.blockTypeIcon.legend"?: string | undefined;
1290
+ "composites.settings.blockTypeIcon.always.label"?: string | undefined;
1291
+ "composites.settings.blockTypeIcon.always.description"?: string | undefined;
1292
+ "composites.settings.blockTypeIcon.hover.label"?: string | undefined;
1293
+ "composites.settings.blockTypeIcon.hover.description"?: string | undefined;
1288
1294
  "composites.settings.dragHandle.legend"?: string | undefined;
1289
1295
  "composites.settings.dragHandle.hover.label"?: string | undefined;
1290
1296
  "composites.settings.dragHandle.hover.description"?: string | undefined;
@@ -1496,8 +1502,8 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
1496
1502
  "ai.settings.autocomplete.description"?: string | undefined;
1497
1503
  "ai.settings.language.label"?: string | undefined;
1498
1504
  "ai.settings.language.description"?: string | undefined;
1499
- "ai.settings.slots.title"?: string | undefined;
1500
- "ai.settings.slots.description"?: string | undefined;
1505
+ "ai.settings.roles.title"?: string | undefined;
1506
+ "ai.settings.roles.description"?: string | undefined;
1501
1507
  "ai.settings.profiles.title"?: string | undefined;
1502
1508
  "ai.settings.profiles.description"?: string | undefined;
1503
1509
  "ai.profiles.server"?: string | undefined;
@@ -1562,7 +1568,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
1562
1568
  } | undefined;
1563
1569
  } | undefined;
1564
1570
  apiKey?: string | undefined;
1565
- slots?: {
1571
+ roles?: {
1566
1572
  complete?: string | undefined;
1567
1573
  rewrite?: string | undefined;
1568
1574
  generate?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","names":[],"sources":["../../src/nuxt/module.ts"],"sourcesContent":["import { addPlugin, addServerScanDir, createResolver, defineNuxtModule } from 'nuxt/kit'\nimport { defineEditorConfig, type EditorConfigInput, publicConfig, serverConfig } from '../config'\n\n/** Module options (`tiptapEditor` in `nuxt.config`): the editor's configuration with every key optional, see `EditorConfig`. */\nexport type ModuleOptions = EditorConfigInput\n\n/**\n * Nuxt/Nitro integration of the editor package: the client context plugin (settings persistence, AI configuration),\n * a server plugin that mounts the editor's routes and the collaboration websocket (`installEditorServer`) and the AI configuration with its server-only secrets. The host\n * plugs in through `setEditorPorts()` (`@ecsplico/editor/server`) in a Nitro plugin (auth, loading and storing\n * document content). Components are imported explicitly from the package entries; nothing is auto-registered.\n */\nexport default defineNuxtModule<ModuleOptions>({\n meta: { name: 'tiptap-editor', configKey: 'tiptapEditor' },\n setup(options, nuxt) {\n const { resolve } = createResolver(import.meta.url)\n // `resolve('..')` is the package root of the built output (`dist`) or of `src` in this repository's app: both\n // hold the stylesheets and the unbundled `nuxt/runtime` files, which Nuxt compiles for the client and Nitro for the server.\n const packageSrc = resolve('..')\n nuxt.options.build.transpile.push(packageSrc)\n // The Nuxt UI token map comes first: the feature sheets (and an Obsidian theme, `themes.css`, last) read and may override `--sk-*`.\n nuxt.options.css.push(resolve('../vue/kit/nuxt-ui.css'))\n nuxt.options.css.push(\n resolve('../styles/core.css'),\n resolve('../styles/media.css'),\n resolve('../styles/mentions.css'),\n resolve('../styles/authors.css'),\n resolve('../styles/comments.css'),\n resolve('../styles/transcript.css'),\n resolve('../styles/composites.css'),\n resolve('../styles/ai.css'),\n resolve('../styles/collab.css'),\n resolve('../styles/block-ui.css'),\n resolve('../styles/themes.css'),\n )\n addPlugin({ src: resolve('./runtime/plugins/editor-context-nuxt-ui.client.ts'), mode: 'client' })\n addServerScanDir(resolve('./runtime/server'))\n // Tailwind only scans the app layers listed in Nuxt UI's generated `ui.css` (`@source \"<layer>/app/**/*\"`), so the\n // utility classes used by the package's components would never be generated. Append its source. `@nuxt/ui` must be\n // registered before this module.\n nuxt.hook('modules:done', () => {\n const uiCss = nuxt.options.build.templates.find(t => t.filename === 'ui.css')\n if (!uiCss?.getContents) throw new Error('tiptap-editor: @nuxt/ui muss vor diesem Modul registriert sein (ui.css-Template fehlt)')\n const getContents = uiCss.getContents\n uiCss.getContents = async data => `@source \"${packageSrc}/**/*\";\\n${await getContents(data)}`\n })\n nuxt.options.nitro.experimental = { ...nuxt.options.nitro.experimental, websocket: true }\n // Nitro bundles the package (the runtime files import `h3` and `nitropack/runtime`, which the host's Nitro resolves): never leave it external.\n nuxt.options.nitro.externals = { ...nuxt.options.nitro.externals, inline: [...(nuxt.options.nitro.externals?.inline ?? []), '@ecsplico/editor', packageSrc] }\n const config = defineEditorConfig(options)\n // The server view keeps an empty `apiKey` on the shared key, every preset and the transcription, so their `NUXT_TIPTAP_EDITOR_AI_*` env variables have a key to override.\n nuxt.options.runtimeConfig.tiptapEditor = {\n ...serverConfig(config),\n ...(nuxt.options.runtimeConfig.tiptapEditor as object | undefined),\n }\n // Default slot presets for the client before `GET /api/ai/models` has answered; read by the client context plugin.\n nuxt.options.runtimeConfig.public.tiptapEditor = {\n ...publicConfig(config),\n ...(nuxt.options.runtimeConfig.public.tiptapEditor as object | undefined),\n }\n },\n})\n"],"mappings":";;;;;;;;;AAYA,IAAA,iBAAe,iBAAgC;CAC7C,MAAM;EAAE,MAAM;EAAiB,WAAW;CAAe;CACzD,MAAM,SAAS,MAAM;EACnB,MAAM,EAAE,YAAY,eAAe,YAAY,GAAG;EAGlD,MAAM,aAAa,QAAQ,IAAI;EAC/B,KAAK,QAAQ,MAAM,UAAU,KAAK,UAAU;EAE5C,KAAK,QAAQ,IAAI,KAAK,QAAQ,wBAAwB,CAAC;EACvD,KAAK,QAAQ,IAAI,KACf,QAAQ,oBAAoB,GAC5B,QAAQ,qBAAqB,GAC7B,QAAQ,wBAAwB,GAChC,QAAQ,uBAAuB,GAC/B,QAAQ,wBAAwB,GAChC,QAAQ,0BAA0B,GAClC,QAAQ,0BAA0B,GAClC,QAAQ,kBAAkB,GAC1B,QAAQ,sBAAsB,GAC9B,QAAQ,wBAAwB,GAChC,QAAQ,sBAAsB,CAChC;EACA,UAAU;GAAE,KAAK,QAAQ,oDAAoD;GAAG,MAAM;EAAS,CAAC;EAChG,iBAAiB,QAAQ,kBAAkB,CAAC;EAI5C,KAAK,KAAK,sBAAsB;GAC9B,MAAM,QAAQ,KAAK,QAAQ,MAAM,UAAU,MAAK,MAAK,EAAE,aAAa,QAAQ;GAC5E,IAAI,CAAC,OAAO,aAAa,MAAM,IAAI,MAAM,wFAAwF;GACjI,MAAM,cAAc,MAAM;GAC1B,MAAM,cAAc,OAAM,SAAQ,YAAY,WAAW,WAAW,MAAM,YAAY,IAAI;EAC5F,CAAC;EACD,KAAK,QAAQ,MAAM,eAAe;GAAE,GAAG,KAAK,QAAQ,MAAM;GAAc,WAAW;EAAK;EAExF,KAAK,QAAQ,MAAM,YAAY;GAAE,GAAG,KAAK,QAAQ,MAAM;GAAW,QAAQ;IAAC,GAAI,KAAK,QAAQ,MAAM,WAAW,UAAU,CAAC;IAAI;IAAoB;GAAU;EAAE;EAC5J,MAAM,SAAS,mBAAmB,OAAO;EAEzC,KAAK,QAAQ,cAAc,eAAe;GACxC,GAAG,aAAa,MAAM;GACtB,GAAI,KAAK,QAAQ,cAAc;EACjC;EAEA,KAAK,QAAQ,cAAc,OAAO,eAAe;GAC/C,GAAG,aAAa,MAAM;GACtB,GAAI,KAAK,QAAQ,cAAc,OAAO;EACxC;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"module.js","names":[],"sources":["../../src/nuxt/module.ts"],"sourcesContent":["import { addPlugin, addServerScanDir, createResolver, defineNuxtModule } from 'nuxt/kit'\nimport { defineEditorConfig, type EditorConfigInput, publicConfig, serverConfig } from '../config'\n\n/** Module options (`tiptapEditor` in `nuxt.config`): the editor's configuration with every key optional, see `EditorConfig`. */\nexport type ModuleOptions = EditorConfigInput\n\n/**\n * Nuxt/Nitro integration of the editor package: the client context plugin (settings persistence, AI configuration),\n * a server plugin that mounts the editor's routes and the collaboration websocket (`installEditorServer`) and the AI configuration with its server-only secrets. The host\n * plugs in through `setEditorPorts()` (`@ecsplico/editor/server`) in a Nitro plugin (auth, loading and storing\n * document content). Components are imported explicitly from the package entries; nothing is auto-registered.\n */\nexport default defineNuxtModule<ModuleOptions>({\n meta: { name: 'tiptap-editor', configKey: 'tiptapEditor' },\n setup(options, nuxt) {\n const { resolve } = createResolver(import.meta.url)\n // `resolve('..')` is the package root of the built output (`dist`) or of `src` in this repository's app: both\n // hold the stylesheets and the unbundled `nuxt/runtime` files, which Nuxt compiles for the client and Nitro for the server.\n const packageSrc = resolve('..')\n nuxt.options.build.transpile.push(packageSrc)\n // The Nuxt UI token map comes first: the feature sheets (and an Obsidian theme, `themes.css`, last) read and may override `--sk-*`.\n nuxt.options.css.push(resolve('../vue/kit/nuxt-ui.css'))\n nuxt.options.css.push(\n resolve('../styles/core.css'),\n resolve('../styles/media.css'),\n resolve('../styles/mentions.css'),\n resolve('../styles/authors.css'),\n resolve('../styles/comments.css'),\n resolve('../styles/transcript.css'),\n resolve('../styles/composites.css'),\n resolve('../styles/ai.css'),\n resolve('../styles/collab.css'),\n resolve('../styles/block-ui.css'),\n resolve('../styles/themes.css'),\n )\n addPlugin({ src: resolve('./runtime/plugins/editor-context-nuxt-ui.client.ts'), mode: 'client' })\n addServerScanDir(resolve('./runtime/server'))\n // Tailwind only scans the app layers listed in Nuxt UI's generated `ui.css` (`@source \"<layer>/app/**/*\"`), so the\n // utility classes used by the package's components would never be generated. Append its source. `@nuxt/ui` must be\n // registered before this module.\n nuxt.hook('modules:done', () => {\n const uiCss = nuxt.options.build.templates.find(t => t.filename === 'ui.css')\n if (!uiCss?.getContents) throw new Error('tiptap-editor: @nuxt/ui muss vor diesem Modul registriert sein (ui.css-Template fehlt)')\n const getContents = uiCss.getContents\n uiCss.getContents = async data => `@source \"${packageSrc}/**/*\";\\n${await getContents(data)}`\n })\n nuxt.options.nitro.experimental = { ...nuxt.options.nitro.experimental, websocket: true }\n // Nitro bundles the package (the runtime files import `h3` and `nitropack/runtime`, which the host's Nitro resolves): never leave it external.\n nuxt.options.nitro.externals = { ...nuxt.options.nitro.externals, inline: [...(nuxt.options.nitro.externals?.inline ?? []), '@ecsplico/editor', packageSrc] }\n const config = defineEditorConfig(options)\n // The server view keeps an empty `apiKey` on the shared key, every preset and the transcription, so their `NUXT_TIPTAP_EDITOR_AI_*` env variables have a key to override.\n nuxt.options.runtimeConfig.tiptapEditor = {\n ...serverConfig(config),\n ...(nuxt.options.runtimeConfig.tiptapEditor as object | undefined),\n }\n // Default role presets for the client before `GET /api/ai/models` has answered; read by the client context plugin.\n nuxt.options.runtimeConfig.public.tiptapEditor = {\n ...publicConfig(config),\n ...(nuxt.options.runtimeConfig.public.tiptapEditor as object | undefined),\n }\n },\n})\n"],"mappings":";;;;;;;;;AAYA,IAAA,iBAAe,iBAAgC;CAC7C,MAAM;EAAE,MAAM;EAAiB,WAAW;CAAe;CACzD,MAAM,SAAS,MAAM;EACnB,MAAM,EAAE,YAAY,eAAe,YAAY,GAAG;EAGlD,MAAM,aAAa,QAAQ,IAAI;EAC/B,KAAK,QAAQ,MAAM,UAAU,KAAK,UAAU;EAE5C,KAAK,QAAQ,IAAI,KAAK,QAAQ,wBAAwB,CAAC;EACvD,KAAK,QAAQ,IAAI,KACf,QAAQ,oBAAoB,GAC5B,QAAQ,qBAAqB,GAC7B,QAAQ,wBAAwB,GAChC,QAAQ,uBAAuB,GAC/B,QAAQ,wBAAwB,GAChC,QAAQ,0BAA0B,GAClC,QAAQ,0BAA0B,GAClC,QAAQ,kBAAkB,GAC1B,QAAQ,sBAAsB,GAC9B,QAAQ,wBAAwB,GAChC,QAAQ,sBAAsB,CAChC;EACA,UAAU;GAAE,KAAK,QAAQ,oDAAoD;GAAG,MAAM;EAAS,CAAC;EAChG,iBAAiB,QAAQ,kBAAkB,CAAC;EAI5C,KAAK,KAAK,sBAAsB;GAC9B,MAAM,QAAQ,KAAK,QAAQ,MAAM,UAAU,MAAK,MAAK,EAAE,aAAa,QAAQ;GAC5E,IAAI,CAAC,OAAO,aAAa,MAAM,IAAI,MAAM,wFAAwF;GACjI,MAAM,cAAc,MAAM;GAC1B,MAAM,cAAc,OAAM,SAAQ,YAAY,WAAW,WAAW,MAAM,YAAY,IAAI;EAC5F,CAAC;EACD,KAAK,QAAQ,MAAM,eAAe;GAAE,GAAG,KAAK,QAAQ,MAAM;GAAc,WAAW;EAAK;EAExF,KAAK,QAAQ,MAAM,YAAY;GAAE,GAAG,KAAK,QAAQ,MAAM;GAAW,QAAQ;IAAC,GAAI,KAAK,QAAQ,MAAM,WAAW,UAAU,CAAC;IAAI;IAAoB;GAAU;EAAE;EAC5J,MAAM,SAAS,mBAAmB,OAAO;EAEzC,KAAK,QAAQ,cAAc,eAAe;GACxC,GAAG,aAAa,MAAM;GACtB,GAAI,KAAK,QAAQ,cAAc;EACjC;EAEA,KAAK,QAAQ,cAAc,OAAO,eAAe;GAC/C,GAAG,aAAa,MAAM;GACtB,GAAI,KAAK,QAAQ,cAAc,OAAO;EACxC;CACF;AACF,CAAC"}
@@ -1,4 +1,4 @@
1
- import { useEditorPorts, useEditorSchema } from "../../../../server/host.js";
1
+ import { useEditorBlockTypes, useEditorPorts, useEditorSchema } from "../../../../server/host.js";
2
2
  import { installEditorServer } from "../../../../adapters/nitro.js";
3
3
  import { defineNitroPlugin, useRuntimeConfig } from "nitropack/runtime";
4
4
  //#region src/nuxt/runtime/server/plugins/editor-server.ts
@@ -18,7 +18,8 @@ var editor_server_default = defineNitroPlugin((nitroApp) => {
18
18
  missingKeyHint: (id) => ` (NUXT_TIPTAP_EDITOR_AI_PRESETS_${id.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase()}_API_KEY oder NUXT_TIPTAP_EDITOR_AI_API_KEY)`
19
19
  },
20
20
  rateLimit,
21
- schema: useEditorSchema()
21
+ schema: useEditorSchema(),
22
+ blockTypes: useEditorBlockTypes()
22
23
  });
23
24
  }
24
25
  });
@@ -1 +1 @@
1
- {"version":3,"file":"editor-server.js","names":[],"sources":["../../../../../src/nuxt/runtime/server/plugins/editor-server.ts"],"sourcesContent":["// Nitro's auto-imports are not applied to files under node_modules (the built package), so every Nitro/h3 helper is imported explicitly.\nimport { defineNitroPlugin, useRuntimeConfig } from 'nitropack/runtime'\nimport { type EditorServer, installEditorServer } from '../../../../adapters/nitro'\nimport type { EditorServerConfig } from '../../../../config'\nimport { useEditorPorts, useEditorSchema } from '../../../../server/host'\n\n// Mounts the editor's routes and the collaboration websocket (`installEditorServer`) over the ports the host registered\n// with `setEditorPorts()`, and takes the AI configuration (presets, keys, slots, transcription), the rate limit and\n// `collab.authenticateUpgrade` from the module's runtime config.\n//\n// The host registers its ports in a Nitro plugin of its own, and Nitro does not order plugins of different layers and\n// modules reliably; the first request is the first moment every plugin has run (the routes it served before this\n// were file-based and read the ports per request, too). A failed install is retried by the next request.\nexport default defineNitroPlugin((nitroApp) => {\n let server: EditorServer | undefined\n nitroApp.hooks.hook('request', () => {\n server ??= install()\n })\n\n function install(): EditorServer {\n // The module's `serverConfig(defineEditorConfig(options))`, with the host's runtime-config and env overrides applied.\n const { ai, rateLimit, collab } = useRuntimeConfig().tiptapEditor as EditorServerConfig\n const ports = useEditorPorts()\n return installEditorServer(nitroApp, {\n ports,\n // Without persisted collaboration state the editor runs without the websocket (documents still load and save over HTTP).\n collab: ports.collabState ? collab : false,\n // Env names use the preset id in upper snake case (`flashLite` → `FLASH_LITE`), like Nuxt's runtime config mapping.\n ai: { ...ai, missingKeyHint: id => ` (NUXT_TIPTAP_EDITOR_AI_PRESETS_${id.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase()}_API_KEY oder NUXT_TIPTAP_EDITOR_AI_API_KEY)` },\n rateLimit,\n schema: useEditorSchema(),\n })\n }\n})\n"],"mappings":";;;;AAaA,IAAA,wBAAe,mBAAmB,aAAa;CAC7C,IAAI;CACJ,SAAS,MAAM,KAAK,iBAAiB;EACnC,WAAW,QAAQ;CACrB,CAAC;CAED,SAAS,UAAwB;EAE/B,MAAM,EAAE,IAAI,WAAW,WAAW,iBAAiB,CAAC,CAAC;EACrD,MAAM,QAAQ,eAAe;EAC7B,OAAO,oBAAoB,UAAU;GACnC;GAEA,QAAQ,MAAM,cAAc,SAAS;GAErC,IAAI;IAAE,GAAG;IAAI,iBAAgB,OAAM,mCAAmC,GAAG,QAAQ,sBAAsB,OAAO,CAAC,CAAC,YAAY,EAAE;GAA8C;GAC5K;GACA,QAAQ,gBAAgB;EAC1B,CAAC;CACH;AACF,CAAC"}
1
+ {"version":3,"file":"editor-server.js","names":[],"sources":["../../../../../src/nuxt/runtime/server/plugins/editor-server.ts"],"sourcesContent":["// Nitro's auto-imports are not applied to files under node_modules (the built package), so every Nitro/h3 helper is imported explicitly.\nimport { defineNitroPlugin, useRuntimeConfig } from 'nitropack/runtime'\nimport { type EditorServer, installEditorServer } from '../../../../adapters/nitro'\nimport type { EditorServerConfig } from '../../../../config'\nimport { useEditorBlockTypes, useEditorPorts, useEditorSchema } from '../../../../server/host'\n\n// Mounts the editor's routes and the collaboration websocket (`installEditorServer`) over the ports the host registered\n// with `setEditorPorts()`, and takes the AI configuration (presets, keys, roles, transcription), the rate limit and\n// `collab.authenticateUpgrade` from the module's runtime config.\n//\n// The host registers its ports in a Nitro plugin of its own, and Nitro does not order plugins of different layers and\n// modules reliably; the first request is the first moment every plugin has run (the routes it served before this\n// were file-based and read the ports per request, too). A failed install is retried by the next request.\nexport default defineNitroPlugin((nitroApp) => {\n let server: EditorServer | undefined\n nitroApp.hooks.hook('request', () => {\n server ??= install()\n })\n\n function install(): EditorServer {\n // The module's `serverConfig(defineEditorConfig(options))`, with the host's runtime-config and env overrides applied.\n const { ai, rateLimit, collab } = useRuntimeConfig().tiptapEditor as EditorServerConfig\n const ports = useEditorPorts()\n return installEditorServer(nitroApp, {\n ports,\n // Without persisted collaboration state the editor runs without the websocket (documents still load and save over HTTP).\n collab: ports.collabState ? collab : false,\n // Env names use the preset id in upper snake case (`flashLite` → `FLASH_LITE`), like Nuxt's runtime config mapping.\n ai: { ...ai, missingKeyHint: id => ` (NUXT_TIPTAP_EDITOR_AI_PRESETS_${id.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase()}_API_KEY oder NUXT_TIPTAP_EDITOR_AI_API_KEY)` },\n rateLimit,\n schema: useEditorSchema(),\n blockTypes: useEditorBlockTypes(),\n })\n }\n})\n"],"mappings":";;;;AAaA,IAAA,wBAAe,mBAAmB,aAAa;CAC7C,IAAI;CACJ,SAAS,MAAM,KAAK,iBAAiB;EACnC,WAAW,QAAQ;CACrB,CAAC;CAED,SAAS,UAAwB;EAE/B,MAAM,EAAE,IAAI,WAAW,WAAW,iBAAiB,CAAC,CAAC;EACrD,MAAM,QAAQ,eAAe;EAC7B,OAAO,oBAAoB,UAAU;GACnC;GAEA,QAAQ,MAAM,cAAc,SAAS;GAErC,IAAI;IAAE,GAAG;IAAI,iBAAgB,OAAM,mCAAmC,GAAG,QAAQ,sBAAsB,OAAO,CAAC,CAAC,YAAY,EAAE;GAA8C;GAC5K;GACA,QAAQ,gBAAgB;GACxB,YAAY,oBAAoB;EAClC,CAAC;CACH;AACF,CAAC"}
@@ -1,10 +1,10 @@
1
1
  import { EditorBackend } from "../core/backend.js";
2
2
  import { BlockUiOptions } from "../core/extension-points.js";
3
3
  import { EditorFeature, EditorPreset } from "../core/feature.js";
4
+ import { Basket } from "../features/composites/baskets.js";
5
+ import { BlockType } from "../features/composites/block-types.js";
4
6
  import { CoreContentOptions } from "../core/schema/index.js";
5
7
  import { CommentsFeatureOptions } from "../features/comments/feature.js";
6
- import { CompositeKind } from "../features/composites/kinds.js";
7
- import { Basket } from "../features/composites/baskets.js";
8
8
  import { CompositeFeatureOptions } from "../features/composites/feature.js";
9
9
  import { BlockTransform } from "../features/transfer/transforms.js";
10
10
  import { TransferFeatureOptions } from "../features/transfer/feature.js";
@@ -20,7 +20,7 @@ export type InteractionLevel = 'minimal' | 'full';
20
20
  * features are bound too, although `composite-ai` and `transcript-ai` have no components: the layer owns every import of
21
21
  * `features/ai`, so a composition without `ai` binds none of them and its bundle holds no AI code. Each binding is a
22
22
  * factory, called only for a feature the composition selects (`themes` reads the current Vue app when built, so
23
- * unselected features are never built). `composites` receives the composition's `compositeKinds` and `compositeBaskets`, `comments` its
23
+ * unselected features are never built). `composites` receives the composition's `blockTypes` and `compositeBaskets`, `comments` its
24
24
  * `comments` options. `core-ui` takes no parameter here: the framework-free `simpleEditor()` has no command palette;
25
25
  * a layer that has one (the `SimpleEditor` surfaces) builds `coreUiFeature({ palette })` itself.
26
26
  */
@@ -61,9 +61,9 @@ export interface ComposeOptions<C> {
61
61
  add?: readonly EditorFeature<C>[];
62
62
  /** Features left out (catalog or host); features that require them are omitted as well. */
63
63
  remove?: readonly FeatureId[];
64
- /** The composite kinds („Bausteine“) offered in the editor (default: the built-in kinds); read once. */
65
- compositeKinds?: readonly CompositeKind[];
66
- /** The colour baskets a Baustein can be put into (default: the built-in red/orange/yellow/green/blue set); read once. */
64
+ /** The Block types offered in the editor (default: the built-in Block types); read once. */
65
+ blockTypes?: readonly BlockType[];
66
+ /** The colour baskets a Typed block can be put into (default: the built-in red/orange/yellow/green/blue set); read once. */
67
67
  compositeBaskets?: readonly Basket[];
68
68
  /** Options of the comments feature, e.g. a host `model` (then comments need no `collab`). */
69
69
  comments?: CommentsFeatureOptions;
@@ -1,8 +1,8 @@
1
1
  import { defineEditor } from "../core/define-editor.js";
2
2
  import { coreContentFeature, coreUiFeature } from "../core/core-feature.js";
3
3
  import { CommentMark } from "../features/comments/schema.js";
4
- import { mentionsFeature } from "../features/mentions/index.js";
5
4
  import { copyTransform } from "../features/transfer/transforms.js";
5
+ import { mentionsFeature } from "../features/mentions/index.js";
6
6
  import { tablesFeature } from "../features/tables/feature.js";
7
7
  import { compositeMediaFeature } from "../integrations/composite-media/index.js";
8
8
  //#region src/presets/compose.ts
@@ -39,10 +39,13 @@ const CATALOG = {
39
39
  "composites": {
40
40
  dimension: "content",
41
41
  levels: ["rich"],
42
- build: (ui, options) => bound(ui, "composites")({
43
- ...options.compositeKinds && { kinds: options.compositeKinds },
44
- ...options.compositeBaskets && { baskets: options.compositeBaskets }
45
- })
42
+ build: (ui, options) => {
43
+ const { blockTypes } = options;
44
+ return bound(ui, "composites")({
45
+ ...blockTypes && { blockTypes },
46
+ ...options.compositeBaskets && { baskets: options.compositeBaskets }
47
+ });
48
+ }
46
49
  },
47
50
  "mentions": {
48
51
  dimension: "content",
@@ -1 +1 @@
1
- {"version":3,"file":"compose.js","names":[],"sources":["../../src/presets/compose.ts"],"sourcesContent":["import type { EditorBackend } from '../core/backend'\nimport { coreContentFeature, coreUiFeature } from '../core/core-feature'\nimport { defineEditor } from '../core/define-editor'\nimport type { BlockUiOptions } from '../core/extension-points'\nimport type { Dimension, EditorFeature, EditorPreset } from '../core/feature'\nimport type { CoreContentOptions } from '../core/schema'\nimport type { CommentsFeatureOptions } from '../features/comments/feature'\nimport { CommentMark } from '../features/comments/schema'\nimport type { CompositeFeatureOptions } from '../features/composites/feature'\nimport type { Basket } from '../features/composites/baskets'\nimport type { CompositeKind } from '../features/composites/kinds'\nimport { mentionsFeature } from '../features/mentions'\nimport type { TransferFeatureOptions } from '../features/transfer/feature'\nimport { type BlockTransform, copyTransform } from '../features/transfer/transforms'\nimport { tablesFeature } from '../features/tables'\nimport { compositeMediaFeature } from '../integrations/composite-media'\n\n/** The id of a catalog feature (`CONTENT`, `INTERACTION`, `AI`) or of a host feature passed to `remove`. */\nexport type FeatureId = string\n\n/** How much document model the editor has: `basic` = `core-content`, `rich` = the full content catalog. */\nexport type ContentLevel = 'basic' | 'rich'\n\n/** How much editing UX the editor has: `minimal` = `core-ui`, `full` = every interaction feature. */\nexport type InteractionLevel = 'minimal' | 'full'\n\n/**\n * The features a UI layer binds, keyed by id; the other catalog features are framework-free and built here. The AI\n * features are bound too, although `composite-ai` and `transcript-ai` have no components: the layer owns every import of\n * `features/ai`, so a composition without `ai` binds none of them and its bundle holds no AI code. Each binding is a\n * factory, called only for a feature the composition selects (`themes` reads the current Vue app when built, so\n * unselected features are never built). `composites` receives the composition's `compositeKinds` and `compositeBaskets`, `comments` its\n * `comments` options. `core-ui` takes no parameter here: the framework-free `simpleEditor()` has no command palette;\n * a layer that has one (the `SimpleEditor` surfaces) builds `coreUiFeature({ palette })` itself.\n */\nexport interface UiBindings<C> {\n 'core-ui': () => EditorFeature<C>\n 'media': () => EditorFeature<C>\n 'transcript': () => EditorFeature<C>\n 'composites': (options: CompositeFeatureOptions) => EditorFeature<C>\n 'authors': () => EditorFeature<C>\n 'comments': (options: CommentsFeatureOptions) => EditorFeature<C>\n 'ai': () => EditorFeature<C>\n 'composite-ai': () => EditorFeature<C>\n 'transcript-ai': () => EditorFeature<C>\n 'collab': () => EditorFeature<C>\n 'block-ui': (options: BlockUiOptions) => EditorFeature<C>\n 'themes': () => EditorFeature<C>\n 'transfer': (options: TransferFeatureOptions) => EditorFeature<C>\n /** The AI transforms of the transfer menu (`summaryTransform`, `bulletsTransform` of `integrations/composite-ai`); called only when `ai` is on and the host passes no `transfer.transforms`. */\n 'transfer-ai': () => readonly BlockTransform[]\n}\n\n/** What `composeEditor` builds the editor from. */\nexport interface ComposeOptions<C> {\n /** The document model: a level or the content feature ids to install (`core-content` is always installed). */\n content: ContentLevel | readonly FeatureId[]\n /** The editing UX: a level or the interaction feature ids (`core-ui` is installed with any non-empty list); `[]` = a viewer without any interaction feature. */\n interaction: InteractionLevel | readonly FeatureId[]\n /** Installs `ai` and every integration whose `requires` are met (composite-AI iff composites, transcript-AI iff transcript). */\n ai: boolean\n /** The backend the editor runs on: features needing a capability it lacks are omitted. Absent = nothing is pruned by capability. */\n backend?: EditorBackend\n /**\n * The host supplies the collaboration session itself (the surface's `collaboration` prop, e.g. from its own Hocuspocus\n * provider), so `collab` and `comments` need no `collaboration` capability from the backend. Only a backend that must\n * open the collaboration (`useEditorDocument(id, { collaboration: true })`) has to offer it. Default `false`.\n */\n collaboration?: boolean\n /** Host features, appended after the catalog in the given order. */\n add?: readonly EditorFeature<C>[]\n /** Features left out (catalog or host); features that require them are omitted as well. */\n remove?: readonly FeatureId[]\n /** The composite kinds („Bausteine“) offered in the editor (default: the built-in kinds); read once. */\n compositeKinds?: readonly CompositeKind[]\n /** The colour baskets a Baustein can be put into (default: the built-in red/orange/yellow/green/blue set); read once. */\n compositeBaskets?: readonly Basket[]\n /** Options of the comments feature, e.g. a host `model` (then comments need no `collab`). */\n comments?: CommentsFeatureOptions\n /** Optional structures the content base drops (headings or heading levels, lists, blockquote, code block, rule); everything is on by default. Applies to the editor and to the server schema built from the preset's `schemaExtensions`. */\n coreContent?: CoreContentOptions\n /** Options of the block UI (`block-ui`, `interaction: 'full'`): which surfaces render block actions (hover bar, selected-block toolbar, both, none); the hover bar by default. */\n blockUi?: BlockUiOptions\n /** Options of the transfer feature (`interaction: [..., 'transfer']`; in no level list): the transforms a drop offers (default: the copy, plus the AI transforms when `ai` is on) and the default one. */\n transfer?: TransferFeatureOptions\n}\n\n/** The composed preset and the features that were selected but dropped, in composition order, with the reason. */\nexport interface ComposedEditor<C> extends EditorPreset<C> {\n readonly omitted: readonly { id: FeatureId, reason: string }[]\n}\n\nfunction fail(message: string): never {\n throw new Error(`@ecsplico/editor: composeEditor: ${message}`)\n}\n\n/** The binding `key` of `ui`; a framework binding the composition needs but `ui` lacks fails here, naming it. */\nfunction bound<C, K extends keyof UiBindings<C>>(ui: Partial<UiBindings<C>>, key: K): UiBindings<C>[K] {\n return ui[key] ?? fail(`no UI binding for feature \"${key}\"`)\n}\n\n/** One row of the catalog: where the feature sits, which level lists hold it, and how it is built from the options. */\ninterface CatalogEntry<C> {\n dimension: Dimension\n /** The level lists (`CONTENT`, `INTERACTION`) that include it; none for AI features, which `ai: true` installs. */\n levels?: readonly (ContentLevel | InteractionLevel)[]\n /** `ui` is partial on purpose: a host that never selects a feature (a viewer has no `block-ui`) binds only the rest, so the bundle holds no code of the others. */\n build: (ui: Partial<UiBindings<C>>, options: ComposeOptions<C>) => EditorFeature<C>\n}\n\n/**\n * The catalog: the one table that drives composition. Its key order is the canonical order (content, interaction, AI):\n * the composed feature list, its schema order and its toolbar order follow it, and `CONTENT`, `INTERACTION`, `AI` are\n * derived from it. Adding a catalog feature is one row here, plus, for a UI-bound feature, a key in `UiBindings` and an\n * entry in both binding records (`vue/compose.ts`, `react/compose.ts`; their `satisfies UiBindings` check fails until\n * they hold it). Framework-free features are called directly, UI-bound ones go through `bound`.\n */\n// `any`: the table is module-level and shared by every UI layer; each `build` is typed by `UiBindings<C>` of its caller.\nconst CATALOG: Record<FeatureId, CatalogEntry<any>> = {\n 'core-content': { dimension: 'content', levels: ['basic', 'rich'], build: (_, options) => coreContentFeature(options.coreContent) },\n 'media': { dimension: 'content', levels: ['rich'], build: ui => bound(ui, 'media')() },\n 'transcript': { dimension: 'content', levels: ['rich'], build: ui => bound(ui, 'transcript')() },\n 'composites': { dimension: 'content', levels: ['rich'], build: (ui, options) => bound(ui, 'composites')({ ...(options.compositeKinds && { kinds: options.compositeKinds }), ...(options.compositeBaskets && { baskets: options.compositeBaskets }) }) },\n 'mentions': { dimension: 'content', levels: ['rich'], build: () => mentionsFeature() },\n 'authors': { dimension: 'content', levels: ['rich'], build: ui => bound(ui, 'authors')() },\n 'tables': { dimension: 'content', levels: ['rich'], build: () => tablesFeature() },\n 'composite-media': { dimension: 'content', levels: ['rich'], build: () => compositeMediaFeature() },\n 'core-ui': { dimension: 'interaction', levels: ['minimal', 'full'], build: ui => bound(ui, 'core-ui')() },\n 'collab': { dimension: 'interaction', levels: ['full'], build: ui => bound(ui, 'collab')() },\n 'comments': { dimension: 'interaction', levels: ['full'], build: (ui, options) => bound(ui, 'comments')(options.comments ?? {}) },\n 'block-ui': { dimension: 'interaction', levels: ['full'], build: (ui, options) => bound(ui, 'block-ui')(options.blockUi ?? {}) },\n 'themes': { dimension: 'interaction', levels: ['full'], build: ui => bound(ui, 'themes')() },\n // In no level list: a host opts in with `interaction: [...INTERACTION.full, 'transfer']`. With `ai` on the menu also offers the AI transforms (bound by the layer, which owns every import of `features/ai`), unless the host passes its own `transfer.transforms`.\n 'transfer': { dimension: 'interaction', build: (ui, options) => bound(ui, 'transfer')({ ...options.transfer, ...(!options.transfer?.transforms && options.ai && { transforms: [copyTransform, ...bound(ui, 'transfer-ai')()] }) }) },\n 'ai': { dimension: 'ai', build: ui => bound(ui, 'ai')() },\n 'composite-ai': { dimension: 'ai', build: ui => bound(ui, 'composite-ai')() },\n 'transcript-ai': { dimension: 'ai', build: ui => bound(ui, 'transcript-ai')() },\n}\n\nconst catalogIds = (include: (entry: CatalogEntry<unknown>) => boolean): readonly FeatureId[] =>\n Object.entries(CATALOG).filter(([, entry]) => include(entry)).map(([id]) => id)\nconst levelIds = (level: ContentLevel | InteractionLevel) => catalogIds(entry => entry.levels?.includes(level) ?? false)\n\n/** The content features of each level, in canonical (schema) order. */\nexport const CONTENT: Record<ContentLevel, readonly FeatureId[]> = { basic: levelIds('basic'), rich: levelIds('rich') }\n\n/** The interaction features of each level, in canonical order. */\nexport const INTERACTION: Record<InteractionLevel, readonly FeatureId[]> = { minimal: levelIds('minimal'), full: levelIds('full') }\n\n/** The AI features (`ai: true`): the AI feature and the integrations that need it; each is installed when its `requires` are met. */\nexport const AI: readonly FeatureId[] = catalogIds(entry => entry.dimension === 'ai')\n\n/** Canonical feature order: the key order of the catalog (content, interaction, AI). */\nconst CANONICAL: readonly FeatureId[] = Object.keys(CATALOG)\n\n/** Builds the catalog feature `id`; an id outside the catalog or a missing binding fails, naming it. */\nfunction build<C>(id: FeatureId, ui: Partial<UiBindings<C>>, options: ComposeOptions<C>): EditorFeature<C> {\n const entry = Object.hasOwn(CATALOG, id) ? CATALOG[id] : undefined\n if (!entry) fail(`unknown catalog feature \"${id}\" (host features go in \\`add\\`)`)\n return entry.build(ui, options)\n}\n\n/** Why `feature` cannot stay in a composition holding `ids` over `backend`, or `undefined`. A host session satisfies `collaboration`. */\nfunction unmet(feature: Pick<EditorFeature, 'backend' | 'requires'>, ids: ReadonlySet<FeatureId>, options: Pick<ComposeOptions<unknown>, 'backend' | 'collaboration'>): string | undefined {\n const { backend } = options\n for (const capability of feature.backend ?? []) {\n if (capability === 'collaboration' && options.collaboration) continue\n if (backend && backend[capability] === undefined) return `backend \"${backend.name}\" lacks \"${capability}\"`\n }\n for (const required of feature.requires ?? []) {\n if (!ids.has(required)) return `requires \"${required}\"`\n }\n return undefined\n}\n\n/**\n * The comment mark is part of the document model (stored documents carry it), but only the `comments` feature brings it.\n * A composition that keeps `authors` (every rich one) yet has no `comments` (a viewer, a backend without collaboration,\n * `remove`) gets the mark through `authors`, inert there, so such documents still load. The catalog is the one place\n * that may couple the two features; each stays importable on its own.\n */\nfunction withCommentMark<C>(features: readonly EditorFeature<C>[]): EditorFeature<C>[] {\n if (features.some(feature => feature.id === 'comments')) return [...features]\n return features.map(feature => feature.id !== 'authors'\n ? feature\n : {\n ...feature,\n schemaExtensions: () => [...(feature.schemaExtensions?.() ?? []), CommentMark],\n extensions: ctx => [...(feature.extensions?.(ctx) ?? []), CommentMark],\n })\n}\n\n/**\n * Composes an editor from three dimensions plus the backend's capabilities, over the UI bindings of a layer.\n *\n * The feature list is `content` + `interaction` (+ the AI features when `ai`) + `add`, minus `remove`. `core-content` is\n * always part of it and `core-ui` of every non-empty interaction list. Features that require a missing feature, or a\n * backend capability `options.backend` lacks, are dropped until the list is stable and reported in `omitted` (so\n * `ai: true` over a backend without `ai` installs no AI and says why). The catalog features keep their canonical order\n * (content, interaction, AI), host features follow in the order given; the result is validated by `defineEditor`.\n * Throws when an id of `content` is not a content feature, an id of `interaction` not an interaction feature, an id\n * names no catalog feature, `remove` names `core-content`, or a selected feature has no binding in `ui`.\n */\nexport function composeEditor<C>(ui: Partial<UiBindings<C>>, options: ComposeOptions<C>): ComposedEditor<C> {\n if (options.remove?.includes('core-content')) fail('\"core-content\" cannot be removed')\n const removed = new Set(options.remove ?? [])\n const catalog = new Map<FeatureId, EditorFeature<C>>()\n const select = (ids: readonly FeatureId[], dimension: 'content' | 'interaction' | 'ai') => {\n for (const id of ids) {\n if (removed.has(id) || catalog.has(id)) continue\n const feature = build(id, ui, options)\n if (feature.dimension !== dimension) fail(`\"${id}\" is not ${dimension === 'ai' ? 'an AI' : `a${dimension === 'interaction' ? 'n' : ''} ${dimension}`} feature`)\n catalog.set(id, feature)\n }\n }\n const content = typeof options.content === 'string' ? CONTENT[options.content] : options.content\n const interaction = typeof options.interaction === 'string' ? INTERACTION[options.interaction] : options.interaction\n select(['core-content', ...content], 'content')\n select(interaction.length ? ['core-ui', ...interaction] : [], 'interaction')\n select(options.ai ? AI : [], 'ai')\n\n const ordered = [...catalog.values()].sort((a, b) => CANONICAL.indexOf(a.id) - CANONICAL.indexOf(b.id))\n const all: EditorFeature<C>[] = [...ordered, ...(options.add ?? []).filter(feature => !removed.has(feature.id))]\n\n const reasons = new Map<FeatureId, string>()\n let alive = all\n for (;;) {\n const ids = new Set(alive.map(feature => feature.id))\n const dropped = new Map<FeatureId, string>()\n for (const feature of alive) {\n const reason = unmet(feature, ids, options)\n if (reason) dropped.set(feature.id, reason)\n }\n if (!dropped.size) break\n for (const [id, reason] of dropped) reasons.set(id, reason)\n alive = alive.filter(feature => !dropped.has(feature.id))\n }\n\n const preset = defineEditor({ features: withCommentMark(alive) })\n const omitted = all.flatMap(feature => reasons.has(feature.id) ? [{ id: feature.id, reason: reasons.get(feature.id)! }] : [])\n return Object.freeze({ ...preset, omitted: Object.freeze(omitted) })\n}\n\n/**\n * The simple editor: `core-content` and `core-ui` (formatting, headings, lists, quotes, code, undo/redo). No backend, no AI,\n * no collaboration, and no ⌘K command palette (`coreUiFeature()` gets no `palette` component here, the framework-free\n * layer has none; the `SimpleEditor` components and the `composeEditor` of `/vue/advanced` and `/react/advanced` bind it).\n * Component-free (`ComposedEditor<never>`), so both the Vue and the React surface accept it.\n */\nexport const simpleEditor = (): ComposedEditor<never> => composeEditor<never>({ 'core-ui': coreUiFeature }, { content: 'basic', interaction: 'minimal', ai: false })\n"],"mappings":"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"}
1
+ {"version":3,"file":"compose.js","names":[],"sources":["../../src/presets/compose.ts"],"sourcesContent":["import type { EditorBackend } from '../core/backend'\nimport { coreContentFeature, coreUiFeature } from '../core/core-feature'\nimport { defineEditor } from '../core/define-editor'\nimport type { BlockUiOptions } from '../core/extension-points'\nimport type { Dimension, EditorFeature, EditorPreset } from '../core/feature'\nimport type { CoreContentOptions } from '../core/schema'\nimport type { CommentsFeatureOptions } from '../features/comments/feature'\nimport { CommentMark } from '../features/comments/schema'\nimport type { CompositeFeatureOptions } from '../features/composites/feature'\nimport type { Basket } from '../features/composites/baskets'\nimport type { BlockType } from '../features/composites/block-types'\nimport { mentionsFeature } from '../features/mentions'\nimport type { TransferFeatureOptions } from '../features/transfer/feature'\nimport { type BlockTransform, copyTransform } from '../features/transfer/transforms'\nimport { tablesFeature } from '../features/tables'\nimport { compositeMediaFeature } from '../integrations/composite-media'\n\n/** The id of a catalog feature (`CONTENT`, `INTERACTION`, `AI`) or of a host feature passed to `remove`. */\nexport type FeatureId = string\n\n/** How much document model the editor has: `basic` = `core-content`, `rich` = the full content catalog. */\nexport type ContentLevel = 'basic' | 'rich'\n\n/** How much editing UX the editor has: `minimal` = `core-ui`, `full` = every interaction feature. */\nexport type InteractionLevel = 'minimal' | 'full'\n\n/**\n * The features a UI layer binds, keyed by id; the other catalog features are framework-free and built here. The AI\n * features are bound too, although `composite-ai` and `transcript-ai` have no components: the layer owns every import of\n * `features/ai`, so a composition without `ai` binds none of them and its bundle holds no AI code. Each binding is a\n * factory, called only for a feature the composition selects (`themes` reads the current Vue app when built, so\n * unselected features are never built). `composites` receives the composition's `blockTypes` and `compositeBaskets`, `comments` its\n * `comments` options. `core-ui` takes no parameter here: the framework-free `simpleEditor()` has no command palette;\n * a layer that has one (the `SimpleEditor` surfaces) builds `coreUiFeature({ palette })` itself.\n */\nexport interface UiBindings<C> {\n 'core-ui': () => EditorFeature<C>\n 'media': () => EditorFeature<C>\n 'transcript': () => EditorFeature<C>\n 'composites': (options: CompositeFeatureOptions) => EditorFeature<C>\n 'authors': () => EditorFeature<C>\n 'comments': (options: CommentsFeatureOptions) => EditorFeature<C>\n 'ai': () => EditorFeature<C>\n 'composite-ai': () => EditorFeature<C>\n 'transcript-ai': () => EditorFeature<C>\n 'collab': () => EditorFeature<C>\n 'block-ui': (options: BlockUiOptions) => EditorFeature<C>\n 'themes': () => EditorFeature<C>\n 'transfer': (options: TransferFeatureOptions) => EditorFeature<C>\n /** The AI transforms of the transfer menu (`summaryTransform`, `bulletsTransform` of `integrations/composite-ai`); called only when `ai` is on and the host passes no `transfer.transforms`. */\n 'transfer-ai': () => readonly BlockTransform[]\n}\n\n/** What `composeEditor` builds the editor from. */\nexport interface ComposeOptions<C> {\n /** The document model: a level or the content feature ids to install (`core-content` is always installed). */\n content: ContentLevel | readonly FeatureId[]\n /** The editing UX: a level or the interaction feature ids (`core-ui` is installed with any non-empty list); `[]` = a viewer without any interaction feature. */\n interaction: InteractionLevel | readonly FeatureId[]\n /** Installs `ai` and every integration whose `requires` are met (composite-AI iff composites, transcript-AI iff transcript). */\n ai: boolean\n /** The backend the editor runs on: features needing a capability it lacks are omitted. Absent = nothing is pruned by capability. */\n backend?: EditorBackend\n /**\n * The host supplies the collaboration session itself (the surface's `collaboration` prop, e.g. from its own Hocuspocus\n * provider), so `collab` and `comments` need no `collaboration` capability from the backend. Only a backend that must\n * open the collaboration (`useEditorDocument(id, { collaboration: true })`) has to offer it. Default `false`.\n */\n collaboration?: boolean\n /** Host features, appended after the catalog in the given order. */\n add?: readonly EditorFeature<C>[]\n /** Features left out (catalog or host); features that require them are omitted as well. */\n remove?: readonly FeatureId[]\n /** The Block types offered in the editor (default: the built-in Block types); read once. */\n blockTypes?: readonly BlockType[]\n /** The colour baskets a Typed block can be put into (default: the built-in red/orange/yellow/green/blue set); read once. */\n compositeBaskets?: readonly Basket[]\n /** Options of the comments feature, e.g. a host `model` (then comments need no `collab`). */\n comments?: CommentsFeatureOptions\n /** Optional structures the content base drops (headings or heading levels, lists, blockquote, code block, rule); everything is on by default. Applies to the editor and to the server schema built from the preset's `schemaExtensions`. */\n coreContent?: CoreContentOptions\n /** Options of the block UI (`block-ui`, `interaction: 'full'`): which surfaces render block actions (hover bar, selected-block toolbar, both, none); the hover bar by default. */\n blockUi?: BlockUiOptions\n /** Options of the transfer feature (`interaction: [..., 'transfer']`; in no level list): the transforms a drop offers (default: the copy, plus the AI transforms when `ai` is on) and the default one. */\n transfer?: TransferFeatureOptions\n}\n\n/** The composed preset and the features that were selected but dropped, in composition order, with the reason. */\nexport interface ComposedEditor<C> extends EditorPreset<C> {\n readonly omitted: readonly { id: FeatureId, reason: string }[]\n}\n\nfunction fail(message: string): never {\n throw new Error(`@ecsplico/editor: composeEditor: ${message}`)\n}\n\n/** The binding `key` of `ui`; a framework binding the composition needs but `ui` lacks fails here, naming it. */\nfunction bound<C, K extends keyof UiBindings<C>>(ui: Partial<UiBindings<C>>, key: K): UiBindings<C>[K] {\n return ui[key] ?? fail(`no UI binding for feature \"${key}\"`)\n}\n\n/** One row of the catalog: where the feature sits, which level lists hold it, and how it is built from the options. */\ninterface CatalogEntry<C> {\n dimension: Dimension\n /** The level lists (`CONTENT`, `INTERACTION`) that include it; none for AI features, which `ai: true` installs. */\n levels?: readonly (ContentLevel | InteractionLevel)[]\n /** `ui` is partial on purpose: a host that never selects a feature (a viewer has no `block-ui`) binds only the rest, so the bundle holds no code of the others. */\n build: (ui: Partial<UiBindings<C>>, options: ComposeOptions<C>) => EditorFeature<C>\n}\n\n/**\n * The catalog: the one table that drives composition. Its key order is the canonical order (content, interaction, AI):\n * the composed feature list, its schema order and its toolbar order follow it, and `CONTENT`, `INTERACTION`, `AI` are\n * derived from it. Adding a catalog feature is one row here, plus, for a UI-bound feature, a key in `UiBindings` and an\n * entry in both binding records (`vue/compose.ts`, `react/compose.ts`; their `satisfies UiBindings` check fails until\n * they hold it). Framework-free features are called directly, UI-bound ones go through `bound`.\n */\n// `any`: the table is module-level and shared by every UI layer; each `build` is typed by `UiBindings<C>` of its caller.\nconst CATALOG: Record<FeatureId, CatalogEntry<any>> = {\n 'core-content': { dimension: 'content', levels: ['basic', 'rich'], build: (_, options) => coreContentFeature(options.coreContent) },\n 'media': { dimension: 'content', levels: ['rich'], build: ui => bound(ui, 'media')() },\n 'transcript': { dimension: 'content', levels: ['rich'], build: ui => bound(ui, 'transcript')() },\n 'composites': {\n dimension: 'content',\n levels: ['rich'],\n build: (ui, options) => {\n const { blockTypes } = options\n return bound(ui, 'composites')({ ...(blockTypes && { blockTypes }), ...(options.compositeBaskets && { baskets: options.compositeBaskets }) })\n },\n },\n 'mentions': { dimension: 'content', levels: ['rich'], build: () => mentionsFeature() },\n 'authors': { dimension: 'content', levels: ['rich'], build: ui => bound(ui, 'authors')() },\n 'tables': { dimension: 'content', levels: ['rich'], build: () => tablesFeature() },\n 'composite-media': { dimension: 'content', levels: ['rich'], build: () => compositeMediaFeature() },\n 'core-ui': { dimension: 'interaction', levels: ['minimal', 'full'], build: ui => bound(ui, 'core-ui')() },\n 'collab': { dimension: 'interaction', levels: ['full'], build: ui => bound(ui, 'collab')() },\n 'comments': { dimension: 'interaction', levels: ['full'], build: (ui, options) => bound(ui, 'comments')(options.comments ?? {}) },\n 'block-ui': { dimension: 'interaction', levels: ['full'], build: (ui, options) => bound(ui, 'block-ui')(options.blockUi ?? {}) },\n 'themes': { dimension: 'interaction', levels: ['full'], build: ui => bound(ui, 'themes')() },\n // In no level list: a host opts in with `interaction: [...INTERACTION.full, 'transfer']`. With `ai` on the menu also offers the AI transforms (bound by the layer, which owns every import of `features/ai`), unless the host passes its own `transfer.transforms`.\n 'transfer': { dimension: 'interaction', build: (ui, options) => bound(ui, 'transfer')({ ...options.transfer, ...(!options.transfer?.transforms && options.ai && { transforms: [copyTransform, ...bound(ui, 'transfer-ai')()] }) }) },\n 'ai': { dimension: 'ai', build: ui => bound(ui, 'ai')() },\n 'composite-ai': { dimension: 'ai', build: ui => bound(ui, 'composite-ai')() },\n 'transcript-ai': { dimension: 'ai', build: ui => bound(ui, 'transcript-ai')() },\n}\n\nconst catalogIds = (include: (entry: CatalogEntry<unknown>) => boolean): readonly FeatureId[] =>\n Object.entries(CATALOG).filter(([, entry]) => include(entry)).map(([id]) => id)\nconst levelIds = (level: ContentLevel | InteractionLevel) => catalogIds(entry => entry.levels?.includes(level) ?? false)\n\n/** The content features of each level, in canonical (schema) order. */\nexport const CONTENT: Record<ContentLevel, readonly FeatureId[]> = { basic: levelIds('basic'), rich: levelIds('rich') }\n\n/** The interaction features of each level, in canonical order. */\nexport const INTERACTION: Record<InteractionLevel, readonly FeatureId[]> = { minimal: levelIds('minimal'), full: levelIds('full') }\n\n/** The AI features (`ai: true`): the AI feature and the integrations that need it; each is installed when its `requires` are met. */\nexport const AI: readonly FeatureId[] = catalogIds(entry => entry.dimension === 'ai')\n\n/** Canonical feature order: the key order of the catalog (content, interaction, AI). */\nconst CANONICAL: readonly FeatureId[] = Object.keys(CATALOG)\n\n/** Builds the catalog feature `id`; an id outside the catalog or a missing binding fails, naming it. */\nfunction build<C>(id: FeatureId, ui: Partial<UiBindings<C>>, options: ComposeOptions<C>): EditorFeature<C> {\n const entry = Object.hasOwn(CATALOG, id) ? CATALOG[id] : undefined\n if (!entry) fail(`unknown catalog feature \"${id}\" (host features go in \\`add\\`)`)\n return entry.build(ui, options)\n}\n\n/** Why `feature` cannot stay in a composition holding `ids` over `backend`, or `undefined`. A host session satisfies `collaboration`. */\nfunction unmet(feature: Pick<EditorFeature, 'backend' | 'requires'>, ids: ReadonlySet<FeatureId>, options: Pick<ComposeOptions<unknown>, 'backend' | 'collaboration'>): string | undefined {\n const { backend } = options\n for (const capability of feature.backend ?? []) {\n if (capability === 'collaboration' && options.collaboration) continue\n if (backend && backend[capability] === undefined) return `backend \"${backend.name}\" lacks \"${capability}\"`\n }\n for (const required of feature.requires ?? []) {\n if (!ids.has(required)) return `requires \"${required}\"`\n }\n return undefined\n}\n\n/**\n * The comment mark is part of the document model (stored documents carry it), but only the `comments` feature brings it.\n * A composition that keeps `authors` (every rich one) yet has no `comments` (a viewer, a backend without collaboration,\n * `remove`) gets the mark through `authors`, inert there, so such documents still load. The catalog is the one place\n * that may couple the two features; each stays importable on its own.\n */\nfunction withCommentMark<C>(features: readonly EditorFeature<C>[]): EditorFeature<C>[] {\n if (features.some(feature => feature.id === 'comments')) return [...features]\n return features.map(feature => feature.id !== 'authors'\n ? feature\n : {\n ...feature,\n schemaExtensions: () => [...(feature.schemaExtensions?.() ?? []), CommentMark],\n extensions: ctx => [...(feature.extensions?.(ctx) ?? []), CommentMark],\n })\n}\n\n/**\n * Composes an editor from three dimensions plus the backend's capabilities, over the UI bindings of a layer.\n *\n * The feature list is `content` + `interaction` (+ the AI features when `ai`) + `add`, minus `remove`. `core-content` is\n * always part of it and `core-ui` of every non-empty interaction list. Features that require a missing feature, or a\n * backend capability `options.backend` lacks, are dropped until the list is stable and reported in `omitted` (so\n * `ai: true` over a backend without `ai` installs no AI and says why). The catalog features keep their canonical order\n * (content, interaction, AI), host features follow in the order given; the result is validated by `defineEditor`.\n * Throws when an id of `content` is not a content feature, an id of `interaction` not an interaction feature, an id\n * names no catalog feature, `remove` names `core-content`, or a selected feature has no binding in `ui`.\n */\nexport function composeEditor<C>(ui: Partial<UiBindings<C>>, options: ComposeOptions<C>): ComposedEditor<C> {\n if (options.remove?.includes('core-content')) fail('\"core-content\" cannot be removed')\n const removed = new Set(options.remove ?? [])\n const catalog = new Map<FeatureId, EditorFeature<C>>()\n const select = (ids: readonly FeatureId[], dimension: 'content' | 'interaction' | 'ai') => {\n for (const id of ids) {\n if (removed.has(id) || catalog.has(id)) continue\n const feature = build(id, ui, options)\n if (feature.dimension !== dimension) fail(`\"${id}\" is not ${dimension === 'ai' ? 'an AI' : `a${dimension === 'interaction' ? 'n' : ''} ${dimension}`} feature`)\n catalog.set(id, feature)\n }\n }\n const content = typeof options.content === 'string' ? CONTENT[options.content] : options.content\n const interaction = typeof options.interaction === 'string' ? INTERACTION[options.interaction] : options.interaction\n select(['core-content', ...content], 'content')\n select(interaction.length ? ['core-ui', ...interaction] : [], 'interaction')\n select(options.ai ? AI : [], 'ai')\n\n const ordered = [...catalog.values()].sort((a, b) => CANONICAL.indexOf(a.id) - CANONICAL.indexOf(b.id))\n const all: EditorFeature<C>[] = [...ordered, ...(options.add ?? []).filter(feature => !removed.has(feature.id))]\n\n const reasons = new Map<FeatureId, string>()\n let alive = all\n for (;;) {\n const ids = new Set(alive.map(feature => feature.id))\n const dropped = new Map<FeatureId, string>()\n for (const feature of alive) {\n const reason = unmet(feature, ids, options)\n if (reason) dropped.set(feature.id, reason)\n }\n if (!dropped.size) break\n for (const [id, reason] of dropped) reasons.set(id, reason)\n alive = alive.filter(feature => !dropped.has(feature.id))\n }\n\n const preset = defineEditor({ features: withCommentMark(alive) })\n const omitted = all.flatMap(feature => reasons.has(feature.id) ? [{ id: feature.id, reason: reasons.get(feature.id)! }] : [])\n return Object.freeze({ ...preset, omitted: Object.freeze(omitted) })\n}\n\n/**\n * The simple editor: `core-content` and `core-ui` (formatting, headings, lists, quotes, code, undo/redo). No backend, no AI,\n * no collaboration, and no ⌘K command palette (`coreUiFeature()` gets no `palette` component here, the framework-free\n * layer has none; the `SimpleEditor` components and the `composeEditor` of `/vue/advanced` and `/react/advanced` bind it).\n * Component-free (`ComposedEditor<never>`), so both the Vue and the React surface accept it.\n */\nexport const simpleEditor = (): ComposedEditor<never> => composeEditor<never>({ 'core-ui': coreUiFeature }, { content: 'basic', interaction: 'minimal', ai: false })\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { ComposedEditorHandle, ComposedEditorProps } from "./composed-surface.js
4
4
  * Props of the advanced editor: the surface's own (collaboration session or standalone `value`/`onChange`, metadata,
5
5
  * abilities, extensions, block actions, commands, `documentId`, `editable`, `settingsUi`, the open state of the sidebar
6
6
  * and comments margin, `onReady` and the other callbacks) except the preset, plus the composition: `content`,
7
- * `interaction`, `ai`, `add`, `remove`, `backend` and the composite kinds. The defaults are the advanced editor's:
7
+ * `interaction`, `ai`, `add`, `remove`, `backend` and the Block types. The defaults are the advanced editor's:
8
8
  * `content: 'rich'`, `interaction: 'full'`, `ai: true`.
9
9
  */
10
10
  export type AdvancedEditorProps = ComposedEditorProps;
@@ -12,7 +12,7 @@ export type AdvancedEditorProps = ComposedEditorProps;
12
12
  * The advanced editor on the React surface: `composeEditor({ content: 'rich', interaction: 'full', ai: true })` mounted
13
13
  * through `EditorSurface`; every dimension is overridable by its prop, and the backend (default: the editor context's)
14
14
  * prunes what it cannot serve. The ref's `preset` is the composed preset (`omitted` lists the dropped features). The
15
- * composition is fixed at mount like the kinds it is built from; hosts remount (`key`) to change it. Place
15
+ * composition is fixed at mount like the Block types it is built from; hosts remount (`key`) to change it. Place
16
16
  * `EditorToolbar` and, with `settingsUi: 'external'`, `EditorSettingsModal`/`EditorSettingsPanel` beside it and give
17
17
  * them the editor from `onReady`; `useEditorUi(editor)` reaches the chrome of a ready editor. Collaboration is active
18
18
  * only when a `collaboration` session is passed; mount `Toaster` once for notices.
@@ -6,7 +6,7 @@ import { jsx } from "react/jsx-runtime";
6
6
  * The advanced editor on the React surface: `composeEditor({ content: 'rich', interaction: 'full', ai: true })` mounted
7
7
  * through `EditorSurface`; every dimension is overridable by its prop, and the backend (default: the editor context's)
8
8
  * prunes what it cannot serve. The ref's `preset` is the composed preset (`omitted` lists the dropped features). The
9
- * composition is fixed at mount like the kinds it is built from; hosts remount (`key`) to change it. Place
9
+ * composition is fixed at mount like the Block types it is built from; hosts remount (`key`) to change it. Place
10
10
  * `EditorToolbar` and, with `settingsUi: 'external'`, `EditorSettingsModal`/`EditorSettingsPanel` beside it and give
11
11
  * them the editor from `onReady`; `useEditorUi(editor)` reaches the chrome of a ready editor. Collaboration is active
12
12
  * only when a `collaboration` session is passed; mount `Toaster` once for notices.