@pixerate/editor 0.164.0 → 0.165.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 (141) hide show
  1. package/dist/agent/index.cjs +54 -39
  2. package/dist/agent/index.js +24 -9
  3. package/dist/animation/index.cjs +6 -5
  4. package/dist/animation/index.js +5 -4
  5. package/dist/animation-editor/index.cjs +65 -64
  6. package/dist/animation-editor/index.js +8 -7
  7. package/dist/bridge/cli.cjs +3 -3
  8. package/dist/bridge/cli.js +2 -2
  9. package/dist/bridge/index.cjs +3 -3
  10. package/dist/bridge/index.js +2 -2
  11. package/dist/canvas/index.cjs +89 -87
  12. package/dist/canvas/index.js +11 -9
  13. package/dist/chart/controller.d.cts +31 -2
  14. package/dist/chart/controller.d.ts +31 -2
  15. package/dist/chart/index.cjs +504 -132
  16. package/dist/chart/index.d.cts +2 -0
  17. package/dist/chart/index.d.ts +2 -0
  18. package/dist/chart/index.js +386 -14
  19. package/dist/chart/layout-families.d.cts +7 -0
  20. package/dist/chart/layout-families.d.ts +7 -0
  21. package/dist/chart/links.d.cts +34 -0
  22. package/dist/chart/links.d.ts +34 -0
  23. package/dist/chart/mermaid.d.cts +9 -6
  24. package/dist/chart/mermaid.d.ts +9 -6
  25. package/dist/chart/schemas.d.cts +3 -0
  26. package/dist/chart/schemas.d.ts +3 -0
  27. package/dist/chart/spec.d.cts +3 -2
  28. package/dist/chart/spec.d.ts +3 -2
  29. package/dist/chart/style.d.cts +33 -0
  30. package/dist/chart/style.d.ts +33 -0
  31. package/dist/chart/types.d.cts +24 -2
  32. package/dist/chart/types.d.ts +24 -2
  33. package/dist/{chunk-TALQONZ5.js → chunk-2J5VLJHC.js} +3 -3
  34. package/dist/{chunk-3NEZJCBY.js → chunk-2ZRN43IN.js} +340 -201
  35. package/dist/{chunk-ZVNAMTFO.cjs → chunk-3FSUJIXN.cjs} +18 -174
  36. package/dist/{chunk-RQCMSEM5.cjs → chunk-4QUUHTGJ.cjs} +2 -2
  37. package/dist/{chunk-CIPIESX4.cjs → chunk-4ZC5QJE2.cjs} +3 -3
  38. package/dist/{chunk-S6X2QRVU.cjs → chunk-5UEFBM2M.cjs} +1 -138
  39. package/dist/{chunk-YSAGBIRW.cjs → chunk-64VWWR5U.cjs} +16 -16
  40. package/dist/{chunk-QYZGBVNC.js → chunk-7272D3K2.js} +10 -8
  41. package/dist/{chunk-462WGGXX.cjs → chunk-AMX23CSN.cjs} +27 -16
  42. package/dist/{chunk-3VLOOO3G.js → chunk-BDIM6NVW.js} +1 -1
  43. package/dist/{chunk-POR54B55.js → chunk-CRFSQWKQ.js} +4 -1
  44. package/dist/{chunk-GZ2FM3ZB.js → chunk-DKNEQX7T.js} +6 -162
  45. package/dist/{chunk-JCXMJUQO.cjs → chunk-EGZM52EO.cjs} +3 -3
  46. package/dist/{chunk-ES3UEVUT.cjs → chunk-EUIDTZNQ.cjs} +112 -110
  47. package/dist/{chunk-H3OEM3Q2.js → chunk-F6R67I3A.js} +1 -1
  48. package/dist/{chunk-5FNGLV2D.js → chunk-FEU2XVQH.js} +15 -3
  49. package/dist/{chunk-SZA42R4N.js → chunk-FRBRLKNQ.js} +154 -16
  50. package/dist/chunk-HIDFL5LQ.js +484 -0
  51. package/dist/{chunk-MKTDELCD.js → chunk-I5MRJW7B.js} +1 -1
  52. package/dist/{chunk-SDHZG5TF.js → chunk-ILP77UD6.js} +160 -2
  53. package/dist/{chunk-GKNEJ6EN.cjs → chunk-IMRXC7OA.cjs} +241 -103
  54. package/dist/chunk-KGRZMHZB.js +204 -0
  55. package/dist/{chunk-SET6KJOP.js → chunk-LPIKXPBM.js} +1 -1
  56. package/dist/{chunk-BQWGN5WH.js → chunk-M2TPMYJE.js} +1 -1
  57. package/dist/{chunk-GTELFJRE.cjs → chunk-M5GLQQWG.cjs} +2 -2
  58. package/dist/{chunk-4VU4CP7R.js → chunk-MHLU6GRJ.js} +1 -138
  59. package/dist/{chunk-D54JHQK2.cjs → chunk-MKXK6E4O.cjs} +51 -51
  60. package/dist/{chunk-DAPQGA55.js → chunk-N7NBGT2Y.js} +2 -2
  61. package/dist/chunk-O6OGNDND.js +164 -0
  62. package/dist/{chunk-22KLZZGH.cjs → chunk-ODFCS7HF.cjs} +8 -8
  63. package/dist/{chunk-PA3IMPPS.cjs → chunk-OVYQAYGH.cjs} +81 -81
  64. package/dist/{chunk-YXOW456B.js → chunk-PPEDZ5WR.js} +1 -1
  65. package/dist/{chunk-YGG7WDWT.cjs → chunk-Q25WAFTD.cjs} +21 -18
  66. package/dist/{chunk-SBQVEBSU.cjs → chunk-QO2T6KA5.cjs} +165 -67
  67. package/dist/{chunk-24M7VD6M.cjs → chunk-S4EIAIEW.cjs} +7 -7
  68. package/dist/{chunk-M4MIZPQI.cjs → chunk-SJ2CPTQC.cjs} +189 -15
  69. package/dist/chunk-TFF2GTGN.cjs +153 -0
  70. package/dist/chunk-TTCJPX4U.cjs +204 -0
  71. package/dist/{chunk-NZD2MZJC.cjs → chunk-TVQW26AV.cjs} +35 -23
  72. package/dist/{chunk-R3P2M7HU.cjs → chunk-UVXTOZ2B.cjs} +346 -207
  73. package/dist/{chunk-WI7QJA7A.cjs → chunk-UXETV2NC.cjs} +161 -3
  74. package/dist/{chunk-Z4P2RBMJ.js → chunk-V5GSY3NC.js} +101 -3
  75. package/dist/{chunk-QY4KUDMY.js → chunk-VRXXAXUT.js} +2 -2
  76. package/dist/chunk-VU6WQSMB.cjs +164 -0
  77. package/dist/{chunk-OXERWBKE.js → chunk-X5W645RI.js} +3 -3
  78. package/dist/{chunk-NHLYK3AX.js → chunk-XBQX76CT.js} +182 -8
  79. package/dist/{chunk-5AARIS3R.cjs → chunk-XCDGM7TD.cjs} +37 -37
  80. package/dist/{chunk-EVXQNQND.js → chunk-XZB3TJ6K.js} +16 -5
  81. package/dist/chunk-YBAPT7NL.js +153 -0
  82. package/dist/chunk-Z2UQYMPS.cjs +484 -0
  83. package/dist/color/index.cjs +5 -3
  84. package/dist/color/index.js +12 -10
  85. package/dist/diagram/index.cjs +55 -243
  86. package/dist/diagram/index.js +12 -200
  87. package/dist/export/index.cjs +7 -6
  88. package/dist/export/index.js +6 -5
  89. package/dist/extensions/index.cjs +12 -9
  90. package/dist/extensions/index.js +11 -8
  91. package/dist/gradient/index.cjs +29 -27
  92. package/dist/gradient/index.js +6 -4
  93. package/dist/image-editor/index.cjs +644 -643
  94. package/dist/image-editor/index.js +7 -6
  95. package/dist/index.cjs +21 -18
  96. package/dist/index.js +14 -11
  97. package/dist/paint-editor/index.cjs +19 -18
  98. package/dist/paint-editor/index.js +7 -6
  99. package/dist/parameters/index.cjs +2 -2
  100. package/dist/parameters/index.js +1 -1
  101. package/dist/persistence/assetWrites.d.cts +22 -0
  102. package/dist/persistence/assetWrites.d.ts +22 -0
  103. package/dist/persistence/assets.d.cts +71 -0
  104. package/dist/persistence/assets.d.ts +71 -0
  105. package/dist/persistence/documentStore.d.cts +17 -1
  106. package/dist/persistence/documentStore.d.ts +17 -1
  107. package/dist/persistence/documentTools.d.cts +5 -1
  108. package/dist/persistence/documentTools.d.ts +5 -1
  109. package/dist/persistence/editorAutosave.d.cts +7 -0
  110. package/dist/persistence/editorAutosave.d.ts +7 -0
  111. package/dist/persistence/index.cjs +141 -21
  112. package/dist/persistence/index.js +130 -10
  113. package/dist/persistence/storage.d.cts +13 -1
  114. package/dist/persistence/storage.d.ts +13 -1
  115. package/dist/spreadsheet/index.cjs +3 -3
  116. package/dist/spreadsheet/index.js +2 -2
  117. package/dist/tokens/index.cjs +11 -3
  118. package/dist/tokens/index.d.cts +1 -0
  119. package/dist/tokens/index.d.ts +1 -0
  120. package/dist/tokens/index.js +10 -2
  121. package/dist/tokens/style.d.cts +36 -0
  122. package/dist/tokens/style.d.ts +36 -0
  123. package/dist/tools/index.cjs +15 -3
  124. package/dist/tools/index.d.cts +2 -0
  125. package/dist/tools/index.d.ts +2 -0
  126. package/dist/tools/index.js +14 -2
  127. package/dist/tools/style-tools.d.cts +19 -0
  128. package/dist/tools/style-tools.d.ts +19 -0
  129. package/dist/tools/style.d.cts +212 -0
  130. package/dist/tools/style.d.ts +212 -0
  131. package/dist/tools/view.d.cts +6 -0
  132. package/dist/tools/view.d.ts +6 -0
  133. package/dist/typography/index.cjs +8 -6
  134. package/dist/typography/index.js +5 -3
  135. package/dist/vector/index.cjs +953 -952
  136. package/dist/vector/index.js +7 -6
  137. package/dist/video-editor/index.cjs +8 -7
  138. package/dist/video-editor/index.js +6 -5
  139. package/package.json +1 -1
  140. package/dist/chunk-ERAGQL2N.cjs +0 -68
  141. package/dist/chunk-KMU6QJB7.js +0 -68
@@ -3,6 +3,42 @@
3
3
 
4
4
  var _chunk2BSBFBOAcjs = require('./chunk-2BSBFBOA.cjs');
5
5
 
6
+ // src/persistence/assetWrites.ts
7
+ var leases = /* @__PURE__ */ new Map();
8
+ var watchers = /* @__PURE__ */ new Set();
9
+ function leaseAssetRefs(refs) {
10
+ const held = [...new Set(refs)];
11
+ for (const ref of held) {
12
+ leases.set(ref, (_nullishCoalesce(leases.get(ref), () => ( 0))) + 1);
13
+ for (const touched of watchers) touched.add(ref);
14
+ }
15
+ let released = false;
16
+ return () => {
17
+ if (released) return;
18
+ released = true;
19
+ for (const ref of held) {
20
+ const n = (_nullishCoalesce(leases.get(ref), () => ( 1))) - 1;
21
+ if (n > 0) leases.set(ref, n);
22
+ else leases.delete(ref);
23
+ }
24
+ };
25
+ }
26
+ function watchAssetLeases() {
27
+ const touched = new Set(leases.keys());
28
+ watchers.add(touched);
29
+ return { touched, stop: () => void watchers.delete(touched) };
30
+ }
31
+ function withAssetLock(prefix, mode, task) {
32
+ let locks;
33
+ try {
34
+ locks = _optionalChain([globalThis, 'access', _ => _.navigator, 'optionalAccess', _2 => _2.locks]);
35
+ } catch (e) {
36
+ locks = void 0;
37
+ }
38
+ if (!locks || typeof locks.request !== "function") return task();
39
+ return locks.request(`pixerate-editor-assets:${prefix}`, { mode }, task);
40
+ }
41
+
6
42
  // src/persistence/assets.ts
7
43
  var EDITOR_ASSET_PREFIX = "pixerate-asset:";
8
44
  var REF = /pixerate-asset:[0-9a-z]+-[0-9a-z]+(?:~[0-9]+)?/g;
@@ -45,7 +81,8 @@ function createEditorAssetRegistry() {
45
81
  },
46
82
  get size() {
47
83
  return byRef.size;
48
- }
84
+ },
85
+ refs: () => [...byRef.keys()]
49
86
  };
50
87
  }
51
88
  function externalizeAssets(value, registry) {
@@ -85,11 +122,22 @@ function internalizeAssets(value, registry) {
85
122
  return walk(value);
86
123
  }
87
124
  var persisted = /* @__PURE__ */ new WeakMap();
88
- var assetKey = (ref, options) => `${_nullishCoalesce(options.prefix, () => ( "pixerate.assets:"))}${ref.slice(EDITOR_ASSET_PREFIX.length)}`;
125
+ var assetPrefix = (options) => _nullishCoalesce(options.prefix, () => ( "pixerate.assets:"));
126
+ var assetKey = (ref, options) => `${assetPrefix(options)}${ref.slice(EDITOR_ASSET_PREFIX.length)}`;
127
+ var markerKey = (options) => `${assetPrefix(options)}#collected`;
128
+ var ASSET_ID = /^[0-9a-z]+-[0-9a-z]+(?:~[0-9]+)?$/;
89
129
  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)) {
130
+ const refs = collectAssetRefs(document);
131
+ if (!refs.length) return;
132
+ const cache = _nullishCoalesce(persisted.get(storage), () => ( { marker: void 0, keys: /* @__PURE__ */ new Set() }));
133
+ persisted.set(storage, cache);
134
+ const marker = await storage.get(markerKey(options)).catch(() => void 0);
135
+ if (marker === void 0 || marker !== cache.marker) {
136
+ cache.keys.clear();
137
+ cache.marker = marker;
138
+ }
139
+ const written = cache.keys;
140
+ for (const ref of refs) {
93
141
  const key = assetKey(ref, options);
94
142
  if (written.has(key)) continue;
95
143
  const data = registry.get(ref);
@@ -120,11 +168,134 @@ function withEditorAssets(storage, registry, options = {}) {
120
168
  return value;
121
169
  },
122
170
  async set(key, value) {
123
- if (value.includes(EDITOR_ASSET_PREFIX)) await persistEditorAssets(storage, registry, value, options);
124
- await storage.set(key, value);
171
+ if (!value.includes(EDITOR_ASSET_PREFIX)) return storage.set(key, value);
172
+ await writeWithAssets(storage, registry, value, options, () => storage.set(key, value));
125
173
  },
126
- remove: (key) => storage.remove(key)
174
+ remove: (key) => storage.remove(key),
175
+ ...storage.keys ? { keys: (prefix) => storage.keys(prefix) } : {}
176
+ };
177
+ }
178
+ async function writeWithAssets(storage, registry, document, options, write) {
179
+ const release = leaseAssetRefs(collectAssetRefs(document));
180
+ try {
181
+ await withAssetLock(assetPrefix(options), "shared", async () => {
182
+ if (registry) await persistEditorAssets(storage, registry, document, options);
183
+ await write();
184
+ });
185
+ } finally {
186
+ release();
187
+ }
188
+ }
189
+ var isRegistry = (value) => !!value && typeof value === "object" && ["put", "get", "has", "set"].every((k) => typeof value[k] === "function");
190
+ var refChars = (ref) => parseInt(ref.slice(EDITOR_ASSET_PREFIX.length).split("-")[0], 36) || 0;
191
+ function keptRefs(keep) {
192
+ const out = /* @__PURE__ */ new Set();
193
+ const addRegistry = (registry) => {
194
+ if (typeof registry.refs !== "function") {
195
+ throw new Error("A registry passed in keep cannot list its references (it has no refs()). Use createEditorAssetRegistry, or pass the documents to keep instead.");
196
+ }
197
+ for (const ref of registry.refs()) out.add(ref);
127
198
  };
199
+ for (const item of keep) {
200
+ if (isRegistry(item)) addRegistry(item);
201
+ else if (item && typeof item === "object" && isRegistry(item.assets)) addRegistry(item.assets);
202
+ else for (const ref of collectAssetRefs(item)) out.add(ref);
203
+ }
204
+ return out;
205
+ }
206
+ async function collectEditorAssetGarbage(storage, options = {}) {
207
+ if (typeof storage.keys !== "function") {
208
+ throw new Error(
209
+ `This ${storage.kind} storage cannot list its keys, so unreferenced assets cannot be found. Give the adapter a keys(prefix) method (every built-in adapter has one).`
210
+ );
211
+ }
212
+ const listKeys = storage.keys.bind(storage);
213
+ const prefix = assetPrefix(options);
214
+ const keep = keptRefs(_nullishCoalesce(options.keep, () => ( [])));
215
+ const dryRun = options.dryRun === true;
216
+ return withAssetLock(prefix, "exclusive", async () => {
217
+ const watch = watchAssetLeases();
218
+ try {
219
+ const assetKeys = (await listKeys(prefix)).filter((key) => ASSET_ID.test(key.slice(prefix.length)));
220
+ const others = (await listKeys("")).filter((key) => !key.startsWith(prefix));
221
+ const live = /* @__PURE__ */ new Set();
222
+ for (const key of others) {
223
+ const value = await storage.get(key);
224
+ if (value !== null && value.includes(EDITOR_ASSET_PREFIX)) for (const ref of collectAssetRefs(value)) live.add(ref);
225
+ }
226
+ const toRef = (key) => `${EDITOR_ASSET_PREFIX}${key.slice(prefix.length)}`;
227
+ let referenced = 0;
228
+ let kept = 0;
229
+ const candidates = [];
230
+ for (const key of assetKeys) {
231
+ const ref = toRef(key);
232
+ if (live.has(ref)) referenced++;
233
+ else if (keep.has(ref) || watch.touched.has(ref)) kept++;
234
+ else candidates.push(ref);
235
+ }
236
+ let unreferenced = candidates;
237
+ if (options.only) {
238
+ const wanted = new Set(options.only);
239
+ const stale = [...wanted].filter((ref) => !candidates.includes(ref));
240
+ if (stale.length) {
241
+ throw new Error(
242
+ `${stale.length} of the given asset${stale.length === 1 ? " is" : "s are"} not unreferenced in storage now (${stale.slice(0, 3).join(", ")}${stale.length > 3 ? ", \u2026" : ""}): unknown, already deleted, referenced or in use. Nothing was deleted; find the unreferenced assets again.`
243
+ );
244
+ }
245
+ unreferenced = candidates.filter((ref) => wanted.has(ref));
246
+ }
247
+ const report = {
248
+ assets: assetKeys.length,
249
+ scannedKeys: others.length,
250
+ referenced,
251
+ kept,
252
+ unreferenced,
253
+ unreferencedChars: unreferenced.reduce((n, ref) => n + refChars(ref), 0),
254
+ removed: [],
255
+ freedChars: 0,
256
+ dryRun
257
+ };
258
+ if (dryRun || !unreferenced.length) return report;
259
+ await storage.set(markerKey(options), `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`);
260
+ for (const ref of unreferenced) {
261
+ if (watch.touched.has(ref)) {
262
+ report.kept++;
263
+ continue;
264
+ }
265
+ try {
266
+ await storage.remove(assetKey(ref, options));
267
+ } catch (error) {
268
+ throw new Error(
269
+ `Deleted ${report.removed.length} of ${unreferenced.length} unreferenced assets, then storage failed: ${error instanceof Error ? error.message : String(error)}. The rest are still stored and nothing refers to the deleted ones; run the collection again.`
270
+ );
271
+ }
272
+ report.removed.push(ref);
273
+ report.freedChars += refChars(ref);
274
+ }
275
+ return report;
276
+ } finally {
277
+ watch.stop();
278
+ }
279
+ });
280
+ }
281
+ async function tryCollectEditorAssetGarbage(storage, options = {}) {
282
+ if (typeof storage.keys !== "function") return null;
283
+ try {
284
+ return await collectEditorAssetGarbage(storage, options);
285
+ } catch (e2) {
286
+ return null;
287
+ }
288
+ }
289
+ async function collectRetiredEditorAssets(storage, doc, setting = true) {
290
+ if (!doc.assets || setting === false) return null;
291
+ const extra = setting === true ? {} : setting;
292
+ let current;
293
+ try {
294
+ current = doc.getDocument();
295
+ } catch (e3) {
296
+ return null;
297
+ }
298
+ return tryCollectEditorAssetGarbage(storage, { ...extra, keep: [current, ..._nullishCoalesce(extra.keep, () => ( []))] });
128
299
  }
129
300
 
130
301
  // src/persistence/migrate.ts
@@ -148,7 +319,7 @@ function toObject(json) {
148
319
  if (typeof json === "string") {
149
320
  try {
150
321
  value = JSON.parse(json);
151
- } catch (e) {
322
+ } catch (e4) {
152
323
  return void 0;
153
324
  }
154
325
  }
@@ -185,7 +356,7 @@ function migrateDocument(json, options) {
185
356
  }
186
357
  let doc = deepClone(original);
187
358
  for (let step = from; step < target; step++) {
188
- const fn = _optionalChain([options, 'access', _ => _.steps, 'optionalAccess', _2 => _2[step]]);
359
+ const fn = _optionalChain([options, 'access', _3 => _3.steps, 'optionalAccess', _4 => _4[step]]);
189
360
  if (!fn) {
190
361
  report.readOnly = {
191
362
  kind: "migrationFailed",
@@ -242,7 +413,7 @@ function loadSections(doc, sections, options = {}) {
242
413
  function loadDocument(json, sections, options) {
243
414
  const { doc, report } = migrateDocument(json, options);
244
415
  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, {
416
+ const result = loadSections(_optionalChain([report, 'access', _5 => _5.readOnly, 'optionalAccess', _6 => _6.kind]) === "invalid" ? {} : doc, sections, {
246
417
  ignore
247
418
  });
248
419
  report.problems = result.problems;
@@ -340,7 +511,7 @@ function defineEditorDocument(spec) {
340
511
  if (document === void 0 || document === null) throw new EditorDocumentLoadError(`No ${spec.kind} document was given.`);
341
512
  try {
342
513
  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);
514
+ if (_optionalChain([result, 'optionalAccess', _7 => _7.problems, 'optionalAccess', _8 => _8.length])) report.problems.push(...result.problems);
344
515
  } catch (error) {
345
516
  if (error instanceof EditorDocumentLoadError) throw error;
346
517
  throw new EditorDocumentLoadError(error instanceof Error ? error.message : String(error));
@@ -360,9 +531,9 @@ function defineEditorDocument(spec) {
360
531
  },
361
532
  history: spec.history,
362
533
  ...spec.assets ? { assets: spec.assets } : {},
363
- readOnly: () => _nullishCoalesce(_optionalChain([spec, 'access', _7 => _7.readOnly, 'optionalCall', _8 => _8()]), () => ( false)),
534
+ readOnly: () => _nullishCoalesce(_optionalChain([spec, 'access', _9 => _9.readOnly, 'optionalCall', _10 => _10()]), () => ( false)),
364
535
  destroy() {
365
- _optionalChain([unsubscribe, 'optionalCall', _9 => _9()]);
536
+ _optionalChain([unsubscribe, 'optionalCall', _11 => _11()]);
366
537
  unsubscribe = null;
367
538
  }
368
539
  };
@@ -390,4 +561,7 @@ function defineEditorDocument(spec) {
390
561
 
391
562
 
392
563
 
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;
564
+
565
+
566
+
567
+ 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.collectEditorAssetGarbage = collectEditorAssetGarbage; exports.tryCollectEditorAssetGarbage = tryCollectEditorAssetGarbage; exports.collectRetiredEditorAssets = collectRetiredEditorAssets; 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;
@@ -0,0 +1,153 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+ var _chunk5UEFBM2Mcjs = require('./chunk-5UEFBM2M.cjs');
14
+
15
+ // src/color/gamut.ts
16
+ var clamp01 = (v) => Math.min(1, Math.max(0, v));
17
+ function inSrgbGamut(c, epsilon = 1e-5) {
18
+ return c.r >= -epsilon && c.r <= 1 + epsilon && c.g >= -epsilon && c.g <= 1 + epsilon && c.b >= -epsilon && c.b <= 1 + epsilon;
19
+ }
20
+ function deltaEOK(a, b) {
21
+ const la = _chunk5UEFBM2Mcjs.rgbToOklab.call(void 0, a);
22
+ const lb = _chunk5UEFBM2Mcjs.rgbToOklab.call(void 0, b);
23
+ return Math.hypot(la.l - lb.l, la.a - lb.a, la.b - lb.b);
24
+ }
25
+ function toSrgbGamut(c) {
26
+ const lch = _chunk5UEFBM2Mcjs.oklabToOklch.call(void 0, _chunk5UEFBM2Mcjs.rgbToOklab.call(void 0, c));
27
+ if (lch.l >= 1) return { r: 1, g: 1, b: 1, a: c.a };
28
+ if (lch.l <= 0) return { r: 0, g: 0, b: 0, a: c.a };
29
+ if (inSrgbGamut(c)) {
30
+ return { r: clamp01(c.r), g: clamp01(c.g), b: clamp01(c.b), a: c.a };
31
+ }
32
+ let low = 0;
33
+ let high = lch.c;
34
+ let clippedCandidate = { r: clamp01(c.r), g: clamp01(c.g), b: clamp01(c.b), a: c.a };
35
+ const JND = 0.02;
36
+ const EPS = 1e-4;
37
+ for (let i = 0; i < 30; i++) {
38
+ const mid = (low + high) / 2;
39
+ const candidate = _chunk5UEFBM2Mcjs.oklabToRgb.call(void 0, _chunk5UEFBM2Mcjs.oklchToOklab.call(void 0, { l: lch.l, c: mid, h: lch.h, alpha: c.a }));
40
+ const clipped = {
41
+ r: clamp01(candidate.r),
42
+ g: clamp01(candidate.g),
43
+ b: clamp01(candidate.b),
44
+ a: c.a
45
+ };
46
+ clippedCandidate = clipped;
47
+ const dE = deltaEOK(candidate, clipped);
48
+ if (dE < JND) {
49
+ if (JND - dE < EPS) {
50
+ return clipped;
51
+ }
52
+ low = mid;
53
+ } else {
54
+ high = mid;
55
+ }
56
+ if (high - low < 1e-4) {
57
+ break;
58
+ }
59
+ }
60
+ return clippedCandidate;
61
+ }
62
+
63
+ // src/color/format.ts
64
+ var clamp012 = (v) => Math.min(1, Math.max(0, v));
65
+ var byte = (v) => Math.round(clamp012(v) * 255);
66
+ var hex2 = (n) => n.toString(16).padStart(2, "0");
67
+ var round2 = (n) => (Math.round(n * 100) / 100).toString();
68
+ function formatHex(c) {
69
+ const mapped = toSrgbGamut(c);
70
+ const head = `#${hex2(byte(mapped.r))}${hex2(byte(mapped.g))}${hex2(byte(mapped.b))}`;
71
+ const alpha = byte(mapped.a);
72
+ return alpha === 255 ? head : head + hex2(alpha);
73
+ }
74
+ function formatColor(c, format) {
75
+ switch (format) {
76
+ case "hex":
77
+ return formatHex(c);
78
+ case "rgb": {
79
+ const inGamut = toSrgbGamut(c);
80
+ const r = byte(inGamut.r);
81
+ const g = byte(inGamut.g);
82
+ const b = byte(inGamut.b);
83
+ return c.a < 1 ? `rgb(${r} ${g} ${b} / ${round2(c.a)})` : `rgb(${r} ${g} ${b})`;
84
+ }
85
+ case "hsl": {
86
+ const hsl = _chunk5UEFBM2Mcjs.rgbToHsl.call(void 0, toSrgbGamut(c));
87
+ const h = (Math.round(hsl.h * 100) / 100).toString();
88
+ const s = (Math.round(hsl.s * 1e4) / 100).toString();
89
+ const l = (Math.round(hsl.l * 1e4) / 100).toString();
90
+ return c.a < 1 ? `hsl(${h} ${s}% ${l}% / ${round2(c.a)})` : `hsl(${h} ${s}% ${l}%)`;
91
+ }
92
+ case "oklch": {
93
+ const lch = _chunk5UEFBM2Mcjs.oklabToOklch.call(void 0, _chunk5UEFBM2Mcjs.rgbToOklab.call(void 0, c));
94
+ const l = (lch.l * 100).toFixed(2);
95
+ const ch = lch.c.toFixed(4);
96
+ const h = lch.h.toFixed(2);
97
+ return c.a < 1 ? `oklch(${l}% ${ch} ${h} / ${round2(c.a)})` : `oklch(${l}% ${ch} ${h})`;
98
+ }
99
+ case "oklab": {
100
+ const lab = _chunk5UEFBM2Mcjs.rgbToOklab.call(void 0, c);
101
+ const l = (lab.l * 100).toFixed(2);
102
+ const a = lab.a.toFixed(4);
103
+ const b = lab.b.toFixed(4);
104
+ return c.a < 1 ? `oklab(${l}% ${a} ${b} / ${round2(c.a)})` : `oklab(${l}% ${a} ${b})`;
105
+ }
106
+ case "p3": {
107
+ const linSrgb = {
108
+ r: _chunk5UEFBM2Mcjs.srgbToLinear.call(void 0, c.r),
109
+ g: _chunk5UEFBM2Mcjs.srgbToLinear.call(void 0, c.g),
110
+ b: _chunk5UEFBM2Mcjs.srgbToLinear.call(void 0, c.b),
111
+ a: c.a
112
+ };
113
+ const linP3 = _chunk5UEFBM2Mcjs.linearSrgbToDisplayP3.call(void 0, linSrgb);
114
+ const r = _chunk5UEFBM2Mcjs.linearToSrgb.call(void 0, linP3.r).toFixed(4);
115
+ const g = _chunk5UEFBM2Mcjs.linearToSrgb.call(void 0, linP3.g).toFixed(4);
116
+ const b = _chunk5UEFBM2Mcjs.linearToSrgb.call(void 0, linP3.b).toFixed(4);
117
+ return c.a < 1 ? `color(display-p3 ${r} ${g} ${b} / ${round2(c.a)})` : `color(display-p3 ${r} ${g} ${b})`;
118
+ }
119
+ }
120
+ }
121
+ function normalizeColor(input) {
122
+ const parsed = _chunk5UEFBM2Mcjs.parseColor.call(void 0, input);
123
+ return parsed ? formatHex(parsed) : null;
124
+ }
125
+
126
+ // src/color/suggest.ts
127
+ function suggestAccessibleForeground(foreground, background, options = {}) {
128
+ const large = _nullishCoalesce(options.large, () => ( false));
129
+ const lch = _chunk5UEFBM2Mcjs.oklabToOklch.call(void 0, _chunk5UEFBM2Mcjs.rgbToOklab.call(void 0, foreground));
130
+ const asHex = (l) => _chunk5UEFBM2Mcjs.parseColor.call(void 0, formatHex(toSrgbGamut(_chunk5UEFBM2Mcjs.oklabToRgb.call(void 0, _chunk5UEFBM2Mcjs.oklchToOklab.call(void 0, { ...lch, l })))));
131
+ for (let d = 0.01; d <= 1; d += 0.01) {
132
+ const downCand = asHex(Math.max(0, lch.l - d));
133
+ const upCand = asHex(Math.min(1, lch.l + d));
134
+ const downRatio = _chunk5UEFBM2Mcjs.contrastRatio.call(void 0, downCand, background);
135
+ const upRatio = _chunk5UEFBM2Mcjs.contrastRatio.call(void 0, upCand, background);
136
+ const downPass = _chunk5UEFBM2Mcjs.contrastLevel.call(void 0, downRatio, { large }) !== "fail";
137
+ const upPass = _chunk5UEFBM2Mcjs.contrastLevel.call(void 0, upRatio, { large }) !== "fail";
138
+ if (downPass && upPass) return formatHex(downRatio >= upRatio ? downCand : upCand);
139
+ if (downPass) return formatHex(downCand);
140
+ if (upPass) return formatHex(upCand);
141
+ }
142
+ return void 0;
143
+ }
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+
153
+ exports.inSrgbGamut = inSrgbGamut; exports.deltaEOK = deltaEOK; exports.toSrgbGamut = toSrgbGamut; exports.formatHex = formatHex; exports.formatColor = formatColor; exports.normalizeColor = normalizeColor; exports.suggestAccessibleForeground = suggestAccessibleForeground;
@@ -0,0 +1,204 @@
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
+ var _chunkVU6WQSMBcjs = require('./chunk-VU6WQSMB.cjs');
4
+
5
+ // src/diagram/sankey/index.ts
6
+ function parseSankey(source) {
7
+ const split = _chunkVU6WQSMBcjs.splitSource.call(void 0, source);
8
+ if (!/^\s*sankey(?:-beta)?\b/i.test(split.header)) {
9
+ return { error: "Not a sankey diagram: the first line should be `sankey-beta`." };
10
+ }
11
+ const firstLine = split.headerIndex + 2;
12
+ const kept = [];
13
+ split.bodyLines.forEach((text, i) => {
14
+ if (/^\s*%%/.test(text)) return;
15
+ kept.push({ text: text.trim(), line: firstLine + i });
16
+ });
17
+ const records = readRecords(kept);
18
+ if ("error" in records) return records;
19
+ const nodes = [];
20
+ const seen = /* @__PURE__ */ new Set();
21
+ const add = (name) => {
22
+ if (!seen.has(name)) {
23
+ seen.add(name);
24
+ nodes.push(name);
25
+ }
26
+ };
27
+ const links = [];
28
+ for (const { fields, line } of records) {
29
+ if (fields.length !== 3) {
30
+ return {
31
+ error: `Expected three fields (source,target,value), found ${fields.length}.`,
32
+ line
33
+ };
34
+ }
35
+ const [source2, target, raw] = fields;
36
+ const value = Number.parseFloat(raw);
37
+ if (!Number.isFinite(value)) {
38
+ return { error: `"${raw}" is not a number.`, line };
39
+ }
40
+ add(source2);
41
+ add(target);
42
+ links.push({ source: source2, target, value });
43
+ }
44
+ if (!links.length) return { error: "No links: add lines like `A,B,10`." };
45
+ return { data: { nodes, links } };
46
+ }
47
+ function readRecords(lines) {
48
+ const records = [];
49
+ let i = 0;
50
+ while (i < lines.length) {
51
+ const start = lines[i];
52
+ if (start.text === "") {
53
+ i++;
54
+ continue;
55
+ }
56
+ const fields = [];
57
+ let text = start.text;
58
+ let pos = 0;
59
+ let field = "";
60
+ let quoted = false;
61
+ for (; ; ) {
62
+ if (quoted) {
63
+ const close = text.indexOf('"', pos);
64
+ if (close < 0) {
65
+ field += text.slice(pos);
66
+ i++;
67
+ if (i >= lines.length)
68
+ return { error: "A quoted field is never closed.", line: start.line };
69
+ field += "\n";
70
+ text = lines[i].text;
71
+ pos = 0;
72
+ continue;
73
+ }
74
+ field += text.slice(pos, close);
75
+ if (text[close + 1] === '"') {
76
+ field += '"';
77
+ pos = close + 2;
78
+ continue;
79
+ }
80
+ quoted = false;
81
+ pos = close + 1;
82
+ const rest = /^[ \t]*/.exec(text.slice(pos))[0].length;
83
+ pos += rest;
84
+ if (pos < text.length && text[pos] !== ",") {
85
+ return { error: "Unexpected text after a quoted field.", line: lines[i].line };
86
+ }
87
+ continue;
88
+ }
89
+ if (pos >= text.length) {
90
+ fields.push(field.trim());
91
+ break;
92
+ }
93
+ const ch = text[pos];
94
+ if (ch === ",") {
95
+ fields.push(field.trim());
96
+ field = "";
97
+ pos++;
98
+ } else if (ch === '"' && field.trim() === "") {
99
+ quoted = true;
100
+ field = "";
101
+ pos++;
102
+ } else if (ch === '"') {
103
+ return { error: "A quote inside an unquoted field.", line: lines[i].line };
104
+ } else {
105
+ field += ch;
106
+ pos++;
107
+ }
108
+ }
109
+ records.push({ fields, line: start.line });
110
+ i++;
111
+ }
112
+ return records;
113
+ }
114
+
115
+ // src/diagram/treemap/index.ts
116
+ var NAME = String.raw`(?:"([^"]*)"|'([^']*)')`;
117
+ var CLASS = String.raw`(?:\s*:::\s*([A-Za-z_]\w*))?`;
118
+ var SECTION_RE = new RegExp(String.raw`^${NAME}${CLASS}$`);
119
+ var LEAF_RE = new RegExp(String.raw`^${NAME}\s*[:,]\s*([0-9_.,]+)${CLASS}$`);
120
+ function parseTreemap(source) {
121
+ const split = _chunkVU6WQSMBcjs.splitSource.call(void 0, source);
122
+ if (!/^\s*treemap(?:-beta)?\b/i.test(split.header)) {
123
+ return { error: "Not a treemap: the first line should be `treemap-beta`." };
124
+ }
125
+ const data = { items: [] };
126
+ const stack = [];
127
+ const firstLine = split.headerIndex + 2;
128
+ const lines = split.bodyLines;
129
+ for (let i = 0; i < lines.length; i++) {
130
+ const raw = lines[i];
131
+ const line = firstLine + i;
132
+ const indent = /^[ \t]*/.exec(raw)[0].length;
133
+ const text = stripComment(raw).trim();
134
+ if (!text) continue;
135
+ const accBlock = /^accDescr\s*\{(.*)$/.exec(text);
136
+ if (accBlock) {
137
+ let body = accBlock[1];
138
+ while (!body.includes("}") && i + 1 < lines.length) body += `
139
+ ${lines[++i]}`;
140
+ if (!body.includes("}")) return { error: "`accDescr {` is never closed.", line };
141
+ data.accDescr = body.slice(0, body.indexOf("}")).trim();
142
+ continue;
143
+ }
144
+ const acc = /^(accTitle|accDescr)\s*:(.*)$/.exec(text);
145
+ if (acc) {
146
+ data[acc[1]] = acc[2].trim();
147
+ continue;
148
+ }
149
+ const title = /^title(?:[ \t]+(.*))?$/.exec(text);
150
+ if (title) {
151
+ data.title = (_nullishCoalesce(title[1], () => ( ""))).trim() || void 0;
152
+ continue;
153
+ }
154
+ if (/^classDef\s/.test(text)) continue;
155
+ let item;
156
+ const leaf = LEAF_RE.exec(text);
157
+ const section = leaf ? null : SECTION_RE.exec(text);
158
+ if (leaf) {
159
+ const value = Number.parseFloat(leaf[3].replace(/,/g, ""));
160
+ if (!Number.isFinite(value)) return { error: `"${leaf[3]}" is not a number.`, line };
161
+ item = { name: _nullishCoalesce(leaf[1], () => ( leaf[2])), value };
162
+ if (leaf[4]) item.className = leaf[4];
163
+ } else if (section) {
164
+ item = { name: _nullishCoalesce(section[1], () => ( section[2])), children: [] };
165
+ if (section[3]) item.className = section[3];
166
+ } else {
167
+ return {
168
+ error: /^["']/.test(text) ? 'Expected `"Name"` for a section or `"Name": value` for a leaf.' : 'Names must be in quotes, e.g. `"Sales": 120`.',
169
+ line
170
+ };
171
+ }
172
+ while (stack.length && stack[stack.length - 1].indent >= indent) stack.pop();
173
+ const parent = _optionalChain([stack, 'access', _ => _[stack.length - 1], 'optionalAccess', _2 => _2.item]);
174
+ if (parent) parent.children.push(item);
175
+ else data.items.push(item);
176
+ if (item.children) stack.push({ item, indent });
177
+ }
178
+ if (!data.items.length) return { error: 'No items: add lines like `"Sales": 120`.' };
179
+ return { data };
180
+ }
181
+ function stripComment(line) {
182
+ let quote = null;
183
+ for (let i = 0; i < line.length; i++) {
184
+ const ch = line[i];
185
+ if (quote) {
186
+ if (ch === quote) quote = null;
187
+ } else if (ch === '"' || ch === "'") {
188
+ quote = ch;
189
+ } else if (ch === "%" && line[i + 1] === "%") {
190
+ return line.slice(0, i);
191
+ }
192
+ }
193
+ return line;
194
+ }
195
+ function treemapValue(item) {
196
+ if (!item.children) return _nullishCoalesce(item.value, () => ( 0));
197
+ return item.children.reduce((sum, child) => sum + treemapValue(child), 0);
198
+ }
199
+
200
+
201
+
202
+
203
+
204
+ exports.parseSankey = parseSankey; exports.parseTreemap = parseTreemap; exports.treemapValue = treemapValue;