@pixerate/editor 0.154.0 → 0.155.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.
Files changed (58) hide show
  1. package/dist/animation-editor/index.cjs +2 -3
  2. package/dist/animation-editor/index.js +1 -2
  3. package/dist/canvas/index.cjs +15 -16
  4. package/dist/canvas/index.js +2 -3
  5. package/dist/chart/index.cjs +2 -3
  6. package/dist/chart/index.js +1 -2
  7. package/dist/chunk-M4MIZPQI.cjs +393 -0
  8. package/dist/chunk-NHLYK3AX.js +393 -0
  9. package/dist/{chunk-XFDQEAOS.cjs → chunk-RQCMSEM5.cjs} +2 -2
  10. package/dist/{chunk-BCY22GBH.js → chunk-SDHZG5TF.js} +1 -1
  11. package/dist/{chunk-HVX35M2I.cjs → chunk-WI7QJA7A.cjs} +2 -2
  12. package/dist/{chunk-4J4MC3F5.js → chunk-YXOW456B.js} +1 -1
  13. package/dist/diagram/index.cjs +2 -3
  14. package/dist/diagram/index.js +1 -2
  15. package/dist/image-editor/controller.d.cts +8 -0
  16. package/dist/image-editor/controller.d.ts +8 -0
  17. package/dist/image-editor/editorDocument.d.cts +16 -0
  18. package/dist/image-editor/editorDocument.d.ts +16 -0
  19. package/dist/image-editor/index.cjs +102 -52
  20. package/dist/image-editor/index.d.cts +1 -0
  21. package/dist/image-editor/index.d.ts +1 -0
  22. package/dist/image-editor/index.js +51 -1
  23. package/dist/index.cjs +4 -5
  24. package/dist/index.js +2 -3
  25. package/dist/paint-editor/controller.d.cts +8 -0
  26. package/dist/paint-editor/controller.d.ts +8 -0
  27. package/dist/paint-editor/editorDocument.d.cts +17 -0
  28. package/dist/paint-editor/editorDocument.d.ts +17 -0
  29. package/dist/paint-editor/index.cjs +74 -18
  30. package/dist/paint-editor/index.d.cts +1 -0
  31. package/dist/paint-editor/index.d.ts +1 -0
  32. package/dist/paint-editor/index.js +58 -2
  33. package/dist/parameters/index.cjs +2 -3
  34. package/dist/parameters/index.js +1 -2
  35. package/dist/persistence/assets.d.cts +51 -0
  36. package/dist/persistence/assets.d.ts +51 -0
  37. package/dist/persistence/editorDocument.d.cts +12 -0
  38. package/dist/persistence/editorDocument.d.ts +12 -0
  39. package/dist/persistence/index.cjs +32 -8
  40. package/dist/persistence/index.d.cts +1 -0
  41. package/dist/persistence/index.d.ts +1 -0
  42. package/dist/persistence/index.js +34 -10
  43. package/dist/spreadsheet/index.cjs +3 -4
  44. package/dist/spreadsheet/index.js +2 -3
  45. package/dist/tokens/index.cjs +3 -4
  46. package/dist/tokens/index.js +2 -3
  47. package/dist/vector/index.cjs +2 -3
  48. package/dist/vector/index.js +1 -2
  49. package/dist/video-editor/index.cjs +2 -3
  50. package/dist/video-editor/index.js +1 -2
  51. package/package.json +1 -1
  52. package/skills/pixerate-image-editor/SKILL.md +16 -24
  53. package/skills/pixerate-image-editor/references/smart-objects.md +28 -0
  54. package/skills/pixerate-paint-editor/SKILL.md +17 -5
  55. package/dist/chunk-5H2C3QSF.cjs +0 -134
  56. package/dist/chunk-GNV54DLO.js +0 -134
  57. package/dist/chunk-L5OWG2NA.cjs +0 -135
  58. package/dist/chunk-WHKNYFM2.js +0 -135
@@ -61,8 +61,7 @@ var _chunkALNIFK5Gcjs = require('../chunk-ALNIFK5G.cjs');
61
61
  require('../chunk-UWEQ55MY.cjs');
62
62
 
63
63
 
64
- var _chunk5H2C3QSFcjs = require('../chunk-5H2C3QSF.cjs');
65
- require('../chunk-L5OWG2NA.cjs');
64
+ var _chunkM4MIZPQIcjs = require('../chunk-M4MIZPQI.cjs');
66
65
  require('../chunk-2BSBFBOA.cjs');
67
66
 
68
67
 
@@ -5938,7 +5937,7 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
5938
5937
 
5939
5938
  // src/animation-editor/editorDocument.ts
5940
5939
  function createAnimationEditorDocument(controller) {
5941
- return _chunk5H2C3QSFcjs.defineEditorDocument.call(void 0, {
5940
+ return _chunkM4MIZPQIcjs.defineEditorDocument.call(void 0, {
5942
5941
  kind: "animation",
5943
5942
  get: () => controller.getScene(),
5944
5943
  load: (document, { history }) => {
@@ -61,8 +61,7 @@ import {
61
61
  import "../chunk-VDGBHYC7.js";
62
62
  import {
63
63
  defineEditorDocument
64
- } from "../chunk-GNV54DLO.js";
65
- import "../chunk-WHKNYFM2.js";
64
+ } from "../chunk-NHLYK3AX.js";
66
65
  import "../chunk-HF5QZS7Z.js";
67
66
  import {
68
67
  HistoryManager
@@ -60,7 +60,7 @@ var _chunkZVNAMTFOcjs = require('../chunk-ZVNAMTFO.cjs');
60
60
 
61
61
 
62
62
 
63
- var _chunkHVX35M2Icjs = require('../chunk-HVX35M2I.cjs');
63
+ var _chunkWI7QJA7Acjs = require('../chunk-WI7QJA7A.cjs');
64
64
 
65
65
 
66
66
 
@@ -215,8 +215,7 @@ require('../chunk-WOFXZ3XU.cjs');
215
215
  var _chunkYQGCPL5Xcjs = require('../chunk-YQGCPL5X.cjs');
216
216
 
217
217
 
218
- var _chunk5H2C3QSFcjs = require('../chunk-5H2C3QSF.cjs');
219
- require('../chunk-L5OWG2NA.cjs');
218
+ var _chunkM4MIZPQIcjs = require('../chunk-M4MIZPQI.cjs');
220
219
  require('../chunk-2BSBFBOA.cjs');
221
220
 
222
221
 
@@ -4050,7 +4049,7 @@ function getTokenPropertyScope(property, node) {
4050
4049
  }
4051
4050
  function getTokensForProperty(state, property, node) {
4052
4051
  const scope = getTokenPropertyScope(property, node);
4053
- return state.variables.filter((v) => v.type === property.type && _chunkHVX35M2Icjs.isTokenInScope.call(void 0, v, scope));
4052
+ return state.variables.filter((v) => v.type === property.type && _chunkWI7QJA7Acjs.isTokenInScope.call(void 0, v, scope));
4054
4053
  }
4055
4054
  function lookupOf(nodes) {
4056
4055
  return new Map(nodes.map((n3) => [n3.id, n3]));
@@ -4058,7 +4057,7 @@ function lookupOf(nodes) {
4058
4057
  function validModes(state, modes, into) {
4059
4058
  for (const [collectionId, modeId] of Object.entries(modes)) {
4060
4059
  if (state) {
4061
- const collection = _chunkHVX35M2Icjs.getTokenCollection.call(void 0, state, collectionId);
4060
+ const collection = _chunkWI7QJA7Acjs.getTokenCollection.call(void 0, state, collectionId);
4062
4061
  if (!collection || !collection.modes.some((m) => m.id === modeId)) continue;
4063
4062
  }
4064
4063
  into[collectionId] = modeId;
@@ -4113,7 +4112,7 @@ function applyBindings(node, state, modes, options, only) {
4113
4112
  if (only && !only.has(variableId)) continue;
4114
4113
  const property = getCanvasTokenProperty(key, options);
4115
4114
  if (!property || !property.appliesTo(next)) continue;
4116
- const resolved = _chunkHVX35M2Icjs.resolveToken.call(void 0, state, variableId, modes);
4115
+ const resolved = _chunkWI7QJA7Acjs.resolveToken.call(void 0, state, variableId, modes);
4117
4116
  if (!resolved.ok || resolved.type !== property.type) continue;
4118
4117
  next = property.write(next, resolved.value);
4119
4118
  }
@@ -4136,7 +4135,7 @@ function inspectNodeTokens(node, nodes, state, options = {}) {
4136
4135
  for (const [key, variableId] of Object.entries(getNodeTokenBindings(node))) {
4137
4136
  const property = getCanvasTokenProperty(key, options);
4138
4137
  if (!property) continue;
4139
- out.push({ property, variableId, variable: _chunkHVX35M2Icjs.getTokenVariable.call(void 0, state, variableId), resolution: _chunkHVX35M2Icjs.resolveToken.call(void 0, state, variableId, modes) });
4138
+ out.push({ property, variableId, variable: _chunkWI7QJA7Acjs.getTokenVariable.call(void 0, state, variableId), resolution: _chunkWI7QJA7Acjs.resolveToken.call(void 0, state, variableId, modes) });
4140
4139
  }
4141
4140
  return out;
4142
4141
  }
@@ -4148,12 +4147,12 @@ function setDataRecord(node, key, record) {
4148
4147
  }
4149
4148
  function bindCanvasToken(nodes, ids, propertyKey, variableId, state, options = {}) {
4150
4149
  const property = getCanvasTokenProperty(propertyKey, options);
4151
- if (!property) throw new (0, _chunkHVX35M2Icjs.TokenError)("not-found", `No bindable property \`${propertyKey}\``);
4150
+ if (!property) throw new (0, _chunkWI7QJA7Acjs.TokenError)("not-found", `No bindable property \`${propertyKey}\``);
4152
4151
  if (variableId !== null) {
4153
- const variable = _chunkHVX35M2Icjs.getTokenVariable.call(void 0, state, variableId);
4154
- if (!variable) throw new (0, _chunkHVX35M2Icjs.TokenError)("not-found", `No variable \`${variableId}\``);
4152
+ const variable = _chunkWI7QJA7Acjs.getTokenVariable.call(void 0, state, variableId);
4153
+ if (!variable) throw new (0, _chunkWI7QJA7Acjs.TokenError)("not-found", `No variable \`${variableId}\``);
4155
4154
  if (variable.type !== property.type) {
4156
- throw new (0, _chunkHVX35M2Icjs.TokenError)("type-mismatch", `${property.label} takes a ${property.type} variable; \`${variable.name}\` is a ${variable.type}`);
4155
+ throw new (0, _chunkWI7QJA7Acjs.TokenError)("type-mismatch", `${property.label} takes a ${property.type} variable; \`${variable.name}\` is a ${variable.type}`);
4157
4156
  }
4158
4157
  }
4159
4158
  const targets = new Set(ids);
@@ -4175,9 +4174,9 @@ function bindCanvasToken(nodes, ids, propertyKey, variableId, state, options = {
4175
4174
  }
4176
4175
  function setCanvasTokenMode(nodes, ids, collectionId, modeId, state, options = {}) {
4177
4176
  if (modeId !== null) {
4178
- const collection = _chunkHVX35M2Icjs.getTokenCollection.call(void 0, state, collectionId);
4179
- if (!collection) throw new (0, _chunkHVX35M2Icjs.TokenError)("not-found", `No collection \`${collectionId}\``);
4180
- if (!collection.modes.some((m) => m.id === modeId)) throw new (0, _chunkHVX35M2Icjs.TokenError)("not-found", `No mode \`${modeId}\` in \`${collection.name}\``);
4177
+ const collection = _chunkWI7QJA7Acjs.getTokenCollection.call(void 0, state, collectionId);
4178
+ if (!collection) throw new (0, _chunkWI7QJA7Acjs.TokenError)("not-found", `No collection \`${collectionId}\``);
4179
+ if (!collection.modes.some((m) => m.id === modeId)) throw new (0, _chunkWI7QJA7Acjs.TokenError)("not-found", `No mode \`${modeId}\` in \`${collection.name}\``);
4181
4180
  }
4182
4181
  const targets = new Set(ids);
4183
4182
  let changed = false;
@@ -4198,7 +4197,7 @@ function setCanvasTokenMode(nodes, ids, collectionId, modeId, state, options = {
4198
4197
  }
4199
4198
  function detachTokenBindings(nodes, state, variableIds, options = {}) {
4200
4199
  const only = variableIds ? new Set(variableIds) : null;
4201
- const isDetached = (id) => only ? only.has(id) : !_chunkHVX35M2Icjs.getTokenVariable.call(void 0, state, id);
4200
+ const isDetached = (id) => only ? only.has(id) : !_chunkWI7QJA7Acjs.getTokenVariable.call(void 0, state, id);
4202
4201
  const { modesOf } = modesResolver(nodes, state, options);
4203
4202
  let changed = false;
4204
4203
  const out = nodes.map((node) => {
@@ -11744,7 +11743,7 @@ function createCanvasEditorDocument(options) {
11744
11743
  options.setEdges(doc.edges.map((e) => ({ ...e })));
11745
11744
  if (scenes2) scenes2.load(_nullishCoalesce(doc.scenes, () => ( [])));
11746
11745
  };
11747
- return _chunk5H2C3QSFcjs.defineEditorDocument.call(void 0, {
11746
+ return _chunkM4MIZPQIcjs.defineEditorDocument.call(void 0, {
11748
11747
  kind: "canvas",
11749
11748
  get: snapshot,
11750
11749
  load: (document2, { history: mode }) => {
@@ -60,7 +60,7 @@ import {
60
60
  getTokenVariable,
61
61
  isTokenInScope,
62
62
  resolveToken
63
- } from "../chunk-BCY22GBH.js";
63
+ } from "../chunk-SDHZG5TF.js";
64
64
  import {
65
65
  DEFAULT_NODE_HEIGHT,
66
66
  DEFAULT_NODE_WIDTH,
@@ -215,8 +215,7 @@ import {
215
215
  } from "../chunk-ODBT55Q7.js";
216
216
  import {
217
217
  defineEditorDocument
218
- } from "../chunk-GNV54DLO.js";
219
- import "../chunk-WHKNYFM2.js";
218
+ } from "../chunk-NHLYK3AX.js";
220
219
  import "../chunk-HF5QZS7Z.js";
221
220
  import {
222
221
  ANIMATION_TIME_EPSILON,
@@ -155,8 +155,7 @@ var _chunkSWTUM32Hcjs = require('../chunk-SWTUM32H.cjs');
155
155
  var _chunkALNIFK5Gcjs = require('../chunk-ALNIFK5G.cjs');
156
156
 
157
157
 
158
- var _chunk5H2C3QSFcjs = require('../chunk-5H2C3QSF.cjs');
159
- require('../chunk-L5OWG2NA.cjs');
158
+ var _chunkM4MIZPQIcjs = require('../chunk-M4MIZPQI.cjs');
160
159
  require('../chunk-2BSBFBOA.cjs');
161
160
  require('../chunk-FJ2MSI43.cjs');
162
161
  require('../chunk-UKCJ43YL.cjs');
@@ -2191,7 +2190,7 @@ function createOfficeChartToolProvider(options = {}) {
2191
2190
 
2192
2191
  // src/chart/editorDocument.ts
2193
2192
  function createChartEditorDocument(controller) {
2194
- return _chunk5H2C3QSFcjs.defineEditorDocument.call(void 0, {
2193
+ return _chunkM4MIZPQIcjs.defineEditorDocument.call(void 0, {
2195
2194
  kind: "chart",
2196
2195
  get: () => controller.toJSON(),
2197
2196
  load: (document, { history }) => {
@@ -155,8 +155,7 @@ import {
155
155
  } from "../chunk-CIQIM2IP.js";
156
156
  import {
157
157
  defineEditorDocument
158
- } from "../chunk-GNV54DLO.js";
159
- import "../chunk-WHKNYFM2.js";
158
+ } from "../chunk-NHLYK3AX.js";
160
159
  import "../chunk-HF5QZS7Z.js";
161
160
  import "../chunk-RNSANXPT.js";
162
161
  import "../chunk-AA34BA7G.js";
@@ -0,0 +1,393 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+ var _chunk2BSBFBOAcjs = require('./chunk-2BSBFBOA.cjs');
5
+
6
+ // src/persistence/assets.ts
7
+ var EDITOR_ASSET_PREFIX = "pixerate-asset:";
8
+ var REF = /pixerate-asset:[0-9a-z]+-[0-9a-z]+(?:~[0-9]+)?/g;
9
+ var BASE64 = /^[A-Za-z0-9+/=\r\n]+$/;
10
+ function isInlineAsset(value) {
11
+ if (value.startsWith("data:")) return value.length >= 512;
12
+ return value.length >= 4096 && BASE64.test(value);
13
+ }
14
+ function hash53(text) {
15
+ let h1 = 3735928559;
16
+ let h2 = 1103547991;
17
+ for (let i = 0; i < text.length; i++) {
18
+ const c = text.charCodeAt(i);
19
+ h1 = Math.imul(h1 ^ c, 2654435761);
20
+ h2 = Math.imul(h2 ^ c, 1597334677);
21
+ }
22
+ h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
23
+ h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
24
+ return 4294967296 * (2097151 & h2) + (h1 >>> 0);
25
+ }
26
+ function createEditorAssetRegistry() {
27
+ const byRef = /* @__PURE__ */ new Map();
28
+ const byData = /* @__PURE__ */ new Map();
29
+ return {
30
+ put(data) {
31
+ const known = byData.get(data);
32
+ if (known) return known;
33
+ const base = `${EDITOR_ASSET_PREFIX}${data.length.toString(36)}-${hash53(data).toString(36)}`;
34
+ let ref = base;
35
+ for (let n = 1; byRef.has(ref) && byRef.get(ref) !== data; n++) ref = `${base}~${n}`;
36
+ byRef.set(ref, data);
37
+ byData.set(data, ref);
38
+ return ref;
39
+ },
40
+ get: (ref) => byRef.get(ref),
41
+ has: (ref) => byRef.has(ref),
42
+ set(ref, data) {
43
+ byRef.set(ref, data);
44
+ byData.set(data, ref);
45
+ },
46
+ get size() {
47
+ return byRef.size;
48
+ }
49
+ };
50
+ }
51
+ function externalizeAssets(value, registry) {
52
+ const walk = (v) => {
53
+ if (typeof v === "string") return isInlineAsset(v) ? registry.put(v) : v;
54
+ if (Array.isArray(v)) return v.map(walk);
55
+ if (v && typeof v === "object") {
56
+ const out = {};
57
+ for (const [k, x] of Object.entries(v)) out[k] = walk(x);
58
+ return out;
59
+ }
60
+ return v;
61
+ };
62
+ return walk(value);
63
+ }
64
+ function collectAssetRefs(value) {
65
+ const text = typeof value === "string" ? value : _nullishCoalesce(JSON.stringify(value), () => ( ""));
66
+ return [...new Set(_nullishCoalesce(text.match(REF), () => ( [])))];
67
+ }
68
+ function internalizeAssets(value, registry) {
69
+ const missing = collectAssetRefs(value).filter((ref) => !registry.has(ref));
70
+ if (missing.length) {
71
+ throw new Error(
72
+ `The document refers to ${missing.length} asset${missing.length === 1 ? "" : "s"} that ${missing.length === 1 ? "is" : "are"} not loaded (${missing.slice(0, 3).join(", ")}${missing.length > 3 ? ", \u2026" : ""}). Pass a document from get_*_document in this session, or open it from storage so its assets are read first.`
73
+ );
74
+ }
75
+ const walk = (v) => {
76
+ if (typeof v === "string") return v.startsWith(EDITOR_ASSET_PREFIX) && registry.has(v) ? registry.get(v) : v;
77
+ if (Array.isArray(v)) return v.map(walk);
78
+ if (v && typeof v === "object") {
79
+ const out = {};
80
+ for (const [k, x] of Object.entries(v)) out[k] = walk(x);
81
+ return out;
82
+ }
83
+ return v;
84
+ };
85
+ return walk(value);
86
+ }
87
+ var persisted = /* @__PURE__ */ new WeakMap();
88
+ var assetKey = (ref, options) => `${_nullishCoalesce(options.prefix, () => ( "pixerate.assets:"))}${ref.slice(EDITOR_ASSET_PREFIX.length)}`;
89
+ async function persistEditorAssets(storage, registry, document, options = {}) {
90
+ const written = _nullishCoalesce(persisted.get(storage), () => ( /* @__PURE__ */ new Set()));
91
+ persisted.set(storage, written);
92
+ for (const ref of collectAssetRefs(document)) {
93
+ const key = assetKey(ref, options);
94
+ if (written.has(key)) continue;
95
+ const data = registry.get(ref);
96
+ if (data === void 0) continue;
97
+ await storage.set(key, data);
98
+ written.add(key);
99
+ }
100
+ }
101
+ async function preloadEditorAssets(storage, registry, document, options = {}) {
102
+ const missing = [];
103
+ for (const ref of collectAssetRefs(document)) {
104
+ if (registry.has(ref)) continue;
105
+ const data = await storage.get(assetKey(ref, options));
106
+ if (data === null) missing.push(ref);
107
+ else registry.set(ref, data);
108
+ }
109
+ return missing;
110
+ }
111
+ function withEditorAssets(storage, registry, options = {}) {
112
+ return {
113
+ kind: storage.kind,
114
+ get available() {
115
+ return storage.available;
116
+ },
117
+ async get(key) {
118
+ const value = await storage.get(key);
119
+ if (value !== null && value.includes(EDITOR_ASSET_PREFIX)) await preloadEditorAssets(storage, registry, value, options);
120
+ return value;
121
+ },
122
+ async set(key, value) {
123
+ if (value.includes(EDITOR_ASSET_PREFIX)) await persistEditorAssets(storage, registry, value, options);
124
+ await storage.set(key, value);
125
+ },
126
+ remove: (key) => storage.remove(key)
127
+ };
128
+ }
129
+
130
+ // src/persistence/migrate.ts
131
+ function hasLoadProblems(report) {
132
+ return report.problems.length > 0 || report.readOnly !== null;
133
+ }
134
+ function createLoadReport(partial = {}) {
135
+ return {
136
+ migratedFrom: null,
137
+ version: null,
138
+ problems: [],
139
+ readOnly: null,
140
+ unknownKeys: [],
141
+ ...partial
142
+ };
143
+ }
144
+ var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
145
+ var deepClone = (value) => typeof structuredClone === "function" ? structuredClone(value) : JSON.parse(JSON.stringify(value));
146
+ function toObject(json) {
147
+ let value = json;
148
+ if (typeof json === "string") {
149
+ try {
150
+ value = JSON.parse(json);
151
+ } catch (e) {
152
+ return void 0;
153
+ }
154
+ }
155
+ return isObject(value) ? _chunk2BSBFBOAcjs.stripPrototypeKeys.call(void 0, deepClone(value)) : void 0;
156
+ }
157
+ function migrateDocument(json, options) {
158
+ const versionKey = _nullishCoalesce(options.versionKey, () => ( "version"));
159
+ const target = options.currentVersion;
160
+ const original = toObject(json);
161
+ if (!original) {
162
+ return {
163
+ doc: { [versionKey]: target },
164
+ report: createLoadReport({
165
+ readOnly: { kind: "invalid", message: "document is not a JSON object" }
166
+ })
167
+ };
168
+ }
169
+ const raw = original[versionKey];
170
+ const found = typeof raw === "number" && Number.isInteger(raw) && raw >= 0 ? raw : null;
171
+ const from = _nullishCoalesce(_nullishCoalesce(found, () => ( options.missingVersion)), () => ( target));
172
+ const report = createLoadReport({ version: found });
173
+ if (from > target) {
174
+ report.readOnly = {
175
+ kind: "newerVersion",
176
+ version: from,
177
+ supported: target,
178
+ message: `document has version ${from}, newer than the supported ${target}`
179
+ };
180
+ return { doc: original, report };
181
+ }
182
+ if (from === target) {
183
+ original[versionKey] = target;
184
+ return { doc: original, report };
185
+ }
186
+ let doc = deepClone(original);
187
+ for (let step = from; step < target; step++) {
188
+ const fn = _optionalChain([options, 'access', _ => _.steps, 'optionalAccess', _2 => _2[step]]);
189
+ if (!fn) {
190
+ report.readOnly = {
191
+ kind: "migrationFailed",
192
+ from: step,
193
+ message: `no migration step from version ${step}`
194
+ };
195
+ return { doc: original, report };
196
+ }
197
+ try {
198
+ doc = _nullishCoalesce(fn(doc), () => ( doc));
199
+ } catch (error) {
200
+ report.readOnly = {
201
+ kind: "migrationFailed",
202
+ from: step,
203
+ message: `migration from version ${step} failed: ${error instanceof Error ? error.message : String(error)}`
204
+ };
205
+ return { doc: original, report };
206
+ }
207
+ doc[versionKey] = step + 1;
208
+ }
209
+ report.migratedFrom = from;
210
+ return { doc, report };
211
+ }
212
+ function loadSections(doc, sections, options = {}) {
213
+ const source = isObject(doc) ? doc : {};
214
+ const ignore = new Set(_nullishCoalesce(options.ignore, () => ( ["version"])));
215
+ const value = {};
216
+ const problems = [];
217
+ for (const key of Object.keys(sections)) {
218
+ const spec = sections[key];
219
+ const fallback = () => typeof spec.defaults === "function" ? spec.defaults() : spec.defaults;
220
+ if (!Object.prototype.hasOwnProperty.call(source, key)) {
221
+ value[key] = fallback();
222
+ continue;
223
+ }
224
+ try {
225
+ const parsed = spec.parse(source[key]);
226
+ if (parsed === void 0) throw new Error("invalid value");
227
+ value[key] = parsed;
228
+ } catch (error) {
229
+ problems.push({
230
+ section: key,
231
+ message: error instanceof Error ? error.message : String(error)
232
+ });
233
+ value[key] = fallback();
234
+ }
235
+ }
236
+ const unknown = {};
237
+ for (const key of Object.keys(source)) {
238
+ if (!(key in sections) && !ignore.has(key) && !_chunk2BSBFBOAcjs.isUnsafeJsonKey.call(void 0, key)) unknown[key] = source[key];
239
+ }
240
+ return { value, problems, unknown };
241
+ }
242
+ function loadDocument(json, sections, options) {
243
+ const { doc, report } = migrateDocument(json, options);
244
+ const ignore = _nullishCoalesce(options.ignore, () => ( [_nullishCoalesce(options.versionKey, () => ( "version"))]));
245
+ const result = loadSections(_optionalChain([report, 'access', _3 => _3.readOnly, 'optionalAccess', _4 => _4.kind]) === "invalid" ? {} : doc, sections, {
246
+ ignore
247
+ });
248
+ report.problems = result.problems;
249
+ report.unknownKeys = Object.keys(result.unknown);
250
+ return { ...result, report };
251
+ }
252
+
253
+ // src/persistence/editorDocument.ts
254
+ var EditorDocumentLoadError = class extends Error {
255
+ /** The `LoadReport` when the input was a file that could not be migrated. */
256
+
257
+ constructor(message, report) {
258
+ super(message);
259
+ this.name = "EditorDocumentLoadError";
260
+ this.report = report;
261
+ }
262
+ };
263
+ var EDITOR_DOCUMENT_FORMAT = "pixerate.editor-document";
264
+ var KIND = /^[a-z][a-z0-9_]*$/;
265
+ function isEditorDocumentFile(value) {
266
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
267
+ const v = value;
268
+ return v.format === EDITOR_DOCUMENT_FORMAT && typeof v.kind === "string" && typeof v.formatVersion === "number" && "document" in v;
269
+ }
270
+ function toEditorDocumentFile(doc, name) {
271
+ return {
272
+ format: EDITOR_DOCUMENT_FORMAT,
273
+ kind: doc.kind,
274
+ formatVersion: doc.formatVersion,
275
+ ...name ? { name } : {},
276
+ document: doc.getDocument()
277
+ };
278
+ }
279
+ function serializeEditorDocument(doc, options = {}) {
280
+ return JSON.stringify(toEditorDocumentFile(doc, options.name), null, options.space);
281
+ }
282
+ function parseEditorDocument(text, options = {}) {
283
+ let value;
284
+ try {
285
+ value = _chunk2BSBFBOAcjs.stripPrototypeKeys.call(void 0, JSON.parse(text));
286
+ } catch (error) {
287
+ throw new EditorDocumentLoadError(`The file is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
288
+ }
289
+ if (!isEditorDocumentFile(value)) {
290
+ throw new EditorDocumentLoadError(`The file is not a saved editor document (expected "format": "${EDITOR_DOCUMENT_FORMAT}").`);
291
+ }
292
+ if (options.kind && value.kind !== options.kind) {
293
+ throw new EditorDocumentLoadError(`The file is a ${value.kind} document, not a ${options.kind} document.`);
294
+ }
295
+ return value;
296
+ }
297
+ function defineEditorDocument(spec) {
298
+ if (!KIND.test(spec.kind)) throw new Error(`Editor document kind "${spec.kind}" must match ${KIND}.`);
299
+ const formatVersion = _nullishCoalesce(spec.formatVersion, () => ( 1));
300
+ const listeners = /* @__PURE__ */ new Set();
301
+ let revision = 0;
302
+ let unsubscribe = null;
303
+ let connected = false;
304
+ const connect = () => {
305
+ if (unsubscribe) return;
306
+ if (connected) revision++;
307
+ connected = true;
308
+ unsubscribe = spec.subscribe(() => {
309
+ revision++;
310
+ listeners.forEach((listener) => {
311
+ try {
312
+ listener();
313
+ } catch (error) {
314
+ console.error(`[${spec.kind} document] Error in change listener:`, error);
315
+ }
316
+ });
317
+ });
318
+ };
319
+ connect();
320
+ const unwrap = (input) => {
321
+ if (!isEditorDocumentFile(input)) return { document: input, report: createLoadReport({ version: formatVersion }) };
322
+ if (input.kind !== spec.kind) throw new EditorDocumentLoadError(`This is a ${input.kind} document; it cannot be opened in the ${spec.kind} editor.`);
323
+ const steps = Object.fromEntries(
324
+ Object.entries(_nullishCoalesce(spec.migrations, () => ( {}))).map(([v, step]) => [v, (w) => ({ ...w, document: step(w.document) })])
325
+ );
326
+ const { doc, report } = migrateDocument(
327
+ { formatVersion: input.formatVersion, document: input.document },
328
+ { currentVersion: formatVersion, versionKey: "formatVersion", steps }
329
+ );
330
+ if (report.readOnly) throw new EditorDocumentLoadError(`Cannot open the ${spec.kind} document: ${report.readOnly.message}.`, report);
331
+ return { document: doc.document, report };
332
+ };
333
+ return {
334
+ kind: spec.kind,
335
+ formatVersion,
336
+ recordsLoads: spec.recordsLoads !== false,
337
+ getDocument: () => spec.assets ? externalizeAssets(spec.get(), spec.assets) : spec.get(),
338
+ loadDocument(input, options = {}) {
339
+ const { document, report } = unwrap(input);
340
+ if (document === void 0 || document === null) throw new EditorDocumentLoadError(`No ${spec.kind} document was given.`);
341
+ try {
342
+ const result = spec.load(spec.assets ? internalizeAssets(document, spec.assets) : document, { history: _nullishCoalesce(options.history, () => ( "reset")) });
343
+ if (_optionalChain([result, 'optionalAccess', _5 => _5.problems, 'optionalAccess', _6 => _6.length])) report.problems.push(...result.problems);
344
+ } catch (error) {
345
+ if (error instanceof EditorDocumentLoadError) throw error;
346
+ throw new EditorDocumentLoadError(error instanceof Error ? error.message : String(error));
347
+ }
348
+ return report;
349
+ },
350
+ revision: () => {
351
+ connect();
352
+ return revision;
353
+ },
354
+ subscribe(listener) {
355
+ connect();
356
+ listeners.add(listener);
357
+ return () => {
358
+ listeners.delete(listener);
359
+ };
360
+ },
361
+ history: spec.history,
362
+ ...spec.assets ? { assets: spec.assets } : {},
363
+ readOnly: () => _nullishCoalesce(_optionalChain([spec, 'access', _7 => _7.readOnly, 'optionalCall', _8 => _8()]), () => ( false)),
364
+ destroy() {
365
+ _optionalChain([unsubscribe, 'optionalCall', _9 => _9()]);
366
+ unsubscribe = null;
367
+ }
368
+ };
369
+ }
370
+
371
+
372
+
373
+
374
+
375
+
376
+
377
+
378
+
379
+
380
+
381
+
382
+
383
+
384
+
385
+
386
+
387
+
388
+
389
+
390
+
391
+
392
+
393
+ exports.EDITOR_ASSET_PREFIX = EDITOR_ASSET_PREFIX; exports.isInlineAsset = isInlineAsset; exports.createEditorAssetRegistry = createEditorAssetRegistry; exports.externalizeAssets = externalizeAssets; exports.collectAssetRefs = collectAssetRefs; exports.internalizeAssets = internalizeAssets; exports.persistEditorAssets = persistEditorAssets; exports.preloadEditorAssets = preloadEditorAssets; exports.withEditorAssets = withEditorAssets; exports.hasLoadProblems = hasLoadProblems; exports.createLoadReport = createLoadReport; exports.migrateDocument = migrateDocument; exports.loadSections = loadSections; exports.loadDocument = loadDocument; exports.EditorDocumentLoadError = EditorDocumentLoadError; exports.EDITOR_DOCUMENT_FORMAT = EDITOR_DOCUMENT_FORMAT; exports.isEditorDocumentFile = isEditorDocumentFile; exports.toEditorDocumentFile = toEditorDocumentFile; exports.serializeEditorDocument = serializeEditorDocument; exports.parseEditorDocument = parseEditorDocument; exports.defineEditorDocument = defineEditorDocument;