@ecsplico/editor 2.1.2 → 3.1.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 (706) hide show
  1. package/CHANGELOG.md +78 -1
  2. package/README.md +39 -156
  3. package/dist/adapters/comments/drizzle.d.ts +1 -1
  4. package/dist/adapters/comments/record.d.ts +15 -0
  5. package/dist/adapters/comments/{client.js → rest-model.js} +3 -3
  6. package/dist/adapters/comments/rest-model.js.map +1 -0
  7. package/dist/adapters/comments/server.d.ts +2 -1
  8. package/dist/adapters/comments/server.js +2 -1
  9. package/dist/adapters/comments/server.js.map +1 -1
  10. package/dist/adapters/comments/types.d.ts +2 -2
  11. package/dist/adapters/document-state.d.ts +23 -0
  12. package/dist/adapters/document-state.js +66 -0
  13. package/dist/adapters/document-state.js.map +1 -0
  14. package/dist/adapters/documents.js +14 -11
  15. package/dist/adapters/documents.js.map +1 -1
  16. package/dist/adapters/drizzle.d.ts +2 -2
  17. package/dist/adapters/drizzle.js +97 -88
  18. package/dist/adapters/drizzle.js.map +1 -1
  19. package/dist/adapters/forge.d.ts +12 -7
  20. package/dist/adapters/forge.js +38 -45
  21. package/dist/adapters/forge.js.map +1 -1
  22. package/dist/adapters/http.d.ts +20 -0
  23. package/dist/adapters/http.js +68 -0
  24. package/dist/adapters/http.js.map +1 -0
  25. package/dist/adapters/index.d.ts +5 -5
  26. package/dist/adapters/json.d.ts +3 -3
  27. package/dist/adapters/json.js +58 -49
  28. package/dist/adapters/json.js.map +1 -1
  29. package/dist/adapters/memory.d.ts +21 -0
  30. package/dist/adapters/memory.js +53 -0
  31. package/dist/adapters/memory.js.map +1 -0
  32. package/dist/adapters/nitro.d.ts +27 -20
  33. package/dist/adapters/nitro.js +59 -163
  34. package/dist/adapters/nitro.js.map +1 -1
  35. package/dist/adapters/react.d.ts +55 -0
  36. package/dist/adapters/react.js +209 -0
  37. package/dist/adapters/react.js.map +1 -0
  38. package/dist/adapters/shared.d.ts +15 -21
  39. package/dist/adapters/shared.js +10 -8
  40. package/dist/adapters/shared.js.map +1 -1
  41. package/dist/adapters/vue.d.ts +15 -30
  42. package/dist/adapters/vue.js +36 -87
  43. package/dist/adapters/vue.js.map +1 -1
  44. package/dist/code/CodeSurface.vue.d.ts +2 -2
  45. package/dist/config/index.d.ts +105 -0
  46. package/dist/config/index.js +95 -0
  47. package/dist/config/index.js.map +1 -0
  48. package/dist/core/abilities.js +1 -0
  49. package/dist/core/abilities.js.map +1 -1
  50. package/dist/{adapters/routes.js → core/api-routes.js} +5 -3
  51. package/dist/core/api-routes.js.map +1 -0
  52. package/dist/core/backend-capability.d.ts +7 -0
  53. package/dist/core/backend-capability.js +17 -0
  54. package/dist/core/backend-capability.js.map +1 -0
  55. package/dist/core/backend-types.d.ts +245 -0
  56. package/dist/core/backend-types.js +17 -0
  57. package/dist/core/backend-types.js.map +1 -0
  58. package/dist/core/backend.d.ts +108 -0
  59. package/dist/core/backend.js +14 -0
  60. package/dist/core/backend.js.map +1 -0
  61. package/dist/core/block-convert.d.ts +7 -5
  62. package/dist/core/block-convert.js +28 -5
  63. package/dist/core/block-convert.js.map +1 -1
  64. package/dist/core/command-types.d.ts +96 -0
  65. package/dist/core/commands.d.ts +40 -0
  66. package/dist/core/commands.js +151 -0
  67. package/dist/core/commands.js.map +1 -0
  68. package/dist/core/context.d.ts +17 -20
  69. package/dist/core/context.js +24 -21
  70. package/dist/core/context.js.map +1 -1
  71. package/dist/core/core-feature.d.ts +22 -7
  72. package/dist/core/core-feature.js +51 -18
  73. package/dist/core/core-feature.js.map +1 -1
  74. package/dist/core/define-editor.d.ts +4 -3
  75. package/dist/core/define-editor.js +14 -7
  76. package/dist/core/define-editor.js.map +1 -1
  77. package/dist/core/document-markdown.js +12 -3
  78. package/dist/core/document-markdown.js.map +1 -1
  79. package/dist/core/editor-ui.d.ts +8 -1
  80. package/dist/core/editor-ui.js +9 -8
  81. package/dist/core/editor-ui.js.map +1 -1
  82. package/dist/core/extension-points.d.ts +3 -15
  83. package/dist/core/feature-context.d.ts +8 -7
  84. package/dist/core/feature-context.js +12 -11
  85. package/dist/core/feature-context.js.map +1 -1
  86. package/dist/core/feature.d.ts +41 -19
  87. package/dist/core/feature.js.map +1 -1
  88. package/dist/core/fences.d.ts +2 -1
  89. package/dist/core/fences.js +3 -2
  90. package/dist/core/fences.js.map +1 -1
  91. package/dist/core/fetch-error.d.ts +1 -1
  92. package/dist/core/fetch-error.js +3 -1
  93. package/dist/core/fetch-error.js.map +1 -1
  94. package/dist/core/hash.d.ts +5 -0
  95. package/dist/core/hash.js +11 -0
  96. package/dist/core/hash.js.map +1 -0
  97. package/dist/core/http-backend.d.ts +11 -0
  98. package/dist/core/http-backend.js +195 -0
  99. package/dist/core/http-backend.js.map +1 -0
  100. package/dist/core/index.d.ts +15 -9
  101. package/dist/core/index.js +13 -9
  102. package/dist/core/palette.d.ts +48 -0
  103. package/dist/core/palette.js +95 -0
  104. package/dist/core/palette.js.map +1 -0
  105. package/dist/core/schema/abilities.d.ts +2 -1
  106. package/dist/core/schema/abilities.js +5 -1
  107. package/dist/core/schema/abilities.js.map +1 -1
  108. package/dist/core/schema/index.d.ts +11 -5
  109. package/dist/core/schema/index.js +13 -8
  110. package/dist/core/schema/index.js.map +1 -1
  111. package/dist/core/schema/mark-flags.d.ts +8 -1
  112. package/dist/core/schema/of-features.d.ts +13 -0
  113. package/dist/core/schema/of-features.js +14 -0
  114. package/dist/core/schema/of-features.js.map +1 -0
  115. package/dist/core/slash.d.ts +8 -6
  116. package/dist/core/slash.js +24 -16
  117. package/dist/core/slash.js.map +1 -1
  118. package/dist/core/surface-session.js +15 -5
  119. package/dist/core/surface-session.js.map +1 -1
  120. package/dist/core/toolbar-items.d.ts +10 -4
  121. package/dist/core/toolbar-items.js +269 -195
  122. package/dist/core/toolbar-items.js.map +1 -1
  123. package/dist/core/transaction-guards.d.ts +21 -0
  124. package/dist/core/transaction-guards.js +49 -0
  125. package/dist/core/transaction-guards.js.map +1 -0
  126. package/dist/core/util.js +11 -0
  127. package/dist/core/util.js.map +1 -0
  128. package/dist/document/DocumentSurface.d.ts +1 -1
  129. package/dist/document/DocumentSurface.vue.d.ts +2 -2
  130. package/dist/features/ai/agent-op-review.d.ts +1 -1
  131. package/dist/features/ai/agent-op-review.js +1 -1
  132. package/dist/features/ai/agent-ops.js +1 -1
  133. package/dist/features/ai/ai-apply.d.ts +2 -2
  134. package/dist/features/ai/ai-apply.js +1 -1
  135. package/dist/features/ai/ai-review.js +1 -1
  136. package/dist/features/ai/ai-sse.d.ts +6 -6
  137. package/dist/features/ai/ai-sse.js +20 -63
  138. package/dist/features/ai/ai-sse.js.map +1 -1
  139. package/dist/features/ai/assistant.d.ts +8 -7
  140. package/dist/features/ai/assistant.js +3 -3
  141. package/dist/features/ai/assistant.js.map +1 -1
  142. package/dist/features/ai/block-actions.d.ts +3 -2
  143. package/dist/features/ai/block-actions.js +3 -2
  144. package/dist/features/ai/block-actions.js.map +1 -1
  145. package/dist/features/ai/components/AiSelectionMenu.js +1 -1
  146. package/dist/features/ai/components/DocumentChatAnswer.js +1 -1
  147. package/dist/features/ai/components/DocumentChatOps.vue.d.ts +1 -1
  148. package/dist/features/ai/components/SettingsModelProfiles.js +8 -8
  149. package/dist/features/ai/components/SettingsModelProfiles.js.map +1 -1
  150. package/dist/features/ai/document-chat-model.d.ts +8 -7
  151. package/dist/features/ai/document-chat-model.js +5 -5
  152. package/dist/features/ai/document-chat-model.js.map +1 -1
  153. package/dist/features/ai/document-chat.js +1 -1
  154. package/dist/features/ai/feature.js +27 -14
  155. package/dist/features/ai/feature.js.map +1 -1
  156. package/dist/features/ai/ghost-autocomplete.d.ts +7 -6
  157. package/dist/features/ai/ghost-autocomplete.js +6 -9
  158. package/dist/features/ai/ghost-autocomplete.js.map +1 -1
  159. package/dist/features/ai/index.d.ts +4 -3
  160. package/dist/features/ai/index.js +10 -10
  161. package/dist/features/ai/model-profiles.d.ts +5 -4
  162. package/dist/features/ai/model-profiles.js +2 -2
  163. package/dist/features/ai/model-profiles.js.map +1 -1
  164. package/dist/features/ai/protocol/block-lines.js +1 -1
  165. package/dist/features/ai/protocol/block-lines.js.map +1 -1
  166. package/dist/features/ai/protocol/chat.js +6 -2
  167. package/dist/features/ai/protocol/chat.js.map +1 -1
  168. package/dist/features/ai/protocol/index.d.ts +3 -2
  169. package/dist/features/ai/protocol/models.d.ts +2 -16
  170. package/dist/features/ai/protocol/models.js.map +1 -1
  171. package/dist/features/ai/rate-limit.d.ts +1 -1
  172. package/dist/features/ai/rate-limit.js +3 -1
  173. package/dist/features/ai/rate-limit.js.map +1 -1
  174. package/dist/features/ai/react/AiSelectionMenu.js +2 -2
  175. package/dist/features/ai/react/AiSidebar.js +4 -4
  176. package/dist/features/ai/react/DocumentChatAnswer.js +1 -1
  177. package/dist/features/ai/react/DocumentChatOps.d.ts +1 -1
  178. package/dist/features/ai/react/DocumentChatOps.js +1 -1
  179. package/dist/features/ai/react/SettingsModelProfiles.js +8 -10
  180. package/dist/features/ai/react/SettingsModelProfiles.js.map +1 -1
  181. package/dist/features/ai/react/use-ai-assistant.d.ts +1 -1
  182. package/dist/features/ai/react/use-ai-assistant.js +3 -3
  183. package/dist/features/ai/react/use-ai-assistant.js.map +1 -1
  184. package/dist/features/ai/react/use-document-chat.js +2 -2
  185. package/dist/features/ai/react/use-document-chat.js.map +1 -1
  186. package/dist/features/ai/react/use-model-profiles.d.ts +2 -1
  187. package/dist/features/ai/selection-flow.d.ts +1 -1
  188. package/dist/features/ai/selection-flow.js +1 -1
  189. package/dist/features/ai/sidebar-flow.d.ts +1 -1
  190. package/dist/features/ai/sidebar-flow.js +1 -1
  191. package/dist/features/ai/use-ai-assistant.d.ts +1 -1
  192. package/dist/features/ai/use-ai-assistant.js +3 -3
  193. package/dist/features/ai/use-ai-assistant.js.map +1 -1
  194. package/dist/features/ai/use-document-chat.js +2 -2
  195. package/dist/features/ai/use-document-chat.js.map +1 -1
  196. package/dist/features/ai/use-model-profiles.d.ts +2 -1
  197. package/dist/features/authors/attribution.d.ts +1 -1
  198. package/dist/features/authors/feature.js +12 -11
  199. package/dist/features/authors/feature.js.map +1 -1
  200. package/dist/features/block-ui/block-actions.d.ts +1 -1
  201. package/dist/features/block-ui/block-actions.js +1 -1
  202. package/dist/features/block-ui/block-actions.js.map +1 -1
  203. package/dist/features/block-ui/components/BlockUi.js +1 -1
  204. package/dist/features/block-ui/feature.js +1 -0
  205. package/dist/features/block-ui/feature.js.map +1 -1
  206. package/dist/features/block-ui/react/BlockUi.js +1 -1
  207. package/dist/features/collab/anchor-resolver.js +1 -1
  208. package/dist/features/collab/feature.js +2 -0
  209. package/dist/features/collab/feature.js.map +1 -1
  210. package/dist/features/comments/components/CommentThreadView.vue.d.ts +2 -1
  211. package/dist/features/comments/feature.js +12 -11
  212. package/dist/features/comments/feature.js.map +1 -1
  213. package/dist/features/comments/index.d.ts +3 -2
  214. package/dist/features/comments/index.js +1 -1
  215. package/dist/features/comments/margin-layout.d.ts +3 -2
  216. package/dist/features/comments/model.d.ts +3 -67
  217. package/dist/features/comments/model.js +2 -2
  218. package/dist/features/comments/model.js.map +1 -1
  219. package/dist/features/comments/react/CommentThreadView.d.ts +3 -2
  220. package/dist/features/comments/react/use-comments.d.ts +2 -1
  221. package/dist/features/comments/react.d.ts +1 -1
  222. package/dist/features/comments/schema.d.ts +2 -52
  223. package/dist/features/comments/schema.js.map +1 -1
  224. package/dist/features/comments/snapshot-equality.js.map +1 -1
  225. package/dist/features/comments/use-comments.d.ts +3 -2
  226. package/dist/features/comments/vue.d.ts +1 -1
  227. package/dist/features/composites/accepted-children.d.ts +1 -0
  228. package/dist/features/composites/accepted-children.js +16 -1
  229. package/dist/features/composites/accepted-children.js.map +1 -1
  230. package/dist/features/composites/ai-brief.js +39 -0
  231. package/dist/features/composites/ai-brief.js.map +1 -1
  232. package/dist/features/composites/bibliography-command.d.ts +11 -0
  233. package/dist/features/composites/bibliography-form.js +90 -0
  234. package/dist/features/composites/bibliography-form.js.map +1 -0
  235. package/dist/features/composites/bibliography.d.ts +33 -0
  236. package/dist/features/composites/bibliography.js +120 -0
  237. package/dist/features/composites/bibliography.js.map +1 -0
  238. package/dist/features/composites/components/BibliographyEditor.js +261 -0
  239. package/dist/features/composites/components/BibliographyEditor.js.map +1 -0
  240. package/dist/features/composites/components/CompositeChrome.js +78 -29
  241. package/dist/features/composites/components/CompositeChrome.js.map +1 -1
  242. package/dist/features/composites/components/CompositeChrome.vue.d.ts +1 -1
  243. package/dist/features/composites/components/CompositeDetails.js +46 -11
  244. package/dist/features/composites/components/CompositeDetails.js.map +1 -1
  245. package/dist/features/composites/components/CompositeDetails.vue.d.ts +2 -1
  246. package/dist/features/composites/components/CompositeFieldEditor.js +64 -5
  247. package/dist/features/composites/components/CompositeFieldEditor.js.map +1 -1
  248. package/dist/features/composites/components/CompositeInspector.js +20 -7
  249. package/dist/features/composites/components/CompositeInspector.js.map +1 -1
  250. package/dist/features/composites/components/CompositeTable.js +13 -4
  251. package/dist/features/composites/components/CompositeTable.js.map +1 -1
  252. package/dist/features/composites/components/CompositeTagsEditor.js +1 -1
  253. package/dist/features/composites/components/CompositeView.js +11 -1
  254. package/dist/features/composites/components/CompositeView.js.map +1 -1
  255. package/dist/features/composites/components/DerivationBadge.js +103 -0
  256. package/dist/features/composites/components/DerivationBadge.js.map +1 -0
  257. package/dist/features/composites/components/ReferenceFieldSelect.js +60 -0
  258. package/dist/features/composites/components/ReferenceFieldSelect.js.map +1 -0
  259. package/dist/features/composites/components/ReferenceView.js +122 -0
  260. package/dist/features/composites/components/ReferenceView.js.map +1 -0
  261. package/dist/features/composites/components/ReferenceView.vue.d.ts +96 -0
  262. package/dist/features/composites/components/SettingsEditingTab.js +1 -1
  263. package/dist/features/composites/convert.js +2 -2
  264. package/dist/features/composites/convert.js.map +1 -1
  265. package/dist/features/composites/derivation.d.ts +61 -0
  266. package/dist/features/composites/derivation.js +98 -0
  267. package/dist/features/composites/derivation.js.map +1 -0
  268. package/dist/features/composites/derived-chrome.js +69 -0
  269. package/dist/features/composites/derived-chrome.js.map +1 -0
  270. package/dist/features/composites/feature.js +159 -109
  271. package/dist/features/composites/feature.js.map +1 -1
  272. package/dist/features/composites/fences.d.ts +4 -3
  273. package/dist/features/composites/fences.js +51 -7
  274. package/dist/features/composites/fences.js.map +1 -1
  275. package/dist/features/composites/index.d.ts +12 -3
  276. package/dist/features/composites/index.js +15 -6
  277. package/dist/features/composites/inspector-model.d.ts +4 -1
  278. package/dist/features/composites/inspector-model.js +8 -4
  279. package/dist/features/composites/inspector-model.js.map +1 -1
  280. package/dist/features/composites/kinds.d.ts +16 -2
  281. package/dist/features/composites/kinds.js +145 -6
  282. package/dist/features/composites/kinds.js.map +1 -1
  283. package/dist/features/composites/legacy.d.ts +4 -1
  284. package/dist/features/composites/legacy.js +56 -1
  285. package/dist/features/composites/legacy.js.map +1 -1
  286. package/dist/features/composites/meta-display.js +45 -2
  287. package/dist/features/composites/meta-display.js.map +1 -1
  288. package/dist/features/composites/meta-keys.d.ts +7 -0
  289. package/dist/features/composites/meta-keys.js +21 -0
  290. package/dist/features/composites/meta-keys.js.map +1 -0
  291. package/dist/features/composites/node-views.d.ts +6 -3
  292. package/dist/features/composites/node-views.js +7 -3
  293. package/dist/features/composites/node-views.js.map +1 -1
  294. package/dist/features/composites/nodes.d.ts +6 -1
  295. package/dist/features/composites/nodes.js +33 -7
  296. package/dist/features/composites/nodes.js.map +1 -1
  297. package/dist/features/composites/react/BibliographyEditor.js +229 -0
  298. package/dist/features/composites/react/BibliographyEditor.js.map +1 -0
  299. package/dist/features/composites/react/CompositeChrome.js +67 -19
  300. package/dist/features/composites/react/CompositeChrome.js.map +1 -1
  301. package/dist/features/composites/react/CompositeDetails.d.ts +2 -1
  302. package/dist/features/composites/react/CompositeDetails.js +45 -6
  303. package/dist/features/composites/react/CompositeDetails.js.map +1 -1
  304. package/dist/features/composites/react/CompositeFieldEditor.d.ts +1 -1
  305. package/dist/features/composites/react/CompositeFieldEditor.js +43 -1
  306. package/dist/features/composites/react/CompositeFieldEditor.js.map +1 -1
  307. package/dist/features/composites/react/CompositeInspector.js +12 -6
  308. package/dist/features/composites/react/CompositeInspector.js.map +1 -1
  309. package/dist/features/composites/react/CompositeStatusMenu.js +1 -1
  310. package/dist/features/composites/react/CompositeSummaryEditor.js +1 -1
  311. package/dist/features/composites/react/CompositeTable.js +16 -2
  312. package/dist/features/composites/react/CompositeTable.js.map +1 -1
  313. package/dist/features/composites/react/CompositeTagsEditor.js +2 -2
  314. package/dist/features/composites/react/CompositeView.js +6 -1
  315. package/dist/features/composites/react/CompositeView.js.map +1 -1
  316. package/dist/features/composites/react/DerivationBadge.js +116 -0
  317. package/dist/features/composites/react/DerivationBadge.js.map +1 -0
  318. package/dist/features/composites/react/ReferenceFieldSelect.js +52 -0
  319. package/dist/features/composites/react/ReferenceFieldSelect.js.map +1 -0
  320. package/dist/features/composites/react/ReferenceView.d.ts +11 -0
  321. package/dist/features/composites/react/ReferenceView.js +115 -0
  322. package/dist/features/composites/react/ReferenceView.js.map +1 -0
  323. package/dist/features/composites/react/SettingsEditingTab.js +2 -2
  324. package/dist/features/composites/react.d.ts +2 -1
  325. package/dist/features/composites/react.js +7 -3
  326. package/dist/features/composites/react.js.map +1 -1
  327. package/dist/features/composites/reference-ai.js +16 -0
  328. package/dist/features/composites/reference-ai.js.map +1 -0
  329. package/dist/features/composites/reference-label.d.ts +19 -0
  330. package/dist/features/composites/reference-label.js +58 -0
  331. package/dist/features/composites/reference-label.js.map +1 -0
  332. package/dist/features/composites/reference-suggestion.d.ts +10 -0
  333. package/dist/features/composites/reference-suggestion.js +41 -0
  334. package/dist/features/composites/reference-suggestion.js.map +1 -0
  335. package/dist/features/composites/reference-text.d.ts +18 -0
  336. package/dist/features/composites/reference-text.js +89 -0
  337. package/dist/features/composites/reference-text.js.map +1 -0
  338. package/dist/features/composites/reference.d.ts +44 -0
  339. package/dist/features/composites/reference.js +148 -0
  340. package/dist/features/composites/reference.js.map +1 -0
  341. package/dist/features/composites/reveal-source.d.ts +32 -0
  342. package/dist/features/composites/reveal-source.js +89 -0
  343. package/dist/features/composites/reveal-source.js.map +1 -0
  344. package/dist/features/composites/rows.d.ts +25 -3
  345. package/dist/features/composites/rows.js +72 -10
  346. package/dist/features/composites/rows.js.map +1 -1
  347. package/dist/features/composites/schema.d.ts +9 -3
  348. package/dist/features/composites/schema.js +11 -4
  349. package/dist/features/composites/schema.js.map +1 -1
  350. package/dist/features/composites/table-model.js +12 -21
  351. package/dist/features/composites/table-model.js.map +1 -1
  352. package/dist/features/composites/vue.d.ts +3 -2
  353. package/dist/features/composites/vue.js +8 -4
  354. package/dist/features/composites/vue.js.map +1 -1
  355. package/dist/features/media/assets.d.ts +2 -0
  356. package/dist/features/media/assets.js +3 -2
  357. package/dist/features/media/assets.js.map +1 -1
  358. package/dist/features/media/components/FileView.js +13 -4
  359. package/dist/features/media/components/FileView.js.map +1 -1
  360. package/dist/features/media/feature.d.ts +3 -3
  361. package/dist/features/media/feature.js +21 -28
  362. package/dist/features/media/feature.js.map +1 -1
  363. package/dist/features/media/file-import.js +2 -2
  364. package/dist/features/media/file-import.js.map +1 -1
  365. package/dist/features/media/index.d.ts +2 -2
  366. package/dist/features/media/index.js +3 -3
  367. package/dist/features/media/react/AudioRecorderModal.js +1 -1
  368. package/dist/features/media/react/FileView.js +19 -2
  369. package/dist/features/media/react/FileView.js.map +1 -1
  370. package/dist/features/media/react.js +1 -1
  371. package/dist/features/media/schema.d.ts +8 -0
  372. package/dist/features/media/schema.js +126 -11
  373. package/dist/features/media/schema.js.map +1 -1
  374. package/dist/features/media/upload.d.ts +16 -14
  375. package/dist/features/media/upload.js +13 -19
  376. package/dist/features/media/upload.js.map +1 -1
  377. package/dist/features/mentions/index.d.ts +4 -3
  378. package/dist/features/mentions/index.js +4 -1
  379. package/dist/features/mentions/index.js.map +1 -1
  380. package/dist/features/mentions/mention-text.d.ts +1 -1
  381. package/dist/features/mentions/mention-text.js.map +1 -1
  382. package/dist/features/mentions/mention.d.ts +0 -6
  383. package/dist/features/mentions/mention.js.map +1 -1
  384. package/dist/features/mentions/metadata-defaults.d.ts +2 -2
  385. package/dist/features/mentions/metadata-defaults.js +3 -9
  386. package/dist/features/mentions/metadata-defaults.js.map +1 -1
  387. package/dist/features/mentions/schema.d.ts +2 -1
  388. package/dist/features/mentions/schema.js.map +1 -1
  389. package/dist/features/tables/feature.d.ts +2 -1
  390. package/dist/features/tables/feature.js +90 -70
  391. package/dist/features/tables/feature.js.map +1 -1
  392. package/dist/features/themes/components/SettingsAppearanceTab.js +6 -9
  393. package/dist/features/themes/components/SettingsAppearanceTab.js.map +1 -1
  394. package/dist/features/themes/feature.js +2 -0
  395. package/dist/features/themes/feature.js.map +1 -1
  396. package/dist/features/themes/index.d.ts +2 -1
  397. package/dist/features/themes/react/SettingsAppearanceTab.js +7 -10
  398. package/dist/features/themes/react/SettingsAppearanceTab.js.map +1 -1
  399. package/dist/features/themes/schema.d.ts +2 -6
  400. package/dist/features/themes/schema.js.map +1 -1
  401. package/dist/features/themes/theme-runtime.d.ts +1 -1
  402. package/dist/features/themes/theme-runtime.js +4 -2
  403. package/dist/features/themes/theme-runtime.js.map +1 -1
  404. package/dist/features/transcript/TranscriptSegmentView.js +48 -28
  405. package/dist/features/transcript/TranscriptSegmentView.js.map +1 -1
  406. package/dist/features/transcript/feature.js +21 -19
  407. package/dist/features/transcript/feature.js.map +1 -1
  408. package/dist/features/transcript/react/TranscriptSegmentView.js +55 -36
  409. package/dist/features/transcript/react/TranscriptSegmentView.js.map +1 -1
  410. package/dist/features/transcript/segment-node.d.ts +2 -0
  411. package/dist/features/transcript/segment-node.js +35 -7
  412. package/dist/features/transcript/segment-node.js.map +1 -1
  413. package/dist/i18n/de/composites.js +91 -1
  414. package/dist/i18n/de/composites.js.map +1 -1
  415. package/dist/i18n/de/integrations.js +49 -8
  416. package/dist/i18n/de/integrations.js.map +1 -1
  417. package/dist/i18n/de/media.js +0 -1
  418. package/dist/i18n/de/media.js.map +1 -1
  419. package/dist/i18n/de/palette.js +22 -0
  420. package/dist/i18n/de/palette.js.map +1 -0
  421. package/dist/i18n/de/tables.js +0 -1
  422. package/dist/i18n/de/tables.js.map +1 -1
  423. package/dist/i18n/de/transcript.js +2 -1
  424. package/dist/i18n/de/transcript.js.map +1 -1
  425. package/dist/i18n/de/tree.js +3 -0
  426. package/dist/i18n/de/tree.js.map +1 -1
  427. package/dist/i18n/de.d.ts +157 -11
  428. package/dist/i18n/de.js +3 -1
  429. package/dist/i18n/de.js.map +1 -1
  430. package/dist/i18n/en/composites.js +89 -1
  431. package/dist/i18n/en/composites.js.map +1 -1
  432. package/dist/i18n/en/integrations.js +49 -8
  433. package/dist/i18n/en/integrations.js.map +1 -1
  434. package/dist/i18n/en/media.js +0 -1
  435. package/dist/i18n/en/media.js.map +1 -1
  436. package/dist/i18n/en/palette.js +22 -0
  437. package/dist/i18n/en/palette.js.map +1 -0
  438. package/dist/i18n/en/tables.js +0 -1
  439. package/dist/i18n/en/tables.js.map +1 -1
  440. package/dist/i18n/en/transcript.js +2 -1
  441. package/dist/i18n/en/transcript.js.map +1 -1
  442. package/dist/i18n/en/tree.js +3 -0
  443. package/dist/i18n/en/tree.js.map +1 -1
  444. package/dist/i18n/en.js +3 -1
  445. package/dist/i18n/en.js.map +1 -1
  446. package/dist/index.d.ts +4 -3
  447. package/dist/integrations/composite-ai/bibliography-fetch.d.ts +31 -0
  448. package/dist/integrations/composite-ai/bibliography-fetch.js +159 -0
  449. package/dist/integrations/composite-ai/bibliography-fetch.js.map +1 -0
  450. package/dist/integrations/composite-ai/composite-fill.d.ts +30 -8
  451. package/dist/integrations/composite-ai/composite-fill.js +97 -56
  452. package/dist/integrations/composite-ai/composite-fill.js.map +1 -1
  453. package/dist/integrations/composite-ai/composite-summary.d.ts +4 -12
  454. package/dist/integrations/composite-ai/composite-summary.js +7 -26
  455. package/dist/integrations/composite-ai/composite-summary.js.map +1 -1
  456. package/dist/integrations/composite-ai/derive.d.ts +29 -0
  457. package/dist/integrations/composite-ai/derive.js +173 -0
  458. package/dist/integrations/composite-ai/derive.js.map +1 -0
  459. package/dist/integrations/composite-ai/index.d.ts +11 -7
  460. package/dist/integrations/composite-ai/index.js +72 -14
  461. package/dist/integrations/composite-ai/index.js.map +1 -1
  462. package/dist/integrations/composite-ai/rendition.d.ts +45 -0
  463. package/dist/integrations/composite-ai/rendition.js +314 -0
  464. package/dist/integrations/composite-ai/rendition.js.map +1 -0
  465. package/dist/integrations/composite-media/index.d.ts +7 -5
  466. package/dist/integrations/composite-media/index.js +86 -13
  467. package/dist/integrations/composite-media/index.js.map +1 -1
  468. package/dist/integrations/transcript-ai/index.d.ts +1 -1
  469. package/dist/integrations/transcript-ai/index.js +5 -2
  470. package/dist/integrations/transcript-ai/index.js.map +1 -1
  471. package/dist/integrations/transcript-ai/protocol.d.ts +2 -12
  472. package/dist/integrations/transcript-ai/protocol.js +0 -2
  473. package/dist/integrations/transcript-ai/protocol.js.map +1 -1
  474. package/dist/integrations/transcript-ai/transcript-cleanup.d.ts +5 -5
  475. package/dist/integrations/transcript-ai/transcript-cleanup.js +7 -10
  476. package/dist/integrations/transcript-ai/transcript-cleanup.js.map +1 -1
  477. package/dist/markdown/MarkdownSurface.vue.d.ts +12 -11
  478. package/dist/markdown/MarkdownSurface2.js +3 -6
  479. package/dist/markdown/MarkdownSurface2.js.map +1 -1
  480. package/dist/markdown/document.js +1 -1
  481. package/dist/markdown/source-mode.d.ts +1 -1
  482. package/dist/nuxt/module.d.ts +1402 -54
  483. package/dist/nuxt/module.js +6 -49
  484. package/dist/nuxt/module.js.map +1 -1
  485. package/dist/nuxt/runtime/install-context.d.ts +7 -3
  486. package/dist/nuxt/runtime/install-context.js +14 -8
  487. package/dist/nuxt/runtime/install-context.js.map +1 -1
  488. package/dist/nuxt/runtime/plugins/editor-context-nuxt-ui.client.ts +2 -2
  489. package/dist/nuxt/runtime/server/plugins/editor-server.js +20 -12
  490. package/dist/nuxt/runtime/server/plugins/editor-server.js.map +1 -1
  491. package/dist/presets/compose.d.ts +94 -0
  492. package/dist/presets/compose.js +164 -0
  493. package/dist/presets/compose.js.map +1 -0
  494. package/dist/react/AdvancedEditor.d.ts +15 -15
  495. package/dist/react/AdvancedEditor.js +15 -13
  496. package/dist/react/AdvancedEditor.js.map +1 -1
  497. package/dist/react/EditorCommandPalette.d.ts +13 -0
  498. package/dist/react/EditorCommandPalette.js +118 -0
  499. package/dist/react/EditorCommandPalette.js.map +1 -0
  500. package/dist/react/EditorSettingsModal.d.ts +5 -5
  501. package/dist/react/EditorSettingsModal.js +7 -4
  502. package/dist/react/EditorSettingsModal.js.map +1 -1
  503. package/dist/react/EditorSettingsPanel.d.ts +7 -7
  504. package/dist/react/EditorSettingsPanel.js +8 -5
  505. package/dist/react/EditorSettingsPanel.js.map +1 -1
  506. package/dist/react/EditorSurface.d.ts +7 -7
  507. package/dist/react/EditorSurface.js +10 -6
  508. package/dist/react/EditorSurface.js.map +1 -1
  509. package/dist/react/EditorToolbar.d.ts +4 -6
  510. package/dist/react/EditorToolbar.js +29 -37
  511. package/dist/react/EditorToolbar.js.map +1 -1
  512. package/dist/react/SimpleEditor.d.ts +22 -23
  513. package/dist/react/SimpleEditor.js +21 -7
  514. package/dist/react/SimpleEditor.js.map +1 -1
  515. package/dist/react/advanced.d.ts +4 -3
  516. package/dist/react/advanced.js +2 -2
  517. package/dist/react/compose.d.ts +20 -0
  518. package/dist/react/compose.js +49 -0
  519. package/dist/react/compose.js.map +1 -0
  520. package/dist/react/composed-surface.d.ts +39 -0
  521. package/dist/react/composed-surface.js +71 -0
  522. package/dist/react/composed-surface.js.map +1 -0
  523. package/dist/react/context.js +6 -2
  524. package/dist/react/context.js.map +1 -1
  525. package/dist/react/index.d.ts +2 -1
  526. package/dist/react/index.js +2 -1
  527. package/dist/react/key-labels.js +15 -0
  528. package/dist/react/key-labels.js.map +1 -0
  529. package/dist/react/settings.d.ts +1 -1
  530. package/dist/react/simple.d.ts +2 -2
  531. package/dist/react/ui/command.js +36 -1
  532. package/dist/react/ui/command.js.map +1 -1
  533. package/dist/schema/advanced.d.ts +6 -6
  534. package/dist/schema/advanced.js +26 -29
  535. package/dist/schema/advanced.js.map +1 -1
  536. package/dist/server/ai.d.ts +5 -16
  537. package/dist/server/ai.js.map +1 -1
  538. package/dist/server/auth.d.ts +9 -0
  539. package/dist/server/collab-state.d.ts +1 -1
  540. package/dist/server/collab-state.js.map +1 -1
  541. package/dist/server/collab.d.ts +13 -13
  542. package/dist/server/collab.js +34 -18
  543. package/dist/server/collab.js.map +1 -1
  544. package/dist/server/crossref.js +78 -0
  545. package/dist/server/crossref.js.map +1 -0
  546. package/dist/server/errors.d.ts +1 -1
  547. package/dist/server/errors.js +1 -1
  548. package/dist/server/errors.js.map +1 -1
  549. package/dist/server/extract.js +308 -0
  550. package/dist/server/extract.js.map +1 -0
  551. package/dist/server/h3.d.ts +8 -0
  552. package/dist/{nuxt/runtime/server/utils/editor-route.js → server/h3.js} +8 -16
  553. package/dist/server/h3.js.map +1 -0
  554. package/dist/server/handlers/ai.d.ts +32 -10
  555. package/dist/server/handlers/ai.js +172 -37
  556. package/dist/server/handlers/ai.js.map +1 -1
  557. package/dist/server/handlers/context.d.ts +12 -5
  558. package/dist/server/handlers/context.js +10 -4
  559. package/dist/server/handlers/context.js.map +1 -1
  560. package/dist/server/handlers/editor.d.ts +19 -13
  561. package/dist/server/handlers/editor.js +49 -38
  562. package/dist/server/handlers/editor.js.map +1 -1
  563. package/dist/server/handlers/index.d.ts +4 -4
  564. package/dist/server/handlers/index.js +4 -4
  565. package/dist/server/host.d.ts +16 -25
  566. package/dist/server/host.js +58 -41
  567. package/dist/server/host.js.map +1 -1
  568. package/dist/server/index.d.ts +6 -4
  569. package/dist/server/index.js +3 -2
  570. package/dist/server/pdf.js +97 -0
  571. package/dist/server/pdf.js.map +1 -0
  572. package/dist/server/{adapter.d.ts → ports.d.ts} +81 -30
  573. package/dist/server/ports.js +29 -0
  574. package/dist/server/ports.js.map +1 -0
  575. package/dist/server/routes.d.ts +22 -0
  576. package/dist/server/routes.js +144 -0
  577. package/dist/server/routes.js.map +1 -0
  578. package/dist/settings/index.d.ts +1 -1
  579. package/dist/settings/index.js.map +1 -1
  580. package/dist/styles/composites.css +25 -0
  581. package/dist/tree/DocumentTree.js +56 -29
  582. package/dist/tree/DocumentTree.js.map +1 -1
  583. package/dist/tree/react/DocumentTree.js +23 -0
  584. package/dist/tree/react/DocumentTree.js.map +1 -1
  585. package/dist/tree/tree-host.js +2 -2
  586. package/dist/tree/tree-items.js +1 -1
  587. package/dist/vue/AdvancedEditor.js +30 -9
  588. package/dist/vue/AdvancedEditor.js.map +1 -1
  589. package/dist/vue/AdvancedEditor.vue.d.ts +32 -12
  590. package/dist/vue/SimpleEditor.js +62 -16
  591. package/dist/vue/SimpleEditor.js.map +1 -1
  592. package/dist/vue/SimpleEditor.vue.d.ts +39 -9
  593. package/dist/vue/advanced.d.ts +3 -2
  594. package/dist/vue/advanced.js +2 -2
  595. package/dist/vue/components/EditorCommandPalette.js +91 -0
  596. package/dist/vue/components/EditorCommandPalette.js.map +1 -0
  597. package/dist/vue/components/EditorCommandPalette.vue.d.ts +15 -0
  598. package/dist/vue/components/EditorSettingsModal.js +10 -6
  599. package/dist/vue/components/EditorSettingsModal.js.map +1 -1
  600. package/dist/vue/components/EditorSettingsModal.vue.d.ts +4 -4
  601. package/dist/vue/components/EditorSettingsPanel.js +10 -6
  602. package/dist/vue/components/EditorSettingsPanel.js.map +1 -1
  603. package/dist/vue/components/EditorSettingsPanel.vue.d.ts +6 -6
  604. package/dist/vue/components/EditorSurface.js +11 -6
  605. package/dist/vue/components/EditorSurface.js.map +1 -1
  606. package/dist/vue/components/EditorSurface.vue.d.ts +11 -11
  607. package/dist/vue/components/EditorToolbar.js +41 -49
  608. package/dist/vue/components/EditorToolbar.js.map +1 -1
  609. package/dist/vue/components/EditorToolbar.vue.d.ts +2 -4
  610. package/dist/vue/compose.d.ts +17 -0
  611. package/dist/vue/compose.js +51 -0
  612. package/dist/vue/compose.js.map +1 -0
  613. package/dist/vue/context-key.d.ts +6 -0
  614. package/dist/vue/context-key.js +6 -0
  615. package/dist/vue/context-key.js.map +1 -0
  616. package/dist/vue/context.d.ts +8 -6
  617. package/dist/vue/context.js +6 -5
  618. package/dist/vue/context.js.map +1 -1
  619. package/dist/vue/index.d.ts +10 -8
  620. package/dist/vue/index.js +10 -8
  621. package/dist/vue/kit/index.d.ts +2 -2
  622. package/dist/vue/kit/nuxt-ui.js +23 -0
  623. package/dist/vue/kit/nuxt-ui.js.map +1 -1
  624. package/dist/vue/kit/types.d.ts +40 -1
  625. package/package.json +30 -16
  626. package/dist/adapters/comments/client.d.ts +0 -64
  627. package/dist/adapters/comments/client.js.map +0 -1
  628. package/dist/adapters/routes.js.map +0 -1
  629. package/dist/core/toolbar.d.ts +0 -74
  630. package/dist/core/toolbar.js +0 -45
  631. package/dist/core/toolbar.js.map +0 -1
  632. package/dist/integrations/composite-ai/document-transcribe.d.ts +0 -14
  633. package/dist/integrations/composite-ai/document-transcribe.js +0 -89
  634. package/dist/integrations/composite-ai/document-transcribe.js.map +0 -1
  635. package/dist/nuxt/runtime/server/api/ai/chat.post.d.ts +0 -5
  636. package/dist/nuxt/runtime/server/api/ai/chat.post.js +0 -8
  637. package/dist/nuxt/runtime/server/api/ai/chat.post.js.map +0 -1
  638. package/dist/nuxt/runtime/server/api/ai/complete.post.d.ts +0 -5
  639. package/dist/nuxt/runtime/server/api/ai/complete.post.js +0 -8
  640. package/dist/nuxt/runtime/server/api/ai/complete.post.js.map +0 -1
  641. package/dist/nuxt/runtime/server/api/ai/generate.post.d.ts +0 -5
  642. package/dist/nuxt/runtime/server/api/ai/generate.post.js +0 -8
  643. package/dist/nuxt/runtime/server/api/ai/generate.post.js.map +0 -1
  644. package/dist/nuxt/runtime/server/api/ai/models.get.d.ts +0 -5
  645. package/dist/nuxt/runtime/server/api/ai/models.get.js +0 -8
  646. package/dist/nuxt/runtime/server/api/ai/models.get.js.map +0 -1
  647. package/dist/nuxt/runtime/server/api/ai/transcribe.post.d.ts +0 -5
  648. package/dist/nuxt/runtime/server/api/ai/transcribe.post.js +0 -8
  649. package/dist/nuxt/runtime/server/api/ai/transcribe.post.js.map +0 -1
  650. package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.d.ts +0 -5
  651. package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.js +0 -8
  652. package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.js.map +0 -1
  653. package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.d.ts +0 -5
  654. package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.js +0 -8
  655. package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.js.map +0 -1
  656. package/dist/nuxt/runtime/server/api/editor/assets/[id].post.d.ts +0 -5
  657. package/dist/nuxt/runtime/server/api/editor/assets/[id].post.js +0 -8
  658. package/dist/nuxt/runtime/server/api/editor/assets/[id].post.js.map +0 -1
  659. package/dist/nuxt/runtime/server/api/editor/settings.get.d.ts +0 -5
  660. package/dist/nuxt/runtime/server/api/editor/settings.get.js +0 -8
  661. package/dist/nuxt/runtime/server/api/editor/settings.get.js.map +0 -1
  662. package/dist/nuxt/runtime/server/api/editor/settings.put.d.ts +0 -5
  663. package/dist/nuxt/runtime/server/api/editor/settings.put.js +0 -8
  664. package/dist/nuxt/runtime/server/api/editor/settings.put.js.map +0 -1
  665. package/dist/nuxt/runtime/server/api/editor/tags.get.d.ts +0 -5
  666. package/dist/nuxt/runtime/server/api/editor/tags.get.js +0 -8
  667. package/dist/nuxt/runtime/server/api/editor/tags.get.js.map +0 -1
  668. package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.d.ts +0 -5
  669. package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.js +0 -8
  670. package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.js.map +0 -1
  671. package/dist/nuxt/runtime/server/api/editor/themes/[id].get.d.ts +0 -5
  672. package/dist/nuxt/runtime/server/api/editor/themes/[id].get.js +0 -8
  673. package/dist/nuxt/runtime/server/api/editor/themes/[id].get.js.map +0 -1
  674. package/dist/nuxt/runtime/server/api/editor/themes/index.get.d.ts +0 -5
  675. package/dist/nuxt/runtime/server/api/editor/themes/index.get.js +0 -8
  676. package/dist/nuxt/runtime/server/api/editor/themes/index.get.js.map +0 -1
  677. package/dist/nuxt/runtime/server/api/editor/themes/index.post.d.ts +0 -5
  678. package/dist/nuxt/runtime/server/api/editor/themes/index.post.js +0 -8
  679. package/dist/nuxt/runtime/server/api/editor/themes/index.post.js.map +0 -1
  680. package/dist/nuxt/runtime/server/api/editor/users.get.d.ts +0 -5
  681. package/dist/nuxt/runtime/server/api/editor/users.get.js +0 -8
  682. package/dist/nuxt/runtime/server/api/editor/users.get.js.map +0 -1
  683. package/dist/nuxt/runtime/server/plugins/collab.d.ts +0 -5
  684. package/dist/nuxt/runtime/server/plugins/collab.js +0 -10
  685. package/dist/nuxt/runtime/server/plugins/collab.js.map +0 -1
  686. package/dist/nuxt/runtime/server/routes/collab/[id].d.ts +0 -5
  687. package/dist/nuxt/runtime/server/routes/collab/[id].js +0 -35
  688. package/dist/nuxt/runtime/server/routes/collab/[id].js.map +0 -1
  689. package/dist/nuxt/runtime/server/utils/editor-route.d.ts +0 -11
  690. package/dist/nuxt/runtime/server/utils/editor-route.js.map +0 -1
  691. package/dist/presets/advanced.d.ts +0 -33
  692. package/dist/presets/advanced.js +0 -50
  693. package/dist/presets/advanced.js.map +0 -1
  694. package/dist/presets/simple.d.ts +0 -9
  695. package/dist/presets/simple.js +0 -12
  696. package/dist/presets/simple.js.map +0 -1
  697. package/dist/react/advanced-preset.d.ts +0 -11
  698. package/dist/react/advanced-preset.js +0 -31
  699. package/dist/react/advanced-preset.js.map +0 -1
  700. package/dist/vue/advanced-preset.d.ts +0 -13
  701. package/dist/vue/advanced-preset.js +0 -33
  702. package/dist/vue/advanced-preset.js.map +0 -1
  703. package/docs/extending.md +0 -538
  704. package/docs/integration.md +0 -632
  705. package/docs/llms.md +0 -383
  706. package/docs/usage.md +0 -1076
@@ -1,35 +1,36 @@
1
- import { FeatureContext, UploadFn } from "../../core/feature.js";
1
+ import { FeatureContext } from "../../core/feature.js";
2
2
  import "../../core/index.js";
3
3
  import { Editor, Extension, JSONContent } from "@tiptap/core";
4
4
  //#region src/features/media/upload.d.ts
5
- /** `importFiles` of the media feature: imports `files` at `pos` (default: the selection), toasting failures; resolves whether every file was imported. */
6
- export type ImportFilesFn = (editor: Editor, files: File[] | FileList, pos?: number) => Promise<boolean>;
7
- /** Default upload: POSTs `file` to the asset endpoint of document `documentId` through the context's HTTP client (size limits per kind, see schema.ts). */
8
- export declare function postUpload(fetch: FeatureContext['fetch'], documentId: string, file: File): Promise<{
5
+ /** Stores a file and resolves with the URL it is addressed by. */
6
+ type UploadFile = (file: File) => Promise<{
9
7
  url: string;
8
+ sha256?: string;
10
9
  }>;
11
- /** The upload of a surface: the host's `upload` prop, else the asset endpoint of its `documentId` (default: the shared `scratch` owner). */
12
- export declare const uploadOf: (ctx: FeatureContext) => UploadFn;
10
+ /** `importFiles` of the media feature: imports `files` at `pos` (default: the selection), toasting failures; resolves whether every file was imported. */
11
+ export type ImportFilesFn = (editor: Editor, files: File[] | FileList, pos?: number) => Promise<boolean>;
12
+ /** The upload of a surface: the backend's asset store for its `documentId` (default: the shared `scratch` owner; size limits per kind, see schema.ts). */
13
+ export declare const uploadOf: (ctx: FeatureContext) => UploadFile;
13
14
  /** Makes the upload and the file import reachable as `editor.storage.media` (drop/paste, toolbar, slash menu, recorder). */
14
15
  export declare const Media: Extension<{
15
- upload: UploadFn;
16
+ upload: UploadFile;
16
17
  importFiles: ImportFilesFn;
17
18
  }, {
18
- upload: UploadFn;
19
+ upload: UploadFile;
19
20
  importFiles: ImportFilesFn;
20
21
  }>;
21
22
  declare module '@tiptap/core' {
22
23
  interface Storage {
23
24
  media: {
24
- upload: UploadFn;
25
+ upload: UploadFile;
25
26
  importFiles: ImportFilesFn;
26
27
  };
27
28
  }
28
29
  }
29
- /** The node that embeds uploaded `file` from `url`; null for files uploads do not accept. */
30
- export declare function mediaNodeFor(file: File, url: string): JSONContent | null;
31
- /** The file block for an uploaded `file` that has no player or image node (PDF, office documents, …). */
32
- export declare function fileNodeFor(file: File, url: string): JSONContent;
30
+ /** The node that embeds uploaded `file` from `url`, remembering the upload's `hash` (SHA-256 hex; none when the backend did not report one); null for files uploads do not accept. */
31
+ export declare function mediaNodeFor(file: File, url: string, hash?: string): JSONContent | null;
32
+ /** The file block for an uploaded `file` that has no player or image node (PDF, office documents, …); `hash` as in `mediaNodeFor`. */
33
+ export declare function fileNodeFor(file: File, url: string, hash?: string): JSONContent;
33
34
  /** Human-readable byte count: 1024-based, one decimal (`1536` → `1.5 KB`), units B/KB/MB/GB. */
34
35
  export declare function formatBytes(bytes: number): string;
35
36
  /** Transaction meta the recorder modal (AudioRecorderModal) listens for: open it, inserting at the current caret. */
@@ -38,4 +39,5 @@ export declare function openAudioRecorder(editor: Editor): void;
38
39
  /** Opens the browser's file picker; resolves the chosen files, `[]` when the picker is cancelled. */
39
40
  export declare function pickFiles(accept: string, multiple?: boolean): Promise<File[]>;
40
41
  //#endregion
42
+ export {};
41
43
  //# sourceMappingURL=upload.d.ts.map
@@ -2,17 +2,8 @@ import "./assets.js";
2
2
  import { mediaKindOf, mediaMime } from "./schema.js";
3
3
  import { Extension } from "@tiptap/core";
4
4
  //#region src/features/media/upload.ts
5
- /** Default upload: POSTs `file` to the asset endpoint of document `documentId` through the context's HTTP client (size limits per kind, see schema.ts). */
6
- async function postUpload(fetch, documentId, file) {
7
- const body = new FormData();
8
- body.append("file", file);
9
- return await fetch(`/api/editor/assets/${documentId}`, {
10
- method: "POST",
11
- body
12
- });
13
- }
14
- /** The upload of a surface: the host's `upload` prop, else the asset endpoint of its `documentId` (default: the shared `scratch` owner). */
15
- const uploadOf = (ctx) => ctx.upload ?? ((file) => postUpload(ctx.fetch, ctx.documentId ?? "scratch", file));
5
+ /** The upload of a surface: the backend's asset store for its `documentId` (default: the shared `scratch` owner; size limits per kind, see schema.ts). */
6
+ const uploadOf = (ctx) => (file) => ctx.backend.assets ? ctx.backend.assets.upload(ctx.documentId ?? "scratch", file) : Promise.reject(/* @__PURE__ */ new Error(`@ecsplico/editor: backend "${ctx.backend.name}" has no assets capability`));
16
7
  /** Makes the upload and the file import reachable as `editor.storage.media` (drop/paste, toolbar, slash menu, recorder). */
17
8
  const Media = Extension.create({
18
9
  name: "media",
@@ -29,15 +20,16 @@ const Media = Extension.create({
29
20
  };
30
21
  }
31
22
  });
32
- /** The node that embeds uploaded `file` from `url`; null for files uploads do not accept. */
33
- function mediaNodeFor(file, url) {
23
+ /** The node that embeds uploaded `file` from `url`, remembering the upload's `hash` (SHA-256 hex; none when the backend did not report one); null for files uploads do not accept. */
24
+ function mediaNodeFor(file, url, hash) {
34
25
  const kind = mediaKindOf(file.type);
35
26
  if (!kind) return null;
36
27
  if (kind === "image") return {
37
28
  type: "image",
38
29
  attrs: {
39
30
  src: url,
40
- alt: file.name
31
+ alt: file.name,
32
+ hash: hash ?? null
41
33
  }
42
34
  };
43
35
  return {
@@ -45,19 +37,21 @@ function mediaNodeFor(file, url) {
45
37
  attrs: {
46
38
  src: url,
47
39
  title: file.name,
48
- mimeType: mediaMime(file.type)
40
+ mimeType: mediaMime(file.type),
41
+ hash: hash ?? null
49
42
  }
50
43
  };
51
44
  }
52
- /** The file block for an uploaded `file` that has no player or image node (PDF, office documents, …). */
53
- function fileNodeFor(file, url) {
45
+ /** The file block for an uploaded `file` that has no player or image node (PDF, office documents, …); `hash` as in `mediaNodeFor`. */
46
+ function fileNodeFor(file, url, hash) {
54
47
  return {
55
48
  type: "file",
56
49
  attrs: {
57
50
  src: url,
58
51
  title: file.name,
59
52
  mimeType: mediaMime(file.type) || "application/octet-stream",
60
- size: file.size
53
+ size: file.size,
54
+ hash: hash ?? null
61
55
  }
62
56
  };
63
57
  }
@@ -101,6 +95,6 @@ function pickFiles(accept, multiple = true) {
101
95
  return promise;
102
96
  }
103
97
  //#endregion
104
- export { AUDIO_RECORDER_OPEN, Media, fileNodeFor, formatBytes, mediaNodeFor, openAudioRecorder, pickFiles, postUpload, uploadOf };
98
+ export { AUDIO_RECORDER_OPEN, Media, fileNodeFor, formatBytes, mediaNodeFor, openAudioRecorder, pickFiles, uploadOf };
105
99
 
106
100
  //# sourceMappingURL=upload.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"upload.js","names":[],"sources":["../../../src/features/media/upload.ts"],"sourcesContent":["import { type Editor, Extension, type JSONContent } from '@tiptap/core'\nimport type { FeatureContext, UploadFn } from '../../core'\nimport { SCRATCH_DOCUMENT_ID } from './assets'\nimport { mediaKindOf, mediaMime } from './schema'\n\n/** `importFiles` of the media feature: imports `files` at `pos` (default: the selection), toasting failures; resolves whether every file was imported. */\nexport type ImportFilesFn = (editor: Editor, files: File[] | FileList, pos?: number) => Promise<boolean>\n\n/** Default upload: POSTs `file` to the asset endpoint of document `documentId` through the context's HTTP client (size limits per kind, see schema.ts). */\nexport async function postUpload(fetch: FeatureContext['fetch'], documentId: string, file: File): Promise<{ url: string }> {\n const body = new FormData()\n body.append('file', file)\n return await fetch<{ url: string }>(`/api/editor/assets/${documentId}`, { method: 'POST', body })\n}\n\n/** The upload of a surface: the host's `upload` prop, else the asset endpoint of its `documentId` (default: the shared `scratch` owner). */\nexport const uploadOf = (ctx: FeatureContext): UploadFn =>\n ctx.upload ?? (file => postUpload(ctx.fetch, ctx.documentId ?? SCRATCH_DOCUMENT_ID, file))\n\n/** Makes the upload and the file import reachable as `editor.storage.media` (drop/paste, toolbar, slash menu, recorder). */\nexport const Media = Extension.create<{ upload: UploadFn, importFiles: ImportFilesFn }, { upload: UploadFn, importFiles: ImportFilesFn }>({\n name: 'media',\n\n addOptions() {\n return {\n upload: () => Promise.reject(new Error('@ecsplico/editor: Media.configure({ upload }) fehlt')),\n importFiles: () => Promise.reject(new Error('@ecsplico/editor: Media.configure({ importFiles }) fehlt')),\n }\n },\n\n addStorage() {\n return { upload: this.options.upload, importFiles: this.options.importFiles }\n },\n})\n\ndeclare module '@tiptap/core' {\n interface Storage {\n media: { upload: UploadFn, importFiles: ImportFilesFn }\n }\n}\n\n/** The node that embeds uploaded `file` from `url`; null for files uploads do not accept. */\nexport function mediaNodeFor(file: File, url: string): JSONContent | null {\n const kind = mediaKindOf(file.type)\n if (!kind) return null\n if (kind === 'image') return { type: 'image', attrs: { src: url, alt: file.name } }\n return { type: kind, attrs: { src: url, title: file.name, mimeType: mediaMime(file.type) } }\n}\n\n/** The file block for an uploaded `file` that has no player or image node (PDF, office documents, …). */\nexport function fileNodeFor(file: File, url: string): JSONContent {\n return {\n type: 'file',\n attrs: { src: url, title: file.name, mimeType: mediaMime(file.type) || 'application/octet-stream', size: file.size },\n }\n}\n\n/** Human-readable byte count: 1024-based, one decimal (`1536` → `1.5 KB`), units B/KB/MB/GB. */\nexport function formatBytes(bytes: number): string {\n const units = ['B', 'KB', 'MB', 'GB']\n let value = Math.max(0, bytes)\n let unit = 0\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024\n unit++\n }\n return unit === 0 ? `${value} B` : `${value.toFixed(1)} ${units[unit]}`\n}\n\n/** Transaction meta the recorder modal (AudioRecorderModal) listens for: open it, inserting at the current caret. */\nexport const AUDIO_RECORDER_OPEN = 'audioRecorderOpen'\n\nexport function openAudioRecorder(editor: Editor): void {\n editor.view.dispatch(editor.state.tr.setMeta(AUDIO_RECORDER_OPEN, true).setMeta('addToHistory', false))\n}\n\n/** Opens the browser's file picker; resolves the chosen files, `[]` when the picker is cancelled. */\nexport function pickFiles(accept: string, multiple = true): Promise<File[]> {\n const { promise, resolve } = Promise.withResolvers<File[]>()\n const input = document.createElement('input')\n input.type = 'file'\n input.accept = accept\n input.multiple = multiple\n input.hidden = true\n // Attached while open: some Safari versions fire no `change` for detached inputs.\n document.body.append(input)\n const done = (files: File[]) => {\n input.remove()\n resolve(files)\n }\n input.addEventListener('change', () => done(Array.from(input.files ?? [])), { once: true })\n input.addEventListener('cancel', () => done([]), { once: true })\n input.click()\n return promise\n}\n"],"mappings":";;;;;AASA,eAAsB,WAAW,OAAgC,YAAoB,MAAsC;CACzH,MAAM,OAAO,IAAI,SAAS;CAC1B,KAAK,OAAO,QAAQ,IAAI;CACxB,OAAO,MAAM,MAAuB,sBAAsB,cAAc;EAAE,QAAQ;EAAQ;CAAK,CAAC;AAClG;;AAGA,MAAa,YAAY,QACvB,IAAI,YAAW,SAAQ,WAAW,IAAI,OAAO,IAAI,cAAA,WAAmC,IAAI;;AAG1F,MAAa,QAAQ,UAAU,OAA2G;CACxI,MAAM;CAEN,aAAa;EACX,OAAO;GACL,cAAc,QAAQ,uBAAO,IAAI,MAAM,qDAAqD,CAAC;GAC7F,mBAAmB,QAAQ,uBAAO,IAAI,MAAM,0DAA0D,CAAC;EACzG;CACF;CAEA,aAAa;EACX,OAAO;GAAE,QAAQ,KAAK,QAAQ;GAAQ,aAAa,KAAK,QAAQ;EAAY;CAC9E;AACF,CAAC;;AASD,SAAgB,aAAa,MAAY,KAAiC;CACxE,MAAM,OAAO,YAAY,KAAK,IAAI;CAClC,IAAI,CAAC,MAAM,OAAO;CAClB,IAAI,SAAS,SAAS,OAAO;EAAE,MAAM;EAAS,OAAO;GAAE,KAAK;GAAK,KAAK,KAAK;EAAK;CAAE;CAClF,OAAO;EAAE,MAAM;EAAM,OAAO;GAAE,KAAK;GAAK,OAAO,KAAK;GAAM,UAAU,UAAU,KAAK,IAAI;EAAE;CAAE;AAC7F;;AAGA,SAAgB,YAAY,MAAY,KAA0B;CAChE,OAAO;EACL,MAAM;EACN,OAAO;GAAE,KAAK;GAAK,OAAO,KAAK;GAAM,UAAU,UAAU,KAAK,IAAI,KAAK;GAA4B,MAAM,KAAK;EAAK;CACrH;AACF;;AAGA,SAAgB,YAAY,OAAuB;CACjD,MAAM,QAAQ;EAAC;EAAK;EAAM;EAAM;CAAI;CACpC,IAAI,QAAQ,KAAK,IAAI,GAAG,KAAK;CAC7B,IAAI,OAAO;CACX,OAAO,SAAS,QAAQ,OAAO,MAAM,SAAS,GAAG;EAC/C,SAAS;EACT;CACF;CACA,OAAO,SAAS,IAAI,GAAG,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,EAAE,GAAG,MAAM;AAClE;;AAGA,MAAa,sBAAsB;AAEnC,SAAgB,kBAAkB,QAAsB;CACtD,OAAO,KAAK,SAAS,OAAO,MAAM,GAAG,QAAQ,qBAAqB,IAAI,CAAC,CAAC,QAAQ,gBAAgB,KAAK,CAAC;AACxG;;AAGA,SAAgB,UAAU,QAAgB,WAAW,MAAuB;CAC1E,MAAM,EAAE,SAAS,YAAY,QAAQ,cAAsB;CAC3D,MAAM,QAAQ,SAAS,cAAc,OAAO;CAC5C,MAAM,OAAO;CACb,MAAM,SAAS;CACf,MAAM,WAAW;CACjB,MAAM,SAAS;CAEf,SAAS,KAAK,OAAO,KAAK;CAC1B,MAAM,QAAQ,UAAkB;EAC9B,MAAM,OAAO;EACb,QAAQ,KAAK;CACf;CACA,MAAM,iBAAiB,gBAAgB,KAAK,MAAM,KAAK,MAAM,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;CAC1F,MAAM,iBAAiB,gBAAgB,KAAK,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;CAC/D,MAAM,MAAM;CACZ,OAAO;AACT"}
1
+ {"version":3,"file":"upload.js","names":[],"sources":["../../../src/features/media/upload.ts"],"sourcesContent":["import { type Editor, Extension, type JSONContent } from '@tiptap/core'\nimport type { FeatureContext } from '../../core'\nimport { SCRATCH_DOCUMENT_ID } from './assets'\nimport { mediaKindOf, mediaMime } from './schema'\n\n/** Stores a file and resolves with the URL it is addressed by. */\ntype UploadFile = (file: File) => Promise<{ url: string, sha256?: string }>\n\n/** `importFiles` of the media feature: imports `files` at `pos` (default: the selection), toasting failures; resolves whether every file was imported. */\nexport type ImportFilesFn = (editor: Editor, files: File[] | FileList, pos?: number) => Promise<boolean>\n\n/** The upload of a surface: the backend's asset store for its `documentId` (default: the shared `scratch` owner; size limits per kind, see schema.ts). */\nexport const uploadOf = (ctx: FeatureContext): UploadFile =>\n file => ctx.backend.assets\n ? ctx.backend.assets.upload(ctx.documentId ?? SCRATCH_DOCUMENT_ID, file)\n : Promise.reject(new Error(`@ecsplico/editor: backend \"${ctx.backend.name}\" has no assets capability`))\n\n/** Makes the upload and the file import reachable as `editor.storage.media` (drop/paste, toolbar, slash menu, recorder). */\nexport const Media = Extension.create<{ upload: UploadFile, importFiles: ImportFilesFn }, { upload: UploadFile, importFiles: ImportFilesFn }>({\n name: 'media',\n\n addOptions() {\n return {\n upload: () => Promise.reject(new Error('@ecsplico/editor: Media.configure({ upload }) fehlt')),\n importFiles: () => Promise.reject(new Error('@ecsplico/editor: Media.configure({ importFiles }) fehlt')),\n }\n },\n\n addStorage() {\n return { upload: this.options.upload, importFiles: this.options.importFiles }\n },\n})\n\ndeclare module '@tiptap/core' {\n interface Storage {\n media: { upload: UploadFile, importFiles: ImportFilesFn }\n }\n}\n\n/** The node that embeds uploaded `file` from `url`, remembering the upload's `hash` (SHA-256 hex; none when the backend did not report one); null for files uploads do not accept. */\nexport function mediaNodeFor(file: File, url: string, hash?: string): JSONContent | null {\n const kind = mediaKindOf(file.type)\n if (!kind) return null\n if (kind === 'image') return { type: 'image', attrs: { src: url, alt: file.name, hash: hash ?? null } }\n return { type: kind, attrs: { src: url, title: file.name, mimeType: mediaMime(file.type), hash: hash ?? null } }\n}\n\n/** The file block for an uploaded `file` that has no player or image node (PDF, office documents, …); `hash` as in `mediaNodeFor`. */\nexport function fileNodeFor(file: File, url: string, hash?: string): JSONContent {\n return {\n type: 'file',\n attrs: { src: url, title: file.name, mimeType: mediaMime(file.type) || 'application/octet-stream', size: file.size, hash: hash ?? null },\n }\n}\n\n/** Human-readable byte count: 1024-based, one decimal (`1536` → `1.5 KB`), units B/KB/MB/GB. */\nexport function formatBytes(bytes: number): string {\n const units = ['B', 'KB', 'MB', 'GB']\n let value = Math.max(0, bytes)\n let unit = 0\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024\n unit++\n }\n return unit === 0 ? `${value} B` : `${value.toFixed(1)} ${units[unit]}`\n}\n\n/** Transaction meta the recorder modal (AudioRecorderModal) listens for: open it, inserting at the current caret. */\nexport const AUDIO_RECORDER_OPEN = 'audioRecorderOpen'\n\nexport function openAudioRecorder(editor: Editor): void {\n editor.view.dispatch(editor.state.tr.setMeta(AUDIO_RECORDER_OPEN, true).setMeta('addToHistory', false))\n}\n\n/** Opens the browser's file picker; resolves the chosen files, `[]` when the picker is cancelled. */\nexport function pickFiles(accept: string, multiple = true): Promise<File[]> {\n const { promise, resolve } = Promise.withResolvers<File[]>()\n const input = document.createElement('input')\n input.type = 'file'\n input.accept = accept\n input.multiple = multiple\n input.hidden = true\n // Attached while open: some Safari versions fire no `change` for detached inputs.\n document.body.append(input)\n const done = (files: File[]) => {\n input.remove()\n resolve(files)\n }\n input.addEventListener('change', () => done(Array.from(input.files ?? [])), { once: true })\n input.addEventListener('cancel', () => done([]), { once: true })\n input.click()\n return promise\n}\n"],"mappings":";;;;;AAYA,MAAa,YAAY,SACvB,SAAQ,IAAI,QAAQ,SAChB,IAAI,QAAQ,OAAO,OAAO,IAAI,cAAA,WAAmC,IAAI,IACrE,QAAQ,uBAAO,IAAI,MAAM,8BAA8B,IAAI,QAAQ,KAAK,2BAA2B,CAAC;;AAG1G,MAAa,QAAQ,UAAU,OAA+G;CAC5I,MAAM;CAEN,aAAa;EACX,OAAO;GACL,cAAc,QAAQ,uBAAO,IAAI,MAAM,qDAAqD,CAAC;GAC7F,mBAAmB,QAAQ,uBAAO,IAAI,MAAM,0DAA0D,CAAC;EACzG;CACF;CAEA,aAAa;EACX,OAAO;GAAE,QAAQ,KAAK,QAAQ;GAAQ,aAAa,KAAK,QAAQ;EAAY;CAC9E;AACF,CAAC;;AASD,SAAgB,aAAa,MAAY,KAAa,MAAmC;CACvF,MAAM,OAAO,YAAY,KAAK,IAAI;CAClC,IAAI,CAAC,MAAM,OAAO;CAClB,IAAI,SAAS,SAAS,OAAO;EAAE,MAAM;EAAS,OAAO;GAAE,KAAK;GAAK,KAAK,KAAK;GAAM,MAAM,QAAQ;EAAK;CAAE;CACtG,OAAO;EAAE,MAAM;EAAM,OAAO;GAAE,KAAK;GAAK,OAAO,KAAK;GAAM,UAAU,UAAU,KAAK,IAAI;GAAG,MAAM,QAAQ;EAAK;CAAE;AACjH;;AAGA,SAAgB,YAAY,MAAY,KAAa,MAA4B;CAC/E,OAAO;EACL,MAAM;EACN,OAAO;GAAE,KAAK;GAAK,OAAO,KAAK;GAAM,UAAU,UAAU,KAAK,IAAI,KAAK;GAA4B,MAAM,KAAK;GAAM,MAAM,QAAQ;EAAK;CACzI;AACF;;AAGA,SAAgB,YAAY,OAAuB;CACjD,MAAM,QAAQ;EAAC;EAAK;EAAM;EAAM;CAAI;CACpC,IAAI,QAAQ,KAAK,IAAI,GAAG,KAAK;CAC7B,IAAI,OAAO;CACX,OAAO,SAAS,QAAQ,OAAO,MAAM,SAAS,GAAG;EAC/C,SAAS;EACT;CACF;CACA,OAAO,SAAS,IAAI,GAAG,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,EAAE,GAAG,MAAM;AAClE;;AAGA,MAAa,sBAAsB;AAEnC,SAAgB,kBAAkB,QAAsB;CACtD,OAAO,KAAK,SAAS,OAAO,MAAM,GAAG,QAAQ,qBAAqB,IAAI,CAAC,CAAC,QAAQ,gBAAgB,KAAK,CAAC;AACxG;;AAGA,SAAgB,UAAU,QAAgB,WAAW,MAAuB;CAC1E,MAAM,EAAE,SAAS,YAAY,QAAQ,cAAsB;CAC3D,MAAM,QAAQ,SAAS,cAAc,OAAO;CAC5C,MAAM,OAAO;CACb,MAAM,SAAS;CACf,MAAM,WAAW;CACjB,MAAM,SAAS;CAEf,SAAS,KAAK,OAAO,KAAK;CAC1B,MAAM,QAAQ,UAAkB;EAC9B,MAAM,OAAO;EACb,QAAQ,KAAK;CACf;CACA,MAAM,iBAAiB,gBAAgB,KAAK,MAAM,KAAK,MAAM,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;CAC1F,MAAM,iBAAiB,gBAAgB,KAAK,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;CAC/D,MAAM,MAAM;CACZ,OAAO;AACT"}
@@ -1,9 +1,10 @@
1
1
  import { EditorFeature } from "../../core/feature.js";
2
- import "../../core/index.js";
3
- import { MentionAttrs, MentionNode, MentionUser } from "./mention.js";
2
+ import { MentionUser } from "../../core/backend-types.js";
3
+ import { MentionAttrs, MentionNode } from "./mention.js";
4
4
  import { MentionTarget, mentionUsersIn, mentionsFromText } from "./mention-text.js";
5
5
  import { TAG_NODE, TagAttrs, TagNode, TagOptions, TagSuggestionItem, TagSuggestionPluginKey, collectTagNames, normalizeTagName, tagsFromText } from "./tag.js";
6
6
  import "./schema.js";
7
+ import "../../core/index.js";
7
8
  import { mentionSuggestion } from "./mention-suggestion.js";
8
9
  import { mentionsMetadata } from "./metadata-defaults.js";
9
10
  import { normalizeMentions } from "./normalize.js";
@@ -11,7 +12,7 @@ import { tagSuggestion } from "./tag-suggestion.js";
11
12
  //#region src/features/mentions/index.d.ts
12
13
  /**
13
14
  * `@user` mention chips and `#tag` chips with their suggestion popups. Without a host list, `mentions` and `hashtags`
14
- * come from `/api/editor/users` and `/api/editor/tags` through the context's HTTP client, and only once a popup is used.
15
+ * come from the context's backend (`users` and `tags`; the HTTP backend asks `/api/editor/users` and `/api/editor/tags`), and only once a popup is used.
15
16
  * Contributes the `normalize` stage: `@name` / `#tag` text of imported or AI-written Markdown becomes chips when it
16
17
  * matches a known user or an existing tag. Contributes no components (`EditorFeature<never>`), so it fits a preset of
17
18
  * any framework layer.
@@ -2,6 +2,7 @@ import { metadataOf } from "../../core/metadata.js";
2
2
  import { MentionNode } from "./mention.js";
3
3
  import { TAG_NODE, TagNode, TagSuggestionPluginKey, collectTagNames, normalizeTagName, tagsFromText } from "./tag.js";
4
4
  import { mentionUsersIn, mentionsFromText } from "./mention-text.js";
5
+ import { mentionsSchemaExtensions } from "./schema.js";
5
6
  import { mentionSuggestion } from "./mention-suggestion.js";
6
7
  import { mentionsMetadata } from "./metadata-defaults.js";
7
8
  import { normalizeMentions } from "./normalize.js";
@@ -9,7 +10,7 @@ import { tagSuggestion } from "./tag-suggestion.js";
9
10
  //#region src/features/mentions/index.ts
10
11
  /**
11
12
  * `@user` mention chips and `#tag` chips with their suggestion popups. Without a host list, `mentions` and `hashtags`
12
- * come from `/api/editor/users` and `/api/editor/tags` through the context's HTTP client, and only once a popup is used.
13
+ * come from the context's backend (`users` and `tags`; the HTTP backend asks `/api/editor/users` and `/api/editor/tags`), and only once a popup is used.
13
14
  * Contributes the `normalize` stage: `@name` / `#tag` text of imported or AI-written Markdown becomes chips when it
14
15
  * matches a known user or an existing tag. Contributes no components (`EditorFeature<never>`), so it fits a preset of
15
16
  * any framework layer.
@@ -17,6 +18,8 @@ import { tagSuggestion } from "./tag-suggestion.js";
17
18
  function mentionsFeature() {
18
19
  return {
19
20
  id: "mentions",
21
+ dimension: "content",
22
+ schemaExtensions: mentionsSchemaExtensions,
20
23
  extensions: (ctx) => [MentionNode.configure({ suggestion: mentionSuggestion(ctx.t) }), TagNode.configure({
21
24
  suggestion: tagSuggestion(ctx.t),
22
25
  onCreate: (editor, name) => metadataOf(editor).create("hashtags", {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/features/mentions/index.ts"],"sourcesContent":["import type { EditorFeature } from '../../core'\nimport { metadataOf } from '../../core'\nimport { mentionSuggestion } from './mention-suggestion'\nimport { mentionsMetadata } from './metadata-defaults'\nimport { MentionNode } from './mention'\nimport { normalizeMentions } from './normalize'\nimport { tagSuggestion } from './tag-suggestion'\nimport { TagNode } from './tag'\n\nexport { mentionSuggestion } from './mention-suggestion'\nexport { mentionsMetadata } from './metadata-defaults'\nexport { normalizeMentions } from './normalize'\nexport { tagSuggestion } from './tag-suggestion'\nexport {\n collectTagNames,\n type MentionAttrs,\n MentionNode,\n type MentionTarget,\n mentionsFromText,\n mentionUsersIn,\n type MentionUser,\n normalizeTagName,\n TAG_NODE,\n TagNode,\n type TagAttrs,\n type TagOptions,\n type TagSuggestionItem,\n tagsFromText,\n TagSuggestionPluginKey,\n} from './schema'\n\n/**\n * `@user` mention chips and `#tag` chips with their suggestion popups. Without a host list, `mentions` and `hashtags`\n * come from `/api/editor/users` and `/api/editor/tags` through the context's HTTP client, and only once a popup is used.\n * Contributes the `normalize` stage: `@name` / `#tag` text of imported or AI-written Markdown becomes chips when it\n * matches a known user or an existing tag. Contributes no components (`EditorFeature<never>`), so it fits a preset of\n * any framework layer.\n */\nexport function mentionsFeature(): EditorFeature<never> {\n return {\n id: 'mentions',\n extensions: ctx => [\n MentionNode.configure({ suggestion: mentionSuggestion(ctx.t) }),\n TagNode.configure({\n suggestion: tagSuggestion(ctx.t),\n onCreate: (editor, name) => metadataOf(editor).create('hashtags', { id: name, label: name }),\n }),\n ],\n metadataDefaults: ctx => mentionsMetadata(ctx),\n blocks: { normalize: normalizeMentions },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAsCA,SAAgB,kBAAwC;CACtD,OAAO;EACL,IAAI;EACJ,aAAY,QAAO,CACjB,YAAY,UAAU,EAAE,YAAY,kBAAkB,IAAI,CAAC,EAAE,CAAC,GAC9D,QAAQ,UAAU;GAChB,YAAY,cAAc,IAAI,CAAC;GAC/B,WAAW,QAAQ,SAAS,WAAW,MAAM,CAAC,CAAC,OAAO,YAAY;IAAE,IAAI;IAAM,OAAO;GAAK,CAAC;EAC7F,CAAC,CACH;EACA,mBAAkB,QAAO,iBAAiB,GAAG;EAC7C,QAAQ,EAAE,WAAW,kBAAkB;CACzC;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/features/mentions/index.ts"],"sourcesContent":["import type { EditorFeature } from '../../core'\nimport { metadataOf } from '../../core'\nimport { mentionSuggestion } from './mention-suggestion'\nimport { mentionsMetadata } from './metadata-defaults'\nimport { MentionNode } from './mention'\nimport { mentionsSchemaExtensions } from './schema'\nimport { normalizeMentions } from './normalize'\nimport { tagSuggestion } from './tag-suggestion'\nimport { TagNode } from './tag'\n\nexport { mentionSuggestion } from './mention-suggestion'\nexport { mentionsMetadata } from './metadata-defaults'\nexport { normalizeMentions } from './normalize'\nexport { tagSuggestion } from './tag-suggestion'\nexport {\n collectTagNames,\n type MentionAttrs,\n MentionNode,\n type MentionTarget,\n mentionsFromText,\n mentionUsersIn,\n type MentionUser,\n normalizeTagName,\n TAG_NODE,\n TagNode,\n type TagAttrs,\n type TagOptions,\n type TagSuggestionItem,\n tagsFromText,\n TagSuggestionPluginKey,\n} from './schema'\n\n/**\n * `@user` mention chips and `#tag` chips with their suggestion popups. Without a host list, `mentions` and `hashtags`\n * come from the context's backend (`users` and `tags`; the HTTP backend asks `/api/editor/users` and `/api/editor/tags`), and only once a popup is used.\n * Contributes the `normalize` stage: `@name` / `#tag` text of imported or AI-written Markdown becomes chips when it\n * matches a known user or an existing tag. Contributes no components (`EditorFeature<never>`), so it fits a preset of\n * any framework layer.\n */\nexport function mentionsFeature(): EditorFeature<never> {\n return {\n id: 'mentions',\n dimension: 'content',\n schemaExtensions: mentionsSchemaExtensions,\n extensions: ctx => [\n MentionNode.configure({ suggestion: mentionSuggestion(ctx.t) }),\n TagNode.configure({\n suggestion: tagSuggestion(ctx.t),\n onCreate: (editor, name) => metadataOf(editor).create('hashtags', { id: name, label: name }),\n }),\n ],\n metadataDefaults: ctx => mentionsMetadata(ctx),\n blocks: { normalize: normalizeMentions },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAuCA,SAAgB,kBAAwC;CACtD,OAAO;EACL,IAAI;EACJ,WAAW;EACX,kBAAkB;EAClB,aAAY,QAAO,CACjB,YAAY,UAAU,EAAE,YAAY,kBAAkB,IAAI,CAAC,EAAE,CAAC,GAC9D,QAAQ,UAAU;GAChB,YAAY,cAAc,IAAI,CAAC;GAC/B,WAAW,QAAQ,SAAS,WAAW,MAAM,CAAC,CAAC,OAAO,YAAY;IAAE,IAAI;IAAM,OAAO;GAAK,CAAC;EAC7F,CAAC,CACH;EACA,mBAAkB,QAAO,iBAAiB,GAAG;EAC7C,QAAQ,EAAE,WAAW,kBAAkB;CACzC;AACF"}
@@ -1,4 +1,4 @@
1
- import { MentionUser } from "./mention.js";
1
+ import { MentionUser } from "../../core/backend-types.js";
2
2
  import { JSONContent } from "@tiptap/core";
3
3
  //#region src/features/mentions/mention-text.d.ts
4
4
  /** A user `@username` may resolve to: a registered user, or the attrs of an existing chip (colour possibly unset). */
@@ -1 +1 @@
1
- {"version":3,"file":"mention-text.js","names":[],"sources":["../../../src/features/mentions/mention-text.ts"],"sourcesContent":["import type { JSONContent } from '@tiptap/core'\nimport type { MentionUser } from './mention'\n\n/** A user `@username` may resolve to: a registered user, or the attrs of an existing chip (colour possibly unset). */\nexport type MentionTarget = Pick<MentionUser, 'id' | 'username'> & { color: string | null }\n\n/**\n * Turns `@username` tokens in text nodes into `mention` nodes (attrs id, label = username, color) — for\n * AI-generated Markdown, whose parser only knows the `[@ …]` shortcode. Matches known users only,\n * case-insensitively; unknown `@foo`, e-mail addresses and text in code blocks, inline code or links stay plain.\n * Returns the input unchanged when nothing matched.\n */\nexport function mentionsFromText(json: JSONContent, users: readonly MentionTarget[]): JSONContent {\n const byName = new Map(users.filter(u => u.username).map(u => [u.username.toLowerCase(), u]))\n if (!byName.size) return json\n const names = [...byName.keys()].sort((a, b) => b.length - a.length).map(n => n.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))\n // Not preceded by a word char, `@` or `.` (e-mail), not followed by a word char or `-`; a trailing `.` ends the sentence.\n const token = new RegExp(`(?<![\\\\p{L}\\\\p{N}_@.])@(${names.join('|')})(?![\\\\p{L}\\\\p{N}_-]|\\\\.[\\\\p{L}\\\\p{N}_])`, 'giu')\n\n const splitText = (node: JSONContent): JSONContent[] => {\n const text = node.text ?? ''\n // Text in inline code or a link stays literal.\n if (!text.includes('@') || node.marks?.some(m => m.type === 'code' || m.type === 'link')) return [node]\n const out: JSONContent[] = []\n let last = 0\n for (const match of text.matchAll(token)) {\n const at = match.index ?? 0\n const user = byName.get(match[1]!.toLowerCase())!\n if (at > last) out.push({ ...node, text: text.slice(last, at) })\n out.push({\n type: 'mention',\n attrs: { id: user.id, label: user.username, color: user.color },\n ...(node.marks?.length ? { marks: node.marks } : {}),\n })\n last = at + match[0].length\n }\n if (!out.length) return [node]\n if (last < text.length) out.push({ ...node, text: text.slice(last) })\n return out\n }\n\n const walk = (node: JSONContent): JSONContent => {\n if (!node.content || node.type === 'codeBlock') return node\n let changed = false\n const content = node.content.flatMap((child) => {\n const next = child.type === 'text' ? splitText(child) : [walk(child)]\n if (next.length !== 1 || next[0] !== child) changed = true\n return next\n })\n return changed ? { ...node, content } : node\n }\n return walk(json)\n}\n\n/** Users of the mention chips inside a JSON tree, e.g. the range an AI result replaces (so echoed `@name`s stay chips). */\nexport function mentionUsersIn(json: JSONContent | JSONContent[]): MentionTarget[] {\n const found = new Map<string, MentionTarget>()\n const visit = (node: JSONContent) => {\n if (node.type === 'mention' && node.attrs?.id && node.attrs.label) {\n found.set(String(node.attrs.id), { id: String(node.attrs.id), username: String(node.attrs.label), color: node.attrs.color ?? null })\n }\n node.content?.forEach(visit)\n }\n ;(Array.isArray(json) ? json : [json]).forEach(visit)\n return [...found.values()]\n}\n"],"mappings":";;;;;;;AAYA,SAAgB,iBAAiB,MAAmB,OAA8C;CAChG,MAAM,SAAS,IAAI,IAAI,MAAM,QAAO,MAAK,EAAE,QAAQ,CAAC,CAAC,KAAI,MAAK,CAAC,EAAE,SAAS,YAAY,GAAG,CAAC,CAAC,CAAC;CAC5F,IAAI,CAAC,OAAO,MAAM,OAAO;CACzB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,KAAI,MAAK,EAAE,QAAQ,uBAAuB,MAAM,CAAC;CAEtH,MAAM,QAAQ,IAAI,OAAO,2BAA2B,MAAM,KAAK,GAAG,EAAE,2CAA2C,KAAK;CAEpH,MAAM,aAAa,SAAqC;EACtD,MAAM,OAAO,KAAK,QAAQ;EAE1B,IAAI,CAAC,KAAK,SAAS,GAAG,KAAK,KAAK,OAAO,MAAK,MAAK,EAAE,SAAS,UAAU,EAAE,SAAS,MAAM,GAAG,OAAO,CAAC,IAAI;EACtG,MAAM,MAAqB,CAAC;EAC5B,IAAI,OAAO;EACX,KAAK,MAAM,SAAS,KAAK,SAAS,KAAK,GAAG;GACxC,MAAM,KAAK,MAAM,SAAS;GAC1B,MAAM,OAAO,OAAO,IAAI,MAAM,EAAE,CAAE,YAAY,CAAC;GAC/C,IAAI,KAAK,MAAM,IAAI,KAAK;IAAE,GAAG;IAAM,MAAM,KAAK,MAAM,MAAM,EAAE;GAAE,CAAC;GAC/D,IAAI,KAAK;IACP,MAAM;IACN,OAAO;KAAE,IAAI,KAAK;KAAI,OAAO,KAAK;KAAU,OAAO,KAAK;IAAM;IAC9D,GAAI,KAAK,OAAO,SAAS,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;GACpD,CAAC;GACD,OAAO,KAAK,MAAM,EAAE,CAAC;EACvB;EACA,IAAI,CAAC,IAAI,QAAQ,OAAO,CAAC,IAAI;EAC7B,IAAI,OAAO,KAAK,QAAQ,IAAI,KAAK;GAAE,GAAG;GAAM,MAAM,KAAK,MAAM,IAAI;EAAE,CAAC;EACpE,OAAO;CACT;CAEA,MAAM,QAAQ,SAAmC;EAC/C,IAAI,CAAC,KAAK,WAAW,KAAK,SAAS,aAAa,OAAO;EACvD,IAAI,UAAU;EACd,MAAM,UAAU,KAAK,QAAQ,SAAS,UAAU;GAC9C,MAAM,OAAO,MAAM,SAAS,SAAS,UAAU,KAAK,IAAI,CAAC,KAAK,KAAK,CAAC;GACpE,IAAI,KAAK,WAAW,KAAK,KAAK,OAAO,OAAO,UAAU;GACtD,OAAO;EACT,CAAC;EACD,OAAO,UAAU;GAAE,GAAG;GAAM;EAAQ,IAAI;CAC1C;CACA,OAAO,KAAK,IAAI;AAClB;;AAGA,SAAgB,eAAe,MAAoD;CACjF,MAAM,wBAAQ,IAAI,IAA2B;CAC7C,MAAM,SAAS,SAAsB;EACnC,IAAI,KAAK,SAAS,aAAa,KAAK,OAAO,MAAM,KAAK,MAAM,OAC1D,MAAM,IAAI,OAAO,KAAK,MAAM,EAAE,GAAG;GAAE,IAAI,OAAO,KAAK,MAAM,EAAE;GAAG,UAAU,OAAO,KAAK,MAAM,KAAK;GAAG,OAAO,KAAK,MAAM,SAAS;EAAK,CAAC;EAErI,KAAK,SAAS,QAAQ,KAAK;CAC7B;CACC,CAAC,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI,EAAA,CAAG,QAAQ,KAAK;CACpD,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC;AAC3B"}
1
+ {"version":3,"file":"mention-text.js","names":[],"sources":["../../../src/features/mentions/mention-text.ts"],"sourcesContent":["import type { JSONContent } from '@tiptap/core'\nimport type { MentionUser } from '../../core/backend-types'\n\n/** A user `@username` may resolve to: a registered user, or the attrs of an existing chip (colour possibly unset). */\nexport type MentionTarget = Pick<MentionUser, 'id' | 'username'> & { color: string | null }\n\n/**\n * Turns `@username` tokens in text nodes into `mention` nodes (attrs id, label = username, color) — for\n * AI-generated Markdown, whose parser only knows the `[@ …]` shortcode. Matches known users only,\n * case-insensitively; unknown `@foo`, e-mail addresses and text in code blocks, inline code or links stay plain.\n * Returns the input unchanged when nothing matched.\n */\nexport function mentionsFromText(json: JSONContent, users: readonly MentionTarget[]): JSONContent {\n const byName = new Map(users.filter(u => u.username).map(u => [u.username.toLowerCase(), u]))\n if (!byName.size) return json\n const names = [...byName.keys()].sort((a, b) => b.length - a.length).map(n => n.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))\n // Not preceded by a word char, `@` or `.` (e-mail), not followed by a word char or `-`; a trailing `.` ends the sentence.\n const token = new RegExp(`(?<![\\\\p{L}\\\\p{N}_@.])@(${names.join('|')})(?![\\\\p{L}\\\\p{N}_-]|\\\\.[\\\\p{L}\\\\p{N}_])`, 'giu')\n\n const splitText = (node: JSONContent): JSONContent[] => {\n const text = node.text ?? ''\n // Text in inline code or a link stays literal.\n if (!text.includes('@') || node.marks?.some(m => m.type === 'code' || m.type === 'link')) return [node]\n const out: JSONContent[] = []\n let last = 0\n for (const match of text.matchAll(token)) {\n const at = match.index ?? 0\n const user = byName.get(match[1]!.toLowerCase())!\n if (at > last) out.push({ ...node, text: text.slice(last, at) })\n out.push({\n type: 'mention',\n attrs: { id: user.id, label: user.username, color: user.color },\n ...(node.marks?.length ? { marks: node.marks } : {}),\n })\n last = at + match[0].length\n }\n if (!out.length) return [node]\n if (last < text.length) out.push({ ...node, text: text.slice(last) })\n return out\n }\n\n const walk = (node: JSONContent): JSONContent => {\n if (!node.content || node.type === 'codeBlock') return node\n let changed = false\n const content = node.content.flatMap((child) => {\n const next = child.type === 'text' ? splitText(child) : [walk(child)]\n if (next.length !== 1 || next[0] !== child) changed = true\n return next\n })\n return changed ? { ...node, content } : node\n }\n return walk(json)\n}\n\n/** Users of the mention chips inside a JSON tree, e.g. the range an AI result replaces (so echoed `@name`s stay chips). */\nexport function mentionUsersIn(json: JSONContent | JSONContent[]): MentionTarget[] {\n const found = new Map<string, MentionTarget>()\n const visit = (node: JSONContent) => {\n if (node.type === 'mention' && node.attrs?.id && node.attrs.label) {\n found.set(String(node.attrs.id), { id: String(node.attrs.id), username: String(node.attrs.label), color: node.attrs.color ?? null })\n }\n node.content?.forEach(visit)\n }\n ;(Array.isArray(json) ? json : [json]).forEach(visit)\n return [...found.values()]\n}\n"],"mappings":";;;;;;;AAYA,SAAgB,iBAAiB,MAAmB,OAA8C;CAChG,MAAM,SAAS,IAAI,IAAI,MAAM,QAAO,MAAK,EAAE,QAAQ,CAAC,CAAC,KAAI,MAAK,CAAC,EAAE,SAAS,YAAY,GAAG,CAAC,CAAC,CAAC;CAC5F,IAAI,CAAC,OAAO,MAAM,OAAO;CACzB,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,KAAI,MAAK,EAAE,QAAQ,uBAAuB,MAAM,CAAC;CAEtH,MAAM,QAAQ,IAAI,OAAO,2BAA2B,MAAM,KAAK,GAAG,EAAE,2CAA2C,KAAK;CAEpH,MAAM,aAAa,SAAqC;EACtD,MAAM,OAAO,KAAK,QAAQ;EAE1B,IAAI,CAAC,KAAK,SAAS,GAAG,KAAK,KAAK,OAAO,MAAK,MAAK,EAAE,SAAS,UAAU,EAAE,SAAS,MAAM,GAAG,OAAO,CAAC,IAAI;EACtG,MAAM,MAAqB,CAAC;EAC5B,IAAI,OAAO;EACX,KAAK,MAAM,SAAS,KAAK,SAAS,KAAK,GAAG;GACxC,MAAM,KAAK,MAAM,SAAS;GAC1B,MAAM,OAAO,OAAO,IAAI,MAAM,EAAE,CAAE,YAAY,CAAC;GAC/C,IAAI,KAAK,MAAM,IAAI,KAAK;IAAE,GAAG;IAAM,MAAM,KAAK,MAAM,MAAM,EAAE;GAAE,CAAC;GAC/D,IAAI,KAAK;IACP,MAAM;IACN,OAAO;KAAE,IAAI,KAAK;KAAI,OAAO,KAAK;KAAU,OAAO,KAAK;IAAM;IAC9D,GAAI,KAAK,OAAO,SAAS,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;GACpD,CAAC;GACD,OAAO,KAAK,MAAM,EAAE,CAAC;EACvB;EACA,IAAI,CAAC,IAAI,QAAQ,OAAO,CAAC,IAAI;EAC7B,IAAI,OAAO,KAAK,QAAQ,IAAI,KAAK;GAAE,GAAG;GAAM,MAAM,KAAK,MAAM,IAAI;EAAE,CAAC;EACpE,OAAO;CACT;CAEA,MAAM,QAAQ,SAAmC;EAC/C,IAAI,CAAC,KAAK,WAAW,KAAK,SAAS,aAAa,OAAO;EACvD,IAAI,UAAU;EACd,MAAM,UAAU,KAAK,QAAQ,SAAS,UAAU;GAC9C,MAAM,OAAO,MAAM,SAAS,SAAS,UAAU,KAAK,IAAI,CAAC,KAAK,KAAK,CAAC;GACpE,IAAI,KAAK,WAAW,KAAK,KAAK,OAAO,OAAO,UAAU;GACtD,OAAO;EACT,CAAC;EACD,OAAO,UAAU;GAAE,GAAG;GAAM;EAAQ,IAAI;CAC1C;CACA,OAAO,KAAK,IAAI;AAClB;;AAGA,SAAgB,eAAe,MAAoD;CACjF,MAAM,wBAAQ,IAAI,IAA2B;CAC7C,MAAM,SAAS,SAAsB;EACnC,IAAI,KAAK,SAAS,aAAa,KAAK,OAAO,MAAM,KAAK,MAAM,OAC1D,MAAM,IAAI,OAAO,KAAK,MAAM,EAAE,GAAG;GAAE,IAAI,OAAO,KAAK,MAAM,EAAE;GAAG,UAAU,OAAO,KAAK,MAAM,KAAK;GAAG,OAAO,KAAK,MAAM,SAAS;EAAK,CAAC;EAErI,KAAK,SAAS,QAAQ,KAAK;CAC7B;CACC,CAAC,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI,EAAA,CAAG,QAAQ,KAAK;CACpD,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC;AAC3B"}
@@ -1,10 +1,4 @@
1
1
  //#region src/features/mentions/mention.d.ts
2
- /** A user as offered for `@` mentions (`GET /api/editor/users`); never carries credentials. */
3
- export interface MentionUser {
4
- id: string;
5
- username: string;
6
- color: string;
7
- }
8
2
  /** Attributes of a mention chip: `label` is the username, `color` the user's colour, both copied in at insert time. */
9
3
  export type MentionAttrs = {
10
4
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"mention.js","names":[],"sources":["../../../src/features/mentions/mention.ts"],"sourcesContent":["import { Mention } from '@tiptap/extension-mention'\nimport { HEX_COLOR } from '../../core/schema/hex-color'\n\n/** A user as offered for `@` mentions (`GET /api/editor/users`); never carries credentials. */\nexport interface MentionUser {\n id: string\n username: string\n color: string\n}\n\n/** Attributes of a mention chip: `label` is the username, `color` the user's colour, both copied in at insert time. */\nexport type MentionAttrs = {\n id: string\n label: string\n color: string | null\n}\n\n/**\n * Schema part of the `@username` chip, shared by the client editor and the server (collab schema, Markdown).\n * The client adds the suggestion popup via `.configure({ suggestion })` in the mentions feature.\n */\nexport const MentionNode = Mention.extend({\n addOptions() {\n return { ...this.parent!(), HTMLAttributes: { class: 'mention' } }\n },\n addAttributes() {\n return {\n ...this.parent?.(),\n color: {\n default: null,\n parseHTML: el => el.getAttribute('data-color'),\n renderHTML: attrs => HEX_COLOR.test(String(attrs.color ?? ''))\n ? { 'data-color': attrs.color, 'style': `--mention-color: ${attrs.color}` }\n : {},\n },\n }\n },\n // Markdown export (editor.getMarkdown(), AI context/selection) shows the chip as plain `@username`.\n renderMarkdown: node => `@${node.attrs?.label ?? node.attrs?.id ?? ''}`,\n})\n"],"mappings":";;;;;;;AAqBA,MAAa,cAAc,QAAQ,OAAO;CACxC,aAAa;EACX,OAAO;GAAE,GAAG,KAAK,OAAQ;GAAG,gBAAgB,EAAE,OAAO,UAAU;EAAE;CACnE;CACA,gBAAgB;EACd,OAAO;GACL,GAAG,KAAK,SAAS;GACjB,OAAO;IACL,SAAS;IACT,YAAW,OAAM,GAAG,aAAa,YAAY;IAC7C,aAAY,UAAS,UAAU,KAAK,OAAO,MAAM,SAAS,EAAE,CAAC,IACzD;KAAE,cAAc,MAAM;KAAO,SAAS,oBAAoB,MAAM;IAAQ,IACxE,CAAC;GACP;EACF;CACF;CAEA,iBAAgB,SAAQ,IAAI,KAAK,OAAO,SAAS,KAAK,OAAO,MAAM;AACrE,CAAC"}
1
+ {"version":3,"file":"mention.js","names":[],"sources":["../../../src/features/mentions/mention.ts"],"sourcesContent":["import { Mention } from '@tiptap/extension-mention'\nimport { HEX_COLOR } from '../../core/schema/hex-color'\n\n/** Attributes of a mention chip: `label` is the username, `color` the user's colour, both copied in at insert time. */\nexport type MentionAttrs = {\n id: string\n label: string\n color: string | null\n}\n\n/**\n * Schema part of the `@username` chip, shared by the client editor and the server (collab schema, Markdown).\n * The client adds the suggestion popup via `.configure({ suggestion })` in the mentions feature.\n */\nexport const MentionNode = Mention.extend({\n addOptions() {\n return { ...this.parent!(), HTMLAttributes: { class: 'mention' } }\n },\n addAttributes() {\n return {\n ...this.parent?.(),\n color: {\n default: null,\n parseHTML: el => el.getAttribute('data-color'),\n renderHTML: attrs => HEX_COLOR.test(String(attrs.color ?? ''))\n ? { 'data-color': attrs.color, 'style': `--mention-color: ${attrs.color}` }\n : {},\n },\n }\n },\n // Markdown export (editor.getMarkdown(), AI context/selection) shows the chip as plain `@username`.\n renderMarkdown: node => `@${node.attrs?.label ?? node.attrs?.id ?? ''}`,\n})\n"],"mappings":";;;;;;;AAcA,MAAa,cAAc,QAAQ,OAAO;CACxC,aAAa;EACX,OAAO;GAAE,GAAG,KAAK,OAAQ;GAAG,gBAAgB,EAAE,OAAO,UAAU;EAAE;CACnE;CACA,gBAAgB;EACd,OAAO;GACL,GAAG,KAAK,SAAS;GACjB,OAAO;IACL,SAAS;IACT,YAAW,OAAM,GAAG,aAAa,YAAY;IAC7C,aAAY,UAAS,UAAU,KAAK,OAAO,MAAM,SAAS,EAAE,CAAC,IACzD;KAAE,cAAc,MAAM;KAAO,SAAS,oBAAoB,MAAM;IAAQ,IACxE,CAAC;GACP;EACF;CACF;CAEA,iBAAgB,SAAQ,IAAI,KAAK,OAAO,SAAS,KAAK,OAAO,MAAM;AACrE,CAAC"}
@@ -2,7 +2,7 @@ import { EditorMetadata } from "../../core/metadata-types.js";
2
2
  import { FeatureContext } from "../../core/feature.js";
3
3
  import "../../core/index.js";
4
4
  //#region src/features/mentions/metadata-defaults.d.ts
5
- /** Built-in `mentions` and `hashtags` lists when the host supplies none: users and tags from the editor API, through the context's HTTP client. */
6
- export declare function mentionsMetadata(ctx: Pick<FeatureContext, 'fetch'>): EditorMetadata;
5
+ /** Built-in `mentions` and `hashtags` lists when the host supplies none: users and tags from the context's backend (`users`, `tags`); a backend without the capability offers none. */
6
+ export declare function mentionsMetadata(ctx: Pick<FeatureContext, 'backend'>): EditorMetadata;
7
7
  //#endregion
8
8
  //# sourceMappingURL=metadata-defaults.d.ts.map
@@ -1,23 +1,17 @@
1
1
  import { normalizeTagName } from "./tag.js";
2
2
  //#region src/features/mentions/metadata-defaults.ts
3
- /** Built-in `mentions` and `hashtags` lists when the host supplies none: users and tags from the editor API, through the context's HTTP client. */
3
+ /** Built-in `mentions` and `hashtags` lists when the host supplies none: users and tags from the context's backend (`users`, `tags`); a backend without the capability offers none. */
4
4
  function mentionsMetadata(ctx) {
5
5
  return {
6
6
  mentions: async ({ query, signal }) => {
7
- return (await ctx.fetch("/api/editor/users", {
8
- query: { q: query },
9
- signal
10
- })).map(({ id, username, color }) => ({
7
+ return (await ctx.backend.users?.search(query, signal) ?? []).map(({ id, username, color }) => ({
11
8
  id,
12
9
  label: username,
13
10
  color
14
11
  }));
15
12
  },
16
13
  hashtags: async ({ query, signal }) => {
17
- return (await ctx.fetch("/api/editor/tags", {
18
- query: { q: normalizeTagName(query) },
19
- signal
20
- })).map((tag) => ({
14
+ return (await ctx.backend.tags?.search(normalizeTagName(query), signal) ?? []).map((tag) => ({
21
15
  id: tag,
22
16
  label: tag
23
17
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"metadata-defaults.js","names":[],"sources":["../../../src/features/mentions/metadata-defaults.ts"],"sourcesContent":["import type { EditorMetadata, FeatureContext } from '../../core'\nimport { normalizeTagName } from './tag'\n\n/** Built-in `mentions` and `hashtags` lists when the host supplies none: users and tags from the editor API, through the context's HTTP client. */\nexport function mentionsMetadata(ctx: Pick<FeatureContext, 'fetch'>): EditorMetadata {\n return {\n mentions: async ({ query, signal }) => {\n const users = await ctx.fetch<{ id: string, username: string, color: string }[]>('/api/editor/users', { query: { q: query }, signal })\n return users.map(({ id, username, color }) => ({ id, label: username, color }))\n },\n hashtags: async ({ query, signal }) => {\n const tags = await ctx.fetch<string[]>('/api/editor/tags', { query: { q: normalizeTagName(query) }, signal })\n return tags.map(tag => ({ id: tag, label: tag }))\n },\n }\n}\n"],"mappings":";;;AAIA,SAAgB,iBAAiB,KAAoD;CACnF,OAAO;EACL,UAAU,OAAO,EAAE,OAAO,aAAa;GAErC,QAAO,MADa,IAAI,MAAyD,qBAAqB;IAAE,OAAO,EAAE,GAAG,MAAM;IAAG;GAAO,CAAC,EAAA,CACxH,KAAK,EAAE,IAAI,UAAU,aAAa;IAAE;IAAI,OAAO;IAAU;GAAM,EAAE;EAChF;EACA,UAAU,OAAO,EAAE,OAAO,aAAa;GAErC,QAAO,MADY,IAAI,MAAgB,oBAAoB;IAAE,OAAO,EAAE,GAAG,iBAAiB,KAAK,EAAE;IAAG;GAAO,CAAC,EAAA,CAChG,KAAI,SAAQ;IAAE,IAAI;IAAK,OAAO;GAAI,EAAE;EAClD;CACF;AACF"}
1
+ {"version":3,"file":"metadata-defaults.js","names":[],"sources":["../../../src/features/mentions/metadata-defaults.ts"],"sourcesContent":["import type { EditorMetadata, FeatureContext } from '../../core'\nimport { normalizeTagName } from './tag'\n\n/** Built-in `mentions` and `hashtags` lists when the host supplies none: users and tags from the context's backend (`users`, `tags`); a backend without the capability offers none. */\nexport function mentionsMetadata(ctx: Pick<FeatureContext, 'backend'>): EditorMetadata {\n return {\n mentions: async ({ query, signal }) => {\n const users = await ctx.backend.users?.search(query, signal) ?? []\n return users.map(({ id, username, color }) => ({ id, label: username, color }))\n },\n hashtags: async ({ query, signal }) => {\n const tags = await ctx.backend.tags?.search(normalizeTagName(query), signal) ?? []\n return tags.map(tag => ({ id: tag, label: tag }))\n },\n }\n}\n"],"mappings":";;;AAIA,SAAgB,iBAAiB,KAAsD;CACrF,OAAO;EACL,UAAU,OAAO,EAAE,OAAO,aAAa;GAErC,QADc,MAAM,IAAI,QAAQ,OAAO,OAAO,OAAO,MAAM,KAAK,CAAC,EAAA,CACpD,KAAK,EAAE,IAAI,UAAU,aAAa;IAAE;IAAI,OAAO;IAAU;GAAM,EAAE;EAChF;EACA,UAAU,OAAO,EAAE,OAAO,aAAa;GAErC,QADa,MAAM,IAAI,QAAQ,MAAM,OAAO,iBAAiB,KAAK,GAAG,MAAM,KAAK,CAAC,EAAA,CACrE,KAAI,SAAQ;IAAE,IAAI;IAAK,OAAO;GAAI,EAAE;EAClD;CACF;AACF"}
@@ -1,4 +1,5 @@
1
- import { MentionAttrs, MentionNode, MentionUser } from "./mention.js";
1
+ import { MentionUser } from "../../core/backend-types.js";
2
+ import { MentionAttrs, MentionNode } from "./mention.js";
2
3
  import { MentionTarget, mentionUsersIn, mentionsFromText } from "./mention-text.js";
3
4
  import { TAG_NODE, TagAttrs, TagNode, TagOptions, TagSuggestionItem, TagSuggestionPluginKey, collectTagNames, normalizeTagName, tagsFromText } from "./tag.js";
4
5
  import { AnyExtension } from "@tiptap/core";
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","names":[],"sources":["../../../src/features/mentions/schema.ts"],"sourcesContent":["import type { AnyExtension } from '@tiptap/core'\nimport { MentionNode } from './mention'\nimport { TagNode } from './tag'\n\n// Vue-free and server-importable (`@ecsplico/editor/mentions/schema`): the mention and tag nodes, their Markdown\n// forms and the text helpers that turn `@name` / `#tag` back into chips. The suggestion popups live in the feature.\n\nexport { type MentionAttrs, MentionNode, type MentionUser } from './mention'\nexport { type MentionTarget, mentionsFromText, mentionUsersIn } from './mention-text'\nexport { collectTagNames, normalizeTagName, TAG_NODE, TagNode, type TagAttrs, type TagOptions, type TagSuggestionItem, tagsFromText, TagSuggestionPluginKey } from './tag'\n\n/** The mention and tag nodes of the document schema. */\nexport const mentionsSchemaExtensions = (): AnyExtension[] => [MentionNode, TagNode]\n"],"mappings":";;;;;AAYA,MAAa,iCAAiD,CAAC,aAAa,OAAO"}
1
+ {"version":3,"file":"schema.js","names":[],"sources":["../../../src/features/mentions/schema.ts"],"sourcesContent":["import type { AnyExtension } from '@tiptap/core'\nimport { MentionNode } from './mention'\nimport { TagNode } from './tag'\n\n// Vue-free and server-importable (`@ecsplico/editor/mentions/schema`): the mention and tag nodes, their Markdown\n// forms and the text helpers that turn `@name` / `#tag` back into chips. The suggestion popups live in the feature.\n\nexport type { MentionUser } from '../../core/backend-types'\nexport { type MentionAttrs, MentionNode } from './mention'\nexport { type MentionTarget, mentionsFromText, mentionUsersIn } from './mention-text'\nexport { collectTagNames, normalizeTagName, TAG_NODE, TagNode, type TagAttrs, type TagOptions, type TagSuggestionItem, tagsFromText, TagSuggestionPluginKey } from './tag'\n\n/** The mention and tag nodes of the document schema. */\nexport const mentionsSchemaExtensions = (): AnyExtension[] => [MentionNode, TagNode]\n"],"mappings":";;;;;AAaA,MAAa,iCAAiD,CAAC,aAAa,OAAO"}
@@ -6,7 +6,8 @@ export declare const TABLE_TOOLBAR_GROUP = "table";
6
6
  /**
7
7
  * GFM tables and task lists: the table and task-list nodes (Markdown round-trips through `@tiptap/markdown`, tables as
8
8
  * pipe tables, tasks as `- [ ]`/`- [x]`), the toolbar group `table` (insert 3×3, add row, add column, delete row, delete
9
- * column, delete table) and the slash entries `table.insert` and `task.insert`. All are offered where the caret has
9
+ * column, delete table) and the slash entries `table.insert` and `task.insert`: one command each, the table commands
10
+ * on the toolbar, `insertTable` and `task.insert` also in the `/` menu. All are offered where the caret has
10
11
  * `block.content`. Contributes no components (`EditorFeature<never>`), so it fits a preset of any framework layer.
11
12
  */
12
13
  export declare function tablesFeature(): EditorFeature<never>;
@@ -1,5 +1,5 @@
1
1
  import { ABILITY } from "../../core/schema/abilities.js";
2
- import { commandItem } from "../../core/toolbar.js";
2
+ import { command } from "../../core/commands.js";
3
3
  import { tablesSchemaExtensions } from "./schema.js";
4
4
  //#region src/features/tables/feature.ts
5
5
  /** The toolbar group the tables feature contributes; its position follows the core groups (`blocks` is 40). */
@@ -10,88 +10,108 @@ const INSERT = {
10
10
  cols: 3,
11
11
  withHeaderRow: true
12
12
  };
13
- const toolbar = (ctx) => [{
13
+ const toolbarGroups = [{
14
14
  id: TABLE_TOOLBAR_GROUP,
15
15
  order: 60,
16
- items: [
17
- {
18
- ...commandItem({
19
- id: "insertTable",
20
- order: 10,
21
- icon: "i-lucide-table",
22
- label: ctx.t("tables.toolbar.insert"),
23
- ability: ABILITY.blockContent,
24
- command: (c) => c.insertTable(INSERT)
25
- }),
26
- disabled: (editor) => editor.isActive("table") || !editor.can().insertTable(INSERT)
27
- },
28
- commandItem({
29
- id: "addRow",
30
- order: 20,
31
- icon: "i-lucide-between-horizontal-end",
32
- label: ctx.t("tables.toolbar.addRow"),
33
- ability: ABILITY.blockContent,
34
- command: (c) => c.addRowAfter()
35
- }),
36
- commandItem({
37
- id: "addColumn",
38
- order: 30,
39
- icon: "i-lucide-between-vertical-end",
40
- label: ctx.t("tables.toolbar.addColumn"),
41
- ability: ABILITY.blockContent,
42
- command: (c) => c.addColumnAfter()
43
- }),
44
- commandItem({
45
- id: "deleteRow",
46
- order: 40,
47
- icon: "i-lucide-table-rows-split",
48
- label: ctx.t("tables.toolbar.deleteRow"),
49
- ability: ABILITY.blockContent,
50
- command: (c) => c.deleteRow()
51
- }),
52
- commandItem({
53
- id: "deleteColumn",
54
- order: 50,
55
- icon: "i-lucide-table-columns-split",
56
- label: ctx.t("tables.toolbar.deleteColumn"),
16
+ labelKey: "palette.group.table"
17
+ }];
18
+ const commands = (ctx) => [
19
+ {
20
+ ...command({
21
+ id: "insertTable",
22
+ toolbar: {
23
+ group: TABLE_TOOLBAR_GROUP,
24
+ order: 10
25
+ },
26
+ slash: { id: "table.insert" },
27
+ creates: { type: "table" },
28
+ icon: "i-lucide-table",
29
+ label: ctx.t("tables.toolbar.insert"),
57
30
  ability: ABILITY.blockContent,
58
- command: (c) => c.deleteColumn()
31
+ command: (c) => c.insertTable(INSERT)
59
32
  }),
60
- commandItem({
61
- id: "deleteTable",
62
- order: 60,
63
- icon: "i-lucide-trash-2",
64
- label: ctx.t("tables.toolbar.deleteTable"),
65
- ability: ABILITY.blockContent,
66
- command: (c) => c.deleteTable()
67
- })
68
- ]
69
- }];
70
- const slashCommands = (ctx) => [{
71
- id: "table.insert",
72
- label: ctx.t("tables.slash.table"),
73
- icon: "i-lucide-table",
74
- ability: ABILITY.blockContent,
75
- run: (editor) => void editor.chain().focus().insertTable(INSERT).run()
76
- }, {
77
- id: "task.insert",
78
- label: ctx.t("tables.slash.tasks"),
79
- icon: "i-lucide-list-checks",
80
- ability: ABILITY.blockContent,
81
- run: (editor) => void editor.chain().focus().toggleTaskList().run()
82
- }];
33
+ can: (editor) => !editor.isActive("table") && editor.can().insertTable(INSERT)
34
+ },
35
+ command({
36
+ id: "addRow",
37
+ toolbar: {
38
+ group: TABLE_TOOLBAR_GROUP,
39
+ order: 20
40
+ },
41
+ icon: "i-lucide-between-horizontal-end",
42
+ label: ctx.t("tables.toolbar.addRow"),
43
+ ability: ABILITY.blockContent,
44
+ command: (c) => c.addRowAfter()
45
+ }),
46
+ command({
47
+ id: "addColumn",
48
+ toolbar: {
49
+ group: TABLE_TOOLBAR_GROUP,
50
+ order: 30
51
+ },
52
+ icon: "i-lucide-between-vertical-end",
53
+ label: ctx.t("tables.toolbar.addColumn"),
54
+ ability: ABILITY.blockContent,
55
+ command: (c) => c.addColumnAfter()
56
+ }),
57
+ command({
58
+ id: "deleteRow",
59
+ toolbar: {
60
+ group: TABLE_TOOLBAR_GROUP,
61
+ order: 40
62
+ },
63
+ icon: "i-lucide-table-rows-split",
64
+ label: ctx.t("tables.toolbar.deleteRow"),
65
+ ability: ABILITY.blockContent,
66
+ command: (c) => c.deleteRow()
67
+ }),
68
+ command({
69
+ id: "deleteColumn",
70
+ toolbar: {
71
+ group: TABLE_TOOLBAR_GROUP,
72
+ order: 50
73
+ },
74
+ icon: "i-lucide-table-columns-split",
75
+ label: ctx.t("tables.toolbar.deleteColumn"),
76
+ ability: ABILITY.blockContent,
77
+ command: (c) => c.deleteColumn()
78
+ }),
79
+ command({
80
+ id: "deleteTable",
81
+ toolbar: {
82
+ group: TABLE_TOOLBAR_GROUP,
83
+ order: 60
84
+ },
85
+ icon: "i-lucide-trash-2",
86
+ label: ctx.t("tables.toolbar.deleteTable"),
87
+ ability: ABILITY.blockContent,
88
+ command: (c) => c.deleteTable()
89
+ }),
90
+ command({
91
+ id: "task.insert",
92
+ slash: { id: "task.insert" },
93
+ creates: { type: "taskList" },
94
+ icon: "i-lucide-list-checks",
95
+ label: ctx.t("tables.slash.tasks"),
96
+ ability: ABILITY.blockContent,
97
+ command: (c) => c.toggleTaskList()
98
+ })
99
+ ];
83
100
  /**
84
101
  * GFM tables and task lists: the table and task-list nodes (Markdown round-trips through `@tiptap/markdown`, tables as
85
102
  * pipe tables, tasks as `- [ ]`/`- [x]`), the toolbar group `table` (insert 3×3, add row, add column, delete row, delete
86
- * column, delete table) and the slash entries `table.insert` and `task.insert`. All are offered where the caret has
103
+ * column, delete table) and the slash entries `table.insert` and `task.insert`: one command each, the table commands
104
+ * on the toolbar, `insertTable` and `task.insert` also in the `/` menu. All are offered where the caret has
87
105
  * `block.content`. Contributes no components (`EditorFeature<never>`), so it fits a preset of any framework layer.
88
106
  */
89
107
  function tablesFeature() {
90
108
  return {
91
109
  id: "tables",
110
+ dimension: "content",
111
+ schemaExtensions: tablesSchemaExtensions,
92
112
  extensions: () => tablesSchemaExtensions(),
93
- toolbar,
94
- slashCommands
113
+ toolbarGroups,
114
+ commands
95
115
  };
96
116
  }
97
117
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"feature.js","names":[],"sources":["../../../src/features/tables/feature.ts"],"sourcesContent":["import { commandItem, type EditorFeature, type FeatureContext, type SlashCommandItem, type ToolbarGroup } from '../../core'\nimport { ABILITY } from '../../core/schema'\nimport { tablesSchemaExtensions } from './schema'\n\n/** The toolbar group the tables feature contributes; its position follows the core groups (`blocks` is 40). */\nexport const TABLE_TOOLBAR_GROUP = 'table'\n\n/** Columns, rows and header row of a table the toolbar and the slash menu insert. */\nconst INSERT = { rows: 3, cols: 3, withHeaderRow: true } as const\n\nconst toolbar = (ctx: FeatureContext): ToolbarGroup<never>[] => [{\n id: TABLE_TOOLBAR_GROUP,\n order: 60,\n items: [\n {\n ...commandItem({ id: 'insertTable', order: 10, icon: 'i-lucide-table', label: ctx.t('tables.toolbar.insert'), ability: ABILITY.blockContent, command: c => c.insertTable(INSERT) }),\n // GFM has no nested tables: inside one the button is off.\n disabled: editor => editor.isActive('table') || !editor.can().insertTable(INSERT),\n },\n commandItem({ id: 'addRow', order: 20, icon: 'i-lucide-between-horizontal-end', label: ctx.t('tables.toolbar.addRow'), ability: ABILITY.blockContent, command: c => c.addRowAfter() }),\n commandItem({ id: 'addColumn', order: 30, icon: 'i-lucide-between-vertical-end', label: ctx.t('tables.toolbar.addColumn'), ability: ABILITY.blockContent, command: c => c.addColumnAfter() }),\n commandItem({ id: 'deleteRow', order: 40, icon: 'i-lucide-table-rows-split', label: ctx.t('tables.toolbar.deleteRow'), ability: ABILITY.blockContent, command: c => c.deleteRow() }),\n commandItem({ id: 'deleteColumn', order: 50, icon: 'i-lucide-table-columns-split', label: ctx.t('tables.toolbar.deleteColumn'), ability: ABILITY.blockContent, command: c => c.deleteColumn() }),\n commandItem({ id: 'deleteTable', order: 60, icon: 'i-lucide-trash-2', label: ctx.t('tables.toolbar.deleteTable'), ability: ABILITY.blockContent, command: c => c.deleteTable() }),\n ],\n}]\n\nconst slashCommands = (ctx: FeatureContext): SlashCommandItem[] => [\n { id: 'table.insert', label: ctx.t('tables.slash.table'), icon: 'i-lucide-table', ability: ABILITY.blockContent, run: editor => void editor.chain().focus().insertTable(INSERT).run() },\n { id: 'task.insert', label: ctx.t('tables.slash.tasks'), icon: 'i-lucide-list-checks', ability: ABILITY.blockContent, run: editor => void editor.chain().focus().toggleTaskList().run() },\n]\n\n/**\n * GFM tables and task lists: the table and task-list nodes (Markdown round-trips through `@tiptap/markdown`, tables as\n * pipe tables, tasks as `- [ ]`/`- [x]`), the toolbar group `table` (insert 3×3, add row, add column, delete row, delete\n * column, delete table) and the slash entries `table.insert` and `task.insert`. All are offered where the caret has\n * `block.content`. Contributes no components (`EditorFeature<never>`), so it fits a preset of any framework layer.\n */\nexport function tablesFeature(): EditorFeature<never> {\n return {\n id: 'tables',\n extensions: () => tablesSchemaExtensions(),\n toolbar,\n slashCommands,\n }\n}\n"],"mappings":";;;;;AAKA,MAAa,sBAAsB;;AAGnC,MAAM,SAAS;CAAE,MAAM;CAAG,MAAM;CAAG,eAAe;AAAK;AAEvD,MAAM,WAAW,QAA+C,CAAC;CAC/D,IAAI;CACJ,OAAO;CACP,OAAO;EACL;GACE,GAAG,YAAY;IAAE,IAAI;IAAe,OAAO;IAAI,MAAM;IAAkB,OAAO,IAAI,EAAE,uBAAuB;IAAG,SAAS,QAAQ;IAAc,UAAS,MAAK,EAAE,YAAY,MAAM;GAAE,CAAC;GAElL,WAAU,WAAU,OAAO,SAAS,OAAO,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,YAAY,MAAM;EAClF;EACA,YAAY;GAAE,IAAI;GAAU,OAAO;GAAI,MAAM;GAAmC,OAAO,IAAI,EAAE,uBAAuB;GAAG,SAAS,QAAQ;GAAc,UAAS,MAAK,EAAE,YAAY;EAAE,CAAC;EACrL,YAAY;GAAE,IAAI;GAAa,OAAO;GAAI,MAAM;GAAiC,OAAO,IAAI,EAAE,0BAA0B;GAAG,SAAS,QAAQ;GAAc,UAAS,MAAK,EAAE,eAAe;EAAE,CAAC;EAC5L,YAAY;GAAE,IAAI;GAAa,OAAO;GAAI,MAAM;GAA6B,OAAO,IAAI,EAAE,0BAA0B;GAAG,SAAS,QAAQ;GAAc,UAAS,MAAK,EAAE,UAAU;EAAE,CAAC;EACnL,YAAY;GAAE,IAAI;GAAgB,OAAO;GAAI,MAAM;GAAgC,OAAO,IAAI,EAAE,6BAA6B;GAAG,SAAS,QAAQ;GAAc,UAAS,MAAK,EAAE,aAAa;EAAE,CAAC;EAC/L,YAAY;GAAE,IAAI;GAAe,OAAO;GAAI,MAAM;GAAoB,OAAO,IAAI,EAAE,4BAA4B;GAAG,SAAS,QAAQ;GAAc,UAAS,MAAK,EAAE,YAAY;EAAE,CAAC;CAClL;AACF,CAAC;AAED,MAAM,iBAAiB,QAA4C,CACjE;CAAE,IAAI;CAAgB,OAAO,IAAI,EAAE,oBAAoB;CAAG,MAAM;CAAkB,SAAS,QAAQ;CAAc,MAAK,WAAU,KAAK,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,YAAY,MAAM,CAAC,CAAC,IAAI;AAAE,GACtL;CAAE,IAAI;CAAe,OAAO,IAAI,EAAE,oBAAoB;CAAG,MAAM;CAAwB,SAAS,QAAQ;CAAc,MAAK,WAAU,KAAK,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,IAAI;AAAE,CAC1L;;;;;;;AAQA,SAAgB,gBAAsC;CACpD,OAAO;EACL,IAAI;EACJ,kBAAkB,uBAAuB;EACzC;EACA;CACF;AACF"}
1
+ {"version":3,"file":"feature.js","names":[],"sources":["../../../src/features/tables/feature.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { type CommandDef, command, type EditorFeature, type FeatureContext, type ToolbarGroupDef } from '../../core'\nimport { ABILITY } from '../../core/schema'\nimport { tablesSchemaExtensions } from './schema'\n\n/** The toolbar group the tables feature contributes; its position follows the core groups (`blocks` is 40). */\nexport const TABLE_TOOLBAR_GROUP = 'table'\n\n/** Columns, rows and header row of a table the toolbar and the slash menu insert. */\nconst INSERT = { rows: 3, cols: 3, withHeaderRow: true } as const\n\nconst toolbarGroups: ToolbarGroupDef[] = [{ id: TABLE_TOOLBAR_GROUP, order: 60, labelKey: 'palette.group.table' }]\n\nconst commands = (ctx: FeatureContext): CommandDef<never>[] => [\n {\n ...command({\n id: 'insertTable',\n toolbar: { group: TABLE_TOOLBAR_GROUP, order: 10 },\n slash: { id: 'table.insert' },\n creates: { type: 'table' },\n icon: 'i-lucide-table',\n label: ctx.t('tables.toolbar.insert'),\n ability: ABILITY.blockContent,\n command: c => c.insertTable(INSERT),\n }),\n // GFM has no nested tables: inside one the command is off.\n can: (editor: Editor) => !editor.isActive('table') && editor.can().insertTable(INSERT),\n },\n command({ id: 'addRow', toolbar: { group: TABLE_TOOLBAR_GROUP, order: 20 }, icon: 'i-lucide-between-horizontal-end', label: ctx.t('tables.toolbar.addRow'), ability: ABILITY.blockContent, command: c => c.addRowAfter() }),\n command({ id: 'addColumn', toolbar: { group: TABLE_TOOLBAR_GROUP, order: 30 }, icon: 'i-lucide-between-vertical-end', label: ctx.t('tables.toolbar.addColumn'), ability: ABILITY.blockContent, command: c => c.addColumnAfter() }),\n command({ id: 'deleteRow', toolbar: { group: TABLE_TOOLBAR_GROUP, order: 40 }, icon: 'i-lucide-table-rows-split', label: ctx.t('tables.toolbar.deleteRow'), ability: ABILITY.blockContent, command: c => c.deleteRow() }),\n command({ id: 'deleteColumn', toolbar: { group: TABLE_TOOLBAR_GROUP, order: 50 }, icon: 'i-lucide-table-columns-split', label: ctx.t('tables.toolbar.deleteColumn'), ability: ABILITY.blockContent, command: c => c.deleteColumn() }),\n command({ id: 'deleteTable', toolbar: { group: TABLE_TOOLBAR_GROUP, order: 60 }, icon: 'i-lucide-trash-2', label: ctx.t('tables.toolbar.deleteTable'), ability: ABILITY.blockContent, command: c => c.deleteTable() }),\n command({ id: 'task.insert', slash: { id: 'task.insert' }, creates: { type: 'taskList' }, icon: 'i-lucide-list-checks', label: ctx.t('tables.slash.tasks'), ability: ABILITY.blockContent, command: c => c.toggleTaskList() }),\n]\n\n/**\n * GFM tables and task lists: the table and task-list nodes (Markdown round-trips through `@tiptap/markdown`, tables as\n * pipe tables, tasks as `- [ ]`/`- [x]`), the toolbar group `table` (insert 3×3, add row, add column, delete row, delete\n * column, delete table) and the slash entries `table.insert` and `task.insert`: one command each, the table commands\n * on the toolbar, `insertTable` and `task.insert` also in the `/` menu. All are offered where the caret has\n * `block.content`. Contributes no components (`EditorFeature<never>`), so it fits a preset of any framework layer.\n */\nexport function tablesFeature(): EditorFeature<never> {\n return {\n id: 'tables',\n dimension: 'content',\n schemaExtensions: tablesSchemaExtensions,\n extensions: () => tablesSchemaExtensions(),\n toolbarGroups,\n commands,\n }\n}\n"],"mappings":";;;;;AAMA,MAAa,sBAAsB;;AAGnC,MAAM,SAAS;CAAE,MAAM;CAAG,MAAM;CAAG,eAAe;AAAK;AAEvD,MAAM,gBAAmC,CAAC;CAAE,IAAI;CAAqB,OAAO;CAAI,UAAU;AAAsB,CAAC;AAEjH,MAAM,YAAY,QAA6C;CAC7D;EACE,GAAG,QAAQ;GACT,IAAI;GACJ,SAAS;IAAE,OAAO;IAAqB,OAAO;GAAG;GACjD,OAAO,EAAE,IAAI,eAAe;GAC5B,SAAS,EAAE,MAAM,QAAQ;GACzB,MAAM;GACN,OAAO,IAAI,EAAE,uBAAuB;GACpC,SAAS,QAAQ;GACjB,UAAS,MAAK,EAAE,YAAY,MAAM;EACpC,CAAC;EAED,MAAM,WAAmB,CAAC,OAAO,SAAS,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,YAAY,MAAM;CACvF;CACA,QAAQ;EAAE,IAAI;EAAU,SAAS;GAAE,OAAO;GAAqB,OAAO;EAAG;EAAG,MAAM;EAAmC,OAAO,IAAI,EAAE,uBAAuB;EAAG,SAAS,QAAQ;EAAc,UAAS,MAAK,EAAE,YAAY;CAAE,CAAC;CAC1N,QAAQ;EAAE,IAAI;EAAa,SAAS;GAAE,OAAO;GAAqB,OAAO;EAAG;EAAG,MAAM;EAAiC,OAAO,IAAI,EAAE,0BAA0B;EAAG,SAAS,QAAQ;EAAc,UAAS,MAAK,EAAE,eAAe;CAAE,CAAC;CACjO,QAAQ;EAAE,IAAI;EAAa,SAAS;GAAE,OAAO;GAAqB,OAAO;EAAG;EAAG,MAAM;EAA6B,OAAO,IAAI,EAAE,0BAA0B;EAAG,SAAS,QAAQ;EAAc,UAAS,MAAK,EAAE,UAAU;CAAE,CAAC;CACxN,QAAQ;EAAE,IAAI;EAAgB,SAAS;GAAE,OAAO;GAAqB,OAAO;EAAG;EAAG,MAAM;EAAgC,OAAO,IAAI,EAAE,6BAA6B;EAAG,SAAS,QAAQ;EAAc,UAAS,MAAK,EAAE,aAAa;CAAE,CAAC;CACpO,QAAQ;EAAE,IAAI;EAAe,SAAS;GAAE,OAAO;GAAqB,OAAO;EAAG;EAAG,MAAM;EAAoB,OAAO,IAAI,EAAE,4BAA4B;EAAG,SAAS,QAAQ;EAAc,UAAS,MAAK,EAAE,YAAY;CAAE,CAAC;CACrN,QAAQ;EAAE,IAAI;EAAe,OAAO,EAAE,IAAI,cAAc;EAAG,SAAS,EAAE,MAAM,WAAW;EAAG,MAAM;EAAwB,OAAO,IAAI,EAAE,oBAAoB;EAAG,SAAS,QAAQ;EAAc,UAAS,MAAK,EAAE,eAAe;CAAE,CAAC;AAC/N;;;;;;;;AASA,SAAgB,gBAAsC;CACpD,OAAO;EACL,IAAI;EACJ,WAAW;EACX,kBAAkB;EAClB,kBAAkB,uBAAuB;EACzC;EACA;CACF;AACF"}