@ecsplico/editor 3.5.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (583) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/dist/adapters/direct-ai.d.ts +4 -4
  3. package/dist/adapters/direct-ai.js +2 -2
  4. package/dist/adapters/direct-ai.js.map +1 -1
  5. package/dist/adapters/document-state.d.ts +1 -1
  6. package/dist/adapters/document-state.js.map +1 -1
  7. package/dist/adapters/forge.d.ts +2 -2
  8. package/dist/adapters/forge.js.map +1 -1
  9. package/dist/adapters/nitro.d.ts +11 -3
  10. package/dist/adapters/nitro.js +3 -1
  11. package/dist/adapters/nitro.js.map +1 -1
  12. package/dist/adapters/shared.d.ts +6 -6
  13. package/dist/adapters/shared.js.map +1 -1
  14. package/dist/code/CodeSurface.vue.d.ts +3 -3
  15. package/dist/config/index.d.ts +14 -14
  16. package/dist/config/index.js +8 -8
  17. package/dist/config/index.js.map +1 -1
  18. package/dist/core/backend-types.d.ts +3 -3
  19. package/dist/core/backend-types.js.map +1 -1
  20. package/dist/core/backend.d.ts +4 -4
  21. package/dist/core/backend.js.map +1 -1
  22. package/dist/core/block-convert.d.ts +1 -1
  23. package/dist/core/block-convert.js +5 -5
  24. package/dist/core/block-convert.js.map +1 -1
  25. package/dist/core/block-transfer.d.ts +8 -4
  26. package/dist/core/block-transfer.js +23 -14
  27. package/dist/core/block-transfer.js.map +1 -1
  28. package/dist/core/capabilities.d.ts +113 -0
  29. package/dist/core/capabilities.js +155 -0
  30. package/dist/core/capabilities.js.map +1 -0
  31. package/dist/core/command-types.d.ts +1 -1
  32. package/dist/core/context.js.map +1 -1
  33. package/dist/core/convert.d.ts +5 -5
  34. package/dist/core/convert.js +5 -5
  35. package/dist/core/convert.js.map +1 -1
  36. package/dist/core/core-feature.js +1 -1
  37. package/dist/core/define-editor.d.ts +2 -2
  38. package/dist/core/define-editor.js +34 -6
  39. package/dist/core/define-editor.js.map +1 -1
  40. package/dist/core/derivation.d.ts +119 -0
  41. package/dist/core/derivation.js +187 -0
  42. package/dist/core/derivation.js.map +1 -0
  43. package/dist/core/derive.d.ts +61 -0
  44. package/dist/core/derive.js +69 -0
  45. package/dist/core/derive.js.map +1 -0
  46. package/dist/core/extension-points.d.ts +16 -0
  47. package/dist/core/feature-context.d.ts +5 -1
  48. package/dist/core/feature-context.js +10 -3
  49. package/dist/core/feature-context.js.map +1 -1
  50. package/dist/core/feature.d.ts +41 -19
  51. package/dist/core/feature.js.map +1 -1
  52. package/dist/core/fences.js +1 -1
  53. package/dist/core/fences.js.map +1 -1
  54. package/dist/core/index.d.ts +6 -2
  55. package/dist/core/index.js +5 -1
  56. package/dist/core/pipeline.d.ts +14 -5
  57. package/dist/core/pipeline.js +19 -7
  58. package/dist/core/pipeline.js.map +1 -1
  59. package/dist/core/properties.d.ts +22 -0
  60. package/dist/core/properties.js +17 -0
  61. package/dist/core/properties.js.map +1 -0
  62. package/dist/core/schema/block-ids.js +5 -5
  63. package/dist/core/schema/block-ids.js.map +1 -1
  64. package/dist/core/schema/index.d.ts +2 -1
  65. package/dist/core/schema/index.js +2 -1
  66. package/dist/core/schema/index.js.map +1 -1
  67. package/dist/core/schema/opaque-fence.d.ts +4 -4
  68. package/dist/core/schema/opaque-fence.js +7 -7
  69. package/dist/core/schema/opaque-fence.js.map +1 -1
  70. package/dist/core/schema/persisted-names.d.ts +58 -0
  71. package/dist/core/schema/persisted-names.js +96 -0
  72. package/dist/core/schema/persisted-names.js.map +1 -0
  73. package/dist/core/toolbar-items.js +1 -1
  74. package/dist/core/toolbar-items.js.map +1 -1
  75. package/dist/core/util.js +5 -1
  76. package/dist/core/util.js.map +1 -1
  77. package/dist/document/DocumentSurface.vue.d.ts +3 -3
  78. package/dist/features/ai/agent-ops.js +1 -1
  79. package/dist/features/ai/ai-review.js +1 -1
  80. package/dist/features/ai/assistant.d.ts +4 -4
  81. package/dist/features/ai/assistant.js +1 -1
  82. package/dist/features/ai/assistant.js.map +1 -1
  83. package/dist/features/ai/components/AiSelectionMenu.js +1 -1
  84. package/dist/features/ai/components/AiSelectionMenu.js.map +1 -1
  85. package/dist/features/ai/components/ModelQuickSwitch.js +7 -7
  86. package/dist/features/ai/components/ModelQuickSwitch.js.map +1 -1
  87. package/dist/features/ai/components/ModelQuickSwitch.vue.d.ts +4 -4
  88. package/dist/features/ai/components/SettingsAiTab.js +8 -8
  89. package/dist/features/ai/components/SettingsAiTab.js.map +1 -1
  90. package/dist/features/ai/components/SettingsModelProfiles.js +1 -1
  91. package/dist/features/ai/components/SettingsModelProfiles.js.map +1 -1
  92. package/dist/features/ai/document-chat-model.d.ts +2 -2
  93. package/dist/features/ai/document-chat-model.js +5 -5
  94. package/dist/features/ai/document-chat-model.js.map +1 -1
  95. package/dist/features/ai/document-chat.js +2 -2
  96. package/dist/features/ai/document-chat.js.map +1 -1
  97. package/dist/features/ai/feature.d.ts +2 -2
  98. package/dist/features/ai/feature.js +2 -2
  99. package/dist/features/ai/feature.js.map +1 -1
  100. package/dist/features/ai/ghost-autocomplete.d.ts +4 -4
  101. package/dist/features/ai/ghost-autocomplete.js +1 -1
  102. package/dist/features/ai/ghost-autocomplete.js.map +1 -1
  103. package/dist/features/ai/index.d.ts +3 -3
  104. package/dist/features/ai/index.js +2 -2
  105. package/dist/features/ai/model-profiles.d.ts +9 -9
  106. package/dist/features/ai/model-profiles.js +13 -13
  107. package/dist/features/ai/model-profiles.js.map +1 -1
  108. package/dist/features/ai/protocol/agent-ops.d.ts +2 -2
  109. package/dist/features/ai/protocol/agent-ops.js +1 -1
  110. package/dist/features/ai/protocol/agent-ops.js.map +1 -1
  111. package/dist/features/ai/protocol/block-lines.d.ts +7 -7
  112. package/dist/features/ai/protocol/block-lines.js +10 -10
  113. package/dist/features/ai/protocol/block-lines.js.map +1 -1
  114. package/dist/features/ai/protocol/chat.d.ts +5 -5
  115. package/dist/features/ai/protocol/chat.js +12 -12
  116. package/dist/features/ai/protocol/chat.js.map +1 -1
  117. package/dist/features/ai/protocol/generate.d.ts +1 -1
  118. package/dist/features/ai/protocol/generate.js +1 -1
  119. package/dist/features/ai/protocol/generate.js.map +1 -1
  120. package/dist/features/ai/protocol/index.d.ts +3 -3
  121. package/dist/features/ai/protocol/index.js +2 -2
  122. package/dist/features/ai/protocol/models.d.ts +3 -3
  123. package/dist/features/ai/protocol/models.js +3 -3
  124. package/dist/features/ai/protocol/models.js.map +1 -1
  125. package/dist/features/ai/protocol/schemas.d.ts +1 -1
  126. package/dist/features/ai/protocol/schemas.js +1 -1
  127. package/dist/features/ai/protocol/schemas.js.map +1 -1
  128. package/dist/features/ai/protocol/tasks.d.ts +5 -5
  129. package/dist/features/ai/protocol/tasks.js +12 -12
  130. package/dist/features/ai/protocol/tasks.js.map +1 -1
  131. package/dist/features/ai/react/AiSelectionMenu.js.map +1 -1
  132. package/dist/features/ai/react/ModelQuickSwitch.d.ts +4 -4
  133. package/dist/features/ai/react/ModelQuickSwitch.js +6 -6
  134. package/dist/features/ai/react/ModelQuickSwitch.js.map +1 -1
  135. package/dist/features/ai/react/SettingsAiTab.d.ts +1 -1
  136. package/dist/features/ai/react/SettingsAiTab.js +8 -8
  137. package/dist/features/ai/react/SettingsAiTab.js.map +1 -1
  138. package/dist/features/ai/react/SettingsModelProfiles.d.ts +1 -1
  139. package/dist/features/ai/react/SettingsModelProfiles.js +1 -1
  140. package/dist/features/ai/react/SettingsModelProfiles.js.map +1 -1
  141. package/dist/features/ai/react/use-ai-assistant.d.ts +1 -1
  142. package/dist/features/ai/react/use-ai-assistant.js +1 -1
  143. package/dist/features/ai/react/use-ai-assistant.js.map +1 -1
  144. package/dist/features/ai/react/use-model-profiles.d.ts +5 -5
  145. package/dist/features/ai/react/use-model-profiles.js +2 -2
  146. package/dist/features/ai/react/use-model-profiles.js.map +1 -1
  147. package/dist/features/ai/use-ai-assistant.d.ts +1 -1
  148. package/dist/features/ai/use-ai-assistant.js +1 -1
  149. package/dist/features/ai/use-ai-assistant.js.map +1 -1
  150. package/dist/features/ai/use-model-profiles.d.ts +4 -4
  151. package/dist/features/ai/use-model-profiles.js +2 -2
  152. package/dist/features/ai/use-model-profiles.js.map +1 -1
  153. package/dist/features/block-ui/block-actions.d.ts +8 -4
  154. package/dist/features/block-ui/block-actions.js +38 -22
  155. package/dist/features/block-ui/block-actions.js.map +1 -1
  156. package/dist/features/block-ui/block-target.d.ts +29 -0
  157. package/dist/features/block-ui/block-target.js +63 -0
  158. package/dist/features/block-ui/block-target.js.map +1 -0
  159. package/dist/features/block-ui/components/BlockHandles.js +3 -3
  160. package/dist/features/block-ui/components/BlockHandles.js.map +1 -1
  161. package/dist/features/block-ui/components/BlockUi.js +11 -23
  162. package/dist/features/block-ui/components/BlockUi.js.map +1 -1
  163. package/dist/features/block-ui/feature.d.ts +3 -2
  164. package/dist/features/block-ui/feature.js +3 -2
  165. package/dist/features/block-ui/feature.js.map +1 -1
  166. package/dist/features/block-ui/handle-geometry.js +12 -23
  167. package/dist/features/block-ui/handle-geometry.js.map +1 -1
  168. package/dist/features/block-ui/index.d.ts +2 -1
  169. package/dist/features/block-ui/index.js +2 -1
  170. package/dist/features/block-ui/react/BlockHandles.d.ts +1 -1
  171. package/dist/features/block-ui/react/BlockHandles.js +4 -4
  172. package/dist/features/block-ui/react/BlockHandles.js.map +1 -1
  173. package/dist/features/block-ui/react/BlockUi.js +13 -25
  174. package/dist/features/block-ui/react/BlockUi.js.map +1 -1
  175. package/dist/features/comments/model.js +1 -1
  176. package/dist/features/composites/accepted-children.d.ts +5 -4
  177. package/dist/features/composites/accepted-children.js +26 -26
  178. package/dist/features/composites/accepted-children.js.map +1 -1
  179. package/dist/features/composites/ai-brief.d.ts +4 -4
  180. package/dist/features/composites/ai-brief.js +14 -12
  181. package/dist/features/composites/ai-brief.js.map +1 -1
  182. package/dist/features/composites/anchors.d.ts +1 -1
  183. package/dist/features/composites/anchors.js.map +1 -1
  184. package/dist/features/composites/baskets.d.ts +1 -1
  185. package/dist/features/composites/baskets.js.map +1 -1
  186. package/dist/features/composites/bibliography-command.d.ts +1 -1
  187. package/dist/features/composites/bibliography-form.js +1 -1
  188. package/dist/features/composites/bibliography-form.js.map +1 -1
  189. package/dist/features/composites/bibliography.js.map +1 -1
  190. package/dist/features/composites/block-types-json.d.ts +38 -0
  191. package/dist/features/composites/block-types-json.js +122 -0
  192. package/dist/features/composites/block-types-json.js.map +1 -0
  193. package/dist/features/composites/block-types.d.ts +119 -0
  194. package/dist/features/composites/block-types.js +343 -0
  195. package/dist/features/composites/block-types.js.map +1 -0
  196. package/dist/features/composites/capabilities.js +109 -0
  197. package/dist/features/composites/capabilities.js.map +1 -0
  198. package/dist/features/composites/components/BibliographyEditor.js +5 -5
  199. package/dist/features/composites/components/BibliographyEditor.js.map +1 -1
  200. package/dist/features/composites/components/CompositeBasketMenu.js +2 -2
  201. package/dist/features/composites/components/CompositeBasketMenu.js.map +1 -1
  202. package/dist/features/composites/components/CompositeChrome.js +18 -8
  203. package/dist/features/composites/components/CompositeChrome.js.map +1 -1
  204. package/dist/features/composites/components/CompositeChrome.vue.d.ts +1 -1
  205. package/dist/features/composites/components/CompositeDetails.js +11 -10
  206. package/dist/features/composites/components/CompositeDetails.js.map +1 -1
  207. package/dist/features/composites/components/CompositeDetails.vue.d.ts +1 -1
  208. package/dist/features/composites/components/CompositeFieldEditor.js +7 -7
  209. package/dist/features/composites/components/CompositeFieldEditor.js.map +1 -1
  210. package/dist/features/composites/components/CompositeFieldEditor.vue.d.ts +5 -5
  211. package/dist/features/composites/components/CompositeInspector.js +136 -113
  212. package/dist/features/composites/components/CompositeInspector.js.map +1 -1
  213. package/dist/features/composites/components/CompositeInspector.vue.d.ts +3 -3
  214. package/dist/features/composites/components/CompositeStatusMenu.js +2 -2
  215. package/dist/features/composites/components/CompositeStatusMenu.js.map +1 -1
  216. package/dist/features/composites/components/CompositeSummaryEditor.js +1 -1
  217. package/dist/features/composites/components/CompositeSummaryEditor.js.map +1 -1
  218. package/dist/features/composites/components/CompositeSummaryEditor.vue.d.ts +1 -1
  219. package/dist/features/composites/components/CompositeTable.js +2 -2
  220. package/dist/features/composites/components/CompositeTable.js.map +1 -1
  221. package/dist/features/composites/components/CompositeTagsEditor.js +1 -1
  222. package/dist/features/composites/components/CompositeTagsEditor.js.map +1 -1
  223. package/dist/features/composites/components/CompositeTagsEditor.vue.d.ts +1 -1
  224. package/dist/features/composites/components/CompositeView.js +19 -17
  225. package/dist/features/composites/components/CompositeView.js.map +1 -1
  226. package/dist/features/composites/components/DerivationBadge.js +15 -6
  227. package/dist/features/composites/components/DerivationBadge.js.map +1 -1
  228. package/dist/features/composites/components/FocusChip.js +1 -1
  229. package/dist/features/composites/components/FocusChip.js.map +1 -1
  230. package/dist/features/composites/components/FocusChip.vue.d.ts +1 -1
  231. package/dist/features/composites/components/ReferenceFieldSelect.js +3 -3
  232. package/dist/features/composites/components/ReferenceFieldSelect.js.map +1 -1
  233. package/dist/features/composites/components/ReferenceView.js +1 -1
  234. package/dist/features/composites/components/ReferenceView.js.map +1 -1
  235. package/dist/features/composites/components/SettingsEditingTab.js +18 -18
  236. package/dist/features/composites/components/SettingsEditingTab.js.map +1 -1
  237. package/dist/features/composites/components/SettingsEditingTab.vue.d.ts +3 -3
  238. package/dist/features/composites/convert.d.ts +4 -4
  239. package/dist/features/composites/convert.js +27 -28
  240. package/dist/features/composites/convert.js.map +1 -1
  241. package/dist/features/composites/derived-chrome.js +34 -28
  242. package/dist/features/composites/derived-chrome.js.map +1 -1
  243. package/dist/features/composites/editing-settings-keys.js +6 -6
  244. package/dist/features/composites/editing-settings-keys.js.map +1 -1
  245. package/dist/features/composites/feature.d.ts +10 -10
  246. package/dist/features/composites/feature.js +58 -46
  247. package/dist/features/composites/feature.js.map +1 -1
  248. package/dist/features/composites/fences.d.ts +3 -3
  249. package/dist/features/composites/fences.js +18 -13
  250. package/dist/features/composites/fences.js.map +1 -1
  251. package/dist/features/composites/focus.d.ts +10 -10
  252. package/dist/features/composites/focus.js +11 -11
  253. package/dist/features/composites/focus.js.map +1 -1
  254. package/dist/features/composites/heading-composites.d.ts +5 -5
  255. package/dist/features/composites/heading-composites.js +13 -16
  256. package/dist/features/composites/heading-composites.js.map +1 -1
  257. package/dist/features/composites/index.d.ts +20 -18
  258. package/dist/features/composites/index.js +9 -7
  259. package/dist/features/composites/inspector-model.d.ts +45 -22
  260. package/dist/features/composites/inspector-model.js +53 -14
  261. package/dist/features/composites/inspector-model.js.map +1 -1
  262. package/dist/features/composites/legacy.d.ts +5 -4
  263. package/dist/features/composites/legacy.js +16 -23
  264. package/dist/features/composites/legacy.js.map +1 -1
  265. package/dist/features/composites/markdown-export.js +3 -3
  266. package/dist/features/composites/markdown-export.js.map +1 -1
  267. package/dist/features/composites/merge.d.ts +8 -7
  268. package/dist/features/composites/merge.js +39 -12
  269. package/dist/features/composites/merge.js.map +1 -1
  270. package/dist/features/composites/meta-display.js +5 -5
  271. package/dist/features/composites/meta-display.js.map +1 -1
  272. package/dist/features/composites/meta-keys.d.ts +5 -5
  273. package/dist/features/composites/meta-keys.js +8 -8
  274. package/dist/features/composites/meta-keys.js.map +1 -1
  275. package/dist/features/composites/node-views.d.ts +3 -3
  276. package/dist/features/composites/node-views.js +2 -2
  277. package/dist/features/composites/node-views.js.map +1 -1
  278. package/dist/features/composites/nodes.d.ts +13 -13
  279. package/dist/features/composites/nodes.js +100 -77
  280. package/dist/features/composites/nodes.js.map +1 -1
  281. package/dist/features/composites/outline.d.ts +15 -12
  282. package/dist/features/composites/outline.js +24 -21
  283. package/dist/features/composites/outline.js.map +1 -1
  284. package/dist/features/composites/properties.d.ts +51 -0
  285. package/dist/features/composites/properties.js +89 -0
  286. package/dist/features/composites/properties.js.map +1 -0
  287. package/dist/features/composites/react/BibliographyEditor.js +5 -5
  288. package/dist/features/composites/react/BibliographyEditor.js.map +1 -1
  289. package/dist/features/composites/react/CompositeBasketMenu.js +2 -2
  290. package/dist/features/composites/react/CompositeBasketMenu.js.map +1 -1
  291. package/dist/features/composites/react/CompositeChrome.d.ts +1 -1
  292. package/dist/features/composites/react/CompositeChrome.js +15 -6
  293. package/dist/features/composites/react/CompositeChrome.js.map +1 -1
  294. package/dist/features/composites/react/CompositeDetails.d.ts +1 -1
  295. package/dist/features/composites/react/CompositeDetails.js +11 -10
  296. package/dist/features/composites/react/CompositeDetails.js.map +1 -1
  297. package/dist/features/composites/react/CompositeFieldEditor.d.ts +5 -5
  298. package/dist/features/composites/react/CompositeFieldEditor.js +6 -6
  299. package/dist/features/composites/react/CompositeFieldEditor.js.map +1 -1
  300. package/dist/features/composites/react/CompositeInspector.d.ts +3 -3
  301. package/dist/features/composites/react/CompositeInspector.js +142 -128
  302. package/dist/features/composites/react/CompositeInspector.js.map +1 -1
  303. package/dist/features/composites/react/CompositeStatusMenu.js +2 -2
  304. package/dist/features/composites/react/CompositeStatusMenu.js.map +1 -1
  305. package/dist/features/composites/react/CompositeSummaryEditor.d.ts +1 -1
  306. package/dist/features/composites/react/CompositeSummaryEditor.js +1 -1
  307. package/dist/features/composites/react/CompositeSummaryEditor.js.map +1 -1
  308. package/dist/features/composites/react/CompositeTable.d.ts +1 -1
  309. package/dist/features/composites/react/CompositeTable.js +3 -3
  310. package/dist/features/composites/react/CompositeTable.js.map +1 -1
  311. package/dist/features/composites/react/CompositeTagsEditor.d.ts +1 -1
  312. package/dist/features/composites/react/CompositeTagsEditor.js +1 -1
  313. package/dist/features/composites/react/CompositeTagsEditor.js.map +1 -1
  314. package/dist/features/composites/react/CompositeView.js +17 -15
  315. package/dist/features/composites/react/CompositeView.js.map +1 -1
  316. package/dist/features/composites/react/DerivationBadge.js +13 -4
  317. package/dist/features/composites/react/DerivationBadge.js.map +1 -1
  318. package/dist/features/composites/react/FocusChip.d.ts +1 -1
  319. package/dist/features/composites/react/FocusChip.js +1 -1
  320. package/dist/features/composites/react/FocusChip.js.map +1 -1
  321. package/dist/features/composites/react/ReferenceFieldSelect.js +3 -3
  322. package/dist/features/composites/react/ReferenceFieldSelect.js.map +1 -1
  323. package/dist/features/composites/react/ReferenceView.d.ts +1 -1
  324. package/dist/features/composites/react/ReferenceView.js +1 -1
  325. package/dist/features/composites/react/ReferenceView.js.map +1 -1
  326. package/dist/features/composites/react/SettingsEditingTab.d.ts +4 -4
  327. package/dist/features/composites/react/SettingsEditingTab.js +20 -20
  328. package/dist/features/composites/react/SettingsEditingTab.js.map +1 -1
  329. package/dist/features/composites/react.js +1 -1
  330. package/dist/features/composites/react.js.map +1 -1
  331. package/dist/features/composites/reference-ai.js +1 -1
  332. package/dist/features/composites/reference-ai.js.map +1 -1
  333. package/dist/features/composites/reference-label.d.ts +3 -3
  334. package/dist/features/composites/reference-label.js +6 -6
  335. package/dist/features/composites/reference-label.js.map +1 -1
  336. package/dist/features/composites/reference-suggestion.d.ts +1 -1
  337. package/dist/features/composites/reference-suggestion.js +3 -3
  338. package/dist/features/composites/reference-suggestion.js.map +1 -1
  339. package/dist/features/composites/reference-text.d.ts +2 -2
  340. package/dist/features/composites/reference-text.js +4 -4
  341. package/dist/features/composites/reference-text.js.map +1 -1
  342. package/dist/features/composites/reference.d.ts +3 -3
  343. package/dist/features/composites/reference.js +1 -1
  344. package/dist/features/composites/reference.js.map +1 -1
  345. package/dist/features/composites/reveal-source.d.ts +3 -3
  346. package/dist/features/composites/reveal-source.js +6 -6
  347. package/dist/features/composites/reveal-source.js.map +1 -1
  348. package/dist/features/composites/rows-model.d.ts +2 -2
  349. package/dist/features/composites/rows-model.js +4 -3
  350. package/dist/features/composites/rows-model.js.map +1 -1
  351. package/dist/features/composites/rows.d.ts +16 -28
  352. package/dist/features/composites/rows.js +20 -54
  353. package/dist/features/composites/rows.js.map +1 -1
  354. package/dist/features/composites/schema.d.ts +12 -11
  355. package/dist/features/composites/schema.js +10 -9
  356. package/dist/features/composites/schema.js.map +1 -1
  357. package/dist/features/composites/source.d.ts +20 -0
  358. package/dist/features/composites/source.js +40 -0
  359. package/dist/features/composites/source.js.map +1 -0
  360. package/dist/features/composites/split.d.ts +11 -11
  361. package/dist/features/composites/split.js +20 -20
  362. package/dist/features/composites/split.js.map +1 -1
  363. package/dist/features/composites/structure-mode.js +3 -3
  364. package/dist/features/composites/structure-mode.js.map +1 -1
  365. package/dist/features/composites/table-model.js +2 -2
  366. package/dist/features/composites/table-model.js.map +1 -1
  367. package/dist/features/composites/use-composite-inspector.js +3 -1
  368. package/dist/features/composites/use-composite-inspector.js.map +1 -1
  369. package/dist/features/composites/use-composite-rows.d.ts +2 -2
  370. package/dist/features/composites/use-composite-rows.js.map +1 -1
  371. package/dist/features/composites/vue.js +1 -1
  372. package/dist/features/composites/vue.js.map +1 -1
  373. package/dist/features/image-studio/components/ImageStudioDialog.js +1 -1
  374. package/dist/features/image-studio/components/ImageStudioDialog.js.map +1 -1
  375. package/dist/features/image-studio/components/ImageStudioDialog.vue.d.ts +1 -1
  376. package/dist/features/image-studio/components/ImageStudioView.js.map +1 -1
  377. package/dist/features/image-studio/feature.d.ts +1 -1
  378. package/dist/features/image-studio/feature.js +1 -1
  379. package/dist/features/image-studio/feature.js.map +1 -1
  380. package/dist/features/image-studio/node-core.d.ts +3 -3
  381. package/dist/features/image-studio/node-core.js +1 -1
  382. package/dist/features/image-studio/node-core.js.map +1 -1
  383. package/dist/features/image-studio/node-store.d.ts +1 -1
  384. package/dist/features/image-studio/node-store.js +1 -1
  385. package/dist/features/image-studio/node-store.js.map +1 -1
  386. package/dist/features/image-studio/react/ImageStudioDialog.d.ts +1 -1
  387. package/dist/features/image-studio/react/ImageStudioDialog.js +1 -1
  388. package/dist/features/image-studio/react/ImageStudioDialog.js.map +1 -1
  389. package/dist/features/image-studio/react/ImageStudioView.js +1 -1
  390. package/dist/features/image-studio/react/ImageStudioView.js.map +1 -1
  391. package/dist/features/image-studio/react/store.d.ts +3 -3
  392. package/dist/features/image-studio/react/store.js.map +1 -1
  393. package/dist/features/image-studio/react.d.ts +1 -1
  394. package/dist/features/image-studio/react.js +1 -1
  395. package/dist/features/image-studio/react.js.map +1 -1
  396. package/dist/features/image-studio/schema.d.ts +1 -1
  397. package/dist/features/image-studio/schema.js +1 -1
  398. package/dist/features/image-studio/schema.js.map +1 -1
  399. package/dist/features/image-studio/state.d.ts +3 -3
  400. package/dist/features/image-studio/state.js +2 -2
  401. package/dist/features/image-studio/state.js.map +1 -1
  402. package/dist/features/image-studio/store.d.ts +3 -3
  403. package/dist/features/image-studio/vue.d.ts +1 -1
  404. package/dist/features/image-studio/vue.js +1 -1
  405. package/dist/features/image-studio/vue.js.map +1 -1
  406. package/dist/features/media/index.js +1 -1
  407. package/dist/features/media/react/AudioRecorderModal.js +1 -1
  408. package/dist/features/media/react.js +1 -1
  409. package/dist/features/mentions/tag.js +2 -1
  410. package/dist/features/mentions/tag.js.map +1 -1
  411. package/dist/features/themes/components/SettingsAppearanceTab.js +1 -1
  412. package/dist/features/themes/components/SettingsAppearanceTab.js.map +1 -1
  413. package/dist/features/themes/feature.d.ts +1 -1
  414. package/dist/features/themes/feature.js.map +1 -1
  415. package/dist/features/themes/react/SettingsAppearanceTab.d.ts +1 -1
  416. package/dist/features/themes/react/SettingsAppearanceTab.js +1 -1
  417. package/dist/features/themes/react/SettingsAppearanceTab.js.map +1 -1
  418. package/dist/features/themes/theme-runtime.js +1 -1
  419. package/dist/features/themes/theme-runtime.js.map +1 -1
  420. package/dist/features/transcript/TranscriptSegmentView.js +1 -1
  421. package/dist/features/transcript/TranscriptSegmentView.js.map +1 -1
  422. package/dist/features/transcript/react/TranscriptSegmentView.js +1 -1
  423. package/dist/features/transcript/react/TranscriptSegmentView.js.map +1 -1
  424. package/dist/features/transcript/segment-node.js.map +1 -1
  425. package/dist/features/transfer/feature.js +1 -1
  426. package/dist/features/transfer/feature.js.map +1 -1
  427. package/dist/features/transfer/transforms.d.ts +4 -4
  428. package/dist/features/transfer/transforms.js +12 -12
  429. package/dist/features/transfer/transforms.js.map +1 -1
  430. package/dist/i18n/de/ai.js +4 -4
  431. package/dist/i18n/de/ai.js.map +1 -1
  432. package/dist/i18n/de/authors.js +1 -1
  433. package/dist/i18n/de/authors.js.map +1 -1
  434. package/dist/i18n/de/comments.js +1 -1
  435. package/dist/i18n/de/comments.js.map +1 -1
  436. package/dist/i18n/de/composites.js +62 -59
  437. package/dist/i18n/de/composites.js.map +1 -1
  438. package/dist/i18n/de/image-studio.js +2 -2
  439. package/dist/i18n/de/image-studio.js.map +1 -1
  440. package/dist/i18n/de/integrations.js +20 -20
  441. package/dist/i18n/de/integrations.js.map +1 -1
  442. package/dist/i18n/de/markdown.js +1 -1
  443. package/dist/i18n/de/markdown.js.map +1 -1
  444. package/dist/i18n/de/palette.js +1 -1
  445. package/dist/i18n/de/palette.js.map +1 -1
  446. package/dist/i18n/de/themes.js +3 -3
  447. package/dist/i18n/de/themes.js.map +1 -1
  448. package/dist/i18n/de/transfer.js +2 -2
  449. package/dist/i18n/de/transfer.js.map +1 -1
  450. package/dist/i18n/de/tree.js +6 -6
  451. package/dist/i18n/de/tree.js.map +1 -1
  452. package/dist/i18n/de.d.ts +101 -98
  453. package/dist/i18n/en/ai.js +2 -2
  454. package/dist/i18n/en/ai.js.map +1 -1
  455. package/dist/i18n/en/composites.js +64 -61
  456. package/dist/i18n/en/composites.js.map +1 -1
  457. package/dist/i18n/en/integrations.js +9 -9
  458. package/dist/i18n/en/integrations.js.map +1 -1
  459. package/dist/i18n/en/markdown.js +1 -1
  460. package/dist/i18n/en/markdown.js.map +1 -1
  461. package/dist/i18n/en/palette.js +1 -1
  462. package/dist/i18n/en/palette.js.map +1 -1
  463. package/dist/i18n/en/themes.js +4 -4
  464. package/dist/i18n/en/themes.js.map +1 -1
  465. package/dist/i18n/en/tree.js +5 -5
  466. package/dist/i18n/en/tree.js.map +1 -1
  467. package/dist/index.d.ts +4 -1
  468. package/dist/integrations/composite-ai/bibliography-fetch.d.ts +6 -6
  469. package/dist/integrations/composite-ai/bibliography-fetch.js +19 -19
  470. package/dist/integrations/composite-ai/bibliography-fetch.js.map +1 -1
  471. package/dist/integrations/composite-ai/composite-fill.d.ts +4 -4
  472. package/dist/integrations/composite-ai/composite-fill.js +5 -5
  473. package/dist/integrations/composite-ai/composite-fill.js.map +1 -1
  474. package/dist/integrations/composite-ai/composite-summary.d.ts +2 -2
  475. package/dist/integrations/composite-ai/composite-summary.js +5 -5
  476. package/dist/integrations/composite-ai/composite-summary.js.map +1 -1
  477. package/dist/integrations/composite-ai/derive.d.ts +17 -17
  478. package/dist/integrations/composite-ai/derive.js +27 -26
  479. package/dist/integrations/composite-ai/derive.js.map +1 -1
  480. package/dist/integrations/composite-ai/index.d.ts +14 -15
  481. package/dist/integrations/composite-ai/index.js +98 -77
  482. package/dist/integrations/composite-ai/index.js.map +1 -1
  483. package/dist/integrations/composite-ai/outline-sanitize.d.ts +1 -1
  484. package/dist/integrations/composite-ai/outline-sanitize.js +1 -1
  485. package/dist/integrations/composite-ai/outline-sanitize.js.map +1 -1
  486. package/dist/integrations/composite-ai/rendition.d.ts +9 -9
  487. package/dist/integrations/composite-ai/rendition.js +27 -27
  488. package/dist/integrations/composite-ai/rendition.js.map +1 -1
  489. package/dist/integrations/composite-ai/split.d.ts +8 -8
  490. package/dist/integrations/composite-ai/split.js +12 -12
  491. package/dist/integrations/composite-ai/split.js.map +1 -1
  492. package/dist/integrations/composite-ai/transfer-transforms.d.ts +2 -2
  493. package/dist/integrations/composite-ai/transfer-transforms.js +12 -12
  494. package/dist/integrations/composite-ai/transfer-transforms.js.map +1 -1
  495. package/dist/integrations/composite-media/index.d.ts +4 -3
  496. package/dist/integrations/composite-media/index.js +20 -14
  497. package/dist/integrations/composite-media/index.js.map +1 -1
  498. package/dist/markdown/MarkdownSurface.vue.d.ts +7 -7
  499. package/dist/markdown/document.js +1 -1
  500. package/dist/markdown/document.js.map +1 -1
  501. package/dist/nuxt/module.d.ts +30 -24
  502. package/dist/nuxt/module.js.map +1 -1
  503. package/dist/nuxt/runtime/server/plugins/editor-server.js +3 -2
  504. package/dist/nuxt/runtime/server/plugins/editor-server.js.map +1 -1
  505. package/dist/presets/compose.d.ts +6 -6
  506. package/dist/presets/compose.js +8 -5
  507. package/dist/presets/compose.js.map +1 -1
  508. package/dist/react/AdvancedEditor.d.ts +2 -2
  509. package/dist/react/AdvancedEditor.js +1 -1
  510. package/dist/react/AdvancedEditor.js.map +1 -1
  511. package/dist/react/compose.d.ts +1 -1
  512. package/dist/react/compose.js +2 -2
  513. package/dist/react/compose.js.map +1 -1
  514. package/dist/react/composed-surface.d.ts +5 -5
  515. package/dist/react/composed-surface.js +2 -2
  516. package/dist/react/composed-surface.js.map +1 -1
  517. package/dist/server/ai.d.ts +7 -7
  518. package/dist/server/ai.js +1 -1
  519. package/dist/server/ai.js.map +1 -1
  520. package/dist/server/auth.d.ts +1 -1
  521. package/dist/server/collab-state.d.ts +1 -1
  522. package/dist/server/collab-state.js.map +1 -1
  523. package/dist/server/collab.d.ts +4 -4
  524. package/dist/server/collab.js +22 -17
  525. package/dist/server/collab.js.map +1 -1
  526. package/dist/server/handlers/ai.d.ts +9 -6
  527. package/dist/server/handlers/ai.js +13 -17
  528. package/dist/server/handlers/ai.js.map +1 -1
  529. package/dist/server/handlers/context.d.ts +4 -0
  530. package/dist/server/handlers/context.js.map +1 -1
  531. package/dist/server/handlers/editor.d.ts +33 -32
  532. package/dist/server/handlers/editor.js +13 -8
  533. package/dist/server/handlers/editor.js.map +1 -1
  534. package/dist/server/handlers/images.d.ts +1 -1
  535. package/dist/server/handlers/images.js +1 -1
  536. package/dist/server/handlers/images.js.map +1 -1
  537. package/dist/server/host.d.ts +4 -0
  538. package/dist/server/host.js +10 -2
  539. package/dist/server/host.js.map +1 -1
  540. package/dist/server/index.d.ts +3 -3
  541. package/dist/server/ports.d.ts +8 -8
  542. package/dist/server/ports.js.map +1 -1
  543. package/dist/settings/index.d.ts +20 -19
  544. package/dist/settings/index.js +25 -24
  545. package/dist/settings/index.js.map +1 -1
  546. package/dist/settings/migrate.d.ts +18 -0
  547. package/dist/settings/migrate.js +46 -0
  548. package/dist/settings/migrate.js.map +1 -0
  549. package/dist/settings/values.d.ts +12 -12
  550. package/dist/settings/values.js +11 -11
  551. package/dist/settings/values.js.map +1 -1
  552. package/dist/styles/composites.css +10 -10
  553. package/dist/tree/DocumentTree.js +12 -5
  554. package/dist/tree/DocumentTree.js.map +1 -1
  555. package/dist/tree/drop-rules.js +5 -5
  556. package/dist/tree/drop-rules.js.map +1 -1
  557. package/dist/tree/react/DocumentTree.js +14 -5
  558. package/dist/tree/react/DocumentTree.js.map +1 -1
  559. package/dist/tree/tree-host.js +6 -6
  560. package/dist/tree/tree-host.js.map +1 -1
  561. package/dist/tree/tree-items.js +34 -28
  562. package/dist/tree/tree-items.js.map +1 -1
  563. package/dist/tree/tree-model.js +16 -16
  564. package/dist/tree/tree-model.js.map +1 -1
  565. package/dist/tree/tree-rows.js +2 -2
  566. package/dist/tree/tree-rows.js.map +1 -1
  567. package/dist/tree/tree-view-model.d.ts +2 -2
  568. package/dist/tree/tree-view-model.js.map +1 -1
  569. package/dist/vue/AdvancedEditor.js +2 -2
  570. package/dist/vue/AdvancedEditor.js.map +1 -1
  571. package/dist/vue/AdvancedEditor.vue.d.ts +10 -10
  572. package/dist/vue/SimpleEditor.vue.d.ts +4 -4
  573. package/dist/vue/components/EditorSurface.vue.d.ts +4 -4
  574. package/dist/vue/compose.d.ts +1 -1
  575. package/dist/vue/compose.js +2 -2
  576. package/dist/vue/compose.js.map +1 -1
  577. package/package.json +1 -1
  578. package/dist/features/composites/derivation.d.ts +0 -62
  579. package/dist/features/composites/derivation.js +0 -102
  580. package/dist/features/composites/derivation.js.map +0 -1
  581. package/dist/features/composites/kinds.d.ts +0 -83
  582. package/dist/features/composites/kinds.js +0 -285
  583. package/dist/features/composites/kinds.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"reveal-source.js","names":[],"sources":["../../../src/features/composites/reveal-source.ts"],"sourcesContent":["// Client-only: show a Baustein's source (the media block of a source-holding kind) at a spot. A time seeks and plays the\n// audio/video; a page number reloads the PDF viewer at that page. Composites must not import media or transcript, so\n// `seekSource` is also registered as an editor command (`SourceReveal`) for the transcript node view to call.\nimport { Extension, type Editor } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { blockIdOf, findBlockById } from '../../core/schema'\nimport { sourceOf } from './derivation'\nimport { compositeKindsOf } from './nodes'\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n sourceReveal: {\n /** Seek and play the media of the source-holding Baustein enclosing `pos` to `seconds`; silent when there is none. */\n seekSource: (pos: number, seconds: number) => ReturnType\n }\n }\n}\n\n/** DOM event the PDF file view listens for; `detail` is the 1-based page to open the viewer at. */\nexport const REVEAL_PAGE_EVENT = 'sk-reveal-page'\n\n/** Where in the source a locator points: a time in seconds (`3:07`) or a PDF page (`S. 12`, `p. 12`, `12`). */\nexport type SourceLocator = { seconds: number } | { page: number }\n\nconst TIME_LOCATOR = /^(\\d+):(\\d{2})$/\nconst PAGE_LOCATOR = /^(?:S\\.|p\\.)?\\s*(\\d+)$/i\n\n/** Parses a reference locator; null for anything that is not a time or a page number. */\nexport function parseLocator(locator: string | null | undefined): SourceLocator | null {\n const text = locator?.trim()\n if (!text) return null\n const time = TIME_LOCATOR.exec(text)\n if (time) return { seconds: Number(time[1]) * 60 + Number(time[2]) }\n const page = PAGE_LOCATOR.exec(text)\n if (page && Number(page[1]) > 0) return { page: Number(page[1]) }\n return null\n}\n\n/** The source block of the composite `composite` at `pos` with its document position, or null. */\nfunction sourceAt(editor: Editor, composite: PMNode, pos: number): { node: PMNode, pos: number } | null {\n const source = sourceOf(composite, compositeKindsOf(editor))\n if (!source) return null\n let sourcePos = pos + 1\n for (let i = 0; i < source.index; i++) sourcePos += composite.child(i).nodeSize\n return { node: source.node, pos: sourcePos }\n}\n\n/** The element of the node view at `pos` that carries the view's own listeners (the framework's wrapper), or null. */\nfunction viewElement(editor: Editor, pos: number): HTMLElement | null {\n const dom = editor.view.nodeDOM(pos)\n if (!(dom instanceof HTMLElement)) return null\n return dom.matches('[data-node-view-wrapper]') ? dom : dom.querySelector<HTMLElement>('[data-node-view-wrapper]') ?? dom\n}\n\nfunction playAt(editor: Editor, sourcePos: number, seconds: number): boolean {\n const dom = editor.view.nodeDOM(sourcePos)\n if (!(dom instanceof HTMLElement)) return false\n const media = dom.matches('audio,video') ? dom as HTMLMediaElement : dom.querySelector<HTMLMediaElement>('audio,video')\n if (!media) return false\n media.currentTime = seconds\n media.play().catch(() => { /* autoplay refused: the seek still happened */ })\n return true\n}\n\n/**\n * Seeks and plays the audio/video of the nearest source-holding Baustein around `pos` (a transcript segment inside a\n * rendition reaches the recording that way). Silent when there is no source or no media element.\n */\nexport function seekSource(editor: Editor, pos: number, seconds: number): void {\n if (!Number.isFinite(seconds) || seconds < 0) return\n const $pos = editor.state.doc.resolve(pos)\n for (let depth = $pos.depth; depth >= 0; depth--) {\n const composite = $pos.node(depth)\n if (composite.type.name !== 'composite') continue\n const source = sourceAt(editor, composite, $pos.before(depth))\n if (!source) continue\n playAt(editor, source.pos, seconds)\n return\n }\n}\n\n/**\n * Shows the source of Baustein `targetId` at `locator`: a `mm:ss` time seeks the media, a page number opens a PDF source\n * at that page; then the source block flashes. Silent when the target or its source is gone.\n */\nexport function revealSource(editor: Editor, targetId: string, locator: string | null): void {\n const target = findBlockById(editor.state.doc, targetId)\n if (!target) return\n const source = sourceAt(editor, target.node, target.pos)\n if (!source) return\n const parsed = parseLocator(locator)\n if (parsed && 'seconds' in parsed) {\n playAt(editor, source.pos, parsed.seconds)\n } else if (parsed && source.node.type.name === 'file' && source.node.attrs.mimeType === 'application/pdf') {\n viewElement(editor, source.pos)?.dispatchEvent(new CustomEvent<number>(REVEAL_PAGE_EVENT, { detail: parsed.page }))\n }\n editor.commands.revealBlock(blockIdOf(source.node) ?? targetId)\n}\n\n/** Registers `seekSource` as an editor command, so features that must not import composites (transcript) can call it. */\nexport const SourceReveal = Extension.create({\n name: 'sourceReveal',\n\n addCommands() {\n return {\n // Does not dispatch: a nested dispatch would leave the command's own transaction stale.\n seekSource: (pos, seconds) => ({ editor }) => {\n seekSource(editor, pos, seconds)\n return true\n },\n }\n },\n})\n"],"mappings":";;;;;;AAmBA,MAAa,oBAAoB;AAKjC,MAAM,eAAe;AACrB,MAAM,eAAe;;AAGrB,SAAgB,aAAa,SAA0D;CACrF,MAAM,OAAO,SAAS,KAAK;CAC3B,IAAI,CAAC,MAAM,OAAO;CAClB,MAAM,OAAO,aAAa,KAAK,IAAI;CACnC,IAAI,MAAM,OAAO,EAAE,SAAS,OAAO,KAAK,EAAE,IAAI,KAAK,OAAO,KAAK,EAAE,EAAE;CACnE,MAAM,OAAO,aAAa,KAAK,IAAI;CACnC,IAAI,QAAQ,OAAO,KAAK,EAAE,IAAI,GAAG,OAAO,EAAE,MAAM,OAAO,KAAK,EAAE,EAAE;CAChE,OAAO;AACT;;AAGA,SAAS,SAAS,QAAgB,WAAmB,KAAmD;CACtG,MAAM,SAAS,SAAS,WAAW,iBAAiB,MAAM,CAAC;CAC3D,IAAI,CAAC,QAAQ,OAAO;CACpB,IAAI,YAAY,MAAM;CACtB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,OAAO,KAAK,aAAa,UAAU,MAAM,CAAC,CAAC,CAAC;CACvE,OAAO;EAAE,MAAM,OAAO;EAAM,KAAK;CAAU;AAC7C;;AAGA,SAAS,YAAY,QAAgB,KAAiC;CACpE,MAAM,MAAM,OAAO,KAAK,QAAQ,GAAG;CACnC,IAAI,EAAE,eAAe,cAAc,OAAO;CAC1C,OAAO,IAAI,QAAQ,0BAA0B,IAAI,MAAM,IAAI,cAA2B,0BAA0B,KAAK;AACvH;AAEA,SAAS,OAAO,QAAgB,WAAmB,SAA0B;CAC3E,MAAM,MAAM,OAAO,KAAK,QAAQ,SAAS;CACzC,IAAI,EAAE,eAAe,cAAc,OAAO;CAC1C,MAAM,QAAQ,IAAI,QAAQ,aAAa,IAAI,MAA0B,IAAI,cAAgC,aAAa;CACtH,IAAI,CAAC,OAAO,OAAO;CACnB,MAAM,cAAc;CACpB,MAAM,KAAK,CAAC,CAAC,YAAY,CAAkD,CAAC;CAC5E,OAAO;AACT;;;;;AAMA,SAAgB,WAAW,QAAgB,KAAa,SAAuB;CAC7E,IAAI,CAAC,OAAO,SAAS,OAAO,KAAK,UAAU,GAAG;CAC9C,MAAM,OAAO,OAAO,MAAM,IAAI,QAAQ,GAAG;CACzC,KAAK,IAAI,QAAQ,KAAK,OAAO,SAAS,GAAG,SAAS;EAChD,MAAM,YAAY,KAAK,KAAK,KAAK;EACjC,IAAI,UAAU,KAAK,SAAS,aAAa;EACzC,MAAM,SAAS,SAAS,QAAQ,WAAW,KAAK,OAAO,KAAK,CAAC;EAC7D,IAAI,CAAC,QAAQ;EACb,OAAO,QAAQ,OAAO,KAAK,OAAO;EAClC;CACF;AACF;;;;;AAMA,SAAgB,aAAa,QAAgB,UAAkB,SAA8B;CAC3F,MAAM,SAAS,cAAc,OAAO,MAAM,KAAK,QAAQ;CACvD,IAAI,CAAC,QAAQ;CACb,MAAM,SAAS,SAAS,QAAQ,OAAO,MAAM,OAAO,GAAG;CACvD,IAAI,CAAC,QAAQ;CACb,MAAM,SAAS,aAAa,OAAO;CACnC,IAAI,UAAU,aAAa,QACzB,OAAO,QAAQ,OAAO,KAAK,OAAO,OAAO;MACpC,IAAI,UAAU,OAAO,KAAK,KAAK,SAAS,UAAU,OAAO,KAAK,MAAM,aAAa,mBACtF,YAAY,QAAQ,OAAO,GAAG,CAAC,EAAE,cAAc,IAAI,YAAoB,mBAAmB,EAAE,QAAQ,OAAO,KAAK,CAAC,CAAC;CAEpH,OAAO,SAAS,YAAY,UAAU,OAAO,IAAI,KAAK,QAAQ;AAChE;;AAGA,MAAa,eAAe,UAAU,OAAO;CAC3C,MAAM;CAEN,cAAc;EACZ,OAAO,EAEL,aAAa,KAAK,aAAa,EAAE,aAAa;GAC5C,WAAW,QAAQ,KAAK,OAAO;GAC/B,OAAO;EACT,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"reveal-source.js","names":[],"sources":["../../../src/features/composites/reveal-source.ts"],"sourcesContent":["// Client-only: show a Typed block's source (the media block of a source-holding Block type) at a spot. A time seeks and plays the\n// audio/video; a page number reloads the PDF viewer at that page. Composites must not import media or transcript, so\n// `seekSource` is also registered as an editor command (`SourceReveal`) for the transcript node view to call.\nimport { Extension, type Editor } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { blockIdOf, findBlockById } from '../../core/schema'\nimport { sourceOf } from './source'\nimport { blockTypesOf } from './nodes'\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n sourceReveal: {\n /** Seek and play the media of the source-holding Typed block enclosing `pos` to `seconds`; silent when there is none. */\n seekSource: (pos: number, seconds: number) => ReturnType\n }\n }\n}\n\n/** DOM event the PDF file view listens for; `detail` is the 1-based page to open the viewer at. */\nexport const REVEAL_PAGE_EVENT = 'sk-reveal-page'\n\n/** Where in the source a locator points: a time in seconds (`3:07`) or a PDF page (`S. 12`, `p. 12`, `12`). */\nexport type SourceLocator = { seconds: number } | { page: number }\n\nconst TIME_LOCATOR = /^(\\d+):(\\d{2})$/\nconst PAGE_LOCATOR = /^(?:S\\.|p\\.)?\\s*(\\d+)$/i\n\n/** Parses a reference locator; null for anything that is not a time or a page number. */\nexport function parseLocator(locator: string | null | undefined): SourceLocator | null {\n const text = locator?.trim()\n if (!text) return null\n const time = TIME_LOCATOR.exec(text)\n if (time) return { seconds: Number(time[1]) * 60 + Number(time[2]) }\n const page = PAGE_LOCATOR.exec(text)\n if (page && Number(page[1]) > 0) return { page: Number(page[1]) }\n return null\n}\n\n/** The source block of the composite `composite` at `pos` with its document position, or null. */\nfunction sourceAt(editor: Editor, composite: PMNode, pos: number): { node: PMNode, pos: number } | null {\n const source = sourceOf(composite, blockTypesOf(editor))\n if (!source) return null\n let sourcePos = pos + 1\n for (let i = 0; i < source.index; i++) sourcePos += composite.child(i).nodeSize\n return { node: source.node, pos: sourcePos }\n}\n\n/** The element of the node view at `pos` that carries the view's own listeners (the framework's wrapper), or null. */\nfunction viewElement(editor: Editor, pos: number): HTMLElement | null {\n const dom = editor.view.nodeDOM(pos)\n if (!(dom instanceof HTMLElement)) return null\n return dom.matches('[data-node-view-wrapper]') ? dom : dom.querySelector<HTMLElement>('[data-node-view-wrapper]') ?? dom\n}\n\nfunction playAt(editor: Editor, sourcePos: number, seconds: number): boolean {\n const dom = editor.view.nodeDOM(sourcePos)\n if (!(dom instanceof HTMLElement)) return false\n const media = dom.matches('audio,video') ? dom as HTMLMediaElement : dom.querySelector<HTMLMediaElement>('audio,video')\n if (!media) return false\n media.currentTime = seconds\n media.play().catch(() => { /* autoplay refused: the seek still happened */ })\n return true\n}\n\n/**\n * Seeks and plays the audio/video of the nearest source-holding Typed block around `pos` (a transcript segment inside a\n * rendition reaches the recording that way). Silent when there is no source or no media element.\n */\nexport function seekSource(editor: Editor, pos: number, seconds: number): void {\n if (!Number.isFinite(seconds) || seconds < 0) return\n const $pos = editor.state.doc.resolve(pos)\n for (let depth = $pos.depth; depth >= 0; depth--) {\n const composite = $pos.node(depth)\n if (composite.type.name !== 'typedBlock') continue\n const source = sourceAt(editor, composite, $pos.before(depth))\n if (!source) continue\n playAt(editor, source.pos, seconds)\n return\n }\n}\n\n/**\n * Shows the source of Typed block `targetId` at `locator`: a `mm:ss` time seeks the media, a page number opens a PDF source\n * at that page; then the source block flashes. Silent when the target or its source is gone.\n */\nexport function revealSource(editor: Editor, targetId: string, locator: string | null): void {\n const target = findBlockById(editor.state.doc, targetId)\n if (!target) return\n const source = sourceAt(editor, target.node, target.pos)\n if (!source) return\n const parsed = parseLocator(locator)\n if (parsed && 'seconds' in parsed) {\n playAt(editor, source.pos, parsed.seconds)\n } else if (parsed && source.node.type.name === 'file' && source.node.attrs.mimeType === 'application/pdf') {\n viewElement(editor, source.pos)?.dispatchEvent(new CustomEvent<number>(REVEAL_PAGE_EVENT, { detail: parsed.page }))\n }\n editor.commands.revealBlock(blockIdOf(source.node) ?? targetId)\n}\n\n/** Registers `seekSource` as an editor command, so features that must not import composites (transcript) can call it. */\nexport const SourceReveal = Extension.create({\n name: 'sourceReveal',\n\n addCommands() {\n return {\n // Does not dispatch: a nested dispatch would leave the command's own transaction stale.\n seekSource: (pos, seconds) => ({ editor }) => {\n seekSource(editor, pos, seconds)\n return true\n },\n }\n },\n})\n"],"mappings":";;;;;;AAmBA,MAAa,oBAAoB;AAKjC,MAAM,eAAe;AACrB,MAAM,eAAe;;AAGrB,SAAgB,aAAa,SAA0D;CACrF,MAAM,OAAO,SAAS,KAAK;CAC3B,IAAI,CAAC,MAAM,OAAO;CAClB,MAAM,OAAO,aAAa,KAAK,IAAI;CACnC,IAAI,MAAM,OAAO,EAAE,SAAS,OAAO,KAAK,EAAE,IAAI,KAAK,OAAO,KAAK,EAAE,EAAE;CACnE,MAAM,OAAO,aAAa,KAAK,IAAI;CACnC,IAAI,QAAQ,OAAO,KAAK,EAAE,IAAI,GAAG,OAAO,EAAE,MAAM,OAAO,KAAK,EAAE,EAAE;CAChE,OAAO;AACT;;AAGA,SAAS,SAAS,QAAgB,WAAmB,KAAmD;CACtG,MAAM,SAAS,SAAS,WAAW,aAAa,MAAM,CAAC;CACvD,IAAI,CAAC,QAAQ,OAAO;CACpB,IAAI,YAAY,MAAM;CACtB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,OAAO,KAAK,aAAa,UAAU,MAAM,CAAC,CAAC,CAAC;CACvE,OAAO;EAAE,MAAM,OAAO;EAAM,KAAK;CAAU;AAC7C;;AAGA,SAAS,YAAY,QAAgB,KAAiC;CACpE,MAAM,MAAM,OAAO,KAAK,QAAQ,GAAG;CACnC,IAAI,EAAE,eAAe,cAAc,OAAO;CAC1C,OAAO,IAAI,QAAQ,0BAA0B,IAAI,MAAM,IAAI,cAA2B,0BAA0B,KAAK;AACvH;AAEA,SAAS,OAAO,QAAgB,WAAmB,SAA0B;CAC3E,MAAM,MAAM,OAAO,KAAK,QAAQ,SAAS;CACzC,IAAI,EAAE,eAAe,cAAc,OAAO;CAC1C,MAAM,QAAQ,IAAI,QAAQ,aAAa,IAAI,MAA0B,IAAI,cAAgC,aAAa;CACtH,IAAI,CAAC,OAAO,OAAO;CACnB,MAAM,cAAc;CACpB,MAAM,KAAK,CAAC,CAAC,YAAY,CAAkD,CAAC;CAC5E,OAAO;AACT;;;;;AAMA,SAAgB,WAAW,QAAgB,KAAa,SAAuB;CAC7E,IAAI,CAAC,OAAO,SAAS,OAAO,KAAK,UAAU,GAAG;CAC9C,MAAM,OAAO,OAAO,MAAM,IAAI,QAAQ,GAAG;CACzC,KAAK,IAAI,QAAQ,KAAK,OAAO,SAAS,GAAG,SAAS;EAChD,MAAM,YAAY,KAAK,KAAK,KAAK;EACjC,IAAI,UAAU,KAAK,SAAS,cAAc;EAC1C,MAAM,SAAS,SAAS,QAAQ,WAAW,KAAK,OAAO,KAAK,CAAC;EAC7D,IAAI,CAAC,QAAQ;EACb,OAAO,QAAQ,OAAO,KAAK,OAAO;EAClC;CACF;AACF;;;;;AAMA,SAAgB,aAAa,QAAgB,UAAkB,SAA8B;CAC3F,MAAM,SAAS,cAAc,OAAO,MAAM,KAAK,QAAQ;CACvD,IAAI,CAAC,QAAQ;CACb,MAAM,SAAS,SAAS,QAAQ,OAAO,MAAM,OAAO,GAAG;CACvD,IAAI,CAAC,QAAQ;CACb,MAAM,SAAS,aAAa,OAAO;CACnC,IAAI,UAAU,aAAa,QACzB,OAAO,QAAQ,OAAO,KAAK,OAAO,OAAO;MACpC,IAAI,UAAU,OAAO,KAAK,KAAK,SAAS,UAAU,OAAO,KAAK,MAAM,aAAa,mBACtF,YAAY,QAAQ,OAAO,GAAG,CAAC,EAAE,cAAc,IAAI,YAAoB,mBAAmB,EAAE,QAAQ,OAAO,KAAK,CAAC,CAAC;CAEpH,OAAO,SAAS,YAAY,UAAU,OAAO,IAAI,KAAK,QAAQ;AAChE;;AAGA,MAAa,eAAe,UAAU,OAAO;CAC3C,MAAM;CAEN,cAAc;EACZ,OAAO,EAEL,aAAa,KAAK,aAAa,EAAE,aAAa;GAC5C,WAAW,QAAQ,KAAK,OAAO;GAC/B,OAAO;EACT,EACF;CACF;AACF,CAAC"}
@@ -3,7 +3,7 @@ import { CompositeMention, CompositeRow } from "./rows.js";
3
3
  import { Editor } from "@tiptap/core";
4
4
  //#region src/features/composites/rows-model.d.ts
5
5
  /** A kind in use in the document, with how many composites have it. */
6
- export interface CompositeKindCount {
6
+ export interface BlockTypeCount {
7
7
  id: string;
8
8
  label: string;
9
9
  icon: string;
@@ -16,7 +16,7 @@ export interface CompositeRowsState {
16
16
  /** Distinct tags of all composites, sorted (German collation). */
17
17
  tags: readonly string[];
18
18
  /** Kinds in use with their counts: configured kinds in their configured order, then unknown ones in order of appearance. */
19
- kinds: readonly CompositeKindCount[];
19
+ kinds: readonly BlockTypeCount[];
20
20
  /** Distinct `@mention` chips of the document. */
21
21
  mentions: readonly CompositeMention[];
22
22
  /** The innermost composite around the selection head, `null` outside of any. */
@@ -1,5 +1,6 @@
1
+ import { capabilitiesOf } from "../../core/capabilities.js";
1
2
  import { createStore } from "../../core/store.js";
2
- import { compositeKindsOf } from "./nodes.js";
3
+ import { blockTypesOf } from "./nodes.js";
3
4
  import { compositeRowAt, compositeRows } from "./rows.js";
4
5
  //#region src/features/composites/rows-model.ts
5
6
  const EMPTY = {
@@ -42,7 +43,7 @@ function createCompositeRows(editor) {
42
43
  state: store,
43
44
  dispose() {}
44
45
  };
45
- const kinds = compositeKindsOf(editor);
46
+ const kinds = blockTypesOf(editor);
46
47
  const order = kinds.map((kind) => kind.id);
47
48
  let frame = 0;
48
49
  let lastDoc;
@@ -54,7 +55,7 @@ function createCompositeRows(editor) {
54
55
  const current = store.get();
55
56
  if (doc !== lastDoc) {
56
57
  lastDoc = doc;
57
- const read = compositeRows(doc, kinds);
58
+ const read = compositeRows(doc, kinds, (node) => capabilitiesOf(editor, node));
58
59
  store.set({
59
60
  rows: read.rows,
60
61
  tags: tagsOf(read.rows),
@@ -1 +1 @@
1
- {"version":3,"file":"rows-model.js","names":[],"sources":["../../../src/features/composites/rows-model.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { createStore, type ReadonlyStore } from '../../core/store'\nimport { compositeKindsOf } from './nodes'\nimport { type CompositeMention, type CompositeRow, compositeRowAt, compositeRows } from './rows'\n\n/** A kind in use in the document, with how many composites have it. */\nexport interface CompositeKindCount {\n id: string\n label: string\n icon: string\n count: number\n}\n\n/** The live metadata read model of an editor's document (see `createCompositeRows`). */\nexport interface CompositeRowsState {\n /** Every composite in document order. */\n rows: readonly CompositeRow[]\n /** Distinct tags of all composites, sorted (German collation). */\n tags: readonly string[]\n /** Kinds in use with their counts: configured kinds in their configured order, then unknown ones in order of appearance. */\n kinds: readonly CompositeKindCount[]\n /** Distinct `@mention` chips of the document. */\n mentions: readonly CompositeMention[]\n /** The innermost composite around the selection head, `null` outside of any. */\n focused: CompositeRow | null\n}\n\n/** The composites of an editor's document as an observable state; `dispose()` detaches the editor listener (idempotent). */\nexport interface CompositeRowsHandle {\n readonly state: ReadonlyStore<CompositeRowsState>\n dispose: () => void\n}\n\nconst EMPTY: CompositeRowsState = { rows: [], tags: [], kinds: [], mentions: [], focused: null }\n\nfunction tagsOf(rows: readonly CompositeRow[]): string[] {\n return [...new Set(rows.flatMap(row => row.tags))].sort((a, b) => a.localeCompare(b, 'de'))\n}\n\nfunction kindCounts(rows: readonly CompositeRow[], order: readonly string[]): CompositeKindCount[] {\n const counts = new Map<string, CompositeKindCount>()\n for (const row of rows) {\n const entry = counts.get(row.kind)\n if (entry) entry.count++\n else counts.set(row.kind, { id: row.kind, label: row.kindLabel, icon: row.icon, count: 1 })\n }\n const rank = (id: string) => {\n const index = order.indexOf(id)\n return index < 0 ? order.length : index\n }\n // Array.sort is stable: unknown kinds (equal rank) keep their order of appearance.\n return [...counts.values()].sort((a, b) => rank(a.id) - rank(b.id))\n}\n\n/**\n * The composites of `editor`'s document as rows, kept current: re-read once per animation frame after a transaction\n * that changed the document (a selection-only change just moves `focused`). A missing or destroyed editor yields empty\n * lists. Create one model per editor (a framework hook follows an editor that changes). Use the `setComposite*` helpers\n * to write.\n */\nexport function createCompositeRows(editor: Editor | undefined): CompositeRowsHandle {\n const store = createStore<CompositeRowsState>(EMPTY)\n if (!editor || editor.isDestroyed) return { state: store, dispose() {} }\n\n const kinds = compositeKindsOf(editor)\n const order = kinds.map(kind => kind.id)\n let frame = 0\n let lastDoc: PMNode | undefined\n let disposed = false\n\n const run = () => {\n frame = 0\n if (disposed || editor.isDestroyed) return\n const { doc, selection } = editor.state\n const current = store.get()\n if (doc !== lastDoc) {\n lastDoc = doc\n const read = compositeRows(doc, kinds)\n store.set({\n rows: read.rows,\n tags: tagsOf(read.rows),\n kinds: kindCounts(read.rows, order),\n mentions: read.mentions,\n focused: compositeRowAt(read.rows, selection.head),\n })\n return\n }\n const focused = compositeRowAt(current.rows, selection.head)\n if (focused !== current.focused) store.set({ ...current, focused })\n }\n const schedule = () => {\n if (!frame) frame = requestAnimationFrame(run)\n }\n\n run()\n editor.on('transaction', schedule)\n\n return {\n state: store,\n dispose() {\n if (disposed) return\n disposed = true\n editor.off('transaction', schedule)\n if (frame) cancelAnimationFrame(frame)\n frame = 0\n },\n }\n}\n"],"mappings":";;;;AAkCA,MAAM,QAA4B;CAAE,MAAM,CAAC;CAAG,MAAM,CAAC;CAAG,OAAO,CAAC;CAAG,UAAU,CAAC;CAAG,SAAS;AAAK;AAE/F,SAAS,OAAO,MAAyC;CACvD,OAAO,CAAC,GAAG,IAAI,IAAI,KAAK,SAAQ,QAAO,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;AAC5F;AAEA,SAAS,WAAW,MAA+B,OAAgD;CACjG,MAAM,yBAAS,IAAI,IAAgC;CACnD,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,QAAQ,OAAO,IAAI,IAAI,IAAI;EACjC,IAAI,OAAO,MAAM;OACZ,OAAO,IAAI,IAAI,MAAM;GAAE,IAAI,IAAI;GAAM,OAAO,IAAI;GAAW,MAAM,IAAI;GAAM,OAAO;EAAE,CAAC;CAC5F;CACA,MAAM,QAAQ,OAAe;EAC3B,MAAM,QAAQ,MAAM,QAAQ,EAAE;EAC9B,OAAO,QAAQ,IAAI,MAAM,SAAS;CACpC;CAEA,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,KAAK,EAAE,EAAE,IAAI,KAAK,EAAE,EAAE,CAAC;AACpE;;;;;;;AAQA,SAAgB,oBAAoB,QAAiD;CACnF,MAAM,QAAQ,YAAgC,KAAK;CACnD,IAAI,CAAC,UAAU,OAAO,aAAa,OAAO;EAAE,OAAO;EAAO,UAAU,CAAC;CAAE;CAEvE,MAAM,QAAQ,iBAAiB,MAAM;CACrC,MAAM,QAAQ,MAAM,KAAI,SAAQ,KAAK,EAAE;CACvC,IAAI,QAAQ;CACZ,IAAI;CACJ,IAAI,WAAW;CAEf,MAAM,YAAY;EAChB,QAAQ;EACR,IAAI,YAAY,OAAO,aAAa;EACpC,MAAM,EAAE,KAAK,cAAc,OAAO;EAClC,MAAM,UAAU,MAAM,IAAI;EAC1B,IAAI,QAAQ,SAAS;GACnB,UAAU;GACV,MAAM,OAAO,cAAc,KAAK,KAAK;GACrC,MAAM,IAAI;IACR,MAAM,KAAK;IACX,MAAM,OAAO,KAAK,IAAI;IACtB,OAAO,WAAW,KAAK,MAAM,KAAK;IAClC,UAAU,KAAK;IACf,SAAS,eAAe,KAAK,MAAM,UAAU,IAAI;GACnD,CAAC;GACD;EACF;EACA,MAAM,UAAU,eAAe,QAAQ,MAAM,UAAU,IAAI;EAC3D,IAAI,YAAY,QAAQ,SAAS,MAAM,IAAI;GAAE,GAAG;GAAS;EAAQ,CAAC;CACpE;CACA,MAAM,iBAAiB;EACrB,IAAI,CAAC,OAAO,QAAQ,sBAAsB,GAAG;CAC/C;CAEA,IAAI;CACJ,OAAO,GAAG,eAAe,QAAQ;CAEjC,OAAO;EACL,OAAO;EACP,UAAU;GACR,IAAI,UAAU;GACd,WAAW;GACX,OAAO,IAAI,eAAe,QAAQ;GAClC,IAAI,OAAO,qBAAqB,KAAK;GACrC,QAAQ;EACV;CACF;AACF"}
1
+ {"version":3,"file":"rows-model.js","names":[],"sources":["../../../src/features/composites/rows-model.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { capabilitiesOf } from '../../core/capabilities'\nimport { createStore, type ReadonlyStore } from '../../core/store'\nimport { blockTypesOf } from './nodes'\nimport { type CompositeMention, type CompositeRow, compositeRowAt, compositeRows } from './rows'\n\n/** A kind in use in the document, with how many composites have it. */\nexport interface BlockTypeCount {\n id: string\n label: string\n icon: string\n count: number\n}\n\n/** The live metadata read model of an editor's document (see `createCompositeRows`). */\nexport interface CompositeRowsState {\n /** Every composite in document order. */\n rows: readonly CompositeRow[]\n /** Distinct tags of all composites, sorted (German collation). */\n tags: readonly string[]\n /** Kinds in use with their counts: configured kinds in their configured order, then unknown ones in order of appearance. */\n kinds: readonly BlockTypeCount[]\n /** Distinct `@mention` chips of the document. */\n mentions: readonly CompositeMention[]\n /** The innermost composite around the selection head, `null` outside of any. */\n focused: CompositeRow | null\n}\n\n/** The composites of an editor's document as an observable state; `dispose()` detaches the editor listener (idempotent). */\nexport interface CompositeRowsHandle {\n readonly state: ReadonlyStore<CompositeRowsState>\n dispose: () => void\n}\n\nconst EMPTY: CompositeRowsState = { rows: [], tags: [], kinds: [], mentions: [], focused: null }\n\nfunction tagsOf(rows: readonly CompositeRow[]): string[] {\n return [...new Set(rows.flatMap(row => row.tags))].sort((a, b) => a.localeCompare(b, 'de'))\n}\n\nfunction kindCounts(rows: readonly CompositeRow[], order: readonly string[]): BlockTypeCount[] {\n const counts = new Map<string, BlockTypeCount>()\n for (const row of rows) {\n const entry = counts.get(row.kind)\n if (entry) entry.count++\n else counts.set(row.kind, { id: row.kind, label: row.kindLabel, icon: row.icon, count: 1 })\n }\n const rank = (id: string) => {\n const index = order.indexOf(id)\n return index < 0 ? order.length : index\n }\n // Array.sort is stable: unknown kinds (equal rank) keep their order of appearance.\n return [...counts.values()].sort((a, b) => rank(a.id) - rank(b.id))\n}\n\n/**\n * The composites of `editor`'s document as rows, kept current: re-read once per animation frame after a transaction\n * that changed the document (a selection-only change just moves `focused`). A missing or destroyed editor yields empty\n * lists. Create one model per editor (a framework hook follows an editor that changes). Use the `setComposite*` helpers\n * to write.\n */\nexport function createCompositeRows(editor: Editor | undefined): CompositeRowsHandle {\n const store = createStore<CompositeRowsState>(EMPTY)\n if (!editor || editor.isDestroyed) return { state: store, dispose() {} }\n\n const kinds = blockTypesOf(editor)\n const order = kinds.map(kind => kind.id)\n let frame = 0\n let lastDoc: PMNode | undefined\n let disposed = false\n\n const run = () => {\n frame = 0\n if (disposed || editor.isDestroyed) return\n const { doc, selection } = editor.state\n const current = store.get()\n if (doc !== lastDoc) {\n lastDoc = doc\n const read = compositeRows(doc, kinds, node => capabilitiesOf(editor, node))\n store.set({\n rows: read.rows,\n tags: tagsOf(read.rows),\n kinds: kindCounts(read.rows, order),\n mentions: read.mentions,\n focused: compositeRowAt(read.rows, selection.head),\n })\n return\n }\n const focused = compositeRowAt(current.rows, selection.head)\n if (focused !== current.focused) store.set({ ...current, focused })\n }\n const schedule = () => {\n if (!frame) frame = requestAnimationFrame(run)\n }\n\n run()\n editor.on('transaction', schedule)\n\n return {\n state: store,\n dispose() {\n if (disposed) return\n disposed = true\n editor.off('transaction', schedule)\n if (frame) cancelAnimationFrame(frame)\n frame = 0\n },\n }\n}\n"],"mappings":";;;;;AAmCA,MAAM,QAA4B;CAAE,MAAM,CAAC;CAAG,MAAM,CAAC;CAAG,OAAO,CAAC;CAAG,UAAU,CAAC;CAAG,SAAS;AAAK;AAE/F,SAAS,OAAO,MAAyC;CACvD,OAAO,CAAC,GAAG,IAAI,IAAI,KAAK,SAAQ,QAAO,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;AAC5F;AAEA,SAAS,WAAW,MAA+B,OAA4C;CAC7F,MAAM,yBAAS,IAAI,IAA4B;CAC/C,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,QAAQ,OAAO,IAAI,IAAI,IAAI;EACjC,IAAI,OAAO,MAAM;OACZ,OAAO,IAAI,IAAI,MAAM;GAAE,IAAI,IAAI;GAAM,OAAO,IAAI;GAAW,MAAM,IAAI;GAAM,OAAO;EAAE,CAAC;CAC5F;CACA,MAAM,QAAQ,OAAe;EAC3B,MAAM,QAAQ,MAAM,QAAQ,EAAE;EAC9B,OAAO,QAAQ,IAAI,MAAM,SAAS;CACpC;CAEA,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,KAAK,EAAE,EAAE,IAAI,KAAK,EAAE,EAAE,CAAC;AACpE;;;;;;;AAQA,SAAgB,oBAAoB,QAAiD;CACnF,MAAM,QAAQ,YAAgC,KAAK;CACnD,IAAI,CAAC,UAAU,OAAO,aAAa,OAAO;EAAE,OAAO;EAAO,UAAU,CAAC;CAAE;CAEvE,MAAM,QAAQ,aAAa,MAAM;CACjC,MAAM,QAAQ,MAAM,KAAI,SAAQ,KAAK,EAAE;CACvC,IAAI,QAAQ;CACZ,IAAI;CACJ,IAAI,WAAW;CAEf,MAAM,YAAY;EAChB,QAAQ;EACR,IAAI,YAAY,OAAO,aAAa;EACpC,MAAM,EAAE,KAAK,cAAc,OAAO;EAClC,MAAM,UAAU,MAAM,IAAI;EAC1B,IAAI,QAAQ,SAAS;GACnB,UAAU;GACV,MAAM,OAAO,cAAc,KAAK,QAAO,SAAQ,eAAe,QAAQ,IAAI,CAAC;GAC3E,MAAM,IAAI;IACR,MAAM,KAAK;IACX,MAAM,OAAO,KAAK,IAAI;IACtB,OAAO,WAAW,KAAK,MAAM,KAAK;IAClC,UAAU,KAAK;IACf,SAAS,eAAe,KAAK,MAAM,UAAU,IAAI;GACnD,CAAC;GACD;EACF;EACA,MAAM,UAAU,eAAe,QAAQ,MAAM,UAAU,IAAI;EAC3D,IAAI,YAAY,QAAQ,SAAS,MAAM,IAAI;GAAE,GAAG;GAAS;EAAQ,CAAC;CACpE;CACA,MAAM,iBAAiB;EACrB,IAAI,CAAC,OAAO,QAAQ,sBAAsB,GAAG;CAC/C;CAEA,IAAI;CACJ,OAAO,GAAG,eAAe,QAAQ;CAEjC,OAAO;EACL,OAAO;EACP,UAAU;GACR,IAAI,UAAU;GACd,WAAW;GACX,OAAO,IAAI,eAAe,QAAQ;GAClC,IAAI,OAAO,qBAAqB,KAAK;GACrC,QAAQ;EACV;CACF;AACF"}
@@ -1,14 +1,10 @@
1
- import { CompositeKind, CompositeMetaField } from "./kinds.js";
1
+ import { BlockType } from "./block-types.js";
2
+ import { BlockProperties } from "./properties.js";
2
3
  import { Editor } from "@tiptap/core";
3
4
  import { Node as Node$1 } from "@tiptap/pm/model";
4
5
  //#region src/features/composites/rows.d.ts
5
- /** One composite („Baustein“) of a document with its metadata, flattened in document order. */
6
- export interface CompositeRow {
7
- /** Block ID, or `pos:<pos>` for a composite without one yet; unique within the document. */
8
- key: string;
9
- id: string | null;
10
- /** Position of the composite when the row was read; the write helpers re-resolve it, so a stale value is safe. */
11
- pos: number;
6
+ /** One composite (a Typed block) of a document with its Block properties (`key`, `id`, `pos`, `meta`, `definitions`) and chrome, flattened in document order. */
7
+ export interface CompositeRow extends BlockProperties {
12
8
  /** Position right after the composite, as of when the row was read. */
13
9
  end: number;
14
10
  kind: string;
@@ -24,10 +20,9 @@ export interface CompositeRow {
24
20
  */
25
21
  descriptionTextOnly: boolean;
26
22
  tags: string[];
27
- meta: Record<string, unknown>;
28
- /** The meta fields of the composite's kind. */
29
- fields: readonly CompositeMetaField[];
30
- /** `false` when the composite's kind hides its tag row (`CompositeKind.chrome.tags === false`): chips, the add-tag control and the tags field stay away. */
23
+ /** The block capabilities the composite has (`capabilitiesOf`); the chrome and the inspector offer only what these allow (basket menu, bibliography editor). */
24
+ capabilities: ReadonlySet<string>;
25
+ /** `false` when the composite's kind hides its tag row (`BlockType.chrome.tags === false`): chips, the add-tag control and the tags field stay away. */
31
26
  tagsVisible: boolean;
32
27
  /** `false` when the composite's kind has `chrome.controls === false`: its chrome (basket, status, title visibility, tags, drag handle) is read-only even in an editable editor. */
33
28
  controls: boolean;
@@ -40,11 +35,11 @@ export interface CompositeMention {
40
35
  label: string;
41
36
  color: string | null;
42
37
  }
43
- /** A reference to a Baustein: a `reference` chip in the text of block `from`, or a `reference` field of the Baustein `from`. */
38
+ /** A reference to a Typed block: a `reference` chip in the text of block `from`, or a `reference` field of the Typed block `from`. */
44
39
  export interface CompositeReference {
45
- /** Block ID of the referenced Baustein. */
40
+ /** Block ID of the referenced Typed block. */
46
41
  target: string;
47
- /** Block ID of the nearest block around the chip (the Baustein itself for a field); `null` when that block has no ID yet. */
42
+ /** Block ID of the nearest block around the chip (the Typed block itself for a field); `null` when that block has no ID yet. */
48
43
  from: string | null;
49
44
  /** The chip's locator (`S. 12`, `03:14`); `null` for a field or a chip without one. */
50
45
  locator: string | null;
@@ -52,21 +47,22 @@ export interface CompositeReference {
52
47
  /**
53
48
  * Reads every composite of `doc` (also inside quotes and lists) as a row, in document order, the distinct
54
49
  * `@mention` chips anywhere in the document and every reference (`reference` chips and `reference` fields) in document
55
- * order. Unknown kinds get the `section` kind's presentation under their own ID.
50
+ * order. Unknown kinds get the `section` kind's presentation under their own ID. `capabilitiesOf` answers which block
51
+ * capabilities a composite has (`createCompositeRows` passes the editor's); without it a row has the ones its Block type lists.
56
52
  */
57
- export declare function compositeRows(doc: Node$1, kinds: readonly CompositeKind[]): {
53
+ export declare function compositeRows(doc: Node$1, kinds: readonly BlockType[], capabilitiesOf?: (node: Node$1) => ReadonlySet<string>): {
58
54
  rows: CompositeRow[];
59
55
  mentions: CompositeMention[];
60
56
  references: CompositeReference[];
61
57
  };
62
- /** A place that refers to a Baustein: the block holding the chip (or the Baustein with the field) and a short text of it. */
58
+ /** A place that refers to a Typed block: the block holding the chip (or the Typed block with the field) and a short text of it. */
63
59
  export interface CompositeBacklink {
64
60
  from: string;
65
61
  locator: string | null;
66
62
  excerpt: string;
67
63
  }
68
- /** Every reference to the Baustein `target` in document order; references whose enclosing block has no ID (or is gone) are left out, as nothing could reveal them. */
69
- export declare function compositeBacklinks(doc: Node$1, kinds: readonly CompositeKind[], target: string): CompositeBacklink[];
64
+ /** Every reference to the Typed block `target` in document order; references whose enclosing block has no ID (or is gone) are left out, as nothing could reveal them. */
65
+ export declare function compositeBacklinks(doc: Node$1, kinds: readonly BlockType[], target: string): CompositeBacklink[];
70
66
  /** The innermost row around document position `pos`, `null` outside of any composite. */
71
67
  export declare function compositeRowAt(rows: readonly CompositeRow[], pos: number): CompositeRow | null;
72
68
  /**
@@ -77,14 +73,6 @@ export declare function compositeOfRow(doc: Node$1, row: Pick<CompositeRow, 'id'
77
73
  pos: number;
78
74
  node: Node$1;
79
75
  } | null;
80
- /**
81
- * `meta` with `value` stored under `field.key`: a number field converts a numeric string, an empty value (`''`,
82
- * `null`, `undefined`, `NaN`) removes the key. A `multiselect` field keeps the string entries of an array value and
83
- * removes the key when none is left. Returns a new object; `meta` is not changed.
84
- */
85
- export declare function compositeMetaWith(meta: Record<string, unknown>, field: Pick<CompositeMetaField, 'key' | 'type'>, value: unknown): Record<string, unknown>;
86
- /** Stores `value` under the meta field `key` of the row's composite (see `compositeMetaWith`), in one transaction. */
87
- export declare function setCompositeMetaField(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos' | 'fields'>, key: string, value: unknown): boolean;
88
76
  /** Replaces the tags row of the row's composite (empty names are dropped), in one transaction. */
89
77
  export declare function setCompositeTags(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos'>, tags: readonly string[]): boolean;
90
78
  /** The text `setCompositeDescription` stores for `text`: the description is one line, so line breaks collapse to spaces. */
@@ -1,8 +1,9 @@
1
1
  import { blockIdOf, findBlockById } from "../../core/schema/block-ids.js";
2
- import { compositeKind } from "./kinds.js";
2
+ import "../../core/schema/persisted-names.js";
3
+ import { blockTypeOf } from "./block-types.js";
4
+ import { blockPropertiesOf } from "./properties.js";
3
5
  import { referenceLabel, referenceTarget } from "./reference-label.js";
4
6
  //#region src/features/composites/rows.ts
5
- const COMPOSITE = "composite";
6
7
  /** True when `node`'s content is empty or text only (with any marks, but no inline nodes such as mentions or tags). */
7
8
  function isTextOnly(node) {
8
9
  let textOnly = true;
@@ -14,24 +15,24 @@ function isTextOnly(node) {
14
15
  /**
15
16
  * Reads every composite of `doc` (also inside quotes and lists) as a row, in document order, the distinct
16
17
  * `@mention` chips anywhere in the document and every reference (`reference` chips and `reference` fields) in document
17
- * order. Unknown kinds get the `section` kind's presentation under their own ID.
18
+ * order. Unknown kinds get the `section` kind's presentation under their own ID. `capabilitiesOf` answers which block
19
+ * capabilities a composite has (`createCompositeRows` passes the editor's); without it a row has the ones its Block type lists.
18
20
  */
19
- function compositeRows(doc, kinds) {
21
+ function compositeRows(doc, kinds, capabilitiesOf) {
20
22
  const rows = [];
21
23
  const mentions = /* @__PURE__ */ new Map();
22
24
  const references = [];
23
25
  function walk(parent, start, depth, block) {
24
26
  parent.forEach((node, offset) => {
25
27
  const pos = start + offset;
26
- if (node.type.name === COMPOSITE) {
27
- const kind = compositeKind(kinds, String(node.attrs.kind));
28
+ if (node.type.name === "typedBlock") {
29
+ const kind = blockTypeOf(kinds, String(node.attrs.blockType));
28
30
  const id = blockIdOf(node);
29
31
  const tags = node.maybeChild(2)?.attrs.tags;
30
32
  const description = node.maybeChild(1);
33
+ const capabilities = capabilitiesOf?.(node) ?? new Set(kind.capabilities.map((entry) => entry.id));
31
34
  const row = {
32
- key: id ?? `pos:${pos}`,
33
- id,
34
- pos,
35
+ ...blockPropertiesOf(node, pos, kinds, capabilities),
35
36
  end: pos + node.nodeSize,
36
37
  kind: kind.id,
37
38
  kindLabel: kind.label,
@@ -40,14 +41,13 @@ function compositeRows(doc, kinds) {
40
41
  description: description?.textContent ?? "",
41
42
  descriptionTextOnly: description ? isTextOnly(description) : true,
42
43
  tags: Array.isArray(tags) ? tags.filter((tag) => typeof tag === "string") : [],
43
- meta: node.attrs.meta ?? {},
44
- fields: kind.fields,
44
+ capabilities,
45
45
  tagsVisible: kind.chrome?.tags !== false,
46
46
  controls: kind.chrome?.controls !== false,
47
47
  depth
48
48
  };
49
49
  rows.push(row);
50
- for (const field of kind.fields) {
50
+ for (const field of row.definitions) {
51
51
  const value = field.type === "reference" ? row.meta[field.key] : void 0;
52
52
  if (typeof value === "string" && value) references.push({
53
53
  target: value,
@@ -90,21 +90,21 @@ function visibleText(doc, kinds, node) {
90
90
  case "tag": return `#${String(attrs.name ?? "")}`;
91
91
  case "reference": {
92
92
  const target = findBlockById(doc, String(attrs.target ?? ""));
93
- const label = target?.node.type.name === COMPOSITE ? referenceLabel(referenceTarget(target.node, kinds)) : String(attrs.label ?? "");
93
+ const label = target?.node.type.name === "typedBlock" ? referenceLabel(referenceTarget(target.node, kinds)) : String(attrs.label ?? "");
94
94
  return typeof attrs.locator === "string" && attrs.locator ? `${label}, ${attrs.locator}` : label;
95
95
  }
96
96
  default: return "";
97
97
  }
98
98
  });
99
99
  }
100
- /** Every reference to the Baustein `target` in document order; references whose enclosing block has no ID (or is gone) are left out, as nothing could reveal them. */
100
+ /** Every reference to the Typed block `target` in document order; references whose enclosing block has no ID (or is gone) are left out, as nothing could reveal them. */
101
101
  function compositeBacklinks(doc, kinds, target) {
102
102
  const links = [];
103
103
  for (const reference of compositeRows(doc, kinds).references) {
104
104
  if (reference.target !== target || !reference.from) continue;
105
105
  const found = findBlockById(doc, reference.from);
106
106
  if (!found) continue;
107
- const source = found.node.type.name === COMPOSITE ? found.node.firstChild : found.node;
107
+ const source = found.node.type.name === "typedBlock" ? found.node.firstChild : found.node;
108
108
  const text = source ? visibleText(doc, kinds, source).trim() : "";
109
109
  links.push({
110
110
  from: reference.from,
@@ -127,48 +127,14 @@ function compositeRowAt(rows, pos) {
127
127
  function compositeOfRow(doc, row) {
128
128
  if (row.id) {
129
129
  const found = findBlockById(doc, row.id);
130
- return found?.node.type.name === COMPOSITE ? found : null;
130
+ return found?.node.type.name === "typedBlock" ? found : null;
131
131
  }
132
132
  const node = doc.nodeAt(row.pos);
133
- return node?.type.name === COMPOSITE ? {
133
+ return node?.type.name === "typedBlock" ? {
134
134
  pos: row.pos,
135
135
  node
136
136
  } : null;
137
137
  }
138
- /**
139
- * `meta` with `value` stored under `field.key`: a number field converts a numeric string, an empty value (`''`,
140
- * `null`, `undefined`, `NaN`) removes the key. A `multiselect` field keeps the string entries of an array value and
141
- * removes the key when none is left. Returns a new object; `meta` is not changed.
142
- */
143
- function compositeMetaWith(meta, field, value) {
144
- const next = { ...meta };
145
- if (field.type === "multiselect") {
146
- const chosen = Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
147
- if (chosen.length) next[field.key] = chosen;
148
- else delete next[field.key];
149
- return next;
150
- }
151
- const stored = field.type === "number" && typeof value === "string" && value !== "" ? Number(value) : value;
152
- if (stored === "" || stored === null || stored === void 0 || Number.isNaN(stored)) delete next[field.key];
153
- else next[field.key] = stored;
154
- return next;
155
- }
156
- /** Stores `value` under the meta field `key` of the row's composite (see `compositeMetaWith`), in one transaction. */
157
- function setCompositeMetaField(editor, row, key, value) {
158
- const field = row.fields.find((candidate) => candidate.key === key) ?? {
159
- key,
160
- type: "text"
161
- };
162
- return editor.commands.command(({ tr }) => {
163
- const found = compositeOfRow(tr.doc, row);
164
- if (!found) return false;
165
- tr.setNodeMarkup(found.pos, void 0, {
166
- ...found.node.attrs,
167
- meta: compositeMetaWith(found.node.attrs.meta ?? {}, field, value)
168
- });
169
- return true;
170
- });
171
- }
172
138
  /** Replaces the tags row of the row's composite (empty names are dropped), in one transaction. */
173
139
  function setCompositeTags(editor, row, tags) {
174
140
  return editor.commands.command(({ tr }) => {
@@ -176,7 +142,7 @@ function setCompositeTags(editor, row, tags) {
176
142
  const title = found?.node.maybeChild(0);
177
143
  const description = found?.node.maybeChild(1);
178
144
  const tagsNode = found?.node.maybeChild(2);
179
- if (!found || !title || !description || tagsNode?.type.name !== "compositeTags") return false;
145
+ if (!found || !title || !description || tagsNode?.type.name !== "typedBlockTags") return false;
180
146
  const tagsPos = found.pos + 1 + title.nodeSize + description.nodeSize;
181
147
  tr.setNodeMarkup(tagsPos, void 0, {
182
148
  ...tagsNode.attrs,
@@ -201,7 +167,7 @@ function setCompositeDescription(editor, row, text, expected) {
201
167
  const found = compositeOfRow(tr.doc, row);
202
168
  const title = found?.node.maybeChild(0);
203
169
  const description = found?.node.maybeChild(1);
204
- if (!found || !title || !description || description.type.name !== "compositeDescription") return false;
170
+ if (!found || !title || !description || description.type.name !== "typedBlockDescription") return false;
205
171
  if (!isTextOnly(description)) return false;
206
172
  const current = description.textContent;
207
173
  if (expected !== void 0 && current !== expected) return false;
@@ -217,6 +183,6 @@ function setCompositeDescription(editor, row, text, expected) {
217
183
  });
218
184
  }
219
185
  //#endregion
220
- export { compositeBacklinks, compositeDescriptionText, compositeMetaWith, compositeOfRow, compositeRowAt, compositeRows, setCompositeDescription, setCompositeMetaField, setCompositeTags };
186
+ export { compositeBacklinks, compositeDescriptionText, compositeOfRow, compositeRowAt, compositeRows, setCompositeDescription, setCompositeTags };
221
187
 
222
188
  //# sourceMappingURL=rows.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rows.js","names":[],"sources":["../../../src/features/composites/rows.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { blockIdOf, findBlockById } from '../../core/schema'\nimport { type CompositeKind, type CompositeMetaField, compositeKind } from './kinds'\nimport { referenceLabel, referenceTarget } from './reference-label'\n\n/** One composite („Baustein“) of a document with its metadata, flattened in document order. */\nexport interface CompositeRow {\n /** Block ID, or `pos:<pos>` for a composite without one yet; unique within the document. */\n key: string\n id: string | null\n /** Position of the composite when the row was read; the write helpers re-resolve it, so a stale value is safe. */\n pos: number\n /** Position right after the composite, as of when the row was read. */\n end: number\n kind: string\n kindLabel: string\n icon: string\n /** Title text, empty for an untitled composite. */\n title: string\n /** Text of the description (summary), empty when there is none. */\n description: string\n /**\n * The description holds text only (marks such as bold, author or comment allowed, no mentions or tags); only then\n * can `setCompositeDescription` write it without losing inline content.\n */\n descriptionTextOnly: boolean\n tags: string[]\n meta: Record<string, unknown>\n /** The meta fields of the composite's kind. */\n fields: readonly CompositeMetaField[]\n /** `false` when the composite's kind hides its tag row (`CompositeKind.chrome.tags === false`): chips, the add-tag control and the tags field stay away. */\n tagsVisible: boolean\n /** `false` when the composite's kind has `chrome.controls === false`: its chrome (basket, status, title visibility, tags, drag handle) is read-only even in an editable editor. */\n controls: boolean\n /** Nesting level among composites, 0 = outermost. */\n depth: number\n}\n\n/** A distinct `@mention` chip of a document. */\nexport interface CompositeMention {\n id: string\n label: string\n color: string | null\n}\n\n/** A reference to a Baustein: a `reference` chip in the text of block `from`, or a `reference` field of the Baustein `from`. */\nexport interface CompositeReference {\n /** Block ID of the referenced Baustein. */\n target: string\n /** Block ID of the nearest block around the chip (the Baustein itself for a field); `null` when that block has no ID yet. */\n from: string | null\n /** The chip's locator (`S. 12`, `03:14`); `null` for a field or a chip without one. */\n locator: string | null\n}\n\nconst COMPOSITE = 'composite'\n\n/** True when `node`'s content is empty or text only (with any marks, but no inline nodes such as mentions or tags). */\nfunction isTextOnly(node: PMNode): boolean {\n let textOnly = true\n node.forEach((child) => {\n if (!child.isText) textOnly = false\n })\n return textOnly\n}\n\n/**\n * Reads every composite of `doc` (also inside quotes and lists) as a row, in document order, the distinct\n * `@mention` chips anywhere in the document and every reference (`reference` chips and `reference` fields) in document\n * order. Unknown kinds get the `section` kind's presentation under their own ID.\n */\nexport function compositeRows(doc: PMNode, kinds: readonly CompositeKind[]): { rows: CompositeRow[], mentions: CompositeMention[], references: CompositeReference[] } {\n const rows: CompositeRow[] = []\n const mentions = new Map<string, CompositeMention>()\n const references: CompositeReference[] = []\n\n function walk(parent: PMNode, start: number, depth: number, block: string | null) {\n parent.forEach((node, offset) => {\n const pos = start + offset\n if (node.type.name === COMPOSITE) {\n const kind = compositeKind(kinds, String(node.attrs.kind))\n const id = blockIdOf(node)\n const tags: unknown = node.maybeChild(2)?.attrs.tags\n const description = node.maybeChild(1)\n const row: CompositeRow = {\n key: id ?? `pos:${pos}`,\n id,\n pos,\n end: pos + node.nodeSize,\n kind: kind.id,\n kindLabel: kind.label,\n icon: kind.icon,\n title: node.firstChild?.textContent.trim() ?? '',\n description: description?.textContent ?? '',\n descriptionTextOnly: description ? isTextOnly(description) : true,\n tags: Array.isArray(tags) ? tags.filter((tag): tag is string => typeof tag === 'string') : [],\n meta: (node.attrs.meta ?? {}) as Record<string, unknown>,\n fields: kind.fields,\n tagsVisible: kind.chrome?.tags !== false,\n controls: kind.chrome?.controls !== false,\n depth,\n }\n rows.push(row)\n for (const field of kind.fields) {\n const value = field.type === 'reference' ? row.meta[field.key] : undefined\n if (typeof value === 'string' && value) references.push({ target: value, from: id, locator: null })\n }\n walk(node, pos + 1, depth + 1, id ?? block)\n }\n else if (node.type.name === 'reference') {\n const target = String(node.attrs.target ?? '')\n if (target) references.push({ target, from: block, locator: typeof node.attrs.locator === 'string' && node.attrs.locator ? node.attrs.locator : null })\n }\n else if (node.type.name === 'mention') {\n const mentionId = String(node.attrs.id ?? '')\n if (mentionId && !mentions.has(mentionId)) {\n mentions.set(mentionId, {\n id: mentionId,\n label: String(node.attrs.label ?? mentionId),\n color: typeof node.attrs.color === 'string' ? node.attrs.color : null,\n })\n }\n }\n else if (!node.isLeaf) {\n walk(node, pos + 1, depth, blockIdOf(node) ?? block)\n }\n })\n }\n walk(doc, 0, 0, null)\n return { rows, mentions: [...mentions.values()], references }\n}\n\n/** A place that refers to a Baustein: the block holding the chip (or the Baustein with the field) and a short text of it. */\nexport interface CompositeBacklink {\n from: string\n locator: string | null\n excerpt: string\n}\n\nconst EXCERPT_LENGTH = 40\n\n/** The text of `node` as read on screen: inline atoms count as their label (`@name`, `#tag`, a reference chip's short citation + locator), not as nothing. */\nfunction visibleText(doc: PMNode, kinds: readonly CompositeKind[], node: PMNode): string {\n return node.textBetween(0, node.content.size, ' ', (leaf) => {\n const attrs = leaf.attrs\n switch (leaf.type.name) {\n case 'mention': return `@${String(attrs.label ?? attrs.id ?? '')}`\n case 'tag': return `#${String(attrs.name ?? '')}`\n case 'reference': {\n const target = findBlockById(doc, String(attrs.target ?? ''))\n const label = target?.node.type.name === COMPOSITE ? referenceLabel(referenceTarget(target.node, kinds)) : String(attrs.label ?? '')\n return typeof attrs.locator === 'string' && attrs.locator ? `${label}, ${attrs.locator}` : label\n }\n default: return ''\n }\n })\n}\n\n/** Every reference to the Baustein `target` in document order; references whose enclosing block has no ID (or is gone) are left out, as nothing could reveal them. */\nexport function compositeBacklinks(doc: PMNode, kinds: readonly CompositeKind[], target: string): CompositeBacklink[] {\n const links: CompositeBacklink[] = []\n for (const reference of compositeRows(doc, kinds).references) {\n if (reference.target !== target || !reference.from) continue\n const found = findBlockById(doc, reference.from)\n if (!found) continue\n const source = found.node.type.name === COMPOSITE ? found.node.firstChild : found.node\n const text = source ? visibleText(doc, kinds, source).trim() : ''\n links.push({ from: reference.from, locator: reference.locator, excerpt: text.length > EXCERPT_LENGTH ? `${text.slice(0, EXCERPT_LENGTH)}…` : text })\n }\n return links\n}\n\n/** The innermost row around document position `pos`, `null` outside of any composite. */\nexport function compositeRowAt(rows: readonly CompositeRow[], pos: number): CompositeRow | null {\n let found: CompositeRow | null = null\n // Pre-order: the last match is the innermost composite.\n for (const row of rows) {\n if (row.pos <= pos && pos < row.end) found = row\n }\n return found\n}\n\n/**\n * The composite `row` stands for in `doc`: by block ID, else (the row has no ID yet) by its position.\n * Positions are re-resolved on every call, so a stale `row.pos` is safe for rows with an ID.\n */\nexport function compositeOfRow(doc: PMNode, row: Pick<CompositeRow, 'id' | 'pos'>): { pos: number, node: PMNode } | null {\n if (row.id) {\n const found = findBlockById(doc, row.id)\n return found?.node.type.name === COMPOSITE ? found : null\n }\n const node = doc.nodeAt(row.pos)\n return node?.type.name === COMPOSITE ? { pos: row.pos, node } : null\n}\n\n/**\n * `meta` with `value` stored under `field.key`: a number field converts a numeric string, an empty value (`''`,\n * `null`, `undefined`, `NaN`) removes the key. A `multiselect` field keeps the string entries of an array value and\n * removes the key when none is left. Returns a new object; `meta` is not changed.\n */\nexport function compositeMetaWith(meta: Record<string, unknown>, field: Pick<CompositeMetaField, 'key' | 'type'>, value: unknown): Record<string, unknown> {\n const next = { ...meta }\n if (field.type === 'multiselect') {\n const chosen = Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string') : []\n if (chosen.length) next[field.key] = chosen\n else delete next[field.key]\n return next\n }\n const stored = field.type === 'number' && typeof value === 'string' && value !== '' ? Number(value) : value\n if (stored === '' || stored === null || stored === undefined || Number.isNaN(stored)) delete next[field.key]\n else next[field.key] = stored\n return next\n}\n\n/** Stores `value` under the meta field `key` of the row's composite (see `compositeMetaWith`), in one transaction. */\nexport function setCompositeMetaField(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos' | 'fields'>, key: string, value: unknown): boolean {\n const field = row.fields.find(candidate => candidate.key === key) ?? { key, type: 'text' as const }\n return editor.commands.command(({ tr }) => {\n const found = compositeOfRow(tr.doc, row)\n if (!found) return false\n tr.setNodeMarkup(found.pos, undefined, { ...found.node.attrs, meta: compositeMetaWith(found.node.attrs.meta ?? {}, field, value) })\n return true\n })\n}\n\n/** Replaces the tags row of the row's composite (empty names are dropped), in one transaction. */\nexport function setCompositeTags(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos'>, tags: readonly string[]): boolean {\n return editor.commands.command(({ tr }) => {\n const found = compositeOfRow(tr.doc, row)\n const title = found?.node.maybeChild(0)\n const description = found?.node.maybeChild(1)\n const tagsNode = found?.node.maybeChild(2)\n if (!found || !title || !description || tagsNode?.type.name !== 'compositeTags') return false\n const tagsPos = found.pos + 1 + title.nodeSize + description.nodeSize\n tr.setNodeMarkup(tagsPos, undefined, { ...tagsNode.attrs, tags: tags.filter(tag => tag) })\n return true\n })\n}\n\n/** The text `setCompositeDescription` stores for `text`: the description is one line, so line breaks collapse to spaces. */\nexport function compositeDescriptionText(text: string): string {\n return text.replace(/\\s*\\n\\s*/g, ' ').trim()\n}\n\n/**\n * Sets the text of the row's composite description to `compositeDescriptionText(text)`; an empty text empties it.\n * Only the changed span is replaced, so marks on the unchanged text (bold, author, comment) stay. Refuses (`false`)\n * when the description holds a mention or tag (it would be lost), and, when `expected` is given, when the\n * description no longer holds that text (a peer changed it since the caller read it; writing would drop that change).\n */\nexport function setCompositeDescription(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos'>, text: string, expected?: string): boolean {\n const value = compositeDescriptionText(text)\n return editor.commands.command(({ tr }) => {\n const found = compositeOfRow(tr.doc, row)\n const title = found?.node.maybeChild(0)\n const description = found?.node.maybeChild(1)\n if (!found || !title || !description || description.type.name !== 'compositeDescription') return false\n if (!isTextOnly(description)) return false\n const current = description.textContent\n if (expected !== undefined && current !== expected) return false\n if (current === value) return true\n // Text only: every character is one position. Keep the common prefix and suffix, replace what lies between.\n let prefix = 0\n const max = Math.min(current.length, value.length)\n while (prefix < max && current[prefix] === value[prefix]) prefix++\n let suffix = 0\n while (suffix < max - prefix && current[current.length - 1 - suffix] === value[value.length - 1 - suffix]) suffix++\n const start = found.pos + 1 + title.nodeSize + 1\n // `insertText` with an empty text deletes the range; inserted text takes the marks at its start, as typing does.\n tr.insertText(value.slice(prefix, value.length - suffix), start + prefix, start + current.length - suffix)\n return true\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"rows.js","names":[],"sources":["../../../src/features/composites/rows.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { blockIdOf, findBlockById, TYPED_BLOCK, TYPED_BLOCK_DESCRIPTION, TYPED_BLOCK_TAGS } from '../../core/schema'\nimport { type BlockType, blockTypeOf } from './block-types'\nimport { type BlockProperties, blockPropertiesOf } from './properties'\nimport { referenceLabel, referenceTarget } from './reference-label'\n\n/** One composite (a Typed block) of a document with its Block properties (`key`, `id`, `pos`, `meta`, `definitions`) and chrome, flattened in document order. */\nexport interface CompositeRow extends BlockProperties {\n /** Position right after the composite, as of when the row was read. */\n end: number\n kind: string\n kindLabel: string\n icon: string\n /** Title text, empty for an untitled composite. */\n title: string\n /** Text of the description (summary), empty when there is none. */\n description: string\n /**\n * The description holds text only (marks such as bold, author or comment allowed, no mentions or tags); only then\n * can `setCompositeDescription` write it without losing inline content.\n */\n descriptionTextOnly: boolean\n tags: string[]\n /** The block capabilities the composite has (`capabilitiesOf`); the chrome and the inspector offer only what these allow (basket menu, bibliography editor). */\n capabilities: ReadonlySet<string>\n /** `false` when the composite's kind hides its tag row (`BlockType.chrome.tags === false`): chips, the add-tag control and the tags field stay away. */\n tagsVisible: boolean\n /** `false` when the composite's kind has `chrome.controls === false`: its chrome (basket, status, title visibility, tags, drag handle) is read-only even in an editable editor. */\n controls: boolean\n /** Nesting level among composites, 0 = outermost. */\n depth: number\n}\n\n/** A distinct `@mention` chip of a document. */\nexport interface CompositeMention {\n id: string\n label: string\n color: string | null\n}\n\n/** A reference to a Typed block: a `reference` chip in the text of block `from`, or a `reference` field of the Typed block `from`. */\nexport interface CompositeReference {\n /** Block ID of the referenced Typed block. */\n target: string\n /** Block ID of the nearest block around the chip (the Typed block itself for a field); `null` when that block has no ID yet. */\n from: string | null\n /** The chip's locator (`S. 12`, `03:14`); `null` for a field or a chip without one. */\n locator: string | null\n}\n\n/** True when `node`'s content is empty or text only (with any marks, but no inline nodes such as mentions or tags). */\nfunction isTextOnly(node: PMNode): boolean {\n let textOnly = true\n node.forEach((child) => {\n if (!child.isText) textOnly = false\n })\n return textOnly\n}\n\n/**\n * Reads every composite of `doc` (also inside quotes and lists) as a row, in document order, the distinct\n * `@mention` chips anywhere in the document and every reference (`reference` chips and `reference` fields) in document\n * order. Unknown kinds get the `section` kind's presentation under their own ID. `capabilitiesOf` answers which block\n * capabilities a composite has (`createCompositeRows` passes the editor's); without it a row has the ones its Block type lists.\n */\nexport function compositeRows(doc: PMNode, kinds: readonly BlockType[], capabilitiesOf?: (node: PMNode) => ReadonlySet<string>): { rows: CompositeRow[], mentions: CompositeMention[], references: CompositeReference[] } {\n const rows: CompositeRow[] = []\n const mentions = new Map<string, CompositeMention>()\n const references: CompositeReference[] = []\n\n function walk(parent: PMNode, start: number, depth: number, block: string | null) {\n parent.forEach((node, offset) => {\n const pos = start + offset\n if (node.type.name === TYPED_BLOCK) {\n const kind = blockTypeOf(kinds, String(node.attrs.blockType))\n const id = blockIdOf(node)\n const tags: unknown = node.maybeChild(2)?.attrs.tags\n const description = node.maybeChild(1)\n const capabilities = capabilitiesOf?.(node) ?? new Set(kind.capabilities.map(entry => entry.id))\n const properties = blockPropertiesOf(node, pos, kinds, capabilities)\n const row: CompositeRow = {\n ...properties,\n end: pos + node.nodeSize,\n kind: kind.id,\n kindLabel: kind.label,\n icon: kind.icon,\n title: node.firstChild?.textContent.trim() ?? '',\n description: description?.textContent ?? '',\n descriptionTextOnly: description ? isTextOnly(description) : true,\n tags: Array.isArray(tags) ? tags.filter((tag): tag is string => typeof tag === 'string') : [],\n capabilities,\n tagsVisible: kind.chrome?.tags !== false,\n controls: kind.chrome?.controls !== false,\n depth,\n }\n rows.push(row)\n for (const field of row.definitions) {\n const value = field.type === 'reference' ? row.meta[field.key] : undefined\n if (typeof value === 'string' && value) references.push({ target: value, from: id, locator: null })\n }\n walk(node, pos + 1, depth + 1, id ?? block)\n }\n else if (node.type.name === 'reference') {\n const target = String(node.attrs.target ?? '')\n if (target) references.push({ target, from: block, locator: typeof node.attrs.locator === 'string' && node.attrs.locator ? node.attrs.locator : null })\n }\n else if (node.type.name === 'mention') {\n const mentionId = String(node.attrs.id ?? '')\n if (mentionId && !mentions.has(mentionId)) {\n mentions.set(mentionId, {\n id: mentionId,\n label: String(node.attrs.label ?? mentionId),\n color: typeof node.attrs.color === 'string' ? node.attrs.color : null,\n })\n }\n }\n else if (!node.isLeaf) {\n walk(node, pos + 1, depth, blockIdOf(node) ?? block)\n }\n })\n }\n walk(doc, 0, 0, null)\n return { rows, mentions: [...mentions.values()], references }\n}\n\n/** A place that refers to a Typed block: the block holding the chip (or the Typed block with the field) and a short text of it. */\nexport interface CompositeBacklink {\n from: string\n locator: string | null\n excerpt: string\n}\n\nconst EXCERPT_LENGTH = 40\n\n/** The text of `node` as read on screen: inline atoms count as their label (`@name`, `#tag`, a reference chip's short citation + locator), not as nothing. */\nfunction visibleText(doc: PMNode, kinds: readonly BlockType[], node: PMNode): string {\n return node.textBetween(0, node.content.size, ' ', (leaf) => {\n const attrs = leaf.attrs\n switch (leaf.type.name) {\n case 'mention': return `@${String(attrs.label ?? attrs.id ?? '')}`\n case 'tag': return `#${String(attrs.name ?? '')}`\n case 'reference': {\n const target = findBlockById(doc, String(attrs.target ?? ''))\n const label = target?.node.type.name === TYPED_BLOCK ? referenceLabel(referenceTarget(target.node, kinds)) : String(attrs.label ?? '')\n return typeof attrs.locator === 'string' && attrs.locator ? `${label}, ${attrs.locator}` : label\n }\n default: return ''\n }\n })\n}\n\n/** Every reference to the Typed block `target` in document order; references whose enclosing block has no ID (or is gone) are left out, as nothing could reveal them. */\nexport function compositeBacklinks(doc: PMNode, kinds: readonly BlockType[], target: string): CompositeBacklink[] {\n const links: CompositeBacklink[] = []\n for (const reference of compositeRows(doc, kinds).references) {\n if (reference.target !== target || !reference.from) continue\n const found = findBlockById(doc, reference.from)\n if (!found) continue\n const source = found.node.type.name === TYPED_BLOCK ? found.node.firstChild : found.node\n const text = source ? visibleText(doc, kinds, source).trim() : ''\n links.push({ from: reference.from, locator: reference.locator, excerpt: text.length > EXCERPT_LENGTH ? `${text.slice(0, EXCERPT_LENGTH)}…` : text })\n }\n return links\n}\n\n/** The innermost row around document position `pos`, `null` outside of any composite. */\nexport function compositeRowAt(rows: readonly CompositeRow[], pos: number): CompositeRow | null {\n let found: CompositeRow | null = null\n // Pre-order: the last match is the innermost composite.\n for (const row of rows) {\n if (row.pos <= pos && pos < row.end) found = row\n }\n return found\n}\n\n/**\n * The composite `row` stands for in `doc`: by block ID, else (the row has no ID yet) by its position.\n * Positions are re-resolved on every call, so a stale `row.pos` is safe for rows with an ID.\n */\nexport function compositeOfRow(doc: PMNode, row: Pick<CompositeRow, 'id' | 'pos'>): { pos: number, node: PMNode } | null {\n if (row.id) {\n const found = findBlockById(doc, row.id)\n return found?.node.type.name === TYPED_BLOCK ? found : null\n }\n const node = doc.nodeAt(row.pos)\n return node?.type.name === TYPED_BLOCK ? { pos: row.pos, node } : null\n}\n\n/** Replaces the tags row of the row's composite (empty names are dropped), in one transaction. */\nexport function setCompositeTags(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos'>, tags: readonly string[]): boolean {\n return editor.commands.command(({ tr }) => {\n const found = compositeOfRow(tr.doc, row)\n const title = found?.node.maybeChild(0)\n const description = found?.node.maybeChild(1)\n const tagsNode = found?.node.maybeChild(2)\n if (!found || !title || !description || tagsNode?.type.name !== TYPED_BLOCK_TAGS) return false\n const tagsPos = found.pos + 1 + title.nodeSize + description.nodeSize\n tr.setNodeMarkup(tagsPos, undefined, { ...tagsNode.attrs, tags: tags.filter(tag => tag) })\n return true\n })\n}\n\n/** The text `setCompositeDescription` stores for `text`: the description is one line, so line breaks collapse to spaces. */\nexport function compositeDescriptionText(text: string): string {\n return text.replace(/\\s*\\n\\s*/g, ' ').trim()\n}\n\n/**\n * Sets the text of the row's composite description to `compositeDescriptionText(text)`; an empty text empties it.\n * Only the changed span is replaced, so marks on the unchanged text (bold, author, comment) stay. Refuses (`false`)\n * when the description holds a mention or tag (it would be lost), and, when `expected` is given, when the\n * description no longer holds that text (a peer changed it since the caller read it; writing would drop that change).\n */\nexport function setCompositeDescription(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos'>, text: string, expected?: string): boolean {\n const value = compositeDescriptionText(text)\n return editor.commands.command(({ tr }) => {\n const found = compositeOfRow(tr.doc, row)\n const title = found?.node.maybeChild(0)\n const description = found?.node.maybeChild(1)\n if (!found || !title || !description || description.type.name !== TYPED_BLOCK_DESCRIPTION) return false\n if (!isTextOnly(description)) return false\n const current = description.textContent\n if (expected !== undefined && current !== expected) return false\n if (current === value) return true\n // Text only: every character is one position. Keep the common prefix and suffix, replace what lies between.\n let prefix = 0\n const max = Math.min(current.length, value.length)\n while (prefix < max && current[prefix] === value[prefix]) prefix++\n let suffix = 0\n while (suffix < max - prefix && current[current.length - 1 - suffix] === value[value.length - 1 - suffix]) suffix++\n const start = found.pos + 1 + title.nodeSize + 1\n // `insertText` with an empty text deletes the range; inserted text takes the marks at its start, as typing does.\n tr.insertText(value.slice(prefix, value.length - suffix), start + prefix, start + current.length - suffix)\n return true\n })\n}\n"],"mappings":"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"}
@@ -1,29 +1,30 @@
1
1
  import { CSL_TYPES, CslDate, CslItem, CslName, CslType } from "../../core/backend-types.js";
2
- import { CompositeAiBrief, compositeAiBrief } from "./ai-brief.js";
3
- import { CompositeKind, CompositeKindAi, CompositeMetaField, SOURCE_MEDIA_TYPES, compositeKind, defaultCompositeKinds, kindAccepts } from "./kinds.js";
4
2
  import { BASKET_IDS, Basket, basketById, basketOf, defaultBaskets, titleHiddenOf } from "./baskets.js";
5
- import { COMPOSITE_CHROME_COUNT, CompositeDescriptionNode, CompositeNode, CompositeOptions, CompositeStorage, CompositeTagsNode, CompositeTitleNode, compositeBasketsOf, compositeJSON, compositeKindsOf } from "./nodes.js";
6
- import { REFERENCE_NODE, ReferenceAttrs, ReferenceNode, ReferenceOptions, ReferenceSuggestionPluginKey, referenceMarkdown } from "./reference.js";
3
+ import { BlockType, BlockTypeAi, ContainerConfig, ImportConfig, PropertiesConfig, SOURCE_MEDIA_TYPES, SourceConfig, SourceMedia, acceptsChild, acceptsImport, acceptsOf, aiBlockTypesOf, aiBriefOf, blockTypeOf, defaultBlockTypes, importTypeOf, isRootBlockType, nestedAfterContentOf, propertiesOf, sourceMediaOf } from "./block-types.js";
4
+ import { CompositeAiBrief, compositeAiBrief } from "./ai-brief.js";
7
5
  import { compositeConversions, convertCompositeBlocks } from "./convert.js";
8
6
  import { CompositeFence, FenceSegment, splitCompositeFences } from "../../core/fences.js";
9
7
  import { blocksFromMarkdown, compositeFence, compositeFromMarkdown } from "./fences.js";
10
8
  import { compositeChromeBlocks, flattenCompositesToHeadings, groupHeadingsIntoComposites, headingGroupRange, structureBlocks } from "./heading-composites.js";
11
- import { BASKET_KEY, BIB_KEY, DERIVATION_KEY, TITLE_HIDDEN_KEY } from "./meta-keys.js";
9
+ import { BASKET_KEY, BIB_KEY, TITLE_HIDDEN_KEY } from "./meta-keys.js";
12
10
  import { bibOf, bibtexOf, citeFull, citeShort, cslOf, cslTypeOptions, yearOf } from "./bibliography.js";
13
- import { Derivation, DerivationMethod, DerivationSource, bodyMarkdown, derivationOf, derivationState, renditionsOf, sourceOf } from "./derivation.js";
14
- import { LEGACY_COMPOSITE_NODE, migrateLegacyContent } from "./legacy.js";
11
+ import { bodyMarkdown, sourceOf } from "./source.js";
12
+ import { BlockTypeJsonError, BlockTypeJsonIssue, mergeBlockTypes, parseBlockTypes } from "./block-types-json.js";
13
+ import { hasFlatTranscript, migrateLegacyContent } from "./legacy.js";
14
+ import { REFERENCE_NODE, ReferenceAttrs, ReferenceNode, ReferenceOptions, ReferenceSuggestionPluginKey, referenceMarkdown } from "./reference.js";
15
15
  import { collectCompositeIds, compositeIdsOf, normalizeReferences, referencesFromText } from "./reference-text.js";
16
+ import { COMPOSITE_CHROME_COUNT, CompositeDescriptionNode, CompositeNode, CompositeOptions, CompositeStorage, CompositeTagsNode, CompositeTitleNode, blockTypesOf, compositeBasketsOf, compositeJSON } from "./nodes.js";
16
17
  import { AnyExtension } from "@tiptap/core";
17
18
  //#region src/features/composites/schema.d.ts
18
19
  /**
19
20
  * The schema-bearing composite family (composite, title, description, tags, and the inline `reference` chip) without node views, to append to
20
- * `coreSchemaExtensions()`: `getSchema([...coreSchemaExtensions(), ...compositeSchemaExtensions({ kinds })])`. `kinds`
21
- * is the host's kind list (default: the built-in kinds in German, `defaultCompositeKinds`); it is storage, not schema.
21
+ * `coreSchemaExtensions()`: `getSchema([...coreSchemaExtensions(), ...compositeSchemaExtensions({ blockTypes })])`. `blockTypes`
22
+ * is the host's Block type list (default: the built-in Block types in German, `defaultBlockTypes`); it is storage, not schema.
22
23
  */
23
24
  export declare function compositeSchemaExtensions(options?: {
24
- kinds?: readonly CompositeKind[];
25
+ blockTypes?: readonly BlockType[];
25
26
  baskets?: readonly Basket[];
26
27
  }): AnyExtension[];
27
28
  //#endregion
28
- export { BASKET_IDS, BASKET_KEY, BIB_KEY, type Basket, COMPOSITE_CHROME_COUNT, CSL_TYPES, type CompositeAiBrief, CompositeDescriptionNode, type CompositeFence, type CompositeKind, type CompositeKindAi, type CompositeMetaField, CompositeNode, type CompositeOptions, type CompositeStorage, CompositeTagsNode, CompositeTitleNode, type CslDate, type CslItem, type CslName, type CslType, DERIVATION_KEY, type Derivation, type DerivationMethod, type DerivationSource, type FenceSegment, LEGACY_COMPOSITE_NODE, REFERENCE_NODE, type ReferenceAttrs, ReferenceNode, type ReferenceOptions, ReferenceSuggestionPluginKey, SOURCE_MEDIA_TYPES, TITLE_HIDDEN_KEY, basketById, basketOf, bibOf, bibtexOf, blocksFromMarkdown, bodyMarkdown, citeFull, citeShort, collectCompositeIds, compositeAiBrief, compositeBasketsOf, compositeChromeBlocks, compositeConversions, compositeFence, compositeFromMarkdown, compositeIdsOf, compositeJSON, compositeKind, compositeKindsOf, convertCompositeBlocks, cslOf, cslTypeOptions, defaultBaskets, defaultCompositeKinds, derivationOf, derivationState, flattenCompositesToHeadings, groupHeadingsIntoComposites, headingGroupRange, kindAccepts, migrateLegacyContent, normalizeReferences, referenceMarkdown, referencesFromText, renditionsOf, sourceOf, splitCompositeFences, structureBlocks, titleHiddenOf, yearOf };
29
+ export { BASKET_IDS, BASKET_KEY, BIB_KEY, type Basket, type BlockType, type BlockTypeAi, BlockTypeJsonError, type BlockTypeJsonIssue, COMPOSITE_CHROME_COUNT, CSL_TYPES, type CompositeAiBrief, CompositeDescriptionNode, type CompositeFence, CompositeNode, type CompositeOptions, type CompositeStorage, CompositeTagsNode, CompositeTitleNode, type ContainerConfig, type CslDate, type CslItem, type CslName, type CslType, type FenceSegment, type ImportConfig, type PropertiesConfig, REFERENCE_NODE, type ReferenceAttrs, ReferenceNode, type ReferenceOptions, ReferenceSuggestionPluginKey, SOURCE_MEDIA_TYPES, type SourceConfig, type SourceMedia, TITLE_HIDDEN_KEY, acceptsChild, acceptsImport, acceptsOf, aiBlockTypesOf, aiBriefOf, basketById, basketOf, bibOf, bibtexOf, blockTypeOf, blockTypesOf, blocksFromMarkdown, bodyMarkdown, citeFull, citeShort, collectCompositeIds, compositeAiBrief, compositeBasketsOf, compositeChromeBlocks, compositeConversions, compositeFence, compositeFromMarkdown, compositeIdsOf, compositeJSON, convertCompositeBlocks, cslOf, cslTypeOptions, defaultBaskets, defaultBlockTypes, flattenCompositesToHeadings, groupHeadingsIntoComposites, hasFlatTranscript, headingGroupRange, importTypeOf, isRootBlockType, mergeBlockTypes, migrateLegacyContent, nestedAfterContentOf, normalizeReferences, parseBlockTypes, propertiesOf, referenceMarkdown, referencesFromText, sourceMediaOf, sourceOf, splitCompositeFences, structureBlocks, titleHiddenOf, yearOf };
29
30
  //# sourceMappingURL=schema.d.ts.map
@@ -1,28 +1,29 @@
1
1
  import { splitCompositeFences } from "../../core/fences.js";
2
- import { SOURCE_MEDIA_TYPES, compositeKind, defaultCompositeKinds, kindAccepts } from "./kinds.js";
3
- import { BASKET_KEY, BIB_KEY, DERIVATION_KEY, TITLE_HIDDEN_KEY } from "./meta-keys.js";
2
+ import { SOURCE_MEDIA_TYPES, acceptsChild, acceptsImport, acceptsOf, aiBlockTypesOf, aiBriefOf, blockTypeOf, defaultBlockTypes, importTypeOf, isRootBlockType, nestedAfterContentOf, propertiesOf, sourceMediaOf } from "./block-types.js";
3
+ import { BASKET_KEY, BIB_KEY, TITLE_HIDDEN_KEY } from "./meta-keys.js";
4
4
  import { blocksFromMarkdown, compositeFence, compositeFromMarkdown } from "./fences.js";
5
5
  import { BASKET_IDS, basketById, basketOf, defaultBaskets, titleHiddenOf } from "./baskets.js";
6
- import { bodyMarkdown, derivationOf, derivationState, renditionsOf, sourceOf } from "./derivation.js";
7
6
  import { compositeChromeBlocks, flattenCompositesToHeadings, groupHeadingsIntoComposites, headingGroupRange, structureBlocks } from "./heading-composites.js";
8
- import { COMPOSITE_CHROME_COUNT, CompositeDescriptionNode, CompositeNode, CompositeTagsNode, CompositeTitleNode, compositeBasketsOf, compositeJSON, compositeKindsOf } from "./nodes.js";
7
+ import { COMPOSITE_CHROME_COUNT, CompositeDescriptionNode, CompositeNode, CompositeTagsNode, CompositeTitleNode, blockTypesOf, compositeBasketsOf, compositeJSON } from "./nodes.js";
9
8
  import { REFERENCE_NODE, ReferenceNode, ReferenceSuggestionPluginKey, referenceMarkdown } from "./reference.js";
10
9
  import { CSL_TYPES } from "../../core/backend-types.js";
11
10
  import { bibOf, bibtexOf, citeFull, citeShort, cslOf, cslTypeOptions, yearOf } from "./bibliography.js";
12
11
  import { compositeAiBrief } from "./ai-brief.js";
13
12
  import { compositeConversions, convertCompositeBlocks } from "./convert.js";
14
- import { LEGACY_COMPOSITE_NODE, migrateLegacyContent } from "./legacy.js";
13
+ import { bodyMarkdown, sourceOf } from "./source.js";
14
+ import { BlockTypeJsonError, mergeBlockTypes, parseBlockTypes } from "./block-types-json.js";
15
+ import { hasFlatTranscript, migrateLegacyContent } from "./legacy.js";
15
16
  import { collectCompositeIds, compositeIdsOf, normalizeReferences, referencesFromText } from "./reference-text.js";
16
17
  //#region src/features/composites/schema.ts
17
18
  /**
18
19
  * The schema-bearing composite family (composite, title, description, tags, and the inline `reference` chip) without node views, to append to
19
- * `coreSchemaExtensions()`: `getSchema([...coreSchemaExtensions(), ...compositeSchemaExtensions({ kinds })])`. `kinds`
20
- * is the host's kind list (default: the built-in kinds in German, `defaultCompositeKinds`); it is storage, not schema.
20
+ * `coreSchemaExtensions()`: `getSchema([...coreSchemaExtensions(), ...compositeSchemaExtensions({ blockTypes })])`. `blockTypes`
21
+ * is the host's Block type list (default: the built-in Block types in German, `defaultBlockTypes`); it is storage, not schema.
21
22
  */
22
23
  function compositeSchemaExtensions(options = {}) {
23
24
  return [
24
25
  CompositeNode.configure({
25
- ...options.kinds && { kinds: options.kinds },
26
+ ...options.blockTypes && { blockTypes: options.blockTypes },
26
27
  ...options.baskets && { baskets: options.baskets }
27
28
  }),
28
29
  CompositeTitleNode,
@@ -32,6 +33,6 @@ function compositeSchemaExtensions(options = {}) {
32
33
  ];
33
34
  }
34
35
  //#endregion
35
- export { BASKET_IDS, BASKET_KEY, BIB_KEY, COMPOSITE_CHROME_COUNT, CSL_TYPES, CompositeDescriptionNode, CompositeNode, CompositeTagsNode, CompositeTitleNode, DERIVATION_KEY, LEGACY_COMPOSITE_NODE, REFERENCE_NODE, ReferenceNode, ReferenceSuggestionPluginKey, SOURCE_MEDIA_TYPES, TITLE_HIDDEN_KEY, basketById, basketOf, bibOf, bibtexOf, blocksFromMarkdown, bodyMarkdown, citeFull, citeShort, collectCompositeIds, compositeAiBrief, compositeBasketsOf, compositeChromeBlocks, compositeConversions, compositeFence, compositeFromMarkdown, compositeIdsOf, compositeJSON, compositeKind, compositeKindsOf, compositeSchemaExtensions, convertCompositeBlocks, cslOf, cslTypeOptions, defaultBaskets, defaultCompositeKinds, derivationOf, derivationState, flattenCompositesToHeadings, groupHeadingsIntoComposites, headingGroupRange, kindAccepts, migrateLegacyContent, normalizeReferences, referenceMarkdown, referencesFromText, renditionsOf, sourceOf, splitCompositeFences, structureBlocks, titleHiddenOf, yearOf };
36
+ export { BASKET_IDS, BASKET_KEY, BIB_KEY, BlockTypeJsonError, COMPOSITE_CHROME_COUNT, CSL_TYPES, CompositeDescriptionNode, CompositeNode, CompositeTagsNode, CompositeTitleNode, REFERENCE_NODE, ReferenceNode, ReferenceSuggestionPluginKey, SOURCE_MEDIA_TYPES, TITLE_HIDDEN_KEY, acceptsChild, acceptsImport, acceptsOf, aiBlockTypesOf, aiBriefOf, basketById, basketOf, bibOf, bibtexOf, blockTypeOf, blockTypesOf, blocksFromMarkdown, bodyMarkdown, citeFull, citeShort, collectCompositeIds, compositeAiBrief, compositeBasketsOf, compositeChromeBlocks, compositeConversions, compositeFence, compositeFromMarkdown, compositeIdsOf, compositeJSON, compositeSchemaExtensions, convertCompositeBlocks, cslOf, cslTypeOptions, defaultBaskets, defaultBlockTypes, flattenCompositesToHeadings, groupHeadingsIntoComposites, hasFlatTranscript, headingGroupRange, importTypeOf, isRootBlockType, mergeBlockTypes, migrateLegacyContent, nestedAfterContentOf, normalizeReferences, parseBlockTypes, propertiesOf, referenceMarkdown, referencesFromText, sourceMediaOf, sourceOf, splitCompositeFences, structureBlocks, titleHiddenOf, yearOf };
36
37
 
37
38
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","names":[],"sources":["../../../src/features/composites/schema.ts"],"sourcesContent":["// Vue-free entry of the composite feature (`@ecsplico/editor/composites/schema`): the node family, kinds, Markdown\n// fences, legacy migration, heading↔composite transforms and conversions. Servers build their schema from it; it never\n// imports node views, components or the feature factory.\nimport type { AnyExtension } from '@tiptap/core'\nimport type { Basket } from './baskets'\nimport { type CompositeKind } from './kinds'\nimport { CompositeNode, CompositeDescriptionNode, CompositeTagsNode, CompositeTitleNode } from './nodes'\nimport { ReferenceNode } from './reference'\n\nexport { type CompositeAiBrief, compositeAiBrief } from './ai-brief'\nexport { type Basket, BASKET_IDS, basketById, basketOf, defaultBaskets, titleHiddenOf } from './baskets'\nexport { compositeConversions, convertCompositeBlocks } from './convert'\nexport { blocksFromMarkdown, type CompositeFence, compositeFence, compositeFromMarkdown, type FenceSegment, splitCompositeFences } from './fences'\nexport { compositeChromeBlocks, flattenCompositesToHeadings, groupHeadingsIntoComposites, headingGroupRange, structureBlocks } from './heading-composites'\nexport { BIB_KEY, bibOf, bibtexOf, citeFull, citeShort, type CslDate, type CslItem, type CslName, type CslType, CSL_TYPES, cslOf, cslTypeOptions, yearOf } from './bibliography'\nexport { bodyMarkdown, DERIVATION_KEY, type Derivation, derivationOf, derivationState, type DerivationMethod, type DerivationSource, renditionsOf, sourceOf } from './derivation'\nexport { type CompositeKind, type CompositeKindAi, type CompositeMetaField, compositeKind, defaultCompositeKinds, kindAccepts, SOURCE_MEDIA_TYPES } from './kinds'\nexport { BASKET_KEY, TITLE_HIDDEN_KEY } from './meta-keys'\nexport { LEGACY_COMPOSITE_NODE, migrateLegacyContent } from './legacy'\nexport { REFERENCE_NODE, type ReferenceAttrs, referenceMarkdown, ReferenceNode, type ReferenceOptions, ReferenceSuggestionPluginKey } from './reference'\nexport { compositeIdsOf, collectCompositeIds, normalizeReferences, referencesFromText } from './reference-text'\nexport {\n COMPOSITE_CHROME_COUNT,\n compositeJSON,\n compositeBasketsOf,\n compositeKindsOf,\n CompositeDescriptionNode,\n CompositeNode,\n type CompositeOptions,\n type CompositeStorage,\n CompositeTagsNode,\n CompositeTitleNode,\n} from './nodes'\n\n/**\n * The schema-bearing composite family (composite, title, description, tags, and the inline `reference` chip) without node views, to append to\n * `coreSchemaExtensions()`: `getSchema([...coreSchemaExtensions(), ...compositeSchemaExtensions({ kinds })])`. `kinds`\n * is the host's kind list (default: the built-in kinds in German, `defaultCompositeKinds`); it is storage, not schema.\n */\nexport function compositeSchemaExtensions(options: { kinds?: readonly CompositeKind[], baskets?: readonly Basket[] } = {}): AnyExtension[] {\n return [CompositeNode.configure({ ...(options.kinds && { kinds: options.kinds }), ...(options.baskets && { baskets: options.baskets }) }), CompositeTitleNode, CompositeDescriptionNode, CompositeTagsNode, ReferenceNode]\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAuCA,SAAgB,0BAA0B,UAA6E,CAAC,GAAmB;CACzI,OAAO;EAAC,cAAc,UAAU;GAAE,GAAI,QAAQ,SAAS,EAAE,OAAO,QAAQ,MAAM;GAAI,GAAI,QAAQ,WAAW,EAAE,SAAS,QAAQ,QAAQ;EAAG,CAAC;EAAG;EAAoB;EAA0B;EAAmB;CAAa;AAC3N"}
1
+ {"version":3,"file":"schema.js","names":[],"sources":["../../../src/features/composites/schema.ts"],"sourcesContent":["// Vue-free entry of the composite feature (`@ecsplico/editor/composites/schema`): the node family, Block types, Markdown\n// fences, legacy migration, heading↔composite transforms and conversions. Servers build their schema from it; it never\n// imports node views, components or the feature factory.\nimport type { AnyExtension } from '@tiptap/core'\nimport type { Basket } from './baskets'\nimport { type BlockType } from './block-types'\nimport { CompositeNode, CompositeDescriptionNode, CompositeTagsNode, CompositeTitleNode } from './nodes'\nimport { ReferenceNode } from './reference'\n\nexport { type CompositeAiBrief, compositeAiBrief } from './ai-brief'\nexport { type Basket, BASKET_IDS, basketById, basketOf, defaultBaskets, titleHiddenOf } from './baskets'\nexport { compositeConversions, convertCompositeBlocks } from './convert'\nexport { blocksFromMarkdown, type CompositeFence, compositeFence, compositeFromMarkdown, type FenceSegment, splitCompositeFences } from './fences'\nexport { compositeChromeBlocks, flattenCompositesToHeadings, groupHeadingsIntoComposites, headingGroupRange, structureBlocks } from './heading-composites'\nexport { BIB_KEY, bibOf, bibtexOf, citeFull, citeShort, type CslDate, type CslItem, type CslName, type CslType, CSL_TYPES, cslOf, cslTypeOptions, yearOf } from './bibliography'\nexport { bodyMarkdown, sourceOf } from './source'\nexport { acceptsChild, acceptsImport, acceptsOf, aiBlockTypesOf, aiBriefOf, nestedAfterContentOf, type BlockType, type BlockTypeAi, blockTypeOf, type ContainerConfig, defaultBlockTypes, type ImportConfig, importTypeOf, isRootBlockType, type PropertiesConfig, propertiesOf, SOURCE_MEDIA_TYPES, type SourceConfig, type SourceMedia, sourceMediaOf } from './block-types'\nexport { BlockTypeJsonError, type BlockTypeJsonIssue, mergeBlockTypes, parseBlockTypes } from './block-types-json'\nexport { BASKET_KEY, TITLE_HIDDEN_KEY } from './meta-keys'\nexport { hasFlatTranscript, migrateLegacyContent } from './legacy'\nexport { REFERENCE_NODE, type ReferenceAttrs, referenceMarkdown, ReferenceNode, type ReferenceOptions, ReferenceSuggestionPluginKey } from './reference'\nexport { compositeIdsOf, collectCompositeIds, normalizeReferences, referencesFromText } from './reference-text'\nexport {\n COMPOSITE_CHROME_COUNT,\n compositeJSON,\n compositeBasketsOf,\n blockTypesOf,\n CompositeDescriptionNode,\n CompositeNode,\n type CompositeOptions,\n type CompositeStorage,\n CompositeTagsNode,\n CompositeTitleNode,\n} from './nodes'\n\n/**\n * The schema-bearing composite family (composite, title, description, tags, and the inline `reference` chip) without node views, to append to\n * `coreSchemaExtensions()`: `getSchema([...coreSchemaExtensions(), ...compositeSchemaExtensions({ blockTypes })])`. `blockTypes`\n * is the host's Block type list (default: the built-in Block types in German, `defaultBlockTypes`); it is storage, not schema.\n */\nexport function compositeSchemaExtensions(options: { blockTypes?: readonly BlockType[], baskets?: readonly Basket[] } = {}): AnyExtension[] {\n return [CompositeNode.configure({ ...(options.blockTypes && { blockTypes: options.blockTypes }), ...(options.baskets && { baskets: options.baskets }) }), CompositeTitleNode, CompositeDescriptionNode, CompositeTagsNode, ReferenceNode]\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,0BAA0B,UAA8E,CAAC,GAAmB;CAC1I,OAAO;EAAC,cAAc,UAAU;GAAE,GAAI,QAAQ,cAAc,EAAE,YAAY,QAAQ,WAAW;GAAI,GAAI,QAAQ,WAAW,EAAE,SAAS,QAAQ,QAAQ;EAAG,CAAC;EAAG;EAAoB;EAA0B;EAAmB;CAAa;AAC1O"}
@@ -0,0 +1,20 @@
1
+ import { BlockType } from "./block-types.js";
2
+ import { Editor } from "@tiptap/core";
3
+ import { Node as Node$1 } from "@tiptap/pm/model";
4
+ //#region src/features/composites/source.d.ts
5
+ /** The media block a source-holding Typed block keeps its original in, with its position among the children, the stored asset behind its `src` and its content hash. */
6
+ export interface SourceBlock {
7
+ node: Node$1;
8
+ index: number;
9
+ asset: {
10
+ documentId: string;
11
+ name: string;
12
+ } | null;
13
+ hash: string | null;
14
+ }
15
+ /** The media block a source-holding Block type keeps its original in: first body child of a type in the `media` of the Block type's `source` capability. */
16
+ export declare function sourceOf(composite: Node$1, blockTypes: readonly BlockType[]): SourceBlock | null;
17
+ /** Markdown of the body of `composite` (everything after title, description and tags). */
18
+ export declare function bodyMarkdown(editor: Editor, composite: Node$1): string;
19
+ //#endregion
20
+ //# sourceMappingURL=source.d.ts.map