@formicoidea/labre-core 0.57.0 → 0.59.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 +94 -65
- package/architecture/domain.c4 +2510 -0
- 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/reading-toolbar.js +12 -12
- 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-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-fragment-doc-title/title-band/title-band.d.ts +3 -1
- package/dist/_pkgs/affine-fragment-doc-title/title-band/title-band.js +15 -2
- 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-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
|
@@ -13,6 +13,13 @@ export declare function copyImageBlob(block: ImageBlockComponent | ImageEdgeless
|
|
|
13
13
|
*/
|
|
14
14
|
export declare function turnImageIntoCardView(block: ImageBlockComponent | ImageEdgelessBlockComponent): Promise<void>;
|
|
15
15
|
export declare function shouldResizeImage(node: Node, target: EventTarget | null): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* One picture from the system file chooser, uploaded to the blob store and
|
|
18
|
+
* measured, for a gesture that writes it itself (ADR 0044). `null` when the
|
|
19
|
+
* file is not an image, is over the size limit or cannot be measured; the
|
|
20
|
+
* user has been told why by a toast.
|
|
21
|
+
*/
|
|
22
|
+
export declare function imageSourceFromFile(std: BlockStdScope, file: File): Promise<ImageBlockSource | null>;
|
|
16
23
|
export declare function addSiblingImageBlocks(std: BlockStdScope, files: File[], targetModel: BlockModel, placement?: 'after' | 'before'): Promise<string[]>;
|
|
17
24
|
export declare function addImageBlocks(std: BlockStdScope, files: File[], parent?: BlockModel | string | null, parentIndex?: number): Promise<string[]>;
|
|
18
25
|
export declare function addImages(std: BlockStdScope, files: File[], options: {
|
|
@@ -165,6 +165,19 @@ async function buildPropsWith(std, file) {
|
|
|
165
165
|
}
|
|
166
166
|
return { size, sourceId, ...imageSize };
|
|
167
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* One picture from the system file chooser, uploaded to the blob store and
|
|
170
|
+
* measured, for a gesture that writes it itself (ADR 0044). `null` when the
|
|
171
|
+
* file is not an image, is over the size limit or cannot be measured; the
|
|
172
|
+
* user has been told why by a toast.
|
|
173
|
+
*/
|
|
174
|
+
export async function imageSourceFromFile(std, file) {
|
|
175
|
+
if (!file.type.startsWith('image/'))
|
|
176
|
+
return null;
|
|
177
|
+
if (hasExceeded(std, [file]))
|
|
178
|
+
return null;
|
|
179
|
+
return buildPropsWith(std, file).catch(() => null);
|
|
180
|
+
}
|
|
168
181
|
export async function addSiblingImageBlocks(std, files, targetModel, placement = 'after') {
|
|
169
182
|
files = files.filter(file => file.type.startsWith('image/'));
|
|
170
183
|
if (!files.length)
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { ViewExtensionProvider, } from '../affine-ext-loader/index.js';
|
|
2
|
+
import { CommandExtension } from '../std/index.js';
|
|
2
3
|
import { EdgelessClipboardImageConfig } from './edgeless-clipboard-config.js';
|
|
3
4
|
import { effects } from './effects.js';
|
|
4
5
|
import { ImageEdgelessBlockInteraction } from './image-edgeless-block.js';
|
|
5
6
|
import { ImageBlockSpec } from './image-spec.js';
|
|
7
|
+
import { imageReplaceCommands } from './replace/commands.js';
|
|
8
|
+
import { shapeReplaceWithImageToolbarExtension } from './replace/toolbar.js';
|
|
6
9
|
export class ImageViewExtension extends ViewExtensionProvider {
|
|
7
10
|
constructor() {
|
|
8
11
|
super(...arguments);
|
|
@@ -18,6 +21,10 @@ export class ImageViewExtension extends ViewExtensionProvider {
|
|
|
18
21
|
if (this.isEdgeless(context.scope)) {
|
|
19
22
|
context.register(EdgelessClipboardImageConfig);
|
|
20
23
|
context.register(ImageEdgelessBlockInteraction);
|
|
24
|
+
// « Replace with image / with shape » (ADR 0044): the shape toolbar's
|
|
25
|
+
// entry is a second module on the shape flavour, owned by this package.
|
|
26
|
+
context.register(shapeReplaceWithImageToolbarExtension);
|
|
27
|
+
context.register(CommandExtension(imageReplaceCommands));
|
|
21
28
|
}
|
|
22
29
|
}
|
|
23
30
|
}
|
|
@@ -2,11 +2,20 @@ import { NoteBlockModel } from '../../affine-model/index.js';
|
|
|
2
2
|
import { type BlockStdScope, ShadowlessElement } from '../../std/index.js';
|
|
3
3
|
declare const EdgelessPageBlockTitle_base: typeof ShadowlessElement & import("../../global/utils/types.js").Constructor<import("../../global/lit/with-disposable.js").DisposableClass>;
|
|
4
4
|
/**
|
|
5
|
-
* The head of the page's note on the canvas: the
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* The head of the page's note on the canvas: the title, then the title band
|
|
6
|
+
* (ADR 0035 §11). The band sits inside the note's DOM so it follows the zoom
|
|
7
|
+
* like the rest of the note (REQ-PR-7); it draws nothing when the host
|
|
8
|
+
* registers no `TitleBandProvider`.
|
|
9
|
+
*
|
|
10
|
+
* The title is the host's `NoteConfigExtension.pageBlockTitle` when it
|
|
11
|
+
* registers one (`nothing` to draw none), else the document title itself.
|
|
12
|
+
* Until 0.59 a host without that config got no title on the canvas at all:
|
|
13
|
+
* the note was already wired for a `<doc-title>` (ArrowUp, the click routing
|
|
14
|
+
* of `EdgelessNoteInteraction`, the band not drawn twice) but nothing put one
|
|
15
|
+
* there. The fallback edits `root.props.title` like the page view's, behind
|
|
16
|
+
* the same note mask as the note's content, so it is editable only once the
|
|
17
|
+
* note is being edited, and never on a read-only store. Page mode never
|
|
18
|
+
* mounts this element, so the page view's own title is not doubled.
|
|
10
19
|
*/
|
|
11
20
|
export declare class EdgelessPageBlockTitle extends EdgelessPageBlockTitle_base {
|
|
12
21
|
render(): import("lit-html").TemplateResult<1> | undefined;
|
|
@@ -41,11 +41,20 @@ import { property } from 'lit/decorators.js';
|
|
|
41
41
|
import { NoteConfigExtension } from '../config.js';
|
|
42
42
|
import * as styles from './edgeless-page-block-title.css.js';
|
|
43
43
|
/**
|
|
44
|
-
* The head of the page's note on the canvas: the
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
44
|
+
* The head of the page's note on the canvas: the title, then the title band
|
|
45
|
+
* (ADR 0035 §11). The band sits inside the note's DOM so it follows the zoom
|
|
46
|
+
* like the rest of the note (REQ-PR-7); it draws nothing when the host
|
|
47
|
+
* registers no `TitleBandProvider`.
|
|
48
|
+
*
|
|
49
|
+
* The title is the host's `NoteConfigExtension.pageBlockTitle` when it
|
|
50
|
+
* registers one (`nothing` to draw none), else the document title itself.
|
|
51
|
+
* Until 0.59 a host without that config got no title on the canvas at all:
|
|
52
|
+
* the note was already wired for a `<doc-title>` (ArrowUp, the click routing
|
|
53
|
+
* of `EdgelessNoteInteraction`, the band not drawn twice) but nothing put one
|
|
54
|
+
* there. The fallback edits `root.props.title` like the page view's, behind
|
|
55
|
+
* the same note mask as the note's content, so it is editable only once the
|
|
56
|
+
* note is being edited, and never on a read-only store. Page mode never
|
|
57
|
+
* mounts this element, so the page view's own title is not doubled.
|
|
49
58
|
*/
|
|
50
59
|
let EdgelessPageBlockTitle = (() => {
|
|
51
60
|
let _classDecorators = [requiredProperties({
|
|
@@ -77,12 +86,10 @@ let EdgelessPageBlockTitle = (() => {
|
|
|
77
86
|
render() {
|
|
78
87
|
if (!this.note.isPageBlock())
|
|
79
88
|
return;
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
std: this.std,
|
|
85
|
-
});
|
|
89
|
+
const pageBlockTitle = this.std.getOptional(NoteConfigExtension.identifier)?.pageBlockTitle;
|
|
90
|
+
const title = pageBlockTitle
|
|
91
|
+
? pageBlockTitle({ note: this.note, std: this.std })
|
|
92
|
+
: html `<doc-title .doc=${this.note.store}></doc-title>`;
|
|
86
93
|
return html `<div class=${styles.pageBlockTitle}>
|
|
87
94
|
${title}
|
|
88
95
|
<labre-title-band
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import type { NoteBlockModel } from '../affine-model/index.js';
|
|
2
2
|
import { type BlockStdScope } from '../std/index.js';
|
|
3
|
-
import type { TemplateResult } from 'lit';
|
|
3
|
+
import type { nothing, TemplateResult } from 'lit';
|
|
4
4
|
type NoteBlockContext = {
|
|
5
5
|
note: NoteBlockModel;
|
|
6
6
|
std: BlockStdScope;
|
|
7
7
|
};
|
|
8
8
|
export type NoteConfig = {
|
|
9
9
|
edgelessNoteHeader: (context: NoteBlockContext) => TemplateResult;
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* The title at the head of the page note on the canvas. Absent, the note
|
|
12
|
+
* draws the document title itself (`<doc-title>`, editable like the rest
|
|
13
|
+
* of the note); a host that draws its own title elsewhere returns
|
|
14
|
+
* `nothing`. Optional since 0.59: a config typed against 0.58 still
|
|
15
|
+
* compiles (`note-config-shape.unit.spec.ts`).
|
|
16
|
+
*/
|
|
17
|
+
pageBlockTitle?: (context: NoteBlockContext) => TemplateResult | typeof nothing;
|
|
11
18
|
/**
|
|
12
19
|
* @returns if the viewport fit animation executed
|
|
13
20
|
*/
|
|
@@ -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 EdgelessClipboardNoteConfig extends EdgelessClipboardConfig {
|
|
4
4
|
static readonly key = "affine:note";
|
|
5
|
-
|
|
5
|
+
prepare(note: BlockSnapshot): Promise<PreparedClipboardBlock | null>;
|
|
6
|
+
createBlock(note: BlockSnapshot, context: ClipboardConfigCreationContext): Promise<null | string>;
|
|
6
7
|
}
|
|
@@ -1,19 +1,22 @@
|
|
|
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 EdgelessClipboardNoteConfig extends EdgelessClipboardConfig {
|
|
4
4
|
static { this.key = 'affine:note'; }
|
|
5
|
-
async
|
|
5
|
+
async prepare(note) {
|
|
6
6
|
const oldId = note.id;
|
|
7
7
|
delete note.props.index;
|
|
8
8
|
if (!note.props.xywh) {
|
|
9
9
|
console.error(`Note block(id: ${oldId}) does not have xywh property`);
|
|
10
10
|
return null;
|
|
11
11
|
}
|
|
12
|
-
const
|
|
13
|
-
if (!
|
|
12
|
+
const prepared = await this.prepareBlockSnapshotPaste(note, this.std.store, this.std.store.root.id);
|
|
13
|
+
if (!prepared) {
|
|
14
14
|
console.error(`Failed to paste note block(id: ${oldId})`);
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
17
|
-
return
|
|
17
|
+
return prepared;
|
|
18
|
+
}
|
|
19
|
+
createBlock(note, context) {
|
|
20
|
+
return this.createPreparedBlock(note, context);
|
|
18
21
|
}
|
|
19
22
|
}
|
|
@@ -3,6 +3,10 @@ import { BlockMarkdownAdapterExtension, IN_PARAGRAPH_NODE_CONTEXT_KEY, isCallout
|
|
|
3
3
|
import { nanoid } from '../../store/index.js';
|
|
4
4
|
const PARAGRAPH_MDAST_TYPE = new Set(['paragraph', 'heading', 'blockquote']);
|
|
5
5
|
const isParagraphMDASTType = (node) => PARAGRAPH_MDAST_TYPE.has(node.type);
|
|
6
|
+
const isImageOnlyParagraph = (node) => node.type === 'paragraph' &&
|
|
7
|
+
node.children.some(child => child.type === 'image') &&
|
|
8
|
+
node.children.every(child => child.type === 'image' ||
|
|
9
|
+
(child.type === 'text' && child.value.trim() === ''));
|
|
6
10
|
export const paragraphBlockMarkdownAdapterMatcher = {
|
|
7
11
|
flavour: ParagraphBlockSchema.model.flavour,
|
|
8
12
|
toMatch: o => isParagraphMDASTType(o.node) && !isCalloutNode(o.node),
|
|
@@ -12,6 +16,13 @@ export const paragraphBlockMarkdownAdapterMatcher = {
|
|
|
12
16
|
const { walkerContext, deltaConverter } = context;
|
|
13
17
|
switch (o.node.type) {
|
|
14
18
|
case 'paragraph': {
|
|
19
|
+
// mdast wraps a standalone image (or images split by a line
|
|
20
|
+
// break) in a paragraph; the image matcher emits the block itself,
|
|
21
|
+
// so opening a paragraph here left an empty one above it (#521).
|
|
22
|
+
// Markdown cannot express an empty paragraph: none is lost.
|
|
23
|
+
if (isImageOnlyParagraph(o.node)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
15
26
|
walkerContext.setGlobalContext(IN_PARAGRAPH_NODE_CONTEXT_KEY, true);
|
|
16
27
|
walkerContext
|
|
17
28
|
.openNode({
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AnyCommandDescriptor } from '../../std/index.js';
|
|
2
|
+
import type { Store } from '../../store/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Strip the invisible characters of every text of `store` — each block's
|
|
5
|
+
* text, the title, table and database cells, and through the surface block
|
|
6
|
+
* every canvas element's text, labels and titles — in ONE transaction, so one
|
|
7
|
+
* undo puts them all back. Writes nothing on a read-only store, and nothing
|
|
8
|
+
* when there is nothing to remove (no empty undo entry).
|
|
9
|
+
*
|
|
10
|
+
* `blockCount` counts blocks: the canvas is one, its elements live in the
|
|
11
|
+
* surface block.
|
|
12
|
+
*/
|
|
13
|
+
export declare function removeInvisibleCharacters(store: Store): {
|
|
14
|
+
count: number;
|
|
15
|
+
blockCount: number;
|
|
16
|
+
};
|
|
17
|
+
export declare const invisibleCharactersCommands: AnyCommandDescriptor[];
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The special characters of a text (`text.invisibles.*`): the zero-width
|
|
3
|
+
* spaces, word joiners and tag characters an AI text generator or a
|
|
4
|
+
* "watermarking" tool leaves behind, invisible to the reader and carried
|
|
5
|
+
* along by every copy.
|
|
6
|
+
*
|
|
7
|
+
* `owner: 'core'`, `scope: 'global'`: a paragraph is the same text in both
|
|
8
|
+
* views, and a canvas label is text too. On the palette, the agent and the
|
|
9
|
+
* host's view menu (`'view-menu'`, ADR 0034 amendment of 2026-10-13): the
|
|
10
|
+
* library draws no menu of its own, a host lists them with `getViewActions`
|
|
11
|
+
* and runs them through `runCommand`.
|
|
12
|
+
*
|
|
13
|
+
* Telemetry is emitted from the bodies, for `doc.copyLink`'s reason: the
|
|
14
|
+
* counts are facts of the invocation and the commands belong to no framework
|
|
15
|
+
* (see the telemetry README, "Special characters").
|
|
16
|
+
*/
|
|
17
|
+
import { InvisibleCharacters, NotificationProvider, TelemetryProvider, translateKey, } from '../../affine-shared/services/index.js';
|
|
18
|
+
import { collectYTexts, stripInvisiblesFromYText, } from '../../affine-shared/utils/index.js';
|
|
19
|
+
import { findInvisibleCharacters } from '../../std/inline/index.js';
|
|
20
|
+
import { ROOT_TOAST_INVISIBLES_REMOVED } from '../translations.js';
|
|
21
|
+
/**
|
|
22
|
+
* Code keeps its characters: a zero-width space in a string literal is the
|
|
23
|
+
* program's business, not a watermark.
|
|
24
|
+
*/
|
|
25
|
+
const UNTOUCHED_FLAVOURS = new Set(['affine:code']);
|
|
26
|
+
/**
|
|
27
|
+
* Strip the invisible characters of every text of `store` — each block's
|
|
28
|
+
* text, the title, table and database cells, and through the surface block
|
|
29
|
+
* every canvas element's text, labels and titles — in ONE transaction, so one
|
|
30
|
+
* undo puts them all back. Writes nothing on a read-only store, and nothing
|
|
31
|
+
* when there is nothing to remove (no empty undo entry).
|
|
32
|
+
*
|
|
33
|
+
* `blockCount` counts blocks: the canvas is one, its elements live in the
|
|
34
|
+
* surface block.
|
|
35
|
+
*/
|
|
36
|
+
export function removeInvisibleCharacters(store) {
|
|
37
|
+
if (store.readonly)
|
|
38
|
+
return { count: 0, blockCount: 0 };
|
|
39
|
+
const touched = store
|
|
40
|
+
.getAllModels()
|
|
41
|
+
.filter(model => !UNTOUCHED_FLAVOURS.has(model.flavour))
|
|
42
|
+
.map(model => ({ model, texts: collectYTexts(model.yBlock) }))
|
|
43
|
+
.filter(({ texts }) => texts.some(text => findInvisibleCharacters(text.toString()).length > 0));
|
|
44
|
+
if (touched.length === 0)
|
|
45
|
+
return { count: 0, blockCount: 0 };
|
|
46
|
+
let count = 0;
|
|
47
|
+
store.captureSync();
|
|
48
|
+
store.transact(() => {
|
|
49
|
+
for (const { texts } of touched) {
|
|
50
|
+
for (const text of texts)
|
|
51
|
+
count += stripInvisiblesFromYText(text);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
store.captureSync();
|
|
55
|
+
return { count, blockCount: touched.length };
|
|
56
|
+
}
|
|
57
|
+
const removeInvisibles = {
|
|
58
|
+
id: 'text.invisibles.remove',
|
|
59
|
+
owner: 'core',
|
|
60
|
+
kind: 'action',
|
|
61
|
+
labelKey: 'com.labre.command.text.invisibles.remove',
|
|
62
|
+
labelFallback: 'Remove invisible characters',
|
|
63
|
+
descriptionKey: 'com.labre.command.text.invisibles.remove.description',
|
|
64
|
+
descriptionFallback: 'Remove the zero-width spaces, word joiners and other invisible characters AI tools leave in a text. Emoji, code and no-break spaces are kept.',
|
|
65
|
+
category: 'text',
|
|
66
|
+
keywords: ['invisible', 'watermark', 'zero-width', 'clean', 'AI'],
|
|
67
|
+
surfaces: ['palette', 'agent', 'view-menu'],
|
|
68
|
+
order: 3,
|
|
69
|
+
scope: 'global',
|
|
70
|
+
defaultKeys: { mac: [], other: [] },
|
|
71
|
+
availability: 'editable',
|
|
72
|
+
run: std => {
|
|
73
|
+
const { count, blockCount } = removeInvisibleCharacters(std.store);
|
|
74
|
+
std
|
|
75
|
+
.getOptional(NotificationProvider)
|
|
76
|
+
?.toast(translateKey(std, ...ROOT_TOAST_INVISIBLES_REMOVED, { count }));
|
|
77
|
+
if (count === 0)
|
|
78
|
+
return;
|
|
79
|
+
std
|
|
80
|
+
.getOptional(TelemetryProvider)
|
|
81
|
+
?.track('InvisibleCharactersRemoved', { count, blockCount });
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Show or hide the special characters for THIS viewer: a dot per space, an
|
|
86
|
+
* arrow per tab, a degree sign per no-break space, a red mark per invisible
|
|
87
|
+
* character, ↵ and ¶ at line ends (`InvisibleCharacters`, `v-text`).
|
|
88
|
+
* Writes nothing to the document, so a reader may do it too.
|
|
89
|
+
*/
|
|
90
|
+
const toggleInvisibles = {
|
|
91
|
+
id: 'text.invisibles.toggle',
|
|
92
|
+
owner: 'core',
|
|
93
|
+
kind: 'action',
|
|
94
|
+
labelKey: 'com.labre.command.text.invisibles.toggle',
|
|
95
|
+
labelFallback: 'Show special characters',
|
|
96
|
+
descriptionKey: 'com.labre.command.text.invisibles.toggle.description',
|
|
97
|
+
descriptionFallback: 'Show or hide spaces, tabs, no-break spaces, line ends and invisible characters on your screen only.',
|
|
98
|
+
category: 'display',
|
|
99
|
+
keywords: ['invisible', 'whitespace', 'pilcrow', 'formatting', 'marks'],
|
|
100
|
+
surfaces: ['palette', 'agent', 'view-menu'],
|
|
101
|
+
order: 2,
|
|
102
|
+
scope: 'global',
|
|
103
|
+
defaultKeys: { mac: [], other: [] },
|
|
104
|
+
when: std => !!std.getOptional(InvisibleCharacters),
|
|
105
|
+
// A signal read, so a menu that reads it inside an effect ticks and
|
|
106
|
+
// unticks with the display, whoever flips it.
|
|
107
|
+
checked: std => std.getOptional(InvisibleCharacters)?.visible$.value ?? false,
|
|
108
|
+
run: std => {
|
|
109
|
+
const display = std.getOptional(InvisibleCharacters);
|
|
110
|
+
if (!display)
|
|
111
|
+
return;
|
|
112
|
+
// Toggled first: an optional call skips its arguments when there is no
|
|
113
|
+
// telemetry provider.
|
|
114
|
+
const visible = display.toggle();
|
|
115
|
+
std
|
|
116
|
+
.getOptional(TelemetryProvider)
|
|
117
|
+
?.track('InvisibleCharactersToggled', { visible });
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
export const invisibleCharactersCommands = [
|
|
121
|
+
toggleInvisibles,
|
|
122
|
+
removeInvisibles,
|
|
123
|
+
];
|
|
@@ -42,41 +42,9 @@ export const createElementsFromClipboardDataCommand = (ctx, next) => {
|
|
|
42
42
|
// born with its final index: written afterwards, each index moved an
|
|
43
43
|
// element already on the board, through the layer manager, one by one.
|
|
44
44
|
const newIndexes = pastedIndexes(std, elementsRawData, oldParents, context.originalIndexes);
|
|
45
|
-
const
|
|
46
|
-
// What each block's snapshot asked for, read before its config creates
|
|
47
|
-
// it; applied in the final transaction (`keepSourceLayerAndHide`).
|
|
48
|
-
const blockRequests = new Map();
|
|
49
|
-
// Canvas elements are written in as few transactions as the blocks allow,
|
|
50
|
-
// so a peer receives one update for a run of them instead of one per
|
|
51
|
-
// element (plus one per index fix-up). A block cannot join: its config's
|
|
52
|
-
// `createBlock` may be async (notes, texts, images and attachments go
|
|
53
|
-
// through the transformer, which awaits), and a Yjs transaction cannot
|
|
54
|
-
// span an `await`. So the run of canvas elements before a block is written
|
|
55
|
-
// first — the block may reference them (a frame's `childElementIds`) —
|
|
56
|
-
// and the last run is written together with the final indexes.
|
|
57
|
-
// ponytail: a block still costs its own transactions; a two-phase config
|
|
58
|
-
// contract (async prepare, then a sync write) is the upgrade path.
|
|
59
|
-
const pendingCanvasElements = [];
|
|
45
|
+
const items = [];
|
|
60
46
|
const seen = new Set();
|
|
61
|
-
|
|
62
|
-
for (const data of pendingCanvasElements) {
|
|
63
|
-
data.index = newIndexes.get(data.id) ?? data.index;
|
|
64
|
-
const element = createCanvasElement(std, data, context, getNewXYWH(data.xywh));
|
|
65
|
-
if (!element)
|
|
66
|
-
continue;
|
|
67
|
-
canvasElements.push(element);
|
|
68
|
-
allElements.push(element);
|
|
69
|
-
context.oldToNewIdMap.set(data.id, element.id);
|
|
70
|
-
}
|
|
71
|
-
pendingCanvasElements.length = 0;
|
|
72
|
-
};
|
|
73
|
-
// One gesture, one undo step: close whatever the previous gesture left
|
|
74
|
-
// open in the undo manager's capture window.
|
|
75
|
-
// ponytail: the paste's own transactions then merge only while each ends
|
|
76
|
-
// within that window (500 ms) of the one before, so a block whose creation
|
|
77
|
-
// takes longer splits the step; the two-phase contract above removes the
|
|
78
|
-
// ceiling (the budget spec measures it on 406 elements).
|
|
79
|
-
std.store.captureSync();
|
|
47
|
+
// Phase A: prepare, write nothing.
|
|
80
48
|
for (const data of elementsRawData) {
|
|
81
49
|
// Clipboard data written before `sortEdgelessElements` deduplicated can
|
|
82
50
|
// list one element twice; the first copy is the one its container maps.
|
|
@@ -86,12 +54,9 @@ export const createElementsFromClipboardDataCommand = (ctx, next) => {
|
|
|
86
54
|
const { data: blockSnapshot } = BlockSnapshotSchema.safeParse(data);
|
|
87
55
|
if (!blockSnapshot) {
|
|
88
56
|
assertType(data);
|
|
89
|
-
|
|
57
|
+
items.push({ element: data });
|
|
90
58
|
continue;
|
|
91
59
|
}
|
|
92
|
-
if (pendingCanvasElements.length > 0) {
|
|
93
|
-
std.store.transact(createPendingCanvasElements);
|
|
94
|
-
}
|
|
95
60
|
const oldId = blockSnapshot.id;
|
|
96
61
|
const config = std.getOptional(EdgelessClipboardConfigIdentifier(blockSnapshot.flavour));
|
|
97
62
|
if (!config)
|
|
@@ -111,24 +76,70 @@ export const createElementsFromClipboardDataCommand = (ctx, next) => {
|
|
|
111
76
|
layer: blockSnapshot.props.layer,
|
|
112
77
|
hiddenForEveryone: blockSnapshot.props.hiddenForEveryone,
|
|
113
78
|
};
|
|
114
|
-
const
|
|
115
|
-
if (!
|
|
116
|
-
continue;
|
|
117
|
-
const block = std.store.getBlock(newId);
|
|
118
|
-
if (!block)
|
|
79
|
+
const prepared = await config.prepare(blockSnapshot, context);
|
|
80
|
+
if (!prepared)
|
|
119
81
|
continue;
|
|
120
|
-
|
|
121
|
-
blockRequests.set(block.model, requested);
|
|
122
|
-
blockModels.push(block.model);
|
|
123
|
-
allElements.push(block.model);
|
|
124
|
-
context.oldToNewIdMap.set(oldId, newId);
|
|
125
|
-
const index = newIndexes.get(oldId);
|
|
126
|
-
if (index)
|
|
127
|
-
blockIndexes.set(block.model, index);
|
|
82
|
+
items.push({ oldId, prepared, requested });
|
|
128
83
|
}
|
|
84
|
+
// The preparation awaited: the document may have turned readonly since.
|
|
85
|
+
if (std.store.readonly)
|
|
86
|
+
return { canvasElements, blockModels };
|
|
87
|
+
const written = [];
|
|
88
|
+
const legacy = [];
|
|
89
|
+
// One gesture, one undo step: close whatever the previous gesture left
|
|
90
|
+
// open in the undo manager's capture window. Taken after the preparation,
|
|
91
|
+
// so its duration no longer matters.
|
|
92
|
+
std.store.captureSync();
|
|
129
93
|
std.store.transact(() => {
|
|
130
|
-
|
|
131
|
-
|
|
94
|
+
for (const item of items) {
|
|
95
|
+
if ('element' in item) {
|
|
96
|
+
const data = item.element;
|
|
97
|
+
data.index = newIndexes.get(data.id) ?? data.index;
|
|
98
|
+
const element = createCanvasElement(std, data, context, getNewXYWH(data.xywh));
|
|
99
|
+
if (!element)
|
|
100
|
+
continue;
|
|
101
|
+
canvasElements.push(element);
|
|
102
|
+
allElements.push(element);
|
|
103
|
+
context.oldToNewIdMap.set(data.id, element.id);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
let newId = null;
|
|
107
|
+
try {
|
|
108
|
+
newId = item.prepared.write();
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error(`Failed to paste block(id: ${item.oldId})`, error);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (newId instanceof Promise) {
|
|
115
|
+
legacy.push({ block: item, id: newId });
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (!newId)
|
|
119
|
+
continue;
|
|
120
|
+
context.oldToNewIdMap.set(item.oldId, newId);
|
|
121
|
+
written.push({ ...item, newId });
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
const parents = new Map();
|
|
125
|
+
const finish = (blocks) => {
|
|
126
|
+
blocks.forEach(({ prepared }) => prepared.afterWrite?.());
|
|
127
|
+
const crud = std.get(EdgelessCRUDIdentifier);
|
|
128
|
+
for (const { oldId, newId, requested } of blocks) {
|
|
129
|
+
const block = std.store.getBlock(newId);
|
|
130
|
+
if (!block)
|
|
131
|
+
continue;
|
|
132
|
+
assertType(block.model);
|
|
133
|
+
blockModels.push(block.model);
|
|
134
|
+
allElements.push(block.model);
|
|
135
|
+
// A block config chooses its own index (a frame takes the top of the
|
|
136
|
+
// board, a note the transformer's): set the planned one afterwards.
|
|
137
|
+
const index = newIndexes.get(oldId);
|
|
138
|
+
if (index && block.model.index !== index) {
|
|
139
|
+
crud.updateElement(block.model.id, { index });
|
|
140
|
+
}
|
|
141
|
+
keepSourceLayerAndHide(std, block.model, requested);
|
|
142
|
+
}
|
|
132
143
|
oldParents.forEach((oldParent, oldChild) => {
|
|
133
144
|
const child = context.oldToNewIdMap.get(oldChild);
|
|
134
145
|
const parent = context.oldToNewIdMap.get(oldParent);
|
|
@@ -136,15 +147,21 @@ export const createElementsFromClipboardDataCommand = (ctx, next) => {
|
|
|
136
147
|
parents.set(child, parent);
|
|
137
148
|
});
|
|
138
149
|
releaseChildrenFromAdoptingFrames(std, allElements, parents);
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
150
|
+
};
|
|
151
|
+
std.store.transact(() => finish(written));
|
|
152
|
+
if (legacy.length > 0) {
|
|
153
|
+
console.warn('EdgelessClipboardConfig: an async createBlock wrote after the paste; implement prepare() to keep the paste one undo step (ADR 0042).');
|
|
154
|
+
const late = [];
|
|
155
|
+
for (const { block, id } of legacy) {
|
|
156
|
+
const newId = await id;
|
|
157
|
+
if (!newId)
|
|
158
|
+
continue;
|
|
159
|
+
context.oldToNewIdMap.set(block.oldId, newId);
|
|
160
|
+
late.push({ ...block, newId });
|
|
161
|
+
}
|
|
162
|
+
if (!std.store.readonly)
|
|
163
|
+
std.store.transact(() => finish(late));
|
|
164
|
+
}
|
|
148
165
|
return {
|
|
149
166
|
canvasElements: canvasElements,
|
|
150
167
|
blockModels: blockModels,
|
|
@@ -159,16 +176,16 @@ export const createElementsFromClipboardDataCommand = (ctx, next) => {
|
|
|
159
176
|
* `crud.addElement`, which forwards every serialized prop (ADR 0031 §6 and
|
|
160
177
|
* "What stays loadable"): its `layer` when it names a layer of this surface,
|
|
161
178
|
* else the active one, and its `hiddenForEveryone`. Most
|
|
162
|
-
* `EdgelessClipboardConfig.
|
|
179
|
+
* `EdgelessClipboardConfig.prepare` rebuild the block from a handful of
|
|
163
180
|
* the snapshot's props (frame, image, attachment, bookmark, the embeds…), so
|
|
164
181
|
* a duplicate fell in the active layer and came back visible. The rule is
|
|
165
182
|
* applied once here, for every config, rather than in each of them; nothing
|
|
166
183
|
* is written when the config already carried both.
|
|
167
184
|
*
|
|
168
|
-
* `requested` is read BEFORE `
|
|
185
|
+
* `requested` is read BEFORE `prepare`: the snapshot-pasting configs
|
|
169
186
|
* stamp `snapshot.props` in place, and an explicit default-layer request from
|
|
170
187
|
* a clone gesture (`prepareCloneData`) is gone from it afterwards. Called
|
|
171
|
-
* inside the paste's
|
|
188
|
+
* inside the paste's second transaction, beside the index fix-ups, so it adds
|
|
172
189
|
* no update of its own.
|
|
173
190
|
*/
|
|
174
191
|
function keepSourceLayerAndHide(std, model, requested) {
|
|
@@ -261,6 +261,8 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager {
|
|
|
261
261
|
},
|
|
262
262
|
'Alt-2': ctx => {
|
|
263
263
|
ctx.get('defaultState').event.preventDefault();
|
|
264
|
+
if (this.rootComponent.service.locked)
|
|
265
|
+
return;
|
|
264
266
|
const selectedElements = this.gfx.selection.selectedElements;
|
|
265
267
|
if (selectedElements.length === 0) {
|
|
266
268
|
return;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './adapters/index.js';
|
|
2
2
|
export * from './clipboard/index.js';
|
|
3
3
|
export * from './commands/copy-link-commands.js';
|
|
4
|
+
export * from './commands/invisible-characters-commands.js';
|
|
4
5
|
export * from './commands/page-export-commands.js';
|
|
5
6
|
export * from './commands/pivot-commands.js';
|
|
6
7
|
export * from './commands/reading-commands.js';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './adapters/index.js';
|
|
2
2
|
export * from './clipboard/index.js';
|
|
3
3
|
export * from './commands/copy-link-commands.js';
|
|
4
|
+
export * from './commands/invisible-characters-commands.js';
|
|
4
5
|
export * from './commands/page-export-commands.js';
|
|
5
6
|
export * from './commands/pivot-commands.js';
|
|
6
7
|
export * from './commands/reading-commands.js';
|
|
@@ -43,6 +43,12 @@ export declare const ROOT_TOOLBAR_TURN_INTO_LINKED_DOC: ChromeWording;
|
|
|
43
43
|
export declare const ROOT_TOOLBAR_EDIT_LINK: ChromeWording;
|
|
44
44
|
export declare const ROOT_TOOLBAR_REMOVE_LINK: ChromeWording;
|
|
45
45
|
export declare const ROOT_TOAST_ZOOM_TO_SELECTION: ChromeWording;
|
|
46
|
+
/**
|
|
47
|
+
* The toast `text.invisibles.remove` shows through the notification seam.
|
|
48
|
+
* `{{count}}` is filled by the host's catalogue, which pluralises on it; the
|
|
49
|
+
* English fallback stays neutral.
|
|
50
|
+
*/
|
|
51
|
+
export declare const ROOT_TOAST_INVISIBLES_REMOVED: ChromeWording;
|
|
46
52
|
/**
|
|
47
53
|
* The Tab/Enter mindmap shortcuts' seed for a freshly added node — the same
|
|
48
54
|
* word `MindmapElementModel.addNode`'s own default falls back to (that
|
|
@@ -117,6 +117,15 @@ export const ROOT_TOAST_ZOOM_TO_SELECTION = [
|
|
|
117
117
|
'com.labre.root.toast.zoom-to-selection',
|
|
118
118
|
'Zoom to selection',
|
|
119
119
|
];
|
|
120
|
+
/**
|
|
121
|
+
* The toast `text.invisibles.remove` shows through the notification seam.
|
|
122
|
+
* `{{count}}` is filled by the host's catalogue, which pluralises on it; the
|
|
123
|
+
* English fallback stays neutral.
|
|
124
|
+
*/
|
|
125
|
+
export const ROOT_TOAST_INVISIBLES_REMOVED = [
|
|
126
|
+
'com.labre.command.text.invisibles.removed',
|
|
127
|
+
'{{count}} invisible characters removed',
|
|
128
|
+
];
|
|
120
129
|
/**
|
|
121
130
|
* The Tab/Enter mindmap shortcuts' seed for a freshly added node — the same
|
|
122
131
|
* word `MindmapElementModel.addNode`'s own default falls back to (that
|
|
@@ -162,6 +171,7 @@ export const ROOT_CHROME_WORDINGS = [
|
|
|
162
171
|
ROOT_TOOLBAR_TURN_INTO_LINKED_DOC,
|
|
163
172
|
ROOT_TOOLBAR_EDIT_LINK,
|
|
164
173
|
ROOT_TOAST_ZOOM_TO_SELECTION,
|
|
174
|
+
ROOT_TOAST_INVISIBLES_REMOVED,
|
|
165
175
|
];
|
|
166
176
|
/** This package's own seed, joined into `PACKAGE_SEED_WORDINGS`. */
|
|
167
177
|
export const ROOT_SEED_WORDINGS = [
|