fabricjs-document-engine 1.1.0 → 1.3.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/README.md +70 -1
- package/README.zh-CN.md +71 -1
- package/dist/assets/asset-pipeline.cjs +10 -8
- package/dist/assets/asset-pipeline.d.cts +1 -1
- package/dist/assets/asset-pipeline.d.ts +1 -1
- package/dist/assets/asset-pipeline.js +10 -8
- package/dist/assets/image-check.cjs +4 -3
- package/dist/assets/image-check.d.cts +1 -1
- package/dist/assets/image-check.d.ts +1 -1
- package/dist/assets/image-check.js +4 -3
- package/dist/commands/clipboard.cjs +5 -0
- package/dist/commands/clipboard.js +5 -0
- package/dist/commands/text-edit.cjs +223 -0
- package/dist/commands/text-edit.d.cts +23 -0
- package/dist/commands/text-edit.d.ts +23 -0
- package/dist/commands/text-edit.js +218 -0
- package/dist/document/document-format.d.cts +15 -0
- package/dist/document/document-format.d.ts +15 -0
- package/dist/document/validate-document.cjs +8 -0
- package/dist/document/validate-document.js +8 -0
- package/dist/engine/create-document-engine.cjs +115 -21
- package/dist/engine/create-document-engine.d.cts +24 -6
- package/dist/engine/create-document-engine.d.ts +24 -6
- package/dist/engine/create-document-engine.js +116 -22
- package/dist/engine/errors.d.cts +1 -1
- package/dist/engine/errors.d.ts +1 -1
- package/dist/export/export-options.cjs +3 -0
- package/dist/export/export-options.d.cts +6 -0
- package/dist/export/export-options.d.ts +6 -0
- package/dist/export/export-options.js +3 -0
- package/dist/export/preflight-export.d.cts +1 -1
- package/dist/export/preflight-export.d.ts +1 -1
- package/dist/export/render-export.cjs +42 -4
- package/dist/export/render-export.js +43 -5
- package/dist/export/svg/clip-masks.cjs +39 -0
- package/dist/export/svg/clip-masks.js +37 -0
- package/dist/export/svg/embed-assets.cjs +1 -0
- package/dist/export/svg/embed-assets.js +1 -0
- package/dist/export/svg/raster-object.cjs +82 -0
- package/dist/export/svg/raster-object.js +81 -0
- package/dist/{pdf → export/svg}/text-decorations.cjs +3 -3
- package/dist/{pdf → export/svg}/text-decorations.js +3 -3
- package/dist/export/svg/text-on-path.cjs +0 -10
- package/dist/export/svg/text-on-path.js +1 -10
- package/dist/fabric/fabric-adapter.cjs +5 -3
- package/dist/fabric/fabric-adapter.js +5 -3
- package/dist/fabric/object-registry.cjs +7 -1
- package/dist/fabric/object-registry.js +7 -1
- package/dist/fabric/page-state.cjs +69 -0
- package/dist/fabric/page-state.js +64 -0
- package/dist/filters/filter-worker.cjs +281 -0
- package/dist/filters/filter-worker.d.cts +26 -0
- package/dist/filters/filter-worker.d.ts +26 -0
- package/dist/filters/filter-worker.js +281 -0
- package/dist/filters/pipeline.cjs +91 -0
- package/dist/filters/pipeline.d.cts +35 -0
- package/dist/filters/pipeline.d.ts +35 -0
- package/dist/filters/pipeline.js +87 -0
- package/dist/filters/worker-entry.cjs +78 -0
- package/dist/filters/worker-entry.d.cts +29 -0
- package/dist/filters/worker-entry.d.ts +29 -0
- package/dist/filters/worker-entry.js +78 -0
- package/dist/filters.cjs +9 -0
- package/dist/filters.d.cts +3 -0
- package/dist/filters.d.ts +3 -0
- package/dist/filters.js +3 -0
- package/dist/history/apply-state.cjs +19 -2
- package/dist/history/apply-state.js +19 -2
- package/dist/history/create-history.cjs +53 -13
- package/dist/history/create-history.d.cts +8 -0
- package/dist/history/create-history.d.ts +8 -0
- package/dist/history/create-history.js +53 -13
- package/dist/history/snapshot.cjs +10 -1
- package/dist/history/snapshot.js +10 -2
- package/dist/import/svg-import.cjs +102 -0
- package/dist/import/svg-import.d.cts +1 -0
- package/dist/import/svg-import.d.ts +1 -0
- package/dist/import/svg-import.js +103 -1
- package/dist/index.cjs +7 -0
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -1
- package/dist/migrations/migrate-document.cjs +2 -1
- package/dist/migrations/migrate-document.js +2 -1
- package/dist/pdf/export-pdf.cjs +8 -67
- package/dist/pdf/export-pdf.js +8 -67
- package/dist/performance/batch.cjs +31 -0
- package/dist/performance/batch.d.cts +4 -0
- package/dist/performance/batch.d.ts +4 -0
- package/dist/performance/batch.js +31 -0
- package/dist/performance/dirty-regions.cjs +378 -0
- package/dist/performance/dirty-regions.d.cts +23 -0
- package/dist/performance/dirty-regions.d.ts +23 -0
- package/dist/performance/dirty-regions.js +378 -0
- package/dist/performance/monitor.cjs +60 -0
- package/dist/performance/monitor.d.cts +20 -0
- package/dist/performance/monitor.d.ts +20 -0
- package/dist/performance/monitor.js +60 -0
- package/dist/performance/spatial-index.cjs +78 -0
- package/dist/performance/spatial-index.d.cts +21 -0
- package/dist/performance/spatial-index.d.ts +21 -0
- package/dist/performance/spatial-index.js +78 -0
- package/dist/performance.cjs +9 -0
- package/dist/performance.d.cts +5 -0
- package/dist/performance.d.ts +5 -0
- package/dist/performance.js +5 -0
- package/dist/recovery/recovery-controller.cjs +148 -29
- package/dist/recovery/recovery-controller.d.cts +8 -0
- package/dist/recovery/recovery-controller.d.ts +8 -0
- package/dist/recovery/recovery-controller.js +148 -29
- package/dist/security/content-limits.cjs +43 -3
- package/dist/security/content-limits.d.cts +8 -0
- package/dist/security/content-limits.d.ts +8 -0
- package/dist/security/content-limits.js +39 -4
- package/dist/text/bounded-textbox.cjs +306 -0
- package/dist/text/bounded-textbox.d.cts +53 -0
- package/dist/text/bounded-textbox.d.ts +53 -0
- package/dist/text/bounded-textbox.js +306 -0
- package/dist/text/mobile-input.cjs +146 -0
- package/dist/text/mobile-input.d.cts +19 -0
- package/dist/text/mobile-input.d.ts +19 -0
- package/dist/text/mobile-input.js +145 -0
- package/dist/text/register.cjs +17 -0
- package/dist/text/register.d.cts +5 -0
- package/dist/text/register.d.ts +5 -0
- package/dist/text/register.js +16 -0
- package/dist/text/shaping.cjs +125 -0
- package/dist/text/shaping.d.cts +28 -0
- package/dist/text/shaping.d.ts +28 -0
- package/dist/text/shaping.js +121 -0
- package/dist/text/vertical-orientation.cjs +192 -0
- package/dist/text/vertical-orientation.d.cts +10 -0
- package/dist/text/vertical-orientation.d.ts +10 -0
- package/dist/text/vertical-orientation.js +190 -0
- package/dist/text/vertical-text.cjs +336 -0
- package/dist/text/vertical-text.d.cts +54 -0
- package/dist/text/vertical-text.d.ts +54 -0
- package/dist/text/vertical-text.js +336 -0
- package/dist/text.cjs +21 -0
- package/dist/text.d.cts +7 -0
- package/dist/text.d.ts +7 -0
- package/dist/text.js +7 -0
- package/dist/util/concurrency.cjs +16 -3
- package/dist/util/concurrency.js +16 -3
- package/package.json +31 -1
- package/schema/document-v1.schema.json +5 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { createSnapshot, diffSnapshots } from "./snapshot.js";
|
|
1
2
|
import { applyStateChange } from "./apply-state.js";
|
|
2
3
|
import { createHistoryStack } from "./history-stack.js";
|
|
3
|
-
import { createSnapshot, diffSnapshots } from "./snapshot.js";
|
|
4
4
|
//#region src/history/create-history.ts
|
|
5
5
|
const verbsByAction = {
|
|
6
6
|
drag: "Move",
|
|
@@ -24,18 +24,23 @@ function describePendingChanges(changes) {
|
|
|
24
24
|
return changes.length === 1 ? `${verb} ${changes[0].noun}` : `${verb} ${changes.length} objects`;
|
|
25
25
|
}
|
|
26
26
|
function createHistory(options) {
|
|
27
|
-
const { canvas,
|
|
27
|
+
const { canvas, serializeState, onChange, onContentChange, onLiveChange } = options;
|
|
28
|
+
const takeSnapshot = () => {
|
|
29
|
+
const { objects, page } = serializeState();
|
|
30
|
+
return createSnapshot(objects, page);
|
|
31
|
+
};
|
|
28
32
|
const stack = createHistoryStack({
|
|
29
33
|
steps: Math.max(1, options.limit ?? 100),
|
|
30
34
|
bytes: Math.max(0, options.maxBytes ?? 67108864)
|
|
31
35
|
});
|
|
32
|
-
let snapshot =
|
|
36
|
+
let snapshot = takeSnapshot();
|
|
33
37
|
let pendingChanges = [];
|
|
34
38
|
let flushScheduled = false;
|
|
35
39
|
let transactionDepth = 0;
|
|
36
40
|
let pausedDepth = 0;
|
|
37
41
|
let applying = false;
|
|
38
42
|
let queue = Promise.resolve();
|
|
43
|
+
let epoch = 0;
|
|
39
44
|
function state() {
|
|
40
45
|
const undoLabels = stack.undoLabels();
|
|
41
46
|
const redoLabels = stack.redoLabels();
|
|
@@ -48,7 +53,7 @@ function createHistory(options) {
|
|
|
48
53
|
}
|
|
49
54
|
function commit(label) {
|
|
50
55
|
pendingChanges = [];
|
|
51
|
-
const nextSnapshot =
|
|
56
|
+
const nextSnapshot = takeSnapshot();
|
|
52
57
|
const difference = diffSnapshots(snapshot, nextSnapshot);
|
|
53
58
|
snapshot = nextSnapshot;
|
|
54
59
|
if (difference === null) return false;
|
|
@@ -86,26 +91,56 @@ function createHistory(options) {
|
|
|
86
91
|
notice(verbsByAction[action] ?? "Transform", event.target);
|
|
87
92
|
};
|
|
88
93
|
const handleTextEdited = ({ target }) => notice("Edit", target);
|
|
94
|
+
const handleTextChanged = () => {
|
|
95
|
+
if (!applying && pausedDepth === 0) onLiveChange?.();
|
|
96
|
+
};
|
|
89
97
|
const listeners = [
|
|
90
98
|
["object:added", handleAdded],
|
|
91
99
|
["object:removed", handleRemoved],
|
|
92
100
|
["object:modified", handleModified],
|
|
93
|
-
["text:editing:exited", handleTextEdited]
|
|
101
|
+
["text:editing:exited", handleTextEdited],
|
|
102
|
+
["text:changed", handleTextChanged]
|
|
94
103
|
];
|
|
95
104
|
const eventTarget = canvas;
|
|
96
105
|
listeners.forEach(([name, handler]) => eventTarget.on(name, handler));
|
|
97
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Puts the canvas back to the last recorded snapshot. The snapshot is the
|
|
108
|
+
* state before the transaction, so the difference to undo is exactly what
|
|
109
|
+
* the transaction changed: one serialization, then only the changed
|
|
110
|
+
* objects are rebuilt.
|
|
111
|
+
*/
|
|
112
|
+
function rollBack() {
|
|
113
|
+
const difference = diffSnapshots(snapshot, takeSnapshot());
|
|
114
|
+
pendingChanges = [];
|
|
115
|
+
if (difference === null) return Promise.resolve();
|
|
116
|
+
applying = true;
|
|
117
|
+
return runInOrder(async () => {
|
|
118
|
+
try {
|
|
119
|
+
await applyStateChange(canvas, difference.before);
|
|
120
|
+
} finally {
|
|
121
|
+
applying = false;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function transaction(label, work, transactionOptions = {}) {
|
|
98
126
|
if (transactionDepth === 0) commitPendingChanges();
|
|
127
|
+
const outermost = transactionDepth === 0;
|
|
99
128
|
transactionDepth += 1;
|
|
100
129
|
const finish = () => {
|
|
101
130
|
transactionDepth -= 1;
|
|
102
131
|
if (transactionDepth === 0) commit(label);
|
|
103
132
|
};
|
|
133
|
+
const fail = () => {
|
|
134
|
+
transactionDepth -= 1;
|
|
135
|
+
if (transactionDepth > 0) return void 0;
|
|
136
|
+
if (outermost && transactionOptions.rollback) return rollBack();
|
|
137
|
+
commit(label);
|
|
138
|
+
};
|
|
104
139
|
let result;
|
|
105
140
|
try {
|
|
106
141
|
result = work();
|
|
107
142
|
} catch (error) {
|
|
108
|
-
|
|
143
|
+
fail()?.catch(() => void 0);
|
|
109
144
|
throw error;
|
|
110
145
|
}
|
|
111
146
|
if (!isPromiseLike(result)) {
|
|
@@ -115,8 +150,8 @@ function createHistory(options) {
|
|
|
115
150
|
return Promise.resolve(result).then((value) => {
|
|
116
151
|
finish();
|
|
117
152
|
return value;
|
|
118
|
-
}, (error) => {
|
|
119
|
-
|
|
153
|
+
}, async (error) => {
|
|
154
|
+
await fail();
|
|
120
155
|
throw error;
|
|
121
156
|
});
|
|
122
157
|
}
|
|
@@ -148,16 +183,19 @@ function createHistory(options) {
|
|
|
148
183
|
commitPendingChanges();
|
|
149
184
|
const step = takeStep();
|
|
150
185
|
if (step === void 0) return false;
|
|
186
|
+
const startedIn = epoch;
|
|
151
187
|
applying = true;
|
|
188
|
+
let applied;
|
|
152
189
|
try {
|
|
153
|
-
await applyStateChange(canvas, pickChange(step));
|
|
190
|
+
applied = await applyStateChange(canvas, pickChange(step), () => epoch !== startedIn);
|
|
154
191
|
} catch (error) {
|
|
155
|
-
putBack(step);
|
|
192
|
+
if (epoch === startedIn) putBack(step);
|
|
156
193
|
throw error;
|
|
157
194
|
} finally {
|
|
158
195
|
applying = false;
|
|
159
196
|
}
|
|
160
|
-
|
|
197
|
+
if (!applied) return false;
|
|
198
|
+
snapshot = takeSnapshot();
|
|
161
199
|
moveTo(step);
|
|
162
200
|
onContentChange();
|
|
163
201
|
onChange(state());
|
|
@@ -170,6 +208,7 @@ function createHistory(options) {
|
|
|
170
208
|
return commit(label);
|
|
171
209
|
},
|
|
172
210
|
transaction,
|
|
211
|
+
settled: () => queue.then(() => void 0),
|
|
173
212
|
undo: () => travel(() => stack.takeUndo(), (step) => step.before, (step) => stack.returnUndo(step), (step) => stack.returnRedo(step)),
|
|
174
213
|
redo: () => travel(() => stack.takeRedo(), (step) => step.after, (step) => stack.returnRedo(step), (step) => stack.returnUndo(step)),
|
|
175
214
|
state,
|
|
@@ -182,7 +221,8 @@ function createHistory(options) {
|
|
|
182
221
|
reset() {
|
|
183
222
|
pendingChanges = [];
|
|
184
223
|
stack.clear();
|
|
185
|
-
|
|
224
|
+
epoch += 1;
|
|
225
|
+
snapshot = takeSnapshot();
|
|
186
226
|
onChange(state());
|
|
187
227
|
},
|
|
188
228
|
destroy() {
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
//#region src/history/snapshot.ts
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* The page itself (size, background, overlay, mask) is one more entry in the
|
|
4
|
+
* same map under this reserved key. It never appears in `order`, so the
|
|
5
|
+
* diff stays proportional to what changed and object ordering is unaffected.
|
|
6
|
+
* Object ids come from `createId`, which never produces this value.
|
|
7
|
+
*/
|
|
8
|
+
const PAGE_KEY = "__page__";
|
|
9
|
+
function createSnapshot(objects, page) {
|
|
3
10
|
const objectsById = /* @__PURE__ */ new Map();
|
|
4
11
|
const order = [];
|
|
12
|
+
if (page !== void 0) objectsById.set(PAGE_KEY, JSON.stringify(page));
|
|
5
13
|
for (const object of objects) {
|
|
6
14
|
const id = object.id ?? "";
|
|
7
15
|
objectsById.set(id, JSON.stringify(object));
|
|
@@ -43,5 +51,6 @@ function diffSnapshots(previous, next) {
|
|
|
43
51
|
};
|
|
44
52
|
}
|
|
45
53
|
//#endregion
|
|
54
|
+
exports.PAGE_KEY = PAGE_KEY;
|
|
46
55
|
exports.createSnapshot = createSnapshot;
|
|
47
56
|
exports.diffSnapshots = diffSnapshots;
|
package/dist/history/snapshot.js
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
//#region src/history/snapshot.ts
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* The page itself (size, background, overlay, mask) is one more entry in the
|
|
4
|
+
* same map under this reserved key. It never appears in `order`, so the
|
|
5
|
+
* diff stays proportional to what changed and object ordering is unaffected.
|
|
6
|
+
* Object ids come from `createId`, which never produces this value.
|
|
7
|
+
*/
|
|
8
|
+
const PAGE_KEY = "__page__";
|
|
9
|
+
function createSnapshot(objects, page) {
|
|
3
10
|
const objectsById = /* @__PURE__ */ new Map();
|
|
4
11
|
const order = [];
|
|
12
|
+
if (page !== void 0) objectsById.set(PAGE_KEY, JSON.stringify(page));
|
|
5
13
|
for (const object of objects) {
|
|
6
14
|
const id = object.id ?? "";
|
|
7
15
|
objectsById.set(id, JSON.stringify(object));
|
|
@@ -43,4 +51,4 @@ function diffSnapshots(previous, next) {
|
|
|
43
51
|
};
|
|
44
52
|
}
|
|
45
53
|
//#endregion
|
|
46
|
-
export { createSnapshot, diffSnapshots };
|
|
54
|
+
export { PAGE_KEY, createSnapshot, diffSnapshots };
|
|
@@ -127,12 +127,110 @@ function contentBounds(objects) {
|
|
|
127
127
|
height: 0
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
+
function dropBrokenUses(document) {
|
|
131
|
+
for (const use of Array.from(document.getElementsByTagName("use"))) {
|
|
132
|
+
const link = (use.getAttribute("href") ?? use.getAttributeNS(XLINK, "href") ?? "").trim();
|
|
133
|
+
if (!link.startsWith("#") || link.length === 1 || document.getElementById(link.slice(1)) === null) use.remove();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const GROUP_MARK = "data-fde-svg-group";
|
|
137
|
+
function markGroups(document) {
|
|
138
|
+
for (const name of ["g", "a"]) for (const element of Array.from(document.documentElement.getElementsByTagName(name))) element.setAttribute(GROUP_MARK, "");
|
|
139
|
+
}
|
|
140
|
+
function svgMetadata(element) {
|
|
141
|
+
const metadata = {};
|
|
142
|
+
const id = element.getAttribute("id");
|
|
143
|
+
if (id) metadata.svgId = id;
|
|
144
|
+
const className = element.getAttribute("class");
|
|
145
|
+
if (className) metadata.svgClass = className;
|
|
146
|
+
for (const attribute of Array.from(element.attributes)) {
|
|
147
|
+
if (!attribute.name.startsWith("data-") || attribute.name === GROUP_MARK) continue;
|
|
148
|
+
(metadata.svgData ?? (metadata.svgData = {}))[attribute.name.slice(5)] = attribute.value;
|
|
149
|
+
}
|
|
150
|
+
return metadata;
|
|
151
|
+
}
|
|
152
|
+
function ownOpacity(element) {
|
|
153
|
+
const fromStyle = /(?:^|;)\s*opacity\s*:\s*([0-9.]+)/.exec(element.getAttribute("style") ?? "")?.[1];
|
|
154
|
+
const value = Number.parseFloat(fromStyle ?? element.getAttribute("opacity") ?? "1");
|
|
155
|
+
return Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : 1;
|
|
156
|
+
}
|
|
157
|
+
function rebuildGroups(objects, elements, root) {
|
|
158
|
+
const top = [];
|
|
159
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
160
|
+
const groupNodes = /* @__PURE__ */ new Set();
|
|
161
|
+
const chains = /* @__PURE__ */ new Map();
|
|
162
|
+
const elementOf = /* @__PURE__ */ new Map();
|
|
163
|
+
objects.forEach((object, index) => {
|
|
164
|
+
const element = elements[index];
|
|
165
|
+
elementOf.set(object, element);
|
|
166
|
+
const chain = [];
|
|
167
|
+
for (let parent = element.parentElement; parent && parent !== root; parent = parent.parentElement) if (parent.hasAttribute(GROUP_MARK)) chain.push(parent);
|
|
168
|
+
chains.set(object, chain);
|
|
169
|
+
let children = top;
|
|
170
|
+
for (let level = chain.length - 1; level >= 0; level -= 1) {
|
|
171
|
+
const groupElement = chain[level];
|
|
172
|
+
let node = nodes.get(groupElement);
|
|
173
|
+
if (!node) {
|
|
174
|
+
node = {
|
|
175
|
+
element: groupElement,
|
|
176
|
+
children: []
|
|
177
|
+
};
|
|
178
|
+
nodes.set(groupElement, node);
|
|
179
|
+
groupNodes.add(node);
|
|
180
|
+
children.push(node);
|
|
181
|
+
}
|
|
182
|
+
children = node.children;
|
|
183
|
+
}
|
|
184
|
+
children.push(object);
|
|
185
|
+
const own = element.getAttribute("id");
|
|
186
|
+
const leaf = object;
|
|
187
|
+
if (!own && chain.length > 0 && leaf.id !== void 0) delete leaf.id;
|
|
188
|
+
const inherited = chain.reduce((product, groupElement) => product * ownOpacity(groupElement), 1);
|
|
189
|
+
if (inherited > 0) object.opacity = Math.min(1, object.opacity / inherited);
|
|
190
|
+
object.set(svgMetadata(element));
|
|
191
|
+
});
|
|
192
|
+
const hoistClip = (node, group) => {
|
|
193
|
+
if (!node.element.hasAttribute("clip-path")) return;
|
|
194
|
+
let clip;
|
|
195
|
+
for (const object of objects) {
|
|
196
|
+
const chain = chains.get(object);
|
|
197
|
+
const at = chain.indexOf(node.element);
|
|
198
|
+
if (at === -1) continue;
|
|
199
|
+
if (elementOf.get(object).hasAttribute("clip-path") || chain.slice(0, at).some((between) => between.hasAttribute("clip-path")) || !object.clipPath) continue;
|
|
200
|
+
if (!clip) {
|
|
201
|
+
const absolute = fabric.util.multiplyTransformMatrices(object.calcTransformMatrix(), object.clipPath.calcTransformMatrix());
|
|
202
|
+
clip = object.clipPath;
|
|
203
|
+
fabric.util.applyTransformToObject(clip, fabric.util.multiplyTransformMatrices(fabric.util.invertTransform(group.calcTransformMatrix()), absolute));
|
|
204
|
+
}
|
|
205
|
+
object.clipPath = void 0;
|
|
206
|
+
object.set("dirty", true);
|
|
207
|
+
}
|
|
208
|
+
if (clip) group.clipPath = clip;
|
|
209
|
+
};
|
|
210
|
+
const build = (item) => {
|
|
211
|
+
if (!groupNodes.has(item)) return item;
|
|
212
|
+
const node = item;
|
|
213
|
+
const group = new fabric.Group(node.children.map(build));
|
|
214
|
+
group.set({
|
|
215
|
+
opacity: ownOpacity(node.element),
|
|
216
|
+
...svgMetadata(node.element)
|
|
217
|
+
});
|
|
218
|
+
const id = node.element.getAttribute("id");
|
|
219
|
+
if (id) group.id = id;
|
|
220
|
+
hoistClip(node, group);
|
|
221
|
+
group.setCoords();
|
|
222
|
+
return group;
|
|
223
|
+
};
|
|
224
|
+
return top.map(build);
|
|
225
|
+
}
|
|
130
226
|
/** Parses and places an SVG. Adding the result to a canvas is up to the caller. */
|
|
131
227
|
async function readSvg(svg, options = {}, limits = {}) {
|
|
132
228
|
if (typeof svg !== "string" || svg.trim().length === 0) refuse("The SVG is empty");
|
|
133
229
|
const warnings = [];
|
|
134
230
|
const document = parse(svg);
|
|
135
231
|
sanitize(document, limits, warnings);
|
|
232
|
+
dropBrokenUses(document);
|
|
233
|
+
if (options.preserveGroups) markGroups(document);
|
|
136
234
|
let parsed;
|
|
137
235
|
try {
|
|
138
236
|
parsed = await (0, fabric.parseSVGDocument)(document, void 0, {
|
|
@@ -145,6 +243,10 @@ async function readSvg(svg, options = {}, limits = {}) {
|
|
|
145
243
|
}
|
|
146
244
|
if (options.signal?.aborted) throw new require_errors.DocumentEngineError("LOAD_ABORTED", "The SVG import was cancelled");
|
|
147
245
|
let objects = parsed.objects.filter((object) => object !== null && object !== void 0);
|
|
246
|
+
if (options.preserveGroups) {
|
|
247
|
+
const elements = parsed.elements.filter((_, index) => parsed.objects[index] !== null && parsed.objects[index] !== void 0);
|
|
248
|
+
objects = rebuildGroups(objects, elements, document.documentElement);
|
|
249
|
+
}
|
|
148
250
|
const declared = {
|
|
149
251
|
width: parsed.options.width ?? 0,
|
|
150
252
|
height: parsed.options.height ?? 0
|
|
@@ -19,6 +19,7 @@ export interface SvgImportOptions {
|
|
|
19
19
|
offscreen?: "keep" | "drop" | "clip";
|
|
20
20
|
/** One group (the default), or separate objects. */
|
|
21
21
|
as?: "group" | "objects";
|
|
22
|
+
preserveGroups?: boolean;
|
|
22
23
|
/** Where the viewport's top-left corner lands on the canvas. Default 0, 0. */
|
|
23
24
|
left?: number;
|
|
24
25
|
top?: number;
|
|
@@ -19,6 +19,7 @@ export interface SvgImportOptions {
|
|
|
19
19
|
offscreen?: "keep" | "drop" | "clip";
|
|
20
20
|
/** One group (the default), or separate objects. */
|
|
21
21
|
as?: "group" | "objects";
|
|
22
|
+
preserveGroups?: boolean;
|
|
22
23
|
/** Where the viewport's top-left corner lands on the canvas. Default 0, 0. */
|
|
23
24
|
left?: number;
|
|
24
25
|
top?: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DocumentEngineError, isDocumentEngineError } from "../engine/errors.js";
|
|
2
2
|
import { isSafeImageUrl } from "../security/content-limits.js";
|
|
3
|
-
import { FixedLayout, Group, LayoutManager, Rect, parseSVGDocument } from "fabric";
|
|
3
|
+
import { FixedLayout, Group, LayoutManager, Rect, parseSVGDocument, util } from "fabric";
|
|
4
4
|
//#region src/import/svg-import.ts
|
|
5
5
|
const XLINK = "http://www.w3.org/1999/xlink";
|
|
6
6
|
const REMOVED_ELEMENTS = [
|
|
@@ -127,12 +127,110 @@ function contentBounds(objects) {
|
|
|
127
127
|
height: 0
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
+
function dropBrokenUses(document) {
|
|
131
|
+
for (const use of Array.from(document.getElementsByTagName("use"))) {
|
|
132
|
+
const link = (use.getAttribute("href") ?? use.getAttributeNS(XLINK, "href") ?? "").trim();
|
|
133
|
+
if (!link.startsWith("#") || link.length === 1 || document.getElementById(link.slice(1)) === null) use.remove();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const GROUP_MARK = "data-fde-svg-group";
|
|
137
|
+
function markGroups(document) {
|
|
138
|
+
for (const name of ["g", "a"]) for (const element of Array.from(document.documentElement.getElementsByTagName(name))) element.setAttribute(GROUP_MARK, "");
|
|
139
|
+
}
|
|
140
|
+
function svgMetadata(element) {
|
|
141
|
+
const metadata = {};
|
|
142
|
+
const id = element.getAttribute("id");
|
|
143
|
+
if (id) metadata.svgId = id;
|
|
144
|
+
const className = element.getAttribute("class");
|
|
145
|
+
if (className) metadata.svgClass = className;
|
|
146
|
+
for (const attribute of Array.from(element.attributes)) {
|
|
147
|
+
if (!attribute.name.startsWith("data-") || attribute.name === GROUP_MARK) continue;
|
|
148
|
+
(metadata.svgData ?? (metadata.svgData = {}))[attribute.name.slice(5)] = attribute.value;
|
|
149
|
+
}
|
|
150
|
+
return metadata;
|
|
151
|
+
}
|
|
152
|
+
function ownOpacity(element) {
|
|
153
|
+
const fromStyle = /(?:^|;)\s*opacity\s*:\s*([0-9.]+)/.exec(element.getAttribute("style") ?? "")?.[1];
|
|
154
|
+
const value = Number.parseFloat(fromStyle ?? element.getAttribute("opacity") ?? "1");
|
|
155
|
+
return Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : 1;
|
|
156
|
+
}
|
|
157
|
+
function rebuildGroups(objects, elements, root) {
|
|
158
|
+
const top = [];
|
|
159
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
160
|
+
const groupNodes = /* @__PURE__ */ new Set();
|
|
161
|
+
const chains = /* @__PURE__ */ new Map();
|
|
162
|
+
const elementOf = /* @__PURE__ */ new Map();
|
|
163
|
+
objects.forEach((object, index) => {
|
|
164
|
+
const element = elements[index];
|
|
165
|
+
elementOf.set(object, element);
|
|
166
|
+
const chain = [];
|
|
167
|
+
for (let parent = element.parentElement; parent && parent !== root; parent = parent.parentElement) if (parent.hasAttribute(GROUP_MARK)) chain.push(parent);
|
|
168
|
+
chains.set(object, chain);
|
|
169
|
+
let children = top;
|
|
170
|
+
for (let level = chain.length - 1; level >= 0; level -= 1) {
|
|
171
|
+
const groupElement = chain[level];
|
|
172
|
+
let node = nodes.get(groupElement);
|
|
173
|
+
if (!node) {
|
|
174
|
+
node = {
|
|
175
|
+
element: groupElement,
|
|
176
|
+
children: []
|
|
177
|
+
};
|
|
178
|
+
nodes.set(groupElement, node);
|
|
179
|
+
groupNodes.add(node);
|
|
180
|
+
children.push(node);
|
|
181
|
+
}
|
|
182
|
+
children = node.children;
|
|
183
|
+
}
|
|
184
|
+
children.push(object);
|
|
185
|
+
const own = element.getAttribute("id");
|
|
186
|
+
const leaf = object;
|
|
187
|
+
if (!own && chain.length > 0 && leaf.id !== void 0) delete leaf.id;
|
|
188
|
+
const inherited = chain.reduce((product, groupElement) => product * ownOpacity(groupElement), 1);
|
|
189
|
+
if (inherited > 0) object.opacity = Math.min(1, object.opacity / inherited);
|
|
190
|
+
object.set(svgMetadata(element));
|
|
191
|
+
});
|
|
192
|
+
const hoistClip = (node, group) => {
|
|
193
|
+
if (!node.element.hasAttribute("clip-path")) return;
|
|
194
|
+
let clip;
|
|
195
|
+
for (const object of objects) {
|
|
196
|
+
const chain = chains.get(object);
|
|
197
|
+
const at = chain.indexOf(node.element);
|
|
198
|
+
if (at === -1) continue;
|
|
199
|
+
if (elementOf.get(object).hasAttribute("clip-path") || chain.slice(0, at).some((between) => between.hasAttribute("clip-path")) || !object.clipPath) continue;
|
|
200
|
+
if (!clip) {
|
|
201
|
+
const absolute = util.multiplyTransformMatrices(object.calcTransformMatrix(), object.clipPath.calcTransformMatrix());
|
|
202
|
+
clip = object.clipPath;
|
|
203
|
+
util.applyTransformToObject(clip, util.multiplyTransformMatrices(util.invertTransform(group.calcTransformMatrix()), absolute));
|
|
204
|
+
}
|
|
205
|
+
object.clipPath = void 0;
|
|
206
|
+
object.set("dirty", true);
|
|
207
|
+
}
|
|
208
|
+
if (clip) group.clipPath = clip;
|
|
209
|
+
};
|
|
210
|
+
const build = (item) => {
|
|
211
|
+
if (!groupNodes.has(item)) return item;
|
|
212
|
+
const node = item;
|
|
213
|
+
const group = new Group(node.children.map(build));
|
|
214
|
+
group.set({
|
|
215
|
+
opacity: ownOpacity(node.element),
|
|
216
|
+
...svgMetadata(node.element)
|
|
217
|
+
});
|
|
218
|
+
const id = node.element.getAttribute("id");
|
|
219
|
+
if (id) group.id = id;
|
|
220
|
+
hoistClip(node, group);
|
|
221
|
+
group.setCoords();
|
|
222
|
+
return group;
|
|
223
|
+
};
|
|
224
|
+
return top.map(build);
|
|
225
|
+
}
|
|
130
226
|
/** Parses and places an SVG. Adding the result to a canvas is up to the caller. */
|
|
131
227
|
async function readSvg(svg, options = {}, limits = {}) {
|
|
132
228
|
if (typeof svg !== "string" || svg.trim().length === 0) refuse("The SVG is empty");
|
|
133
229
|
const warnings = [];
|
|
134
230
|
const document = parse(svg);
|
|
135
231
|
sanitize(document, limits, warnings);
|
|
232
|
+
dropBrokenUses(document);
|
|
233
|
+
if (options.preserveGroups) markGroups(document);
|
|
136
234
|
let parsed;
|
|
137
235
|
try {
|
|
138
236
|
parsed = await parseSVGDocument(document, void 0, {
|
|
@@ -145,6 +243,10 @@ async function readSvg(svg, options = {}, limits = {}) {
|
|
|
145
243
|
}
|
|
146
244
|
if (options.signal?.aborted) throw new DocumentEngineError("LOAD_ABORTED", "The SVG import was cancelled");
|
|
147
245
|
let objects = parsed.objects.filter((object) => object !== null && object !== void 0);
|
|
246
|
+
if (options.preserveGroups) {
|
|
247
|
+
const elements = parsed.elements.filter((_, index) => parsed.objects[index] !== null && parsed.objects[index] !== void 0);
|
|
248
|
+
objects = rebuildGroups(objects, elements, document.documentElement);
|
|
249
|
+
}
|
|
148
250
|
const declared = {
|
|
149
251
|
width: parsed.options.width ?? 0,
|
|
150
252
|
height: parsed.options.height ?? 0
|
package/dist/index.cjs
CHANGED
|
@@ -12,6 +12,7 @@ const require_batch_render = require("./export/batch-render.cjs");
|
|
|
12
12
|
const require_document_state_store = require("./state/document-state-store.cjs");
|
|
13
13
|
const require_clipboard = require("./commands/clipboard.cjs");
|
|
14
14
|
const require_layers = require("./commands/layers.cjs");
|
|
15
|
+
const require_text_edit = require("./commands/text-edit.cjs");
|
|
15
16
|
exports.CLIPBOARD_FORMAT = require_clipboard.CLIPBOARD_FORMAT;
|
|
16
17
|
exports.CURRENT_SCHEMA_VERSION = require_document_format.CURRENT_SCHEMA_VERSION;
|
|
17
18
|
exports.DocumentEngineError = require_errors.DocumentEngineError;
|
|
@@ -23,6 +24,7 @@ exports.createClipboard = require_clipboard.createClipboard;
|
|
|
23
24
|
exports.createConflictError = require_errors.createConflictError;
|
|
24
25
|
exports.createDocumentEngine = require_create_document_engine.createDocumentEngine;
|
|
25
26
|
exports.createDocumentStateStore = require_document_state_store.createDocumentStateStore;
|
|
27
|
+
exports.createTextCommands = require_text_edit.createTextCommands;
|
|
26
28
|
exports.detectSchemaVersion = require_migrate_document.detectSchemaVersion;
|
|
27
29
|
exports.downloadExport = require_download_export.downloadExport;
|
|
28
30
|
exports.getLayers = require_layers.getLayers;
|
|
@@ -30,9 +32,14 @@ exports.isDocumentEngineError = require_errors.isDocumentEngineError;
|
|
|
30
32
|
exports.isSafeImageUrl = require_content_limits.isSafeImageUrl;
|
|
31
33
|
exports.migrateDocument = require_migrate_document.migrateDocument;
|
|
32
34
|
exports.moveToIndex = require_layers.moveToIndex;
|
|
35
|
+
exports.readStyleRuns = require_text_edit.readStyleRuns;
|
|
33
36
|
exports.refuseUnsafeImageUrls = require_content_limits.refuseUnsafeImageUrls;
|
|
34
37
|
exports.renderDocuments = require_batch_render.renderDocuments;
|
|
38
|
+
exports.replaceTextRange = require_text_edit.replaceTextRange;
|
|
35
39
|
exports.secureDocument = require_content_limits.secureDocument;
|
|
36
40
|
exports.sendBackward = require_layers.sendBackward;
|
|
37
41
|
exports.sendToBack = require_layers.sendToBack;
|
|
42
|
+
exports.setTextRangeStyle = require_text_edit.setTextRangeStyle;
|
|
43
|
+
exports.shiftStyleRuns = require_text_edit.shiftStyleRuns;
|
|
38
44
|
exports.validateDocument = require_validate_document.validateDocument;
|
|
45
|
+
exports.writeStyleRuns = require_text_edit.writeStyleRuns;
|
package/dist/index.d.cts
CHANGED
|
@@ -9,7 +9,7 @@ import { ContentLimits, isSafeImageUrl, refuseUnsafeImageUrls, secureDocument }
|
|
|
9
9
|
import { SvgImportOptions, SvgImportResult, SvgImportWarning, SvgImportWarningCode } from "./import/svg-import.cjs";
|
|
10
10
|
import { NewDocumentOptions } from "./document/create-document.cjs";
|
|
11
11
|
import { CustomObjectDefinition } from "./fabric/object-registry.cjs";
|
|
12
|
-
import { HistoryOptions, HistoryState } from "./history/create-history.cjs";
|
|
12
|
+
import { HistoryOptions, HistoryState, TransactionOptions } from "./history/create-history.cjs";
|
|
13
13
|
import { DocumentVersion, VersionKind, VersionOptions, VersionStorage, VersionSummary } from "./versions/document-version.cjs";
|
|
14
14
|
import { RecoveryStore } from "./recovery/recovery-store.cjs";
|
|
15
15
|
import { InterruptedLoad, RecoveryOptions, RecoveryRecord } from "./recovery/recovery-controller.cjs";
|
|
@@ -19,7 +19,7 @@ import { DocumentEngineError, DocumentEngineErrorDetails, DocumentErrorCode, Doc
|
|
|
19
19
|
import { DocumentStorage, SaveContext, SaveResult } from "./storage/storage-contract.cjs";
|
|
20
20
|
import { SaveOptions, SaveRetryEvent, SaveState, SaveStatus } from "./save/save-controller.cjs";
|
|
21
21
|
import { Unsubscribe } from "./engine/event-emitter.cjs";
|
|
22
|
-
import { DocumentEngine, DocumentEngineEvents, DocumentEngineOptions, ExportResult, ImportOptions, LoadOptions, LoadProgress, LoadStage, NewDocumentRequest, createDocumentEngine } from "./engine/create-document-engine.cjs";
|
|
22
|
+
import { DocumentEngine, DocumentEngineEvents, DocumentEngineOptions, ExportResult, ImportOptions, LoadOptions, LoadProgress, LoadStage, NewDocumentRequest, PageChanges, RestoreRecoveryOptions, createDocumentEngine } from "./engine/create-document-engine.cjs";
|
|
23
23
|
import { validateDocument } from "./document/validate-document.cjs";
|
|
24
24
|
import { KeyboardShortcutOptions, UndoRedoTarget, bindKeyboardShortcuts } from "./history/keyboard-shortcuts.cjs";
|
|
25
25
|
import { UnsavedChangesSource, bindUnsavedChangesWarning } from "./save/unsaved-changes-warning.cjs";
|
|
@@ -29,4 +29,5 @@ import { Migration, MigrationContext, MigrationResult, detectSchemaVersion, migr
|
|
|
29
29
|
import { DocumentState, DocumentStateStore, createDocumentStateStore } from "./state/document-state-store.cjs";
|
|
30
30
|
import { CLIPBOARD_FORMAT, Clipboard, ClipboardContent, ClipboardOptions, PasteOptions, createClipboard } from "./commands/clipboard.cjs";
|
|
31
31
|
import { LayerInfo, LayerOptions, LayerPin, bringForward, bringToFront, getLayers, moveToIndex, sendBackward, sendToBack } from "./commands/layers.cjs";
|
|
32
|
-
|
|
32
|
+
import { EditableTextObject, InsertedStyle, StyleRun, TextCommands, createTextCommands, readStyleRuns, replaceTextRange, setTextRangeStyle, shiftStyleRuns, writeStyleRuns } from "./commands/text-edit.cjs";
|
|
33
|
+
export { type AssetManifest, type AssetOptions, type AssetReport, type AssetWarning, type AssetWarningCode, type AutosaveOptions, CLIPBOARD_FORMAT, CURRENT_SCHEMA_VERSION, type Clipboard, type ClipboardContent, type ClipboardOptions, type ContentLimits, type CustomObjectDefinition, type DocumentCanvas, type DocumentEngine, DocumentEngineError, type DocumentEngineErrorDetails, type DocumentEngineEvents, type DocumentEngineOptions, type DocumentErrorCode, type DocumentInfo, type DocumentIssue, type DocumentState, type DocumentStateStore, type DocumentStorage, type DocumentVersion, type DownloadableExport, type EditableTextObject, type ExportArea, type ExportBackground, type ExportFormat, type ExportOptions, type ExportPreflight, type ExportProblem, type ExportProblemCode, type ExportRect, type ExportResult, type FabricDocument, type FontAsset, type FontLoader, type FontSource, type HistoryOptions, type HistoryState, type ImageAsset, type ImageFailureReason, type ImageLoadFailure, type ImportOptions, type InsertedStyle, type InterruptedLoad, type KeyboardShortcutOptions, type LayerInfo, type LayerOptions, type LayerPin, type LoadOptions, type LoadProgress, type LoadStage, type Migration, type MigrationContext, type MigrationResult, type NewDocumentOptions, type NewDocumentRequest, type PageChanges, type PasteOptions, type RecoveryOptions, type RecoveryRecord, type RecoveryStore, type RenderDocumentsOptions, type RenderedDocument, type RestoreRecoveryOptions, type RetryOptions, type SaveContext, type SaveOptions, type SaveResult, type SaveRetryEvent, type SaveState, type SaveStatus, type SerializedFabricObject, type StyleRun, type SvgExportOptions, type SvgImportOptions, type SvgImportResult, type SvgImportWarning, type SvgImportWarningCode, type TextCommands, type TransactionOptions, type UndoRedoTarget, type UnsavedChangesSource, type Unsubscribe, type UploadRequest, type VersionKind, type VersionOptions, type VersionStorage, type VersionSummary, bindKeyboardShortcuts, bindUnsavedChangesWarning, bringForward, bringToFront, createClipboard, createConflictError, createDocumentEngine, createDocumentStateStore, createTextCommands, detectSchemaVersion, downloadExport, getLayers, isDocumentEngineError, isSafeImageUrl, migrateDocument, moveToIndex, readStyleRuns, refuseUnsafeImageUrls, renderDocuments, replaceTextRange, secureDocument, sendBackward, sendToBack, setTextRangeStyle, shiftStyleRuns, validateDocument, writeStyleRuns };
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { ContentLimits, isSafeImageUrl, refuseUnsafeImageUrls, secureDocument }
|
|
|
9
9
|
import { SvgImportOptions, SvgImportResult, SvgImportWarning, SvgImportWarningCode } from "./import/svg-import.js";
|
|
10
10
|
import { NewDocumentOptions } from "./document/create-document.js";
|
|
11
11
|
import { CustomObjectDefinition } from "./fabric/object-registry.js";
|
|
12
|
-
import { HistoryOptions, HistoryState } from "./history/create-history.js";
|
|
12
|
+
import { HistoryOptions, HistoryState, TransactionOptions } from "./history/create-history.js";
|
|
13
13
|
import { DocumentVersion, VersionKind, VersionOptions, VersionStorage, VersionSummary } from "./versions/document-version.js";
|
|
14
14
|
import { RecoveryStore } from "./recovery/recovery-store.js";
|
|
15
15
|
import { InterruptedLoad, RecoveryOptions, RecoveryRecord } from "./recovery/recovery-controller.js";
|
|
@@ -19,7 +19,7 @@ import { DocumentEngineError, DocumentEngineErrorDetails, DocumentErrorCode, Doc
|
|
|
19
19
|
import { DocumentStorage, SaveContext, SaveResult } from "./storage/storage-contract.js";
|
|
20
20
|
import { SaveOptions, SaveRetryEvent, SaveState, SaveStatus } from "./save/save-controller.js";
|
|
21
21
|
import { Unsubscribe } from "./engine/event-emitter.js";
|
|
22
|
-
import { DocumentEngine, DocumentEngineEvents, DocumentEngineOptions, ExportResult, ImportOptions, LoadOptions, LoadProgress, LoadStage, NewDocumentRequest, createDocumentEngine } from "./engine/create-document-engine.js";
|
|
22
|
+
import { DocumentEngine, DocumentEngineEvents, DocumentEngineOptions, ExportResult, ImportOptions, LoadOptions, LoadProgress, LoadStage, NewDocumentRequest, PageChanges, RestoreRecoveryOptions, createDocumentEngine } from "./engine/create-document-engine.js";
|
|
23
23
|
import { validateDocument } from "./document/validate-document.js";
|
|
24
24
|
import { KeyboardShortcutOptions, UndoRedoTarget, bindKeyboardShortcuts } from "./history/keyboard-shortcuts.js";
|
|
25
25
|
import { UnsavedChangesSource, bindUnsavedChangesWarning } from "./save/unsaved-changes-warning.js";
|
|
@@ -29,4 +29,5 @@ import { Migration, MigrationContext, MigrationResult, detectSchemaVersion, migr
|
|
|
29
29
|
import { DocumentState, DocumentStateStore, createDocumentStateStore } from "./state/document-state-store.js";
|
|
30
30
|
import { CLIPBOARD_FORMAT, Clipboard, ClipboardContent, ClipboardOptions, PasteOptions, createClipboard } from "./commands/clipboard.js";
|
|
31
31
|
import { LayerInfo, LayerOptions, LayerPin, bringForward, bringToFront, getLayers, moveToIndex, sendBackward, sendToBack } from "./commands/layers.js";
|
|
32
|
-
|
|
32
|
+
import { EditableTextObject, InsertedStyle, StyleRun, TextCommands, createTextCommands, readStyleRuns, replaceTextRange, setTextRangeStyle, shiftStyleRuns, writeStyleRuns } from "./commands/text-edit.js";
|
|
33
|
+
export { type AssetManifest, type AssetOptions, type AssetReport, type AssetWarning, type AssetWarningCode, type AutosaveOptions, CLIPBOARD_FORMAT, CURRENT_SCHEMA_VERSION, type Clipboard, type ClipboardContent, type ClipboardOptions, type ContentLimits, type CustomObjectDefinition, type DocumentCanvas, type DocumentEngine, DocumentEngineError, type DocumentEngineErrorDetails, type DocumentEngineEvents, type DocumentEngineOptions, type DocumentErrorCode, type DocumentInfo, type DocumentIssue, type DocumentState, type DocumentStateStore, type DocumentStorage, type DocumentVersion, type DownloadableExport, type EditableTextObject, type ExportArea, type ExportBackground, type ExportFormat, type ExportOptions, type ExportPreflight, type ExportProblem, type ExportProblemCode, type ExportRect, type ExportResult, type FabricDocument, type FontAsset, type FontLoader, type FontSource, type HistoryOptions, type HistoryState, type ImageAsset, type ImageFailureReason, type ImageLoadFailure, type ImportOptions, type InsertedStyle, type InterruptedLoad, type KeyboardShortcutOptions, type LayerInfo, type LayerOptions, type LayerPin, type LoadOptions, type LoadProgress, type LoadStage, type Migration, type MigrationContext, type MigrationResult, type NewDocumentOptions, type NewDocumentRequest, type PageChanges, type PasteOptions, type RecoveryOptions, type RecoveryRecord, type RecoveryStore, type RenderDocumentsOptions, type RenderedDocument, type RestoreRecoveryOptions, type RetryOptions, type SaveContext, type SaveOptions, type SaveResult, type SaveRetryEvent, type SaveState, type SaveStatus, type SerializedFabricObject, type StyleRun, type SvgExportOptions, type SvgImportOptions, type SvgImportResult, type SvgImportWarning, type SvgImportWarningCode, type TextCommands, type TransactionOptions, type UndoRedoTarget, type UnsavedChangesSource, type Unsubscribe, type UploadRequest, type VersionKind, type VersionOptions, type VersionStorage, type VersionSummary, bindKeyboardShortcuts, bindUnsavedChangesWarning, bringForward, bringToFront, createClipboard, createConflictError, createDocumentEngine, createDocumentStateStore, createTextCommands, detectSchemaVersion, downloadExport, getLayers, isDocumentEngineError, isSafeImageUrl, migrateDocument, moveToIndex, readStyleRuns, refuseUnsafeImageUrls, renderDocuments, replaceTextRange, secureDocument, sendBackward, sendToBack, setTextRangeStyle, shiftStyleRuns, validateDocument, writeStyleRuns };
|
package/dist/index.js
CHANGED
|
@@ -11,4 +11,5 @@ import { renderDocuments } from "./export/batch-render.js";
|
|
|
11
11
|
import { createDocumentStateStore } from "./state/document-state-store.js";
|
|
12
12
|
import { CLIPBOARD_FORMAT, createClipboard } from "./commands/clipboard.js";
|
|
13
13
|
import { bringForward, bringToFront, getLayers, moveToIndex, sendBackward, sendToBack } from "./commands/layers.js";
|
|
14
|
-
|
|
14
|
+
import { createTextCommands, readStyleRuns, replaceTextRange, setTextRangeStyle, shiftStyleRuns, writeStyleRuns } from "./commands/text-edit.js";
|
|
15
|
+
export { CLIPBOARD_FORMAT, CURRENT_SCHEMA_VERSION, DocumentEngineError, bindKeyboardShortcuts, bindUnsavedChangesWarning, bringForward, bringToFront, createClipboard, createConflictError, createDocumentEngine, createDocumentStateStore, createTextCommands, detectSchemaVersion, downloadExport, getLayers, isDocumentEngineError, isSafeImageUrl, migrateDocument, moveToIndex, readStyleRuns, refuseUnsafeImageUrls, renderDocuments, replaceTextRange, secureDocument, sendBackward, sendToBack, setTextRangeStyle, shiftStyleRuns, validateDocument, writeStyleRuns };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const require_page_state = require("../fabric/page-state.cjs");
|
|
1
2
|
const require_errors = require("../engine/errors.cjs");
|
|
2
3
|
require("../document/document-format.cjs");
|
|
3
4
|
const require_ids = require("../document/ids.cjs");
|
|
@@ -19,7 +20,7 @@ function fromFabricJson(json, context) {
|
|
|
19
20
|
canvas: {
|
|
20
21
|
width: positiveNumberOr(json.width, context.canvasWidth),
|
|
21
22
|
height: positiveNumberOr(json.height, context.canvasHeight),
|
|
22
|
-
...
|
|
23
|
+
...require_page_state.pickPageFields(json)
|
|
23
24
|
},
|
|
24
25
|
objects: json.objects,
|
|
25
26
|
metadata: { ...context.metadata }
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { pickPageFields } from "../fabric/page-state.js";
|
|
1
2
|
import { DocumentEngineError } from "../engine/errors.js";
|
|
2
3
|
import "../document/document-format.js";
|
|
3
4
|
import { createId } from "../document/ids.js";
|
|
@@ -19,7 +20,7 @@ function fromFabricJson(json, context) {
|
|
|
19
20
|
canvas: {
|
|
20
21
|
width: positiveNumberOr(json.width, context.canvasWidth),
|
|
21
22
|
height: positiveNumberOr(json.height, context.canvasHeight),
|
|
22
|
-
...json
|
|
23
|
+
...pickPageFields(json)
|
|
23
24
|
},
|
|
24
25
|
objects: json.objects,
|
|
25
26
|
metadata: { ...context.metadata }
|