@formicoidea/labre-core 0.41.0 → 0.43.1
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.
- package/LICENSE +384 -0
- package/dist/_pkgs/affine-block-bookmark/bookmark-block.js +2 -2
- package/dist/_pkgs/affine-block-data-view/configs/tooltips.js +1 -1
- package/dist/_pkgs/affine-block-database/configs/tooltips.js +1 -1
- package/dist/_pkgs/affine-block-edgeless-text/edgeless-text-block.js +4 -2
- package/dist/_pkgs/affine-block-edgeless-text/edgeless-toolbar/config.js +7 -1
- package/dist/_pkgs/affine-block-embed/common/iframe-sandbox.d.ts +39 -0
- package/dist/_pkgs/affine-block-embed/common/iframe-sandbox.js +39 -0
- package/dist/_pkgs/affine-block-embed/embed-figma-block/embed-figma-block.js +4 -1
- package/dist/_pkgs/affine-block-embed/embed-github-block/embed-github-block.js +2 -1
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-error-card.d.ts +14 -1
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-error-card.js +21 -2
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/consts.js +2 -0
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.d.ts +2 -1
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.js +41 -11
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/types.d.ts +16 -0
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/types.js +17 -1
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/utils.d.ts +8 -0
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/utils.js +19 -0
- package/dist/_pkgs/affine-block-embed/embed-loom-block/embed-loom-block.js +4 -1
- package/dist/_pkgs/affine-block-embed/embed-youtube-block/embed-youtube-block.js +4 -1
- package/dist/_pkgs/affine-block-embed/index.d.ts +1 -0
- package/dist/_pkgs/affine-block-embed/index.js +1 -0
- package/dist/_pkgs/affine-block-embed/translations.d.ts +8 -0
- package/dist/_pkgs/affine-block-embed/translations.js +28 -0
- package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/embed-linked-doc-block.js +4 -2
- package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-synced-doc-block.js +2 -2
- package/dist/_pkgs/affine-block-frame/frame-manager.js +6 -3
- package/dist/_pkgs/affine-block-frame/frame-tool.js +1 -1
- package/dist/_pkgs/affine-block-frame/frame-toolbar.js +6 -1
- package/dist/_pkgs/affine-block-list/list-keymap.js +7 -0
- package/dist/_pkgs/affine-block-list/utils/get-list-icon.js +3 -1
- package/dist/_pkgs/affine-block-note/configs/tooltips.js +1 -1
- package/dist/_pkgs/affine-block-note/note-keymap.js +7 -1
- package/dist/_pkgs/affine-block-paragraph/paragraph-keymap.js +7 -1
- package/dist/_pkgs/affine-block-root/adapters/html.js +2 -2
- package/dist/_pkgs/affine-block-root/commands/copy-link-commands.d.ts +2 -0
- package/dist/_pkgs/affine-block-root/commands/copy-link-commands.js +155 -0
- package/dist/_pkgs/affine-block-root/commands/pivot-commands.js +1 -8
- package/dist/_pkgs/affine-block-root/commands/tag-commands.js +1 -8
- package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.d.ts +9 -0
- package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.js +51 -0
- package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.d.ts +22 -0
- package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.js +46 -0
- package/dist/_pkgs/affine-block-root/edgeless/utils/pinch-zoom.d.ts +21 -0
- package/dist/_pkgs/affine-block-root/edgeless/utils/pinch-zoom.js +24 -0
- package/dist/_pkgs/affine-block-root/edgeless/utils/query.js +8 -0
- package/dist/_pkgs/affine-block-root/index.d.ts +1 -0
- package/dist/_pkgs/affine-block-root/index.js +1 -0
- package/dist/_pkgs/affine-block-root/keyboard/keymap.js +1 -16
- package/dist/_pkgs/affine-block-root/view.js +2 -0
- package/dist/_pkgs/affine-block-surface/element-model/index.d.ts +21 -3
- package/dist/_pkgs/affine-block-surface/element-model/index.js +14 -2
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.d.ts +23 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.js +89 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.d.ts +7 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.js +5 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.d.ts +41 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.js +70 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.d.ts +49 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.js +257 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/tagged-path.d.ts +16 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/tagged-path.js +24 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/toolbar.d.ts +24 -0
- package/dist/_pkgs/affine-block-surface/extensions/export-svg/toolbar.js +66 -0
- package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +4 -0
- package/dist/_pkgs/affine-block-surface/extensions/index.js +4 -0
- package/dist/_pkgs/affine-block-surface/extensions/interchange-import.d.ts +66 -4
- package/dist/_pkgs/affine-block-surface/extensions/interchange-import.js +253 -11
- package/dist/_pkgs/affine-block-surface/extensions/interchange.d.ts +18 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend-toolbar.d.ts +81 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend-toolbar.js +81 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend.d.ts +144 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend.js +495 -0
- package/dist/_pkgs/affine-block-surface/extensions/morph-toolbar.js +4 -0
- package/dist/_pkgs/affine-block-surface/extensions/reading-widget.d.ts +17 -3
- package/dist/_pkgs/affine-block-surface/extensions/reading-widget.js +35 -13
- package/dist/_pkgs/affine-block-surface/extensions/reading.d.ts +61 -1
- package/dist/_pkgs/affine-block-surface/extensions/reading.js +85 -39
- package/dist/_pkgs/affine-block-surface/extensions/record-action.d.ts +66 -0
- package/dist/_pkgs/affine-block-surface/extensions/record-action.js +145 -0
- package/dist/_pkgs/affine-block-surface/extensions/svg-sketch-translations.d.ts +3 -0
- package/dist/_pkgs/affine-block-surface/extensions/svg-sketch-translations.js +23 -0
- package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.d.ts +1 -1
- package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.js +12 -4
- package/dist/_pkgs/affine-block-surface/extensions/validation.d.ts +253 -28
- package/dist/_pkgs/affine-block-surface/extensions/validation.js +489 -41
- package/dist/_pkgs/affine-block-surface/framework-background/background-view.d.ts +115 -0
- package/dist/_pkgs/affine-block-surface/framework-background/background-view.js +185 -0
- package/dist/_pkgs/affine-block-surface/framework-background/fit.d.ts +36 -0
- package/dist/_pkgs/affine-block-surface/framework-background/fit.js +30 -0
- package/dist/_pkgs/affine-block-surface/framework-background/index.d.ts +2 -0
- package/dist/_pkgs/affine-block-surface/framework-background/index.js +2 -0
- package/dist/_pkgs/affine-block-surface/framework-background/labels.d.ts +16 -1
- package/dist/_pkgs/affine-block-surface/framework-background/labels.js +31 -21
- package/dist/_pkgs/affine-block-surface/framework-background/renderer.js +29 -5
- package/dist/_pkgs/affine-block-surface/framework-background/stacking.d.ts +6 -4
- package/dist/_pkgs/affine-block-surface/framework-background/stacking.js +56 -8
- package/dist/_pkgs/affine-block-surface/renderer/canvas-renderer.d.ts +12 -0
- package/dist/_pkgs/affine-block-surface/renderer/canvas-renderer.js +15 -0
- package/dist/_pkgs/affine-block-surface/renderer/element-highlight-overlay.js +2 -7
- package/dist/_pkgs/affine-block-surface/view.js +8 -1
- package/dist/_pkgs/affine-block-surface-ref/configs/slash-menu.js +1 -1
- package/dist/_pkgs/affine-block-surface-ref/configs/tooltips.js +2 -2
- package/dist/_pkgs/affine-components/color-picker/button.d.ts +56 -1
- package/dist/_pkgs/affine-components/color-picker/button.js +168 -23
- package/dist/_pkgs/affine-components/color-picker/framework-palette.d.ts +106 -0
- package/dist/_pkgs/affine-components/color-picker/framework-palette.js +177 -0
- package/dist/_pkgs/affine-components/color-picker/index.d.ts +2 -0
- package/dist/_pkgs/affine-components/color-picker/index.js +2 -0
- package/dist/_pkgs/affine-components/color-picker/palette-carousel.d.ts +85 -0
- package/dist/_pkgs/affine-components/color-picker/palette-carousel.js +445 -0
- package/dist/_pkgs/affine-components/color-picker/styles.js +1 -1
- package/dist/_pkgs/affine-components/context-menu/button.js +3 -1
- package/dist/_pkgs/affine-components/edgeless-shape-color-picker/color-picker.d.ts +31 -1
- package/dist/_pkgs/affine-components/edgeless-shape-color-picker/color-picker.js +189 -63
- package/dist/_pkgs/affine-components/icons/ai.js +3 -3
- package/dist/_pkgs/affine-components/icons/list.js +7 -1
- package/dist/_pkgs/affine-components/resource/resource.js +29 -16
- package/dist/_pkgs/affine-components/size-dropdown-menu/dropdown-menu.js +6 -1
- package/dist/_pkgs/affine-components/toolbar/index.d.ts +1 -1
- package/dist/_pkgs/affine-components/toolbar/index.js +1 -1
- package/dist/_pkgs/affine-components/toolbar/menu-button.d.ts +7 -0
- package/dist/_pkgs/affine-components/toolbar/menu-button.js +30 -0
- package/dist/_pkgs/affine-components/toolbar/picker-menu.d.ts +16 -1
- package/dist/_pkgs/affine-components/toolbar/picker-menu.js +2 -2
- package/dist/_pkgs/affine-components/toolbar/toolbar.d.ts +1 -0
- package/dist/_pkgs/affine-components/toolbar/toolbar.js +67 -0
- package/dist/_pkgs/affine-components/translations.d.ts +8 -0
- package/dist/_pkgs/affine-components/translations.js +17 -0
- package/dist/_pkgs/affine-foundation/view.js +2 -1
- package/dist/_pkgs/affine-fragment-frame-panel/card/frame-card-title-editor.js +1 -1
- package/dist/_pkgs/affine-fragment-frame-panel/card/frame-card.js +1 -1
- package/dist/_pkgs/affine-gfx-brush/element-renderer.js +2 -2
- package/dist/_pkgs/affine-gfx-brush/toolbar/components/eraser/icons.js +1 -1
- package/dist/_pkgs/affine-gfx-brush/toolbar/configs/brush.js +6 -1
- package/dist/_pkgs/affine-gfx-brush/toolbar/configs/highlighter.js +6 -1
- package/dist/_pkgs/affine-gfx-connector/connector-manager.d.ts +9 -1
- package/dist/_pkgs/affine-gfx-connector/connector-manager.js +61 -0
- package/dist/_pkgs/affine-gfx-connector/direction/direction-reveal.d.ts +11 -2
- package/dist/_pkgs/affine-gfx-connector/direction/direction-reveal.js +11 -2
- package/dist/_pkgs/affine-gfx-connector/element-renderer/connector-dom/index.d.ts +7 -1
- package/dist/_pkgs/affine-gfx-connector/element-renderer/connector-dom/index.js +87 -17
- package/dist/_pkgs/affine-gfx-connector/element-renderer/index.js +78 -17
- package/dist/_pkgs/affine-gfx-connector/element-renderer/utils.d.ts +24 -2
- package/dist/_pkgs/affine-gfx-connector/element-renderer/utils.js +31 -8
- package/dist/_pkgs/affine-gfx-connector/text/edgeless-connector-label-editor.d.ts +124 -3
- package/dist/_pkgs/affine-gfx-connector/text/edgeless-connector-label-editor.js +219 -56
- package/dist/_pkgs/affine-gfx-connector/text/text.d.ts +13 -4
- package/dist/_pkgs/affine-gfx-connector/text/text.js +13 -44
- package/dist/_pkgs/affine-gfx-connector/toolbar/config.d.ts +56 -0
- package/dist/_pkgs/affine-gfx-connector/toolbar/config.js +94 -10
- package/dist/_pkgs/affine-gfx-connector/toolbar/hollow-endpoint-icons.d.ts +8 -0
- package/dist/_pkgs/affine-gfx-connector/toolbar/hollow-endpoint-icons.js +118 -0
- package/dist/_pkgs/affine-gfx-connector/translations.d.ts +3 -0
- package/dist/_pkgs/affine-gfx-connector/translations.js +23 -0
- package/dist/_pkgs/affine-gfx-connector/view/view.d.ts +37 -1
- package/dist/_pkgs/affine-gfx-connector/view/view.js +97 -8
- package/dist/_pkgs/affine-gfx-group/command/group-api.js +1 -1
- package/dist/_pkgs/affine-gfx-group/store.js +0 -2
- package/dist/_pkgs/affine-gfx-group/translations.d.ts +9 -10
- package/dist/_pkgs/affine-gfx-group/translations.js +9 -13
- package/dist/_pkgs/affine-gfx-mindmap/indicator-overlay/index.js +6 -2
- package/dist/_pkgs/affine-gfx-mindmap/templates/index.js +1 -1
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/basket-elements.js +1 -1
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/config.js +4 -2
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/utils/import-mindmap.js +2 -2
- package/dist/_pkgs/affine-gfx-mindmap/translations.d.ts +7 -1
- package/dist/_pkgs/affine-gfx-mindmap/translations.js +11 -1
- package/dist/_pkgs/affine-gfx-shape/element-renderer/highlighter.js +2 -2
- package/dist/_pkgs/affine-gfx-shape/overlay/polygon-drawing-overlay.d.ts +6 -0
- package/dist/_pkgs/affine-gfx-shape/overlay/polygon-drawing-overlay.js +30 -1
- package/dist/_pkgs/affine-gfx-shape/polygon-tool.d.ts +20 -1
- package/dist/_pkgs/affine-gfx-shape/polygon-tool.js +9 -1
- package/dist/_pkgs/affine-gfx-shape/toolbar/config.js +10 -3
- package/dist/_pkgs/affine-gfx-shape/toolbar/palette-color-action.js +11 -1
- package/dist/_pkgs/affine-gfx-shape/translations.d.ts +7 -0
- package/dist/_pkgs/affine-gfx-shape/translations.js +11 -0
- package/dist/_pkgs/affine-gfx-template/builtin/other.js +14 -8
- package/dist/_pkgs/affine-gfx-template/snapshot-from-action.js +32 -119
- package/dist/_pkgs/affine-gfx-template/toolbar/template-loading.js +1 -1
- package/dist/_pkgs/affine-gfx-template/toolbar/template-type.d.ts +1 -1
- package/dist/_pkgs/affine-gfx-template/translations.d.ts +5 -0
- package/dist/_pkgs/affine-gfx-template/translations.js +38 -0
- package/dist/_pkgs/affine-gfx-text/dblclick-add-edgeless-text.d.ts +13 -1
- package/dist/_pkgs/affine-gfx-text/dblclick-add-edgeless-text.js +19 -4
- package/dist/_pkgs/affine-gfx-text/edgeless-text-editor.d.ts +41 -0
- package/dist/_pkgs/affine-gfx-text/edgeless-text-editor.js +60 -4
- package/dist/_pkgs/affine-gfx-text/toolbar/actions.d.ts +8 -1
- package/dist/_pkgs/affine-gfx-text/toolbar/actions.js +14 -2
- package/dist/_pkgs/affine-gfx-text/translations.d.ts +9 -0
- package/dist/_pkgs/affine-gfx-text/translations.js +14 -1
- package/dist/_pkgs/affine-inline-latex/latex-node/latex-editor-menu.js +2 -1
- package/dist/_pkgs/affine-inline-preset/markdown.js +5 -1
- package/dist/_pkgs/affine-model/consts/connector.d.ts +28 -2
- package/dist/_pkgs/affine-model/consts/connector.js +26 -0
- package/dist/_pkgs/affine-model/consts/text.d.ts +15 -2
- package/dist/_pkgs/affine-model/consts/text.js +25 -1
- package/dist/_pkgs/affine-model/elements/bpmn/pool.js +1 -1
- package/dist/_pkgs/affine-model/elements/brush/brush.js +1 -1
- package/dist/_pkgs/affine-model/elements/c4/board.js +1 -1
- package/dist/_pkgs/affine-model/elements/c4/boundary.js +1 -1
- package/dist/_pkgs/affine-model/elements/connector/connector.d.ts +135 -0
- package/dist/_pkgs/affine-model/elements/connector/connector.js +246 -5
- package/dist/_pkgs/affine-model/elements/connector/end-label.d.ts +83 -0
- package/dist/_pkgs/affine-model/elements/connector/end-label.js +119 -0
- package/dist/_pkgs/affine-model/elements/connector/index.d.ts +1 -0
- package/dist/_pkgs/affine-model/elements/connector/index.js +1 -0
- package/dist/_pkgs/affine-model/elements/context-map/context-map.js +1 -1
- package/dist/_pkgs/affine-model/elements/core-domain/core-domain.d.ts +28 -0
- package/dist/_pkgs/affine-model/elements/core-domain/core-domain.js +129 -2
- package/dist/_pkgs/affine-model/elements/cynefin/cynefin.d.ts +8 -0
- package/dist/_pkgs/affine-model/elements/cynefin/cynefin.js +45 -2
- package/dist/_pkgs/affine-model/elements/edgy/board.js +1 -1
- package/dist/_pkgs/affine-model/elements/edgy/facets.js +1 -1
- package/dist/_pkgs/affine-model/elements/estuarine/estuarine.d.ts +6 -0
- package/dist/_pkgs/affine-model/elements/estuarine/estuarine.js +36 -2
- package/dist/_pkgs/affine-model/elements/event-storming/event-storming.d.ts +18 -7
- package/dist/_pkgs/affine-model/elements/event-storming/event-storming.js +23 -8
- package/dist/_pkgs/affine-model/elements/framework-background/background.d.ts +16 -0
- package/dist/_pkgs/affine-model/elements/framework-background/background.js +18 -0
- package/dist/_pkgs/affine-model/elements/highlighter/highlighter.js +1 -1
- package/dist/_pkgs/affine-model/elements/index.d.ts +8 -0
- package/dist/_pkgs/affine-model/elements/index.js +1 -0
- package/dist/_pkgs/affine-model/elements/shape/shape.js +1 -1
- package/dist/_pkgs/affine-model/elements/text/text.js +1 -1
- package/dist/_pkgs/affine-model/elements/uml/band.d.ts +39 -0
- package/dist/_pkgs/affine-model/elements/uml/band.js +31 -0
- package/dist/_pkgs/affine-model/elements/uml/diagram.d.ts +158 -0
- package/dist/_pkgs/affine-model/elements/uml/diagram.js +229 -0
- package/dist/_pkgs/affine-model/elements/uml/fragment.d.ts +161 -0
- package/dist/_pkgs/affine-model/elements/uml/fragment.js +205 -0
- package/dist/_pkgs/affine-model/elements/uml/index.d.ts +8 -0
- package/dist/_pkgs/affine-model/elements/uml/index.js +8 -0
- package/dist/_pkgs/affine-model/elements/uml/lifeline.d.ts +77 -0
- package/dist/_pkgs/affine-model/elements/uml/lifeline.js +89 -0
- package/dist/_pkgs/affine-model/elements/uml/node.d.ts +142 -0
- package/dist/_pkgs/affine-model/elements/uml/node.js +190 -0
- package/dist/_pkgs/affine-model/elements/uml/partition.d.ts +106 -0
- package/dist/_pkgs/affine-model/elements/uml/partition.js +172 -0
- package/dist/_pkgs/affine-model/elements/uml/region.d.ts +75 -0
- package/dist/_pkgs/affine-model/elements/uml/region.js +150 -0
- package/dist/_pkgs/affine-model/elements/uml/subject.d.ts +37 -0
- package/dist/_pkgs/affine-model/elements/uml/subject.js +108 -0
- package/dist/_pkgs/affine-model/elements/wardley/wardley.js +1 -1
- package/dist/_pkgs/affine-shared/services/embed-iframe/embed-iframe-config.d.ts +1 -0
- package/dist/_pkgs/affine-shared/services/font-loader/config.d.ts +18 -0
- package/dist/_pkgs/affine-shared/services/font-loader/config.js +82 -50
- package/dist/_pkgs/affine-shared/services/pivot-materiality-publisher.js +1 -9
- package/dist/_pkgs/affine-shared/services/telemetry-service/document-damage-watcher.d.ts +53 -0
- package/dist/_pkgs/affine-shared/services/telemetry-service/document-damage-watcher.js +95 -0
- package/dist/_pkgs/affine-shared/services/telemetry-service/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/services/telemetry-service/index.js +1 -0
- package/dist/_pkgs/affine-shared/services/telemetry-service/lifecycle.d.ts +26 -1
- package/dist/_pkgs/affine-shared/services/telemetry-service/telemetry-service.d.ts +2 -2
- package/dist/_pkgs/affine-shared/services/theme-service.d.ts +19 -0
- package/dist/_pkgs/affine-shared/services/theme-service.js +24 -0
- package/dist/_pkgs/affine-shared/services/toolbar-service/command-action.d.ts +34 -0
- package/dist/_pkgs/affine-shared/services/toolbar-service/command-action.js +63 -0
- package/dist/_pkgs/affine-shared/services/toolbar-service/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/services/toolbar-service/index.js +1 -0
- package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +97 -7
- package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +178 -7
- package/dist/_pkgs/affine-shared/styles/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/styles/index.js +1 -0
- package/dist/_pkgs/affine-shared/styles/motion.d.ts +14 -0
- package/dist/_pkgs/affine-shared/styles/motion.js +38 -0
- package/dist/_pkgs/affine-shared/utils/event.d.ts +10 -0
- package/dist/_pkgs/affine-shared/utils/event.js +20 -0
- package/dist/_pkgs/affine-shared/utils/file/filesys.d.ts +16 -0
- package/dist/_pkgs/affine-shared/utils/file/filesys.js +25 -0
- package/dist/_pkgs/affine-shared/utils/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/utils/index.js +1 -0
- package/dist/_pkgs/affine-shared/utils/link-preview-refresh.d.ts +12 -0
- package/dist/_pkgs/affine-shared/utils/link-preview-refresh.js +13 -0
- package/dist/_pkgs/affine-widget-edgeless-dragging-area/edgeless-dragging-area-rect.js +2 -2
- package/dist/_pkgs/affine-widget-edgeless-selected-rect/utils.js +5 -1
- package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.d.ts +12 -4
- package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.js +27 -4
- package/dist/_pkgs/affine-widget-edgeless-toolbar/config/types.d.ts +15 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/config/utils.d.ts +1 -1
- package/dist/_pkgs/affine-widget-edgeless-toolbar/config/utils.js +7 -2
- package/dist/_pkgs/affine-widget-edgeless-toolbar/create-popper.js +13 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/index.d.ts +2 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/index.js +2 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/command-menu.d.ts +80 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/command-menu.js +270 -81
- package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/senior-menu-selection.d.ts +15 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/senior-menu-selection.js +15 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/panel/font-family-panel.d.ts +18 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/panel/font-family-panel.js +52 -6
- package/dist/_pkgs/affine-widget-edgeless-toolbar/panel/font-weight-and-style-panel.js +8 -1
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-ghost-overlay.d.ts +42 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-ghost-overlay.js +100 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-placement-tool.d.ts +100 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-placement-tool.js +274 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/index.d.ts +3 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/index.js +3 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/translate-created.d.ts +25 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/translate-created.js +67 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/translations.d.ts +6 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/translations.js +10 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/view.js +5 -0
- package/dist/_pkgs/affine-widget-frame-title/edgeless-frame-title-editor.js +2 -1
- package/dist/_pkgs/affine-widget-slash-menu/translations.d.ts +16 -0
- package/dist/_pkgs/affine-widget-slash-menu/translations.js +23 -1
- package/dist/_pkgs/affine-widget-toolbar/utils.js +57 -14
- package/dist/_pkgs/data-view/core/detail/field.js +2 -1
- package/dist/_pkgs/data-view/core/filter/literal/define.js +3 -1
- package/dist/_pkgs/data-view/core/group-by/renderer/boolean-group.js +1 -1
- package/dist/_pkgs/data-view/property-presets/checkbox/cell-renderer.js +8 -2
- package/dist/_pkgs/data-view/view-presets/kanban/pc/cell.js +1 -1
- package/dist/_pkgs/data-view/view-presets/kanban/pc/controller/drag.js +2 -1
- package/dist/_pkgs/data-view/view-presets/table/pc/controller/drag.js +2 -1
- package/dist/_pkgs/data-view/view-presets/table/pc/controller/selection.js +1 -1
- package/dist/_pkgs/data-view/view-presets/table/pc/header/vertical-indicator.js +2 -1
- package/dist/_pkgs/data-view/view-presets/table/pc/row/row-select-checkbox.js +3 -1
- package/dist/_pkgs/data-view/view-presets/table/pc-virtual/controller/drag.js +2 -1
- package/dist/_pkgs/data-view/view-presets/table/pc-virtual/controller/selection.js +1 -1
- package/dist/_pkgs/data-view/view-presets/table/pc-virtual/group/top/header/vertical-indicator.js +2 -1
- package/dist/_pkgs/data-view/view-presets/table/pc-virtual/row/row-header.js +3 -1
- package/dist/_pkgs/global/gfx/xywh.js +7 -0
- package/dist/_pkgs/std/extension/command-registry.d.ts +158 -1
- package/dist/_pkgs/std/extension/command-registry.js +22 -0
- package/dist/_pkgs/std/gfx/index.d.ts +1 -1
- package/dist/_pkgs/std/gfx/interactivity/gfx-view-event-handler.d.ts +12 -0
- package/dist/_pkgs/std/gfx/interactivity/gfx-view-event-handler.js +20 -1
- package/dist/_pkgs/std/gfx/interactivity/manager.d.ts +10 -0
- package/dist/_pkgs/std/gfx/interactivity/manager.js +12 -0
- package/dist/_pkgs/std/gfx/model/surface/element-model.js +12 -7
- package/dist/_pkgs/std/gfx/model/surface/role.d.ts +10 -5
- package/dist/_pkgs/std/gfx/model/surface/surface-model.d.ts +56 -0
- package/dist/_pkgs/std/gfx/model/surface/surface-model.js +84 -3
- package/dist/_pkgs/std/gfx/view/view.d.ts +11 -2
- package/dist/_pkgs/std/gfx/view/view.js +16 -2
- package/dist/commands.d.ts +6 -0
- package/dist/commands.js +10 -2
- package/dist/frameworks.d.ts +9 -0
- package/dist/frameworks.js +19 -0
- package/dist/translations.js +21 -0
- package/package.json +13 -4
- package/dist/_pkgs/affine-gfx-group/group-watcher.d.ts +0 -1
- package/dist/_pkgs/affine-gfx-group/group-watcher.js +0 -20
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { FrameworkBackgroundElementModel } from '../../../affine-model/index.js';
|
|
2
|
+
import { downloadBlob, safeFilename } from '../../../affine-shared/utils/index.js';
|
|
3
|
+
import { GfxControllerIdentifier } from '../../../std/gfx/index.js';
|
|
4
|
+
import { renderBoardSvg } from './render.js';
|
|
5
|
+
/** What the file is, told to the browser. */
|
|
6
|
+
const SVG_MIME = 'image/svg+xml';
|
|
7
|
+
/** The name a board with no document title falls back to. */
|
|
8
|
+
const SVG_FILENAME_FALLBACK = 'board';
|
|
9
|
+
/**
|
|
10
|
+
* The framework boards in the current canvas selection.
|
|
11
|
+
*
|
|
12
|
+
* `FrameworkBackgroundElementModel` is the whole test, and that is the point of
|
|
13
|
+
* this command: eleven board kinds today — a Wardley map, a BPMN pool, a C4
|
|
14
|
+
* board and its boundaries, the three DDD boards, Cynefin, Estuarine, the two
|
|
15
|
+
* EDGY ones — and whatever a framework adds next, because a board IS the class
|
|
16
|
+
* and nothing about SVG is per framework (ADR 0025).
|
|
17
|
+
*/
|
|
18
|
+
export function selectedBoards(std) {
|
|
19
|
+
return std
|
|
20
|
+
.get(GfxControllerIdentifier)
|
|
21
|
+
.selection.selectedElements.filter((element) => element instanceof FrameworkBackgroundElementModel);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Render the selected board and hand it to the browser.
|
|
25
|
+
*
|
|
26
|
+
* ponytail: ONE board per click, the first of the selection. Browsers throttle
|
|
27
|
+
* (and Safari silently drops) programmatic downloads fired in a burst, so a
|
|
28
|
+
* selection of three boards would yield one file, two files or three depending
|
|
29
|
+
* on the browser — a result nobody can read off the gesture. One board, one
|
|
30
|
+
* file, every time.
|
|
31
|
+
*/
|
|
32
|
+
export function exportBoardSvg(std) {
|
|
33
|
+
const [board] = selectedBoards(std);
|
|
34
|
+
if (!board)
|
|
35
|
+
return;
|
|
36
|
+
const { svg } = renderBoardSvg(std, board);
|
|
37
|
+
const title = std.store.workspace.meta.getDocMeta(std.store.id)?.title;
|
|
38
|
+
downloadBlob(
|
|
39
|
+
// The charset is the browser's business, not the format's: `image/svg+xml`
|
|
40
|
+
// is what the file IS, and this is how a blob is told to carry it.
|
|
41
|
+
new Blob([svg], { type: `${SVG_MIME};charset=utf-8` }), `${safeFilename(title, SVG_FILENAME_FALLBACK)}.svg`);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* "Export SVG", in the command registry (ADR 0025).
|
|
45
|
+
*
|
|
46
|
+
* `owner: 'core'` and not a framework's, for the reason `map.audit` and
|
|
47
|
+
* `validation.mapQuality` are core: the command belongs to no framework —
|
|
48
|
+
* it renders whatever board is selected with the renderer that already paints
|
|
49
|
+
* it — and a framework owner would have forced the id prefix `wardley.` and
|
|
50
|
+
* then a second, identical command for every framework that follows. `'core'`
|
|
51
|
+
* owners are exempt from the id-prefix rule (ADR 0008).
|
|
52
|
+
*
|
|
53
|
+
* It READS, so there is no read-only guard: taking a picture of a board you
|
|
54
|
+
* cannot edit is precisely what a reader does.
|
|
55
|
+
*
|
|
56
|
+
* No `telemetry` field: `CommandTelemetry.framework` is typed on `FrameworkId`,
|
|
57
|
+
* and this command cannot name one — the surface package knows a board by its
|
|
58
|
+
* MODEL CLASS, and nothing in it maps `bpmnPool` back to `bpmn` without
|
|
59
|
+
* importing the framework packages the layering forbids. Usage is still
|
|
60
|
+
* measured, because `runCommand` records it outside the telemetry condition.
|
|
61
|
+
*/
|
|
62
|
+
const exportSvg = {
|
|
63
|
+
id: 'export.svg',
|
|
64
|
+
owner: 'core',
|
|
65
|
+
kind: 'action',
|
|
66
|
+
labelKey: 'com.labre.command.export.svg',
|
|
67
|
+
labelFallback: 'Export SVG',
|
|
68
|
+
descriptionKey: 'com.labre.command.export.svg.description',
|
|
69
|
+
descriptionFallback: 'Download the selected board and everything drawn on it as an SVG file.',
|
|
70
|
+
// The category the framework exports already file under: this is the same
|
|
71
|
+
// shelf as `wardley.exportOwm`, `bpmn.exportXml` and `c4.exportMermaid`, and
|
|
72
|
+
// a host catalogue groups them together.
|
|
73
|
+
category: 'interchange',
|
|
74
|
+
// Deliberately NOT `'senior-menu'`: those slots are for artefacts you DRAW,
|
|
75
|
+
// and "Export SVG" answers no question asked of a row of shapes — the same
|
|
76
|
+
// arbitration `bpmn.exportXml` is filed under (ADR 0014, R4).
|
|
77
|
+
surfaces: ['catalogue', 'contextual-toolbar', 'palette', 'agent'],
|
|
78
|
+
scope: 'edgeless',
|
|
79
|
+
// Keyless by intent. Still bindable from Settings › Shortcuts, which is what
|
|
80
|
+
// `toShortcutDescriptor` being total buys.
|
|
81
|
+
defaultKeys: { mac: [], other: [] },
|
|
82
|
+
// The serializable precondition a host catalogue can show; `when` narrows it
|
|
83
|
+
// to "…and that selection contains a board", which no member of the closed
|
|
84
|
+
// union can express.
|
|
85
|
+
availability: 'selection:framework',
|
|
86
|
+
when: std => selectedBoards(std).length > 0,
|
|
87
|
+
run: std => exportBoardSvg(std),
|
|
88
|
+
};
|
|
89
|
+
export const exportSvgCommands = [exportSvg];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { exportBoardSvg, exportSvgCommands, selectedBoards, } from './command.js';
|
|
2
|
+
export type { BoardSvgExport } from './render.js';
|
|
3
|
+
export { exportBoundOf, renderBoardSvg, selectBoardElements, } from './render.js';
|
|
4
|
+
export { taggedPath2D } from './tagged-path.js';
|
|
5
|
+
export type { SvgContext } from './svg-context.js';
|
|
6
|
+
export { createSvgContext, runWithRecordingPath2D } from './svg-context.js';
|
|
7
|
+
export { exportSvgToolbarConfig, exportSvgToolbarExtension, } from './toolbar.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { exportBoardSvg, exportSvgCommands, selectedBoards, } from './command.js';
|
|
2
|
+
export { exportBoundOf, renderBoardSvg, selectBoardElements, } from './render.js';
|
|
3
|
+
export { taggedPath2D } from './tagged-path.js';
|
|
4
|
+
export { createSvgContext, runWithRecordingPath2D } from './svg-context.js';
|
|
5
|
+
export { exportSvgToolbarConfig, exportSvgToolbarExtension, } from './toolbar.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { FrameworkBackgroundElementModel } from '../../../affine-model/index.js';
|
|
2
|
+
import { Bound } from '../../../global/gfx/index.js';
|
|
3
|
+
import type { BlockStdScope } from '../../../std/index.js';
|
|
4
|
+
import { type GfxPrimitiveElementModel } from '../../../std/gfx/index.js';
|
|
5
|
+
export interface BoardSvgExport {
|
|
6
|
+
/** A standalone SVG document. */
|
|
7
|
+
svg: string;
|
|
8
|
+
/** The world-space rectangle the document covers. */
|
|
9
|
+
bound: Bound;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The canvas elements that make up `board`'s picture, in paint order.
|
|
13
|
+
*
|
|
14
|
+
* `candidates` comes from a bound query, so it also holds whatever a NEIGHBOUR
|
|
15
|
+
* board happens to overlap with. Another framework background is kept only
|
|
16
|
+
* when its frame lies ENTIRELY inside the exported one (edges may touch): that
|
|
17
|
+
* is a nested frame — a UML subject, partition, region or fragment inside its
|
|
18
|
+
* diagram frame, a C4 boundary inside a C4 board — and it is part of the
|
|
19
|
+
* picture. One that merely overlaps is a neighbour and is dropped: without
|
|
20
|
+
* that, a map sitting next to this one would paint its whole frame into this
|
|
21
|
+
* file. So is one that ENCLOSES the board, the diagram frame around an
|
|
22
|
+
* exported partition. Non-background elements are kept whoever owns them — an
|
|
23
|
+
* element inside the exported frame belongs to the picture.
|
|
24
|
+
*
|
|
25
|
+
* Containment is read on the stored `xywh`, the same rectangle
|
|
26
|
+
* {@link exportBoundOf} starts from; a background at exactly the board's own
|
|
27
|
+
* rectangle therefore counts as nested.
|
|
28
|
+
*/
|
|
29
|
+
export declare function selectBoardElements<T extends GfxPrimitiveElementModel>(board: FrameworkBackgroundElementModel, candidates: readonly T[]): (FrameworkBackgroundElementModel | T)[];
|
|
30
|
+
/**
|
|
31
|
+
* The board's frame, widened to the union of what is painted on it: a Wardley
|
|
32
|
+
* label overhanging the right edge, or a connector ending just outside, is part
|
|
33
|
+
* of the picture and must not be cut off.
|
|
34
|
+
*/
|
|
35
|
+
export declare function exportBoundOf(board: FrameworkBackgroundElementModel, elements: readonly GfxPrimitiveElementModel[]): Bound;
|
|
36
|
+
/**
|
|
37
|
+
* The selected board and everything painted within its frame, as an SVG
|
|
38
|
+
* document — a true vector export, produced by replaying the very element
|
|
39
|
+
* renderers the canvas uses into an SVG-emitting 2D context.
|
|
40
|
+
*/
|
|
41
|
+
export declare function renderBoardSvg(std: BlockStdScope, board: FrameworkBackgroundElementModel): BoardSvgExport;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { FrameworkBackgroundElementModel } from '../../../affine-model/index.js';
|
|
2
|
+
import { Bound } from '../../../global/gfx/index.js';
|
|
3
|
+
import { GfxControllerIdentifier, } from '../../../std/gfx/index.js';
|
|
4
|
+
import { CanvasRenderer } from '../../renderer/canvas-renderer.js';
|
|
5
|
+
import { RoughCanvas } from '../../utils/rough/canvas.js';
|
|
6
|
+
import { createSvgContext, runWithRecordingPath2D } from './svg-context.js';
|
|
7
|
+
/**
|
|
8
|
+
* The canvas elements that make up `board`'s picture, in paint order.
|
|
9
|
+
*
|
|
10
|
+
* `candidates` comes from a bound query, so it also holds whatever a NEIGHBOUR
|
|
11
|
+
* board happens to overlap with. Another framework background is kept only
|
|
12
|
+
* when its frame lies ENTIRELY inside the exported one (edges may touch): that
|
|
13
|
+
* is a nested frame — a UML subject, partition, region or fragment inside its
|
|
14
|
+
* diagram frame, a C4 boundary inside a C4 board — and it is part of the
|
|
15
|
+
* picture. One that merely overlaps is a neighbour and is dropped: without
|
|
16
|
+
* that, a map sitting next to this one would paint its whole frame into this
|
|
17
|
+
* file. So is one that ENCLOSES the board, the diagram frame around an
|
|
18
|
+
* exported partition. Non-background elements are kept whoever owns them — an
|
|
19
|
+
* element inside the exported frame belongs to the picture.
|
|
20
|
+
*
|
|
21
|
+
* Containment is read on the stored `xywh`, the same rectangle
|
|
22
|
+
* {@link exportBoundOf} starts from; a background at exactly the board's own
|
|
23
|
+
* rectangle therefore counts as nested.
|
|
24
|
+
*/
|
|
25
|
+
export function selectBoardElements(board, candidates) {
|
|
26
|
+
const frame = Bound.deserialize(board.xywh);
|
|
27
|
+
const kept = candidates.filter(element => element === board ||
|
|
28
|
+
!(element instanceof FrameworkBackgroundElementModel) ||
|
|
29
|
+
frame.contains(Bound.deserialize(element.xywh)));
|
|
30
|
+
// A background paints under everything, so a board missing from the query
|
|
31
|
+
// (an empty bound, a stub) goes in front of the list, not at the end.
|
|
32
|
+
return kept.some(element => element === board)
|
|
33
|
+
? kept
|
|
34
|
+
: [board, ...kept];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The board's frame, widened to the union of what is painted on it: a Wardley
|
|
38
|
+
* label overhanging the right edge, or a connector ending just outside, is part
|
|
39
|
+
* of the picture and must not be cut off.
|
|
40
|
+
*/
|
|
41
|
+
export function exportBoundOf(board, elements) {
|
|
42
|
+
let bound = Bound.deserialize(board.xywh);
|
|
43
|
+
for (const element of elements) {
|
|
44
|
+
bound = bound.unite(Bound.deserialize(element.xywh));
|
|
45
|
+
}
|
|
46
|
+
return bound;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The selected board and everything painted within its frame, as an SVG
|
|
50
|
+
* document — a true vector export, produced by replaying the very element
|
|
51
|
+
* renderers the canvas uses into an SVG-emitting 2D context.
|
|
52
|
+
*/
|
|
53
|
+
export function renderBoardSvg(std, board) {
|
|
54
|
+
const gfx = std.get(GfxControllerIdentifier);
|
|
55
|
+
const renderer = gfx.surfaceComponent?.renderer;
|
|
56
|
+
if (!(renderer instanceof CanvasRenderer)) {
|
|
57
|
+
throw new Error('SVG export needs the surface to be painted by a CanvasRenderer.');
|
|
58
|
+
}
|
|
59
|
+
// Already sorted by `layer.compare`, which is the canvas' own z-order.
|
|
60
|
+
const candidates = gfx.getElementsByBound(Bound.deserialize(board.xywh), {
|
|
61
|
+
type: 'canvas',
|
|
62
|
+
});
|
|
63
|
+
const elements = selectBoardElements(board, candidates);
|
|
64
|
+
const bound = exportBoundOf(board, elements);
|
|
65
|
+
return runWithRecordingPath2D(() => {
|
|
66
|
+
const { ctx, canvas, serialize } = createSvgContext(bound.w, bound.h);
|
|
67
|
+
renderer.renderBoundTo(ctx, new RoughCanvas(canvas), bound, elements);
|
|
68
|
+
return { svg: serialize(), bound };
|
|
69
|
+
});
|
|
70
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A 2D context that records an SVG document instead of pixels, shaped so the
|
|
3
|
+
* existing canvas renderers can paint into it unchanged.
|
|
4
|
+
*/
|
|
5
|
+
export interface SvgContext {
|
|
6
|
+
/** What the element renderers draw into. */
|
|
7
|
+
ctx: CanvasRenderingContext2D;
|
|
8
|
+
/** What `new RoughCanvas(...)` takes: `getContext('2d')` returns {@link ctx}. */
|
|
9
|
+
canvas: HTMLCanvasElement;
|
|
10
|
+
/** The finished document, with `viewBox`, `width`/`height` in px and `xmlns`. */
|
|
11
|
+
serialize(): string;
|
|
12
|
+
}
|
|
13
|
+
/** Marks a {@link RecordingPath2D} and carries what it recorded. */
|
|
14
|
+
declare const RECORDED_D: unique symbol;
|
|
15
|
+
interface RecordedPath {
|
|
16
|
+
[RECORDED_D]: string;
|
|
17
|
+
}
|
|
18
|
+
/** A `Path2D` that also remembers itself as an SVG `d`, in the caller's space. */
|
|
19
|
+
export type RecordingPath2D = Path2D & RecordedPath & {
|
|
20
|
+
readonly d: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Runs `render` with `globalThis.Path2D` swapped for the recording subclass, so
|
|
24
|
+
* the `new Path2D(d)` a renderer builds can be replayed into the SVG document.
|
|
25
|
+
*
|
|
26
|
+
* Swapping a global is safe here because the swap and the restore bracket a
|
|
27
|
+
* SYNCHRONOUS call on a single-threaded runtime: no other code can run — let
|
|
28
|
+
* alone observe `Path2D` — between the two, and the `finally` restores the
|
|
29
|
+
* original even when a renderer throws.
|
|
30
|
+
*/
|
|
31
|
+
export declare function runWithRecordingPath2D<T>(render: () => T): T;
|
|
32
|
+
/**
|
|
33
|
+
* The dash pattern svgcanvas holds, as the `number[]` Canvas2D's `getLineDash`
|
|
34
|
+
* returns.
|
|
35
|
+
*
|
|
36
|
+
* svgcanvas 2.6.0 implements `setLineDash` but not `getLineDash`, and a
|
|
37
|
+
* renderer that reads the pattern back (to put it back after a dashed stroke)
|
|
38
|
+
* would throw and abort the whole export. Its `setLineDash` stores the pattern
|
|
39
|
+
* in the `lineDash` style — a comma-joined string, `null` once cleared, the
|
|
40
|
+
* default `[]` before any call — and that style is saved and restored with the
|
|
41
|
+
* rest of the drawing state, so reading it is exact.
|
|
42
|
+
*/
|
|
43
|
+
export declare function readLineDash(lineDash: unknown): number[];
|
|
44
|
+
/**
|
|
45
|
+
* An SVG-emitting 2D context of `width` × `height` user units, ready to be
|
|
46
|
+
* handed to {@link CanvasRenderer.renderBoundTo}.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createSvgContext(width: number, height: number): SvgContext;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { Context } from 'svgcanvas/dist/svgcanvas.esm.js';
|
|
2
|
+
const PATH_OPS = ['fill', 'stroke', 'clip'];
|
|
3
|
+
/** Marks a {@link RecordingPath2D} and carries what it recorded. */
|
|
4
|
+
const RECORDED_D = Symbol('labre.export-svg.recorded-d');
|
|
5
|
+
function isRecordingPath(value) {
|
|
6
|
+
return (typeof value?.[RECORDED_D] === 'string');
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The SVG `d` of a path argument, or `undefined` when it cannot be read.
|
|
10
|
+
*
|
|
11
|
+
* Duck-typed on a string `d` so it covers both paths this module recorded and
|
|
12
|
+
* the native ones `taggedPath2D` tagged — a renderer is free to memoise those,
|
|
13
|
+
* and a memo built during an ordinary canvas paint must still be readable here.
|
|
14
|
+
*/
|
|
15
|
+
function readablePathD(value) {
|
|
16
|
+
const d = value?.d;
|
|
17
|
+
return typeof d === 'string' ? d : undefined;
|
|
18
|
+
}
|
|
19
|
+
/** A path argument whose geometry is unreadable: a bare native `Path2D`. */
|
|
20
|
+
function isOpaquePath(value) {
|
|
21
|
+
return (typeof value === 'object' &&
|
|
22
|
+
value !== null &&
|
|
23
|
+
readablePathD(value) === undefined);
|
|
24
|
+
}
|
|
25
|
+
function isEvenOdd(value) {
|
|
26
|
+
return value === 'evenodd';
|
|
27
|
+
}
|
|
28
|
+
function unsupported(method) {
|
|
29
|
+
return new Error(`SVG export: Path2D.${method}() is not recorded. Add it to RecordingPath2D ` +
|
|
30
|
+
`in extensions/export-svg/svg-context.ts, or draw it on the context directly.`);
|
|
31
|
+
}
|
|
32
|
+
let recordingPath2D;
|
|
33
|
+
/**
|
|
34
|
+
* Built on first use rather than at import time: it extends the platform
|
|
35
|
+
* `Path2D`, which does not exist under Node, and merely importing this module
|
|
36
|
+
* must not throw there (same arrangement as `gfx/cynefin-estuarine`'s lazy
|
|
37
|
+
* curves).
|
|
38
|
+
*
|
|
39
|
+
* It EXTENDS `Path2D` on purpose. A renderer is free to memoise the paths it
|
|
40
|
+
* builds (`gfx/cynefin-estuarine` does), so an instance created while the shim
|
|
41
|
+
* is installed can outlive the export and be handed to a real canvas context
|
|
42
|
+
* later — which only works if it is a genuine `Path2D` as well.
|
|
43
|
+
*/
|
|
44
|
+
function getRecordingPath2D() {
|
|
45
|
+
var _a;
|
|
46
|
+
if (recordingPath2D)
|
|
47
|
+
return recordingPath2D;
|
|
48
|
+
const Base = globalThis.Path2D;
|
|
49
|
+
if (!Base) {
|
|
50
|
+
throw new Error('SVG export: Path2D is unavailable in this environment.');
|
|
51
|
+
}
|
|
52
|
+
class RecordingPath2DImpl extends Base {
|
|
53
|
+
static { _a = RECORDED_D; }
|
|
54
|
+
get d() {
|
|
55
|
+
return this[RECORDED_D];
|
|
56
|
+
}
|
|
57
|
+
constructor(source) {
|
|
58
|
+
super(source);
|
|
59
|
+
this[_a] = '';
|
|
60
|
+
if (typeof source === 'string') {
|
|
61
|
+
this[RECORDED_D] = source;
|
|
62
|
+
}
|
|
63
|
+
else if (isRecordingPath(source)) {
|
|
64
|
+
this[RECORDED_D] = source[RECORDED_D];
|
|
65
|
+
}
|
|
66
|
+
else if (source) {
|
|
67
|
+
throw unsupported('constructor(Path2D)');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
_push(command) {
|
|
71
|
+
this[RECORDED_D] += this[RECORDED_D] ? ` ${command}` : command;
|
|
72
|
+
}
|
|
73
|
+
addPath(path, transform) {
|
|
74
|
+
if (transform)
|
|
75
|
+
throw unsupported('addPath(path, transform)');
|
|
76
|
+
if (!isRecordingPath(path))
|
|
77
|
+
throw unsupported('addPath(Path2D)');
|
|
78
|
+
super.addPath(path);
|
|
79
|
+
this._push(path[RECORDED_D]);
|
|
80
|
+
}
|
|
81
|
+
arc() {
|
|
82
|
+
throw unsupported('arc');
|
|
83
|
+
}
|
|
84
|
+
arcTo() {
|
|
85
|
+
throw unsupported('arcTo');
|
|
86
|
+
}
|
|
87
|
+
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) {
|
|
88
|
+
super.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
|
|
89
|
+
this._push(`C ${cp1x} ${cp1y} ${cp2x} ${cp2y} ${x} ${y}`);
|
|
90
|
+
}
|
|
91
|
+
closePath() {
|
|
92
|
+
super.closePath();
|
|
93
|
+
this._push('Z');
|
|
94
|
+
}
|
|
95
|
+
ellipse() {
|
|
96
|
+
throw unsupported('ellipse');
|
|
97
|
+
}
|
|
98
|
+
lineTo(x, y) {
|
|
99
|
+
super.lineTo(x, y);
|
|
100
|
+
this._push(`L ${x} ${y}`);
|
|
101
|
+
}
|
|
102
|
+
moveTo(x, y) {
|
|
103
|
+
super.moveTo(x, y);
|
|
104
|
+
this._push(`M ${x} ${y}`);
|
|
105
|
+
}
|
|
106
|
+
quadraticCurveTo(cpx, cpy, x, y) {
|
|
107
|
+
super.quadraticCurveTo(cpx, cpy, x, y);
|
|
108
|
+
this._push(`Q ${cpx} ${cpy} ${x} ${y}`);
|
|
109
|
+
}
|
|
110
|
+
rect(x, y, w, h) {
|
|
111
|
+
super.rect(x, y, w, h);
|
|
112
|
+
this._push(`M ${x} ${y} L ${x + w} ${y} L ${x + w} ${y + h} L ${x} ${y + h} Z`);
|
|
113
|
+
}
|
|
114
|
+
roundRect() {
|
|
115
|
+
throw unsupported('roundRect');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
recordingPath2D =
|
|
119
|
+
RecordingPath2DImpl;
|
|
120
|
+
return recordingPath2D;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Runs `render` with `globalThis.Path2D` swapped for the recording subclass, so
|
|
124
|
+
* the `new Path2D(d)` a renderer builds can be replayed into the SVG document.
|
|
125
|
+
*
|
|
126
|
+
* Swapping a global is safe here because the swap and the restore bracket a
|
|
127
|
+
* SYNCHRONOUS call on a single-threaded runtime: no other code can run — let
|
|
128
|
+
* alone observe `Path2D` — between the two, and the `finally` restores the
|
|
129
|
+
* original even when a renderer throws.
|
|
130
|
+
*/
|
|
131
|
+
export function runWithRecordingPath2D(render) {
|
|
132
|
+
const original = globalThis.Path2D;
|
|
133
|
+
globalThis.Path2D = getRecordingPath2D();
|
|
134
|
+
try {
|
|
135
|
+
return render();
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
globalThis.Path2D = original;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Teaches `fill`/`stroke`/`clip` the two things svgcanvas drops on the floor:
|
|
143
|
+
* the `Path2D` argument, and the fill rule.
|
|
144
|
+
*/
|
|
145
|
+
function installPathOps(ctx) {
|
|
146
|
+
for (const op of PATH_OPS) {
|
|
147
|
+
const original = ctx[op];
|
|
148
|
+
ctx[op] = (...args) => {
|
|
149
|
+
const d = args.map(readablePathD).find(value => value !== undefined);
|
|
150
|
+
const hasPath = d !== undefined;
|
|
151
|
+
const evenOdd = args.some(isEvenOdd);
|
|
152
|
+
if (hasPath) {
|
|
153
|
+
// svgcanvas ignores Path2D arguments and always paints its "current
|
|
154
|
+
// default path", so the path's `d` becomes exactly that.
|
|
155
|
+
ctx.beginPath();
|
|
156
|
+
ctx.__currentDefaultPath = d;
|
|
157
|
+
}
|
|
158
|
+
else if (args.some(isOpaquePath)) {
|
|
159
|
+
// An untagged native Path2D. Nothing can read its geometry back, so
|
|
160
|
+
// drop it loudly rather than let svgcanvas paint whatever path happened
|
|
161
|
+
// to be current. `taggedPath2D` is the fix at the call site.
|
|
162
|
+
ctx.beginPath();
|
|
163
|
+
ctx.__currentDefaultPath = '';
|
|
164
|
+
console.warn('SVG export: an untagged Path2D cannot be read back; that shape is ' +
|
|
165
|
+
'missing from the SVG. Build it with `taggedPath2D`.');
|
|
166
|
+
}
|
|
167
|
+
// `clip()` moves this node into a <clipPath>, so grab it beforehand.
|
|
168
|
+
const element = ctx.__currentElement;
|
|
169
|
+
const lineWidth = ctx.lineWidth;
|
|
170
|
+
original.call(ctx);
|
|
171
|
+
if (hasPath) {
|
|
172
|
+
// svgcanvas BAKES the current matrix into every coordinate it emits;
|
|
173
|
+
// an injected `d` never went through that, so the matrix rides along
|
|
174
|
+
// as a `transform` attribute instead…
|
|
175
|
+
ctx.__applyTransformation(element);
|
|
176
|
+
// …and the stroke width, which svgcanvas pre-multiplied by the matrix
|
|
177
|
+
// scale, goes back to its raw value or the transform scales it twice.
|
|
178
|
+
if (op === 'stroke') {
|
|
179
|
+
element.setAttribute('stroke-width', `${lineWidth}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (evenOdd) {
|
|
183
|
+
element.setAttribute(op === 'clip' ? 'clip-rule' : 'fill-rule', 'evenodd');
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* The dash pattern svgcanvas holds, as the `number[]` Canvas2D's `getLineDash`
|
|
190
|
+
* returns.
|
|
191
|
+
*
|
|
192
|
+
* svgcanvas 2.6.0 implements `setLineDash` but not `getLineDash`, and a
|
|
193
|
+
* renderer that reads the pattern back (to put it back after a dashed stroke)
|
|
194
|
+
* would throw and abort the whole export. Its `setLineDash` stores the pattern
|
|
195
|
+
* in the `lineDash` style — a comma-joined string, `null` once cleared, the
|
|
196
|
+
* default `[]` before any call — and that style is saved and restored with the
|
|
197
|
+
* rest of the drawing state, so reading it is exact.
|
|
198
|
+
*/
|
|
199
|
+
export function readLineDash(lineDash) {
|
|
200
|
+
if (Array.isArray(lineDash))
|
|
201
|
+
return lineDash.map(Number);
|
|
202
|
+
if (typeof lineDash !== 'string' || lineDash === '')
|
|
203
|
+
return [];
|
|
204
|
+
return lineDash.split(',').map(Number);
|
|
205
|
+
}
|
|
206
|
+
/** Adds `viewBox` / `xmlns` / px units to the root `<svg>` if they are missing. */
|
|
207
|
+
function finishSvg(svg, width, height) {
|
|
208
|
+
return (svg
|
|
209
|
+
// Models store fonts under the loader's own face name
|
|
210
|
+
// (`blocksuite:surface:Inter`); outside the editor only `Inter` exists.
|
|
211
|
+
.replace(/blocksuite:surface:/g, '')
|
|
212
|
+
// svgcanvas writes the (unset) text decoration out literally.
|
|
213
|
+
.replace(/ text-decoration="undefined"/g, '')
|
|
214
|
+
.replace(/<svg\b[^>]*>/, tag => {
|
|
215
|
+
let out = tag;
|
|
216
|
+
if (!/\sviewBox=/.test(out)) {
|
|
217
|
+
out = out.replace(/^<svg/, `<svg viewBox="0 0 ${width} ${height}"`);
|
|
218
|
+
}
|
|
219
|
+
if (!/\sxmlns=/.test(out)) {
|
|
220
|
+
out = out.replace(/^<svg/, `<svg xmlns="http://www.w3.org/2000/svg"`);
|
|
221
|
+
}
|
|
222
|
+
out = /\swidth=/.test(out)
|
|
223
|
+
? out.replace(/\swidth="[^"]*"/, ` width="${width}px"`)
|
|
224
|
+
: out.replace(/^<svg/, `<svg width="${width}px"`);
|
|
225
|
+
out = /\sheight=/.test(out)
|
|
226
|
+
? out.replace(/\sheight="[^"]*"/, ` height="${height}px"`)
|
|
227
|
+
: out.replace(/^<svg/, `<svg height="${height}px"`);
|
|
228
|
+
return out;
|
|
229
|
+
}));
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* An SVG-emitting 2D context of `width` × `height` user units, ready to be
|
|
233
|
+
* handed to {@link CanvasRenderer.renderBoundTo}.
|
|
234
|
+
*/
|
|
235
|
+
export function createSvgContext(width, height) {
|
|
236
|
+
const context = new Context({ width, height });
|
|
237
|
+
const ctx = context;
|
|
238
|
+
// `RoughCanvas` takes the CANVAS and calls `getContext('2d')` on it.
|
|
239
|
+
// svgcanvas already points `canvas` back at the context, so one method
|
|
240
|
+
// closes the loop.
|
|
241
|
+
context.getContext = () => ctx;
|
|
242
|
+
// Text renderers temporarily attach a detached canvas to <body> to measure
|
|
243
|
+
// RTL runs. This context is not a DOM node, so claim it is already attached.
|
|
244
|
+
context.isConnected = true;
|
|
245
|
+
// …and they set `dir` on the canvas before every text run; a no-op keeps
|
|
246
|
+
// that call from reaching an object that is not an element.
|
|
247
|
+
context.setAttribute = () => { };
|
|
248
|
+
// The one Canvas2D method a renderer calls that svgcanvas lacks — see
|
|
249
|
+
// `readLineDash`. Without it a single `getLineDash()` aborts the export.
|
|
250
|
+
context.getLineDash = () => readLineDash(context.lineDash);
|
|
251
|
+
installPathOps(context);
|
|
252
|
+
return {
|
|
253
|
+
ctx,
|
|
254
|
+
canvas: ctx.canvas,
|
|
255
|
+
serialize: () => finishSvg(context.getSerializedSvg(true), width, height),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `Path2D` that carries the `d` it was built from.
|
|
3
|
+
*
|
|
4
|
+
* The SVG export replays the element renderers into an SVG-emitting context,
|
|
5
|
+
* and a native `Path2D` is a black box: nothing can read its geometry back, so
|
|
6
|
+
* a shape drawn through one would be missing from the export. The tag is what
|
|
7
|
+
* the export reads — see `svg-context.ts`.
|
|
8
|
+
*
|
|
9
|
+
* Use it anywhere a renderer builds a `Path2D` FROM A STRING. A path built by
|
|
10
|
+
* calling methods (`new Path2D()` then `rect(...)`) needs no tag: the export
|
|
11
|
+
* records those calls itself.
|
|
12
|
+
*
|
|
13
|
+
* It is a plain function, not a constant: `Path2D` does not exist under Node,
|
|
14
|
+
* so this must only ever run on a paint, never at module load.
|
|
15
|
+
*/
|
|
16
|
+
export declare function taggedPath2D(d: string): Path2D;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `Path2D` that carries the `d` it was built from.
|
|
3
|
+
*
|
|
4
|
+
* The SVG export replays the element renderers into an SVG-emitting context,
|
|
5
|
+
* and a native `Path2D` is a black box: nothing can read its geometry back, so
|
|
6
|
+
* a shape drawn through one would be missing from the export. The tag is what
|
|
7
|
+
* the export reads — see `svg-context.ts`.
|
|
8
|
+
*
|
|
9
|
+
* Use it anywhere a renderer builds a `Path2D` FROM A STRING. A path built by
|
|
10
|
+
* calling methods (`new Path2D()` then `rect(...)`) needs no tag: the export
|
|
11
|
+
* records those calls itself.
|
|
12
|
+
*
|
|
13
|
+
* It is a plain function, not a constant: `Path2D` does not exist under Node,
|
|
14
|
+
* so this must only ever run on a paint, never at module load.
|
|
15
|
+
*/
|
|
16
|
+
export function taggedPath2D(d) {
|
|
17
|
+
const path = new Path2D(d);
|
|
18
|
+
// While the export's recording `Path2D` is installed, the instance already
|
|
19
|
+
// exposes `d` through a getter; writing it again would throw.
|
|
20
|
+
if (typeof path.d !== 'string') {
|
|
21
|
+
Object.defineProperty(path, 'd', { value: d, enumerable: true });
|
|
22
|
+
}
|
|
23
|
+
return path;
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ToolbarContext } from '../../../affine-shared/services/index.js';
|
|
2
|
+
export declare const exportSvgToolbarConfig: {
|
|
3
|
+
readonly actions: [import("../../../affine-shared/services/index.js").ToolbarActionGenerator];
|
|
4
|
+
readonly when: (ctx: ToolbarContext) => boolean;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* "Export SVG" in the "⋮" of EVERY framework board (ADR 0025).
|
|
8
|
+
*
|
|
9
|
+
* ## Where it is registered
|
|
10
|
+
*
|
|
11
|
+
* `custom:affine:surface:*` — the wildcard slot merged into the toolbar of every
|
|
12
|
+
* canvas element — with an OWNER suffix. The bare key is already taken by
|
|
13
|
+
* `validation-toolbar.ts` (and `affine:surface:*` by the root's built-in misc
|
|
14
|
+
* module), so a second module on either would be a
|
|
15
|
+
* `DuplicateServiceDefinitionError` at setup rather than a menu entry;
|
|
16
|
+
* {@link toolbarModuleKey} is what gives a second contributor a distinct DI
|
|
17
|
+
* variant while `modulesFor` still hands it to the row drawn for that flavour.
|
|
18
|
+
*
|
|
19
|
+
* One registration therefore covers all eleven board kinds and every one that
|
|
20
|
+
* follows, which is the whole claim of the ADR: the export is generic, so it is
|
|
21
|
+
* registered once, generically, and a new framework inherits it by extending
|
|
22
|
+
* `FrameworkBackgroundElementModel` and doing nothing else.
|
|
23
|
+
*/
|
|
24
|
+
export declare const exportSvgToolbarExtension: import("../../../store/index.js").ExtensionType;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { FrameworkBackgroundElementModel } from '../../../affine-model/index.js';
|
|
2
|
+
import { commandMoreAction, ToolbarModuleExtension, toolbarModuleKey, } from '../../../affine-shared/services/index.js';
|
|
3
|
+
import { BlockFlavourIdentifier } from '../../../std/index.js';
|
|
4
|
+
import { html } from 'lit';
|
|
5
|
+
/**
|
|
6
|
+
* A sheet with an arrow leaving it: the board, on its way out of the editor.
|
|
7
|
+
*
|
|
8
|
+
* Drawn inline like its neighbours in this package (`reading-toolbar.ts`,
|
|
9
|
+
* `tags-toolbar.ts`, `validation-toolbar.ts`): the surface block does not
|
|
10
|
+
* depend on `@blocksuite/icons`, and one glyph is not worth a new dependency.
|
|
11
|
+
*/
|
|
12
|
+
const ExportSvgIcon = html `<svg
|
|
13
|
+
width="20"
|
|
14
|
+
height="20"
|
|
15
|
+
viewBox="0 0 24 24"
|
|
16
|
+
fill="none"
|
|
17
|
+
stroke="currentColor"
|
|
18
|
+
stroke-width="2"
|
|
19
|
+
stroke-linecap="round"
|
|
20
|
+
stroke-linejoin="round"
|
|
21
|
+
>
|
|
22
|
+
<path d="M12 3v12" />
|
|
23
|
+
<path d="M8 11l4 4 4-4" />
|
|
24
|
+
<path d="M4 17v2a2 2 0 002 2h12a2 2 0 002-2v-2" />
|
|
25
|
+
</svg>`;
|
|
26
|
+
/** The keys the command declares; spelled once, read here and nowhere else. */
|
|
27
|
+
const EXPORT_SVG_COMMAND_ID = 'export.svg';
|
|
28
|
+
const EXPORT_SVG_LABEL_KEY = 'com.labre.command.export.svg';
|
|
29
|
+
const EXPORT_SVG_LABEL_FALLBACK = 'Export SVG';
|
|
30
|
+
export const exportSvgToolbarConfig = {
|
|
31
|
+
actions: [
|
|
32
|
+
commandMoreAction(
|
|
33
|
+
// `z.z-` and not `z.`: a framework's own export (`z.export-owm`,
|
|
34
|
+
// `z.export-xml`, `z.export-mermaid`) is the format that says what the
|
|
35
|
+
// board MEANS, and it reads first. The picture reads last, under
|
|
36
|
+
// everything, which is also where a reader looks for it.
|
|
37
|
+
'z.z-export-svg', EXPORT_SVG_COMMAND_ID, EXPORT_SVG_LABEL_KEY, EXPORT_SVG_LABEL_FALLBACK, ExportSvgIcon),
|
|
38
|
+
],
|
|
39
|
+
// The module says "a board is selected"; the command's own `when` says the
|
|
40
|
+
// same thing from the registry side, and the two are deliberately both there
|
|
41
|
+
// — the entry is drawn from the module and the behaviour is guarded by the
|
|
42
|
+
// command, whichever surface reaches it.
|
|
43
|
+
when: (ctx) => ctx.getSurfaceModelsByType(FrameworkBackgroundElementModel).length > 0,
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* "Export SVG" in the "⋮" of EVERY framework board (ADR 0025).
|
|
47
|
+
*
|
|
48
|
+
* ## Where it is registered
|
|
49
|
+
*
|
|
50
|
+
* `custom:affine:surface:*` — the wildcard slot merged into the toolbar of every
|
|
51
|
+
* canvas element — with an OWNER suffix. The bare key is already taken by
|
|
52
|
+
* `validation-toolbar.ts` (and `affine:surface:*` by the root's built-in misc
|
|
53
|
+
* module), so a second module on either would be a
|
|
54
|
+
* `DuplicateServiceDefinitionError` at setup rather than a menu entry;
|
|
55
|
+
* {@link toolbarModuleKey} is what gives a second contributor a distinct DI
|
|
56
|
+
* variant while `modulesFor` still hands it to the row drawn for that flavour.
|
|
57
|
+
*
|
|
58
|
+
* One registration therefore covers all eleven board kinds and every one that
|
|
59
|
+
* follows, which is the whole claim of the ADR: the export is generic, so it is
|
|
60
|
+
* registered once, generically, and a new framework inherits it by extending
|
|
61
|
+
* `FrameworkBackgroundElementModel` and doing nothing else.
|
|
62
|
+
*/
|
|
63
|
+
export const exportSvgToolbarExtension = ToolbarModuleExtension({
|
|
64
|
+
id: BlockFlavourIdentifier(toolbarModuleKey('custom:affine:surface:*', 'export-svg')),
|
|
65
|
+
config: exportSvgToolbarConfig,
|
|
66
|
+
});
|