@stll/folio-core 0.22.2 → 0.23.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/ai-edits/apply.d.ts +1 -1
- package/dist/controller/layoutPipeline.js +28 -0
- package/dist/document-operations.d.ts +4 -4
- package/dist/document-operations.js +17 -1
- package/dist/docx/imageParser.js +6 -9
- package/dist/docx/rezip.d.ts +1 -1
- package/dist/docx/rezip.js +12 -31
- package/dist/docx/server/inspectDocxPackage.js +8 -7
- package/dist/docx/styleParser.js +16 -16
- package/dist/docx/xmlParser.d.ts +7 -3
- package/dist/docx/xmlParser.js +20 -7
- package/dist/layout-bridge/convert/toFlowBlocks.js +35 -61
- package/dist/layout-engine/measure/measureHelpers.d.ts +2 -1
- package/dist/layout-engine/measure/measureHelpers.js +5 -2
- package/dist/layout-engine/types.d.ts +6 -0
- package/dist/layout-painter/anchoredImagePosition.d.ts +2 -1
- package/dist/layout-painter/anchoredImagePosition.js +14 -6
- package/dist/layout-painter/imageLayout.d.ts +1 -1
- package/dist/layout-painter/renderPage.js +11 -1
- package/dist/layout-painter/renderParagraph.js +3 -4
- package/dist/managers/AutoSaveManager.js +8 -40
- package/dist/managers/TableSelectionManager.d.ts +1 -1
- package/dist/managers/autoSaveCodec.d.ts +17 -0
- package/dist/managers/autoSaveCodec.js +109 -0
- package/dist/prosemirror/attrs/index.js +278 -29
- package/dist/prosemirror/commands/comments.js +3 -3
- package/dist/prosemirror/commands/formatting.js +19 -19
- package/dist/prosemirror/commands/index.d.ts +2 -2
- package/dist/prosemirror/commands/paragraph.js +32 -32
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +5 -3
- package/dist/prosemirror/commands/propertyChangeScope.js +9 -8
- package/dist/prosemirror/commands/table.d.ts +10 -52
- package/dist/prosemirror/commands/table.js +34 -34
- package/dist/prosemirror/conversion/fromProseDoc.js +33 -20
- package/dist/prosemirror/conversion/sdtAttrs.d.ts +2 -1
- package/dist/prosemirror/conversion/sdtAttrs.js +9 -4
- package/dist/prosemirror/conversion/toProseDoc.js +1 -0
- package/dist/prosemirror/extensions/ExtensionManager.d.ts +6 -3
- package/dist/prosemirror/extensions/ExtensionManager.js +5 -3
- package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +1 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +30 -3
- package/dist/prosemirror/extensions/features/ListExtension.js +4 -4
- package/dist/prosemirror/extensions/marks/UnderlineExtension.js +9 -7
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +2 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +92 -16
- package/dist/prosemirror/extensions/nodes/ShapeExtension.d.ts +1 -1
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +1 -1
- package/dist/prosemirror/extensions/types.d.ts +134 -1
- package/dist/prosemirror/index.d.ts +2 -2
- package/dist/prosemirror/plugins/selectionTracker.js +25 -94
- package/dist/prosemirror/revisionCarriers.js +3 -1
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/index.js +87 -0
- package/dist/prosemirror/schema/nodes.d.ts +14 -2
- package/dist/prosemirror/selectionMarks.d.ts +11 -0
- package/dist/prosemirror/selectionMarks.js +19 -0
- package/dist/prosemirror/selectionState.d.ts +11 -5
- package/dist/prosemirror/selectionState.js +99 -74
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
- package/dist/utils/formatToStyle.js +1 -1
- package/dist/utils/tableOperations.d.ts +7 -6
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ImageRun } from "../layout-engine/types.js";
|
|
1
|
+
import { ImageRun, PageMargins } from "../layout-engine/types.js";
|
|
2
2
|
//#region src/layout-painter/anchoredImagePosition.d.ts
|
|
3
3
|
type PageGeometry = {
|
|
4
4
|
pageWidth: number;
|
|
@@ -7,6 +7,7 @@ type PageGeometry = {
|
|
|
7
7
|
marginTop: number;
|
|
8
8
|
marginRight: number;
|
|
9
9
|
marginBottom: number;
|
|
10
|
+
authoredMargins?: PageMargins;
|
|
10
11
|
contentWidth: number;
|
|
11
12
|
contentHeight: number;
|
|
12
13
|
};
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { emuToPixels } from "./renderUtils.js";
|
|
2
2
|
//#region src/layout-painter/anchoredImagePosition.ts
|
|
3
|
+
const authoredMargins = (geometry) => geometry.authoredMargins ?? {
|
|
4
|
+
top: geometry.marginTop,
|
|
5
|
+
right: geometry.marginRight,
|
|
6
|
+
bottom: geometry.marginBottom,
|
|
7
|
+
left: geometry.marginLeft
|
|
8
|
+
};
|
|
3
9
|
function resolveHorizontalBand(relativeTo, geometry) {
|
|
10
|
+
const margins = authoredMargins(geometry);
|
|
4
11
|
switch (relativeTo) {
|
|
5
12
|
case "page": return {
|
|
6
13
|
baseX: -geometry.marginLeft,
|
|
@@ -9,12 +16,12 @@ function resolveHorizontalBand(relativeTo, geometry) {
|
|
|
9
16
|
case "leftMargin":
|
|
10
17
|
case "insideMargin": return {
|
|
11
18
|
baseX: -geometry.marginLeft,
|
|
12
|
-
bandWidth:
|
|
19
|
+
bandWidth: margins.left
|
|
13
20
|
};
|
|
14
21
|
case "rightMargin":
|
|
15
22
|
case "outsideMargin": return {
|
|
16
|
-
baseX: geometry.
|
|
17
|
-
bandWidth:
|
|
23
|
+
baseX: geometry.pageWidth - geometry.marginLeft - margins.right,
|
|
24
|
+
bandWidth: margins.right
|
|
18
25
|
};
|
|
19
26
|
case "character": return {
|
|
20
27
|
baseX: 0,
|
|
@@ -27,6 +34,7 @@ function resolveHorizontalBand(relativeTo, geometry) {
|
|
|
27
34
|
}
|
|
28
35
|
}
|
|
29
36
|
function resolveVerticalBand(relativeTo, fragmentY, geometry) {
|
|
37
|
+
const margins = authoredMargins(geometry);
|
|
30
38
|
switch (relativeTo) {
|
|
31
39
|
case "page": return {
|
|
32
40
|
baseY: -geometry.marginTop,
|
|
@@ -34,11 +42,11 @@ function resolveVerticalBand(relativeTo, fragmentY, geometry) {
|
|
|
34
42
|
};
|
|
35
43
|
case "topMargin": return {
|
|
36
44
|
baseY: -geometry.marginTop,
|
|
37
|
-
bandHeight:
|
|
45
|
+
bandHeight: margins.top
|
|
38
46
|
};
|
|
39
47
|
case "bottomMargin": return {
|
|
40
|
-
baseY: geometry.
|
|
41
|
-
bandHeight:
|
|
48
|
+
baseY: geometry.pageHeight - geometry.marginTop - margins.bottom,
|
|
49
|
+
bandHeight: margins.bottom
|
|
42
50
|
};
|
|
43
51
|
case "paragraph":
|
|
44
52
|
case "line": return {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FlowBlock, Measure } from "../layout-engine/types.js";
|
|
2
|
+
import { ImageAttrs } from "../prosemirror/schema/nodes.js";
|
|
2
3
|
import { BlockLookup } from "./index.js";
|
|
3
4
|
import { WrapType } from "../docx/wrapTypes.js";
|
|
4
|
-
import { ImageAttrs } from "../prosemirror/schema/nodes.js";
|
|
5
5
|
//#region src/layout-painter/imageLayout.d.ts
|
|
6
6
|
/**
|
|
7
7
|
* Anchored wrap-type targets — the OOXML wrap types except `inline`.
|
|
@@ -797,6 +797,7 @@ function renderPage(page, context, options = {}) {
|
|
|
797
797
|
marginTop: page.margins.top,
|
|
798
798
|
marginRight: page.margins.right,
|
|
799
799
|
marginBottom: page.margins.bottom,
|
|
800
|
+
...page.authoredMargins ? { authoredMargins: page.authoredMargins } : {},
|
|
800
801
|
contentWidth,
|
|
801
802
|
contentHeight: page.size.h - page.margins.top - page.margins.bottom
|
|
802
803
|
};
|
|
@@ -1209,10 +1210,19 @@ function computePageFingerprint(page, blockLookup) {
|
|
|
1209
1210
|
function computePageRenderFingerprint(page, blockLookup) {
|
|
1210
1211
|
return computePageFingerprintInternal(page, blockLookup, { includePmPositions: false });
|
|
1211
1212
|
}
|
|
1213
|
+
const pageMarginsFingerprint = (margins) => [
|
|
1214
|
+
margins.top,
|
|
1215
|
+
margins.right,
|
|
1216
|
+
margins.bottom,
|
|
1217
|
+
margins.left,
|
|
1218
|
+
margins.header ?? "",
|
|
1219
|
+
margins.footer ?? ""
|
|
1220
|
+
].join(",");
|
|
1212
1221
|
function computePageFingerprintInternal(page, blockLookup, options) {
|
|
1213
1222
|
const parts = [];
|
|
1214
1223
|
parts.push(`s:${page.size.w},${page.size.h}`);
|
|
1215
|
-
parts.push(`m:${page.margins
|
|
1224
|
+
parts.push(`m:${pageMarginsFingerprint(page.margins)}`);
|
|
1225
|
+
if (page.authoredMargins) parts.push(`am:${pageMarginsFingerprint(page.authoredMargins)}`);
|
|
1216
1226
|
parts.push(`n:${page.number}`);
|
|
1217
1227
|
if (page.sectionIndex !== void 0) parts.push(`si:${page.sectionIndex}`);
|
|
1218
1228
|
if (page.sectionPageNumber !== void 0) parts.push(`sp:${page.sectionPageNumber}`);
|
|
@@ -2,7 +2,7 @@ import { ommlToMathml } from "../docx/mathToMathml.js";
|
|
|
2
2
|
import { parseXmlDocument } from "../docx/xmlParser.js";
|
|
3
3
|
import { evaluateFieldInstruction } from "../fields/evaluateField.js";
|
|
4
4
|
import { getListMarkerInlineWidth, getListMarkerVisualOffset } from "../layout-engine/measure/listMarkerWidth.js";
|
|
5
|
-
import "../layout-engine/measure/measureHelpers.js";
|
|
5
|
+
import { DOCX_SCRIPT_FONT_SCALE } from "../layout-engine/measure/measureHelpers.js";
|
|
6
6
|
import { FONT_KERNING_MODE, countCompressibleSpaces, getFontKerningMode, getRunFontKerningMode, toPaintedText } from "../layout-engine/measure/textMeasurementPolicy.js";
|
|
7
7
|
import { isFloatingImageRun } from "../layout-engine/types.js";
|
|
8
8
|
import { calculateTabWidth } from "../prosemirror/utils/tabCalculator.js";
|
|
@@ -76,7 +76,6 @@ function isMathRun(run) {
|
|
|
76
76
|
}
|
|
77
77
|
const AUTOMATIC_TEXT_COLOR_VALUES = /* @__PURE__ */ new Set(["auto", "windowtext"]);
|
|
78
78
|
const DEFAULT_BLACK_TEXT_COLOR_VALUES = /* @__PURE__ */ new Set(["000000", "000"]);
|
|
79
|
-
const DOCX_SUPERSCRIPT_SCALE = .75;
|
|
80
79
|
const SUGGESTION_COLOR_CSS = "var(--suggestion-color, #6d3bd6)";
|
|
81
80
|
const SUGGESTION_TINT_CSS = "var(--suggestion-bg, color-mix(in oklch, #6d3bd6 12%, transparent))";
|
|
82
81
|
const SUGGESTION_TINT_LAYER_CSS = `linear-gradient(${SUGGESTION_TINT_CSS}, ${SUGGESTION_TINT_CSS})`;
|
|
@@ -109,8 +108,8 @@ function fontSizePtToPx(fontSizePt) {
|
|
|
109
108
|
return fontSizePt * 96 / 72;
|
|
110
109
|
}
|
|
111
110
|
function getRaisedRunFontSize(run) {
|
|
112
|
-
if (run.fontSize) return `${fontSizePtToPx(run.fontSize) *
|
|
113
|
-
return `${
|
|
111
|
+
if (run.fontSize) return `${fontSizePtToPx(run.fontSize) * DOCX_SCRIPT_FONT_SCALE}px`;
|
|
112
|
+
return `${DOCX_SCRIPT_FONT_SCALE}em`;
|
|
114
113
|
}
|
|
115
114
|
/**
|
|
116
115
|
* Apply text run styles to an element
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Subscribable } from "./Subscribable.js";
|
|
2
|
+
import { decodeAutoSaveEnvelope, encodeAutoSaveDocument, encodeAutoSaveEnvelopeFromDocument } from "./autoSaveCodec.js";
|
|
2
3
|
//#region src/managers/AutoSaveManager.ts
|
|
3
4
|
const DEFAULT_STORAGE_KEY = "docx-editor-autosave";
|
|
4
5
|
const DEFAULT_INTERVAL = 3e4;
|
|
5
6
|
const DEFAULT_MAX_AGE = 1440 * 60 * 1e3;
|
|
6
7
|
const DEFAULT_DEBOUNCE_DELAY = 2e3;
|
|
7
|
-
const SAVE_VERSION = 1;
|
|
8
8
|
function isLocalStorageAvailable() {
|
|
9
9
|
try {
|
|
10
10
|
const testKey = "__docx_editor_test__";
|
|
@@ -16,31 +16,7 @@ function isLocalStorageAvailable() {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
function serializeForStorage(document) {
|
|
19
|
-
return
|
|
20
|
-
...document,
|
|
21
|
-
originalBuffer: null
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
function isDocumentLike(value) {
|
|
25
|
-
return typeof value === "object" && value !== null && "package" in value;
|
|
26
|
-
}
|
|
27
|
-
function parseSavedData(json) {
|
|
28
|
-
let parsed;
|
|
29
|
-
try {
|
|
30
|
-
parsed = JSON.parse(json);
|
|
31
|
-
} catch {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
if (typeof parsed !== "object" || parsed === null) return null;
|
|
35
|
-
if (!("document" in parsed) || !("savedAt" in parsed) || !("version" in parsed)) return null;
|
|
36
|
-
const { document, savedAt, version } = parsed;
|
|
37
|
-
if (typeof savedAt !== "string" || typeof version !== "number") return null;
|
|
38
|
-
if (!isDocumentLike(document)) return null;
|
|
39
|
-
return {
|
|
40
|
-
document,
|
|
41
|
-
savedAt,
|
|
42
|
-
version
|
|
43
|
-
};
|
|
19
|
+
return encodeAutoSaveDocument(document);
|
|
44
20
|
}
|
|
45
21
|
function isStale(savedAt, maxAge) {
|
|
46
22
|
const savedTime = new Date(savedAt).getTime();
|
|
@@ -99,12 +75,12 @@ var AutoSaveManager = class extends Subscribable {
|
|
|
99
75
|
this.updateStatus("saving");
|
|
100
76
|
try {
|
|
101
77
|
const serialized = serializeForStorage(doc);
|
|
102
|
-
if (serialized === this.lastSavedJson) {
|
|
78
|
+
if (serialized.json === this.lastSavedJson) {
|
|
103
79
|
this.updateStatus("saved");
|
|
104
80
|
return true;
|
|
105
81
|
}
|
|
106
|
-
this.persistToStorage(
|
|
107
|
-
this.lastSavedJson = serialized;
|
|
82
|
+
this.persistToStorage(serialized);
|
|
83
|
+
this.lastSavedJson = serialized.json;
|
|
108
84
|
const saveTime = /* @__PURE__ */ new Date();
|
|
109
85
|
this.lastSaveTime = saveTime;
|
|
110
86
|
this.updateStatus("saved");
|
|
@@ -133,7 +109,7 @@ var AutoSaveManager = class extends Subscribable {
|
|
|
133
109
|
if (!this.storageAvailable) return null;
|
|
134
110
|
const savedJson = localStorage.getItem(this.storageKey);
|
|
135
111
|
if (!savedJson) return null;
|
|
136
|
-
const savedData =
|
|
112
|
+
const savedData = decodeAutoSaveEnvelope(savedJson);
|
|
137
113
|
if (!savedData) return null;
|
|
138
114
|
if (isStale(savedData.savedAt, this.maxAge)) {
|
|
139
115
|
this.clear();
|
|
@@ -179,7 +155,7 @@ var AutoSaveManager = class extends Subscribable {
|
|
|
179
155
|
destroy() {
|
|
180
156
|
this.stopTimers();
|
|
181
157
|
if (this.isEnabled && this.currentDocument && this.storageAvailable) try {
|
|
182
|
-
this.persistToStorage(this.currentDocument);
|
|
158
|
+
this.persistToStorage(serializeForStorage(this.currentDocument));
|
|
183
159
|
} catch (error) {
|
|
184
160
|
this.onErrorCallback?.(error instanceof Error ? error : new Error(String(error)));
|
|
185
161
|
}
|
|
@@ -194,15 +170,7 @@ var AutoSaveManager = class extends Subscribable {
|
|
|
194
170
|
}
|
|
195
171
|
}
|
|
196
172
|
persistToStorage(document) {
|
|
197
|
-
|
|
198
|
-
document: {
|
|
199
|
-
...document,
|
|
200
|
-
originalBuffer: null
|
|
201
|
-
},
|
|
202
|
-
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
203
|
-
version: SAVE_VERSION
|
|
204
|
-
};
|
|
205
|
-
localStorage.setItem(this.storageKey, JSON.stringify(dataToSave));
|
|
173
|
+
localStorage.setItem(this.storageKey, encodeAutoSaveEnvelopeFromDocument(document, (/* @__PURE__ */ new Date()).toISOString()));
|
|
206
174
|
}
|
|
207
175
|
debounceSave() {
|
|
208
176
|
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { TableAction, TableContext } from "../utils/tableOperations.js";
|
|
2
3
|
import { Subscribable } from "./Subscribable.js";
|
|
3
4
|
import { CellCoordinates } from "./types.js";
|
|
4
|
-
import { TableAction, TableContext } from "../utils/tableOperations.js";
|
|
5
5
|
//#region src/managers/TableSelectionManager.d.ts
|
|
6
6
|
/** Data attributes for table elements in the rendered DOM */
|
|
7
7
|
declare const TABLE_DATA_ATTRIBUTES: {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
//#region src/managers/autoSaveCodec.d.ts
|
|
3
|
+
declare const AUTOSAVE_FORMAT_VERSION = 2;
|
|
4
|
+
type DecodedAutoSave = {
|
|
5
|
+
document: document_d_exports.Document;
|
|
6
|
+
savedAt: string;
|
|
7
|
+
version: typeof AUTOSAVE_FORMAT_VERSION;
|
|
8
|
+
};
|
|
9
|
+
type EncodedAutoSaveDocument = {
|
|
10
|
+
json: string;
|
|
11
|
+
};
|
|
12
|
+
declare const encodeAutoSaveDocument: (document: document_d_exports.Document) => EncodedAutoSaveDocument;
|
|
13
|
+
declare const encodeAutoSaveEnvelopeFromDocument: (document: EncodedAutoSaveDocument, savedAt: string) => string;
|
|
14
|
+
declare const encodeAutoSaveEnvelope: (document: document_d_exports.Document, savedAt: string) => string;
|
|
15
|
+
declare const decodeAutoSaveEnvelope: (json: string) => DecodedAutoSave | null;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { AUTOSAVE_FORMAT_VERSION, DecodedAutoSave, EncodedAutoSaveDocument, decodeAutoSaveEnvelope, encodeAutoSaveDocument, encodeAutoSaveEnvelope, encodeAutoSaveEnvelopeFromDocument };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { validateFolioDocumentModel } from "../docx/modelValidation.js";
|
|
2
|
+
//#region src/managers/autoSaveCodec.ts
|
|
3
|
+
const AUTOSAVE_FORMAT_VERSION = 2;
|
|
4
|
+
const BASE64_CHUNK_BYTES = 32768;
|
|
5
|
+
const encodeBase64 = (buffer) => {
|
|
6
|
+
const bytes = new Uint8Array(buffer);
|
|
7
|
+
const chunks = [];
|
|
8
|
+
for (let offset = 0; offset < bytes.length; offset += BASE64_CHUNK_BYTES) chunks.push(String.fromCharCode(...bytes.subarray(offset, offset + BASE64_CHUNK_BYTES)));
|
|
9
|
+
return btoa(chunks.join(""));
|
|
10
|
+
};
|
|
11
|
+
const decodeBase64 = (value) => {
|
|
12
|
+
const binary = atob(value);
|
|
13
|
+
const bytes = new Uint8Array(binary.length);
|
|
14
|
+
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
15
|
+
return bytes.buffer;
|
|
16
|
+
};
|
|
17
|
+
const encodeValue = (value) => {
|
|
18
|
+
if (value === void 0) return { type: "undefined" };
|
|
19
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
|
|
20
|
+
if (value instanceof Date) return {
|
|
21
|
+
type: "date",
|
|
22
|
+
value: value.toISOString()
|
|
23
|
+
};
|
|
24
|
+
if (value instanceof ArrayBuffer) return {
|
|
25
|
+
type: "arrayBuffer",
|
|
26
|
+
value: encodeBase64(value)
|
|
27
|
+
};
|
|
28
|
+
if (value instanceof Map) return {
|
|
29
|
+
type: "map",
|
|
30
|
+
value: [...value.entries()].map(([key, entry]) => [encodeValue(key), encodeValue(entry)])
|
|
31
|
+
};
|
|
32
|
+
if (Array.isArray(value)) return {
|
|
33
|
+
type: "array",
|
|
34
|
+
value: value.map(encodeValue)
|
|
35
|
+
};
|
|
36
|
+
if (typeof value === "object") {
|
|
37
|
+
const encoded = {};
|
|
38
|
+
for (const [key, entry] of Object.entries(value)) encoded[key] = encodeValue(entry);
|
|
39
|
+
return {
|
|
40
|
+
type: "object",
|
|
41
|
+
value: encoded
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
throw new TypeError(`Unsupported auto-save value: ${typeof value}`);
|
|
45
|
+
};
|
|
46
|
+
const decodeValue = (value) => {
|
|
47
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
|
|
48
|
+
if (typeof value !== "object" || !value || !("type" in value)) throw new TypeError("Invalid auto-save encoded value");
|
|
49
|
+
const type = value.type;
|
|
50
|
+
if (type === "undefined") return;
|
|
51
|
+
if (type === "date") {
|
|
52
|
+
if (!("value" in value) || typeof value.value !== "string" || !Number.isFinite(Date.parse(value.value))) throw new TypeError("Invalid auto-save date");
|
|
53
|
+
return new Date(value.value);
|
|
54
|
+
}
|
|
55
|
+
if (type === "arrayBuffer") {
|
|
56
|
+
if (!("value" in value) || typeof value.value !== "string") throw new TypeError("Invalid auto-save binary data");
|
|
57
|
+
return decodeBase64(value.value);
|
|
58
|
+
}
|
|
59
|
+
if (type === "array") {
|
|
60
|
+
if (!("value" in value) || !Array.isArray(value.value)) throw new TypeError("Invalid auto-save array");
|
|
61
|
+
return value.value.map(decodeValue);
|
|
62
|
+
}
|
|
63
|
+
if (type === "map") {
|
|
64
|
+
if (!("value" in value) || !Array.isArray(value.value)) throw new TypeError("Invalid auto-save map");
|
|
65
|
+
return new Map(value.value.map((entry) => {
|
|
66
|
+
if (!Array.isArray(entry) || entry.length !== 2) throw new TypeError("Invalid auto-save map entry");
|
|
67
|
+
return [decodeValue(entry[0]), decodeValue(entry[1])];
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
if (type === "object") {
|
|
71
|
+
if (!("value" in value) || typeof value.value !== "object" || !value.value) throw new TypeError("Invalid auto-save object");
|
|
72
|
+
const decoded = Object.create(null);
|
|
73
|
+
for (const [key, entry] of Object.entries(value.value)) {
|
|
74
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") throw new TypeError("Invalid auto-save object key");
|
|
75
|
+
const decodedEntry = decodeValue(entry);
|
|
76
|
+
if (decodedEntry !== void 0) decoded[key] = decodedEntry;
|
|
77
|
+
}
|
|
78
|
+
return decoded;
|
|
79
|
+
}
|
|
80
|
+
throw new TypeError("Unknown auto-save encoded value");
|
|
81
|
+
};
|
|
82
|
+
const encodeAutoSaveDocument = (document) => {
|
|
83
|
+
const snapshot = {
|
|
84
|
+
...document,
|
|
85
|
+
originalBuffer: null
|
|
86
|
+
};
|
|
87
|
+
return { json: JSON.stringify(encodeValue(snapshot)) };
|
|
88
|
+
};
|
|
89
|
+
const encodeAutoSaveEnvelopeFromDocument = (document, savedAt) => `{"document":${document.json},"savedAt":${JSON.stringify(savedAt)},"version":2}`;
|
|
90
|
+
const encodeAutoSaveEnvelope = (document, savedAt) => encodeAutoSaveEnvelopeFromDocument(encodeAutoSaveDocument(document), savedAt);
|
|
91
|
+
const decodeAutoSaveEnvelope = (json) => {
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(json);
|
|
94
|
+
if (typeof parsed !== "object" || !parsed || !("document" in parsed) || !("savedAt" in parsed) || !("version" in parsed)) return null;
|
|
95
|
+
if (parsed.version !== 2 || typeof parsed.savedAt !== "string" || !Number.isFinite(Date.parse(parsed.savedAt))) return null;
|
|
96
|
+
const document = decodeValue(parsed.document);
|
|
97
|
+
if (typeof document !== "object" || !document) return null;
|
|
98
|
+
if (!validateFolioDocumentModel(document).valid) return null;
|
|
99
|
+
return {
|
|
100
|
+
document,
|
|
101
|
+
savedAt: parsed.savedAt,
|
|
102
|
+
version: 2
|
|
103
|
+
};
|
|
104
|
+
} catch {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
//#endregion
|
|
109
|
+
export { AUTOSAVE_FORMAT_VERSION, decodeAutoSaveEnvelope, encodeAutoSaveDocument, encodeAutoSaveEnvelope, encodeAutoSaveEnvelopeFromDocument };
|