@formicoidea/labre-core 0.58.0 → 0.60.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.
- package/architecture/code.c4 +175 -144
- package/architecture/domain.c4 +15 -9
- package/architecture/likec4.config.json +3 -3
- package/dist/_pkgs/affine-block-attachment/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-attachment/edgeless-clipboard-config.js +18 -13
- package/dist/_pkgs/affine-block-callout/adapters/markdown.js +4 -1
- package/dist/_pkgs/affine-block-code/adapters/html.js +1 -1
- package/dist/_pkgs/affine-block-code/adapters/markdown/preprocessor.js +13 -1
- package/dist/_pkgs/affine-block-code/adapters/notion-html.js +1 -1
- package/dist/_pkgs/affine-block-code/code-block.d.ts +17 -2
- package/dist/_pkgs/affine-block-code/code-block.js +28 -23
- package/dist/_pkgs/affine-block-code/code-toolbar/components/lang-button.js +17 -4
- package/dist/_pkgs/affine-block-code/code-toolbar/components/preview-button.js +1 -1
- package/dist/_pkgs/affine-block-data-view/data-source.js +12 -5
- package/dist/_pkgs/affine-block-edgeless-text/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-edgeless-text/edgeless-clipboard-config.js +8 -5
- package/dist/_pkgs/affine-block-image/asset-picker.d.ts +23 -2
- package/dist/_pkgs/affine-block-image/asset-picker.js +52 -12
- package/dist/_pkgs/affine-block-image/configs/replace-action.d.ts +8 -5
- package/dist/_pkgs/affine-block-image/configs/replace-action.js +8 -8
- package/dist/_pkgs/affine-block-image/configs/toolbar.js +2 -1
- package/dist/_pkgs/affine-block-image/crop/crop-controller.d.ts +15 -0
- package/dist/_pkgs/affine-block-image/crop/crop-controller.js +40 -2
- package/dist/_pkgs/affine-block-image/crop/crop-math.d.ts +22 -0
- package/dist/_pkgs/affine-block-image/crop/crop-math.js +55 -2
- package/dist/_pkgs/affine-block-image/crop/crop-overlay.d.ts +17 -3
- package/dist/_pkgs/affine-block-image/crop/crop-overlay.js +64 -6
- package/dist/_pkgs/affine-block-image/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-image/edgeless-clipboard-config.js +20 -14
- package/dist/_pkgs/affine-block-image/image-block.js +1 -0
- package/dist/_pkgs/affine-block-image/image-edgeless-block.js +3 -0
- package/dist/_pkgs/affine-block-image/index.d.ts +2 -0
- package/dist/_pkgs/affine-block-image/index.js +2 -0
- package/dist/_pkgs/affine-block-image/replace/commands.d.ts +68 -0
- package/dist/_pkgs/affine-block-image/replace/commands.js +200 -0
- package/dist/_pkgs/affine-block-image/replace/replace-model.d.ts +44 -0
- package/dist/_pkgs/affine-block-image/replace/replace-model.js +168 -0
- package/dist/_pkgs/affine-block-image/replace/toolbar.d.ts +21 -0
- package/dist/_pkgs/affine-block-image/replace/toolbar.js +159 -0
- package/dist/_pkgs/affine-block-image/translations.d.ts +15 -2
- package/dist/_pkgs/affine-block-image/translations.js +35 -2
- package/dist/_pkgs/affine-block-image/utils.d.ts +7 -0
- package/dist/_pkgs/affine-block-image/utils.js +13 -0
- package/dist/_pkgs/affine-block-image/view.js +7 -0
- package/dist/_pkgs/affine-block-note/components/edgeless-page-block-title.d.ts +14 -5
- package/dist/_pkgs/affine-block-note/components/edgeless-page-block-title.js +18 -11
- package/dist/_pkgs/affine-block-note/config.d.ts +9 -2
- package/dist/_pkgs/affine-block-note/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-note/edgeless-clipboard-config.js +8 -5
- package/dist/_pkgs/affine-block-paragraph/adapters/markdown.js +11 -0
- package/dist/_pkgs/affine-block-root/commands/invisible-characters-commands.d.ts +17 -0
- package/dist/_pkgs/affine-block-root/commands/invisible-characters-commands.js +123 -0
- package/dist/_pkgs/affine-block-root/edgeless/clipboard/command.js +82 -65
- package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.js +2 -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/translations.d.ts +6 -0
- package/dist/_pkgs/affine-block-root/translations.js +10 -0
- package/dist/_pkgs/affine-block-root/view.js +6 -1
- package/dist/_pkgs/affine-block-surface/commands/index.d.ts +1 -1
- package/dist/_pkgs/affine-block-surface/commands/index.js +1 -1
- package/dist/_pkgs/affine-block-surface/commands/reassociate-connectors.d.ts +9 -0
- package/dist/_pkgs/affine-block-surface/commands/reassociate-connectors.js +21 -12
- package/dist/_pkgs/affine-block-surface/extensions/clipboard-config.d.ts +33 -0
- package/dist/_pkgs/affine-block-surface/extensions/clipboard-config.js +53 -0
- package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +1 -0
- package/dist/_pkgs/affine-block-surface/extensions/index.js +1 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend-label.d.ts +11 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend-label.js +16 -0
- package/dist/_pkgs/affine-block-surface/extensions/legend.d.ts +1 -11
- package/dist/_pkgs/affine-block-surface/extensions/legend.js +2 -11
- package/dist/_pkgs/affine-block-surface/extensions/reading-toolbar.js +12 -12
- package/dist/_pkgs/affine-block-surface/extensions/toolbox.d.ts +62 -0
- package/dist/_pkgs/affine-block-surface/extensions/toolbox.js +1 -0
- package/dist/_pkgs/affine-block-surface/framework-background/background-view.js +2 -1
- package/dist/_pkgs/affine-block-surface/framework-background/band-widths.d.ts +104 -0
- package/dist/_pkgs/affine-block-surface/framework-background/band-widths.js +156 -0
- package/dist/_pkgs/affine-block-surface/framework-background/def.d.ts +87 -4
- package/dist/_pkgs/affine-block-surface/framework-background/def.js +26 -7
- package/dist/_pkgs/affine-block-surface/framework-background/ellipsis.d.ts +58 -0
- package/dist/_pkgs/affine-block-surface/framework-background/ellipsis.js +110 -0
- package/dist/_pkgs/affine-block-surface/framework-background/index.d.ts +3 -0
- package/dist/_pkgs/affine-block-surface/framework-background/index.js +3 -0
- package/dist/_pkgs/affine-block-surface/framework-background/labels.d.ts +12 -2
- package/dist/_pkgs/affine-block-surface/framework-background/labels.js +29 -5
- package/dist/_pkgs/affine-block-surface/framework-background/measure-text.d.ts +14 -0
- package/dist/_pkgs/affine-block-surface/framework-background/measure-text.js +31 -0
- package/dist/_pkgs/affine-block-surface/framework-background/renderer.d.ts +14 -1
- package/dist/_pkgs/affine-block-surface/framework-background/renderer.js +84 -31
- package/dist/_pkgs/affine-block-surface/interchange-headless.d.ts +2 -0
- package/dist/_pkgs/affine-block-surface/interchange-headless.js +2 -0
- package/dist/_pkgs/affine-block-table/adapters/html.js +26 -14
- package/dist/_pkgs/affine-block-table/adapters/utils.d.ts +1 -0
- package/dist/_pkgs/affine-block-table/adapters/utils.js +23 -5
- package/dist/_pkgs/affine-block-table/header-menu.d.ts +13 -0
- package/dist/_pkgs/affine-block-table/header-menu.js +25 -0
- package/dist/_pkgs/affine-block-table/selection-controller.d.ts +15 -0
- package/dist/_pkgs/affine-block-table/selection-controller.js +62 -0
- package/dist/_pkgs/affine-block-table/table-cell-css.d.ts +7 -0
- package/dist/_pkgs/affine-block-table/table-cell-css.js +10 -0
- package/dist/_pkgs/affine-block-table/table-cell.d.ts +8 -0
- package/dist/_pkgs/affine-block-table/table-cell.js +35 -3
- package/dist/_pkgs/affine-block-table/table-data-manager.d.ts +14 -0
- package/dist/_pkgs/affine-block-table/table-data-manager.js +44 -3
- package/dist/_pkgs/affine-block-table/translations.d.ts +14 -0
- package/dist/_pkgs/affine-block-table/translations.js +22 -0
- package/dist/_pkgs/affine-components/highlight-dropdown-menu/highlight-duotone-icon.js +8 -8
- package/dist/_pkgs/affine-components/highlight-dropdown-menu/text-duotone-icon.js +11 -11
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/mindmap-tool-button.d.ts +2 -2
- package/dist/_pkgs/affine-gfx-template/builtin/other.d.ts +4 -0
- package/dist/_pkgs/affine-gfx-template/builtin/other.js +1 -1
- package/dist/_pkgs/affine-gfx-template/builtin/slides/build.d.ts +81 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/build.js +276 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/consts.d.ts +126 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/consts.js +101 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/index.d.ts +8 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/index.js +27 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/masks.d.ts +83 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/masks.js +674 -0
- package/dist/_pkgs/affine-gfx-template/contribute.js +12 -17
- package/dist/_pkgs/affine-gfx-template/make-snapshot.d.ts +14 -2
- package/dist/_pkgs/affine-gfx-template/make-snapshot.js +6 -2
- package/dist/_pkgs/affine-gfx-template/services/template-middlewares.d.ts +12 -0
- package/dist/_pkgs/affine-gfx-template/services/template-middlewares.js +48 -0
- package/dist/_pkgs/affine-gfx-template/services/template.js +2 -1
- package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.d.ts +15 -1
- package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.js +33 -37
- package/dist/_pkgs/affine-gfx-template/toolbar/template-type.d.ts +6 -0
- package/dist/_pkgs/affine-gfx-template/translations.d.ts +94 -0
- package/dist/_pkgs/affine-gfx-template/translations.js +441 -2
- package/dist/_pkgs/affine-model/blocks/table/table-model.d.ts +4 -0
- package/dist/_pkgs/affine-model/blocks/table/table-model.js +4 -0
- package/dist/_pkgs/affine-model/elements/bpmn/node.d.ts +46 -3
- package/dist/_pkgs/affine-model/elements/bpmn/node.js +47 -4
- package/dist/_pkgs/affine-model/elements/bpmn/pool.d.ts +20 -0
- package/dist/_pkgs/affine-model/elements/bpmn/pool.js +33 -4
- package/dist/_pkgs/affine-model/elements/c4/board.d.ts +0 -22
- package/dist/_pkgs/affine-model/elements/c4/board.js +1 -22
- package/dist/_pkgs/affine-model/elements/c4/consts.d.ts +29 -0
- package/dist/_pkgs/affine-model/elements/c4/consts.js +29 -0
- package/dist/_pkgs/affine-model/elements/c4/index.d.ts +1 -0
- package/dist/_pkgs/affine-model/elements/c4/index.js +1 -0
- package/dist/_pkgs/affine-model/headless.d.ts +1 -0
- package/dist/_pkgs/affine-model/headless.js +1 -0
- package/dist/_pkgs/affine-shared/services/edit-props-store.d.ts +3 -16
- package/dist/_pkgs/affine-shared/services/edit-props-store.js +16 -16
- package/dist/_pkgs/affine-shared/services/editor-setting-service.d.ts +3 -0
- package/dist/_pkgs/affine-shared/services/editor-setting-service.js +4 -0
- package/dist/_pkgs/affine-shared/services/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/services/index.js +1 -0
- package/dist/_pkgs/affine-shared/services/invisible-characters.d.ts +33 -0
- package/dist/_pkgs/affine-shared/services/invisible-characters.js +63 -0
- package/dist/_pkgs/affine-shared/services/link-preview-service/link-preview-cache.d.ts +0 -9
- package/dist/_pkgs/affine-shared/services/link-preview-service/link-preview-cache.js +3 -9
- package/dist/_pkgs/affine-shared/services/telemetry-service/lifecycle.d.ts +26 -0
- package/dist/_pkgs/affine-shared/services/telemetry-service/telemetry-service.d.ts +4 -3
- package/dist/_pkgs/affine-shared/services/telemetry-service/types.d.ts +11 -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/invisible-characters.d.ts +42 -0
- package/dist/_pkgs/affine-shared/utils/invisible-characters.js +81 -0
- package/dist/_pkgs/affine-widget-edgeless-zoom-toolbar/index.js +26 -26
- package/dist/_pkgs/affine-widget-edgeless-zoom-toolbar/zoom-toolbar.js +13 -2
- package/dist/_pkgs/affine-widget-keyboard-toolbar/icons.js +98 -98
- package/dist/_pkgs/affine-widget-page-dragging-area/index.js +10 -10
- package/dist/_pkgs/affine-widget-viewport-overlay/index.js +13 -13
- package/dist/_pkgs/data-view/core/utils/menu-title.js +17 -17
- package/dist/_pkgs/data-view/view-presets/table/pc/header/column-header.js +6 -0
- package/dist/_pkgs/data-view/view-presets/table/pc/table-view-ui-logic.js +5 -2
- package/dist/_pkgs/std/clipboard/clipboard.d.ts +15 -1
- package/dist/_pkgs/std/clipboard/clipboard.js +18 -0
- package/dist/_pkgs/std/inline/components/embed-gap.js +1 -1
- package/dist/_pkgs/std/inline/components/v-line.js +1 -1
- package/dist/_pkgs/std/inline/components/v-text.d.ts +15 -2
- package/dist/_pkgs/std/inline/components/v-text.js +147 -15
- package/dist/_pkgs/std/inline/consts.d.ts +5 -0
- package/dist/_pkgs/std/inline/consts.js +5 -0
- package/dist/_pkgs/std/inline/utils/index.d.ts +1 -0
- package/dist/_pkgs/std/inline/utils/index.js +1 -0
- package/dist/_pkgs/std/inline/utils/invisible-characters.d.ts +57 -0
- package/dist/_pkgs/std/inline/utils/invisible-characters.js +162 -0
- package/dist/_pkgs/std/inline/utils/point-conversion.js +3 -3
- package/dist/_pkgs/std/inline/utils/text.d.ts +8 -0
- package/dist/_pkgs/std/inline/utils/text.js +11 -2
- package/dist/_pkgs/store/model/store/crud.d.ts +28 -0
- package/dist/_pkgs/store/model/store/crud.js +97 -30
- package/dist/_pkgs/store/model/store/query.js +3 -2
- package/dist/_pkgs/store/model/store/store.d.ts +21 -0
- package/dist/_pkgs/store/model/store/store.js +88 -21
- package/dist/_pkgs/store/transformer/transformer.d.ts +46 -0
- package/dist/_pkgs/store/transformer/transformer.js +72 -0
- package/dist/commands.js +6 -1
- package/dist/translations.js +2 -0
- package/package.json +3 -4
package/architecture/domain.c4
CHANGED
|
@@ -524,6 +524,12 @@ model {
|
|
|
524
524
|
domain_file '1.00'
|
|
525
525
|
}
|
|
526
526
|
}
|
|
527
|
+
extend features.blocks.image.replace {
|
|
528
|
+
metadata {
|
|
529
|
+
domain ['file']
|
|
530
|
+
domain_file '1.00'
|
|
531
|
+
}
|
|
532
|
+
}
|
|
527
533
|
extend features.blocks.image.src {
|
|
528
534
|
metadata {
|
|
529
535
|
domain ['file']
|
|
@@ -677,7 +683,7 @@ model {
|
|
|
677
683
|
extend features.blocks.root {
|
|
678
684
|
metadata {
|
|
679
685
|
domain ['canvas', 'file']
|
|
680
|
-
domain_canvas '0.
|
|
686
|
+
domain_canvas '0.49'
|
|
681
687
|
domain_file '0.15'
|
|
682
688
|
}
|
|
683
689
|
}
|
|
@@ -702,9 +708,9 @@ model {
|
|
|
702
708
|
extend features.blocks.surface {
|
|
703
709
|
metadata {
|
|
704
710
|
domain ['canvas', 'file', 'layer']
|
|
705
|
-
domain_canvas '0.
|
|
706
|
-
domain_file '0.
|
|
707
|
-
domain_layer '0.
|
|
711
|
+
domain_canvas '0.75'
|
|
712
|
+
domain_file '0.17'
|
|
713
|
+
domain_layer '0.05'
|
|
708
714
|
}
|
|
709
715
|
}
|
|
710
716
|
extend features.blocks.surface-ref {
|
|
@@ -764,8 +770,8 @@ model {
|
|
|
764
770
|
extend features.blocks.surface.extensions {
|
|
765
771
|
metadata {
|
|
766
772
|
domain ['canvas', 'file', 'layer']
|
|
767
|
-
domain_canvas '0.
|
|
768
|
-
domain_file '0.
|
|
773
|
+
domain_canvas '0.53'
|
|
774
|
+
domain_file '0.29'
|
|
769
775
|
domain_layer '0.12'
|
|
770
776
|
}
|
|
771
777
|
}
|
|
@@ -1945,7 +1951,7 @@ model {
|
|
|
1945
1951
|
extend features.shared.services {
|
|
1946
1952
|
metadata {
|
|
1947
1953
|
domain ['collaboration', 'canvas']
|
|
1948
|
-
domain_collaboration '0.
|
|
1954
|
+
domain_collaboration '0.11'
|
|
1949
1955
|
domain_canvas '0.06'
|
|
1950
1956
|
}
|
|
1951
1957
|
}
|
|
@@ -2286,7 +2292,7 @@ model {
|
|
|
2286
2292
|
metadata {
|
|
2287
2293
|
domain ['canvas', 'document']
|
|
2288
2294
|
domain_canvas '0.31'
|
|
2289
|
-
domain_document '0.
|
|
2295
|
+
domain_document '0.27'
|
|
2290
2296
|
}
|
|
2291
2297
|
}
|
|
2292
2298
|
extend framework.std.gfx {
|
|
@@ -2416,7 +2422,7 @@ model {
|
|
|
2416
2422
|
metadata {
|
|
2417
2423
|
domain ['document', 'canvas']
|
|
2418
2424
|
domain_document '0.72'
|
|
2419
|
-
domain_canvas '0.
|
|
2425
|
+
domain_canvas '0.24'
|
|
2420
2426
|
}
|
|
2421
2427
|
}
|
|
2422
2428
|
extend model_.model_.blocks {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "blocksuite"
|
|
3
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "blocksuite"
|
|
3
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { EdgelessClipboardConfig } from '../affine-block-surface/index.js';
|
|
1
|
+
import { type ClipboardConfigCreationContext, EdgelessClipboardConfig, type PreparedClipboardBlock } from '../affine-block-surface/index.js';
|
|
2
2
|
import { type BlockSnapshot } from '../store/index.js';
|
|
3
3
|
export declare class EdgelessClipboardAttachmentConfig extends EdgelessClipboardConfig {
|
|
4
4
|
static readonly key = "affine:attachment";
|
|
5
|
-
|
|
5
|
+
prepare(attachment: BlockSnapshot): Promise<PreparedClipboardBlock | null>;
|
|
6
|
+
createBlock(attachment: BlockSnapshot, context: ClipboardConfigCreationContext): Promise<string | null>;
|
|
6
7
|
}
|
|
@@ -1,24 +1,29 @@
|
|
|
1
|
-
import { EdgelessClipboardConfig } from '../affine-block-surface/index.js';
|
|
1
|
+
import { EdgelessClipboardConfig, } from '../affine-block-surface/index.js';
|
|
2
2
|
import {} from '../store/index.js';
|
|
3
3
|
export class EdgelessClipboardAttachmentConfig extends EdgelessClipboardConfig {
|
|
4
4
|
static { this.key = 'affine:attachment'; }
|
|
5
|
-
async
|
|
5
|
+
async prepare(attachment) {
|
|
6
6
|
if (!this.surface)
|
|
7
7
|
return null;
|
|
8
8
|
const { xywh, rotate, sourceId, name, size, type, embed, style } = attachment.props;
|
|
9
9
|
if (!(await this.std.workspace.blobSync.get(sourceId))) {
|
|
10
10
|
return null;
|
|
11
11
|
}
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
const surfaceId = this.surface.model.id;
|
|
13
|
+
return {
|
|
14
|
+
write: () => this.crud.addBlock('affine:attachment', {
|
|
15
|
+
xywh,
|
|
16
|
+
rotate,
|
|
17
|
+
sourceId,
|
|
18
|
+
name,
|
|
19
|
+
size,
|
|
20
|
+
type,
|
|
21
|
+
embed,
|
|
22
|
+
style,
|
|
23
|
+
}, surfaceId),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
createBlock(attachment, context) {
|
|
27
|
+
return this.createPreparedBlock(attachment, context);
|
|
23
28
|
}
|
|
24
29
|
}
|
|
@@ -135,8 +135,11 @@ export const calloutBlockMarkdownAdapterMatcher = {
|
|
|
135
135
|
.openNode({
|
|
136
136
|
type: 'paragraph',
|
|
137
137
|
children: [
|
|
138
|
+
// A raw node, not `text`: the stringifier escapes a `text` that
|
|
139
|
+
// starts with `[` (`\[!💡]`), which GFM and Obsidian readers
|
|
140
|
+
// show as a quote with the literal marker (#520).
|
|
138
141
|
{
|
|
139
|
-
type: '
|
|
142
|
+
type: 'html',
|
|
140
143
|
value: `[!${emoji}]`,
|
|
141
144
|
},
|
|
142
145
|
],
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { MarkdownPreprocessorExtension, } from '../../../affine-shared/adapters/index.js';
|
|
2
2
|
import { isValidUrl } from '../../../affine-shared/utils/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* A list item's marker (`-`, `*`, `+`, `1.`, `1)`) followed by a space or the
|
|
5
|
+
* end of the line. Its indentation is what nests it, so it is left alone (#519).
|
|
6
|
+
*/
|
|
7
|
+
const LIST_ITEM = /^(?:[*+-]|\d{1,9}[.)])(?:\s|$)/;
|
|
8
|
+
/**
|
|
9
|
+
* Plain text pasted as a slice (BlockSuite #6017, the plain-text adapter):
|
|
10
|
+
* the first leading space of a line becomes ` `, so the line keeps its
|
|
11
|
+
* indentation instead of losing it or turning into an indented code block.
|
|
12
|
+
* Fenced code, list items and `-` lines are left as written.
|
|
13
|
+
*/
|
|
3
14
|
const codePreprocessor = {
|
|
4
15
|
name: 'code',
|
|
5
16
|
levels: ['slice'],
|
|
@@ -8,7 +19,8 @@ const codePreprocessor = {
|
|
|
8
19
|
const lines = content
|
|
9
20
|
.split('\n')
|
|
10
21
|
.map(line => {
|
|
11
|
-
if (line.trimStart().startsWith('-')
|
|
22
|
+
if (line.trimStart().startsWith('-') ||
|
|
23
|
+
LIST_ITEM.test(line.trimStart())) {
|
|
12
24
|
return line;
|
|
13
25
|
}
|
|
14
26
|
let trimmedLine = line.trimStart();
|
|
@@ -3,8 +3,21 @@ import type { CodeBlockModel } from '../affine-model/index.js';
|
|
|
3
3
|
import type { BlockComponent } from '../std/index.js';
|
|
4
4
|
import { type Signal } from '@preact/signals-core';
|
|
5
5
|
import { type TemplateResult } from 'lit';
|
|
6
|
-
import { type ThemedToken } from 'shiki';
|
|
6
|
+
import { type BundledLanguageInfo, type ThemedToken } from 'shiki';
|
|
7
7
|
import { CodeBlockHighlighter } from './code-block-service.js';
|
|
8
|
+
/**
|
|
9
|
+
* The language a stored `language` value stands for: matched on the id, the
|
|
10
|
+
* display name or an alias, so a document whose block says `'TypeScript'` or
|
|
11
|
+
* `'ts'` highlights as `typescript`. `undefined` (unknown or `null`) means
|
|
12
|
+
* plain text.
|
|
13
|
+
*
|
|
14
|
+
* Derived, never written back: the render path used to normalise the stored
|
|
15
|
+
* value to the id and to null an unknown one, which wrote to the store on every
|
|
16
|
+
* mount — on a readonly store, from a remote peer's render, and as an undo
|
|
17
|
+
* entry nobody made. The stored value stays what the author or the importer
|
|
18
|
+
* wrote; only a gesture (the language picker) changes it.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveCodeLanguage(language: string | null, langs: readonly BundledLanguageInfo[]): BundledLanguageInfo | undefined;
|
|
8
21
|
export declare class CodeBlockComponent extends CaptionedBlockComponent<CodeBlockModel> {
|
|
9
22
|
static styles: import("lit").CSSResult;
|
|
10
23
|
private _inlineRangeProvider;
|
|
@@ -12,6 +25,8 @@ export declare class CodeBlockComponent extends CaptionedBlockComponent<CodeBloc
|
|
|
12
25
|
preview$: Signal<boolean>;
|
|
13
26
|
collapsed$: Signal<boolean>;
|
|
14
27
|
highlightTokens$: Signal<ThemedToken[][]>;
|
|
28
|
+
/** The language the block highlights as, see `resolveCodeLanguage`. */
|
|
29
|
+
languageInfo$: Signal<BundledLanguageInfo | undefined>;
|
|
15
30
|
languageName$: Signal<string>;
|
|
16
31
|
get inlineEditor(): import("../std/inline/inline-editor.js").InlineEditor<{
|
|
17
32
|
bold?: true | null | undefined;
|
|
@@ -24,7 +39,7 @@ export declare class CodeBlockComponent extends CaptionedBlockComponent<CodeBloc
|
|
|
24
39
|
get inlineManager(): import("../std/inline/index.js").InlineManager<import("../affine-shared/types/index.js").AffineTextAttributes>;
|
|
25
40
|
get notificationService(): import("../affine-shared/services/notification-service.js").NotificationService | null;
|
|
26
41
|
get readonly(): boolean;
|
|
27
|
-
get langs():
|
|
42
|
+
get langs(): BundledLanguageInfo[];
|
|
28
43
|
get highlighter(): CodeBlockHighlighter;
|
|
29
44
|
/**
|
|
30
45
|
* Whether line numbers are currently shown for this block, accounting for the
|
|
@@ -47,7 +47,7 @@ import { html, nothing } from 'lit';
|
|
|
47
47
|
import { query } from 'lit/decorators.js';
|
|
48
48
|
import { classMap } from 'lit/directives/class-map.js';
|
|
49
49
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
50
|
-
import { bundledLanguagesInfo } from 'shiki';
|
|
50
|
+
import { bundledLanguagesInfo, } from 'shiki';
|
|
51
51
|
import { CodeBlockConfigExtension } from './code-block-config.js';
|
|
52
52
|
import { CodeBlockInlineManagerExtension } from './code-block-inline.js';
|
|
53
53
|
import { CodeBlockHighlighter } from './code-block-service.js';
|
|
@@ -55,6 +55,25 @@ import { CodeBlockPreviewIdentifier } from './code-preview-extension.js';
|
|
|
55
55
|
import { readGlobalLineNumbers, resolveShowLineNumbers, } from './line-numbers.js';
|
|
56
56
|
import { codeBlockStyles } from './styles.js';
|
|
57
57
|
import { CODE_COPY_FAILED, CODE_PLAIN_TEXT_LANGUAGE } from './translations.js';
|
|
58
|
+
/**
|
|
59
|
+
* The language a stored `language` value stands for: matched on the id, the
|
|
60
|
+
* display name or an alias, so a document whose block says `'TypeScript'` or
|
|
61
|
+
* `'ts'` highlights as `typescript`. `undefined` (unknown or `null`) means
|
|
62
|
+
* plain text.
|
|
63
|
+
*
|
|
64
|
+
* Derived, never written back: the render path used to normalise the stored
|
|
65
|
+
* value to the id and to null an unknown one, which wrote to the store on every
|
|
66
|
+
* mount — on a readonly store, from a remote peer's render, and as an undo
|
|
67
|
+
* entry nobody made. The stored value stays what the author or the importer
|
|
68
|
+
* wrote; only a gesture (the language picker) changes it.
|
|
69
|
+
*/
|
|
70
|
+
export function resolveCodeLanguage(language, langs) {
|
|
71
|
+
if (language === null)
|
|
72
|
+
return undefined;
|
|
73
|
+
return langs.find(info => info.id === language ||
|
|
74
|
+
info.name === language ||
|
|
75
|
+
info.aliases?.includes(language));
|
|
76
|
+
}
|
|
58
77
|
let CodeBlockComponent = (() => {
|
|
59
78
|
let _classSuper = CaptionedBlockComponent;
|
|
60
79
|
let __richTextElement_decorators;
|
|
@@ -74,16 +93,10 @@ let CodeBlockComponent = (() => {
|
|
|
74
93
|
});
|
|
75
94
|
this.collapsed$ = computed(() => !!this.model.props.collapsed$.value);
|
|
76
95
|
this.highlightTokens$ = signal([]);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
const matchedInfo = this.langs.find(info => info.id === lang);
|
|
83
|
-
return matchedInfo
|
|
84
|
-
? matchedInfo.name
|
|
85
|
-
: translateKey(this.std, ...CODE_PLAIN_TEXT_LANGUAGE);
|
|
86
|
-
});
|
|
96
|
+
/** The language the block highlights as, see `resolveCodeLanguage`. */
|
|
97
|
+
this.languageInfo$ = computed(() => resolveCodeLanguage(this.model.props.language$.value, this.langs));
|
|
98
|
+
this.languageName$ = computed(() => this.languageInfo$.value?.name ??
|
|
99
|
+
translateKey(this.std, ...CODE_PLAIN_TEXT_LANGUAGE));
|
|
87
100
|
/**
|
|
88
101
|
* Bumped on every highlight request: a grammar load that resolves after a
|
|
89
102
|
* newer request (another language, or plain text) must not repaint the
|
|
@@ -153,16 +166,10 @@ let CodeBlockComponent = (() => {
|
|
|
153
166
|
}
|
|
154
167
|
_updateHighlightTokens() {
|
|
155
168
|
const requestId = ++this._highlightRequestId;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
const matchedInfo = this.langs.find(info => info.id === modelLang ||
|
|
162
|
-
info.name === modelLang ||
|
|
163
|
-
info.aliases?.includes(modelLang));
|
|
169
|
+
// Resolved here rather than read from `languageInfo$`: the race spec
|
|
170
|
+
// drives this method on a stub that has no component field initializers.
|
|
171
|
+
const matchedInfo = resolveCodeLanguage(this.model.props.language$.value, this.langs);
|
|
164
172
|
if (matchedInfo) {
|
|
165
|
-
this.model.props.language$.value = matchedInfo.id;
|
|
166
173
|
const langImport = matchedInfo.import;
|
|
167
174
|
const lang = matchedInfo.id;
|
|
168
175
|
const highlighter = this.highlighter.highlighter$.value;
|
|
@@ -196,8 +203,6 @@ let CodeBlockComponent = (() => {
|
|
|
196
203
|
}
|
|
197
204
|
else {
|
|
198
205
|
this.highlightTokens$.value = [];
|
|
199
|
-
// clear language if not found
|
|
200
|
-
this.model.props.language$.value = null;
|
|
201
206
|
}
|
|
202
207
|
}
|
|
203
208
|
connectedCallback() {
|
|
@@ -418,7 +423,7 @@ let CodeBlockComponent = (() => {
|
|
|
418
423
|
renderBlock() {
|
|
419
424
|
const showLineNumbers = this.showLineNumbers;
|
|
420
425
|
const preview = this.preview$.value;
|
|
421
|
-
const previewContext = this.std.getOptional(CodeBlockPreviewIdentifier(this.
|
|
426
|
+
const previewContext = this.std.getOptional(CodeBlockPreviewIdentifier(this.languageInfo$.value?.id ?? ''));
|
|
422
427
|
const shouldRenderPreview = preview && previewContext;
|
|
423
428
|
const collapsed = this.collapsed$.value;
|
|
424
429
|
return html `
|
|
@@ -42,6 +42,7 @@ import { css, LitElement, nothing } from 'lit';
|
|
|
42
42
|
import { property, query } from 'lit/decorators.js';
|
|
43
43
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
44
44
|
import { html } from 'lit/static-html.js';
|
|
45
|
+
import { resolveCodeLanguage } from '../../code-block.js';
|
|
45
46
|
import { CODE_PLAIN_TEXT_LANGUAGE, CODE_SEARCH_FOR_LANGUAGE, } from '../../translations.js';
|
|
46
47
|
/**
|
|
47
48
|
* The list name of the Plain Text entry, which stands for `language: null`
|
|
@@ -191,9 +192,17 @@ let LanguageListButton = (() => {
|
|
|
191
192
|
sortedBundledLanguages.splice(index, 1);
|
|
192
193
|
sortedBundledLanguages.unshift(item);
|
|
193
194
|
}
|
|
194
|
-
this.blockComponent
|
|
195
|
-
|
|
196
|
-
|
|
195
|
+
const { store, model } = this.blockComponent;
|
|
196
|
+
// The button is disabled on a readonly store, but a list opened
|
|
197
|
+
// before the store turned readonly can still fire.
|
|
198
|
+
if (store.readonly)
|
|
199
|
+
return;
|
|
200
|
+
const language = languageOf(item);
|
|
201
|
+
// An unchanged write would push an empty undo entry.
|
|
202
|
+
if (model.props.language === language)
|
|
203
|
+
return;
|
|
204
|
+
store.captureSync();
|
|
205
|
+
store.updateBlock(model, { language });
|
|
197
206
|
const std = this.blockComponent.std;
|
|
198
207
|
const mode = std.getOptional(DocModeProvider)?.getEditorMode() ?? 'page';
|
|
199
208
|
const telemetryService = std.getOptional(TelemetryProvider);
|
|
@@ -206,7 +215,11 @@ let LanguageListButton = (() => {
|
|
|
206
215
|
control: item.name,
|
|
207
216
|
});
|
|
208
217
|
},
|
|
209
|
-
|
|
218
|
+
// Against the resolved id, so a block stored as `'TypeScript'` or
|
|
219
|
+
// with an unknown language still marks its entry (Plain Text for the
|
|
220
|
+
// latter).
|
|
221
|
+
active: item => languageOf(item) ===
|
|
222
|
+
(resolveCodeLanguage(this.blockComponent.model.props.language, this.blockComponent.langs)?.id ?? null),
|
|
210
223
|
items: this._sortedBundledLanguages,
|
|
211
224
|
};
|
|
212
225
|
showPopFilterableList({
|
|
@@ -100,7 +100,7 @@ let PreviewButton = (() => {
|
|
|
100
100
|
return this.blockComponent.preview$.value;
|
|
101
101
|
}
|
|
102
102
|
render() {
|
|
103
|
-
const lang = this.blockComponent.
|
|
103
|
+
const lang = this.blockComponent.languageInfo$.value?.id ?? '';
|
|
104
104
|
const previewContext = this.blockComponent.std.getOptional(CodeBlockPreviewIdentifier(lang));
|
|
105
105
|
if (!previewContext)
|
|
106
106
|
return nothing;
|
|
@@ -81,10 +81,14 @@ export class BlockQueryDataSource extends DataSourceBase {
|
|
|
81
81
|
cellValueChange(rowId, propertyId, value) {
|
|
82
82
|
const viewColumn = this.getViewColumn(propertyId);
|
|
83
83
|
if (viewColumn) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
// A nested prop write goes through the props proxy with its own origin,
|
|
85
|
+
// which the undo manager does not track: transact makes it undoable.
|
|
86
|
+
this.block.store.transact(() => {
|
|
87
|
+
this.block.props.cells[rowId] = {
|
|
88
|
+
...this.block.props.cells[rowId],
|
|
89
|
+
[propertyId]: value,
|
|
90
|
+
};
|
|
91
|
+
});
|
|
88
92
|
return;
|
|
89
93
|
}
|
|
90
94
|
const block = this.blockMap.get(rowId);
|
|
@@ -158,7 +162,10 @@ export class BlockQueryDataSource extends DataSourceBase {
|
|
|
158
162
|
propertyDelete(_id) {
|
|
159
163
|
const index = this.block.props.columns.findIndex(v => v.id === _id);
|
|
160
164
|
if (index >= 0) {
|
|
161
|
-
|
|
165
|
+
// Same origin trap as `cellValueChange`.
|
|
166
|
+
this.block.store.transact(() => {
|
|
167
|
+
this.block.props.columns.splice(index, 1);
|
|
168
|
+
});
|
|
162
169
|
}
|
|
163
170
|
}
|
|
164
171
|
propertyDuplicate(_columnId) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { EdgelessClipboardConfig } from '../affine-block-surface/index.js';
|
|
1
|
+
import { type ClipboardConfigCreationContext, EdgelessClipboardConfig, type PreparedClipboardBlock } from '../affine-block-surface/index.js';
|
|
2
2
|
import { type BlockSnapshot } from '../store/index.js';
|
|
3
3
|
export declare class EdgelessClipboardEdgelessTextConfig extends EdgelessClipboardConfig {
|
|
4
4
|
static readonly key = "affine:edgeless-text";
|
|
5
|
-
|
|
5
|
+
prepare(edgelessText: BlockSnapshot): Promise<PreparedClipboardBlock | null>;
|
|
6
|
+
createBlock(edgelessText: BlockSnapshot, context: ClipboardConfigCreationContext): Promise<string | null>;
|
|
6
7
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { EdgelessClipboardConfig } from '../affine-block-surface/index.js';
|
|
1
|
+
import { EdgelessClipboardConfig, } from '../affine-block-surface/index.js';
|
|
2
2
|
import {} from '../store/index.js';
|
|
3
3
|
export class EdgelessClipboardEdgelessTextConfig extends EdgelessClipboardConfig {
|
|
4
4
|
static { this.key = 'affine:edgeless-text'; }
|
|
5
|
-
async
|
|
5
|
+
async prepare(edgelessText) {
|
|
6
6
|
const oldId = edgelessText.id;
|
|
7
7
|
delete edgelessText.props.index;
|
|
8
8
|
if (!edgelessText.props.xywh) {
|
|
@@ -12,11 +12,14 @@ export class EdgelessClipboardEdgelessTextConfig extends EdgelessClipboardConfig
|
|
|
12
12
|
if (!this.surface) {
|
|
13
13
|
return null;
|
|
14
14
|
}
|
|
15
|
-
const
|
|
16
|
-
if (!
|
|
15
|
+
const prepared = await this.prepareBlockSnapshotPaste(edgelessText, this.std.store, this.surface.model.id);
|
|
16
|
+
if (!prepared) {
|
|
17
17
|
console.error(`Failed to paste EdgelessText block(id: ${oldId})`);
|
|
18
18
|
return null;
|
|
19
19
|
}
|
|
20
|
-
return
|
|
20
|
+
return prepared;
|
|
21
|
+
}
|
|
22
|
+
createBlock(edgelessText, context) {
|
|
23
|
+
return this.createPreparedBlock(edgelessText, context);
|
|
21
24
|
}
|
|
22
25
|
}
|
|
@@ -3,6 +3,7 @@ import { type AssetRef } from '../affine-shared/services/index.js';
|
|
|
3
3
|
import { type IVec } from '../global/gfx/index.js';
|
|
4
4
|
import type { BlockStdScope } from '../std/index.js';
|
|
5
5
|
import type { BlockModel } from '../store/index.js';
|
|
6
|
+
import { type ImageBlockSource } from './utils.js';
|
|
6
7
|
/**
|
|
7
8
|
* Images from the host's asset library (`AssetPickerProvider`, labre P4): the
|
|
8
9
|
* block references a blob the host already stores, by its `sourceId`. Nothing
|
|
@@ -16,6 +17,7 @@ type Size = {
|
|
|
16
17
|
width: number;
|
|
17
18
|
height: number;
|
|
18
19
|
};
|
|
20
|
+
export declare function imagePropsFrom(std: BlockStdScope, assets: readonly AssetRef[]): Promise<ImageBlockSource[]>;
|
|
19
21
|
/**
|
|
20
22
|
* Adds one image block per image ref next to `targetModel`, as one undo
|
|
21
23
|
* step. Refs that are not `image/*`, or whose size cannot be read, are
|
|
@@ -45,6 +47,12 @@ export declare function replacementProps(model: ImageBlockModel, asset: Pick<Ass
|
|
|
45
47
|
* that cannot be read, or a block deleted meanwhile.
|
|
46
48
|
*/
|
|
47
49
|
export declare function replaceImage(std: BlockStdScope, model: ImageBlockModel, asset: AssetRef): Promise<boolean>;
|
|
50
|
+
/**
|
|
51
|
+
* The write half of {@link replaceImage}, for a picture already measured
|
|
52
|
+
* ({@link pickImageSource}): same refusals, same one undo step, synchronous,
|
|
53
|
+
* so a caller re-reads its target after a dialog and writes at once.
|
|
54
|
+
*/
|
|
55
|
+
export declare function replaceImageSource(model: ImageBlockModel, source: ImageBlockSource): boolean;
|
|
48
56
|
/**
|
|
49
57
|
* The image entries of the slash menu and of the mobile keyboard toolbar:
|
|
50
58
|
* the host's asset dialog when there is one, the system file chooser
|
|
@@ -56,8 +64,21 @@ export declare function pickAndAddImages(std: BlockStdScope, options: {
|
|
|
56
64
|
maxWidth?: number;
|
|
57
65
|
}): Promise<string[]>;
|
|
58
66
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
67
|
+
* One picture to put in place of another, measured: the host's asset dialog
|
|
68
|
+
* when there is one (`replace` mode, one asset), the system file chooser
|
|
69
|
+
* otherwise (the file goes up through the blob source, like every
|
|
70
|
+
* file-chooser path). `null` when cancelled, when the ref is not an image or
|
|
71
|
+
* when its size cannot be read.
|
|
72
|
+
*
|
|
73
|
+
* Shared by the page toolbar's "Replace", the canvas image's « Replace with
|
|
74
|
+
* image » (`canvas.image.replaceWithImage`) and the shape's (ADR 0044,
|
|
75
|
+
* amendment of 2026-10-27): there is one way to choose a picture.
|
|
76
|
+
*/
|
|
77
|
+
export declare function pickImageSource(std: BlockStdScope): Promise<ImageBlockSource | null>;
|
|
78
|
+
/**
|
|
79
|
+
* The page toolbar's "Replace": {@link pickImageSource}, then
|
|
80
|
+
* {@link replaceImageSource} on the block as it is AFTER the dialog (it may
|
|
81
|
+
* be gone, or the document read-only, by then).
|
|
61
82
|
*/
|
|
62
83
|
export declare function pickAndReplaceImage(std: BlockStdScope, model: ImageBlockModel): Promise<boolean>;
|
|
63
84
|
export {};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { toast } from '../affine-components/toast/index.js';
|
|
2
2
|
import { ImageBlockSchema, } from '../affine-model/index.js';
|
|
3
3
|
import { AssetPickerProvider, translateKey, } from '../affine-shared/services/index.js';
|
|
4
|
-
import { getImageFilesFromLocal, readImageSize, } from '../affine-shared/utils/index.js';
|
|
4
|
+
import { getImageFilesFromLocal, openFilesWith, readImageSize, } from '../affine-shared/utils/index.js';
|
|
5
5
|
import { Bound } from '../global/gfx/index.js';
|
|
6
6
|
import { IMAGE_TOAST_READ_SIZE_FAILED } from './translations.js';
|
|
7
|
-
import { addImages, addSiblingImageBlocks, placeImagesOnCanvas, } from './utils.js';
|
|
7
|
+
import { addImages, addSiblingImageBlocks, imageSourceFromFile, placeImagesOnCanvas, } from './utils.js';
|
|
8
8
|
function isSize(width = 0, height = 0) {
|
|
9
9
|
return width > 0 && height > 0;
|
|
10
10
|
}
|
|
@@ -20,7 +20,7 @@ async function naturalSize(store, asset) {
|
|
|
20
20
|
const size = await readImageSize(typed);
|
|
21
21
|
return isSize(size.width, size.height) ? size : null;
|
|
22
22
|
}
|
|
23
|
-
async function imagePropsFrom(std, assets) {
|
|
23
|
+
export async function imagePropsFrom(std, assets) {
|
|
24
24
|
const images = assets.filter(asset => asset.type.startsWith('image/'));
|
|
25
25
|
const sized = await Promise.all(images.map(async (asset) => {
|
|
26
26
|
const size = await naturalSize(std.store, asset);
|
|
@@ -109,8 +109,27 @@ export async function replaceImage(std, model, asset) {
|
|
|
109
109
|
toast(std.host, translateKey(std, ...IMAGE_TOAST_READ_SIZE_FAILED));
|
|
110
110
|
return false;
|
|
111
111
|
}
|
|
112
|
+
return replaceImageSource(model, {
|
|
113
|
+
sourceId: asset.sourceId,
|
|
114
|
+
size: asset.size,
|
|
115
|
+
...natural,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The write half of {@link replaceImage}, for a picture already measured
|
|
120
|
+
* ({@link pickImageSource}): same refusals, same one undo step, synchronous,
|
|
121
|
+
* so a caller re-reads its target after a dialog and writes at once.
|
|
122
|
+
*/
|
|
123
|
+
export function replaceImageSource(model, source) {
|
|
124
|
+
const { store } = model;
|
|
112
125
|
if (store.readonly || !store.getBlock(model.id))
|
|
113
126
|
return false;
|
|
127
|
+
if (!source.sourceId || !isSize(source.width, source.height))
|
|
128
|
+
return false;
|
|
129
|
+
if (source.sourceId === model.props.sourceId$.peek())
|
|
130
|
+
return false;
|
|
131
|
+
const natural = { width: source.width, height: source.height };
|
|
132
|
+
const asset = { sourceId: source.sourceId, size: source.size };
|
|
114
133
|
store.captureSync();
|
|
115
134
|
store.transact(() => {
|
|
116
135
|
store.updateBlock(model, replacementProps(model, asset, natural));
|
|
@@ -163,21 +182,42 @@ export async function pickAndAddImages(std, options) {
|
|
|
163
182
|
return addImagesFromAssets(std, assets, options);
|
|
164
183
|
}
|
|
165
184
|
/**
|
|
166
|
-
*
|
|
167
|
-
*
|
|
185
|
+
* One picture to put in place of another, measured: the host's asset dialog
|
|
186
|
+
* when there is one (`replace` mode, one asset), the system file chooser
|
|
187
|
+
* otherwise (the file goes up through the blob source, like every
|
|
188
|
+
* file-chooser path). `null` when cancelled, when the ref is not an image or
|
|
189
|
+
* when its size cannot be read.
|
|
190
|
+
*
|
|
191
|
+
* Shared by the page toolbar's "Replace", the canvas image's « Replace with
|
|
192
|
+
* image » (`canvas.image.replaceWithImage`) and the shape's (ADR 0044,
|
|
193
|
+
* amendment of 2026-10-27): there is one way to choose a picture.
|
|
168
194
|
*/
|
|
169
|
-
export async function
|
|
170
|
-
if (model.store.readonly)
|
|
171
|
-
return false;
|
|
195
|
+
export async function pickImageSource(std) {
|
|
172
196
|
const picked = pickRequest(std, {
|
|
173
197
|
kind: 'image',
|
|
174
198
|
mode: 'replace',
|
|
175
199
|
multiple: false,
|
|
176
200
|
});
|
|
177
|
-
if (
|
|
201
|
+
if (picked) {
|
|
202
|
+
const assets = await picked;
|
|
203
|
+
if (!assets?.length)
|
|
204
|
+
return null;
|
|
205
|
+
const [props] = await imagePropsFrom(std, assets.slice(0, 1));
|
|
206
|
+
return props ?? null;
|
|
207
|
+
}
|
|
208
|
+
const [file] = (await openFilesWith('Images', false)) ?? [];
|
|
209
|
+
return file ? imageSourceFromFile(std, file) : null;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* The page toolbar's "Replace": {@link pickImageSource}, then
|
|
213
|
+
* {@link replaceImageSource} on the block as it is AFTER the dialog (it may
|
|
214
|
+
* be gone, or the document read-only, by then).
|
|
215
|
+
*/
|
|
216
|
+
export async function pickAndReplaceImage(std, model) {
|
|
217
|
+
if (model.store.readonly)
|
|
178
218
|
return false;
|
|
179
|
-
const
|
|
180
|
-
if (!
|
|
219
|
+
const source = await pickImageSource(std);
|
|
220
|
+
if (!source)
|
|
181
221
|
return false;
|
|
182
|
-
return
|
|
222
|
+
return replaceImageSource(model, source);
|
|
183
223
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { ImageBlockModel } from '../../affine-model/index.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { ToolbarAction, ToolbarContext } from '../../affine-shared/services/index.js';
|
|
3
3
|
/**
|
|
4
|
-
* "Replace" on the image toolbar
|
|
5
|
-
* asset dialog in `replace` mode
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* "Replace" on the PAGE image toolbar: swaps the picture in place
|
|
5
|
+
* (`pickAndReplaceImage`), from the host's asset dialog in `replace` mode when
|
|
6
|
+
* there is one, from the system file chooser otherwise — so it is offered
|
|
7
|
+
* without a host too (ADR 0044, amendment of 2026-10-27). Hidden on a
|
|
8
|
+
* read-only document. The canvas toolbar has a « Replace » MENU instead
|
|
9
|
+
* (`replace/toolbar.ts`), which reaches the same picking helper through
|
|
10
|
+
* `canvas.image.replaceWithImage`.
|
|
8
11
|
*/
|
|
9
12
|
export declare function imageReplaceToolbarAction(getModel: (ctx: ToolbarContext) => ImageBlockModel | null): ToolbarAction;
|