@formicoidea/labre-core 0.50.0 → 0.51.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 (191) hide show
  1. package/dist/_pkgs/affine-block-attachment/asset-picker.d.ts +24 -0
  2. package/dist/_pkgs/affine-block-attachment/asset-picker.js +87 -0
  3. package/dist/_pkgs/affine-block-attachment/configs/slash-menu.js +3 -20
  4. package/dist/_pkgs/affine-block-attachment/index.d.ts +1 -0
  5. package/dist/_pkgs/affine-block-attachment/index.js +1 -0
  6. package/dist/_pkgs/affine-block-attachment/utils.d.ts +9 -1
  7. package/dist/_pkgs/affine-block-attachment/utils.js +9 -0
  8. package/dist/_pkgs/affine-block-bookmark/adapters/markdown/markdown.js +14 -1
  9. package/dist/_pkgs/affine-block-bookmark/adapters/notion-html.js +5 -1
  10. package/dist/_pkgs/affine-block-database/adapters/markdown.js +5 -3
  11. package/dist/_pkgs/affine-block-embed/common/adapters/html.js +5 -3
  12. package/dist/_pkgs/affine-block-embed/common/adapters/markdown.js +11 -0
  13. package/dist/_pkgs/affine-block-frame/frame-template.d.ts +58 -0
  14. package/dist/_pkgs/affine-block-frame/frame-template.js +207 -0
  15. package/dist/_pkgs/affine-block-frame/frame-toolbar.js +19 -3
  16. package/dist/_pkgs/affine-block-frame/index.d.ts +1 -0
  17. package/dist/_pkgs/affine-block-frame/index.js +1 -0
  18. package/dist/_pkgs/affine-block-frame/translations.d.ts +7 -0
  19. package/dist/_pkgs/affine-block-frame/translations.js +16 -1
  20. package/dist/_pkgs/affine-block-frame/view.js +6 -0
  21. package/dist/_pkgs/affine-block-image/asset-picker.d.ts +63 -0
  22. package/dist/_pkgs/affine-block-image/asset-picker.js +183 -0
  23. package/dist/_pkgs/affine-block-image/commands/insert-images.d.ts +5 -0
  24. package/dist/_pkgs/affine-block-image/commands/insert-images.js +8 -8
  25. package/dist/_pkgs/affine-block-image/components/page-image-block.d.ts +11 -0
  26. package/dist/_pkgs/affine-block-image/components/page-image-block.js +81 -12
  27. package/dist/_pkgs/affine-block-image/configs/replace-action.d.ts +9 -0
  28. package/dist/_pkgs/affine-block-image/configs/replace-action.js +27 -0
  29. package/dist/_pkgs/affine-block-image/configs/toolbar.js +6 -0
  30. package/dist/_pkgs/affine-block-image/crop/crop-controller.d.ts +46 -0
  31. package/dist/_pkgs/affine-block-image/crop/crop-controller.js +104 -0
  32. package/dist/_pkgs/affine-block-image/crop/crop-math.d.ts +70 -0
  33. package/dist/_pkgs/affine-block-image/crop/crop-math.js +141 -0
  34. package/dist/_pkgs/affine-block-image/crop/crop-overlay.d.ts +57 -0
  35. package/dist/_pkgs/affine-block-image/crop/crop-overlay.js +343 -0
  36. package/dist/_pkgs/affine-block-image/crop/crop-toolbar.d.ts +12 -0
  37. package/dist/_pkgs/affine-block-image/crop/crop-toolbar.js +78 -0
  38. package/dist/_pkgs/affine-block-image/crop/write-crop.d.ts +16 -0
  39. package/dist/_pkgs/affine-block-image/crop/write-crop.js +57 -0
  40. package/dist/_pkgs/affine-block-image/edgeless-clipboard-config.js +4 -1
  41. package/dist/_pkgs/affine-block-image/effects.js +2 -0
  42. package/dist/_pkgs/affine-block-image/image-block.d.ts +2 -0
  43. package/dist/_pkgs/affine-block-image/image-block.js +2 -0
  44. package/dist/_pkgs/affine-block-image/image-edgeless-block.d.ts +2 -0
  45. package/dist/_pkgs/affine-block-image/image-edgeless-block.js +36 -8
  46. package/dist/_pkgs/affine-block-image/image-resize-manager.js +15 -0
  47. package/dist/_pkgs/affine-block-image/index.d.ts +1 -0
  48. package/dist/_pkgs/affine-block-image/index.js +1 -0
  49. package/dist/_pkgs/affine-block-image/translations.d.ts +15 -0
  50. package/dist/_pkgs/affine-block-image/translations.js +43 -0
  51. package/dist/_pkgs/affine-block-image/utils.d.ts +13 -0
  52. package/dist/_pkgs/affine-block-image/utils.js +10 -1
  53. package/dist/_pkgs/affine-block-root/clipboard/page-clipboard.js +5 -0
  54. package/dist/_pkgs/affine-block-root/commands/page-export-commands.d.ts +2 -0
  55. package/dist/_pkgs/affine-block-root/commands/page-export-commands.js +71 -0
  56. package/dist/_pkgs/affine-block-root/index.d.ts +1 -0
  57. package/dist/_pkgs/affine-block-root/index.js +1 -0
  58. package/dist/_pkgs/affine-block-root/view.js +8 -0
  59. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/capability.d.ts +30 -0
  60. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/capability.js +44 -0
  61. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/colors.d.ts +26 -0
  62. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/colors.js +82 -0
  63. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/command.d.ts +18 -0
  64. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/command.js +91 -0
  65. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/index.d.ts +3 -0
  66. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/index.js +3 -0
  67. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/writer.d.ts +50 -0
  68. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/writer.js +732 -0
  69. package/dist/_pkgs/affine-block-surface/extensions/export-manager/draw-image-block.d.ts +12 -0
  70. package/dist/_pkgs/affine-block-surface/extensions/export-manager/draw-image-block.js +15 -0
  71. package/dist/_pkgs/affine-block-surface/extensions/export-manager/export-manager.js +7 -1
  72. package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.d.ts +7 -1
  73. package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.js +60 -1
  74. package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.d.ts +2 -2
  75. package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.js +2 -2
  76. package/dist/_pkgs/affine-block-surface/extensions/export-svg/marker-version.d.ts +6 -0
  77. package/dist/_pkgs/affine-block-surface/extensions/export-svg/marker-version.js +8 -0
  78. package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.d.ts +28 -1
  79. package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.js +66 -6
  80. package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.d.ts +2 -7
  81. package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.js +2 -6
  82. package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +2 -0
  83. package/dist/_pkgs/affine-block-surface/extensions/index.js +2 -0
  84. package/dist/_pkgs/affine-block-surface/extensions/interchange-export.d.ts +84 -0
  85. package/dist/_pkgs/affine-block-surface/extensions/interchange-export.js +150 -0
  86. package/dist/_pkgs/affine-block-surface/extensions/interchange-import.js +24 -2
  87. package/dist/_pkgs/affine-block-surface/extensions/interchange.d.ts +23 -2
  88. package/dist/_pkgs/affine-block-surface/extensions/interchange.js +4 -1
  89. package/dist/_pkgs/affine-block-surface/extensions/legend-role.d.ts +18 -0
  90. package/dist/_pkgs/affine-block-surface/extensions/legend-role.js +20 -0
  91. package/dist/_pkgs/affine-block-surface/extensions/legend.d.ts +2 -19
  92. package/dist/_pkgs/affine-block-surface/extensions/legend.js +2 -18
  93. package/dist/_pkgs/affine-block-surface/extensions/svg-sanitize.d.ts +67 -0
  94. package/dist/_pkgs/affine-block-surface/extensions/svg-sanitize.js +235 -0
  95. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch-translations.d.ts +1 -0
  96. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch-translations.js +9 -0
  97. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.d.ts +17 -13
  98. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.js +52 -80
  99. package/dist/_pkgs/affine-block-surface/extensions/xml-element.d.ts +98 -0
  100. package/dist/_pkgs/affine-block-surface/extensions/xml-element.js +261 -0
  101. package/dist/_pkgs/affine-block-surface/extensions/xml-reader.d.ts +238 -0
  102. package/dist/_pkgs/affine-block-surface/extensions/xml-reader.js +570 -0
  103. package/dist/_pkgs/affine-block-surface/framework-background/def.js +1 -1
  104. package/dist/_pkgs/affine-block-surface/interchange-headless.d.ts +29 -0
  105. package/dist/_pkgs/affine-block-surface/interchange-headless.js +32 -0
  106. package/dist/_pkgs/affine-block-surface/view.js +22 -2
  107. package/dist/_pkgs/affine-block-table/adapters/utils.js +24 -1
  108. package/dist/_pkgs/affine-gfx-note/toolbar/note-menu.js +5 -8
  109. package/dist/_pkgs/affine-gfx-template/contribute.d.ts +14 -4
  110. package/dist/_pkgs/affine-gfx-template/contribute.js +47 -6
  111. package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.d.ts +7 -2
  112. package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.js +14 -40
  113. package/dist/_pkgs/affine-gfx-template/toolbar/resolve-name.d.ts +1 -1
  114. package/dist/_pkgs/affine-gfx-template/toolbar/resolve-name.js +1 -1
  115. package/dist/_pkgs/affine-gfx-template/toolbar/template-panel.d.ts +4 -4
  116. package/dist/_pkgs/affine-gfx-template/toolbar/template-panel.js +9 -9
  117. package/dist/_pkgs/affine-gfx-template/toolbar/template-type.d.ts +2 -4
  118. package/dist/_pkgs/affine-gfx-template/translations.d.ts +5 -0
  119. package/dist/_pkgs/affine-gfx-template/translations.js +9 -0
  120. package/dist/_pkgs/affine-inline-footnote/adapters/markdown/inline-delta.js +6 -0
  121. package/dist/_pkgs/affine-inline-footnote/adapters/markdown/markdown-inline.js +7 -0
  122. package/dist/_pkgs/affine-inline-link/adapters/html/html-inline.js +4 -1
  123. package/dist/_pkgs/affine-inline-link/adapters/html/inline-delta.js +3 -1
  124. package/dist/_pkgs/affine-inline-link/adapters/markdown/inline-delta.js +4 -1
  125. package/dist/_pkgs/affine-inline-link/adapters/notion-html/html-inline.js +2 -1
  126. package/dist/_pkgs/affine-inline-link/link-node/affine-link.d.ts +7 -0
  127. package/dist/_pkgs/affine-inline-link/link-node/affine-link.js +37 -0
  128. package/dist/_pkgs/affine-inline-link/link-node/index.d.ts +1 -0
  129. package/dist/_pkgs/affine-inline-link/link-node/index.js +1 -0
  130. package/dist/_pkgs/affine-inline-link/link-node/propose-views.d.ts +22 -0
  131. package/dist/_pkgs/affine-inline-link/link-node/propose-views.js +59 -0
  132. package/dist/_pkgs/affine-model/blocks/image/image-crop.d.ts +48 -0
  133. package/dist/_pkgs/affine-model/blocks/image/image-crop.js +78 -0
  134. package/dist/_pkgs/affine-model/blocks/image/image-model.d.ts +6 -0
  135. package/dist/_pkgs/affine-model/blocks/image/image-model.js +2 -0
  136. package/dist/_pkgs/affine-model/blocks/image/index.d.ts +1 -0
  137. package/dist/_pkgs/affine-model/blocks/image/index.js +1 -0
  138. package/dist/_pkgs/affine-model/consts/shape.d.ts +2 -0
  139. package/dist/_pkgs/affine-model/consts/shape.js +5 -0
  140. package/dist/_pkgs/affine-model/elements/bpmn/consts.d.ts +31 -0
  141. package/dist/_pkgs/affine-model/elements/bpmn/consts.js +31 -0
  142. package/dist/_pkgs/affine-model/elements/bpmn/index.d.ts +1 -0
  143. package/dist/_pkgs/affine-model/elements/bpmn/index.js +1 -0
  144. package/dist/_pkgs/affine-model/elements/bpmn/pool.d.ts +0 -25
  145. package/dist/_pkgs/affine-model/elements/bpmn/pool.js +1 -25
  146. package/dist/_pkgs/affine-model/elements/shape/shape.d.ts +0 -2
  147. package/dist/_pkgs/affine-model/elements/shape/shape.js +1 -2
  148. package/dist/_pkgs/affine-model/elements/uml/consts.d.ts +133 -0
  149. package/dist/_pkgs/affine-model/elements/uml/consts.js +107 -0
  150. package/dist/_pkgs/affine-model/elements/uml/diagram.d.ts +1 -79
  151. package/dist/_pkgs/affine-model/elements/uml/diagram.js +1 -53
  152. package/dist/_pkgs/affine-model/elements/uml/fragment.d.ts +0 -15
  153. package/dist/_pkgs/affine-model/elements/uml/fragment.js +1 -15
  154. package/dist/_pkgs/affine-model/elements/uml/index.d.ts +1 -0
  155. package/dist/_pkgs/affine-model/elements/uml/index.js +1 -0
  156. package/dist/_pkgs/affine-model/elements/uml/partition.d.ts +0 -20
  157. package/dist/_pkgs/affine-model/elements/uml/partition.js +1 -20
  158. package/dist/_pkgs/affine-model/elements/uml/region.d.ts +0 -11
  159. package/dist/_pkgs/affine-model/elements/uml/region.js +1 -11
  160. package/dist/_pkgs/affine-model/headless.d.ts +19 -0
  161. package/dist/_pkgs/affine-model/headless.js +19 -0
  162. package/dist/_pkgs/affine-shared/headless.d.ts +10 -0
  163. package/dist/_pkgs/affine-shared/headless.js +10 -0
  164. package/dist/_pkgs/affine-shared/services/asset-picker-service.d.ts +63 -0
  165. package/dist/_pkgs/affine-shared/services/asset-picker-service.js +20 -0
  166. package/dist/_pkgs/affine-shared/services/frame-template-service.d.ts +83 -0
  167. package/dist/_pkgs/affine-shared/services/frame-template-service.js +17 -0
  168. package/dist/_pkgs/affine-shared/services/index.d.ts +2 -0
  169. package/dist/_pkgs/affine-shared/services/index.js +2 -0
  170. package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +6 -0
  171. package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +10 -0
  172. package/dist/_pkgs/affine-widget-drag-handle/watchers/drag-event-watcher.js +8 -3
  173. package/dist/_pkgs/affine-widget-keyboard-toolbar/config.js +4 -16
  174. package/dist/_pkgs/affine-widget-linked-doc/transformers/html.d.ts +7 -0
  175. package/dist/_pkgs/affine-widget-linked-doc/transformers/html.js +25 -24
  176. package/dist/_pkgs/affine-widget-linked-doc/transformers/index.d.ts +1 -1
  177. package/dist/_pkgs/affine-widget-linked-doc/transformers/markdown.d.ts +7 -0
  178. package/dist/_pkgs/affine-widget-linked-doc/transformers/markdown.js +26 -25
  179. package/dist/_pkgs/affine-widget-linked-doc/transformers/utils.d.ts +23 -0
  180. package/dist/_pkgs/affine-widget-linked-doc/transformers/utils.js +14 -0
  181. package/dist/commands.js +5 -2
  182. package/dist/host-panels.d.ts +21 -1
  183. package/dist/host-panels.js +50 -10
  184. package/dist/interchange.d.ts +1 -0
  185. package/dist/interchange.js +1 -0
  186. package/dist/model/headless.d.ts +1 -0
  187. package/dist/model/headless.js +1 -0
  188. package/dist/shared/headless.d.ts +1 -0
  189. package/dist/shared/headless.js +1 -0
  190. package/dist/translations.js +8 -1
  191. package/package.json +13 -1
@@ -0,0 +1,17 @@
1
+ import { createIdentifier } from '../../global/di/index.js';
2
+ export const FrameTemplateProvider = createIdentifier('AffineFrameTemplate');
3
+ /**
4
+ * Host seam: keep frames saved as templates. Absent, the toolbar has no
5
+ * "Save as template", the Templates panel has no "Saved frames" category and
6
+ * nothing is reported when a frame is deleted.
7
+ *
8
+ * `di.override`, like `OutlinePanelExtension`, so a later registration always
9
+ * wins and registering twice never throws at boot.
10
+ */
11
+ export function FrameTemplateExtension(service) {
12
+ return {
13
+ setup: di => {
14
+ di.override(FrameTemplateProvider, () => service);
15
+ },
16
+ };
17
+ }
@@ -1,4 +1,5 @@
1
1
  export * from './artefact-catalogue-service.js';
2
+ export * from './asset-picker-service.js';
2
3
  export * from './audit-service.js';
3
4
  export * from './auto-clear-selection-service.js';
4
5
  export * from './block-meta-service.js';
@@ -18,6 +19,7 @@ export * from './embed-option-service.js';
18
19
  export * from './feature-flag-service.js';
19
20
  export * from './file-size-limit-service.js';
20
21
  export * from './font-loader/index.js';
22
+ export * from './frame-template-service.js';
21
23
  export * from './generate-url-service.js';
22
24
  export * from './keymap-override-service.js';
23
25
  export * from './link-preview-service/index.js';
@@ -1,4 +1,5 @@
1
1
  export * from './artefact-catalogue-service.js';
2
+ export * from './asset-picker-service.js';
2
3
  export * from './audit-service.js';
3
4
  export * from './auto-clear-selection-service.js';
4
5
  export * from './block-meta-service.js';
@@ -18,6 +19,7 @@ export * from './embed-option-service.js';
18
19
  export * from './feature-flag-service.js';
19
20
  export * from './file-size-limit-service.js';
20
21
  export * from './font-loader/index.js';
22
+ export * from './frame-template-service.js';
21
23
  export * from './generate-url-service.js';
22
24
  export * from './keymap-override-service.js';
23
25
  export * from './link-preview-service/index.js';
@@ -509,6 +509,12 @@ export declare const TOOLBAR_INSERT_INTO_PAGE: ChromeWording;
509
509
  * frame's. Was `GROUP_TOOLBAR_UNGROUP` (`gfx/group`).
510
510
  */
511
511
  export declare const TOOLBAR_UNGROUP: ChromeWording;
512
+ /**
513
+ * "Save as template" — a database view's own menu entry, said identically by
514
+ * a frame's toolbar (`FrameTemplateProvider`). Was `VIEW_MENU_SAVE_TEMPLATE`
515
+ * (`database-editor`), whose key it keeps.
516
+ */
517
+ export declare const SAVE_AS_TEMPLATE: ChromeWording;
512
518
  /**
513
519
  * "Mind Map" as chrome — the mindmap tool's own name (template-panel tab,
514
520
  * senior/quick tool tooltips), said identically by the surface-ref slash
@@ -1100,6 +1100,15 @@ export const TOOLBAR_UNGROUP = [
1100
1100
  'com.labre.group.toolbar.ungroup',
1101
1101
  'Ungroup',
1102
1102
  ];
1103
+ /**
1104
+ * "Save as template" — a database view's own menu entry, said identically by
1105
+ * a frame's toolbar (`FrameTemplateProvider`). Was `VIEW_MENU_SAVE_TEMPLATE`
1106
+ * (`database-editor`), whose key it keeps.
1107
+ */
1108
+ export const SAVE_AS_TEMPLATE = [
1109
+ 'com.labre.database.view-menu.save-template',
1110
+ 'Save as template',
1111
+ ];
1103
1112
  /**
1104
1113
  * "Mind Map" as chrome — the mindmap tool's own name (template-panel tab,
1105
1114
  * senior/quick tool tooltips), said identically by the surface-ref slash
@@ -1308,6 +1317,7 @@ export const CHROME_WORDINGS = [
1308
1317
  IMAGE_LABEL,
1309
1318
  TOOLBAR_INSERT_INTO_PAGE,
1310
1319
  TOOLBAR_UNGROUP,
1320
+ SAVE_AS_TEMPLATE,
1311
1321
  MINDMAP_NAME,
1312
1322
  NEW_DOC_LABEL,
1313
1323
  CATALOGUE_OTHER,
@@ -1,7 +1,7 @@
1
1
  import { EMBED_IFRAME_DEFAULT_HEIGHT_IN_SURFACE, EMBED_IFRAME_DEFAULT_WIDTH_IN_SURFACE, } from '../../affine-block-embed/index.js';
2
2
  import { ParagraphBlockComponent } from '../../affine-block-paragraph/index.js';
3
3
  import { DropIndicator } from '../../affine-components/drop-indicator/index.js';
4
- import { AttachmentBlockModel, BookmarkBlockModel, DatabaseBlockModel, DEFAULT_NOTE_HEIGHT, DEFAULT_NOTE_WIDTH, ListBlockModel, NoteBlockModel, RootBlockModel, } from '../../affine-model/index.js';
4
+ import { AttachmentBlockModel, BookmarkBlockModel, DatabaseBlockModel, DEFAULT_NOTE_HEIGHT, DEFAULT_NOTE_WIDTH, ListBlockModel, NoteBlockModel, readImageCrop, RootBlockModel, } from '../../affine-model/index.js';
5
5
  import { surfaceRefToEmbed } from '../../affine-shared/adapters/index.js';
6
6
  import { BLOCK_CHILDREN_CONTAINER_PADDING_LEFT, EMBED_CARD_HEIGHT, EMBED_CARD_WIDTH, } from '../../affine-shared/consts/index.js';
7
7
  import { DndApiExtensionIdentifier, DocModeProvider, EmbedIframeService, TelemetryProvider, } from '../../affine-shared/services/index.js';
@@ -721,8 +721,13 @@ export class DragEventWatcher {
721
721
  }
722
722
  if (block.flavour === 'affine:image') {
723
723
  assertType(block.props);
724
- blockBound.w = blockBound.w || block.props.width || 100;
725
- blockBound.h = blockBound.h || block.props.height || 100;
724
+ // A page image's `width`/`height` are the WHOLE picture; on the
725
+ // canvas the box is the cropped window (ADR 0037).
726
+ const crop = readImageCrop(block.props.crop);
727
+ blockBound.w =
728
+ blockBound.w || block.props.width * (crop?.w ?? 1) || 100;
729
+ blockBound.h =
730
+ blockBound.h || block.props.height * (crop?.h ?? 1) || 100;
726
731
  }
727
732
  if (ignoreOriginalPos) {
728
733
  blockBound.x = modelX;
@@ -1,4 +1,4 @@
1
- import { addSiblingAttachmentBlocks } from '../affine-block-attachment/index.js';
1
+ import { pickAndAddSiblingAttachmentBlocks } from '../affine-block-attachment/index.js';
2
2
  import { insertDatabaseBlockCommand } from '../affine-block-database/index.js';
3
3
  import { insertEmptyEmbedIframeCommand } from '../affine-block-embed/index.js';
4
4
  import { insertImagesCommand } from '../affine-block-image/index.js';
@@ -16,7 +16,7 @@ import { formatBlockCommand, formatNativeCommand, formatTextCommand, getTextAttr
16
16
  import { insertContent } from '../affine-rich-text/index.js';
17
17
  import { copySelectedModelsCommand, deleteSelectedModelsCommand, draftSelectedModelsCommand, duplicateSelectedModelsCommand, getBlockSelectionsCommand, getSelectedModelsCommand, getTextSelectionCommand, } from '../affine-shared/commands/index.js';
18
18
  import { REFERENCE_NODE } from '../affine-shared/consts/index.js';
19
- import { createDefaultDoc, openSingleFileWith, } from '../affine-shared/utils/index.js';
19
+ import { createDefaultDoc } from '../affine-shared/utils/index.js';
20
20
  import { viewPresets } from '../data-view/view-presets/index.js';
21
21
  import { assertType } from '../global/utils/index.js';
22
22
  import { AttachmentIcon, BoldIcon, BulletedListIcon, CheckBoxCheckLinearIcon, CloseIcon, CodeBlockIcon, CodeIcon, CollapseTabIcon, CopyIcon, DatabaseKanbanViewIcon, DatabaseTableViewIcon, DeleteIcon, DividerIcon, DuplicateIcon, EmbedIcon, FontIcon, FrameIcon, GithubIcon, GroupIcon, ImageIcon, ItalicIcon, LinkedPageIcon, LinkIcon, LoomLogoIcon, NewPageIcon, NowIcon, NumberedListIcon, PlusIcon, QuoteIcon, RedoIcon, RightTabIcon, StrikeThroughIcon, TeXIcon, TextIcon, TodayIcon, TomorrowIcon, UnderLineIcon, UndoIcon, YesterdayIcon, YoutubeDuotoneIcon, } from '@blocksuite/icons/lit';
@@ -233,13 +233,7 @@ const contentMediaToolGroup = {
233
233
  const model = selectedModels?.[0];
234
234
  if (!model)
235
235
  return;
236
- const file = await openSingleFileWith();
237
- if (!file)
238
- return;
239
- await addSiblingAttachmentBlocks(std, [file], model);
240
- if (model.text?.length === 0) {
241
- std.store.deleteBlock(model);
242
- }
236
+ await pickAndAddSiblingAttachmentBlocks(std, model);
243
237
  },
244
238
  },
245
239
  {
@@ -778,13 +772,7 @@ export const defaultKeyboardToolbarConfig = {
778
772
  const model = selectedModels?.[0];
779
773
  if (!model)
780
774
  return;
781
- const file = await openSingleFileWith();
782
- if (!file)
783
- return;
784
- await addSiblingAttachmentBlocks(std, [file], model);
785
- if (model.text?.length === 0) {
786
- std.store.deleteBlock(model);
787
- }
775
+ await pickAndAddSiblingAttachmentBlocks(std, model);
788
776
  },
789
777
  },
790
778
  {
@@ -1,4 +1,5 @@
1
1
  import type { ExtensionType, Schema, Store, Workspace } from '../../store/index.js';
2
+ import { type DocExportFile } from './utils.js';
2
3
  type ImportHTMLToDocOptions = {
3
4
  collection: Workspace;
4
5
  schema: Schema;
@@ -12,6 +13,11 @@ type ImportHTMLZipOptions = {
12
13
  imported: Blob;
13
14
  extensions: ExtensionType[];
14
15
  };
16
+ /**
17
+ * A doc as an HTML file, or as a zip of the HTML and its assets when it holds
18
+ * any — without downloading it. `null` when the doc has no snapshot.
19
+ */
20
+ declare function docFile(doc: Store): Promise<DocExportFile | null>;
15
21
  /**
16
22
  * Exports a doc to HTML format.
17
23
  *
@@ -41,6 +47,7 @@ declare function importHTMLToDoc({ collection, schema, html, fileName, extension
41
47
  */
42
48
  declare function importHTMLZip({ collection, schema, imported, extensions, }: ImportHTMLZipOptions): Promise<string[]>;
43
49
  export declare const HtmlTransformer: {
50
+ docFile: typeof docFile;
44
51
  exportDoc: typeof exportDoc;
45
52
  importHTMLToDoc: typeof importHTMLToDoc;
46
53
  importHTMLZip: typeof importHTMLZip;
@@ -1,9 +1,10 @@
1
1
  import { defaultImageProxyMiddleware, docLinkBaseURLMiddleware, fileNameMiddleware, filePathMiddleware, HtmlAdapter, resolveWording, titleMiddleware, } from '../../affine-shared/adapters/index.js';
2
2
  import { CHROME_UNTITLED } from '../../affine-shared/services/index.js';
3
+ import { safeFilename } from '../../affine-shared/utils/index.js';
3
4
  import { Container } from '../../global/di/index.js';
4
5
  import { sha } from '../../global/utils/index.js';
5
6
  import { extMimeMap, Transformer } from '../../store/index.js';
6
- import { createAssetsArchive, download, Unzip } from './utils.js';
7
+ import { download, packDocExport, Unzip } from './utils.js';
7
8
  function getProvider(extensions) {
8
9
  const container = new Container();
9
10
  extensions.forEach(ext => {
@@ -12,41 +13,40 @@ function getProvider(extensions) {
12
13
  return container.provider();
13
14
  }
14
15
  /**
15
- * Exports a doc to HTML format.
16
- *
17
- * @param doc - The doc to be exported.
18
- * @returns A Promise that resolves when the export is complete.
16
+ * A doc as an HTML file, or as a zip of the HTML and its assets when it holds
17
+ * any — without downloading it. `null` when the doc has no snapshot.
19
18
  */
20
- async function exportDoc(doc) {
19
+ async function docFile(doc) {
21
20
  const provider = doc.provider;
22
21
  const job = doc.getTransformer([
23
22
  docLinkBaseURLMiddleware(doc.workspace.id),
24
23
  titleMiddleware(doc.workspace.meta.docMetas),
25
24
  ]);
26
25
  const snapshot = job.docToSnapshot(doc);
26
+ if (!snapshot)
27
+ return null;
27
28
  const adapter = new HtmlAdapter(job, provider);
28
- if (!snapshot) {
29
- return;
30
- }
31
29
  const htmlResult = await adapter.fromDocSnapshot({
32
30
  snapshot,
33
31
  assets: job.assetsManager,
34
32
  });
35
- let downloadBlob;
36
- const docTitle = doc.meta?.title || resolveWording(provider, CHROME_UNTITLED);
37
- let name;
38
- const contentBlob = new Blob([htmlResult.file], { type: 'plain/text' });
39
- if (htmlResult.assetsIds.length > 0) {
40
- const zip = await createAssetsArchive(job.assets, htmlResult.assetsIds);
41
- await zip.file('index.html', contentBlob);
42
- downloadBlob = await zip.generate();
43
- name = `${docTitle}.zip`;
44
- }
45
- else {
46
- downloadBlob = contentBlob;
47
- name = `${docTitle}.html`;
48
- }
49
- download(downloadBlob, name);
33
+ const untitled = resolveWording(provider, CHROME_UNTITLED);
34
+ return packDocExport(htmlResult, job.assets, {
35
+ name: safeFilename(doc.meta?.title, untitled),
36
+ extension: '.html',
37
+ mime: 'text/html;charset=utf-8',
38
+ });
39
+ }
40
+ /**
41
+ * Exports a doc to HTML format.
42
+ *
43
+ * @param doc - The doc to be exported.
44
+ * @returns A Promise that resolves when the export is complete.
45
+ */
46
+ async function exportDoc(doc) {
47
+ const file = await docFile(doc);
48
+ if (file)
49
+ download(file.blob, file.filename);
50
50
  }
51
51
  /**
52
52
  * Imports HTML content into a new doc within a collection.
@@ -160,6 +160,7 @@ async function importHTMLZip({ collection, schema, imported, extensions, }) {
160
160
  return docIds;
161
161
  }
162
162
  export const HtmlTransformer = {
163
+ docFile,
163
164
  exportDoc,
164
165
  importHTMLToDoc,
165
166
  importHTMLZip,
@@ -1,5 +1,5 @@
1
1
  export { HtmlTransformer } from './html.js';
2
2
  export { MarkdownTransformer } from './markdown.js';
3
3
  export { NotionHtmlTransformer } from './notion-html.js';
4
- export { createAssetsArchive, download } from './utils.js';
4
+ export { createAssetsArchive, type DocExportFile, download } from './utils.js';
5
5
  export { ZipTransformer } from './zip.js';
@@ -1,4 +1,5 @@
1
1
  import type { DocMeta, ExtensionType, Schema, Store, Workspace } from '../../store/index.js';
2
+ import { type DocExportFile } from './utils.js';
2
3
  type ParsedFrontmatterMeta = Partial<Pick<DocMeta, 'title' | 'createDate' | 'updatedDate' | 'tags' | 'favorite'>>;
3
4
  /**
4
5
  * Read the frontmatter off a markdown file and hand back the content without
@@ -27,6 +28,11 @@ type ImportMarkdownZipOptions = {
27
28
  imported: Blob;
28
29
  extensions: ExtensionType[];
29
30
  };
31
+ /**
32
+ * A doc as a Markdown file, or as a zip of the Markdown and its assets when it
33
+ * holds any — without downloading it. `null` when the doc has no snapshot.
34
+ */
35
+ declare function docFile(doc: Store): Promise<DocExportFile | null>;
30
36
  /**
31
37
  * Exports a doc to a Markdown file or a zip archive containing Markdown and assets.
32
38
  * @param doc The doc to export
@@ -62,6 +68,7 @@ declare function importMarkdownToDoc({ collection, schema, markdown, fileName, e
62
68
  */
63
69
  declare function importMarkdownZip({ collection, schema, imported, extensions, }: ImportMarkdownZipOptions): Promise<string[]>;
64
70
  export declare const MarkdownTransformer: {
71
+ docFile: typeof docFile;
65
72
  exportDoc: typeof exportDoc;
66
73
  importMarkdownToBlock: typeof importMarkdownToBlock;
67
74
  importMarkdownToDoc: typeof importMarkdownToDoc;
@@ -1,10 +1,11 @@
1
1
  import { defaultImageProxyMiddleware, docLinkBaseURLMiddleware, fileNameMiddleware, filePathMiddleware, MarkdownAdapter, resolveWording, titleMiddleware, } from '../../affine-shared/adapters/index.js';
2
2
  import { CHROME_UNTITLED } from '../../affine-shared/services/index.js';
3
+ import { safeFilename } from '../../affine-shared/utils/index.js';
3
4
  import { Container } from '../../global/di/index.js';
4
5
  import { BlockSuiteError, ErrorCode } from '../../global/exceptions/index.js';
5
6
  import { sha } from '../../global/utils/index.js';
6
7
  import { extMimeMap, Transformer } from '../../store/index.js';
7
- import { createAssetsArchive, download, parseMatter, Unzip, } from './utils.js';
8
+ import { download, packDocExport, parseMatter, Unzip, } from './utils.js';
8
9
  /**
9
10
  * The spellings the tools people export markdown from actually use. Anything
10
11
  * else in the frontmatter is metadata we have no field for, and is dropped.
@@ -137,43 +138,42 @@ function getProvider(extensions) {
137
138
  return container.provider();
138
139
  }
139
140
  /**
140
- * Exports a doc to a Markdown file or a zip archive containing Markdown and assets.
141
- * @param doc The doc to export
142
- * @returns A Promise that resolves when the export is complete
141
+ * A doc as a Markdown file, or as a zip of the Markdown and its assets when it
142
+ * holds any — without downloading it. `null` when the doc has no snapshot.
143
143
  */
144
- async function exportDoc(doc) {
144
+ async function docFile(doc) {
145
145
  const provider = doc.provider;
146
146
  const job = doc.getTransformer([
147
147
  docLinkBaseURLMiddleware(doc.workspace.id),
148
148
  titleMiddleware(doc.workspace.meta.docMetas),
149
149
  ]);
150
150
  const snapshot = job.docToSnapshot(doc);
151
+ if (!snapshot)
152
+ return null;
151
153
  const adapter = new MarkdownAdapter(job, provider);
152
- if (!snapshot) {
153
- return;
154
- }
155
154
  const markdownResult = await adapter.fromDocSnapshot({
156
155
  snapshot,
157
156
  assets: job.assetsManager,
158
157
  });
159
- let downloadBlob;
160
- const docTitle = doc.meta?.title || resolveWording(provider, CHROME_UNTITLED);
161
- let name;
162
- const contentBlob = new Blob([markdownResult.file], { type: 'plain/text' });
163
- if (markdownResult.assetsIds.length > 0) {
164
- if (!job.assets) {
165
- throw new BlockSuiteError(ErrorCode.ValueNotExists, 'No assets found');
166
- }
167
- const zip = await createAssetsArchive(job.assets, markdownResult.assetsIds);
168
- await zip.file('index.md', contentBlob);
169
- downloadBlob = await zip.generate();
170
- name = `${docTitle}.zip`;
171
- }
172
- else {
173
- downloadBlob = contentBlob;
174
- name = `${docTitle}.md`;
158
+ if (markdownResult.assetsIds.length > 0 && !job.assets) {
159
+ throw new BlockSuiteError(ErrorCode.ValueNotExists, 'No assets found');
175
160
  }
176
- download(downloadBlob, name);
161
+ const untitled = resolveWording(provider, CHROME_UNTITLED);
162
+ return packDocExport(markdownResult, job.assets, {
163
+ name: safeFilename(doc.meta?.title, untitled),
164
+ extension: '.md',
165
+ mime: 'text/markdown;charset=utf-8',
166
+ });
167
+ }
168
+ /**
169
+ * Exports a doc to a Markdown file or a zip archive containing Markdown and assets.
170
+ * @param doc The doc to export
171
+ * @returns A Promise that resolves when the export is complete
172
+ */
173
+ async function exportDoc(doc) {
174
+ const file = await docFile(doc);
175
+ if (file)
176
+ download(file.blob, file.filename);
177
177
  }
178
178
  /**
179
179
  * Imports Markdown content into a specific block within a doc.
@@ -328,6 +328,7 @@ async function importMarkdownZip({ collection, schema, imported, extensions, })
328
328
  return docIds;
329
329
  }
330
330
  export const MarkdownTransformer = {
331
+ docFile,
331
332
  exportDoc,
332
333
  importMarkdownToBlock,
333
334
  importMarkdownToDoc,
@@ -32,3 +32,26 @@ export declare const parseMatter: (contents: string) => {
32
32
  metadata: Record<string, FrontmatterValue>;
33
33
  } | null;
34
34
  export declare function download(blob: Blob, name: string): void;
35
+ /**
36
+ * A page exported to a file, before anything is done with it: the bytes and
37
+ * the name a download would give them. What `exportDoc` downloads, and what
38
+ * the `page.export.*` view actions hand to the host instead.
39
+ */
40
+ export interface DocExportFile {
41
+ blob: Blob;
42
+ /** Sanitised, extension included: `Order to cash.md` or `Order to cash.zip`. */
43
+ filename: string;
44
+ }
45
+ /**
46
+ * Pack an adapter's output: the document alone when it references no asset,
47
+ * else a zip holding it as `index.<ext>` beside an `assets/` folder — the
48
+ * relative paths the Markdown and HTML adapters write for images point there.
49
+ */
50
+ export declare function packDocExport(result: {
51
+ file: string;
52
+ assetsIds: string[];
53
+ }, assets: Map<string, Blob>, { name, extension, mime }: {
54
+ name: string;
55
+ extension: string;
56
+ mime: string;
57
+ }): Promise<DocExportFile>;
@@ -214,3 +214,17 @@ export function download(blob, name) {
214
214
  element.remove();
215
215
  URL.revokeObjectURL(fileURL);
216
216
  }
217
+ /**
218
+ * Pack an adapter's output: the document alone when it references no asset,
219
+ * else a zip holding it as `index.<ext>` beside an `assets/` folder — the
220
+ * relative paths the Markdown and HTML adapters write for images point there.
221
+ */
222
+ export async function packDocExport(result, assets, { name, extension, mime }) {
223
+ const content = new Blob([result.file], { type: mime });
224
+ if (result.assetsIds.length === 0) {
225
+ return { blob: content, filename: `${name}${extension}` };
226
+ }
227
+ const zip = await createAssetsArchive(assets, result.assetsIds);
228
+ await zip.file(`index${extension}`, content);
229
+ return { blob: await zip.generate(), filename: `${name}.zip` };
230
+ }
package/dist/commands.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { frameCommands } from './_pkgs/affine-block-frame/index.js';
2
- import { copyLinkCommands, coreCommands, pivotCommands, readingCommands, tagCommands, } from './_pkgs/affine-block-root/index.js';
3
- import { auditCommands, canvasExportCommands, canvasGridCommands, exportSvgCommands, mapQualityCommands, selectionPaneCommands, userLayerCommands, } from './_pkgs/affine-block-surface/index.js';
2
+ import { copyLinkCommands, coreCommands, pageExportCommands, pivotCommands, readingCommands, tagCommands, } from './_pkgs/affine-block-root/index.js';
3
+ import { auditCommands, canvasDrawioExportCommands, canvasExportCommands, canvasGridCommands, canvasSvgExportCommands, exportSvgCommands, mapQualityCommands, selectionPaneCommands, userLayerCommands, } from './_pkgs/affine-block-surface/index.js';
4
4
  import { edgeDirectionCommands } from './_pkgs/affine-gfx-connector/index.js';
5
5
  import { shapeCommands } from './_pkgs/affine-gfx-shape/index.js';
6
6
  import { toCommandManifestEntry, } from './_pkgs/std/index.js';
@@ -49,6 +49,7 @@ export function getCommands(flags) {
49
49
  return buildCommandRegistry([
50
50
  ...coreCommands,
51
51
  ...copyLinkCommands,
52
+ ...pageExportCommands,
52
53
  ...pivotCommands,
53
54
  ...tagCommands,
54
55
  ...readingCommands,
@@ -59,6 +60,8 @@ export function getCommands(flags) {
59
60
  ...frameCommands,
60
61
  ...canvasGridCommands,
61
62
  ...canvasExportCommands,
63
+ ...canvasDrawioExportCommands,
64
+ ...canvasSvgExportCommands,
62
65
  ...userLayerCommands,
63
66
  ...edgeDirectionCommands,
64
67
  ...(isCapabilityEnabled(flags, 'ai-audit') ? auditCommands : []),
@@ -1,5 +1,6 @@
1
1
  import { type FramePreview } from './_pkgs/affine-fragment-frame-panel/index.js';
2
2
  import type { FrameBlockModel } from './_pkgs/affine-model/index.js';
3
+ import { type TranslationParams } from './_pkgs/affine-shared/services/index.js';
3
4
  import { type BlockStdScope, type CommandFile } from './_pkgs/std/index.js';
4
5
  /**
5
6
  * `@labre/affine/host-panels` — the verbs a host's own panel calls (ADR 0034
@@ -121,6 +122,13 @@ export interface ViewAction {
121
122
  label: string;
122
123
  /** The `com.labre.*` key behind {@link label}, for a host that translates itself. */
123
124
  labelKey: string;
125
+ /**
126
+ * The `{{name}}` values {@link labelKey} is filled with, for a host that
127
+ * translates itself — present only on a label that has placeholders (the
128
+ * framework exports: `{ framework, extension }`, the framework's name
129
+ * already resolved). {@link label} has them filled in.
130
+ */
131
+ labelParams?: TranslationParams;
124
132
  /** Stable asset key; `getCommandIcon(std, iconKey)` is the library's icon. */
125
133
  iconKey?: string;
126
134
  /** Present only on a toggle: the state a check mark shows. */
@@ -143,7 +151,8 @@ export interface ViewActionResult {
143
151
  /**
144
152
  * The actions proper to the view the editor shows now, in their declared
145
153
  * order: the commands registered on the `'view-menu'` surface whose `scope`
146
- * is this mode (or `'global'`) and whose `when` holds.
154
+ * is this mode (or `'global'`) and whose `when` holds, and on the canvas
155
+ * one export per framework format the interchange registry can write.
147
156
  *
148
157
  * `mode` is the view the host shows; omitted, it is read from
149
158
  * `DocModeProvider`, and a provider that does not know (the library default
@@ -157,6 +166,17 @@ export interface ViewActionResult {
157
166
  * mode switch: the `std` is rebuilt.
158
167
  */
159
168
  export declare function getViewActions(std: BlockStdScope, mode?: 'page' | 'edgeless'): ViewAction[];
169
+ /**
170
+ * The exports of the view the editor shows now — the `'export'` section of
171
+ * {@link getViewActions}, in the same order: what a host lists in ONE
172
+ * "Export…" menu. On the page: Markdown and HTML. On the canvas: PNG and PDF
173
+ * (with an `ExportManager`), draw.io, SVG (with a canvas renderer), one entry
174
+ * per framework format the registry writes (`canvas.export.<framework>.<format>`,
175
+ * listed while the board holds that framework's elements), then Markdown and
176
+ * HTML. Every one resolves {@link runViewAction} with `{ file }` and downloads
177
+ * nothing.
178
+ */
179
+ export declare function getViewExports(std: BlockStdScope, mode?: 'page' | 'edgeless'): ViewAction[];
160
180
  /**
161
181
  * Run one entry of {@link getViewActions} by its id, through `runCommand`'s
162
182
  * bottleneck (usage and telemetry recorded once), and wait for it.
@@ -1,8 +1,10 @@
1
1
  import { EdgelessFrameManagerIdentifier } from './_pkgs/affine-block-frame/index.js';
2
2
  import { AFFINE_FRAME_PREVIEW, } from './_pkgs/affine-fragment-frame-panel/index.js';
3
- import { DocModeProvider, translateKey } from './_pkgs/affine-shared/services/index.js';
3
+ import { interchangeExportActions } from './_pkgs/affine-block-surface/index.js';
4
+ import { DocModeProvider, translateKey, } from './_pkgs/affine-shared/services/index.js';
4
5
  import { getRegisteredCommands, isCommandAvailable, runCommandAsync, } from './_pkgs/std/index.js';
5
6
  import { GfxControllerIdentifier } from './_pkgs/std/gfx/index.js';
7
+ import { frameworkDescriptor } from './frameworks.js';
6
8
  /**
7
9
  * `@labre/affine/host-panels` — the verbs a host's own panel calls (ADR 0034
8
10
  * §4, docs/integrate/08-host-panels.md).
@@ -129,10 +131,35 @@ export function createFramePreview(std, frame, options = {}) {
129
131
  preview.fillScreen = options.fillScreen;
130
132
  return preview;
131
133
  }
134
+ /**
135
+ * Everything on the `'view-menu'` surface: the registered commands, then
136
+ * one export per framework `*:export` capability in the interchange registry
137
+ * (`interchangeExportActions`, ADR 0034 amendment of 2026-10-14) — derived
138
+ * at read time, so what a flag removed from the registry is not listed.
139
+ */
140
+ function viewMenuEntries(std) {
141
+ const registered = getRegisteredCommands(std)
142
+ .filter(command => command.surfaces.includes('view-menu'))
143
+ .map(command => ({ command }));
144
+ const derived = interchangeExportActions(std).map(({ command, capability }) => {
145
+ const framework = frameworkDescriptor(capability.framework);
146
+ return {
147
+ command,
148
+ labelParams: {
149
+ framework: framework
150
+ ? translateKey(std, framework.labelKey, framework.labelFallback)
151
+ : capability.framework,
152
+ extension: capability.format.extensions[0],
153
+ },
154
+ };
155
+ });
156
+ return [...registered, ...derived];
157
+ }
132
158
  /**
133
159
  * The actions proper to the view the editor shows now, in their declared
134
160
  * order: the commands registered on the `'view-menu'` surface whose `scope`
135
- * is this mode (or `'global'`) and whose `when` holds.
161
+ * is this mode (or `'global'`) and whose `when` holds, and on the canvas
162
+ * one export per framework format the interchange registry can write.
136
163
  *
137
164
  * `mode` is the view the host shows; omitted, it is read from
138
165
  * `DocModeProvider`, and a provider that does not know (the library default
@@ -147,21 +174,34 @@ export function createFramePreview(std, frame, options = {}) {
147
174
  */
148
175
  export function getViewActions(std, mode) {
149
176
  const view = mode ?? std.getOptional(DocModeProvider)?.getEditorMode();
150
- return getRegisteredCommands(std)
151
- .filter(command => command.surfaces.includes('view-menu'))
152
- .filter(command => command.scope === 'global' || !view || command.scope === view)
153
- .filter(command => !command.when || command.when(std))
154
- .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
155
- .map(command => ({
177
+ return viewMenuEntries(std)
178
+ .filter(({ command }) => command.scope === 'global' || !view || command.scope === view)
179
+ .filter(({ command }) => !command.when || command.when(std))
180
+ .sort((a, b) => (a.command.order ?? 0) - (b.command.order ?? 0))
181
+ .map(({ command, labelParams }) => ({
156
182
  id: command.id,
157
183
  section: command.category ?? 'display',
158
- label: translateKey(std, command.labelKey, command.labelFallback),
184
+ label: translateKey(std, command.labelKey, command.labelFallback, labelParams),
159
185
  labelKey: command.labelKey,
186
+ ...(labelParams ? { labelParams } : {}),
160
187
  ...(command.iconKey ? { iconKey: command.iconKey } : {}),
161
188
  ...(command.checked ? { checked: command.checked(std) } : {}),
162
189
  disabled: !isCommandAvailable(std, command),
163
190
  }));
164
191
  }
192
+ /**
193
+ * The exports of the view the editor shows now — the `'export'` section of
194
+ * {@link getViewActions}, in the same order: what a host lists in ONE
195
+ * "Export…" menu. On the page: Markdown and HTML. On the canvas: PNG and PDF
196
+ * (with an `ExportManager`), draw.io, SVG (with a canvas renderer), one entry
197
+ * per framework format the registry writes (`canvas.export.<framework>.<format>`,
198
+ * listed while the board holds that framework's elements), then Markdown and
199
+ * HTML. Every one resolves {@link runViewAction} with `{ file }` and downloads
200
+ * nothing.
201
+ */
202
+ export function getViewExports(std, mode) {
203
+ return getViewActions(std, mode).filter(action => action.section === 'export');
204
+ }
165
205
  /**
166
206
  * Run one entry of {@link getViewActions} by its id, through `runCommand`'s
167
207
  * bottleneck (usage and telemetry recorded once), and wait for it.
@@ -174,7 +214,7 @@ export function getViewActions(std, mode) {
174
214
  * with no file.
175
215
  */
176
216
  export async function runViewAction(std, id) {
177
- const command = getRegisteredCommands(std).find(candidate => candidate.id === id && candidate.surfaces.includes('view-menu'));
217
+ const command = viewMenuEntries(std).find(entry => entry.command.id === id)?.command;
178
218
  if (!command)
179
219
  return {};
180
220
  if (command.when && !command.when(std))
@@ -0,0 +1 @@
1
+ export * from './_pkgs/affine-block-surface/interchange-headless.js';
@@ -0,0 +1 @@
1
+ export * from './_pkgs/affine-block-surface/interchange-headless.js';
@@ -0,0 +1 @@
1
+ export * from '../_pkgs/affine-model/headless.js';
@@ -0,0 +1 @@
1
+ export * from '../_pkgs/affine-model/headless.js';
@@ -0,0 +1 @@
1
+ export * from '../_pkgs/affine-shared/headless.js';
@@ -0,0 +1 @@
1
+ export * from '../_pkgs/affine-shared/headless.js';