@formicoidea/labre-core 0.32.0 → 0.33.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 (227) hide show
  1. package/dist/_pkgs/affine-block-attachment/attachment-block.js +1 -1
  2. package/dist/_pkgs/affine-block-callout/callout-block.js +1 -1
  3. package/dist/_pkgs/affine-block-code/code-block-inline.js +1 -1
  4. package/dist/_pkgs/affine-block-code/code-toolbar/config.js +3 -1
  5. package/dist/_pkgs/affine-block-code/code-toolbar/index.js +1 -1
  6. package/dist/_pkgs/affine-block-database/data-source.js +1 -2
  7. package/dist/_pkgs/affine-block-database/external-data-source.js +1 -1
  8. package/dist/_pkgs/affine-block-edgeless-text/edgeless-text-block.js +1 -1
  9. package/dist/_pkgs/affine-block-edgeless-text/edgeless-toolbar/config.js +1 -1
  10. package/dist/_pkgs/affine-block-embed/embed-figma-block/embed-figma-service.js +1 -1
  11. package/dist/_pkgs/affine-block-embed/embed-iframe-block/configs/toolbar.js +2 -2
  12. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/toolbar.js +1 -1
  13. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/utils.js +1 -1
  14. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/configs/toolbar.js +1 -1
  15. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-synced-doc-block.js +1 -1
  16. package/dist/_pkgs/affine-block-frame/frame-manager.js +3 -1
  17. package/dist/_pkgs/affine-block-frame/frame-tool.js +1 -1
  18. package/dist/_pkgs/affine-block-image/components/page-image-block.js +1 -1
  19. package/dist/_pkgs/affine-block-image/image-edgeless-block.js +1 -1
  20. package/dist/_pkgs/affine-block-list/utils/forward-delete.js +1 -1
  21. package/dist/_pkgs/affine-block-note/commands/select-block.js +1 -1
  22. package/dist/_pkgs/affine-block-note/commands/select-blocks-between.js +1 -1
  23. package/dist/_pkgs/affine-block-note/move-block.js +1 -1
  24. package/dist/_pkgs/affine-block-paragraph/utils/forward-delete.js +2 -2
  25. package/dist/_pkgs/affine-block-paragraph/utils/merge-with-prev.js +1 -1
  26. package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/more.js +1 -1
  27. package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.js +1 -1
  28. package/dist/_pkgs/affine-block-root/edgeless/utils/clipboard-utils.js +1 -1
  29. package/dist/_pkgs/affine-block-surface/adapters/markdown/element-adapter/type.js +1 -1
  30. package/dist/_pkgs/affine-block-surface/adapters/plain-text/element-adapter/type.js +1 -1
  31. package/dist/_pkgs/affine-block-surface/element-model/index.d.ts +18 -3
  32. package/dist/_pkgs/affine-block-surface/element-model/index.js +12 -2
  33. package/dist/_pkgs/affine-block-surface/extensions/audit.js +23 -6
  34. package/dist/_pkgs/affine-block-surface/extensions/crud-extension.js +10 -5
  35. package/dist/_pkgs/affine-block-surface/extensions/editor-anchored-panel.js +2 -1
  36. package/dist/_pkgs/affine-block-surface/extensions/element-renderer.js +1 -1
  37. package/dist/_pkgs/affine-block-surface/extensions/export-manager/export-manager.js +1 -1
  38. package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +4 -0
  39. package/dist/_pkgs/affine-block-surface/extensions/index.js +4 -0
  40. package/dist/_pkgs/affine-block-surface/extensions/interchange-import.d.ts +172 -0
  41. package/dist/_pkgs/affine-block-surface/extensions/interchange-import.js +393 -0
  42. package/dist/_pkgs/affine-block-surface/extensions/interchange.d.ts +306 -0
  43. package/dist/_pkgs/affine-block-surface/extensions/interchange.js +64 -0
  44. package/dist/_pkgs/affine-block-surface/extensions/map-quality-widget.js +61 -61
  45. package/dist/_pkgs/affine-block-surface/extensions/morph-toolbar.d.ts +248 -0
  46. package/dist/_pkgs/affine-block-surface/extensions/morph-toolbar.js +248 -0
  47. package/dist/_pkgs/affine-block-surface/extensions/reading-widget.js +78 -80
  48. package/dist/_pkgs/affine-block-surface/extensions/reading.js +2 -2
  49. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.d.ts +107 -0
  50. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.js +958 -0
  51. package/dist/_pkgs/affine-block-surface/extensions/validation.d.ts +809 -20
  52. package/dist/_pkgs/affine-block-surface/extensions/validation.js +1661 -50
  53. package/dist/_pkgs/affine-block-surface/extensions/violation-detail-widget.d.ts +50 -6
  54. package/dist/_pkgs/affine-block-surface/extensions/violation-detail-widget.js +129 -32
  55. package/dist/_pkgs/affine-block-surface/framework-background/def.d.ts +289 -0
  56. package/dist/_pkgs/affine-block-surface/framework-background/def.js +126 -1
  57. package/dist/_pkgs/affine-block-surface/framework-background/labels.d.ts +42 -2
  58. package/dist/_pkgs/affine-block-surface/framework-background/labels.js +80 -4
  59. package/dist/_pkgs/affine-block-surface/framework-background/renderer.js +172 -11
  60. package/dist/_pkgs/affine-block-surface/renderer/overlay.js +1 -1
  61. package/dist/_pkgs/affine-block-surface-ref/portal/note.js +2 -2
  62. package/dist/_pkgs/affine-block-table/commands.js +1 -1
  63. package/dist/_pkgs/affine-components/edgeless-shape-color-picker/color-picker.js +1 -1
  64. package/dist/_pkgs/affine-components/embed-card-modal/embed-card-edit-modal.js +1 -1
  65. package/dist/_pkgs/affine-components/filterable-list/styles.js +1 -1
  66. package/dist/_pkgs/affine-components/peek/peekable.js +1 -1
  67. package/dist/_pkgs/affine-components/toolbar/index.d.ts +1 -0
  68. package/dist/_pkgs/affine-components/toolbar/index.js +1 -0
  69. package/dist/_pkgs/affine-components/toolbar/menu-button.js +1 -1
  70. package/dist/_pkgs/affine-components/toolbar/picker-menu.d.ts +55 -0
  71. package/dist/_pkgs/affine-components/toolbar/picker-menu.js +47 -0
  72. package/dist/_pkgs/affine-fragment-frame-panel/body/frame-panel-body.js +2 -2
  73. package/dist/_pkgs/affine-fragment-frame-panel/header/frame-panel-header.js +2 -2
  74. package/dist/_pkgs/affine-fragment-frame-panel/header/frames-setting-menu.js +1 -1
  75. package/dist/_pkgs/affine-fragment-outline/mobile-outline-panel.js +1 -1
  76. package/dist/_pkgs/affine-gfx-brush/toolbar/components/pen/pen-tool-button.js +1 -1
  77. package/dist/_pkgs/affine-gfx-connector/connector-manager.js +7 -10
  78. package/dist/_pkgs/affine-gfx-connector/connector-tool.d.ts +19 -1
  79. package/dist/_pkgs/affine-gfx-connector/connector-tool.js +10 -2
  80. package/dist/_pkgs/affine-gfx-connector/connector-watcher.js +1 -4
  81. package/dist/_pkgs/affine-gfx-connector/direction/direction-reveal.js +2 -1
  82. package/dist/_pkgs/affine-gfx-connector/direction/invert-direction.js +1 -3
  83. package/dist/_pkgs/affine-gfx-connector/element-renderer/index.js +1 -1
  84. package/dist/_pkgs/affine-gfx-connector/element-renderer/utils.js +1 -1
  85. package/dist/_pkgs/affine-gfx-connector/toolbar/config.js +1 -1
  86. package/dist/_pkgs/affine-gfx-mindmap/adapter/markdown/index.js +1 -1
  87. package/dist/_pkgs/affine-gfx-mindmap/adapter/utils.js +1 -1
  88. package/dist/_pkgs/affine-gfx-mindmap/templates/index.js +583 -4
  89. package/dist/_pkgs/affine-gfx-mindmap/toolbar/mindmap-menu.js +23 -23
  90. package/dist/_pkgs/affine-gfx-mindmap/toolbar/mindmap-tool-button.js +5 -1
  91. package/dist/_pkgs/affine-gfx-mindmap/view/utils.js +1 -1
  92. package/dist/_pkgs/affine-gfx-note/overlay/overlay.js +1 -1
  93. package/dist/_pkgs/affine-gfx-note/toolbar/note-senior-button.js +1 -1
  94. package/dist/_pkgs/affine-gfx-shape/consts.js +1 -1
  95. package/dist/_pkgs/affine-gfx-shape/draggable/shape-draggable.js +1 -1
  96. package/dist/_pkgs/affine-gfx-shape/element-renderer/shape/polygon.js +17 -9
  97. package/dist/_pkgs/affine-gfx-shape/element-renderer/shape/utils.js +8 -3
  98. package/dist/_pkgs/affine-gfx-shape/element-view.js +19 -12
  99. package/dist/_pkgs/affine-gfx-shape/overlay/polygon-drawing-overlay.js +1 -1
  100. package/dist/_pkgs/affine-gfx-shape/overlay/polygon-vertex-editing-overlay.js +12 -7
  101. package/dist/_pkgs/affine-gfx-shape/overlay/shape-overlay.js +1 -1
  102. package/dist/_pkgs/affine-gfx-shape/polygon-tool.js +4 -2
  103. package/dist/_pkgs/affine-gfx-shape/shape-tool.js +1 -1
  104. package/dist/_pkgs/affine-gfx-shape/text/edgeless-shape-text-editor.js +1 -3
  105. package/dist/_pkgs/affine-gfx-template/builtin/other.js +66 -17
  106. package/dist/_pkgs/affine-gfx-template/toolbar/overlay-scrollbar.js +1 -1
  107. package/dist/_pkgs/affine-gfx-template/toolbar/template-panel.js +1 -1
  108. package/dist/_pkgs/affine-gfx-text/toolbar/actions.js +1 -1
  109. package/dist/_pkgs/affine-inline-link/command.js +1 -1
  110. package/dist/_pkgs/affine-inline-preset/command/format-block.js +1 -1
  111. package/dist/_pkgs/affine-inline-preset/command/format-native.js +2 -2
  112. package/dist/_pkgs/affine-inline-preset/command/format-text.js +1 -1
  113. package/dist/_pkgs/affine-inline-preset/inline-spec.js +1 -1
  114. package/dist/_pkgs/affine-inline-reference/reference-node/reference-node.js +1 -1
  115. package/dist/_pkgs/affine-model/elements/bpmn/node.d.ts +40 -7
  116. package/dist/_pkgs/affine-model/elements/bpmn/node.js +4 -2
  117. package/dist/_pkgs/affine-model/elements/bpmn/pool.d.ts +74 -17
  118. package/dist/_pkgs/affine-model/elements/bpmn/pool.js +55 -26
  119. package/dist/_pkgs/affine-model/elements/c4/board.d.ts +88 -0
  120. package/dist/_pkgs/affine-model/elements/c4/board.js +128 -0
  121. package/dist/_pkgs/affine-model/elements/c4/boundary.d.ts +63 -0
  122. package/dist/_pkgs/affine-model/elements/c4/boundary.js +134 -0
  123. package/dist/_pkgs/affine-model/elements/c4/index.d.ts +3 -0
  124. package/dist/_pkgs/affine-model/elements/c4/index.js +3 -0
  125. package/dist/_pkgs/affine-model/elements/c4/node.d.ts +97 -0
  126. package/dist/_pkgs/affine-model/elements/c4/node.js +130 -0
  127. package/dist/_pkgs/affine-model/elements/connector/connector.js +1 -1
  128. package/dist/_pkgs/affine-model/elements/context-map/context-map.d.ts +27 -0
  129. package/dist/_pkgs/affine-model/elements/context-map/context-map.js +94 -0
  130. package/dist/_pkgs/affine-model/elements/context-map/index.d.ts +1 -0
  131. package/dist/_pkgs/affine-model/elements/context-map/index.js +1 -0
  132. package/dist/_pkgs/affine-model/elements/core-domain/core-domain.d.ts +34 -17
  133. package/dist/_pkgs/affine-model/elements/core-domain/core-domain.js +28 -26
  134. package/dist/_pkgs/affine-model/elements/event-storming/event-storming.d.ts +36 -0
  135. package/dist/_pkgs/affine-model/elements/event-storming/event-storming.js +103 -0
  136. package/dist/_pkgs/affine-model/elements/event-storming/index.d.ts +1 -0
  137. package/dist/_pkgs/affine-model/elements/event-storming/index.js +1 -0
  138. package/dist/_pkgs/affine-model/elements/index.d.ts +11 -0
  139. package/dist/_pkgs/affine-model/elements/index.js +3 -0
  140. package/dist/_pkgs/affine-model/elements/shape/api/polygon.js +2 -8
  141. package/dist/_pkgs/affine-shared/adapters/html/block-adapter.js +1 -1
  142. package/dist/_pkgs/affine-shared/adapters/markdown/block-adapter.js +1 -1
  143. package/dist/_pkgs/affine-shared/adapters/markdown/delta-converter.js +1 -1
  144. package/dist/_pkgs/affine-shared/adapters/notion-html/block-adapter.js +1 -1
  145. package/dist/_pkgs/affine-shared/adapters/notion-html/delta-converter.js +1 -1
  146. package/dist/_pkgs/affine-shared/adapters/plain-text/block-adapter.js +1 -1
  147. package/dist/_pkgs/affine-shared/adapters/plain-text/delta-converter.js +1 -1
  148. package/dist/_pkgs/affine-shared/adapters/utils/color.js +5 -2
  149. package/dist/_pkgs/affine-shared/commands/model-crud/draft-selected-models.js +1 -1
  150. package/dist/_pkgs/affine-shared/commands/selection/focus-block-end.js +1 -1
  151. package/dist/_pkgs/affine-shared/commands/selection/focus-block-start.js +1 -1
  152. package/dist/_pkgs/affine-shared/consts/index.d.ts +10 -0
  153. package/dist/_pkgs/affine-shared/consts/index.js +10 -0
  154. package/dist/_pkgs/affine-shared/services/artefact-catalogue-service.d.ts +55 -0
  155. package/dist/_pkgs/affine-shared/services/artefact-catalogue-service.js +35 -0
  156. package/dist/_pkgs/affine-shared/services/audit-service.d.ts +11 -0
  157. package/dist/_pkgs/affine-shared/services/command-usage-service.d.ts +31 -0
  158. package/dist/_pkgs/affine-shared/services/command-usage-service.js +109 -0
  159. package/dist/_pkgs/affine-shared/services/comment-service/block-comment-manager.js +1 -1
  160. package/dist/_pkgs/affine-shared/services/doc-display-meta-service.js +1 -1
  161. package/dist/_pkgs/affine-shared/services/embed-iframe/embed-iframe-config.js +1 -1
  162. package/dist/_pkgs/affine-shared/services/index.d.ts +2 -0
  163. package/dist/_pkgs/affine-shared/services/index.js +2 -0
  164. package/dist/_pkgs/affine-shared/services/pivot-materiality-publisher.js +2 -1
  165. package/dist/_pkgs/affine-shared/services/telemetry-service/lifecycle.d.ts +73 -1
  166. package/dist/_pkgs/affine-shared/services/toolbar-service/registry.d.ts +44 -0
  167. package/dist/_pkgs/affine-shared/services/toolbar-service/registry.js +161 -3
  168. package/dist/_pkgs/affine-shared/services/universe-tag-defs-service.js +5 -3
  169. package/dist/_pkgs/affine-shared/test-utils/affine-template.js +1 -1
  170. package/dist/_pkgs/affine-shared/utils/edgeless.js +1 -1
  171. package/dist/_pkgs/affine-shared/utils/file/filesys.d.ts +34 -0
  172. package/dist/_pkgs/affine-shared/utils/file/filesys.js +48 -7
  173. package/dist/_pkgs/affine-shared/utils/zod-schema.js +1 -3
  174. package/dist/_pkgs/affine-widget-drag-handle/utils.js +1 -1
  175. package/dist/_pkgs/affine-widget-edgeless-auto-connect/index.js +1 -1
  176. package/dist/_pkgs/affine-widget-edgeless-dragging-area/edgeless-dragging-area-rect.js +1 -1
  177. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-default.d.ts +14 -0
  178. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-default.js +40 -0
  179. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.d.ts +158 -0
  180. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.js +572 -0
  181. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/catalogue-groups.d.ts +46 -0
  182. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/catalogue-groups.js +66 -0
  183. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/chord-format.d.ts +13 -0
  184. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/chord-format.js +50 -0
  185. package/dist/_pkgs/affine-widget-edgeless-toolbar/edgeless-toolbar.d.ts +6 -0
  186. package/dist/_pkgs/affine-widget-edgeless-toolbar/edgeless-toolbar.js +15 -5
  187. package/dist/_pkgs/affine-widget-edgeless-toolbar/effects.d.ts +2 -0
  188. package/dist/_pkgs/affine-widget-edgeless-toolbar/effects.js +2 -0
  189. package/dist/_pkgs/affine-widget-edgeless-toolbar/extension/index.d.ts +7 -0
  190. package/dist/_pkgs/affine-widget-edgeless-toolbar/index.d.ts +4 -0
  191. package/dist/_pkgs/affine-widget-edgeless-toolbar/index.js +4 -0
  192. package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/command-menu.d.ts +19 -0
  193. package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/command-menu.js +51 -10
  194. package/dist/_pkgs/affine-widget-edgeless-toolbar/view.js +9 -0
  195. package/dist/_pkgs/affine-widget-keyboard-toolbar/keyboard-tool-panel.js +1 -1
  196. package/dist/_pkgs/affine-widget-linked-doc/import-doc/import-doc.js +1 -1
  197. package/dist/_pkgs/affine-widget-linked-doc/linked-doc-popover.js +1 -1
  198. package/dist/_pkgs/affine-widget-page-dragging-area/index.js +1 -1
  199. package/dist/_pkgs/affine-widget-remote-selection/doc/doc-remote-selection.js +1 -1
  200. package/dist/_pkgs/affine-widget-toolbar/toolbar.js +6 -2
  201. package/dist/_pkgs/affine-widget-toolbar/utils.js +6 -2
  202. package/dist/_pkgs/data-view/view-presets/calendar/pc/actions.js +8 -12
  203. package/dist/_pkgs/data-view/view-presets/calendar/pc/view.js +52 -40
  204. package/dist/_pkgs/data-view/view-presets/table/mobile/group.js +3 -1
  205. package/dist/_pkgs/data-view/view-presets/table/pc/group.js +3 -1
  206. package/dist/_pkgs/std/clipboard/utils.js +4 -1
  207. package/dist/_pkgs/std/extension/command-registry.d.ts +159 -5
  208. package/dist/_pkgs/std/extension/command-registry.js +202 -4
  209. package/dist/_pkgs/std/extension/shortcut.js +2 -1
  210. package/dist/_pkgs/std/gfx/grid.js +1 -1
  211. package/dist/_pkgs/std/gfx/index.d.ts +1 -1
  212. package/dist/_pkgs/std/gfx/model/surface/element-model.d.ts +160 -0
  213. package/dist/_pkgs/std/gfx/model/surface/element-model.js +75 -1
  214. package/dist/_pkgs/std/gfx/model/surface/role.js +5 -3
  215. package/dist/_pkgs/std/gfx/model/surface/surface-model.js +2 -1
  216. package/dist/_pkgs/std/gfx/selection.js +1 -1
  217. package/dist/_pkgs/std/gfx/viewport.js +1 -1
  218. package/dist/_pkgs/std/inline/extensions/inline-manager.js +1 -1
  219. package/dist/_pkgs/std/inline/extensions/markdown-matcher.js +1 -1
  220. package/dist/_pkgs/store/model/store/crud.js +4 -1
  221. package/dist/commands.js +1 -1
  222. package/dist/extensions/command-usage.d.ts +23 -0
  223. package/dist/extensions/command-usage.js +37 -0
  224. package/dist/extensions/view.js +12 -0
  225. package/dist/frameworks.js +32 -0
  226. package/dist/translations.js +90 -2
  227. package/package.json +1 -1
@@ -0,0 +1,306 @@
1
+ import { type ServiceProvider } from '../../global/di/index.js';
2
+ import type { GfxPrimitiveElementModel } from '../../std/gfx/index.js';
3
+ import type { ExtensionType } from '../../store/index.js';
4
+ /**
5
+ * The interchange registry (`docs/adr/0012`, P1).
6
+ *
7
+ * Reading a foreign file and writing one are DECLARED PLATFORM CAPABILITIES,
8
+ * registered the way rules and profiles already are — `createIdentifier` plus
9
+ * an `…Extension` helper — and not a function some toolbar happens to call.
10
+ * What that buys is a question the platform can answer about itself: "what can
11
+ * Labre read, what can it write, and for which framework" is a lookup, so the
12
+ * roadmap is a table of real rows rather than a wish.
13
+ *
14
+ * Three properties are load-bearing, and each one is a decision, not a detail.
15
+ *
16
+ * **The unit is the TRIPLE — framework × format × direction.** A direction is
17
+ * never implied by its opposite: BPMN writes `.bpmn` (#149) and cannot read one
18
+ * yet, and a registry that keyed on the format alone would have no way to say
19
+ * so. {@link interchangeCapabilityId} builds the key and
20
+ * {@link InterchangeExtension} refuses a capability whose `id` disagrees with
21
+ * its own three fields, because an id that lies is worse than no id.
22
+ *
23
+ * **The two `run` signatures are mirror images, and neither touches an
24
+ * editor.** An exporter takes element models and returns text; an importer
25
+ * takes text and returns SERIALIZED ELEMENT PROPS — never live models, because
26
+ * it has no surface to add them to and giving it one would cost the purity that
27
+ * lets both halves be unit-tested with plain objects and no DI. The caller does
28
+ * the writing: `surface.addElement` from an editor command, a document mutation
29
+ * from labre-mcp. See P3.
30
+ *
31
+ * **Registration is flag-gated tooling; what it wrote is content.** Call
32
+ * {@link InterchangeExtension} from the framework's FLAG-GATED view extension,
33
+ * beside `ValidationRuleExtension`, because offering to read a file is tooling.
34
+ * Turning a framework's flag off removes its import and export commands; it
35
+ * does not touch one element a past import created. See `docs/adr/0009`.
36
+ */
37
+ /**
38
+ * A format Labre can read or write, and what it PROMISES (ADR 0012, P2).
39
+ *
40
+ * The tier is the single most load-bearing field here, because it is what a
41
+ * user is entitled to expect:
42
+ *
43
+ * - **`semantic`** — the file carries a MODEL (`.bpmn` XML, mermaid, the OWM
44
+ * DSL). Import is a translation, the preservation contract is full (mapped /
45
+ * carried / quarantined), and a round-trip is promised.
46
+ * - **`visual`** — the file carries a RENDERING (SVG). Import is best-effort
47
+ * RECOGNITION, it writes no foreign-matter payload, and it promises exactly
48
+ * one thing: the picture arrives as editable elements. No round-trip is
49
+ * implied, and the import surface must say so before the file is read.
50
+ */
51
+ export interface InterchangeFormat {
52
+ /**
53
+ * Stable id, and THE KEY under which foreign matter is carried on an
54
+ * element — `'bpmn'`, `'owm'`, `'mermaid'`, `'svg'`.
55
+ */
56
+ id: string;
57
+ tier: 'semantic' | 'visual';
58
+ /**
59
+ * For the file picker and the download name — `['.bpmn']`. The FIRST is the
60
+ * one a download is given, and the type says there is one: a format nothing
61
+ * on a disk is ever called is not a format anybody can hand us.
62
+ */
63
+ extensions: readonly [string, ...string[]];
64
+ mime?: string;
65
+ }
66
+ /** Which way round a capability goes. Never both: see the triple, above. */
67
+ export type InterchangeDirection = 'import' | 'export';
68
+ /**
69
+ * One element as it is handed to `surface.addElement` — the exact shape the
70
+ * store already takes, so an importer's output is written with no translation
71
+ * step in between and no live model in sight.
72
+ */
73
+ export type SerializedElementProps = Record<string, unknown> & {
74
+ type: string;
75
+ };
76
+ /**
77
+ * One thing an import did that the drawing does not show, named (ADR 0012).
78
+ *
79
+ * The counts below say how much; a note says WHICH, and the ADR asks for that
80
+ * in five places — D1's quarantined column is "listed in the report", D3
81
+ * "records the substitution" of an id it could not keep and the lane
82
+ * disagreement it resolved, D4 "names" a shape that arrived with no diagram and
83
+ * says so when it laid one out, D5 surfaces `mustUnderstand` "by name". The
84
+ * ADR's own rejection of a document-level side table is the argument for this
85
+ * type: a tool that says "I lost some things" and cannot say which, where, or
86
+ * how to get them back has told the user nothing they can act on.
87
+ */
88
+ export interface InterchangeNote {
89
+ kind: InterchangeNoteKind;
90
+ /** The Labre element it landed on or rides on, when there is one. */
91
+ elementId?: string;
92
+ /** The source element's id, VERBATIM, when it had one (D3). */
93
+ sourceId?: string;
94
+ /** Its source element name — `boundaryEvent`, `bioc:fill` (D1, D5). */
95
+ element?: string;
96
+ /** One line, in the user's words: what happened and what it costs them. */
97
+ message: string;
98
+ }
99
+ /**
100
+ * The five things worth saying about one item, and no sixth.
101
+ *
102
+ * - `carried` — no artefact for it; kept verbatim on the nearest mapped
103
+ * element, invisible on the canvas, re-emitted in place (D1).
104
+ * - `quarantined` — kept in the document and deliberately NOT re-emitted,
105
+ * because re-emitting it would write a file that contradicts the drawing.
106
+ * The four cases are closed and named in D5.
107
+ * - `substituted-id` — the file's id could not be given back, so one was
108
+ * minted. D3's whole point: record what we were given, never reconstruct
109
+ * what we think we sent.
110
+ * - `invented-layout` — a position the source did not carry. D4 forbids
111
+ * claiming an invented position came from the file, so it is declared here.
112
+ * - `warning` — the reader proceeded but its reading may be wrong;
113
+ * `extension/@mustUnderstand="true"` is the named case (D5), a lane the DI
114
+ * and the `flowNodeRef` disagreed about is the other (D3).
115
+ */
116
+ export type InterchangeNoteKind = 'carried' | 'quarantined' | 'substituted-id' | 'invented-layout' | 'warning';
117
+ /**
118
+ * What a semantic import did with every node of the file (ADR 0012, D1).
119
+ *
120
+ * Three states and not two, and the middle one is the whole point: **mapped**
121
+ * became a drawn artefact, **carried** had no artefact and was kept verbatim on
122
+ * the nearest mapped element, **quarantined** was kept in the document but will
123
+ * not be re-emitted, because re-emitting it would produce a file that
124
+ * contradicts itself. A semantic import classifies; it never silently discards.
125
+ *
126
+ * The counts are here because a UI wants a headline it can render without
127
+ * walking a list; {@link notes} is here because a headline is not a product
128
+ * surface. Neither derives from the other — an import may carry a hundred
129
+ * fragments and have three worth naming — so both are stated.
130
+ */
131
+ export interface InterchangeReport {
132
+ /** Nodes that became a drawn, editable artefact. */
133
+ mapped: number;
134
+ /** Nodes kept verbatim on the nearest mapped element, invisible on canvas. */
135
+ carried: number;
136
+ /** Nodes kept but deliberately not re-emitted. */
137
+ quarantined: number;
138
+ /** Which ones, and why. Empty is a claim: nothing was worth naming. */
139
+ notes: readonly InterchangeNote[];
140
+ /**
141
+ * The format version actually read — `'2.0'`, a mermaid release (P2, as
142
+ * amended). Absent when the source declared none, which is itself a fact
143
+ * about the file rather than a gap in the reader.
144
+ */
145
+ sourceVersion?: string;
146
+ }
147
+ /** What the caller tells an exporter about the document it is producing. */
148
+ export interface InterchangeExportContext {
149
+ /**
150
+ * Names the produced document and the file it is offered as — the board's own
151
+ * title. A capability writes a name, it does not go looking for one: the
152
+ * caller reads the title, this says what to do with it.
153
+ *
154
+ * Making it safe to write to disk is the CAPABILITY's job, not the caller's,
155
+ * because the answer is the format's — which characters, which cap, which
156
+ * extension. Pass the raw title. Note the consequence, which is inherited and
157
+ * not introduced here: the sanitized name is also what lands as the
158
+ * document's own name INSIDE the file, so a board titled `Order/to cash` is
159
+ * named `Order-to cash` in the XML as well as on the download.
160
+ */
161
+ name?: string;
162
+ }
163
+ /** What the caller tells an importer about the source it is handing over. */
164
+ export interface InterchangeImportContext {
165
+ /**
166
+ * A name for what is read, used only when the source document names nothing
167
+ * itself. A file that carries its own name always wins: an import states what
168
+ * the file says, and never what the caller wished it said.
169
+ */
170
+ name?: string;
171
+ }
172
+ /**
173
+ * A whole document, as text, plus what a caller needs to hand it to a browser
174
+ * or an HTTP response without knowing which format it asked for.
175
+ */
176
+ export interface InterchangeExportResult {
177
+ /** The document. */
178
+ text: string;
179
+ /** Suggested download name, extension included. */
180
+ filename: string;
181
+ /** `application/xml`, `text/plain`, … — the format's, not the caller's. */
182
+ mime: string;
183
+ /**
184
+ * What the WRITER could not say, one line each, in the user's words. Absent
185
+ * when the board came out whole, which is the usual case.
186
+ *
187
+ * Not a three-way classification — an exporter has nothing foreign to sort,
188
+ * which is why {@link InterchangeReport} is the importer's alone. But an
189
+ * export loses things too: a board can hold sentences the format has no way
190
+ * to write down, and the user who clicked Export is the one person entitled
191
+ * to be told. Warnings are never errors — the file is valid and the export
192
+ * succeeded.
193
+ */
194
+ warnings?: readonly string[];
195
+ }
196
+ /** Element props for the caller to write, and what became of the source. */
197
+ export interface InterchangeImportResult {
198
+ elements: readonly SerializedElementProps[];
199
+ report: InterchangeReport;
200
+ }
201
+ /**
202
+ * The whole board, in document order — never a selection.
203
+ *
204
+ * A framework document is one statement and half a statement is not a smaller
205
+ * one, so the capability is handed the surface's elements and picks out what it
206
+ * speaks about itself. Document order is the caller's, and it matters: it is
207
+ * the tie-break the audit and the validation rules already break on, so an
208
+ * export cannot disagree with a badge the user can see.
209
+ */
210
+ export type InterchangeExporter = (elements: readonly GfxPrimitiveElementModel[], context: InterchangeExportContext) => InterchangeExportResult;
211
+ /**
212
+ * Text in, element props out. No surface, no `std`, no DI — see P3: this is
213
+ * what makes the same function callable from an editor command and from
214
+ * labre-mcp, and testable from neither.
215
+ */
216
+ export type InterchangeImporter = (source: string, context: InterchangeImportContext) => InterchangeImportResult;
217
+ /** Everything a capability declares that does not depend on its direction. */
218
+ export interface InterchangeCapabilityBase {
219
+ /**
220
+ * `${framework}:${format.id}:${direction}` — unique, and the DI key. Build it
221
+ * with {@link interchangeCapabilityId} rather than by hand.
222
+ */
223
+ id: string;
224
+ /** `'bpmn'`, `'wardley'`, `'c4'` — the framework that owns the vocabulary. */
225
+ framework: string;
226
+ format: InterchangeFormat;
227
+ }
228
+ /**
229
+ * One direction of one format for one framework.
230
+ *
231
+ * A UNION discriminated on `direction`, so `run` is the function that direction
232
+ * means and nothing else. This is what makes the triple structural rather than
233
+ * a naming convention: `InterchangeExtension` can refuse an id that lies about
234
+ * its three fields, but only the type system can refuse an importer handed over
235
+ * as an export — no runtime check can tell two functions apart by looking. It
236
+ * also means a caller that has narrowed on `direction` calls `run` directly,
237
+ * with no cast, which is the difference between a registry and a bag.
238
+ */
239
+ export type InterchangeCapability = (InterchangeCapabilityBase & {
240
+ direction: 'export';
241
+ /** The pure function. See P3 — this is the whole contract. */
242
+ run: InterchangeExporter;
243
+ }) | (InterchangeCapabilityBase & {
244
+ direction: 'import';
245
+ /** The pure function. See P3 — this is the whole contract. */
246
+ run: InterchangeImporter;
247
+ });
248
+ /** Narrowed by direction, for a caller that asked the registry for one. */
249
+ export type InterchangeExportCapability = Extract<InterchangeCapability, {
250
+ direction: 'export';
251
+ }>;
252
+ export type InterchangeImportCapability = Extract<InterchangeCapability, {
253
+ direction: 'import';
254
+ }>;
255
+ /** The one way to spell a capability's id. */
256
+ export declare function interchangeCapabilityId(framework: string, formatId: string, direction: InterchangeDirection): string;
257
+ /** A framework registers its interchange here; nothing else registers any. */
258
+ export declare const InterchangeIdentifier: import("../../global/di/types.js").ServiceIdentifier<InterchangeCapability> & (<U extends InterchangeCapability = InterchangeCapability>(variant: import("../../global/di/types.js").ServiceVariant) => import("../../global/di/types.js").ServiceIdentifier<U>);
259
+ /**
260
+ * Register a framework's interchange capabilities. Call it from the FLAG-GATED
261
+ * view extension — offering to read or write a file is tooling, so a disabled
262
+ * framework offers neither, and a board a past import wrote keeps every byte it
263
+ * was given (`docs/adr/0009`).
264
+ *
265
+ * ```ts
266
+ * context.register(InterchangeExtension([BPMN_XML_EXPORT]));
267
+ * ```
268
+ *
269
+ * The id is checked against the triple it claims to be, its parts are checked
270
+ * for the separator that would let two different triples mint one key, and the
271
+ * DI container refuses a second capability under the same id. All three
272
+ * refusals are loud and all three are deliberate: a registry whose keys can lie
273
+ * or collide answers the question "what can Labre read" with something other
274
+ * than the truth, and that question is the only reason this registry exists.
275
+ *
276
+ * They fire at container setup — at boot, or in any test that mounts — never
277
+ * mid-session, and never on a capability built with
278
+ * {@link interchangeCapabilityId}.
279
+ */
280
+ export declare function InterchangeExtension(capabilities: readonly InterchangeCapability[]): ExtensionType;
281
+ /** Narrows {@link interchangeCapabilities}. Every field is optional and ANDed. */
282
+ export interface InterchangeQuery {
283
+ framework?: string;
284
+ /** The format's id, not its extension. */
285
+ format?: string;
286
+ direction?: InterchangeDirection;
287
+ }
288
+ /**
289
+ * The capabilities registered in this assembly, optionally narrowed.
290
+ *
291
+ * Read straight off the DI identifier, exactly as the audit reads the rules:
292
+ * registration is the gate, so a framework whose flag is off contributes
293
+ * nothing here for the same reason it contributes no rule. Sorted by id, so a
294
+ * menu built from this list is in the same order on every boot.
295
+ *
296
+ * Asking for a direction returns that direction's capabilities, typed: a caller
297
+ * that queried for exporters gets `run`s it can call, not a union it must
298
+ * narrow a second time by hand.
299
+ */
300
+ export declare function interchangeCapabilities(provider: ServiceProvider, query: InterchangeQuery & {
301
+ direction: 'export';
302
+ }): InterchangeExportCapability[];
303
+ export declare function interchangeCapabilities(provider: ServiceProvider, query: InterchangeQuery & {
304
+ direction: 'import';
305
+ }): InterchangeImportCapability[];
306
+ export declare function interchangeCapabilities(provider: ServiceProvider, query?: InterchangeQuery): InterchangeCapability[];
@@ -0,0 +1,64 @@
1
+ import { createIdentifier } from '../../global/di/index.js';
2
+ /** The separator the triple is built from, and therefore reserved in its parts. */
3
+ const ID_SEPARATOR = ':';
4
+ /** The one way to spell a capability's id. */
5
+ export function interchangeCapabilityId(framework, formatId, direction) {
6
+ return `${framework}${ID_SEPARATOR}${formatId}${ID_SEPARATOR}${direction}`;
7
+ }
8
+ /** A framework registers its interchange here; nothing else registers any. */
9
+ export const InterchangeIdentifier = createIdentifier('Interchange');
10
+ /**
11
+ * Register a framework's interchange capabilities. Call it from the FLAG-GATED
12
+ * view extension — offering to read or write a file is tooling, so a disabled
13
+ * framework offers neither, and a board a past import wrote keeps every byte it
14
+ * was given (`docs/adr/0009`).
15
+ *
16
+ * ```ts
17
+ * context.register(InterchangeExtension([BPMN_XML_EXPORT]));
18
+ * ```
19
+ *
20
+ * The id is checked against the triple it claims to be, its parts are checked
21
+ * for the separator that would let two different triples mint one key, and the
22
+ * DI container refuses a second capability under the same id. All three
23
+ * refusals are loud and all three are deliberate: a registry whose keys can lie
24
+ * or collide answers the question "what can Labre read" with something other
25
+ * than the truth, and that question is the only reason this registry exists.
26
+ *
27
+ * They fire at container setup — at boot, or in any test that mounts — never
28
+ * mid-session, and never on a capability built with
29
+ * {@link interchangeCapabilityId}.
30
+ */
31
+ export function InterchangeExtension(capabilities) {
32
+ return {
33
+ setup: di => {
34
+ for (const capability of capabilities) {
35
+ // Checked BEFORE the triple is minted from them: `('a', 'b:c')` and
36
+ // `('a:b', 'c')` mint the same key, and the id would agree with itself.
37
+ // Without this, that surfaces as an opaque DI collision instead of the
38
+ // sentence this function already knows how to write.
39
+ for (const [field, value] of [
40
+ ['framework', capability.framework],
41
+ ['format.id', capability.format.id],
42
+ ]) {
43
+ if (value.includes(ID_SEPARATOR)) {
44
+ throw new Error(`Interchange ${field} "${value}" contains "${ID_SEPARATOR}", which separates the parts of a capability id.`);
45
+ }
46
+ }
47
+ const expected = interchangeCapabilityId(capability.framework, capability.format.id, capability.direction);
48
+ if (capability.id !== expected) {
49
+ throw new Error(`Interchange capability id "${capability.id}" is not its triple: expected "${expected}".`);
50
+ }
51
+ di.addImpl(InterchangeIdentifier(capability.id), () => capability);
52
+ }
53
+ },
54
+ };
55
+ }
56
+ export function interchangeCapabilities(provider, query = {}) {
57
+ return [...provider.getAll(InterchangeIdentifier).values()]
58
+ .filter(capability => (query.framework === undefined ||
59
+ capability.framework === query.framework) &&
60
+ (query.format === undefined || capability.format.id === query.format) &&
61
+ (query.direction === undefined ||
62
+ capability.direction === query.direction))
63
+ .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
64
+ }
@@ -149,77 +149,77 @@ let MapQualityWidget = (() => {
149
149
  static { this.styles = [
150
150
  editorAnchoredPanelStyles,
151
151
  css `
152
- /* The box, the layer and the anchoring come from the shared pattern; this
152
+ /* The box, the layer and the anchoring come from the shared pattern; this
153
153
  is the panel's own stacking of sections inside it. */
154
- .map-quality-panel {
155
- display: flex;
156
- flex-direction: column;
157
- gap: 12px;
158
- }
154
+ .map-quality-panel {
155
+ display: flex;
156
+ flex-direction: column;
157
+ gap: 12px;
158
+ }
159
159
 
160
- .map-quality-head {
161
- display: flex;
162
- align-items: center;
163
- justify-content: space-between;
164
- gap: 8px;
165
- font-weight: 600;
166
- }
160
+ .map-quality-head {
161
+ display: flex;
162
+ align-items: center;
163
+ justify-content: space-between;
164
+ gap: 8px;
165
+ font-weight: 600;
166
+ }
167
167
 
168
- .map-quality-close {
169
- border: none;
170
- background: transparent;
171
- color: var(--affine-text-secondary-color);
172
- font-family: inherit;
173
- font-size: 16px;
174
- line-height: 1;
175
- padding: 2px 6px;
176
- border-radius: 4px;
177
- cursor: pointer;
178
- }
168
+ .map-quality-close {
169
+ border: none;
170
+ background: transparent;
171
+ color: var(--affine-text-secondary-color);
172
+ font-family: inherit;
173
+ font-size: 16px;
174
+ line-height: 1;
175
+ padding: 2px 6px;
176
+ border-radius: 4px;
177
+ cursor: pointer;
178
+ }
179
179
 
180
- .map-quality-close:hover {
181
- background: var(--affine-hover-color);
182
- color: var(--affine-text-primary-color);
183
- }
180
+ .map-quality-close:hover {
181
+ background: var(--affine-hover-color);
182
+ color: var(--affine-text-primary-color);
183
+ }
184
184
 
185
- .map-quality-group-label {
186
- color: var(--affine-text-secondary-color);
187
- font-size: 12px;
188
- text-transform: uppercase;
189
- letter-spacing: 0.04em;
190
- }
185
+ .map-quality-group-label {
186
+ color: var(--affine-text-secondary-color);
187
+ font-size: 12px;
188
+ text-transform: uppercase;
189
+ letter-spacing: 0.04em;
190
+ }
191
191
 
192
- /* One column for the control, one for the words. */
193
- .map-quality-nudge {
194
- display: grid;
195
- grid-template-columns: ${unsafeCSS(CHECKBOX_GUTTER)}px 1fr;
196
- align-items: start;
197
- padding: 4px 0;
198
- cursor: pointer;
199
- }
192
+ /* One column for the control, one for the words. */
193
+ .map-quality-nudge {
194
+ display: grid;
195
+ grid-template-columns: ${unsafeCSS(CHECKBOX_GUTTER)}px 1fr;
196
+ align-items: start;
197
+ padding: 4px 0;
198
+ cursor: pointer;
199
+ }
200
200
 
201
- .map-quality-nudge input[disabled] {
202
- cursor: not-allowed;
203
- }
201
+ .map-quality-nudge input[disabled] {
202
+ cursor: not-allowed;
203
+ }
204
204
 
205
- .map-quality-nudge input {
206
- margin: 2px 0 0;
207
- justify-self: start;
208
- }
205
+ .map-quality-nudge input {
206
+ margin: 2px 0 0;
207
+ justify-self: start;
208
+ }
209
209
 
210
- .map-quality-nudge[data-checked='true'] .map-quality-nudge-label {
211
- color: var(--affine-text-secondary-color);
212
- }
210
+ .map-quality-nudge[data-checked='true'] .map-quality-nudge-label {
211
+ color: var(--affine-text-secondary-color);
212
+ }
213
213
 
214
- .map-quality-nudge-label {
215
- overflow-wrap: anywhere;
216
- }
214
+ .map-quality-nudge-label {
215
+ overflow-wrap: anywhere;
216
+ }
217
217
 
218
- .map-quality-close:focus-visible,
219
- .map-quality-nudge input:focus-visible {
220
- outline: 2px solid var(--affine-primary-color);
221
- outline-offset: 1px;
222
- }
218
+ .map-quality-close:focus-visible,
219
+ .map-quality-nudge input:focus-visible {
220
+ outline: 2px solid var(--affine-primary-color);
221
+ outline-offset: 1px;
222
+ }
223
223
  `,
224
224
  ]; }
225
225
  #_openFor_accessor_storage;
@@ -265,7 +265,7 @@ let MapQualityWidget = (() => {
265
265
  */
266
266
  _watchElements() {
267
267
  const wanted = this._openFor !== null;
268
- if (wanted === (this._elementSubscriptions.length > 0))
268
+ if (wanted === this._elementSubscriptions.length > 0)
269
269
  return;
270
270
  for (const subscription of this._elementSubscriptions) {
271
271
  subscription.unsubscribe();