ducjs 2.2.3 → 2.4.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/dist/flatbuffers/duc/document-grid-align-items.d.ts +5 -0
- package/dist/flatbuffers/duc/document-grid-align-items.js +8 -0
- package/dist/flatbuffers/duc/document-grid-config.d.ts +24 -0
- package/dist/flatbuffers/duc/document-grid-config.js +81 -0
- package/dist/flatbuffers/duc/duc-doc-element.d.ts +6 -0
- package/dist/flatbuffers/duc/duc-doc-element.js +16 -1
- package/dist/flatbuffers/duc/duc-model-element.d.ts +26 -0
- package/dist/flatbuffers/duc/duc-model-element.js +79 -0
- package/dist/flatbuffers/duc/duc-pdf-element.d.ts +3 -1
- package/dist/flatbuffers/duc/duc-pdf-element.js +9 -7
- package/dist/flatbuffers/duc/element.d.ts +5 -3
- package/dist/flatbuffers/duc/element.js +4 -0
- package/dist/flatbuffers/duc.d.ts +3 -0
- package/dist/flatbuffers/duc.js +3 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +4 -3
- package/dist/lazy-files.d.ts +84 -0
- package/dist/lazy-files.js +207 -0
- package/dist/parse.d.ts +35 -2
- package/dist/parse.js +244 -14
- package/dist/restore/restoreDataState.d.ts +1 -6
- package/dist/restore/restoreDataState.js +4 -11
- package/dist/restore/restoreElements.js +51 -26
- package/dist/serialize.js +56 -27
- package/dist/types/elements/index.d.ts +32 -31
- package/dist/types/elements/typeChecks.d.ts +4 -1
- package/dist/types/elements/typeChecks.js +7 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.js +1 -1
- package/dist/utils/constants.d.ts +18 -14
- package/dist/utils/constants.js +28 -15
- package/dist/utils/elements/freedrawElement.d.ts +6 -0
- package/dist/utils/elements/freedrawElement.js +28 -11
- package/dist/utils/elements/newElement.d.ts +2 -2
- package/dist/utils/elements/newElement.js +14 -5
- package/dist/utils/elements/textElement.d.ts +3 -3
- package/dist/utils/elements/textElement.js +43 -16
- package/dist/utils/state/index.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LazyExternalFileStore — Zero-copy, on-demand access to external file data from a FlatBuffer.
|
|
3
|
+
*
|
|
4
|
+
* Instead of eagerly parsing and copying every external file's binary data into JS memory,
|
|
5
|
+
* this store keeps a reference to the original FlatBuffer Uint8Array and reads file bytes
|
|
6
|
+
* only when explicitly requested. FlatBuffer `dataArray()` returns a zero-copy view
|
|
7
|
+
* (a Uint8Array pointing into the original buffer), so no allocation occurs until the
|
|
8
|
+
* consumer actually needs the data.
|
|
9
|
+
*
|
|
10
|
+
* Memory lifecycle:
|
|
11
|
+
* 1. On parse: only metadata (~200 bytes per file) enters JS heap.
|
|
12
|
+
* 2. On demand: `getFileData(fileId)` reads the zero-copy slice from the buffer.
|
|
13
|
+
* 3. The caller (renderer/worker) uses the data, then lets it GC naturally.
|
|
14
|
+
* 4. If the store is released, the buffer reference is dropped, freeing everything.
|
|
15
|
+
*
|
|
16
|
+
* This is the key to supporting 1000s of external files without RAM bloat.
|
|
17
|
+
*/
|
|
18
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
19
|
+
var t = {};
|
|
20
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
21
|
+
t[p] = s[p];
|
|
22
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
23
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
24
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
25
|
+
t[p[i]] = s[p[i]];
|
|
26
|
+
}
|
|
27
|
+
return t;
|
|
28
|
+
};
|
|
29
|
+
import * as flatbuffers from "flatbuffers";
|
|
30
|
+
import { ExportedDataState as ExportedDataStateFb } from "./flatbuffers/duc";
|
|
31
|
+
export class LazyExternalFileStore {
|
|
32
|
+
constructor(buffer) {
|
|
33
|
+
/** Map from file id → lazy entry */
|
|
34
|
+
this._entries = new Map();
|
|
35
|
+
/** Map from element key → file id (the external_files vector uses element id as key) */
|
|
36
|
+
this._keyToFileId = new Map();
|
|
37
|
+
/**
|
|
38
|
+
* Files that were added at runtime (e.g. user uploading a new image).
|
|
39
|
+
* These aren't in the original FlatBuffer so we hold their data directly.
|
|
40
|
+
*/
|
|
41
|
+
this._runtimeFiles = new Map();
|
|
42
|
+
this._buffer = buffer;
|
|
43
|
+
this._byteBuffer = new flatbuffers.ByteBuffer(buffer);
|
|
44
|
+
this._dataState = ExportedDataStateFb.getRootAsExportedDataState(this._byteBuffer);
|
|
45
|
+
this._indexMetadata();
|
|
46
|
+
console.info(`[LazyExternalFileStore] indexed ${this._entries.size} files from ${buffer.byteLength} byte buffer, ids: [${[...this._entries.keys()].map(k => k.slice(0, 12)).join(', ')}]`);
|
|
47
|
+
}
|
|
48
|
+
_indexMetadata() {
|
|
49
|
+
if (!this._dataState)
|
|
50
|
+
return;
|
|
51
|
+
const count = this._dataState.externalFilesLength();
|
|
52
|
+
for (let i = 0; i < count; i++) {
|
|
53
|
+
const entry = this._dataState.externalFiles(i);
|
|
54
|
+
if (!entry)
|
|
55
|
+
continue;
|
|
56
|
+
const key = entry.key();
|
|
57
|
+
const fileData = entry.value();
|
|
58
|
+
if (!key || !fileData)
|
|
59
|
+
continue;
|
|
60
|
+
const id = fileData.id();
|
|
61
|
+
if (!id)
|
|
62
|
+
continue;
|
|
63
|
+
const metadata = {
|
|
64
|
+
id,
|
|
65
|
+
mimeType: fileData.mimeType() || "application/octet-stream",
|
|
66
|
+
created: Number(fileData.created()),
|
|
67
|
+
lastRetrieved: Number(fileData.lastRetrieved()) || undefined,
|
|
68
|
+
};
|
|
69
|
+
const lazyEntry = { metadata, vectorIndex: i };
|
|
70
|
+
this._entries.set(id, lazyEntry);
|
|
71
|
+
this._keyToFileId.set(key, id);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Total number of external files */
|
|
75
|
+
get size() {
|
|
76
|
+
return this._entries.size + this._runtimeFiles.size;
|
|
77
|
+
}
|
|
78
|
+
/** Whether a file with the given id exists */
|
|
79
|
+
has(fileId) {
|
|
80
|
+
return this._entries.has(fileId) || this._runtimeFiles.has(fileId);
|
|
81
|
+
}
|
|
82
|
+
/** Get metadata only (no binary data copied) — ~200 bytes per file */
|
|
83
|
+
getMetadata(fileId) {
|
|
84
|
+
var _a, _b;
|
|
85
|
+
const runtime = this._runtimeFiles.get(fileId);
|
|
86
|
+
if (runtime) {
|
|
87
|
+
const { data: _ } = runtime, meta = __rest(runtime, ["data"]);
|
|
88
|
+
return meta;
|
|
89
|
+
}
|
|
90
|
+
return (_b = (_a = this._entries.get(fileId)) === null || _a === void 0 ? void 0 : _a.metadata) !== null && _b !== void 0 ? _b : null;
|
|
91
|
+
}
|
|
92
|
+
/** Get all metadata entries (for UI listing, etc.) */
|
|
93
|
+
getAllMetadata() {
|
|
94
|
+
const result = {};
|
|
95
|
+
for (const [id, entry] of this._entries) {
|
|
96
|
+
result[id] = entry.metadata;
|
|
97
|
+
}
|
|
98
|
+
for (const [id, file] of this._runtimeFiles) {
|
|
99
|
+
const { data: _ } = file, meta = __rest(file, ["data"]);
|
|
100
|
+
result[id] = meta;
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get full file data (metadata + binary bytes) ON DEMAND.
|
|
106
|
+
*
|
|
107
|
+
* For files from the original FlatBuffer, this returns a zero-copy Uint8Array
|
|
108
|
+
* view into the original buffer — no allocation for the file bytes themselves.
|
|
109
|
+
* The view is valid as long as this store hasn't been released.
|
|
110
|
+
*
|
|
111
|
+
* For runtime-added files, returns the data directly.
|
|
112
|
+
*/
|
|
113
|
+
getFileData(fileId) {
|
|
114
|
+
const runtime = this._runtimeFiles.get(fileId);
|
|
115
|
+
if (runtime)
|
|
116
|
+
return runtime;
|
|
117
|
+
const entry = this._entries.get(fileId);
|
|
118
|
+
if (!entry || !this._dataState)
|
|
119
|
+
return null;
|
|
120
|
+
const fbEntry = this._dataState.externalFiles(entry.vectorIndex);
|
|
121
|
+
if (!fbEntry)
|
|
122
|
+
return null;
|
|
123
|
+
const fileData = fbEntry.value();
|
|
124
|
+
if (!fileData)
|
|
125
|
+
return null;
|
|
126
|
+
const data = fileData.dataArray();
|
|
127
|
+
if (!data)
|
|
128
|
+
return null;
|
|
129
|
+
return Object.assign(Object.assign({}, entry.metadata), { data });
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get a detached copy of the file data (allocates new ArrayBuffer).
|
|
133
|
+
* Use this when you need to transfer data to a worker or keep it beyond store lifetime.
|
|
134
|
+
*/
|
|
135
|
+
getFileDataCopy(fileId) {
|
|
136
|
+
const fileDataRef = this.getFileData(fileId);
|
|
137
|
+
if (!fileDataRef)
|
|
138
|
+
return null;
|
|
139
|
+
return Object.assign(Object.assign({}, fileDataRef), { data: new Uint8Array(fileDataRef.data) });
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Add a file at runtime (user upload, paste, etc.).
|
|
143
|
+
* These files are held in memory since they aren't in the FlatBuffer.
|
|
144
|
+
*/
|
|
145
|
+
addRuntimeFile(fileData) {
|
|
146
|
+
this._runtimeFiles.set(fileData.id, fileData);
|
|
147
|
+
}
|
|
148
|
+
/** Remove a runtime-added file */
|
|
149
|
+
removeRuntimeFile(fileId) {
|
|
150
|
+
this._runtimeFiles.delete(fileId);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Export all files as a standard DucExternalFiles record.
|
|
154
|
+
* This COPIES all file data eagerly — use only for serialization.
|
|
155
|
+
*/
|
|
156
|
+
toExternalFiles() {
|
|
157
|
+
const result = {};
|
|
158
|
+
for (const [key, fileId] of this._keyToFileId) {
|
|
159
|
+
const fileData = this.getFileData(fileId);
|
|
160
|
+
if (fileData) {
|
|
161
|
+
result[key] = fileData;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
for (const [id, file] of this._runtimeFiles) {
|
|
165
|
+
result[id] = file;
|
|
166
|
+
}
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Merge runtime files from the given DucExternalFiles map.
|
|
171
|
+
* Only adds files not already present in the store.
|
|
172
|
+
*/
|
|
173
|
+
mergeFiles(files) {
|
|
174
|
+
for (const [_key, fileData] of Object.entries(files)) {
|
|
175
|
+
if (!this.has(fileData.id)) {
|
|
176
|
+
this.addRuntimeFile(fileData);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/** Estimated RAM usage for metadata only (not counting the backing buffer) */
|
|
181
|
+
get estimatedMetadataBytes() {
|
|
182
|
+
var _a, _b;
|
|
183
|
+
let bytes = 0;
|
|
184
|
+
for (const [, entry] of this._entries) {
|
|
185
|
+
bytes += 200 + entry.metadata.id.length * 2 + entry.metadata.mimeType.length * 2;
|
|
186
|
+
}
|
|
187
|
+
for (const [, file] of this._runtimeFiles) {
|
|
188
|
+
bytes += 200 + ((_b = (_a = file.data) === null || _a === void 0 ? void 0 : _a.byteLength) !== null && _b !== void 0 ? _b : 0);
|
|
189
|
+
}
|
|
190
|
+
return bytes;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Release the FlatBuffer reference. After this, only runtime-added files remain accessible.
|
|
194
|
+
* Call this when switching documents or when the store is no longer needed.
|
|
195
|
+
*/
|
|
196
|
+
release() {
|
|
197
|
+
this._buffer = null;
|
|
198
|
+
this._byteBuffer = null;
|
|
199
|
+
this._dataState = null;
|
|
200
|
+
this._entries.clear();
|
|
201
|
+
this._keyToFileId.clear();
|
|
202
|
+
}
|
|
203
|
+
/** Whether the store has been released */
|
|
204
|
+
get isReleased() {
|
|
205
|
+
return this._buffer === null;
|
|
206
|
+
}
|
|
207
|
+
}
|
package/dist/parse.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { FileSystemHandle } from 'browser-fs-access';
|
|
2
|
-
import { CustomHatchPattern as CustomHatchPatternFb, DimensionToleranceStyle as DimensionToleranceStyleFb, DucBlock as DucBlockFb, DucDimensionStyle as DucDimensionStyleFb, DucDocStyle as DucDocStyleFb, DucExternalFileEntry, DucFeatureControlFrameStyle as DucFeatureControlFrameStyleFb, DucGlobalState as DucGlobalStateFb, DucGroup as DucGroupFb, DucHatchStyle as DucHatchStyleFb, DucHead as DucHeadFb, DucImageFilter as DucImageFilterFb, DucLayer as DucLayerFb, DucLeaderStyle as DucLeaderStyleFb, DucLine as DucLineFb, DucLineReference as DucLineReferenceFb, DucLocalState as DucLocalStateFb, DucPath as DucPathFb, DucPlotStyle as DucPlotStyleFb, DucPointBinding as DucPointBindingFb, DucPoint as DucPointFb, DucRegion as DucRegionFb, DucStackLikeStyles as DucStackLikeStylesFb, DucTableCellStyle as DucTableCellStyleFb, DucTableStyle as DucTableStyleFb, DucTextStyle as DucTextStyleFb, DucViewportStyle as DucViewportStyleFb, DucXRayStyle as DucXRayStyleFb, ElementBackground as ElementBackgroundFb, ElementContentBase as ElementContentBaseFb, ElementStroke as ElementStrokeFb, ElementWrapper, ExportedDataState as ExportedDataStateFb, GeometricPoint as GeometricPointFb, HatchPatternLine as HatchPatternLineFb, Margins as MarginsFb, PrimaryUnits as PrimaryUnitsFb, Standard as StandardFb, StrokeSides as StrokeSidesFb, StrokeStyle as StrokeStyleFb, TilingProperties as TilingPropertiesFb, VersionGraph as VersionGraphFb, _DucElementBase as _DucElementBaseFb, _DucElementStylesBase as _DucElementStylesBaseFb, _DucLinearElementBase as _DucLinearElementBaseFb, _DucStackBase as _DucStackBaseFb, _DucStackElementBase as _DucStackElementBaseFb } from "./flatbuffers/duc";
|
|
2
|
+
import { CustomHatchPattern as CustomHatchPatternFb, DimensionToleranceStyle as DimensionToleranceStyleFb, DocumentGridConfig as DocumentGridConfigFb, DucBlock as DucBlockFb, DucDimensionStyle as DucDimensionStyleFb, DucDocStyle as DucDocStyleFb, DucExternalFileEntry, DucFeatureControlFrameStyle as DucFeatureControlFrameStyleFb, DucGlobalState as DucGlobalStateFb, DucGroup as DucGroupFb, DucHatchStyle as DucHatchStyleFb, DucHead as DucHeadFb, DucImageFilter as DucImageFilterFb, DucLayer as DucLayerFb, DucLeaderStyle as DucLeaderStyleFb, DucLine as DucLineFb, DucLineReference as DucLineReferenceFb, DucLocalState as DucLocalStateFb, DucPath as DucPathFb, DucPlotStyle as DucPlotStyleFb, DucPointBinding as DucPointBindingFb, DucPoint as DucPointFb, DucRegion as DucRegionFb, DucStackLikeStyles as DucStackLikeStylesFb, DucTableCellStyle as DucTableCellStyleFb, DucTableStyle as DucTableStyleFb, DucTextStyle as DucTextStyleFb, DucViewportStyle as DucViewportStyleFb, DucXRayStyle as DucXRayStyleFb, ElementBackground as ElementBackgroundFb, ElementContentBase as ElementContentBaseFb, ElementStroke as ElementStrokeFb, ElementWrapper, ExportedDataState as ExportedDataStateFb, GeometricPoint as GeometricPointFb, HatchPatternLine as HatchPatternLineFb, Margins as MarginsFb, PrimaryUnits as PrimaryUnitsFb, Standard as StandardFb, StrokeSides as StrokeSidesFb, StrokeStyle as StrokeStyleFb, TilingProperties as TilingPropertiesFb, VersionGraph as VersionGraphFb, _DucElementBase as _DucElementBaseFb, _DucElementStylesBase as _DucElementStylesBaseFb, _DucLinearElementBase as _DucLinearElementBaseFb, _DucStackBase as _DucStackBaseFb, _DucStackElementBase as _DucStackElementBaseFb } from "./flatbuffers/duc";
|
|
3
3
|
import { RestoreConfig, RestoredDataState } from "./restore";
|
|
4
4
|
import { Standard, StandardUnits } from "./technical";
|
|
5
|
-
import { CustomHatchPattern, Dictionary, DucBlock, DucDimensionStyle, DucDocStyle, DucElement, DucExternalFiles, DucFeatureControlFrameStyle, DucGlobalState, DucGroup, DucHatchStyle, DucHead, DucImageFilter, DucLayer, DucLeaderStyle, DucLine, DucLineReference, DucLocalState, DucPath, DucPlotStyle, DucPoint, DucPointBinding, DucRegion, DucStackLikeStyles, DucTableCellStyle, DucTableStyle, DucTextStyle, DucViewportStyle, DucXRayStyle, ElementBackground, ElementContentBase, ElementStroke, GeometricPoint, HatchPatternLine, PlotLayout, StrokeSides, StrokeStyle, TilingProperties, VersionGraph, _DucElementBase, _DucElementStylesBase, _DucLinearElementBase, _DucStackBase, _DucStackElementBase } from "./types";
|
|
5
|
+
import { CustomHatchPattern, Dictionary, DocumentGridConfig, DucBlock, DucDimensionStyle, DucDocStyle, DucElement, DucExternalFileMetadata, DucExternalFiles, DucFeatureControlFrameStyle, DucGlobalState, DucGroup, DucHatchStyle, DucHead, DucImageFilter, DucLayer, DucLeaderStyle, DucLine, DucLineReference, DucLocalState, DucPath, DucPlotStyle, DucPoint, DucPointBinding, DucRegion, DucStackLikeStyles, DucTableCellStyle, DucTableStyle, DucTextStyle, DucViewportStyle, DucXRayStyle, ElementBackground, ElementContentBase, ElementStroke, GeometricPoint, HatchPatternLine, PlotLayout, StrokeSides, StrokeStyle, TilingProperties, VersionGraph, _DucElementBase, _DucElementStylesBase, _DucLinearElementBase, _DucStackBase, _DucStackElementBase } from "./types";
|
|
6
6
|
export declare function parseGeometricPoint(point: GeometricPointFb): GeometricPoint;
|
|
7
7
|
export declare function parsePoint(point: DucPointFb): DucPoint;
|
|
8
8
|
export declare function parseMargins(margins: MarginsFb): PlotLayout["margins"];
|
|
9
|
+
export declare function parseDocumentGridConfig(gridConfig: DocumentGridConfigFb): DocumentGridConfig;
|
|
9
10
|
export declare function parseHead(head: DucHeadFb): DucHead;
|
|
10
11
|
export declare function parseHatchPatternLine(line: HatchPatternLineFb): HatchPatternLine;
|
|
11
12
|
export declare function parseCustomHatchPattern(pattern: CustomHatchPatternFb): CustomHatchPattern;
|
|
@@ -42,6 +43,14 @@ export declare function parseElementFromBinary(wrapper: ElementWrapper): DucElem
|
|
|
42
43
|
export declare function parseBlockFromBinary(block: DucBlockFb): DucBlock;
|
|
43
44
|
export declare function parseDictionaryFromBinary(data: ExportedDataStateFb): Dictionary;
|
|
44
45
|
export declare function parseExternalFilesFromBinary(entry: DucExternalFileEntry): DucExternalFiles;
|
|
46
|
+
/**
|
|
47
|
+
* Parse only metadata (no binary data) from an external file entry.
|
|
48
|
+
* Used by the lazy file store to avoid copying file bytes into JS memory.
|
|
49
|
+
*/
|
|
50
|
+
export declare function parseExternalFileMetadataFromBinary(entry: DucExternalFileEntry): {
|
|
51
|
+
key: string;
|
|
52
|
+
metadata: DucExternalFileMetadata;
|
|
53
|
+
} | null;
|
|
45
54
|
export declare function parseGlobalStateFromBinary(state: DucGlobalStateFb): DucGlobalState;
|
|
46
55
|
export declare function parseGroupFromBinary(group: DucGroupFb): DucGroup;
|
|
47
56
|
export declare function parseLayerFromBinary(layer: DucLayerFb): DucLayer;
|
|
@@ -52,3 +61,27 @@ export declare function parseStandardFromBinary(standard: StandardFb): Standard;
|
|
|
52
61
|
export declare function parseThumbnailFromBinary(data: ExportedDataStateFb): Uint8Array | undefined;
|
|
53
62
|
export declare function parseVersionGraphFromBinary(graph: VersionGraphFb | null): VersionGraph | null;
|
|
54
63
|
export declare const parseDuc: (blob: Blob | File, fileHandle?: FileSystemHandle | null, restoreConfig?: RestoreConfig) => Promise<RestoredDataState>;
|
|
64
|
+
import { LazyExternalFileStore } from "./lazy-files";
|
|
65
|
+
export type LazyRestoredDataState = Omit<RestoredDataState, 'files'> & {
|
|
66
|
+
/** Lazy file store: only metadata is in memory, file bytes are read on-demand from the buffer */
|
|
67
|
+
lazyFileStore: LazyExternalFileStore;
|
|
68
|
+
/** Legacy `files` field — always empty. Use lazyFileStore instead. */
|
|
69
|
+
files: DucExternalFiles;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Parse a .duc binary with lazy external file loading.
|
|
73
|
+
*
|
|
74
|
+
* This is identical to `parseDuc` except:
|
|
75
|
+
* - External file BYTES are NOT copied into JS memory.
|
|
76
|
+
* - Only file metadata (~200 bytes per file) is parsed.
|
|
77
|
+
* - A `LazyExternalFileStore` is returned for on-demand data access.
|
|
78
|
+
* - The store holds a reference to the original Uint8Array buffer.
|
|
79
|
+
*
|
|
80
|
+
* Memory comparison for 500 PDFs averaging 5MB each:
|
|
81
|
+
* - parseDuc: files field holds 2.5GB of ArrayBuffer data in JS heap
|
|
82
|
+
* - parseDucLazy: ~100KB of metadata + the original buffer (referenced, not copied)
|
|
83
|
+
*
|
|
84
|
+
* @param buffer - The raw .duc file bytes (from storage/IndexedDB/filesystem)
|
|
85
|
+
* @param restoreConfig - Optional restore configuration
|
|
86
|
+
*/
|
|
87
|
+
export declare const parseDucLazy: (buffer: Uint8Array, restoreConfig?: RestoreConfig) => Promise<LazyRestoredDataState>;
|
package/dist/parse.js
CHANGED
|
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { decompressSync, strFromU8 } from 'fflate';
|
|
11
11
|
import * as flatbuffers from "flatbuffers";
|
|
12
12
|
import { nanoid } from 'nanoid';
|
|
13
|
-
import { DucArrowElement as DucArrowElementFb, DucDimensionElement as DucDimensionElementFb, DucDocElement as DucDocElementFb, DucEllipseElement as DucEllipseElementFb, DucEmbeddableElement as DucEmbeddableElementFb, DucFeatureControlFrameElement as DucFeatureControlFrameElementFb, DucFrameElement as DucFrameElementFb, DucFreeDrawElement as DucFreeDrawElementFb, DucImageElement as DucImageElementFb, DucLeaderElement as DucLeaderElementFb, DucLinearElement as DucLinearElementFb, DucMermaidElement as DucMermaidElementFb,
|
|
13
|
+
import { DOCUMENT_GRID_ALIGN_ITEMS, DucArrowElement as DucArrowElementFb, DucDimensionElement as DucDimensionElementFb, DucDocElement as DucDocElementFb, DucEllipseElement as DucEllipseElementFb, DucEmbeddableElement as DucEmbeddableElementFb, DucFeatureControlFrameElement as DucFeatureControlFrameElementFb, DucFrameElement as DucFrameElementFb, DucFreeDrawElement as DucFreeDrawElementFb, DucImageElement as DucImageElementFb, DucLeaderElement as DucLeaderElementFb, DucLinearElement as DucLinearElementFb, DucMermaidElement as DucMermaidElementFb, DucModelElement as DucModelElementFb, DucPdfElement as DucPdfElementFb, DucPlotElement as DucPlotElementFb, DucPolygonElement as DucPolygonElementFb, DucRectangleElement as DucRectangleElementFb, DucTableElement as DucTableElementFb, DucTextDynamicDictionarySource as DucTextDynamicDictionarySourceFb, DucTextDynamicElementSource as DucTextDynamicElementSourceFb, DucTextElement as DucTextElementFb, DucViewportElement as DucViewportElementFb, DucXRayElement as DucXRayElementFb, Element as ElementUnion, ExportedDataState, LEADER_CONTENT_TYPE as LEADER_CONTENT_TYPE_ENUM, LeaderBlockContent as LeaderBlockContentFb, LeaderTextBlockContent as LeaderTextBlockContentFb, TEXT_FIELD_SOURCE_TYPE } from "./flatbuffers/duc";
|
|
14
14
|
import { restore } from "./restore";
|
|
15
15
|
// #region HELPERS & LOW-LEVEL CASTS
|
|
16
16
|
// Helper functions for type casting
|
|
@@ -70,6 +70,25 @@ export function parseMargins(margins) {
|
|
|
70
70
|
left: toPrecisionValue(margins.left()),
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
|
+
export function parseDocumentGridConfig(gridConfig) {
|
|
74
|
+
return {
|
|
75
|
+
columns: gridConfig.columns(),
|
|
76
|
+
gapX: gridConfig.gapX(),
|
|
77
|
+
gapY: gridConfig.gapY(),
|
|
78
|
+
alignItems: (() => {
|
|
79
|
+
const align = gridConfig.alignItems();
|
|
80
|
+
if (align === DOCUMENT_GRID_ALIGN_ITEMS.START)
|
|
81
|
+
return 'start';
|
|
82
|
+
if (align === DOCUMENT_GRID_ALIGN_ITEMS.CENTER)
|
|
83
|
+
return 'center';
|
|
84
|
+
if (align === DOCUMENT_GRID_ALIGN_ITEMS.END)
|
|
85
|
+
return 'end';
|
|
86
|
+
return 'start';
|
|
87
|
+
})(),
|
|
88
|
+
firstPageAlone: gridConfig.firstPageAlone(),
|
|
89
|
+
scale: gridConfig.scale(),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
73
92
|
export function parseHead(head) {
|
|
74
93
|
return {
|
|
75
94
|
type: head.type(),
|
|
@@ -257,7 +276,15 @@ function parseEmbeddableElement(element) {
|
|
|
257
276
|
return Object.assign({ type: "embeddable" }, parseElementBase(element.base()));
|
|
258
277
|
}
|
|
259
278
|
function parsePdfElement(element) {
|
|
260
|
-
|
|
279
|
+
const gridConfig = element.gridConfig();
|
|
280
|
+
return Object.assign(Object.assign({ type: "pdf" }, parseElementBase(element.base())), { fileId: element.fileId(), gridConfig: gridConfig ? parseDocumentGridConfig(gridConfig) : {
|
|
281
|
+
columns: 1,
|
|
282
|
+
gapX: 0,
|
|
283
|
+
gapY: 0,
|
|
284
|
+
alignItems: 'start',
|
|
285
|
+
firstPageAlone: false,
|
|
286
|
+
scale: 1,
|
|
287
|
+
} });
|
|
261
288
|
}
|
|
262
289
|
function parseMermaidElement(element) {
|
|
263
290
|
return Object.assign(Object.assign({ type: "mermaid" }, parseElementBase(element.base())), { source: element.source(), theme: element.theme() || undefined, svgPath: element.svgPath() });
|
|
@@ -545,6 +572,7 @@ function parseDocElement(element) {
|
|
|
545
572
|
});
|
|
546
573
|
}
|
|
547
574
|
const columns = element.columns();
|
|
575
|
+
const gridConfig = element.gridConfig();
|
|
548
576
|
return Object.assign(Object.assign(Object.assign({ type: "doc" }, parseElementBase(element.base())), parseDocStyle(element.style())), { text: element.text(), dynamic: dynamicParts, flowDirection: element.flowDirection(), columns: {
|
|
549
577
|
type: columns.type(),
|
|
550
578
|
definitions: Array.from({ length: columns.definitionsLength() }, (_, i) => {
|
|
@@ -555,16 +583,18 @@ function parseDocElement(element) {
|
|
|
555
583
|
};
|
|
556
584
|
}),
|
|
557
585
|
autoHeight: columns.autoHeight(),
|
|
558
|
-
}, autoResize: element.autoResize()
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
fileId: source.fileId(),
|
|
586
|
+
}, autoResize: element.autoResize(), fileId: element.fileId(), gridConfig: gridConfig ? parseDocumentGridConfig(gridConfig) : {
|
|
587
|
+
columns: 1,
|
|
588
|
+
gapX: 0,
|
|
589
|
+
gapY: 0,
|
|
590
|
+
alignItems: 'start',
|
|
591
|
+
firstPageAlone: false,
|
|
592
|
+
scale: 1,
|
|
566
593
|
} });
|
|
567
594
|
}
|
|
595
|
+
function parseModelElement(element) {
|
|
596
|
+
return Object.assign(Object.assign({ type: "model" }, parseElementBase(element.base())), { source: element.source(), svgPath: element.svgPath(), fileIds: Array.from({ length: element.fileIdsLength() }, (_, i) => element.fileIds(i)) });
|
|
597
|
+
}
|
|
568
598
|
// #endregion
|
|
569
599
|
// #region STYLE PARSERS (ELEMENT-LEVEL)
|
|
570
600
|
export function parseTextStyle(style) {
|
|
@@ -772,8 +802,8 @@ export function parseElementFromBinary(wrapper) {
|
|
|
772
802
|
case ElementUnion.DucDocElement:
|
|
773
803
|
element = wrapper.element(new DucDocElementFb());
|
|
774
804
|
break;
|
|
775
|
-
case ElementUnion.
|
|
776
|
-
element = wrapper.element(new
|
|
805
|
+
case ElementUnion.DucModelElement:
|
|
806
|
+
element = wrapper.element(new DucModelElementFb());
|
|
777
807
|
break;
|
|
778
808
|
default:
|
|
779
809
|
return null;
|
|
@@ -823,8 +853,8 @@ export function parseElementFromBinary(wrapper) {
|
|
|
823
853
|
return parseFeatureControlFrameElement(element);
|
|
824
854
|
case ElementUnion.DucDocElement:
|
|
825
855
|
return parseDocElement(element);
|
|
826
|
-
case ElementUnion.
|
|
827
|
-
return
|
|
856
|
+
case ElementUnion.DucModelElement:
|
|
857
|
+
return parseModelElement(element);
|
|
828
858
|
default:
|
|
829
859
|
return null;
|
|
830
860
|
}
|
|
@@ -880,6 +910,28 @@ export function parseExternalFilesFromBinary(entry) {
|
|
|
880
910
|
}
|
|
881
911
|
};
|
|
882
912
|
}
|
|
913
|
+
/**
|
|
914
|
+
* Parse only metadata (no binary data) from an external file entry.
|
|
915
|
+
* Used by the lazy file store to avoid copying file bytes into JS memory.
|
|
916
|
+
*/
|
|
917
|
+
export function parseExternalFileMetadataFromBinary(entry) {
|
|
918
|
+
const fileData = entry.value();
|
|
919
|
+
const key = entry.key();
|
|
920
|
+
if (!fileData || !key)
|
|
921
|
+
return null;
|
|
922
|
+
const id = fileData.id();
|
|
923
|
+
if (!id)
|
|
924
|
+
return null;
|
|
925
|
+
return {
|
|
926
|
+
key,
|
|
927
|
+
metadata: {
|
|
928
|
+
id,
|
|
929
|
+
mimeType: fileData.mimeType() || "application/octet-stream",
|
|
930
|
+
created: Number(fileData.created()),
|
|
931
|
+
lastRetrieved: Number(fileData.lastRetrieved()) || undefined,
|
|
932
|
+
},
|
|
933
|
+
};
|
|
934
|
+
}
|
|
883
935
|
export function parseGlobalStateFromBinary(state) {
|
|
884
936
|
return {
|
|
885
937
|
name: state.name(),
|
|
@@ -1432,3 +1484,181 @@ export const parseDuc = (blob_1, ...args_1) => __awaiter(void 0, [blob_1, ...arg
|
|
|
1432
1484
|
};
|
|
1433
1485
|
});
|
|
1434
1486
|
// #endregion
|
|
1487
|
+
// #region LAZY ROOT PARSER
|
|
1488
|
+
import { LazyExternalFileStore } from "./lazy-files";
|
|
1489
|
+
/**
|
|
1490
|
+
* Parse a .duc binary with lazy external file loading.
|
|
1491
|
+
*
|
|
1492
|
+
* This is identical to `parseDuc` except:
|
|
1493
|
+
* - External file BYTES are NOT copied into JS memory.
|
|
1494
|
+
* - Only file metadata (~200 bytes per file) is parsed.
|
|
1495
|
+
* - A `LazyExternalFileStore` is returned for on-demand data access.
|
|
1496
|
+
* - The store holds a reference to the original Uint8Array buffer.
|
|
1497
|
+
*
|
|
1498
|
+
* Memory comparison for 500 PDFs averaging 5MB each:
|
|
1499
|
+
* - parseDuc: files field holds 2.5GB of ArrayBuffer data in JS heap
|
|
1500
|
+
* - parseDucLazy: ~100KB of metadata + the original buffer (referenced, not copied)
|
|
1501
|
+
*
|
|
1502
|
+
* @param buffer - The raw .duc file bytes (from storage/IndexedDB/filesystem)
|
|
1503
|
+
* @param restoreConfig - Optional restore configuration
|
|
1504
|
+
*/
|
|
1505
|
+
export const parseDucLazy = (buffer_1, ...args_1) => __awaiter(void 0, [buffer_1, ...args_1], void 0, function* (buffer, restoreConfig = {}) {
|
|
1506
|
+
var _a;
|
|
1507
|
+
if (!buffer || buffer.byteLength === 0) {
|
|
1508
|
+
throw new Error('Invalid DUC buffer: empty file');
|
|
1509
|
+
}
|
|
1510
|
+
const byteBuffer = new flatbuffers.ByteBuffer(buffer);
|
|
1511
|
+
let data;
|
|
1512
|
+
try {
|
|
1513
|
+
data = ExportedDataState.getRootAsExportedDataState(byteBuffer);
|
|
1514
|
+
}
|
|
1515
|
+
catch (e) {
|
|
1516
|
+
throw new Error('Invalid DUC buffer: cannot read root table');
|
|
1517
|
+
}
|
|
1518
|
+
const legacyVersion = data.versionLegacy();
|
|
1519
|
+
if (legacyVersion) {
|
|
1520
|
+
throw new Error(`Unsupported DUC version: ${legacyVersion}. Please use version ducjs@2.0.1 or lower to support this file.`);
|
|
1521
|
+
}
|
|
1522
|
+
const localState = data.ducLocalState();
|
|
1523
|
+
const parsedLocalState = localState && parseLocalStateFromBinary(localState);
|
|
1524
|
+
const globalState = data.ducGlobalState();
|
|
1525
|
+
const parsedGlobalState = globalState && parseGlobalStateFromBinary(globalState);
|
|
1526
|
+
// Parse elements
|
|
1527
|
+
const elements = [];
|
|
1528
|
+
for (let i = 0; i < data.elementsLength(); i++) {
|
|
1529
|
+
const e = data.elements(i);
|
|
1530
|
+
if (e) {
|
|
1531
|
+
const element = parseElementFromBinary(e);
|
|
1532
|
+
if (element) {
|
|
1533
|
+
elements.push(element);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
// Create lazy file store — only metadata is parsed, no file bytes copied
|
|
1538
|
+
const lazyFileStore = new LazyExternalFileStore(buffer);
|
|
1539
|
+
// Parse blocks
|
|
1540
|
+
const blocks = [];
|
|
1541
|
+
for (let i = 0; i < data.blocksLength(); i++) {
|
|
1542
|
+
const block = data.blocks(i);
|
|
1543
|
+
if (block) {
|
|
1544
|
+
const parsedBlock = parseBlockFromBinary(block);
|
|
1545
|
+
if (parsedBlock) {
|
|
1546
|
+
blocks.push(parsedBlock);
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
// Parse block instances
|
|
1551
|
+
const blockInstances = [];
|
|
1552
|
+
for (let i = 0; i < data.blockInstancesLength(); i++) {
|
|
1553
|
+
const blockInstance = data.blockInstances(i);
|
|
1554
|
+
if (blockInstance) {
|
|
1555
|
+
const parsedBlockInstance = parseBlockInstance(blockInstance);
|
|
1556
|
+
if (parsedBlockInstance) {
|
|
1557
|
+
blockInstances.push(parsedBlockInstance);
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
// Parse block collections
|
|
1562
|
+
const blockCollections = [];
|
|
1563
|
+
for (let i = 0; i < data.blockCollectionsLength(); i++) {
|
|
1564
|
+
const blockCollection = data.blockCollections(i);
|
|
1565
|
+
if (blockCollection) {
|
|
1566
|
+
const parsedBlockCollection = parseBlockCollection(blockCollection);
|
|
1567
|
+
if (parsedBlockCollection) {
|
|
1568
|
+
blockCollections.push(parsedBlockCollection);
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
// Parse groups
|
|
1573
|
+
const groups = [];
|
|
1574
|
+
for (let i = 0; i < data.groupsLength(); i++) {
|
|
1575
|
+
const group = data.groups(i);
|
|
1576
|
+
if (group) {
|
|
1577
|
+
const parsedGroup = parseGroupFromBinary(group);
|
|
1578
|
+
if (parsedGroup) {
|
|
1579
|
+
groups.push(parsedGroup);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
// Parse dictionary
|
|
1584
|
+
const dictionary = parseDictionaryFromBinary(data);
|
|
1585
|
+
// Parse thumbnail
|
|
1586
|
+
const thumbnail = parseThumbnailFromBinary(data);
|
|
1587
|
+
// Parse version graph
|
|
1588
|
+
const versionGraphData = data.versionGraph();
|
|
1589
|
+
const versionGraph = parseVersionGraphFromBinary(versionGraphData);
|
|
1590
|
+
// Parse regions
|
|
1591
|
+
const regions = [];
|
|
1592
|
+
for (let i = 0; i < data.regionsLength(); i++) {
|
|
1593
|
+
const region = data.regions(i);
|
|
1594
|
+
if (region) {
|
|
1595
|
+
const parsedRegion = parseRegionFromBinary(region);
|
|
1596
|
+
if (parsedRegion) {
|
|
1597
|
+
regions.push(parsedRegion);
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
// Parse layers
|
|
1602
|
+
const layers = [];
|
|
1603
|
+
for (let i = 0; i < data.layersLength(); i++) {
|
|
1604
|
+
const layer = data.layers(i);
|
|
1605
|
+
if (layer) {
|
|
1606
|
+
const parsedLayer = parseLayerFromBinary(layer);
|
|
1607
|
+
if (parsedLayer) {
|
|
1608
|
+
layers.push(parsedLayer);
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
// Parse standards
|
|
1613
|
+
const standards = [];
|
|
1614
|
+
for (let i = 0; i < data.standardsLength(); i++) {
|
|
1615
|
+
const standard = data.standards(i);
|
|
1616
|
+
if (standard) {
|
|
1617
|
+
const parsedStandard = parseStandardFromBinary(standard);
|
|
1618
|
+
if (parsedStandard) {
|
|
1619
|
+
standards.push(parsedStandard);
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
const exportData = {
|
|
1624
|
+
thumbnail,
|
|
1625
|
+
dictionary,
|
|
1626
|
+
elements: elements,
|
|
1627
|
+
localState: parsedLocalState,
|
|
1628
|
+
globalState: parsedGlobalState,
|
|
1629
|
+
blocks,
|
|
1630
|
+
blockInstances,
|
|
1631
|
+
blockCollections,
|
|
1632
|
+
groups,
|
|
1633
|
+
regions,
|
|
1634
|
+
layers,
|
|
1635
|
+
standards,
|
|
1636
|
+
files: {}, // empty — use lazyFileStore
|
|
1637
|
+
versionGraph: versionGraph !== null && versionGraph !== void 0 ? versionGraph : undefined,
|
|
1638
|
+
id: (_a = data.id()) !== null && _a !== void 0 ? _a : nanoid(),
|
|
1639
|
+
};
|
|
1640
|
+
const sanitized = restore(exportData, {
|
|
1641
|
+
syncInvalidIndices: (elements) => elements,
|
|
1642
|
+
repairBindings: true,
|
|
1643
|
+
refreshDimensions: false,
|
|
1644
|
+
}, restoreConfig);
|
|
1645
|
+
return {
|
|
1646
|
+
thumbnail: sanitized.thumbnail,
|
|
1647
|
+
dictionary: sanitized.dictionary,
|
|
1648
|
+
elements: sanitized.elements,
|
|
1649
|
+
localState: sanitized.localState,
|
|
1650
|
+
globalState: sanitized.globalState,
|
|
1651
|
+
files: {},
|
|
1652
|
+
lazyFileStore,
|
|
1653
|
+
blocks: sanitized.blocks,
|
|
1654
|
+
blockInstances: sanitized.blockInstances,
|
|
1655
|
+
groups: sanitized.groups,
|
|
1656
|
+
regions: sanitized.regions,
|
|
1657
|
+
layers: sanitized.layers,
|
|
1658
|
+
blockCollections: sanitized.blockCollections,
|
|
1659
|
+
standards: sanitized.standards,
|
|
1660
|
+
versionGraph: sanitized.versionGraph,
|
|
1661
|
+
id: sanitized.id,
|
|
1662
|
+
};
|
|
1663
|
+
});
|
|
1664
|
+
// #endregion
|
|
@@ -97,12 +97,7 @@ export declare const restoreBlockCollections: (collections: unknown) => Restored
|
|
|
97
97
|
* Restores the blockInstances array from imported data, ensuring each item
|
|
98
98
|
* conforms to the DucBlockInstance type.
|
|
99
99
|
*/
|
|
100
|
-
export declare const restoreBlockInstances: (blockInstances: unknown) => RestoredDataState["blockInstances"];
|
|
101
|
-
/**
|
|
102
|
-
* Restores instances from block instances data (alias for restoreBlockInstances)
|
|
103
|
-
* This method provides a consistent naming convention for instance restoration.
|
|
104
|
-
*/
|
|
105
|
-
export declare const restoreInstances: (instances: unknown) => RestoredDataState["blockInstances"];
|
|
100
|
+
export declare const restoreBlockInstances: (blockInstances: unknown, currentScope: Scope) => RestoredDataState["blockInstances"];
|
|
106
101
|
/**
|
|
107
102
|
* Restores the global state of the document from imported data.
|
|
108
103
|
* It validates and provides defaults for missing or invalid properties.
|
|
@@ -20,7 +20,7 @@ export const restore = (data, elementsConfig, restoreConfig = {}) => {
|
|
|
20
20
|
const restoredRegions = restoreRegions(data === null || data === void 0 ? void 0 : data.regions);
|
|
21
21
|
const restoredGroups = restoreGroups(data === null || data === void 0 ? void 0 : data.groups);
|
|
22
22
|
const restoredLayers = restoreLayers(data === null || data === void 0 ? void 0 : data.layers, restoredLocalState.scope);
|
|
23
|
-
const restoredBlockInstances = restoreBlockInstances(data === null || data === void 0 ? void 0 : data.blockInstances);
|
|
23
|
+
const restoredBlockInstances = restoreBlockInstances(data === null || data === void 0 ? void 0 : data.blockInstances, restoredLocalState.scope);
|
|
24
24
|
const restoredElements = restoreElements(data === null || data === void 0 ? void 0 : data.elements, restoredLocalState.scope, restoredBlocks, restoredElementsConfig);
|
|
25
25
|
const restoredVersionGraph = restoreVersionGraph(data === null || data === void 0 ? void 0 : data.versionGraph);
|
|
26
26
|
// Generate a new ID if none exists or if it's empty
|
|
@@ -247,7 +247,7 @@ export const restoreBlockCollections = (collections) => {
|
|
|
247
247
|
* Restores the blockInstances array from imported data, ensuring each item
|
|
248
248
|
* conforms to the DucBlockInstance type.
|
|
249
249
|
*/
|
|
250
|
-
export const restoreBlockInstances = (blockInstances) => {
|
|
250
|
+
export const restoreBlockInstances = (blockInstances, currentScope) => {
|
|
251
251
|
if (!Array.isArray(blockInstances)) {
|
|
252
252
|
return [];
|
|
253
253
|
}
|
|
@@ -301,8 +301,8 @@ export const restoreBlockInstances = (blockInstances) => {
|
|
|
301
301
|
? {
|
|
302
302
|
rows: typeof dupArray.rows === "number" ? dupArray.rows : 1,
|
|
303
303
|
cols: typeof dupArray.cols === "number" ? dupArray.cols : 1,
|
|
304
|
-
rowSpacing:
|
|
305
|
-
colSpacing:
|
|
304
|
+
rowSpacing: restorePrecisionValue(dupArray.rowSpacing, NEUTRAL_SCOPE, currentScope),
|
|
305
|
+
colSpacing: restorePrecisionValue(dupArray.colSpacing, NEUTRAL_SCOPE, currentScope),
|
|
306
306
|
}
|
|
307
307
|
: null,
|
|
308
308
|
};
|
|
@@ -337,13 +337,6 @@ const restoreBlockMetadata = (metadata) => {
|
|
|
337
337
|
: undefined;
|
|
338
338
|
return Object.assign(Object.assign({}, (source ? { source } : {})), { usageCount: typeof metadataObj.usageCount === "number" ? metadataObj.usageCount : 0, createdAt: typeof metadataObj.createdAt === "number" ? metadataObj.createdAt : Date.now(), updatedAt: typeof metadataObj.updatedAt === "number" ? metadataObj.updatedAt : Date.now(), localization });
|
|
339
339
|
};
|
|
340
|
-
/**
|
|
341
|
-
* Restores instances from block instances data (alias for restoreBlockInstances)
|
|
342
|
-
* This method provides a consistent naming convention for instance restoration.
|
|
343
|
-
*/
|
|
344
|
-
export const restoreInstances = (instances) => {
|
|
345
|
-
return restoreBlockInstances(instances);
|
|
346
|
-
};
|
|
347
340
|
/**
|
|
348
341
|
* Restores the global state of the document from imported data.
|
|
349
342
|
* It validates and provides defaults for missing or invalid properties.
|