@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
|
@@ -4,21 +4,95 @@ import { isPureObject, native2Y } from '../../reactive/index.js';
|
|
|
4
4
|
import { internalPrimitives } from '../block/zod.js';
|
|
5
5
|
export class DocCRUD {
|
|
6
6
|
get root() {
|
|
7
|
-
|
|
8
|
-
this._yBlocks.forEach(yBlock => {
|
|
9
|
-
const flavour = yBlock.get('sys:flavour');
|
|
10
|
-
const schema = this._schema.flavourSchemaMap.get(flavour);
|
|
11
|
-
if (!schema)
|
|
12
|
-
return;
|
|
13
|
-
if (schema.model.role === 'root') {
|
|
14
|
-
rootId = yBlock.get('sys:id');
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
return rootId;
|
|
7
|
+
return this._ensureIndex().root;
|
|
18
8
|
}
|
|
19
9
|
constructor(_yBlocks, _schema) {
|
|
20
10
|
this._yBlocks = _yBlocks;
|
|
21
11
|
this._schema = _schema;
|
|
12
|
+
/**
|
|
13
|
+
* In-memory index of the tree: `childId -> parentId` plus the root id,
|
|
14
|
+
* rebuilt lazily after any structural change. Nothing here is written to Yjs
|
|
15
|
+
* (ADR 0041).
|
|
16
|
+
*
|
|
17
|
+
* Why: `root` scanned every block and `getParent` walked the tree from the
|
|
18
|
+
* root, so a load path calling `getParent` once per block was quadratic
|
|
19
|
+
* (#507: 11 s for 4000 blocks under a query with `viewType: 'hidden'`, whose
|
|
20
|
+
* `setAncestorsToDisplayIfHidden` climbs the ancestors of every block). #508
|
|
21
|
+
* only skipped that walk for queries that cannot hide blocks; the index
|
|
22
|
+
* makes the walk itself linear.
|
|
23
|
+
*
|
|
24
|
+
* Invalidation contract:
|
|
25
|
+
* - every transaction, local, remote (`Y.applyUpdate`) or undo, reaches
|
|
26
|
+
* `beforeObserverCalls` before any observer runs, so observers and
|
|
27
|
+
* everything after them read a fresh index;
|
|
28
|
+
* - inside a transaction, before that event, only the mutators below write
|
|
29
|
+
* the tree (`sys:children`, the blocks map): each drops the index before
|
|
30
|
+
* its first write, so a throw half-way leaves no stale index, and again
|
|
31
|
+
* after its last one, so a read in between cannot cache a half-written
|
|
32
|
+
* tree. A new writer of `sys:children` must do the same.
|
|
33
|
+
*/
|
|
34
|
+
this._index = null;
|
|
35
|
+
/** Once deaf to remote changes, every read rebuilds (the pre-#507 cost). */
|
|
36
|
+
this._live = false;
|
|
37
|
+
this._onBeforeObserverCalls = (transaction) => {
|
|
38
|
+
if (!this._index)
|
|
39
|
+
return;
|
|
40
|
+
// `changed` only lists types that existed before the transaction: a block
|
|
41
|
+
// created in it shows up through the blocks map, a children array created
|
|
42
|
+
// in it through its block's `sys:children` key.
|
|
43
|
+
for (const [type, keys] of transaction.changed) {
|
|
44
|
+
if (type === this._yBlocks ||
|
|
45
|
+
type._item?.parentSub === 'sys:children' ||
|
|
46
|
+
keys.has('sys:children') ||
|
|
47
|
+
keys.has('sys:flavour') ||
|
|
48
|
+
keys.has('sys:id')) {
|
|
49
|
+
this._index = null;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
if (!_yBlocks.doc)
|
|
55
|
+
return;
|
|
56
|
+
_yBlocks.doc.on('beforeObserverCalls', this._onBeforeObserverCalls);
|
|
57
|
+
this._live = true;
|
|
58
|
+
}
|
|
59
|
+
dispose() {
|
|
60
|
+
this._yBlocks.doc?.off('beforeObserverCalls', this._onBeforeObserverCalls);
|
|
61
|
+
this._live = false;
|
|
62
|
+
this._index = null;
|
|
63
|
+
}
|
|
64
|
+
// Same answers as the former scan + DFS: the last root in map order, and the
|
|
65
|
+
// first parent met in a pre-order walk from it. Orphans have none, nor does
|
|
66
|
+
// the root even when some block lists it as a child. A block listed twice
|
|
67
|
+
// keeps its first parent and its subtree is walked once, which also ends a
|
|
68
|
+
// cycle where the former DFS overflowed the stack.
|
|
69
|
+
_ensureIndex() {
|
|
70
|
+
if (this._index)
|
|
71
|
+
return this._index;
|
|
72
|
+
let root = null;
|
|
73
|
+
this._yBlocks.forEach(yBlock => {
|
|
74
|
+
const schema = this._schema.flavourSchemaMap.get(yBlock.get('sys:flavour'));
|
|
75
|
+
if (schema?.model.role === 'root')
|
|
76
|
+
root = yBlock.get('sys:id');
|
|
77
|
+
});
|
|
78
|
+
const parentOf = new Map();
|
|
79
|
+
const walk = (parentId) => {
|
|
80
|
+
const children = this._yBlocks.get(parentId)?.get('sys:children');
|
|
81
|
+
if (!children)
|
|
82
|
+
return;
|
|
83
|
+
for (const childId of children.toArray()) {
|
|
84
|
+
if (childId === root || parentOf.has(childId))
|
|
85
|
+
continue;
|
|
86
|
+
parentOf.set(childId, parentId);
|
|
87
|
+
walk(childId);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
if (root)
|
|
91
|
+
walk(root);
|
|
92
|
+
const index = { root, parentOf };
|
|
93
|
+
if (this._live)
|
|
94
|
+
this._index = index;
|
|
95
|
+
return index;
|
|
22
96
|
}
|
|
23
97
|
_getSiblings(id, fn) {
|
|
24
98
|
const parentId = this.getParent(id);
|
|
@@ -46,6 +120,10 @@ export class DocCRUD {
|
|
|
46
120
|
? this._yBlocks.get(parent)?.get('sys:flavour')
|
|
47
121
|
: undefined;
|
|
48
122
|
this._schema.validate(flavour, parentFlavour);
|
|
123
|
+
// Read the index before the first write; a root-role block never has a
|
|
124
|
+
// default parent, so the new block cannot change the answer.
|
|
125
|
+
const parentId = parent ?? (schema.model.role === 'root' ? null : this.root);
|
|
126
|
+
this._index = null;
|
|
49
127
|
const yBlock = new Y.Map();
|
|
50
128
|
this._yBlocks.set(id, yBlock);
|
|
51
129
|
const version = schema.version;
|
|
@@ -84,7 +162,6 @@ export class DocCRUD {
|
|
|
84
162
|
yBlock.set(`prop:${key}`, native2Y(value));
|
|
85
163
|
});
|
|
86
164
|
}
|
|
87
|
-
const parentId = parent ?? (schema.model.role === 'root' ? null : this.root);
|
|
88
165
|
if (!parentId)
|
|
89
166
|
return;
|
|
90
167
|
const yParent = this._yBlocks.get(parentId);
|
|
@@ -97,6 +174,7 @@ export class DocCRUD {
|
|
|
97
174
|
: parentIndex
|
|
98
175
|
: yParentChildren.length;
|
|
99
176
|
yParentChildren.insert(index, [id]);
|
|
177
|
+
this._index = null;
|
|
100
178
|
}
|
|
101
179
|
deleteBlock(id, options = {
|
|
102
180
|
deleteChildren: true,
|
|
@@ -116,6 +194,7 @@ export class DocCRUD {
|
|
|
116
194
|
const yParent = this._yBlocks.get(parent);
|
|
117
195
|
const yParentChildren = yParent.get('sys:children');
|
|
118
196
|
const modelIndex = yParentChildren.toArray().indexOf(id);
|
|
197
|
+
this._index = null;
|
|
119
198
|
if (modelIndex > -1) {
|
|
120
199
|
yParentChildren.delete(modelIndex, 1);
|
|
121
200
|
}
|
|
@@ -162,6 +241,7 @@ export class DocCRUD {
|
|
|
162
241
|
};
|
|
163
242
|
apply();
|
|
164
243
|
this._yBlocks.delete(id);
|
|
244
|
+
this._index = null;
|
|
165
245
|
}
|
|
166
246
|
getNext(id) {
|
|
167
247
|
return this._getSiblings(id, (index, parent) => parent
|
|
@@ -170,24 +250,7 @@ export class DocCRUD {
|
|
|
170
250
|
.at(index + 1) ?? null);
|
|
171
251
|
}
|
|
172
252
|
getParent(targetId) {
|
|
173
|
-
|
|
174
|
-
if (!root || root === targetId)
|
|
175
|
-
return null;
|
|
176
|
-
const findParent = (parentId) => {
|
|
177
|
-
const parentYBlock = this._yBlocks.get(parentId);
|
|
178
|
-
if (!parentYBlock)
|
|
179
|
-
return null;
|
|
180
|
-
const children = parentYBlock.get('sys:children');
|
|
181
|
-
for (const childId of children.toArray()) {
|
|
182
|
-
if (childId === targetId)
|
|
183
|
-
return parentId;
|
|
184
|
-
const parent = findParent(childId);
|
|
185
|
-
if (parent != null)
|
|
186
|
-
return parent;
|
|
187
|
-
}
|
|
188
|
-
return null;
|
|
189
|
-
};
|
|
190
|
-
return findParent(root);
|
|
253
|
+
return this._ensureIndex().parentOf.get(targetId) ?? null;
|
|
191
254
|
}
|
|
192
255
|
getPrev(id) {
|
|
193
256
|
return this._getSiblings(id, (index, parent) => {
|
|
@@ -241,6 +304,7 @@ export class DocCRUD {
|
|
|
241
304
|
children.push(blockId);
|
|
242
305
|
});
|
|
243
306
|
let insertIndex = 0;
|
|
307
|
+
this._index = null;
|
|
244
308
|
Array.from(childBlocksPerParent.entries()).forEach(([parentBlock, blocksToMove], index) => {
|
|
245
309
|
const targetParentBlock = this._yBlocks.get(newParent);
|
|
246
310
|
if (!targetParentBlock)
|
|
@@ -280,13 +344,16 @@ export class DocCRUD {
|
|
|
280
344
|
updateInsertIndex();
|
|
281
345
|
targetParentChildren.insert(insertIndex, blocksToMove);
|
|
282
346
|
});
|
|
347
|
+
this._index = null;
|
|
283
348
|
}
|
|
284
349
|
updateBlockChildren(id, children) {
|
|
285
350
|
const yBlock = this._yBlocks.get(id);
|
|
286
351
|
if (!yBlock)
|
|
287
352
|
return;
|
|
288
353
|
const yChildrenArray = yBlock.get('sys:children');
|
|
354
|
+
this._index = null;
|
|
289
355
|
yChildrenArray.delete(0, yChildrenArray.length);
|
|
290
356
|
yChildrenArray.push(children);
|
|
357
|
+
this._index = null;
|
|
291
358
|
}
|
|
292
359
|
}
|
|
@@ -10,9 +10,10 @@ export function runQuery(query, block) {
|
|
|
10
10
|
/**
|
|
11
11
|
* A loose query hides a block only through a `viewType: 'hidden'` entry, so
|
|
12
12
|
* without one no ancestor can be hidden and the walk below is a no-op. The
|
|
13
|
-
* walk
|
|
13
|
+
* walk cost one O(n) `getParent` per ancestor, which made opening a store
|
|
14
14
|
* with the default query quadratic in the block count (#507, guard
|
|
15
|
-
* `__tests__/query.unit.spec.ts`)
|
|
15
|
+
* `__tests__/query.unit.spec.ts`); `getParent` is now an index lookup
|
|
16
|
+
* (ADR 0041), and skipping the no-op walk still saves the calls.
|
|
16
17
|
*/
|
|
17
18
|
function canHideBlocks(query) {
|
|
18
19
|
if (query.mode !== 'loose')
|
|
@@ -172,6 +172,27 @@ export declare class Store {
|
|
|
172
172
|
private readonly _runQuery;
|
|
173
173
|
private readonly _doc;
|
|
174
174
|
private readonly _blocks;
|
|
175
|
+
/**
|
|
176
|
+
* The blocks record while a batch runs, `null` otherwise (#507, ADR 0041).
|
|
177
|
+
*
|
|
178
|
+
* Adding a block used to copy the whole record into a new one, once per
|
|
179
|
+
* block: quadratic when a store opens on n blocks, and far slower with real
|
|
180
|
+
* string ids than with integer-like ones, which V8 copies on a fast path
|
|
181
|
+
* (2000 string ids: 2.6 s under any query). A batch copies the record once,
|
|
182
|
+
* adds and removes blocks in this draft, and assigns `_blocks` once at the
|
|
183
|
+
* end, so its subscribers are notified once.
|
|
184
|
+
*
|
|
185
|
+
* The store's own reads (`getBlock`, `hasBlock`, `getParent`,
|
|
186
|
+
* `blockSize`…) go through `_peekBlocks()` and see each block as soon as
|
|
187
|
+
* its `add` is handled, as before; `blockUpdated` still fires per block.
|
|
188
|
+
* Only a direct read of `store.blocks` sees the batch at its end. Batches:
|
|
189
|
+
* the init loop of the constructor, and a transaction that adds or removes
|
|
190
|
+
* more than one block; a single block keeps the per-block assignment.
|
|
191
|
+
*/
|
|
192
|
+
private _blocksDraft;
|
|
193
|
+
private _blocksDraftChanged;
|
|
194
|
+
private _peekBlocks;
|
|
195
|
+
private _batchBlocks;
|
|
175
196
|
private readonly _crud;
|
|
176
197
|
private readonly _query;
|
|
177
198
|
private readonly _readonly;
|
|
@@ -24,6 +24,28 @@ const internalExtensions = [StoreSelectionExtension, HistoryExtension];
|
|
|
24
24
|
* @category Store
|
|
25
25
|
*/
|
|
26
26
|
export class Store {
|
|
27
|
+
_peekBlocks() {
|
|
28
|
+
return this._blocksDraft ?? this._blocks.peek();
|
|
29
|
+
}
|
|
30
|
+
_batchBlocks(fn) {
|
|
31
|
+
// A batch opened inside another one is part of it: the outer one assigns.
|
|
32
|
+
if (this._blocksDraft) {
|
|
33
|
+
fn();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const draft = { ...this._blocks.peek() };
|
|
37
|
+
this._blocksDraft = draft;
|
|
38
|
+
this._blocksDraftChanged = false;
|
|
39
|
+
try {
|
|
40
|
+
fn();
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
this._blocksDraft = null;
|
|
44
|
+
// An unchanged batch notifies nobody, like the per-block path.
|
|
45
|
+
if (this._blocksDraftChanged)
|
|
46
|
+
this._blocks.value = draft;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
27
49
|
/**
|
|
28
50
|
* Get the id of the store.
|
|
29
51
|
*
|
|
@@ -73,7 +95,7 @@ export class Store {
|
|
|
73
95
|
* @category Block CRUD
|
|
74
96
|
*/
|
|
75
97
|
get blockSize() {
|
|
76
|
-
return Object.values(this.
|
|
98
|
+
return Object.values(this._peekBlocks()).length;
|
|
77
99
|
}
|
|
78
100
|
/**
|
|
79
101
|
* Check if the store can redo
|
|
@@ -271,6 +293,25 @@ export class Store {
|
|
|
271
293
|
runQuery(this._query, block);
|
|
272
294
|
};
|
|
273
295
|
this._blocks = signal({});
|
|
296
|
+
/**
|
|
297
|
+
* The blocks record while a batch runs, `null` otherwise (#507, ADR 0041).
|
|
298
|
+
*
|
|
299
|
+
* Adding a block used to copy the whole record into a new one, once per
|
|
300
|
+
* block: quadratic when a store opens on n blocks, and far slower with real
|
|
301
|
+
* string ids than with integer-like ones, which V8 copies on a fast path
|
|
302
|
+
* (2000 string ids: 2.6 s under any query). A batch copies the record once,
|
|
303
|
+
* adds and removes blocks in this draft, and assigns `_blocks` once at the
|
|
304
|
+
* end, so its subscribers are notified once.
|
|
305
|
+
*
|
|
306
|
+
* The store's own reads (`getBlock`, `hasBlock`, `getParent`,
|
|
307
|
+
* `blockSize`…) go through `_peekBlocks()` and see each block as soon as
|
|
308
|
+
* its `add` is handled, as before; `blockUpdated` still fires per block.
|
|
309
|
+
* Only a direct read of `store.blocks` sees the batch at its end. Batches:
|
|
310
|
+
* the init loop of the constructor, and a transaction that adds or removes
|
|
311
|
+
* more than one block; a single block keeps the per-block assignment.
|
|
312
|
+
*/
|
|
313
|
+
this._blocksDraft = null;
|
|
314
|
+
this._blocksDraftChanged = false;
|
|
274
315
|
this._query = {
|
|
275
316
|
match: [],
|
|
276
317
|
mode: 'loose',
|
|
@@ -350,7 +391,16 @@ export class Store {
|
|
|
350
391
|
this.disposableGroup.add(this.slots.rootDeleted);
|
|
351
392
|
};
|
|
352
393
|
this._handleYEvents = (events) => {
|
|
353
|
-
events.forEach(event => this._handleYEvent(event));
|
|
394
|
+
const handle = () => events.forEach(event => this._handleYEvent(event));
|
|
395
|
+
// One transaction that adds or removes several blocks (a remote load, a
|
|
396
|
+
// paste, a subtree deletion) assigns the blocks record once (#507); a
|
|
397
|
+
// single block keeps the per-block path unchanged.
|
|
398
|
+
const keys = events.reduce((count, event) => event.target === this._yBlocks ? count + event.keys.size : count, 0);
|
|
399
|
+
if (keys > 1) {
|
|
400
|
+
this._batchBlocks(handle);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
handle();
|
|
354
404
|
};
|
|
355
405
|
this.slots = {
|
|
356
406
|
ready: new Subject(),
|
|
@@ -383,12 +433,14 @@ export class Store {
|
|
|
383
433
|
this._query = query;
|
|
384
434
|
}
|
|
385
435
|
this._yBlocks.observeDeep(this._handleYEvents);
|
|
386
|
-
this.
|
|
387
|
-
this.
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
436
|
+
this._batchBlocks(() => {
|
|
437
|
+
this._yBlocks.forEach((_, id) => {
|
|
438
|
+
this._handleYBlockAdd(id, false);
|
|
439
|
+
if (id in this._peekBlocks()) {
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
this._onBlockAdded(id, false, true);
|
|
443
|
+
});
|
|
392
444
|
});
|
|
393
445
|
this._subscribeToSlots();
|
|
394
446
|
}
|
|
@@ -406,7 +458,7 @@ export class Store {
|
|
|
406
458
|
}
|
|
407
459
|
_onBlockAdded(id, isLocal, init) {
|
|
408
460
|
try {
|
|
409
|
-
if (id in this.
|
|
461
|
+
if (id in this._peekBlocks()) {
|
|
410
462
|
return;
|
|
411
463
|
}
|
|
412
464
|
const yBlock = this._yBlocks.get(id);
|
|
@@ -430,10 +482,16 @@ export class Store {
|
|
|
430
482
|
};
|
|
431
483
|
const block = new Block(this._schema, yBlock, this, options);
|
|
432
484
|
this._runQuery(block);
|
|
433
|
-
this.
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
}
|
|
485
|
+
if (this._blocksDraft) {
|
|
486
|
+
this._blocksDraft[id] = block;
|
|
487
|
+
this._blocksDraftChanged = true;
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
this._blocks.value = {
|
|
491
|
+
...this._blocks.value,
|
|
492
|
+
[id]: block,
|
|
493
|
+
};
|
|
494
|
+
}
|
|
437
495
|
block.model.created.next();
|
|
438
496
|
if (block.model.role === 'root') {
|
|
439
497
|
this.slots.rootAdded.next(id);
|
|
@@ -468,8 +526,14 @@ export class Store {
|
|
|
468
526
|
model: block.model,
|
|
469
527
|
isLocal,
|
|
470
528
|
});
|
|
471
|
-
|
|
472
|
-
|
|
529
|
+
if (this._blocksDraft) {
|
|
530
|
+
delete this._blocksDraft[id];
|
|
531
|
+
this._blocksDraftChanged = true;
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
const { [id]: _, ...blocks } = this._blocks.peek();
|
|
535
|
+
this._blocks.value = blocks;
|
|
536
|
+
}
|
|
473
537
|
block.model.deleted.next();
|
|
474
538
|
block.model.dispose();
|
|
475
539
|
}
|
|
@@ -633,7 +697,7 @@ export class Store {
|
|
|
633
697
|
* @category Block CRUD
|
|
634
698
|
*/
|
|
635
699
|
getBlock(id) {
|
|
636
|
-
return this.
|
|
700
|
+
return this._peekBlocks()[id];
|
|
637
701
|
}
|
|
638
702
|
/**
|
|
639
703
|
* Gets a block by its ID
|
|
@@ -643,7 +707,9 @@ export class Store {
|
|
|
643
707
|
* @category Block CRUD
|
|
644
708
|
*/
|
|
645
709
|
getBlock$(id) {
|
|
646
|
-
|
|
710
|
+
// Subscribes to the record, answers from the draft during a batch.
|
|
711
|
+
const blocks = this._blocks.value;
|
|
712
|
+
return (this._blocksDraft ?? blocks)[id];
|
|
647
713
|
}
|
|
648
714
|
/**
|
|
649
715
|
* Get a model by its ID
|
|
@@ -664,7 +730,7 @@ export class Store {
|
|
|
664
730
|
*/
|
|
665
731
|
getBlocksByFlavour(blockFlavour) {
|
|
666
732
|
const flavours = typeof blockFlavour === 'string' ? [blockFlavour] : blockFlavour;
|
|
667
|
-
return Object.values(this.
|
|
733
|
+
return Object.values(this._peekBlocks()).filter(({ flavour }) => flavours.includes(flavour));
|
|
668
734
|
}
|
|
669
735
|
/**
|
|
670
736
|
* Get all models in the store
|
|
@@ -673,7 +739,7 @@ export class Store {
|
|
|
673
739
|
* @category Block CRUD
|
|
674
740
|
*/
|
|
675
741
|
getAllModels() {
|
|
676
|
-
return Object.values(this.
|
|
742
|
+
return Object.values(this._peekBlocks()).map(block => block.model);
|
|
677
743
|
}
|
|
678
744
|
/**
|
|
679
745
|
* Get all models of specified flavour(s)
|
|
@@ -697,7 +763,7 @@ export class Store {
|
|
|
697
763
|
const parentId = this._crud.getParent(targetId);
|
|
698
764
|
if (!parentId)
|
|
699
765
|
return null;
|
|
700
|
-
const parent = this.
|
|
766
|
+
const parent = this._peekBlocks()[parentId];
|
|
701
767
|
if (!parent)
|
|
702
768
|
return null;
|
|
703
769
|
return parent.model;
|
|
@@ -750,7 +816,7 @@ export class Store {
|
|
|
750
816
|
* @category Block CRUD
|
|
751
817
|
*/
|
|
752
818
|
hasBlock(id) {
|
|
753
|
-
return id in this.
|
|
819
|
+
return id in this._peekBlocks();
|
|
754
820
|
}
|
|
755
821
|
/**
|
|
756
822
|
* Move blocks to a new parent block
|
|
@@ -858,6 +924,7 @@ export class Store {
|
|
|
858
924
|
this.slots.blockUpdated.complete();
|
|
859
925
|
this.slots.yBlockUpdated.complete();
|
|
860
926
|
this.disposableGroup.dispose();
|
|
927
|
+
this._crud.dispose();
|
|
861
928
|
this._isDisposed = true;
|
|
862
929
|
}
|
|
863
930
|
_handleYBlockAdd(id, isLocal) {
|
|
@@ -10,6 +10,32 @@ export type TransformerOptions = {
|
|
|
10
10
|
docCRUD: DocCRUD;
|
|
11
11
|
middlewares?: TransformerMiddleware[];
|
|
12
12
|
};
|
|
13
|
+
interface DraftBlockTreeNode {
|
|
14
|
+
draft: DraftModel;
|
|
15
|
+
snapshot: BlockSnapshot;
|
|
16
|
+
children: Array<DraftBlockTreeNode>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A block snapshot converted to draft models and not written yet: what
|
|
20
|
+
* {@link Transformer.prepareSnapshotToBlock} returns and
|
|
21
|
+
* {@link Transformer.insertPrepared} writes. `id` is the id the root block
|
|
22
|
+
* will have, after the `beforeImport` middlewares (a replaced one).
|
|
23
|
+
*/
|
|
24
|
+
export interface PreparedBlockSnapshot {
|
|
25
|
+
readonly id: string;
|
|
26
|
+
readonly tree: DraftBlockTreeNode;
|
|
27
|
+
readonly parent?: string;
|
|
28
|
+
readonly index?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* What {@link Transformer.insertPrepared} wrote. A block model only exists
|
|
32
|
+
* once the transaction that wrote it has ended, so the `afterImport` events
|
|
33
|
+
* wait for `flushAfterImport`, which returns the root model.
|
|
34
|
+
*/
|
|
35
|
+
export interface InsertedBlockSnapshot {
|
|
36
|
+
readonly id: string;
|
|
37
|
+
flushAfterImport(): BlockModel | null;
|
|
38
|
+
}
|
|
13
39
|
export declare class Transformer {
|
|
14
40
|
private readonly _adapterConfigs;
|
|
15
41
|
private readonly _transformerConfigs;
|
|
@@ -22,6 +48,24 @@ export declare class Transformer {
|
|
|
22
48
|
docToSnapshot: (doc: Store) => DocSnapshot | undefined;
|
|
23
49
|
sliceToSnapshot: (slice: Slice) => SliceSnapshot | undefined;
|
|
24
50
|
snapshotToBlock: (snapshot: BlockSnapshot, doc: Store, parent?: string, index?: number) => Promise<BlockModel | undefined>;
|
|
51
|
+
/**
|
|
52
|
+
* The first half of {@link snapshotToBlock}: fires `beforeImport` and
|
|
53
|
+
* converts every node (the block transformers await their blobs here), and
|
|
54
|
+
* writes nothing. Pair it with {@link insertPrepared} on the SAME
|
|
55
|
+
* transformer: a middleware keeps its state per transformer
|
|
56
|
+
* (`replaceIdMiddleware`'s id map). Split so that a gesture can await every
|
|
57
|
+
* preparation first, then write them all in one synchronous transaction —
|
|
58
|
+
* one undo step whatever the preparation took (ADR 0042).
|
|
59
|
+
*/
|
|
60
|
+
prepareSnapshotToBlock: (snapshot: BlockSnapshot, parent?: string, index?: number) => Promise<PreparedBlockSnapshot | undefined>;
|
|
61
|
+
/**
|
|
62
|
+
* The second half of {@link snapshotToBlock}: adds the prepared blocks to
|
|
63
|
+
* `doc` synchronously, without the yield every `BATCH_SIZE` blocks, so the
|
|
64
|
+
* caller may run it inside its own `store.transact`. The `afterImport`
|
|
65
|
+
* events (middlewares write props from them) wait for `flushAfterImport()`,
|
|
66
|
+
* to call once that transaction has ended and the models exist.
|
|
67
|
+
*/
|
|
68
|
+
insertPrepared: (prepared: PreparedBlockSnapshot, doc: Store) => InsertedBlockSnapshot | undefined;
|
|
25
69
|
snapshotToDoc: (snapshot: DocSnapshot) => Promise<Store | undefined>;
|
|
26
70
|
snapshotToModelData: (snapshot: BlockSnapshot) => Promise<import("./base.js").SnapshotNode<object> | undefined>;
|
|
27
71
|
snapshotToSlice: (snapshot: SliceSnapshot, doc: Store, parent?: string, index?: number) => Promise<Slice | undefined>;
|
|
@@ -40,9 +84,11 @@ export declare class Transformer {
|
|
|
40
84
|
private _getSchema;
|
|
41
85
|
private _getTransformer;
|
|
42
86
|
private _insertBlockTree;
|
|
87
|
+
private _insertBlockTreeSync;
|
|
43
88
|
private _rebuildBlockTree;
|
|
44
89
|
private _snapshotToBlock;
|
|
45
90
|
private _triggerBeforeImportEvent;
|
|
46
91
|
reset(): void;
|
|
47
92
|
[Symbol.dispose](): void;
|
|
48
93
|
}
|
|
94
|
+
export {};
|
|
@@ -134,6 +134,65 @@ export class Transformer {
|
|
|
134
134
|
return;
|
|
135
135
|
}
|
|
136
136
|
};
|
|
137
|
+
/**
|
|
138
|
+
* The first half of {@link snapshotToBlock}: fires `beforeImport` and
|
|
139
|
+
* converts every node (the block transformers await their blobs here), and
|
|
140
|
+
* writes nothing. Pair it with {@link insertPrepared} on the SAME
|
|
141
|
+
* transformer: a middleware keeps its state per transformer
|
|
142
|
+
* (`replaceIdMiddleware`'s id map). Split so that a gesture can await every
|
|
143
|
+
* preparation first, then write them all in one synchronous transaction —
|
|
144
|
+
* one undo step whatever the preparation took (ADR 0042).
|
|
145
|
+
*/
|
|
146
|
+
this.prepareSnapshotToBlock = async (snapshot, parent, index) => {
|
|
147
|
+
try {
|
|
148
|
+
BlockSnapshotSchema.parse(snapshot);
|
|
149
|
+
this._triggerBeforeImportEvent(snapshot, parent, index);
|
|
150
|
+
const flatSnapshots = [];
|
|
151
|
+
this._flattenSnapshot(snapshot, flatSnapshots, parent, index);
|
|
152
|
+
const tree = await this._convertFlatSnapshots(flatSnapshots);
|
|
153
|
+
return { id: tree.draft.id, tree, parent, index };
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
console.error(`Error when preparing snapshot to block:`);
|
|
157
|
+
console.error(error);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* The second half of {@link snapshotToBlock}: adds the prepared blocks to
|
|
163
|
+
* `doc` synchronously, without the yield every `BATCH_SIZE` blocks, so the
|
|
164
|
+
* caller may run it inside its own `store.transact`. The `afterImport`
|
|
165
|
+
* events (middlewares write props from them) wait for `flushAfterImport()`,
|
|
166
|
+
* to call once that transaction has ended and the models exist.
|
|
167
|
+
*/
|
|
168
|
+
this.insertPrepared = (prepared, doc) => {
|
|
169
|
+
const inserted = [];
|
|
170
|
+
try {
|
|
171
|
+
this._insertBlockTreeSync([prepared.tree], doc, inserted, prepared.parent, prepared.index);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
console.error(`Error when inserting prepared snapshot:`);
|
|
175
|
+
console.error(error);
|
|
176
|
+
if (inserted.length === 0)
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
id: prepared.id,
|
|
181
|
+
flushAfterImport: () => {
|
|
182
|
+
for (const node of inserted) {
|
|
183
|
+
const model = doc.getBlock(node.draft.id)?.model;
|
|
184
|
+
if (!model)
|
|
185
|
+
continue;
|
|
186
|
+
this._slots.afterImport.next({
|
|
187
|
+
type: 'block',
|
|
188
|
+
model,
|
|
189
|
+
snapshot: node.snapshot,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return doc.getBlock(prepared.id)?.model ?? null;
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
};
|
|
137
196
|
this.snapshotToDoc = async (snapshot) => {
|
|
138
197
|
try {
|
|
139
198
|
this._slots.beforeImport.next({
|
|
@@ -407,6 +466,17 @@ export class Transformer {
|
|
|
407
466
|
}
|
|
408
467
|
return counter;
|
|
409
468
|
}
|
|
469
|
+
_insertBlockTreeSync(nodes, doc, inserted, parentId, startIndex) {
|
|
470
|
+
nodes.forEach((node, index) => {
|
|
471
|
+
const { id, flavour, props } = node.draft;
|
|
472
|
+
const actualIndex = startIndex !== undefined ? startIndex + index : undefined;
|
|
473
|
+
doc.addBlock(flavour, { id, ...props }, parentId, actualIndex);
|
|
474
|
+
inserted.push(node);
|
|
475
|
+
if (node.children.length > 0) {
|
|
476
|
+
this._insertBlockTreeSync(node.children, doc, inserted, id);
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
}
|
|
410
480
|
_rebuildBlockTree(draftModels) {
|
|
411
481
|
const nodeMap = new Map();
|
|
412
482
|
// First pass: create nodes and add them to the map
|
|
@@ -436,6 +506,8 @@ export class Transformer {
|
|
|
436
506
|
const flatSnapshots = [];
|
|
437
507
|
this._flattenSnapshot(snapshot, flatSnapshots, parent, index);
|
|
438
508
|
const blockTree = await this._convertFlatSnapshots(flatSnapshots);
|
|
509
|
+
// Not `insertPrepared`: an import may hold thousands of blocks, and this
|
|
510
|
+
// path yields to the main thread every BATCH_SIZE of them.
|
|
439
511
|
await this._insertBlockTree([blockTree], doc, parent, index);
|
|
440
512
|
return doc.getBlock(snapshot.id)?.model ?? null;
|
|
441
513
|
}
|
package/dist/commands.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { frameCommands } from './_pkgs/affine-block-frame/index.js';
|
|
2
|
-
import {
|
|
2
|
+
import { imageReplaceCommands } from './_pkgs/affine-block-image/index.js';
|
|
3
|
+
import { copyLinkCommands, coreCommands, invisibleCharactersCommands, pageExportCommands, pivotCommands, readingCommands, tagCommands, } from './_pkgs/affine-block-root/index.js';
|
|
3
4
|
import { auditCommands, canvasDrawioExportCommands, canvasExportCommands, canvasGridCommands, canvasSvgExportCommands, exportSvgCommands, mapQualityCommands, selectionPaneCommands, userLayerCommands, } from './_pkgs/affine-block-surface/index.js';
|
|
4
5
|
import { edgeDirectionCommands } from './_pkgs/affine-gfx-connector/index.js';
|
|
5
6
|
import { shapeCommands } from './_pkgs/affine-gfx-shape/index.js';
|
|
@@ -50,6 +51,7 @@ export function getCommands(flags) {
|
|
|
50
51
|
...coreCommands,
|
|
51
52
|
...copyLinkCommands,
|
|
52
53
|
...pageExportCommands,
|
|
54
|
+
...invisibleCharactersCommands,
|
|
53
55
|
...pivotCommands,
|
|
54
56
|
...tagCommands,
|
|
55
57
|
...readingCommands,
|
|
@@ -58,6 +60,9 @@ export function getCommands(flags) {
|
|
|
58
60
|
...exportSvgCommands,
|
|
59
61
|
...selectionPaneCommands,
|
|
60
62
|
...frameCommands,
|
|
63
|
+
// ADR 0044: registered by the image view extension, so they go with
|
|
64
|
+
// the `image` flag here too.
|
|
65
|
+
...(isBlockEnabled(flags, 'image') ? imageReplaceCommands : []),
|
|
61
66
|
...canvasGridCommands,
|
|
62
67
|
...canvasExportCommands,
|
|
63
68
|
...canvasDrawioExportCommands,
|
package/dist/translations.js
CHANGED
|
@@ -29,6 +29,7 @@ import { PRESET_WORDINGS } from './_pkgs/affine-inline-preset/translations.js';
|
|
|
29
29
|
import { REFERENCE_WORDINGS } from './_pkgs/affine-inline-reference/translations.js';
|
|
30
30
|
import { CHROME_WORDINGS, } from './_pkgs/affine-shared/services/index.js';
|
|
31
31
|
import { CALLOUT_WORDINGS } from './_pkgs/affine-block-callout/translations.js';
|
|
32
|
+
import { TABLE_WORDINGS } from './_pkgs/affine-block-table/translations.js';
|
|
32
33
|
import { CODE_WORDINGS } from './_pkgs/affine-block-code/translations.js';
|
|
33
34
|
import { LATEX_WORDINGS } from './_pkgs/affine-block-latex/translations.js';
|
|
34
35
|
import { NOTE_WORDINGS } from './_pkgs/affine-block-note/translations.js';
|
|
@@ -295,6 +296,7 @@ const PACKAGE_WORDINGS = [
|
|
|
295
296
|
CODE_WORDINGS,
|
|
296
297
|
LATEX_WORDINGS,
|
|
297
298
|
CALLOUT_WORDINGS,
|
|
299
|
+
TABLE_WORDINGS,
|
|
298
300
|
PARAGRAPH_WORDINGS,
|
|
299
301
|
ADAPTER_PANEL_WORDINGS,
|
|
300
302
|
DOC_TITLE_WORDINGS,
|