@ecsplico/editor 2.1.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (692) hide show
  1. package/CHANGELOG.md +68 -1
  2. package/README.md +39 -156
  3. package/dist/adapters/comments/drizzle.d.ts +1 -1
  4. package/dist/adapters/comments/{client.js → rest-model.js} +3 -3
  5. package/dist/adapters/comments/rest-model.js.map +1 -0
  6. package/dist/adapters/comments/types.d.ts +2 -2
  7. package/dist/adapters/document-state.d.ts +23 -0
  8. package/dist/adapters/document-state.js +66 -0
  9. package/dist/adapters/document-state.js.map +1 -0
  10. package/dist/adapters/documents.js +14 -11
  11. package/dist/adapters/documents.js.map +1 -1
  12. package/dist/adapters/drizzle.d.ts +2 -2
  13. package/dist/adapters/drizzle.js +97 -88
  14. package/dist/adapters/drizzle.js.map +1 -1
  15. package/dist/adapters/forge.d.ts +12 -7
  16. package/dist/adapters/forge.js +38 -45
  17. package/dist/adapters/forge.js.map +1 -1
  18. package/dist/adapters/http.d.ts +20 -0
  19. package/dist/adapters/http.js +68 -0
  20. package/dist/adapters/http.js.map +1 -0
  21. package/dist/adapters/index.d.ts +5 -5
  22. package/dist/adapters/json.d.ts +3 -3
  23. package/dist/adapters/json.js +58 -49
  24. package/dist/adapters/json.js.map +1 -1
  25. package/dist/adapters/memory.d.ts +21 -0
  26. package/dist/adapters/memory.js +53 -0
  27. package/dist/adapters/memory.js.map +1 -0
  28. package/dist/adapters/nitro.d.ts +23 -20
  29. package/dist/adapters/nitro.js +58 -163
  30. package/dist/adapters/nitro.js.map +1 -1
  31. package/dist/adapters/react.d.ts +55 -0
  32. package/dist/adapters/react.js +209 -0
  33. package/dist/adapters/react.js.map +1 -0
  34. package/dist/adapters/shared.d.ts +15 -21
  35. package/dist/adapters/shared.js +10 -8
  36. package/dist/adapters/shared.js.map +1 -1
  37. package/dist/adapters/vue.d.ts +15 -30
  38. package/dist/adapters/vue.js +36 -87
  39. package/dist/adapters/vue.js.map +1 -1
  40. package/dist/config/index.d.ts +105 -0
  41. package/dist/config/index.js +95 -0
  42. package/dist/config/index.js.map +1 -0
  43. package/dist/core/abilities.js +1 -0
  44. package/dist/core/abilities.js.map +1 -1
  45. package/dist/{adapters/routes.js → core/api-routes.js} +5 -3
  46. package/dist/core/api-routes.js.map +1 -0
  47. package/dist/core/backend-capability.d.ts +7 -0
  48. package/dist/core/backend-capability.js +17 -0
  49. package/dist/core/backend-capability.js.map +1 -0
  50. package/dist/core/backend-types.d.ts +245 -0
  51. package/dist/core/backend-types.js +17 -0
  52. package/dist/core/backend-types.js.map +1 -0
  53. package/dist/core/backend.d.ts +108 -0
  54. package/dist/core/backend.js +14 -0
  55. package/dist/core/backend.js.map +1 -0
  56. package/dist/core/block-convert.d.ts +7 -5
  57. package/dist/core/block-convert.js +28 -5
  58. package/dist/core/block-convert.js.map +1 -1
  59. package/dist/core/command-types.d.ts +89 -0
  60. package/dist/core/commands.d.ts +40 -0
  61. package/dist/core/commands.js +151 -0
  62. package/dist/core/commands.js.map +1 -0
  63. package/dist/core/context.d.ts +17 -20
  64. package/dist/core/context.js +24 -21
  65. package/dist/core/context.js.map +1 -1
  66. package/dist/core/core-feature.d.ts +22 -7
  67. package/dist/core/core-feature.js +51 -18
  68. package/dist/core/core-feature.js.map +1 -1
  69. package/dist/core/define-editor.d.ts +4 -3
  70. package/dist/core/define-editor.js +14 -7
  71. package/dist/core/define-editor.js.map +1 -1
  72. package/dist/core/document-markdown.js +12 -3
  73. package/dist/core/document-markdown.js.map +1 -1
  74. package/dist/core/editor-ui.d.ts +8 -1
  75. package/dist/core/editor-ui.js +9 -8
  76. package/dist/core/editor-ui.js.map +1 -1
  77. package/dist/core/extension-points.d.ts +3 -15
  78. package/dist/core/feature-context.d.ts +8 -7
  79. package/dist/core/feature-context.js +12 -11
  80. package/dist/core/feature-context.js.map +1 -1
  81. package/dist/core/feature.d.ts +35 -19
  82. package/dist/core/feature.js.map +1 -1
  83. package/dist/core/fences.d.ts +2 -1
  84. package/dist/core/fences.js +3 -2
  85. package/dist/core/fences.js.map +1 -1
  86. package/dist/core/fetch-error.d.ts +1 -1
  87. package/dist/core/fetch-error.js +3 -1
  88. package/dist/core/fetch-error.js.map +1 -1
  89. package/dist/core/hash.d.ts +5 -0
  90. package/dist/core/hash.js +11 -0
  91. package/dist/core/hash.js.map +1 -0
  92. package/dist/core/http-backend.d.ts +11 -0
  93. package/dist/core/http-backend.js +195 -0
  94. package/dist/core/http-backend.js.map +1 -0
  95. package/dist/core/index.d.ts +14 -9
  96. package/dist/core/index.js +12 -9
  97. package/dist/core/palette.d.ts +48 -0
  98. package/dist/core/palette.js +95 -0
  99. package/dist/core/palette.js.map +1 -0
  100. package/dist/core/schema/abilities.d.ts +2 -1
  101. package/dist/core/schema/abilities.js +5 -1
  102. package/dist/core/schema/abilities.js.map +1 -1
  103. package/dist/core/schema/index.d.ts +11 -5
  104. package/dist/core/schema/index.js +13 -8
  105. package/dist/core/schema/index.js.map +1 -1
  106. package/dist/core/schema/mark-flags.d.ts +8 -1
  107. package/dist/core/schema/of-features.d.ts +13 -0
  108. package/dist/core/schema/of-features.js +14 -0
  109. package/dist/core/schema/of-features.js.map +1 -0
  110. package/dist/core/slash.d.ts +8 -6
  111. package/dist/core/slash.js +24 -16
  112. package/dist/core/slash.js.map +1 -1
  113. package/dist/core/surface-session.js +13 -5
  114. package/dist/core/surface-session.js.map +1 -1
  115. package/dist/core/toolbar-items.d.ts +10 -4
  116. package/dist/core/toolbar-items.js +269 -195
  117. package/dist/core/toolbar-items.js.map +1 -1
  118. package/dist/core/util.js +11 -0
  119. package/dist/core/util.js.map +1 -0
  120. package/dist/document/DocumentSurface.d.ts +1 -1
  121. package/dist/features/ai/agent-op-review.d.ts +1 -1
  122. package/dist/features/ai/agent-op-review.js +1 -1
  123. package/dist/features/ai/agent-ops.js +1 -1
  124. package/dist/features/ai/ai-apply.d.ts +2 -2
  125. package/dist/features/ai/ai-apply.js +1 -1
  126. package/dist/features/ai/ai-review.js +1 -1
  127. package/dist/features/ai/ai-sse.d.ts +6 -6
  128. package/dist/features/ai/ai-sse.js +20 -63
  129. package/dist/features/ai/ai-sse.js.map +1 -1
  130. package/dist/features/ai/assistant.d.ts +8 -7
  131. package/dist/features/ai/assistant.js +3 -3
  132. package/dist/features/ai/assistant.js.map +1 -1
  133. package/dist/features/ai/block-actions.d.ts +3 -2
  134. package/dist/features/ai/block-actions.js +3 -2
  135. package/dist/features/ai/block-actions.js.map +1 -1
  136. package/dist/features/ai/components/AiSelectionMenu.js +1 -1
  137. package/dist/features/ai/components/DocumentChatAnswer.js +1 -1
  138. package/dist/features/ai/components/DocumentChatOps.vue.d.ts +1 -1
  139. package/dist/features/ai/components/SettingsModelProfiles.js +8 -8
  140. package/dist/features/ai/components/SettingsModelProfiles.js.map +1 -1
  141. package/dist/features/ai/document-chat-model.d.ts +8 -7
  142. package/dist/features/ai/document-chat-model.js +5 -5
  143. package/dist/features/ai/document-chat-model.js.map +1 -1
  144. package/dist/features/ai/document-chat.js +1 -1
  145. package/dist/features/ai/feature.js +27 -14
  146. package/dist/features/ai/feature.js.map +1 -1
  147. package/dist/features/ai/ghost-autocomplete.d.ts +7 -6
  148. package/dist/features/ai/ghost-autocomplete.js +6 -9
  149. package/dist/features/ai/ghost-autocomplete.js.map +1 -1
  150. package/dist/features/ai/index.d.ts +4 -3
  151. package/dist/features/ai/index.js +10 -10
  152. package/dist/features/ai/model-profiles.d.ts +5 -4
  153. package/dist/features/ai/model-profiles.js +2 -2
  154. package/dist/features/ai/model-profiles.js.map +1 -1
  155. package/dist/features/ai/protocol/block-lines.js +1 -1
  156. package/dist/features/ai/protocol/block-lines.js.map +1 -1
  157. package/dist/features/ai/protocol/chat.js +4 -1
  158. package/dist/features/ai/protocol/chat.js.map +1 -1
  159. package/dist/features/ai/protocol/index.d.ts +3 -2
  160. package/dist/features/ai/protocol/models.d.ts +2 -16
  161. package/dist/features/ai/protocol/models.js.map +1 -1
  162. package/dist/features/ai/rate-limit.d.ts +1 -1
  163. package/dist/features/ai/rate-limit.js +3 -1
  164. package/dist/features/ai/rate-limit.js.map +1 -1
  165. package/dist/features/ai/react/AiSelectionMenu.js +2 -2
  166. package/dist/features/ai/react/AiSidebar.js +4 -4
  167. package/dist/features/ai/react/DocumentChatAnswer.js +1 -1
  168. package/dist/features/ai/react/DocumentChatOps.d.ts +1 -1
  169. package/dist/features/ai/react/DocumentChatOps.js +1 -1
  170. package/dist/features/ai/react/SettingsModelProfiles.js +8 -10
  171. package/dist/features/ai/react/SettingsModelProfiles.js.map +1 -1
  172. package/dist/features/ai/react/use-ai-assistant.d.ts +1 -1
  173. package/dist/features/ai/react/use-ai-assistant.js +3 -3
  174. package/dist/features/ai/react/use-ai-assistant.js.map +1 -1
  175. package/dist/features/ai/react/use-document-chat.js +2 -2
  176. package/dist/features/ai/react/use-document-chat.js.map +1 -1
  177. package/dist/features/ai/react/use-model-profiles.d.ts +2 -1
  178. package/dist/features/ai/selection-flow.d.ts +1 -1
  179. package/dist/features/ai/selection-flow.js +1 -1
  180. package/dist/features/ai/sidebar-flow.d.ts +1 -1
  181. package/dist/features/ai/sidebar-flow.js +1 -1
  182. package/dist/features/ai/use-ai-assistant.d.ts +1 -1
  183. package/dist/features/ai/use-ai-assistant.js +3 -3
  184. package/dist/features/ai/use-ai-assistant.js.map +1 -1
  185. package/dist/features/ai/use-document-chat.js +2 -2
  186. package/dist/features/ai/use-document-chat.js.map +1 -1
  187. package/dist/features/ai/use-model-profiles.d.ts +2 -1
  188. package/dist/features/authors/attribution.d.ts +1 -1
  189. package/dist/features/authors/feature.js +12 -11
  190. package/dist/features/authors/feature.js.map +1 -1
  191. package/dist/features/block-ui/block-actions.d.ts +1 -1
  192. package/dist/features/block-ui/block-actions.js +1 -1
  193. package/dist/features/block-ui/block-actions.js.map +1 -1
  194. package/dist/features/block-ui/components/BlockUi.js +1 -1
  195. package/dist/features/block-ui/feature.js +1 -0
  196. package/dist/features/block-ui/feature.js.map +1 -1
  197. package/dist/features/block-ui/react/BlockUi.js +1 -1
  198. package/dist/features/collab/anchor-resolver.js +1 -1
  199. package/dist/features/collab/feature.js +2 -0
  200. package/dist/features/collab/feature.js.map +1 -1
  201. package/dist/features/comments/components/CommentThreadView.vue.d.ts +2 -1
  202. package/dist/features/comments/feature.js +12 -11
  203. package/dist/features/comments/feature.js.map +1 -1
  204. package/dist/features/comments/index.d.ts +3 -2
  205. package/dist/features/comments/index.js +1 -1
  206. package/dist/features/comments/margin-layout.d.ts +3 -2
  207. package/dist/features/comments/model.d.ts +3 -67
  208. package/dist/features/comments/model.js +2 -2
  209. package/dist/features/comments/model.js.map +1 -1
  210. package/dist/features/comments/react/CommentThreadView.d.ts +3 -2
  211. package/dist/features/comments/react/use-comments.d.ts +2 -1
  212. package/dist/features/comments/react.d.ts +1 -1
  213. package/dist/features/comments/schema.d.ts +2 -52
  214. package/dist/features/comments/schema.js.map +1 -1
  215. package/dist/features/comments/snapshot-equality.js.map +1 -1
  216. package/dist/features/comments/use-comments.d.ts +3 -2
  217. package/dist/features/comments/vue.d.ts +1 -1
  218. package/dist/features/composites/accepted-children.d.ts +1 -0
  219. package/dist/features/composites/accepted-children.js +16 -1
  220. package/dist/features/composites/accepted-children.js.map +1 -1
  221. package/dist/features/composites/ai-brief.js +31 -0
  222. package/dist/features/composites/ai-brief.js.map +1 -1
  223. package/dist/features/composites/bibliography-command.d.ts +11 -0
  224. package/dist/features/composites/bibliography-form.js +90 -0
  225. package/dist/features/composites/bibliography-form.js.map +1 -0
  226. package/dist/features/composites/bibliography.d.ts +33 -0
  227. package/dist/features/composites/bibliography.js +120 -0
  228. package/dist/features/composites/bibliography.js.map +1 -0
  229. package/dist/features/composites/components/BibliographyEditor.js +261 -0
  230. package/dist/features/composites/components/BibliographyEditor.js.map +1 -0
  231. package/dist/features/composites/components/CompositeChrome.js +75 -26
  232. package/dist/features/composites/components/CompositeChrome.js.map +1 -1
  233. package/dist/features/composites/components/CompositeDetails.js +46 -11
  234. package/dist/features/composites/components/CompositeDetails.js.map +1 -1
  235. package/dist/features/composites/components/CompositeDetails.vue.d.ts +2 -1
  236. package/dist/features/composites/components/CompositeFieldEditor.js +37 -4
  237. package/dist/features/composites/components/CompositeFieldEditor.js.map +1 -1
  238. package/dist/features/composites/components/CompositeInspector.js +17 -5
  239. package/dist/features/composites/components/CompositeInspector.js.map +1 -1
  240. package/dist/features/composites/components/CompositeTable.js +13 -4
  241. package/dist/features/composites/components/CompositeTable.js.map +1 -1
  242. package/dist/features/composites/components/CompositeTagsEditor.js +1 -1
  243. package/dist/features/composites/components/CompositeView.js +11 -1
  244. package/dist/features/composites/components/CompositeView.js.map +1 -1
  245. package/dist/features/composites/components/DerivationBadge.js +103 -0
  246. package/dist/features/composites/components/DerivationBadge.js.map +1 -0
  247. package/dist/features/composites/components/ReferenceFieldSelect.js +60 -0
  248. package/dist/features/composites/components/ReferenceFieldSelect.js.map +1 -0
  249. package/dist/features/composites/components/ReferenceView.js +122 -0
  250. package/dist/features/composites/components/ReferenceView.js.map +1 -0
  251. package/dist/features/composites/components/ReferenceView.vue.d.ts +96 -0
  252. package/dist/features/composites/components/SettingsEditingTab.js +1 -1
  253. package/dist/features/composites/convert.js +2 -2
  254. package/dist/features/composites/convert.js.map +1 -1
  255. package/dist/features/composites/derivation.d.ts +61 -0
  256. package/dist/features/composites/derivation.js +98 -0
  257. package/dist/features/composites/derivation.js.map +1 -0
  258. package/dist/features/composites/derived-chrome.js +69 -0
  259. package/dist/features/composites/derived-chrome.js.map +1 -0
  260. package/dist/features/composites/feature.js +159 -109
  261. package/dist/features/composites/feature.js.map +1 -1
  262. package/dist/features/composites/fences.d.ts +4 -3
  263. package/dist/features/composites/fences.js +51 -7
  264. package/dist/features/composites/fences.js.map +1 -1
  265. package/dist/features/composites/index.d.ts +12 -3
  266. package/dist/features/composites/index.js +15 -6
  267. package/dist/features/composites/inspector-model.d.ts +4 -1
  268. package/dist/features/composites/inspector-model.js +8 -4
  269. package/dist/features/composites/inspector-model.js.map +1 -1
  270. package/dist/features/composites/kinds.d.ts +8 -1
  271. package/dist/features/composites/kinds.js +145 -6
  272. package/dist/features/composites/kinds.js.map +1 -1
  273. package/dist/features/composites/legacy.d.ts +4 -1
  274. package/dist/features/composites/legacy.js +56 -1
  275. package/dist/features/composites/legacy.js.map +1 -1
  276. package/dist/features/composites/meta-display.js +40 -1
  277. package/dist/features/composites/meta-display.js.map +1 -1
  278. package/dist/features/composites/meta-keys.d.ts +7 -0
  279. package/dist/features/composites/meta-keys.js +21 -0
  280. package/dist/features/composites/meta-keys.js.map +1 -0
  281. package/dist/features/composites/node-views.d.ts +6 -3
  282. package/dist/features/composites/node-views.js +7 -3
  283. package/dist/features/composites/node-views.js.map +1 -1
  284. package/dist/features/composites/nodes.d.ts +6 -1
  285. package/dist/features/composites/nodes.js +33 -7
  286. package/dist/features/composites/nodes.js.map +1 -1
  287. package/dist/features/composites/react/BibliographyEditor.js +229 -0
  288. package/dist/features/composites/react/BibliographyEditor.js.map +1 -0
  289. package/dist/features/composites/react/CompositeChrome.js +65 -17
  290. package/dist/features/composites/react/CompositeChrome.js.map +1 -1
  291. package/dist/features/composites/react/CompositeDetails.d.ts +2 -1
  292. package/dist/features/composites/react/CompositeDetails.js +45 -6
  293. package/dist/features/composites/react/CompositeDetails.js.map +1 -1
  294. package/dist/features/composites/react/CompositeFieldEditor.d.ts +1 -1
  295. package/dist/features/composites/react/CompositeFieldEditor.js +24 -1
  296. package/dist/features/composites/react/CompositeFieldEditor.js.map +1 -1
  297. package/dist/features/composites/react/CompositeInspector.js +11 -5
  298. package/dist/features/composites/react/CompositeInspector.js.map +1 -1
  299. package/dist/features/composites/react/CompositeStatusMenu.js +1 -1
  300. package/dist/features/composites/react/CompositeSummaryEditor.js +1 -1
  301. package/dist/features/composites/react/CompositeTable.js +16 -2
  302. package/dist/features/composites/react/CompositeTable.js.map +1 -1
  303. package/dist/features/composites/react/CompositeTagsEditor.js +2 -2
  304. package/dist/features/composites/react/CompositeView.js +6 -1
  305. package/dist/features/composites/react/CompositeView.js.map +1 -1
  306. package/dist/features/composites/react/DerivationBadge.js +116 -0
  307. package/dist/features/composites/react/DerivationBadge.js.map +1 -0
  308. package/dist/features/composites/react/ReferenceFieldSelect.js +52 -0
  309. package/dist/features/composites/react/ReferenceFieldSelect.js.map +1 -0
  310. package/dist/features/composites/react/ReferenceView.d.ts +11 -0
  311. package/dist/features/composites/react/ReferenceView.js +115 -0
  312. package/dist/features/composites/react/ReferenceView.js.map +1 -0
  313. package/dist/features/composites/react/SettingsEditingTab.js +2 -2
  314. package/dist/features/composites/react.d.ts +2 -1
  315. package/dist/features/composites/react.js +7 -3
  316. package/dist/features/composites/react.js.map +1 -1
  317. package/dist/features/composites/reference-ai.js +16 -0
  318. package/dist/features/composites/reference-ai.js.map +1 -0
  319. package/dist/features/composites/reference-label.d.ts +19 -0
  320. package/dist/features/composites/reference-label.js +58 -0
  321. package/dist/features/composites/reference-label.js.map +1 -0
  322. package/dist/features/composites/reference-suggestion.d.ts +10 -0
  323. package/dist/features/composites/reference-suggestion.js +41 -0
  324. package/dist/features/composites/reference-suggestion.js.map +1 -0
  325. package/dist/features/composites/reference-text.d.ts +18 -0
  326. package/dist/features/composites/reference-text.js +89 -0
  327. package/dist/features/composites/reference-text.js.map +1 -0
  328. package/dist/features/composites/reference.d.ts +44 -0
  329. package/dist/features/composites/reference.js +148 -0
  330. package/dist/features/composites/reference.js.map +1 -0
  331. package/dist/features/composites/reveal-source.d.ts +32 -0
  332. package/dist/features/composites/reveal-source.js +89 -0
  333. package/dist/features/composites/reveal-source.js.map +1 -0
  334. package/dist/features/composites/rows.d.ts +21 -2
  335. package/dist/features/composites/rows.js +63 -9
  336. package/dist/features/composites/rows.js.map +1 -1
  337. package/dist/features/composites/schema.d.ts +9 -3
  338. package/dist/features/composites/schema.js +11 -4
  339. package/dist/features/composites/schema.js.map +1 -1
  340. package/dist/features/composites/table-model.js +12 -21
  341. package/dist/features/composites/table-model.js.map +1 -1
  342. package/dist/features/composites/vue.d.ts +3 -2
  343. package/dist/features/composites/vue.js +8 -4
  344. package/dist/features/composites/vue.js.map +1 -1
  345. package/dist/features/media/assets.d.ts +2 -0
  346. package/dist/features/media/assets.js +3 -2
  347. package/dist/features/media/assets.js.map +1 -1
  348. package/dist/features/media/components/FileView.js +13 -4
  349. package/dist/features/media/components/FileView.js.map +1 -1
  350. package/dist/features/media/feature.d.ts +3 -3
  351. package/dist/features/media/feature.js +21 -28
  352. package/dist/features/media/feature.js.map +1 -1
  353. package/dist/features/media/file-import.js +2 -2
  354. package/dist/features/media/file-import.js.map +1 -1
  355. package/dist/features/media/index.d.ts +2 -2
  356. package/dist/features/media/index.js +2 -2
  357. package/dist/features/media/react/FileView.js +19 -2
  358. package/dist/features/media/react/FileView.js.map +1 -1
  359. package/dist/features/media/schema.d.ts +8 -0
  360. package/dist/features/media/schema.js +126 -11
  361. package/dist/features/media/schema.js.map +1 -1
  362. package/dist/features/media/upload.d.ts +16 -14
  363. package/dist/features/media/upload.js +13 -19
  364. package/dist/features/media/upload.js.map +1 -1
  365. package/dist/features/mentions/index.d.ts +4 -3
  366. package/dist/features/mentions/index.js +4 -1
  367. package/dist/features/mentions/index.js.map +1 -1
  368. package/dist/features/mentions/mention-text.d.ts +1 -1
  369. package/dist/features/mentions/mention-text.js.map +1 -1
  370. package/dist/features/mentions/mention.d.ts +0 -6
  371. package/dist/features/mentions/mention.js.map +1 -1
  372. package/dist/features/mentions/metadata-defaults.d.ts +2 -2
  373. package/dist/features/mentions/metadata-defaults.js +3 -9
  374. package/dist/features/mentions/metadata-defaults.js.map +1 -1
  375. package/dist/features/mentions/schema.d.ts +2 -1
  376. package/dist/features/mentions/schema.js.map +1 -1
  377. package/dist/features/tables/feature.d.ts +2 -1
  378. package/dist/features/tables/feature.js +90 -70
  379. package/dist/features/tables/feature.js.map +1 -1
  380. package/dist/features/themes/components/SettingsAppearanceTab.js +6 -9
  381. package/dist/features/themes/components/SettingsAppearanceTab.js.map +1 -1
  382. package/dist/features/themes/feature.js +2 -0
  383. package/dist/features/themes/feature.js.map +1 -1
  384. package/dist/features/themes/index.d.ts +2 -1
  385. package/dist/features/themes/react/SettingsAppearanceTab.js +7 -10
  386. package/dist/features/themes/react/SettingsAppearanceTab.js.map +1 -1
  387. package/dist/features/themes/schema.d.ts +2 -6
  388. package/dist/features/themes/schema.js.map +1 -1
  389. package/dist/features/themes/theme-runtime.d.ts +1 -1
  390. package/dist/features/themes/theme-runtime.js +4 -2
  391. package/dist/features/themes/theme-runtime.js.map +1 -1
  392. package/dist/features/transcript/TranscriptSegmentView.js +48 -28
  393. package/dist/features/transcript/TranscriptSegmentView.js.map +1 -1
  394. package/dist/features/transcript/feature.js +21 -19
  395. package/dist/features/transcript/feature.js.map +1 -1
  396. package/dist/features/transcript/react/TranscriptSegmentView.js +55 -36
  397. package/dist/features/transcript/react/TranscriptSegmentView.js.map +1 -1
  398. package/dist/features/transcript/segment-node.d.ts +2 -0
  399. package/dist/features/transcript/segment-node.js +35 -7
  400. package/dist/features/transcript/segment-node.js.map +1 -1
  401. package/dist/i18n/de/composites.js +91 -1
  402. package/dist/i18n/de/composites.js.map +1 -1
  403. package/dist/i18n/de/integrations.js +49 -8
  404. package/dist/i18n/de/integrations.js.map +1 -1
  405. package/dist/i18n/de/media.js +0 -1
  406. package/dist/i18n/de/media.js.map +1 -1
  407. package/dist/i18n/de/palette.js +22 -0
  408. package/dist/i18n/de/palette.js.map +1 -0
  409. package/dist/i18n/de/tables.js +0 -1
  410. package/dist/i18n/de/tables.js.map +1 -1
  411. package/dist/i18n/de/transcript.js +2 -1
  412. package/dist/i18n/de/transcript.js.map +1 -1
  413. package/dist/i18n/de/tree.js +3 -0
  414. package/dist/i18n/de/tree.js.map +1 -1
  415. package/dist/i18n/de.d.ts +157 -11
  416. package/dist/i18n/de.js +3 -1
  417. package/dist/i18n/de.js.map +1 -1
  418. package/dist/i18n/en/composites.js +89 -1
  419. package/dist/i18n/en/composites.js.map +1 -1
  420. package/dist/i18n/en/integrations.js +49 -8
  421. package/dist/i18n/en/integrations.js.map +1 -1
  422. package/dist/i18n/en/media.js +0 -1
  423. package/dist/i18n/en/media.js.map +1 -1
  424. package/dist/i18n/en/palette.js +22 -0
  425. package/dist/i18n/en/palette.js.map +1 -0
  426. package/dist/i18n/en/tables.js +0 -1
  427. package/dist/i18n/en/tables.js.map +1 -1
  428. package/dist/i18n/en/transcript.js +2 -1
  429. package/dist/i18n/en/transcript.js.map +1 -1
  430. package/dist/i18n/en/tree.js +3 -0
  431. package/dist/i18n/en/tree.js.map +1 -1
  432. package/dist/i18n/en.js +3 -1
  433. package/dist/i18n/en.js.map +1 -1
  434. package/dist/index.d.ts +4 -3
  435. package/dist/integrations/composite-ai/bibliography-fetch.d.ts +31 -0
  436. package/dist/integrations/composite-ai/bibliography-fetch.js +159 -0
  437. package/dist/integrations/composite-ai/bibliography-fetch.js.map +1 -0
  438. package/dist/integrations/composite-ai/composite-fill.d.ts +30 -8
  439. package/dist/integrations/composite-ai/composite-fill.js +97 -56
  440. package/dist/integrations/composite-ai/composite-fill.js.map +1 -1
  441. package/dist/integrations/composite-ai/composite-summary.d.ts +4 -12
  442. package/dist/integrations/composite-ai/composite-summary.js +7 -26
  443. package/dist/integrations/composite-ai/composite-summary.js.map +1 -1
  444. package/dist/integrations/composite-ai/derive.d.ts +29 -0
  445. package/dist/integrations/composite-ai/derive.js +173 -0
  446. package/dist/integrations/composite-ai/derive.js.map +1 -0
  447. package/dist/integrations/composite-ai/index.d.ts +11 -7
  448. package/dist/integrations/composite-ai/index.js +72 -14
  449. package/dist/integrations/composite-ai/index.js.map +1 -1
  450. package/dist/integrations/composite-ai/rendition.d.ts +45 -0
  451. package/dist/integrations/composite-ai/rendition.js +314 -0
  452. package/dist/integrations/composite-ai/rendition.js.map +1 -0
  453. package/dist/integrations/composite-media/index.d.ts +7 -5
  454. package/dist/integrations/composite-media/index.js +86 -13
  455. package/dist/integrations/composite-media/index.js.map +1 -1
  456. package/dist/integrations/transcript-ai/index.d.ts +1 -1
  457. package/dist/integrations/transcript-ai/index.js +5 -2
  458. package/dist/integrations/transcript-ai/index.js.map +1 -1
  459. package/dist/integrations/transcript-ai/protocol.d.ts +2 -12
  460. package/dist/integrations/transcript-ai/protocol.js +0 -2
  461. package/dist/integrations/transcript-ai/protocol.js.map +1 -1
  462. package/dist/integrations/transcript-ai/transcript-cleanup.d.ts +5 -5
  463. package/dist/integrations/transcript-ai/transcript-cleanup.js +7 -10
  464. package/dist/integrations/transcript-ai/transcript-cleanup.js.map +1 -1
  465. package/dist/markdown/MarkdownSurface.vue.d.ts +6 -5
  466. package/dist/markdown/MarkdownSurface2.js +3 -6
  467. package/dist/markdown/MarkdownSurface2.js.map +1 -1
  468. package/dist/markdown/document.js +1 -1
  469. package/dist/markdown/source-mode.d.ts +1 -1
  470. package/dist/nuxt/module.d.ts +1402 -54
  471. package/dist/nuxt/module.js +6 -49
  472. package/dist/nuxt/module.js.map +1 -1
  473. package/dist/nuxt/runtime/install-context.d.ts +7 -3
  474. package/dist/nuxt/runtime/install-context.js +14 -8
  475. package/dist/nuxt/runtime/install-context.js.map +1 -1
  476. package/dist/nuxt/runtime/plugins/editor-context-nuxt-ui.client.ts +2 -2
  477. package/dist/nuxt/runtime/server/plugins/editor-server.js +20 -12
  478. package/dist/nuxt/runtime/server/plugins/editor-server.js.map +1 -1
  479. package/dist/presets/compose.d.ts +94 -0
  480. package/dist/presets/compose.js +164 -0
  481. package/dist/presets/compose.js.map +1 -0
  482. package/dist/react/AdvancedEditor.d.ts +15 -15
  483. package/dist/react/AdvancedEditor.js +15 -13
  484. package/dist/react/AdvancedEditor.js.map +1 -1
  485. package/dist/react/EditorCommandPalette.d.ts +13 -0
  486. package/dist/react/EditorCommandPalette.js +118 -0
  487. package/dist/react/EditorCommandPalette.js.map +1 -0
  488. package/dist/react/EditorSettingsModal.d.ts +5 -5
  489. package/dist/react/EditorSettingsModal.js +7 -4
  490. package/dist/react/EditorSettingsModal.js.map +1 -1
  491. package/dist/react/EditorSettingsPanel.d.ts +7 -7
  492. package/dist/react/EditorSettingsPanel.js +8 -5
  493. package/dist/react/EditorSettingsPanel.js.map +1 -1
  494. package/dist/react/EditorSurface.d.ts +7 -7
  495. package/dist/react/EditorSurface.js +10 -6
  496. package/dist/react/EditorSurface.js.map +1 -1
  497. package/dist/react/EditorToolbar.d.ts +4 -6
  498. package/dist/react/EditorToolbar.js +29 -37
  499. package/dist/react/EditorToolbar.js.map +1 -1
  500. package/dist/react/SimpleEditor.d.ts +22 -23
  501. package/dist/react/SimpleEditor.js +21 -7
  502. package/dist/react/SimpleEditor.js.map +1 -1
  503. package/dist/react/advanced.d.ts +4 -3
  504. package/dist/react/advanced.js +2 -2
  505. package/dist/react/compose.d.ts +20 -0
  506. package/dist/react/compose.js +49 -0
  507. package/dist/react/compose.js.map +1 -0
  508. package/dist/react/composed-surface.d.ts +39 -0
  509. package/dist/react/composed-surface.js +71 -0
  510. package/dist/react/composed-surface.js.map +1 -0
  511. package/dist/react/context.js +6 -2
  512. package/dist/react/context.js.map +1 -1
  513. package/dist/react/index.d.ts +2 -1
  514. package/dist/react/index.js +2 -1
  515. package/dist/react/key-labels.js +15 -0
  516. package/dist/react/key-labels.js.map +1 -0
  517. package/dist/react/settings.d.ts +1 -1
  518. package/dist/react/simple.d.ts +2 -2
  519. package/dist/react/ui/command.js +36 -1
  520. package/dist/react/ui/command.js.map +1 -1
  521. package/dist/schema/advanced.d.ts +6 -6
  522. package/dist/schema/advanced.js +26 -29
  523. package/dist/schema/advanced.js.map +1 -1
  524. package/dist/server/ai.d.ts +5 -16
  525. package/dist/server/ai.js.map +1 -1
  526. package/dist/server/auth.d.ts +9 -0
  527. package/dist/server/collab-state.d.ts +1 -1
  528. package/dist/server/collab-state.js.map +1 -1
  529. package/dist/server/collab.d.ts +13 -13
  530. package/dist/server/collab.js +34 -18
  531. package/dist/server/collab.js.map +1 -1
  532. package/dist/server/crossref.js +78 -0
  533. package/dist/server/crossref.js.map +1 -0
  534. package/dist/server/errors.d.ts +1 -1
  535. package/dist/server/errors.js +1 -1
  536. package/dist/server/errors.js.map +1 -1
  537. package/dist/server/extract.js +308 -0
  538. package/dist/server/extract.js.map +1 -0
  539. package/dist/{nuxt/runtime/server/utils/editor-route.js → server/h3.js} +8 -16
  540. package/dist/server/h3.js.map +1 -0
  541. package/dist/server/handlers/ai.d.ts +30 -9
  542. package/dist/server/handlers/ai.js +170 -36
  543. package/dist/server/handlers/ai.js.map +1 -1
  544. package/dist/server/handlers/context.d.ts +12 -5
  545. package/dist/server/handlers/context.js +10 -4
  546. package/dist/server/handlers/context.js.map +1 -1
  547. package/dist/server/handlers/editor.d.ts +19 -13
  548. package/dist/server/handlers/editor.js +49 -38
  549. package/dist/server/handlers/editor.js.map +1 -1
  550. package/dist/server/handlers/index.d.ts +4 -4
  551. package/dist/server/handlers/index.js +4 -4
  552. package/dist/server/host.d.ts +16 -25
  553. package/dist/server/host.js +58 -41
  554. package/dist/server/host.js.map +1 -1
  555. package/dist/server/index.d.ts +6 -4
  556. package/dist/server/index.js +3 -2
  557. package/dist/server/pdf.js +97 -0
  558. package/dist/server/pdf.js.map +1 -0
  559. package/dist/server/{adapter.d.ts → ports.d.ts} +81 -30
  560. package/dist/server/ports.js +29 -0
  561. package/dist/server/ports.js.map +1 -0
  562. package/dist/server/routes.js +144 -0
  563. package/dist/server/routes.js.map +1 -0
  564. package/dist/settings/index.d.ts +1 -1
  565. package/dist/settings/index.js.map +1 -1
  566. package/dist/styles/composites.css +25 -0
  567. package/dist/tree/DocumentTree.js +56 -29
  568. package/dist/tree/DocumentTree.js.map +1 -1
  569. package/dist/tree/react/DocumentTree.js +23 -0
  570. package/dist/tree/react/DocumentTree.js.map +1 -1
  571. package/dist/tree/tree-host.js +2 -2
  572. package/dist/tree/tree-items.js +1 -1
  573. package/dist/vue/AdvancedEditor.js +30 -9
  574. package/dist/vue/AdvancedEditor.js.map +1 -1
  575. package/dist/vue/AdvancedEditor.vue.d.ts +28 -8
  576. package/dist/vue/SimpleEditor.js +62 -16
  577. package/dist/vue/SimpleEditor.js.map +1 -1
  578. package/dist/vue/SimpleEditor.vue.d.ts +37 -7
  579. package/dist/vue/advanced.d.ts +3 -2
  580. package/dist/vue/advanced.js +2 -2
  581. package/dist/vue/components/EditorCommandPalette.js +91 -0
  582. package/dist/vue/components/EditorCommandPalette.js.map +1 -0
  583. package/dist/vue/components/EditorCommandPalette.vue.d.ts +15 -0
  584. package/dist/vue/components/EditorSettingsModal.js +10 -6
  585. package/dist/vue/components/EditorSettingsModal.js.map +1 -1
  586. package/dist/vue/components/EditorSettingsModal.vue.d.ts +4 -4
  587. package/dist/vue/components/EditorSettingsPanel.js +10 -6
  588. package/dist/vue/components/EditorSettingsPanel.js.map +1 -1
  589. package/dist/vue/components/EditorSettingsPanel.vue.d.ts +6 -6
  590. package/dist/vue/components/EditorSurface.js +11 -6
  591. package/dist/vue/components/EditorSurface.js.map +1 -1
  592. package/dist/vue/components/EditorSurface.vue.d.ts +7 -7
  593. package/dist/vue/components/EditorToolbar.js +41 -49
  594. package/dist/vue/components/EditorToolbar.js.map +1 -1
  595. package/dist/vue/components/EditorToolbar.vue.d.ts +2 -4
  596. package/dist/vue/compose.d.ts +17 -0
  597. package/dist/vue/compose.js +51 -0
  598. package/dist/vue/compose.js.map +1 -0
  599. package/dist/vue/context-key.d.ts +6 -0
  600. package/dist/vue/context-key.js +6 -0
  601. package/dist/vue/context-key.js.map +1 -0
  602. package/dist/vue/context.d.ts +8 -6
  603. package/dist/vue/context.js +6 -5
  604. package/dist/vue/context.js.map +1 -1
  605. package/dist/vue/index.d.ts +10 -8
  606. package/dist/vue/index.js +10 -8
  607. package/dist/vue/kit/index.d.ts +2 -2
  608. package/dist/vue/kit/nuxt-ui.js +23 -0
  609. package/dist/vue/kit/nuxt-ui.js.map +1 -1
  610. package/dist/vue/kit/types.d.ts +40 -1
  611. package/package.json +30 -16
  612. package/dist/adapters/comments/client.d.ts +0 -64
  613. package/dist/adapters/comments/client.js.map +0 -1
  614. package/dist/adapters/routes.js.map +0 -1
  615. package/dist/core/toolbar.d.ts +0 -74
  616. package/dist/core/toolbar.js +0 -45
  617. package/dist/core/toolbar.js.map +0 -1
  618. package/dist/integrations/composite-ai/document-transcribe.d.ts +0 -14
  619. package/dist/integrations/composite-ai/document-transcribe.js +0 -89
  620. package/dist/integrations/composite-ai/document-transcribe.js.map +0 -1
  621. package/dist/nuxt/runtime/server/api/ai/chat.post.d.ts +0 -5
  622. package/dist/nuxt/runtime/server/api/ai/chat.post.js +0 -8
  623. package/dist/nuxt/runtime/server/api/ai/chat.post.js.map +0 -1
  624. package/dist/nuxt/runtime/server/api/ai/complete.post.d.ts +0 -5
  625. package/dist/nuxt/runtime/server/api/ai/complete.post.js +0 -8
  626. package/dist/nuxt/runtime/server/api/ai/complete.post.js.map +0 -1
  627. package/dist/nuxt/runtime/server/api/ai/generate.post.d.ts +0 -5
  628. package/dist/nuxt/runtime/server/api/ai/generate.post.js +0 -8
  629. package/dist/nuxt/runtime/server/api/ai/generate.post.js.map +0 -1
  630. package/dist/nuxt/runtime/server/api/ai/models.get.d.ts +0 -5
  631. package/dist/nuxt/runtime/server/api/ai/models.get.js +0 -8
  632. package/dist/nuxt/runtime/server/api/ai/models.get.js.map +0 -1
  633. package/dist/nuxt/runtime/server/api/ai/transcribe.post.d.ts +0 -5
  634. package/dist/nuxt/runtime/server/api/ai/transcribe.post.js +0 -8
  635. package/dist/nuxt/runtime/server/api/ai/transcribe.post.js.map +0 -1
  636. package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.d.ts +0 -5
  637. package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.js +0 -8
  638. package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.js.map +0 -1
  639. package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.d.ts +0 -5
  640. package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.js +0 -8
  641. package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.js.map +0 -1
  642. package/dist/nuxt/runtime/server/api/editor/assets/[id].post.d.ts +0 -5
  643. package/dist/nuxt/runtime/server/api/editor/assets/[id].post.js +0 -8
  644. package/dist/nuxt/runtime/server/api/editor/assets/[id].post.js.map +0 -1
  645. package/dist/nuxt/runtime/server/api/editor/settings.get.d.ts +0 -5
  646. package/dist/nuxt/runtime/server/api/editor/settings.get.js +0 -8
  647. package/dist/nuxt/runtime/server/api/editor/settings.get.js.map +0 -1
  648. package/dist/nuxt/runtime/server/api/editor/settings.put.d.ts +0 -5
  649. package/dist/nuxt/runtime/server/api/editor/settings.put.js +0 -8
  650. package/dist/nuxt/runtime/server/api/editor/settings.put.js.map +0 -1
  651. package/dist/nuxt/runtime/server/api/editor/tags.get.d.ts +0 -5
  652. package/dist/nuxt/runtime/server/api/editor/tags.get.js +0 -8
  653. package/dist/nuxt/runtime/server/api/editor/tags.get.js.map +0 -1
  654. package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.d.ts +0 -5
  655. package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.js +0 -8
  656. package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.js.map +0 -1
  657. package/dist/nuxt/runtime/server/api/editor/themes/[id].get.d.ts +0 -5
  658. package/dist/nuxt/runtime/server/api/editor/themes/[id].get.js +0 -8
  659. package/dist/nuxt/runtime/server/api/editor/themes/[id].get.js.map +0 -1
  660. package/dist/nuxt/runtime/server/api/editor/themes/index.get.d.ts +0 -5
  661. package/dist/nuxt/runtime/server/api/editor/themes/index.get.js +0 -8
  662. package/dist/nuxt/runtime/server/api/editor/themes/index.get.js.map +0 -1
  663. package/dist/nuxt/runtime/server/api/editor/themes/index.post.d.ts +0 -5
  664. package/dist/nuxt/runtime/server/api/editor/themes/index.post.js +0 -8
  665. package/dist/nuxt/runtime/server/api/editor/themes/index.post.js.map +0 -1
  666. package/dist/nuxt/runtime/server/api/editor/users.get.d.ts +0 -5
  667. package/dist/nuxt/runtime/server/api/editor/users.get.js +0 -8
  668. package/dist/nuxt/runtime/server/api/editor/users.get.js.map +0 -1
  669. package/dist/nuxt/runtime/server/plugins/collab.d.ts +0 -5
  670. package/dist/nuxt/runtime/server/plugins/collab.js +0 -10
  671. package/dist/nuxt/runtime/server/plugins/collab.js.map +0 -1
  672. package/dist/nuxt/runtime/server/routes/collab/[id].d.ts +0 -5
  673. package/dist/nuxt/runtime/server/routes/collab/[id].js +0 -35
  674. package/dist/nuxt/runtime/server/routes/collab/[id].js.map +0 -1
  675. package/dist/nuxt/runtime/server/utils/editor-route.d.ts +0 -11
  676. package/dist/nuxt/runtime/server/utils/editor-route.js.map +0 -1
  677. package/dist/presets/advanced.d.ts +0 -33
  678. package/dist/presets/advanced.js +0 -50
  679. package/dist/presets/advanced.js.map +0 -1
  680. package/dist/presets/simple.d.ts +0 -9
  681. package/dist/presets/simple.js +0 -12
  682. package/dist/presets/simple.js.map +0 -1
  683. package/dist/react/advanced-preset.d.ts +0 -11
  684. package/dist/react/advanced-preset.js +0 -31
  685. package/dist/react/advanced-preset.js.map +0 -1
  686. package/dist/vue/advanced-preset.d.ts +0 -13
  687. package/dist/vue/advanced-preset.js +0 -33
  688. package/dist/vue/advanced-preset.js.map +0 -1
  689. package/docs/extending.md +0 -538
  690. package/docs/integration.md +0 -632
  691. package/docs/llms.md +0 -383
  692. package/docs/usage.md +0 -1076
@@ -1,17 +1,25 @@
1
1
  import { ABILITY } from "../../core/schema/abilities.js";
2
2
  import { abilitiesAtSelection } from "../../core/abilities.js";
3
3
  import { settingsTabsOf } from "../../core/define-editor.js";
4
- import { downloadText } from "../../core/download.js";
5
4
  import { editorEntryOf } from "../../core/editor-ui.js";
5
+ import { findBlockById } from "../../core/schema/block-ids.js";
6
+ import { downloadText } from "../../core/download.js";
6
7
  import { compositeKind, defaultCompositeKinds } from "./kinds.js";
7
8
  import { blocksFromMarkdown } from "./fences.js";
9
+ import { bodyMarkdown, derivationOf } from "./derivation.js";
8
10
  import { structureBlocks } from "./heading-composites.js";
9
11
  import { CompositeDescriptionNode, CompositeTitleNode, compositeKindsOf } from "./nodes.js";
12
+ import { bibOf, bibtexOf, cslOf } from "./bibliography.js";
10
13
  import { compositeConversions } from "./convert.js";
11
14
  import { migrateLegacyContent } from "./legacy.js";
12
- import { AcceptedChildren } from "./accepted-children.js";
15
+ import { compositeIdsOf, normalizeReferences } from "./reference-text.js";
16
+ import { compositeSchemaExtensions } from "./schema.js";
17
+ import { AcceptedChildren, compositeInsertGuard } from "./accepted-children.js";
13
18
  import { documentCompositeMarkdown, markdownFileName } from "./markdown-export.js";
14
19
  import { compositeNodes } from "./node-views.js";
20
+ import { REFERENCE_AI_BLOCK } from "./reference-ai.js";
21
+ import { referenceSuggestion } from "./reference-suggestion.js";
22
+ import { SourceReveal } from "./reveal-source.js";
15
23
  import { Structure, structureOf } from "./structure.js";
16
24
  import { STRUCTURE_MODE_KEYS } from "./structure-mode.js";
17
25
  //#region src/features/composites/feature.ts
@@ -28,9 +36,11 @@ const STRUCTURE_STAGE_LEVEL = 2;
28
36
  */
29
37
  function compositeFeatureCore(ui, options = {}) {
30
38
  const kindsOf = (ctx) => options.kinds ?? defaultCompositeKinds(ctx.t);
31
- const { Composite, CompositeTags } = compositeNodes(ui.nodeViews);
39
+ const { Composite, CompositeTags, Reference } = compositeNodes(ui.nodeViews);
32
40
  return {
33
41
  id: "composites",
42
+ dimension: "content",
43
+ schemaExtensions: () => compositeSchemaExtensions(options.kinds ? { kinds: options.kinds } : {}),
34
44
  extensions: (ctx) => [
35
45
  Composite.configure({ kinds: kindsOf(ctx) }),
36
46
  CompositeTitleNode,
@@ -40,14 +50,13 @@ function compositeFeatureCore(ui, options = {}) {
40
50
  AcceptedChildren.configure({
41
51
  notify: ctx.notify,
42
52
  t: ctx.t
43
- })
53
+ }),
54
+ SourceReveal,
55
+ Reference.configure({ suggestion: referenceSuggestion(ctx.t) })
44
56
  ],
45
- toolbar: (ctx) => [{
46
- id: "composites",
47
- order: 60,
48
- items: compositeToolbarItems(ctx, kindsOf(ctx))
49
- }],
50
- slashCommands: (ctx) => compositeSlashCommands(ctx, kindsOf(ctx)),
57
+ toolbarGroups: COMPOSITE_TOOLBAR_GROUPS,
58
+ commands: (ctx) => compositeCommands(ctx, kindsOf(ctx)),
59
+ insertGuards: () => [compositeInsertGuard],
51
60
  blockActions: (ctx) => [{
52
61
  id: "document-export",
53
62
  label: ctx.t("composites.blockAction.export"),
@@ -56,6 +65,14 @@ function compositeFeatureCore(ui, options = {}) {
56
65
  order: 400,
57
66
  isVisible: ({ node }) => node.attrs.kind === "document",
58
67
  run: ({ editor, node }) => downloadText(markdownFileName(node), documentCompositeMarkdown(editor, node))
68
+ }, {
69
+ id: "bibliography-export",
70
+ label: ctx.t("composites.blockAction.bibtex"),
71
+ icon: "i-lucide-book-marked",
72
+ ability: ABILITY.compositeExport,
73
+ order: 410,
74
+ isVisible: ({ node }) => bibOf(node) !== null,
75
+ run: ({ node }) => downloadText(`${markdownFileName(node).replace(/\.md$/, "")}.bib`, bibtexOf(cslOf(node)), "text/x-bibtex;charset=utf-8")
59
76
  }],
60
77
  overlays: [ui.chrome],
61
78
  settingsTabs: (ctx) => [{
@@ -71,7 +88,8 @@ function compositeFeatureCore(ui, options = {}) {
71
88
  const { schema } = editor;
72
89
  return structureBlocks(schema, blocks.map((block) => schema.nodeFromJSON(block)), structureOf(editor), STRUCTURE_STAGE_LEVEL, compositeKindsOf(editor)).map((node) => node.toJSON());
73
90
  },
74
- migrateContent: migrateLegacyContent
91
+ migrateContent: migrateLegacyContent,
92
+ normalize: (editor, blocks) => normalizeReferences(blocks, compositeIdsOf(editor.state.doc))
75
93
  },
76
94
  conversions: compositeConversions(options.kinds),
77
95
  aiContext: (editor) => ({
@@ -81,87 +99,57 @@ function compositeFeatureCore(ui, options = {}) {
81
99
  fields,
82
100
  ...ai?.purpose && { purpose: ai.purpose }
83
101
  })),
84
- structure: structureOf(editor)
85
- })
86
- };
87
- }
88
- function compositeSlashCommands({ settings, t }, kinds) {
89
- const insert = (kind) => (editor) => editor.commands.insertComposite(kind);
90
- const group = (recursive) => (editor) => {
91
- const { editing, blocks } = settings.get();
92
- return editor.commands.convertHeadingsToComposites({
93
- recursive,
94
- scope: editing.headingConversionScope,
95
- kind: blocks.defaultKind
96
- });
97
- };
98
- const flatten = (recursive) => (editor) => editor.commands.convertCompositesToHeadings({
99
- recursive,
100
- scope: settings.get().editing.headingConversionScope
101
- });
102
- return [
103
- {
104
- id: "abschnitt",
105
- label: t("composites.slash.section"),
106
- icon: "i-lucide-layers",
107
- ability: ABILITY.composite,
108
- run: insert("section")
109
- },
110
- ...kinds.filter((kind) => kind.id !== "section").map((kind) => ({
111
- id: kind.id,
112
- label: kind.label,
113
- icon: kind.icon,
114
- ability: ABILITY.composite,
115
- run: insert(kind.id)
116
- })),
117
- {
118
- id: "gliedern",
119
- label: t("composites.slash.group"),
120
- icon: "i-lucide-layers",
121
- ability: ABILITY.composite,
122
- run: group(false)
123
- },
124
- {
125
- id: "gliedern-alle",
126
- label: t("composites.slash.groupAll"),
127
- icon: "i-lucide-list-tree",
128
- ability: ABILITY.composite,
129
- run: group(true)
130
- },
131
- {
132
- id: "aufloesen",
133
- label: t("composites.slash.flatten"),
134
- icon: "i-lucide-heading",
135
- ability: ABILITY.headings,
136
- run: flatten(false)
137
- },
138
- {
139
- id: "aufloesen-alle",
140
- label: t("composites.slash.flattenAll"),
141
- icon: "i-lucide-align-left",
142
- ability: ABILITY.headings,
143
- run: flatten(true)
102
+ structure: structureOf(editor),
103
+ blocks: [REFERENCE_AI_BLOCK]
104
+ }),
105
+ aiBlockData: ({ editor, node }) => {
106
+ const from = derivationOf(node)?.from;
107
+ const source = from && "block" in from ? findBlockById(editor.state.doc, from.block)?.node : void 0;
108
+ return source?.type.name === "composite" ? [{
109
+ label: `Quelle: ${source.child(0).textContent.trim()}`,
110
+ text: bodyMarkdown(editor, source)
111
+ }] : [];
144
112
  }
145
- ];
113
+ };
146
114
  }
115
+ const COMPOSITE_TOOLBAR_GROUPS = [{
116
+ id: "composites",
117
+ order: 60,
118
+ labelKey: "palette.group.composites"
119
+ }];
147
120
  /**
148
- * The toolbar group beside the inserts: the default kind's insert button (it follows the setting, so label/icon/shortcut
149
- * are getters read at render time), „In Baustein umwandeln“ (one entry per kind for the caret's block) and „Gliederung
150
- * umwandeln“ (headings <-> composites in both directions, the preferred structure's direction first).
121
+ * Converting headings to Bausteine and back: the checks and actions the toolbar's „Gliederung umwandeln“ menu and the
122
+ * `/gliedern*` and `/aufloesen*` commands share, so both placements gate and act identically. They read the scope and
123
+ * default kind from the settings at call time.
151
124
  */
152
- function compositeToolbarItems({ settings, t }, kinds) {
153
- const defaultKind = () => compositeKind(kinds, settings.get().blocks.defaultKind);
154
- const insert = (chain) => chain.insertComposite(defaultKind().id);
155
- const scope = () => settings.get().editing.headingConversionScope;
156
- const canGroup = (editor, recursive) => editor.can().convertHeadingsToComposites({
125
+ function structureActions({ settings }) {
126
+ const groupOptions = (recursive) => ({
157
127
  recursive,
158
- scope: scope(),
128
+ scope: settings.get().editing.headingConversionScope,
159
129
  kind: settings.get().blocks.defaultKind
160
130
  });
161
- const canFlatten = (editor, recursive) => editor.can().convertCompositesToHeadings({
131
+ const flattenOptions = (recursive) => ({
162
132
  recursive,
163
- scope: scope()
133
+ scope: settings.get().editing.headingConversionScope
164
134
  });
135
+ return {
136
+ canGroup: (editor, recursive) => editor.can().convertHeadingsToComposites(groupOptions(recursive)),
137
+ canFlatten: (editor, recursive) => editor.can().convertCompositesToHeadings(flattenOptions(recursive)),
138
+ group: (editor, recursive) => void editor.chain().focus().convertHeadingsToComposites(groupOptions(recursive)).run(),
139
+ flatten: (editor, recursive) => void editor.chain().focus().convertCompositesToHeadings(flattenOptions(recursive)).run()
140
+ };
141
+ }
142
+ /**
143
+ * The commands of the composites feature, each declared once. Toolbar group beside the inserts: the default kind's
144
+ * insert button (it follows the setting, so label/icon/shortcut/`creates` are getters read at render time), „In
145
+ * Baustein umwandeln“ (one entry per kind for the caret's block) and „Gliederung umwandeln“ (headings <-> composites in
146
+ * both directions, the preferred structure's direction first). `/` menu: one command per kind (`creates` that kind, so
147
+ * the insert guard hides kinds the surrounding Baustein does not accept) and the four heading conversions.
148
+ */
149
+ function compositeCommands(ctx, kinds) {
150
+ const { settings, t } = ctx;
151
+ const defaultKind = () => compositeKind(kinds, settings.get().blocks.defaultKind);
152
+ const { canGroup, canFlatten, group, flatten } = structureActions(ctx);
165
153
  function kindItems(editor) {
166
154
  return [{
167
155
  type: "label",
@@ -184,7 +172,6 @@ function compositeToolbarItems({ settings, t }, kinds) {
184
172
  const abilities = abilitiesAtSelection(editor);
185
173
  const composite = abilities.has(ABILITY.composite);
186
174
  const headings = abilities.has(ABILITY.headings);
187
- const run = (command) => () => void command();
188
175
  const sep = { type: "separator" };
189
176
  const toComposites = [
190
177
  {
@@ -196,22 +183,14 @@ function compositeToolbarItems({ settings, t }, kinds) {
196
183
  description: t("composites.menu.toComposites.top.description"),
197
184
  icon: "i-lucide-layers",
198
185
  disabled: !composite || !canGroup(editor, false),
199
- onSelect: run(() => editor.chain().focus().convertHeadingsToComposites({
200
- recursive: false,
201
- scope: scope(),
202
- kind: settings.get().blocks.defaultKind
203
- }).run())
186
+ onSelect: () => group(editor, false)
204
187
  },
205
188
  {
206
189
  label: t("composites.menu.toComposites.all"),
207
190
  description: t("composites.menu.toComposites.all.description"),
208
191
  icon: "i-lucide-list-tree",
209
192
  disabled: !composite || !canGroup(editor, true),
210
- onSelect: run(() => editor.chain().focus().convertHeadingsToComposites({
211
- recursive: true,
212
- scope: scope(),
213
- kind: settings.get().blocks.defaultKind
214
- }).run())
193
+ onSelect: () => group(editor, true)
215
194
  }
216
195
  ];
217
196
  const toHeadings = [
@@ -224,20 +203,14 @@ function compositeToolbarItems({ settings, t }, kinds) {
224
203
  description: t("composites.menu.toHeadings.top.description"),
225
204
  icon: "i-lucide-heading",
226
205
  disabled: !headings || !canFlatten(editor, false),
227
- onSelect: run(() => editor.chain().focus().convertCompositesToHeadings({
228
- recursive: false,
229
- scope: scope()
230
- }).run())
206
+ onSelect: () => flatten(editor, false)
231
207
  },
232
208
  {
233
209
  label: t("composites.menu.toHeadings.all"),
234
210
  description: t("composites.menu.toHeadings.all.description"),
235
211
  icon: "i-lucide-align-left",
236
212
  disabled: !headings || !canFlatten(editor, true),
237
- onSelect: run(() => editor.chain().focus().convertCompositesToHeadings({
238
- recursive: true,
239
- scope: scope()
240
- }).run())
213
+ onSelect: () => flatten(editor, true)
241
214
  }
242
215
  ];
243
216
  const entry = editorEntryOf(editor);
@@ -263,10 +236,27 @@ function compositeToolbarItems({ settings, t }, kinds) {
263
236
  ...settingsEntry
264
237
  ];
265
238
  }
239
+ const insertKind = (kind, slashId, label, icon) => ({
240
+ id: `composite.${kind}`,
241
+ slash: { id: slashId },
242
+ creates: {
243
+ type: "composite",
244
+ attrs: { kind }
245
+ },
246
+ icon,
247
+ label,
248
+ ability: ABILITY.composite,
249
+ run: (editor) => {
250
+ editor.chain().focus().insertComposite(kind).run();
251
+ }
252
+ });
266
253
  return [
267
254
  {
268
255
  id: "insert",
269
- order: 10,
256
+ toolbar: {
257
+ group: "composites",
258
+ order: 10
259
+ },
270
260
  get icon() {
271
261
  return defaultKind().icon;
272
262
  },
@@ -280,28 +270,88 @@ function compositeToolbarItems({ settings, t }, kinds) {
280
270
  "a"
281
271
  ] : void 0;
282
272
  },
273
+ get creates() {
274
+ return {
275
+ type: "composite",
276
+ attrs: { kind: defaultKind().id }
277
+ };
278
+ },
283
279
  ability: ABILITY.composite,
284
- disabled: (editor) => !insert(editor.can().chain()).run(),
280
+ can: (editor) => editor.can().insertComposite(defaultKind().id),
285
281
  run: (editor) => {
286
- insert(editor.chain().focus()).run();
282
+ editor.chain().focus().insertComposite(defaultKind().id).run();
287
283
  }
288
284
  },
289
285
  {
290
286
  id: "to-kind",
291
- order: 20,
287
+ toolbar: {
288
+ group: "composites",
289
+ order: 20
290
+ },
292
291
  icon: "i-lucide-replace",
293
292
  label: t("composites.toolbar.toKind"),
294
293
  ability: ABILITY.composite,
295
- disabled: (editor) => kindItems(editor).every((item) => item.type === "label" || item.disabled),
294
+ can: (editor) => kindItems(editor).some((item) => item.type !== "label" && !item.disabled),
296
295
  menu: kindItems
297
296
  },
298
297
  {
299
298
  id: "structure",
300
- order: 30,
299
+ toolbar: {
300
+ group: "composites",
301
+ order: 30
302
+ },
301
303
  icon: "i-lucide-list-tree",
302
304
  label: t("composites.toolbar.structure"),
303
- disabled: (editor) => !canGroup(editor, true) && !canFlatten(editor, true),
305
+ can: (editor) => canGroup(editor, true) || canFlatten(editor, true),
304
306
  menu: structureItems
307
+ },
308
+ insertKind("section", "abschnitt", t("composites.slash.section"), "i-lucide-layers"),
309
+ ...kinds.filter((kind) => kind.id !== "section").map((kind) => insertKind(kind.id, kind.id, kind.label, kind.icon)),
310
+ {
311
+ id: "gliedern",
312
+ slash: {},
313
+ label: t("composites.slash.group"),
314
+ icon: "i-lucide-layers",
315
+ ability: ABILITY.composite,
316
+ can: (editor) => canGroup(editor, false),
317
+ run: (editor) => group(editor, false)
318
+ },
319
+ {
320
+ id: "gliedern-alle",
321
+ slash: {},
322
+ label: t("composites.slash.groupAll"),
323
+ icon: "i-lucide-list-tree",
324
+ ability: ABILITY.composite,
325
+ can: (editor) => canGroup(editor, true),
326
+ run: (editor) => group(editor, true)
327
+ },
328
+ {
329
+ id: "aufloesen",
330
+ slash: {},
331
+ label: t("composites.slash.flatten"),
332
+ icon: "i-lucide-heading",
333
+ ability: ABILITY.headings,
334
+ can: (editor) => canFlatten(editor, false),
335
+ run: (editor) => flatten(editor, false)
336
+ },
337
+ {
338
+ id: "aufloesen-alle",
339
+ slash: {},
340
+ label: t("composites.slash.flattenAll"),
341
+ icon: "i-lucide-align-left",
342
+ ability: ABILITY.headings,
343
+ can: (editor) => canFlatten(editor, true),
344
+ run: (editor) => flatten(editor, true)
345
+ },
346
+ {
347
+ id: "verweis",
348
+ slash: {},
349
+ label: t("composites.reference.insert"),
350
+ icon: "i-lucide-link-2",
351
+ ability: ABILITY.reference,
352
+ run: (editor) => {
353
+ editor.chain().focus().insertContent("[@").run();
354
+ }
305
355
  }
306
356
  ];
307
357
  }
@@ -1 +1 @@
1
- {"version":3,"file":"feature.js","names":[],"sources":["../../../src/features/composites/feature.ts"],"sourcesContent":["import type { ChainedCommands, Editor } from '@tiptap/core'\nimport type { EditorFeature, FeatureContext, MenuItem, SlashCommandItem, ToolbarItem } from '../../core'\nimport { abilitiesAtSelection, downloadText, editorEntryOf, settingsTabsOf } from '../../core'\nimport type { Translate } from '../../i18n'\nimport { ABILITY } from '../../core/schema'\nimport { AcceptedChildren } from './accepted-children'\nimport { compositeConversions } from './convert'\nimport { blocksFromMarkdown } from './fences'\nimport { structureBlocks } from './heading-composites'\nimport { type CompositeKind, compositeKind, defaultCompositeKinds } from './kinds'\nimport { migrateLegacyContent } from './legacy'\nimport { documentCompositeMarkdown, markdownFileName } from './markdown-export'\nimport { type CompositeNodeViews, compositeNodes } from './node-views'\nimport { CompositeDescriptionNode, CompositeTitleNode, compositeKindsOf } from './nodes'\nimport { Structure, structureOf } from './structure'\nimport { STRUCTURE_MODE_KEYS } from './structure-mode'\n\n/** What a framework binding supplies to the composites feature. */\nexport interface CompositesUi<C> {\n /** The chips on each title line and the details popover on the kind icon; mounted as an overlay. */\n chrome: C\n /** The „Bearbeiten“ settings tab; receives `{ kinds }` as props. */\n settingsTab: C\n /** The composite block view of the framework. */\n nodeViews: CompositeNodeViews\n}\n\n/** Options of `compositeFeature`. */\nexport interface CompositeFeatureOptions {\n /** The composite kinds („Bausteine“) offered in the editor, with their own labels (default: `defaultCompositeKinds(t)`, the built-in kinds in the editor's language); read once. */\n kinds?: readonly CompositeKind[]\n}\n\n/** Heading level the structure stage starts at when it turns composites into headings (below the document title). */\nconst STRUCTURE_STAGE_LEVEL = 2\n\n/**\n * Composites („Bausteine“): the node family with its node views, the toolbar group (insert, „In Baustein umwandeln“,\n * „Gliederung umwandeln“), `/` commands, the conversion providers (wrap into / switch kind of / unwrap composites),\n * Markdown `:::` fences, legacy `section` migration, the preferred-structure setting and its `editing` settings tab,\n * the chips on each title line (status, tags) and the details popover on the kind icon (the binding's `chrome` overlay), and\n * the AI view of kinds and structure, and the kinds' accepted children (`AcceptedChildren`: an edit that nests a Baustein\n * into one that does not accept its kind is refused with a notice). Contributes the `parseMarkdown`,\n * `structure` and `migrateContent` stages. Imports no AI, media or transcript code.\n */\nexport function compositeFeatureCore<C>(ui: CompositesUi<C>, options: CompositeFeatureOptions = {}): EditorFeature<C> {\n // Host kinds keep their labels; the built-in ones are produced from the context's translator (memoized per `t`).\n const kindsOf = (ctx: { t: Translate }) => options.kinds ?? defaultCompositeKinds(ctx.t)\n const { Composite, CompositeTags } = compositeNodes(ui.nodeViews)\n return {\n id: 'composites',\n extensions: ctx => [\n Composite.configure({ kinds: kindsOf(ctx) }),\n CompositeTitleNode,\n CompositeDescriptionNode,\n CompositeTags,\n Structure.configure({ mode: () => ctx.settings.get().blocks.structure }),\n AcceptedChildren.configure({ notify: ctx.notify, t: ctx.t }),\n ],\n toolbar: ctx => [{\n id: 'composites',\n order: 60,\n items: compositeToolbarItems(ctx, kindsOf(ctx)),\n }],\n slashCommands: ctx => compositeSlashCommands(ctx, kindsOf(ctx)),\n blockActions: ctx => [{\n id: 'document-export',\n label: ctx.t('composites.blockAction.export'),\n icon: 'i-lucide-download',\n ability: ABILITY.compositeExport,\n order: 400,\n isVisible: ({ node }) => node.attrs.kind === 'document',\n run: ({ editor, node }) => downloadText(markdownFileName(node), documentCompositeMarkdown(editor, node)),\n }],\n overlays: [ui.chrome],\n settingsTabs: ctx => [{ id: 'editing', label: ctx.t('composites.tab'), icon: 'i-lucide-pencil', component: ui.settingsTab, props: { kinds: kindsOf(ctx) } }],\n blocks: {\n parseMarkdown: (editor, markdown) => blocksFromMarkdown(md => editor.markdown!.parse(md), markdown, compositeKindsOf(editor)),\n structure: (editor, blocks) => {\n const { schema } = editor\n return structureBlocks(schema, blocks.map(block => schema.nodeFromJSON(block)), structureOf(editor), STRUCTURE_STAGE_LEVEL, compositeKindsOf(editor)).map(node => node.toJSON())\n },\n migrateContent: migrateLegacyContent,\n },\n conversions: compositeConversions(options.kinds),\n aiContext: editor => ({\n kinds: compositeKindsOf(editor).map(({ id, label, fields, ai }) => ({ id, label, fields, ...(ai?.purpose && { purpose: ai.purpose }) })),\n structure: structureOf(editor),\n }),\n }\n}\n\nfunction compositeSlashCommands({ settings, t }: FeatureContext, kinds: readonly CompositeKind[]): SlashCommandItem[] {\n const insert = (kind: string) => (editor: Editor) => editor.commands.insertComposite(kind)\n const group = (recursive: boolean) => (editor: Editor) => {\n const { editing, blocks } = settings.get()\n return editor.commands.convertHeadingsToComposites({ recursive, scope: editing.headingConversionScope, kind: blocks.defaultKind })\n }\n const flatten = (recursive: boolean) => (editor: Editor) => editor.commands.convertCompositesToHeadings({ recursive, scope: settings.get().editing.headingConversionScope })\n return [\n { id: 'abschnitt', label: t('composites.slash.section'), icon: 'i-lucide-layers', ability: ABILITY.composite, run: insert('section') },\n ...kinds.filter(kind => kind.id !== 'section').map((kind): SlashCommandItem => (\n { id: kind.id, label: kind.label, icon: kind.icon, ability: ABILITY.composite, run: insert(kind.id) }\n )),\n { id: 'gliedern', label: t('composites.slash.group'), icon: 'i-lucide-layers', ability: ABILITY.composite, run: group(false) },\n { id: 'gliedern-alle', label: t('composites.slash.groupAll'), icon: 'i-lucide-list-tree', ability: ABILITY.composite, run: group(true) },\n { id: 'aufloesen', label: t('composites.slash.flatten'), icon: 'i-lucide-heading', ability: ABILITY.headings, run: flatten(false) },\n { id: 'aufloesen-alle', label: t('composites.slash.flattenAll'), icon: 'i-lucide-align-left', ability: ABILITY.headings, run: flatten(true) },\n ]\n}\n\n/**\n * The toolbar group beside the inserts: the default kind's insert button (it follows the setting, so label/icon/shortcut\n * are getters read at render time), „In Baustein umwandeln“ (one entry per kind for the caret's block) and „Gliederung\n * umwandeln“ (headings <-> composites in both directions, the preferred structure's direction first).\n */\nfunction compositeToolbarItems<C>({ settings, t }: FeatureContext, kinds: readonly CompositeKind[]): ToolbarItem<C>[] {\n const defaultKind = () => compositeKind(kinds, settings.get().blocks.defaultKind)\n const insert = (chain: ChainedCommands) => chain.insertComposite(defaultKind().id)\n const scope = () => settings.get().editing.headingConversionScope\n\n const canGroup = (editor: Editor, recursive: boolean) => editor.can().convertHeadingsToComposites({ recursive, scope: scope(), kind: settings.get().blocks.defaultKind })\n const canFlatten = (editor: Editor, recursive: boolean) => editor.can().convertCompositesToHeadings({ recursive, scope: scope() })\n\n function kindItems(editor: Editor): MenuItem[] {\n return [\n { type: 'label', label: t('composites.menu.kindHeading') },\n ...compositeKindsOf(editor).map((kind): MenuItem => {\n const target = { type: 'composite', kind: kind.id } as const\n return { label: kind.label, icon: kind.icon, disabled: !editor.can().convertBlockTo(target), onSelect: () => editor.chain().focus().convertBlockTo(target).run() }\n }),\n ]\n }\n\n function structureItems(editor: Editor): MenuItem[] {\n const structure = settings.get().blocks.structure\n const abilities = abilitiesAtSelection(editor)\n const composite = abilities.has(ABILITY.composite)\n const headings = abilities.has(ABILITY.headings)\n const run = (command: () => boolean) => () => void command()\n const sep: MenuItem = { type: 'separator' }\n const toComposites: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toComposites') },\n { label: t('composites.menu.toComposites.top'), description: t('composites.menu.toComposites.top.description'), icon: 'i-lucide-layers', disabled: !composite || !canGroup(editor, false), onSelect: run(() => editor.chain().focus().convertHeadingsToComposites({ recursive: false, scope: scope(), kind: settings.get().blocks.defaultKind }).run()) },\n { label: t('composites.menu.toComposites.all'), description: t('composites.menu.toComposites.all.description'), icon: 'i-lucide-list-tree', disabled: !composite || !canGroup(editor, true), onSelect: run(() => editor.chain().focus().convertHeadingsToComposites({ recursive: true, scope: scope(), kind: settings.get().blocks.defaultKind }).run()) },\n ]\n const toHeadings: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toHeadings') },\n { label: t('composites.menu.toHeadings.top'), description: t('composites.menu.toHeadings.top.description'), icon: 'i-lucide-heading', disabled: !headings || !canFlatten(editor, false), onSelect: run(() => editor.chain().focus().convertCompositesToHeadings({ recursive: false, scope: scope() }).run()) },\n { label: t('composites.menu.toHeadings.all'), description: t('composites.menu.toHeadings.all.description'), icon: 'i-lucide-align-left', disabled: !headings || !canFlatten(editor, true), onSelect: run(() => editor.chain().focus().convertCompositesToHeadings({ recursive: true, scope: scope() }).run()) },\n ]\n const entry = editorEntryOf(editor)\n // The settings entry exists only while some feature contributes a tab to open.\n const settingsEntry: MenuItem[] = entry && settingsTabsOf(entry.preset, entry.ctx.app).length\n ? [sep, { label: t('composites.menu.settings'), icon: 'i-lucide-settings-2', onSelect: () => entry.ui.openSettings('editing') }]\n : []\n return [\n { type: 'label', label: t('composites.menu.preferred', { mode: t(STRUCTURE_MODE_KEYS[structure].labelKey) }) },\n ...(structure === 'composite' ? [...toComposites, sep, ...toHeadings] : [...toHeadings, sep, ...toComposites]),\n ...settingsEntry,\n ]\n }\n\n return [\n {\n id: 'insert',\n order: 10,\n // Getters: the default kind arrives with the server settings; the toolbar reads them at render time.\n get icon() { return defaultKind().icon },\n get label() { return defaultKind().label },\n // Mod-Shift-a (CompositeNode) always inserts a `section`, so only then is it shown as the shortcut.\n get kbds() { return defaultKind().id === 'section' ? ['meta', 'shift', 'a'] : undefined },\n ability: ABILITY.composite,\n disabled: editor => !insert(editor.can().chain()).run(),\n run: (editor) => { insert(editor.chain().focus()).run() },\n },\n {\n id: 'to-kind',\n order: 20,\n icon: 'i-lucide-replace',\n label: t('composites.toolbar.toKind'),\n ability: ABILITY.composite,\n disabled: editor => kindItems(editor).every(item => item.type === 'label' || item.disabled),\n menu: kindItems,\n },\n {\n id: 'structure',\n order: 30,\n icon: 'i-lucide-list-tree',\n label: t('composites.toolbar.structure'),\n disabled: editor => !canGroup(editor, true) && !canFlatten(editor, true),\n menu: structureItems,\n },\n ]\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"feature.js","names":[],"sources":["../../../src/features/composites/feature.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { CommandDef, EditorFeature, FeatureContext, MenuItem, ToolbarGroupDef } from '../../core'\nimport { abilitiesAtSelection, downloadText, editorEntryOf, settingsTabsOf } from '../../core'\nimport type { Translate } from '../../i18n'\nimport { ABILITY, findBlockById } from '../../core/schema'\nimport { AcceptedChildren, compositeInsertGuard } from './accepted-children'\nimport { bibOf, bibtexOf, cslOf } from './bibliography'\nimport { compositeConversions } from './convert'\nimport { bodyMarkdown, derivationOf } from './derivation'\nimport { blocksFromMarkdown } from './fences'\nimport { structureBlocks } from './heading-composites'\nimport { type CompositeKind, compositeKind, defaultCompositeKinds } from './kinds'\nimport { migrateLegacyContent } from './legacy'\nimport { compositeSchemaExtensions } from './schema'\nimport { documentCompositeMarkdown, markdownFileName } from './markdown-export'\nimport { type CompositeNodeViews, compositeNodes } from './node-views'\nimport { CompositeDescriptionNode, CompositeTitleNode, compositeKindsOf } from './nodes'\nimport { REFERENCE_TRIGGER } from './reference'\nimport { REFERENCE_AI_BLOCK } from './reference-ai'\nimport { referenceSuggestion } from './reference-suggestion'\nimport { compositeIdsOf, normalizeReferences } from './reference-text'\nimport { SourceReveal } from './reveal-source'\nimport { Structure, structureOf } from './structure'\nimport { STRUCTURE_MODE_KEYS } from './structure-mode'\n\n/** What a framework binding supplies to the composites feature. */\nexport interface CompositesUi<C> {\n /** The chips on each title line and the details popover on the kind icon; mounted as an overlay. */\n chrome: C\n /** The „Bearbeiten“ settings tab; receives `{ kinds }` as props. */\n settingsTab: C\n /** The composite block view of the framework. */\n nodeViews: CompositeNodeViews\n}\n\n/** Options of `compositeFeature`. */\nexport interface CompositeFeatureOptions {\n /** The composite kinds („Bausteine“) offered in the editor, with their own labels (default: `defaultCompositeKinds(t)`, the built-in kinds in the editor's language); read once. */\n kinds?: readonly CompositeKind[]\n}\n\n/** Heading level the structure stage starts at when it turns composites into headings (below the document title). */\nconst STRUCTURE_STAGE_LEVEL = 2\n\n/**\n * Composites („Bausteine“): the node family with its node views, the toolbar group (insert, „In Baustein umwandeln“,\n * „Gliederung umwandeln“), `/` commands, the conversion providers (wrap into / switch kind of / unwrap composites),\n * Markdown `:::` fences, legacy `section` migration, the preferred-structure setting and its `editing` settings tab,\n * the chips on each title line (status, tags) and the details popover on the kind icon (the binding's `chrome` overlay), and\n * the AI view of kinds and structure, and the kinds' accepted children (`AcceptedChildren`: an edit that nests a Baustein\n * into one that does not accept its kind is refused with a notice). Contributes the `parseMarkdown`,\n * `structure` and `migrateContent` stages. Imports no AI, media or transcript code.\n */\nexport function compositeFeatureCore<C>(ui: CompositesUi<C>, options: CompositeFeatureOptions = {}): EditorFeature<C> {\n // Host kinds keep their labels; the built-in ones are produced from the context's translator (memoized per `t`).\n const kindsOf = (ctx: { t: Translate }) => options.kinds ?? defaultCompositeKinds(ctx.t)\n const { Composite, CompositeTags, Reference } = compositeNodes(ui.nodeViews)\n return {\n id: 'composites',\n dimension: 'content',\n schemaExtensions: () => compositeSchemaExtensions(options.kinds ? { kinds: options.kinds } : {}),\n extensions: ctx => [\n Composite.configure({ kinds: kindsOf(ctx) }),\n CompositeTitleNode,\n CompositeDescriptionNode,\n CompositeTags,\n Structure.configure({ mode: () => ctx.settings.get().blocks.structure }),\n AcceptedChildren.configure({ notify: ctx.notify, t: ctx.t }),\n SourceReveal,\n Reference.configure({ suggestion: referenceSuggestion(ctx.t) }),\n ],\n toolbarGroups: COMPOSITE_TOOLBAR_GROUPS,\n commands: ctx => compositeCommands(ctx, kindsOf(ctx)),\n insertGuards: () => [compositeInsertGuard],\n blockActions: ctx => [{\n id: 'document-export',\n label: ctx.t('composites.blockAction.export'),\n icon: 'i-lucide-download',\n ability: ABILITY.compositeExport,\n order: 400,\n isVisible: ({ node }) => node.attrs.kind === 'document',\n run: ({ editor, node }) => downloadText(markdownFileName(node), documentCompositeMarkdown(editor, node)),\n }, {\n id: 'bibliography-export',\n label: ctx.t('composites.blockAction.bibtex'),\n icon: 'i-lucide-book-marked',\n ability: ABILITY.compositeExport,\n order: 410,\n isVisible: ({ node }) => bibOf(node) !== null,\n run: ({ node }) => downloadText(`${markdownFileName(node).replace(/\\.md$/, '')}.bib`, bibtexOf(cslOf(node)!), 'text/x-bibtex;charset=utf-8'),\n }],\n overlays: [ui.chrome],\n settingsTabs: ctx => [{ id: 'editing', label: ctx.t('composites.tab'), icon: 'i-lucide-pencil', component: ui.settingsTab, props: { kinds: kindsOf(ctx) } }],\n blocks: {\n parseMarkdown: (editor, markdown) => blocksFromMarkdown(md => editor.markdown!.parse(md), markdown, compositeKindsOf(editor)),\n structure: (editor, blocks) => {\n const { schema } = editor\n return structureBlocks(schema, blocks.map(block => schema.nodeFromJSON(block)), structureOf(editor), STRUCTURE_STAGE_LEVEL, compositeKindsOf(editor)).map(node => node.toJSON())\n },\n migrateContent: migrateLegacyContent,\n normalize: (editor, blocks) => normalizeReferences(blocks, compositeIdsOf(editor.state.doc)),\n },\n conversions: compositeConversions(options.kinds),\n aiContext: editor => ({\n kinds: compositeKindsOf(editor).map(({ id, label, fields, ai }) => ({ id, label, fields, ...(ai?.purpose && { purpose: ai.purpose }) })),\n structure: structureOf(editor),\n blocks: [REFERENCE_AI_BLOCK],\n }),\n // A Baustein derived from another block hands the model that source block's Markdown.\n aiBlockData: ({ editor, node }) => {\n const from = derivationOf(node)?.from\n const source = from && 'block' in from ? findBlockById(editor.state.doc, from.block)?.node : undefined\n // i18n-ignore: model-facing data label (German prompt text, not UI)\n return source?.type.name === 'composite' ? [{ label: `Quelle: ${source.child(0).textContent.trim()}`, text: bodyMarkdown(editor, source) }] : []\n },\n }\n}\n\nconst COMPOSITE_TOOLBAR_GROUPS: ToolbarGroupDef[] = [{ id: 'composites', order: 60, labelKey: 'palette.group.composites' }]\n\n/**\n * Converting headings to Bausteine and back: the checks and actions the toolbar's „Gliederung umwandeln“ menu and the\n * `/gliedern*` and `/aufloesen*` commands share, so both placements gate and act identically. They read the scope and\n * default kind from the settings at call time.\n */\nfunction structureActions({ settings }: FeatureContext) {\n const groupOptions = (recursive: boolean) => ({ recursive, scope: settings.get().editing.headingConversionScope, kind: settings.get().blocks.defaultKind })\n const flattenOptions = (recursive: boolean) => ({ recursive, scope: settings.get().editing.headingConversionScope })\n return {\n canGroup: (editor: Editor, recursive: boolean) => editor.can().convertHeadingsToComposites(groupOptions(recursive)),\n canFlatten: (editor: Editor, recursive: boolean) => editor.can().convertCompositesToHeadings(flattenOptions(recursive)),\n group: (editor: Editor, recursive: boolean) => void editor.chain().focus().convertHeadingsToComposites(groupOptions(recursive)).run(),\n flatten: (editor: Editor, recursive: boolean) => void editor.chain().focus().convertCompositesToHeadings(flattenOptions(recursive)).run(),\n }\n}\n\n/**\n * The commands of the composites feature, each declared once. Toolbar group beside the inserts: the default kind's\n * insert button (it follows the setting, so label/icon/shortcut/`creates` are getters read at render time), „In\n * Baustein umwandeln“ (one entry per kind for the caret's block) and „Gliederung umwandeln“ (headings <-> composites in\n * both directions, the preferred structure's direction first). `/` menu: one command per kind (`creates` that kind, so\n * the insert guard hides kinds the surrounding Baustein does not accept) and the four heading conversions.\n */\nfunction compositeCommands<C>(ctx: FeatureContext, kinds: readonly CompositeKind[]): CommandDef<C>[] {\n const { settings, t } = ctx\n const defaultKind = () => compositeKind(kinds, settings.get().blocks.defaultKind)\n const { canGroup, canFlatten, group, flatten } = structureActions(ctx)\n\n function kindItems(editor: Editor): MenuItem[] {\n return [\n { type: 'label', label: t('composites.menu.kindHeading') },\n ...compositeKindsOf(editor).map((kind): MenuItem => {\n const target = { type: 'composite', kind: kind.id } as const\n return { label: kind.label, icon: kind.icon, disabled: !editor.can().convertBlockTo(target), onSelect: () => editor.chain().focus().convertBlockTo(target).run() }\n }),\n ]\n }\n\n function structureItems(editor: Editor): MenuItem[] {\n const structure = settings.get().blocks.structure\n const abilities = abilitiesAtSelection(editor)\n const composite = abilities.has(ABILITY.composite)\n const headings = abilities.has(ABILITY.headings)\n const sep: MenuItem = { type: 'separator' }\n const toComposites: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toComposites') },\n { label: t('composites.menu.toComposites.top'), description: t('composites.menu.toComposites.top.description'), icon: 'i-lucide-layers', disabled: !composite || !canGroup(editor, false), onSelect: () => group(editor, false) },\n { label: t('composites.menu.toComposites.all'), description: t('composites.menu.toComposites.all.description'), icon: 'i-lucide-list-tree', disabled: !composite || !canGroup(editor, true), onSelect: () => group(editor, true) },\n ]\n const toHeadings: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toHeadings') },\n { label: t('composites.menu.toHeadings.top'), description: t('composites.menu.toHeadings.top.description'), icon: 'i-lucide-heading', disabled: !headings || !canFlatten(editor, false), onSelect: () => flatten(editor, false) },\n { label: t('composites.menu.toHeadings.all'), description: t('composites.menu.toHeadings.all.description'), icon: 'i-lucide-align-left', disabled: !headings || !canFlatten(editor, true), onSelect: () => flatten(editor, true) },\n ]\n const entry = editorEntryOf(editor)\n // The settings entry exists only while some feature contributes a tab to open.\n const settingsEntry: MenuItem[] = entry && settingsTabsOf(entry.preset, entry.ctx.app).length\n ? [sep, { label: t('composites.menu.settings'), icon: 'i-lucide-settings-2', onSelect: () => entry.ui.openSettings('editing') }]\n : []\n return [\n { type: 'label', label: t('composites.menu.preferred', { mode: t(STRUCTURE_MODE_KEYS[structure].labelKey) }) },\n ...(structure === 'composite' ? [...toComposites, sep, ...toHeadings] : [...toHeadings, sep, ...toComposites]),\n ...settingsEntry,\n ]\n }\n\n const insertKind = (kind: string, slashId: string, label: string, icon: string): CommandDef<C> => ({\n id: `composite.${kind}`,\n slash: { id: slashId },\n creates: { type: 'composite', attrs: { kind } },\n icon,\n label,\n ability: ABILITY.composite,\n run: (editor) => { editor.chain().focus().insertComposite(kind).run() },\n })\n\n return [\n {\n id: 'insert',\n toolbar: { group: 'composites', order: 10 },\n // Getters: the default kind arrives with the server settings; the toolbar reads them at render time.\n get icon() { return defaultKind().icon },\n get label() { return defaultKind().label },\n // Mod-Shift-a (CompositeNode) always inserts a `section`, so only then is it shown as the shortcut.\n get kbds() { return defaultKind().id === 'section' ? ['meta', 'shift', 'a'] : undefined },\n get creates() { return { type: 'composite', attrs: { kind: defaultKind().id } } },\n ability: ABILITY.composite,\n can: editor => editor.can().insertComposite(defaultKind().id),\n run: (editor) => { editor.chain().focus().insertComposite(defaultKind().id).run() },\n },\n {\n id: 'to-kind',\n toolbar: { group: 'composites', order: 20 },\n icon: 'i-lucide-replace',\n label: t('composites.toolbar.toKind'),\n ability: ABILITY.composite,\n can: editor => kindItems(editor).some(item => item.type !== 'label' && !item.disabled),\n menu: kindItems,\n },\n {\n id: 'structure',\n toolbar: { group: 'composites', order: 30 },\n icon: 'i-lucide-list-tree',\n label: t('composites.toolbar.structure'),\n can: editor => canGroup(editor, true) || canFlatten(editor, true),\n menu: structureItems,\n },\n insertKind('section', 'abschnitt', t('composites.slash.section'), 'i-lucide-layers'),\n ...kinds.filter(kind => kind.id !== 'section').map(kind => insertKind(kind.id, kind.id, kind.label, kind.icon)),\n { id: 'gliedern', slash: {}, label: t('composites.slash.group'), icon: 'i-lucide-layers', ability: ABILITY.composite, can: editor => canGroup(editor, false), run: editor => group(editor, false) },\n { id: 'gliedern-alle', slash: {}, label: t('composites.slash.groupAll'), icon: 'i-lucide-list-tree', ability: ABILITY.composite, can: editor => canGroup(editor, true), run: editor => group(editor, true) },\n { id: 'aufloesen', slash: {}, label: t('composites.slash.flatten'), icon: 'i-lucide-heading', ability: ABILITY.headings, can: editor => canFlatten(editor, false), run: editor => flatten(editor, false) },\n { id: 'aufloesen-alle', slash: {}, label: t('composites.slash.flattenAll'), icon: 'i-lucide-align-left', ability: ABILITY.headings, can: editor => canFlatten(editor, true), run: editor => flatten(editor, true) },\n { id: 'verweis', slash: {}, label: t('composites.reference.insert'), icon: 'i-lucide-link-2', ability: ABILITY.reference, run: (editor) => { editor.chain().focus().insertContent(REFERENCE_TRIGGER).run() } },\n ]\n}\n"],"mappings":"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"}
@@ -2,8 +2,8 @@ import { CompositeKind } from "./kinds.js";
2
2
  import { CompositeFence, FenceSegment, splitCompositeFences } from "../../core/fences.js";
3
3
  import { JSONContent } from "@tiptap/core";
4
4
  //#region src/features/composites/fences.d.ts
5
- /** `inner` fenced as composite of `kind`: `::: kind {meta}` (meta JSON only when non-empty), `inner`, `:::`. */
6
- export declare function compositeFence(kind: string, meta: Record<string, unknown>, inner: string): string;
5
+ /** `inner` fenced as composite of `kind`: `::: kind #id {meta}` (`#id` only with an `id`, meta JSON only when non-empty), `inner`, `:::`. */
6
+ export declare function compositeFence(kind: string, meta: Record<string, unknown>, inner: string, id?: string): string;
7
7
  /**
8
8
  * Markdown segments parsed, fences of a registered kind turned into composites, in order. A fence of any other kind
9
9
  * becomes an `opaqueFence` that keeps its text verbatim.
@@ -12,7 +12,8 @@ export declare function blocksFromMarkdown(parse: (md: string) => JSONContent, m
12
12
  /**
13
13
  * JSON of a composite built from the fence body: first `#`-heading → title, first blockquote directly after →
14
14
  * description, a `Tags:` line → tags, rest → body (recursing for nested fences). Missing title → empty title; empty
15
- * body → [paragraph]. Meta of a known kind keeps only that kind's fields.
15
+ * body → [paragraph]. Meta of a known kind keeps only that kind's fields, plus provenance (`derivation`) and the
16
+ * bibliographic record (`bib`), which any kind may carry.
16
17
  */
17
18
  export declare function compositeFromMarkdown(parse: (md: string) => JSONContent, fence: CompositeFence, kinds: readonly CompositeKind[]): JSONContent;
18
19
  //#endregion
@@ -1,8 +1,50 @@
1
1
  import { opaqueFenceJSON, splitCompositeFences } from "../../core/fences.js";
2
+ import { DERIVATION_KEY, keptMeta } from "./meta-keys.js";
2
3
  //#region src/features/composites/fences.ts
3
- /** `inner` fenced as composite of `kind`: `::: kind {meta}` (meta JSON only when non-empty), `inner`, `:::`. */
4
- function compositeFence(kind, meta, inner) {
5
- return `${Object.keys(meta).length ? `::: ${kind} ${JSON.stringify(meta)}` : `::: ${kind}`}\n${inner}\n:::`;
4
+ /** `inner` fenced as composite of `kind`: `::: kind #id {meta}` (`#id` only with an `id`, meta JSON only when non-empty), `inner`, `:::`. */
5
+ function compositeFence(kind, meta, inner, id) {
6
+ const parts = [`::: ${kind}`];
7
+ if (id) parts.push(`#${id}`);
8
+ if (Object.keys(meta).length) parts.push(JSON.stringify(meta));
9
+ return `${parts.join(" ")}\n${inner}\n:::`;
10
+ }
11
+ /**
12
+ * `json` with the `id` attr removed from every composite that nothing in `json` references: the Markdown renderer writes
13
+ * the id of the composites that still have one. References are `reference` nodes (`target`) and meta values of `reference`
14
+ * fields of the composite's kind. The input is not modified; unchanged subtrees are shared.
15
+ */
16
+ function withReferencedFenceIds(json, kinds) {
17
+ const referenced = /* @__PURE__ */ new Set();
18
+ let anyId = false;
19
+ const collect = (node) => {
20
+ if (node.type === "reference" && typeof node.attrs?.target === "string") referenced.add(node.attrs.target);
21
+ if (node.type === "composite") {
22
+ if (typeof node.attrs?.id === "string" && node.attrs.id) anyId = true;
23
+ const meta = node.attrs?.meta;
24
+ if (meta && typeof meta === "object") for (const field of kinds.find((kind) => kind.id === node.attrs?.kind)?.fields ?? []) {
25
+ const value = meta[field.key];
26
+ if (field.type === "reference" && typeof value === "string" && value) referenced.add(value);
27
+ }
28
+ const sourceBlock = node.attrs?.meta?.[DERIVATION_KEY]?.from?.block;
29
+ if (typeof sourceBlock === "string" && sourceBlock) referenced.add(sourceBlock);
30
+ }
31
+ node.content?.forEach(collect);
32
+ };
33
+ collect(json);
34
+ if (!anyId) return json;
35
+ const strip = (node) => {
36
+ const content = node.content?.map(strip);
37
+ const changed = content?.some((child, index) => child !== node.content[index]);
38
+ const dropId = node.type === "composite" && typeof node.attrs?.id === "string" && !referenced.has(node.attrs.id);
39
+ if (!dropId && !changed) return node;
40
+ const { id: _id, ...attrs } = node.attrs ?? {};
41
+ return {
42
+ ...node,
43
+ ...dropId ? { attrs } : {},
44
+ ...changed ? { content } : {}
45
+ };
46
+ };
47
+ return strip(json);
6
48
  }
7
49
  /**
8
50
  * Markdown segments parsed, fences of a registered kind turned into composites, in order. A fence of any other kind
@@ -28,7 +70,8 @@ function inlineOf(parse, md) {
28
70
  /**
29
71
  * JSON of a composite built from the fence body: first `#`-heading → title, first blockquote directly after →
30
72
  * description, a `Tags:` line → tags, rest → body (recursing for nested fences). Missing title → empty title; empty
31
- * body → [paragraph]. Meta of a known kind keeps only that kind's fields.
73
+ * body → [paragraph]. Meta of a known kind keeps only that kind's fields, plus provenance (`derivation`) and the
74
+ * bibliographic record (`bib`), which any kind may carry.
32
75
  */
33
76
  function compositeFromMarkdown(parse, fence, kinds) {
34
77
  const lines = fence.inner.split("\n");
@@ -55,12 +98,13 @@ function compositeFromMarkdown(parse, fence, kinds) {
55
98
  i++;
56
99
  }
57
100
  const body = blocksFromMarkdown(parse, lines.slice(i).join("\n"), kinds);
58
- const fields = kinds.find((kind) => kind.id === fence.kind)?.fields.map((field) => field.key);
59
- const meta = fields ? Object.fromEntries(Object.entries(fence.meta).filter(([key]) => fields.includes(key))) : fence.meta;
101
+ const kind = kinds.find((candidate) => candidate.id === fence.kind);
102
+ const meta = kind ? keptMeta(kind, fence.meta) : fence.meta;
60
103
  return {
61
104
  type: "composite",
62
105
  attrs: {
63
106
  kind: fence.kind,
107
+ ...fence.id && { id: fence.id },
64
108
  meta
65
109
  },
66
110
  content: [
@@ -81,6 +125,6 @@ function compositeFromMarkdown(parse, fence, kinds) {
81
125
  };
82
126
  }
83
127
  //#endregion
84
- export { blocksFromMarkdown, compositeFence, compositeFromMarkdown, splitCompositeFences };
128
+ export { blocksFromMarkdown, compositeFence, compositeFromMarkdown, splitCompositeFences, withReferencedFenceIds };
85
129
 
86
130
  //# sourceMappingURL=fences.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fences.js","names":[],"sources":["../../../src/features/composites/fences.ts"],"sourcesContent":["import type { JSONContent } from '@tiptap/core'\nimport { type CompositeFence, opaqueFenceJSON, splitCompositeFences } from '../../core/fences'\nimport type { CompositeKind } from './kinds'\n\n// Inverse of the composite nodes' renderMarkdown: `::: kind {meta}`, `## title`, `> description`, `Tags: #a #b`, body,\n// `:::`. The fence grammar itself (`splitCompositeFences`) is shared with the Markdown entry (`core/fences`).\nexport { type CompositeFence, type FenceSegment, splitCompositeFences } from '../../core/fences'\n\n/** `inner` fenced as composite of `kind`: `::: kind {meta}` (meta JSON only when non-empty), `inner`, `:::`. */\nexport function compositeFence(kind: string, meta: Record<string, unknown>, inner: string): string {\n const opener = Object.keys(meta).length ? `::: ${kind} ${JSON.stringify(meta)}` : `::: ${kind}`\n return `${opener}\\n${inner}\\n:::`\n}\n\n/**\n * Markdown segments parsed, fences of a registered kind turned into composites, in order. A fence of any other kind\n * becomes an `opaqueFence` that keeps its text verbatim.\n */\nexport function blocksFromMarkdown(parse: (md: string) => JSONContent, markdown: string, kinds: readonly CompositeKind[]): JSONContent[] {\n return splitCompositeFences(markdown).flatMap((segment) => {\n if (!('inner' in segment)) return parse(segment.markdown).content ?? []\n return kinds.some(kind => kind.id === segment.kind) ? [compositeFromMarkdown(parse, segment, kinds)] : [opaqueFenceJSON(segment)]\n })\n}\n\n/** Inline content of the first textblock `parse` makes of `md`. */\nfunction inlineOf(parse: (md: string) => JSONContent, md: string): JSONContent[] | undefined {\n let found: JSONContent[] | undefined\n const walk = (node: JSONContent): void => {\n if (found) return\n if (node.content?.some(child => child.type === 'text')) found = node.content\n else node.content?.forEach(walk)\n }\n if (md.trim()) walk(parse(md))\n return found?.length ? found : undefined\n}\n\n/**\n * JSON of a composite built from the fence body: first `#`-heading → title, first blockquote directly after →\n * description, a `Tags:` line → tags, rest → body (recursing for nested fences). Missing title → empty title; empty\n * body → [paragraph]. Meta of a known kind keeps only that kind's fields.\n */\nexport function compositeFromMarkdown(parse: (md: string) => JSONContent, fence: CompositeFence, kinds: readonly CompositeKind[]): JSONContent {\n const lines = fence.inner.split('\\n')\n let i = 0\n const skipBlank = () => {\n while (i < lines.length && !lines[i]!.trim()) i++\n }\n skipBlank()\n let title: JSONContent[] | undefined\n const heading = /^\\s*#{1,6}(?:\\s+(.*?))?\\s*#*\\s*$/.exec(lines[i] ?? '')\n if (heading) {\n title = inlineOf(parse, heading[1] ?? '')\n i++\n skipBlank()\n }\n const quote: string[] = []\n while (i < lines.length && /^\\s*>/.test(lines[i]!)) quote.push(lines[i++]!.replace(/^\\s*>\\s?/, ''))\n const description = quote.length ? inlineOf(parse, quote.join('\\n')) : undefined\n skipBlank()\n let tags: string[] = []\n const tagLine = /^\\s*Tags:\\s*(.*)$/i.exec(lines[i] ?? '')\n if (tagLine) {\n tags = [...new Set([...tagLine[1]!.matchAll(/#?([\\p{L}\\p{N}_-]+)/gu)].map(m => m[1]!.toLowerCase()))]\n i++\n }\n const body = blocksFromMarkdown(parse, lines.slice(i).join('\\n'), kinds)\n\n // A kind outside `kinds` (only reachable when called directly; `blocksFromMarkdown` makes those fences opaque) keeps its id (the views fall back via `compositeKind()`) and its meta as given.\n const fields = kinds.find(kind => kind.id === fence.kind)?.fields.map(field => field.key)\n const meta = fields ? Object.fromEntries(Object.entries(fence.meta).filter(([key]) => fields.includes(key))) : fence.meta\n return {\n type: 'composite',\n attrs: { kind: fence.kind, meta },\n content: [\n title ? { type: 'compositeTitle', content: title } : { type: 'compositeTitle' },\n description ? { type: 'compositeDescription', content: description } : { type: 'compositeDescription' },\n { type: 'compositeTags', attrs: { tags } },\n ...(body.length ? body : [{ type: 'paragraph' }]),\n ],\n }\n}\n"],"mappings":";;;AASA,SAAgB,eAAe,MAAc,MAA+B,OAAuB;CAEjG,OAAO,GADQ,OAAO,KAAK,IAAI,CAAC,CAAC,SAAS,OAAO,KAAK,GAAG,KAAK,UAAU,IAAI,MAAM,OAAO,OACxE,IAAI,MAAM;AAC7B;;;;;AAMA,SAAgB,mBAAmB,OAAoC,UAAkB,OAAgD;CACvI,OAAO,qBAAqB,QAAQ,CAAC,CAAC,SAAS,YAAY;EACzD,IAAI,EAAE,WAAW,UAAU,OAAO,MAAM,QAAQ,QAAQ,CAAC,CAAC,WAAW,CAAC;EACtE,OAAO,MAAM,MAAK,SAAQ,KAAK,OAAO,QAAQ,IAAI,IAAI,CAAC,sBAAsB,OAAO,SAAS,KAAK,CAAC,IAAI,CAAC,gBAAgB,OAAO,CAAC;CAClI,CAAC;AACH;;AAGA,SAAS,SAAS,OAAoC,IAAuC;CAC3F,IAAI;CACJ,MAAM,QAAQ,SAA4B;EACxC,IAAI,OAAO;EACX,IAAI,KAAK,SAAS,MAAK,UAAS,MAAM,SAAS,MAAM,GAAG,QAAQ,KAAK;OAChE,KAAK,SAAS,QAAQ,IAAI;CACjC;CACA,IAAI,GAAG,KAAK,GAAG,KAAK,MAAM,EAAE,CAAC;CAC7B,OAAO,OAAO,SAAS,QAAQ,KAAA;AACjC;;;;;;AAOA,SAAgB,sBAAsB,OAAoC,OAAuB,OAA8C;CAC7I,MAAM,QAAQ,MAAM,MAAM,MAAM,IAAI;CACpC,IAAI,IAAI;CACR,MAAM,kBAAkB;EACtB,OAAO,IAAI,MAAM,UAAU,CAAC,MAAM,EAAE,CAAE,KAAK,GAAG;CAChD;CACA,UAAU;CACV,IAAI;CACJ,MAAM,UAAU,mCAAmC,KAAK,MAAM,MAAM,EAAE;CACtE,IAAI,SAAS;EACX,QAAQ,SAAS,OAAO,QAAQ,MAAM,EAAE;EACxC;EACA,UAAU;CACZ;CACA,MAAM,QAAkB,CAAC;CACzB,OAAO,IAAI,MAAM,UAAU,QAAQ,KAAK,MAAM,EAAG,GAAG,MAAM,KAAK,MAAM,IAAI,CAAE,QAAQ,YAAY,EAAE,CAAC;CAClG,MAAM,cAAc,MAAM,SAAS,SAAS,OAAO,MAAM,KAAK,IAAI,CAAC,IAAI,KAAA;CACvE,UAAU;CACV,IAAI,OAAiB,CAAC;CACtB,MAAM,UAAU,qBAAqB,KAAK,MAAM,MAAM,EAAE;CACxD,IAAI,SAAS;EACX,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,QAAQ,EAAE,CAAE,SAAS,uBAAuB,CAAC,CAAC,CAAC,KAAI,MAAK,EAAE,EAAE,CAAE,YAAY,CAAC,CAAC,CAAC;EACpG;CACF;CACA,MAAM,OAAO,mBAAmB,OAAO,MAAM,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,KAAK;CAGvE,MAAM,SAAS,MAAM,MAAK,SAAQ,KAAK,OAAO,MAAM,IAAI,CAAC,EAAE,OAAO,KAAI,UAAS,MAAM,GAAG;CACxF,MAAM,OAAO,SAAS,OAAO,YAAY,OAAO,QAAQ,MAAM,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,OAAO,SAAS,GAAG,CAAC,CAAC,IAAI,MAAM;CACrH,OAAO;EACL,MAAM;EACN,OAAO;GAAE,MAAM,MAAM;GAAM;EAAK;EAChC,SAAS;GACP,QAAQ;IAAE,MAAM;IAAkB,SAAS;GAAM,IAAI,EAAE,MAAM,iBAAiB;GAC9E,cAAc;IAAE,MAAM;IAAwB,SAAS;GAAY,IAAI,EAAE,MAAM,uBAAuB;GACtG;IAAE,MAAM;IAAiB,OAAO,EAAE,KAAK;GAAE;GACzC,GAAI,KAAK,SAAS,OAAO,CAAC,EAAE,MAAM,YAAY,CAAC;EACjD;CACF;AACF"}
1
+ {"version":3,"file":"fences.js","names":[],"sources":["../../../src/features/composites/fences.ts"],"sourcesContent":["import type { JSONContent } from '@tiptap/core'\nimport { type CompositeFence, opaqueFenceJSON, splitCompositeFences } from '../../core/fences'\nimport { DERIVATION_KEY, keptMeta } from './meta-keys'\nimport type { CompositeKind } from './kinds'\n\n// Inverse of the composite nodes' renderMarkdown: `::: kind #id {meta}`, `## title`, `> description`, `Tags: #a #b`, body,\n// `:::`. The fence grammar itself (`splitCompositeFences`) is shared with the Markdown entry (`core/fences`).\n//\n// Block ids in fences: a Baustein written to Markdown carries its block id in the opener (`::: paper #<uuid> {meta}`,\n// Pandoc-like `#id` between kind and meta) only when something in the same serialized content points at it — a `reference`\n// chip (`[@<id>, S. 3]`) or a `reference` meta field. Every other fence stays `::: kind {meta}`. Parsing restores the id\n// as `attrs.id`, so after a Markdown round trip (source-mode commit, import) the `[@<id>]` tokens still resolve to\n// the same Bausteine. `withReferencedFenceIds` is the pre-pass that decides which ids are written.\nexport { type CompositeFence, type FenceSegment, splitCompositeFences } from '../../core/fences'\n\n/** `inner` fenced as composite of `kind`: `::: kind #id {meta}` (`#id` only with an `id`, meta JSON only when non-empty), `inner`, `:::`. */\nexport function compositeFence(kind: string, meta: Record<string, unknown>, inner: string, id?: string): string {\n const parts = [`::: ${kind}`]\n if (id) parts.push(`#${id}`)\n if (Object.keys(meta).length) parts.push(JSON.stringify(meta))\n return `${parts.join(' ')}\\n${inner}\\n:::`\n}\n\n/**\n * `json` with the `id` attr removed from every composite that nothing in `json` references: the Markdown renderer writes\n * the id of the composites that still have one. References are `reference` nodes (`target`) and meta values of `reference`\n * fields of the composite's kind. The input is not modified; unchanged subtrees are shared.\n */\nexport function withReferencedFenceIds(json: JSONContent, kinds: readonly CompositeKind[]): JSONContent {\n const referenced = new Set<string>()\n let anyId = false\n const collect = (node: JSONContent): void => {\n if (node.type === 'reference' && typeof node.attrs?.target === 'string') referenced.add(node.attrs.target)\n if (node.type === 'composite') {\n if (typeof node.attrs?.id === 'string' && node.attrs.id) anyId = true\n const meta: unknown = node.attrs?.meta\n if (meta && typeof meta === 'object') {\n for (const field of kinds.find(kind => kind.id === node.attrs?.kind)?.fields ?? []) {\n const value = (meta as Record<string, unknown>)[field.key]\n if (field.type === 'reference' && typeof value === 'string' && value) referenced.add(value)\n }\n }\n // A block-derived Baustein points at its source (`meta.derivation.from.block`): the source keeps its id across a round trip.\n const sourceBlock: unknown = node.attrs?.meta?.[DERIVATION_KEY]?.from?.block\n if (typeof sourceBlock === 'string' && sourceBlock) referenced.add(sourceBlock)\n }\n node.content?.forEach(collect)\n }\n collect(json)\n if (!anyId) return json\n const strip = (node: JSONContent): JSONContent => {\n const content = node.content?.map(strip)\n const changed = content?.some((child, index) => child !== node.content![index])\n const dropId = node.type === 'composite' && typeof node.attrs?.id === 'string' && !referenced.has(node.attrs.id)\n if (!dropId && !changed) return node\n const { id: _id, ...attrs } = node.attrs ?? {}\n return { ...node, ...(dropId ? { attrs } : {}), ...(changed ? { content } : {}) }\n }\n return strip(json)\n}\n\n/**\n * Markdown segments parsed, fences of a registered kind turned into composites, in order. A fence of any other kind\n * becomes an `opaqueFence` that keeps its text verbatim.\n */\nexport function blocksFromMarkdown(parse: (md: string) => JSONContent, markdown: string, kinds: readonly CompositeKind[]): JSONContent[] {\n return splitCompositeFences(markdown).flatMap((segment) => {\n if (!('inner' in segment)) return parse(segment.markdown).content ?? []\n return kinds.some(kind => kind.id === segment.kind) ? [compositeFromMarkdown(parse, segment, kinds)] : [opaqueFenceJSON(segment)]\n })\n}\n\n/** Inline content of the first textblock `parse` makes of `md`. */\nfunction inlineOf(parse: (md: string) => JSONContent, md: string): JSONContent[] | undefined {\n let found: JSONContent[] | undefined\n const walk = (node: JSONContent): void => {\n if (found) return\n if (node.content?.some(child => child.type === 'text')) found = node.content\n else node.content?.forEach(walk)\n }\n if (md.trim()) walk(parse(md))\n return found?.length ? found : undefined\n}\n\n/**\n * JSON of a composite built from the fence body: first `#`-heading → title, first blockquote directly after →\n * description, a `Tags:` line → tags, rest → body (recursing for nested fences). Missing title → empty title; empty\n * body → [paragraph]. Meta of a known kind keeps only that kind's fields, plus provenance (`derivation`) and the\n * bibliographic record (`bib`), which any kind may carry.\n */\nexport function compositeFromMarkdown(parse: (md: string) => JSONContent, fence: CompositeFence, kinds: readonly CompositeKind[]): JSONContent {\n const lines = fence.inner.split('\\n')\n let i = 0\n const skipBlank = () => {\n while (i < lines.length && !lines[i]!.trim()) i++\n }\n skipBlank()\n let title: JSONContent[] | undefined\n const heading = /^\\s*#{1,6}(?:\\s+(.*?))?\\s*#*\\s*$/.exec(lines[i] ?? '')\n if (heading) {\n title = inlineOf(parse, heading[1] ?? '')\n i++\n skipBlank()\n }\n const quote: string[] = []\n while (i < lines.length && /^\\s*>/.test(lines[i]!)) quote.push(lines[i++]!.replace(/^\\s*>\\s?/, ''))\n const description = quote.length ? inlineOf(parse, quote.join('\\n')) : undefined\n skipBlank()\n let tags: string[] = []\n const tagLine = /^\\s*Tags:\\s*(.*)$/i.exec(lines[i] ?? '')\n if (tagLine) {\n tags = [...new Set([...tagLine[1]!.matchAll(/#?([\\p{L}\\p{N}_-]+)/gu)].map(m => m[1]!.toLowerCase()))]\n i++\n }\n const body = blocksFromMarkdown(parse, lines.slice(i).join('\\n'), kinds)\n\n // A kind outside `kinds` (only reachable when called directly; `blocksFromMarkdown` makes those fences opaque) keeps its id (the views fall back via `compositeKind()`) and its meta as given.\n const kind = kinds.find(candidate => candidate.id === fence.kind)\n const meta = kind ? keptMeta(kind, fence.meta) : fence.meta\n return {\n type: 'composite',\n attrs: { kind: fence.kind, ...(fence.id && { id: fence.id }), meta },\n content: [\n title ? { type: 'compositeTitle', content: title } : { type: 'compositeTitle' },\n description ? { type: 'compositeDescription', content: description } : { type: 'compositeDescription' },\n { type: 'compositeTags', attrs: { tags } },\n ...(body.length ? body : [{ type: 'paragraph' }]),\n ],\n }\n}\n"],"mappings":"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"}