@bubblydoo/uxp-toolkit 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -100,44 +100,105 @@ var executeAsModalAndSuspendHistory = async (commandName, document, fn) => {
100
100
  });
101
101
  };
102
102
 
103
- // src/commands-library/getLayerProperties.ts
103
+ // src/commands-library/renameLayer.ts
104
104
  import { z as z2 } from "zod";
105
- var getLayerProperties = async (document) => {
106
- const command = createCommand({
105
+ function createRenameLayerCommand(layerRef, newName) {
106
+ return createCommand({
107
+ modifying: true,
108
+ descriptor: {
109
+ _obj: "set",
110
+ _target: [{ _ref: "layer", _id: layerRef.id }, { _ref: "document", _id: layerRef.docId }],
111
+ to: { _obj: "layer", name: newName }
112
+ },
113
+ schema: z2.unknown()
114
+ });
115
+ }
116
+
117
+ // src/commands-library/getDocument.ts
118
+ import z3 from "zod";
119
+ function createGetDocumentCommand(documentId) {
120
+ return createCommand({
107
121
  modifying: false,
108
122
  descriptor: {
109
- _obj: "multiGet",
110
- _target: { _ref: [{ _ref: "document", _id: document.id }] },
111
- extendedReference: [
112
- ["name", "layerID", "visible"],
113
- { _obj: "layer", index: 1, count: -1 }
114
- ]
123
+ _obj: "get",
124
+ _target: { _ref: [{ _ref: "document", _id: documentId }] }
115
125
  },
116
- schema: z2.object({
117
- list: z2.array(
118
- z2.object({
119
- name: z2.string(),
120
- layerID: z2.number(),
121
- visible: z2.boolean().optional()
122
- })
123
- )
126
+ schema: z3.object({
127
+ title: z3.string(),
128
+ documentID: z3.number(),
129
+ visible: z3.boolean(),
130
+ hasBackgroundLayer: z3.boolean()
124
131
  })
125
132
  });
126
- const result = await batchPlayCommand(command);
127
- return [...result.list].reverse();
128
- };
133
+ }
134
+ function createGetDocumentHasBackgroundLayerCommand(documentId) {
135
+ return createCommand({
136
+ modifying: false,
137
+ descriptor: {
138
+ _obj: "get",
139
+ _target: {
140
+ _ref: [
141
+ { _property: "hasBackgroundLayer" },
142
+ { _ref: "document", _id: documentId }
143
+ ]
144
+ }
145
+ },
146
+ schema: z3.object({
147
+ hasBackgroundLayer: z3.boolean()
148
+ })
149
+ });
150
+ }
129
151
 
130
- // src/commands-library/renameLayer.ts
131
- import { z as z3 } from "zod";
132
- function createRenameLayerCommand(layerRef, newName) {
152
+ // src/commands-library/getLayer.ts
153
+ import z4 from "zod";
154
+ var layerSchema = z4.object({
155
+ name: z4.string(),
156
+ visible: z4.boolean(),
157
+ group: z4.boolean(),
158
+ layerSection: z4.object({
159
+ _value: z4.enum([
160
+ "layerSectionStart",
161
+ "layerSectionEnd",
162
+ "layerSectionContent"
163
+ ]),
164
+ _enum: z4.literal("layerSectionType")
165
+ }),
166
+ layerKind: z4.number(),
167
+ itemIndex: z4.number(),
168
+ background: z4.boolean(),
169
+ mode: z4.object({
170
+ _enum: z4.literal("blendMode"),
171
+ _value: z4.string()
172
+ }),
173
+ layerID: z4.number(),
174
+ layerEffects: z4.record(z4.string(), z4.object({
175
+ // "scale" does not have an "enabled" property, that's why it's optional
176
+ enabled: z4.boolean().optional()
177
+ }).or(z4.array(z4.object({
178
+ enabled: z4.boolean()
179
+ })))).optional()
180
+ });
181
+ function createGetLayerCommand(layerRef) {
133
182
  return createCommand({
134
- modifying: true,
183
+ modifying: false,
135
184
  descriptor: {
136
- _obj: "set",
137
- _target: [{ _ref: "layer", _id: layerRef.id }, { _ref: "document", _id: layerRef.docId }],
138
- to: { _obj: "layer", name: newName }
185
+ _obj: "get",
186
+ _target: [
187
+ { _ref: "layer", _id: layerRef.id },
188
+ { _ref: "document", _id: layerRef.docId }
189
+ ]
139
190
  },
140
- schema: z3.unknown()
191
+ schema: layerSchema
192
+ });
193
+ }
194
+ function createGetBackgroundLayerCommand(docId) {
195
+ return createCommand({
196
+ modifying: false,
197
+ descriptor: {
198
+ _obj: "get",
199
+ _target: { _ref: [{ _ref: "layer", "_property": "background" }, { _ref: "document", _id: docId }] }
200
+ },
201
+ schema: layerSchema
141
202
  });
142
203
  }
143
204
 
@@ -223,37 +284,37 @@ function mapTreeRef(tree, mapFn) {
223
284
  }
224
285
 
225
286
  // src/other/applicationInfo.ts
226
- import { z as z4 } from "zod";
287
+ import { z as z5 } from "zod";
227
288
  async function photoshopGetApplicationInfo() {
228
289
  return await batchPlayCommand(photoshopApplicationInfoCommand);
229
290
  }
230
- var photoshopAppInfoSchema = z4.object({
231
- active: z4.boolean(),
232
- autoShowHomeScreen: z4.boolean(),
233
- available: z4.number(),
234
- buildNumber: z4.string(),
235
- documentArea: z4.object({
236
- left: z4.number(),
237
- top: z4.number(),
238
- right: z4.number(),
239
- bottom: z4.number()
291
+ var photoshopAppInfoSchema = z5.object({
292
+ active: z5.boolean(),
293
+ autoShowHomeScreen: z5.boolean(),
294
+ available: z5.number(),
295
+ buildNumber: z5.string(),
296
+ documentArea: z5.object({
297
+ left: z5.number(),
298
+ top: z5.number(),
299
+ right: z5.number(),
300
+ bottom: z5.number()
240
301
  }),
241
- hostName: z4.string(),
242
- hostVersion: z4.object({
243
- versionMajor: z4.number(),
244
- versionMinor: z4.number(),
245
- versionFix: z4.number()
302
+ hostName: z5.string(),
303
+ hostVersion: z5.object({
304
+ versionMajor: z5.number(),
305
+ versionMinor: z5.number(),
306
+ versionFix: z5.number()
246
307
  }),
247
- localeInfo: z4.object({
248
- decimalPoint: z4.string()
308
+ localeInfo: z5.object({
309
+ decimalPoint: z5.string()
249
310
  }),
250
- osVersion: z4.string(),
251
- panelList: z4.array(
252
- z4.object({
253
- ID: z4.string(),
254
- name: z4.string(),
255
- obscured: z4.boolean(),
256
- visible: z4.boolean()
311
+ osVersion: z5.string(),
312
+ panelList: z5.array(
313
+ z5.object({
314
+ ID: z5.string(),
315
+ name: z5.string(),
316
+ obscured: z5.boolean(),
317
+ visible: z5.boolean()
257
318
  })
258
319
  )
259
320
  });
@@ -284,17 +345,17 @@ async function readFromClipboard() {
284
345
  }
285
346
 
286
347
  // src/other/uxpEntrypoints.ts
287
- import { z as z5 } from "zod";
288
- var uxpEntrypointsSchema = z5.object({
289
- _pluginInfo: z5.object({
290
- id: z5.string(),
291
- name: z5.string(),
292
- version: z5.string()
348
+ import { z as z6 } from "zod";
349
+ var uxpEntrypointsSchema = z6.object({
350
+ _pluginInfo: z6.object({
351
+ id: z6.string(),
352
+ name: z6.string(),
353
+ version: z6.string()
293
354
  })
294
355
  });
295
356
 
296
357
  // src/ut-tree/getLayerProperties.ts
297
- import { z as z6 } from "zod";
358
+ import { z as z7 } from "zod";
298
359
  function createGetLayerPropertiesCommand(docId) {
299
360
  return createCommand({
300
361
  modifying: false,
@@ -302,105 +363,62 @@ function createGetLayerPropertiesCommand(docId) {
302
363
  _obj: "multiGet",
303
364
  _target: { _ref: [{ _ref: "document", _id: docId }] },
304
365
  extendedReference: [
305
- ["name", "layerID", "visible"],
366
+ ["name", "layerID", "visible", "group", "layerSection", "layerKind", "itemIndex", "background", "mode", "layerEffects"],
306
367
  { _obj: "layer", index: 1, count: -1 }
307
368
  ]
308
369
  },
309
- schema: z6.object({
310
- list: z6.array(
311
- z6.object({
312
- name: z6.string(),
313
- layerID: z6.number(),
314
- visible: z6.boolean().optional()
370
+ schema: z7.object({
371
+ list: z7.array(
372
+ z7.object({
373
+ name: z7.string(),
374
+ layerID: z7.number(),
375
+ visible: z7.boolean(),
376
+ group: z7.boolean(),
377
+ layerSection: z7.object({
378
+ _value: z7.enum([
379
+ "layerSectionStart",
380
+ "layerSectionEnd",
381
+ "layerSectionContent"
382
+ ]),
383
+ _enum: z7.literal("layerSectionType")
384
+ }),
385
+ layerKind: z7.number(),
386
+ itemIndex: z7.number(),
387
+ background: z7.boolean(),
388
+ mode: z7.object({
389
+ _enum: z7.literal("blendMode"),
390
+ _value: z7.string()
391
+ }),
392
+ layerEffects: z7.record(z7.string(), z7.object({
393
+ // "scale" does not have an "enabled" property, that's why it's optional
394
+ enabled: z7.boolean().optional()
395
+ }).or(z7.array(z7.object({
396
+ enabled: z7.boolean()
397
+ })))).optional()
315
398
  })
316
399
  )
317
400
  })
318
401
  });
319
402
  }
320
- var getLayerProperties2 = async (documentId) => {
321
- const command = createGetLayerPropertiesCommand(documentId);
322
- const result = await batchPlayCommand(command);
323
- return [...result.list].reverse();
324
- };
325
-
326
- // src/ut-tree/getFlattenedLayerDescriptorsList.ts
327
- import { z as z7 } from "zod";
328
- var layerDescriptorSchema = z7.object({
329
- name: z7.string(),
330
- // id: z.number(),
331
- layerID: z7.number(),
332
- // _docId: z.number(),
333
- mode: z7.object({
334
- _enum: z7.literal("blendMode"),
335
- _value: z7.string()
336
- // passThrough, normal, multiply, screen, overlay, etc.
337
- }),
338
- background: z7.boolean(),
339
- itemIndex: z7.number(),
340
- visible: z7.boolean(),
341
- layerKind: z7.number(),
342
- layerSection: z7.object({
343
- _value: z7.enum([
344
- "layerSectionStart",
345
- "layerSectionEnd",
346
- "layerSectionContent"
347
- ]),
348
- _enum: z7.literal("layerSectionType")
349
- })
350
- });
351
- var getFlattenedLayerDescriptorsList = async (documentId) => {
352
- const layerProperties = await getLayerProperties2(documentId);
353
- const commands = layerProperties.map(
354
- (layerProp) => createCommand({
355
- modifying: false,
356
- descriptor: {
357
- _obj: "get",
358
- _target: [
359
- {
360
- _ref: "layer",
361
- _id: layerProp.layerID
362
- }
363
- ],
364
- makeVisible: false,
365
- layerID: [layerProp.layerID],
366
- _isCommand: false
367
- },
368
- schema: layerDescriptorSchema
369
- })
370
- );
371
- const layerDescriptors = await batchPlayCommands(commands);
372
- return layerDescriptors.map((desc) => {
403
+ var getDocumentLayerDescriptors = async (documentId) => {
404
+ const [layersResult, documentHasBackgroundLayerResult] = await batchPlayCommands([
405
+ createGetLayerPropertiesCommand(documentId),
406
+ createGetDocumentHasBackgroundLayerCommand(documentId)
407
+ ]);
408
+ const backgroundLayerResult = documentHasBackgroundLayerResult.hasBackgroundLayer ? await batchPlayCommand(createGetBackgroundLayerCommand(documentId)) : null;
409
+ const list = [...layersResult.list].reverse();
410
+ if (backgroundLayerResult) {
411
+ list.push(backgroundLayerResult);
412
+ }
413
+ return list.map((layerProp) => {
373
414
  return {
374
- ...desc,
415
+ ...layerProp,
375
416
  docId: documentId
376
417
  };
377
418
  });
378
419
  };
379
420
 
380
421
  // src/ut-tree/getLayerEffects.ts
381
- import { z as z8 } from "zod";
382
- function createGetLayerCommand(layerRef) {
383
- return createCommand({
384
- modifying: false,
385
- descriptor: {
386
- _obj: "get",
387
- _target: [
388
- { _ref: "layer", _id: layerRef.id },
389
- { _ref: "document", _id: layerRef.docId }
390
- ]
391
- },
392
- schema: z8.object({
393
- layerID: z8.number(),
394
- group: z8.boolean().optional(),
395
- layerEffects: z8.record(z8.string(), z8.object({
396
- // "scale" does not have an "enabled" property, that's why it's optional
397
- enabled: z8.boolean().optional()
398
- }).or(z8.array(z8.object({
399
- enabled: z8.boolean()
400
- })))).optional()
401
- })
402
- });
403
- }
404
422
  async function getLayerEffects(layerRef) {
405
423
  const result = await batchPlayCommand(createGetLayerCommand(layerRef));
406
424
  const data = result.layerEffects || {};
@@ -411,132 +429,6 @@ async function getLayerEffects(layerRef) {
411
429
  return effects;
412
430
  }
413
431
 
414
- // src/ut-tree/photoshopLayerDescriptorsToUTLayers.ts
415
- var layerKindMap = /* @__PURE__ */ new Map([
416
- [1, "pixel"],
417
- [2, "adjustment-layer"],
418
- // All adjustment layers
419
- [3, "text"],
420
- [4, "curves"],
421
- [5, "smartObject"],
422
- [6, "video"],
423
- [7, "group"],
424
- [8, "threeD"],
425
- [9, "gradientFill"],
426
- [10, "pattern"],
427
- [11, "solidColor"],
428
- [12, "background"]
429
- // according to the internet but the actual value is undefined
430
- ]);
431
- var blendModes = [
432
- "normal",
433
- "dissolve",
434
- "darken",
435
- "multiply",
436
- "colorBurn",
437
- "linearBurn",
438
- "darkerColor",
439
- "lighten",
440
- "screen",
441
- "colorDodge",
442
- "linearDodge",
443
- "lighterColor",
444
- "overlay",
445
- "softLight",
446
- "hardLight",
447
- "vividLight",
448
- "linearLight",
449
- "pinLight",
450
- "hardMix",
451
- "difference",
452
- "exclusion",
453
- "blendSubtraction",
454
- "blendDivide",
455
- "hue",
456
- "saturation",
457
- "color",
458
- "luminosity",
459
- "passThrough"
460
- ];
461
- var getLayerSectionValue = (layer) => {
462
- if (typeof layer.layerSection === "string") {
463
- return layer.layerSection;
464
- }
465
- if (layer.layerSection && typeof layer.layerSection === "object" && "_value" in layer.layerSection) {
466
- return layer.layerSection._value;
467
- }
468
- return void 0;
469
- };
470
- var getLayerKind = (layer) => {
471
- const kind = layerKindMap.get(layer.layerKind);
472
- if (!kind) {
473
- throw new Error(`Unknown layer kind: ${layer.layerKind}`);
474
- }
475
- return kind;
476
- };
477
- var getBlendMode = (layer) => {
478
- const mode = layer.mode._value;
479
- if (!blendModes.includes(mode)) {
480
- throw new Error(`Unknown blend mode: ${mode}`);
481
- }
482
- return mode;
483
- };
484
- var determineLayerSection = (layer) => {
485
- const section = getLayerSectionValue(layer);
486
- const isGroupEnd = layer.name === "</Layer group>" || layer.name === "</Layer set>" || section === "layerSectionEnd";
487
- const isGroupStart = section === "layerSectionStart";
488
- return isGroupStart ? "start" : isGroupEnd ? "end" : "normal";
489
- };
490
- var photoshopLayerDescriptorsToUTLayers = async (layers) => {
491
- const root = [];
492
- const stack = [{ layers: root }];
493
- const commands = layers.map((layer) => createGetLayerCommand({ docId: layer.docId, id: layer.layerID }));
494
- const batchResults = await executeAsModal("Get Layer Effects Data", async (ctx) => {
495
- return await ctx.batchPlayCommands(commands);
496
- });
497
- const effectsMap = /* @__PURE__ */ new Map();
498
- batchResults.forEach((result, index) => {
499
- const layerId = layers[index].layerID;
500
- const data = result.layerEffects;
501
- const effects = {};
502
- if (data) {
503
- for (const effect in data) {
504
- effects[effect] = Array.isArray(data[effect]) ? data[effect].some((e) => e.enabled) : !!data[effect]?.enabled;
505
- }
506
- }
507
- effectsMap.set(layerId, effects);
508
- });
509
- for (const layer of layers) {
510
- const sectionType = determineLayerSection(layer);
511
- const isClippingMask = !!batchResults.find((res, index) => {
512
- return layer.layerID === res.layerID;
513
- })?.group;
514
- if (sectionType === "end") {
515
- if (stack.length > 1) {
516
- stack.pop();
517
- }
518
- continue;
519
- }
520
- const node = {
521
- name: layer.name,
522
- docId: layer.docId,
523
- id: layer.layerID,
524
- visible: layer.visible,
525
- kind: getLayerKind(layer),
526
- blendMode: getBlendMode(layer),
527
- isClippingMask,
528
- effects: effectsMap.get(layer.layerID) || {}
529
- };
530
- const current = stack[stack.length - 1];
531
- current.layers.push(node);
532
- if (sectionType === "start") {
533
- node.layers = [];
534
- stack.push({ layers: node.layers });
535
- }
536
- }
537
- return root;
538
- };
539
-
540
432
  // src/ut-tree/utLayersToTree.ts
541
433
  function utLayersToTree(layer) {
542
434
  return layer.map((layer2) => ({
@@ -548,13 +440,41 @@ function utLayersToTree(layer) {
548
440
  kind: layer2.kind,
549
441
  blendMode: layer2.blendMode,
550
442
  isClippingMask: layer2.isClippingMask,
551
- effects: layer2.effects
443
+ effects: layer2.effects,
444
+ background: layer2.background
552
445
  },
553
446
  name: layer2.name,
554
447
  children: layer2.layers ? utLayersToTree(layer2.layers) : void 0
555
448
  }));
556
449
  }
557
450
 
451
+ // src/ut-tree/utLayersToText.ts
452
+ var VISIBLE_ICON = "\u25EF";
453
+ var INVISIBLE_ICON = "\u2298";
454
+ var CLIPPING_MASK_ICON = "\u2B10";
455
+ var GROUP_ICON = "\u25BE";
456
+ var EFFECTS_ICON = "\u0192";
457
+ var BLEND_ICON = "\u2055";
458
+ function utLayersToText(tree, depth = 0) {
459
+ return tree.map((layer) => {
460
+ const prefix = " ".repeat(depth * 2);
461
+ const name = layer.name;
462
+ const effects = Object.keys(layer.effects).length > 0 ? EFFECTS_ICON : "";
463
+ const blend = isSpecialBlendMode(layer) ? BLEND_ICON : "";
464
+ const clippingMask = layer.isClippingMask ? CLIPPING_MASK_ICON : "";
465
+ const group = layer.kind === "group" ? GROUP_ICON : "";
466
+ const visible = layer.visible ? VISIBLE_ICON : INVISIBLE_ICON;
467
+ const line = [visible, prefix, clippingMask, group, name, effects, blend].filter(Boolean).join(" ");
468
+ if (layer.layers) {
469
+ return line + "\n" + utLayersToText(layer.layers, depth + 1);
470
+ }
471
+ return line;
472
+ }).join("\n");
473
+ }
474
+ function isSpecialBlendMode(layer) {
475
+ return layer.kind === "group" ? layer.blendMode !== "passThrough" : layer.blendMode !== "normal";
476
+ }
477
+
558
478
  // src/util/utLayerToLayer.ts
559
479
  import { app as app2 } from "photoshop";
560
480
  function utLayerToDomLayer(layer) {
@@ -704,7 +624,9 @@ export {
704
624
  batchPlayCommands,
705
625
  copyToClipboard,
706
626
  createCommand,
707
- createGetLayerCommand as createGetLayerEffectsCommand,
627
+ createGetBackgroundLayerCommand,
628
+ createGetDocumentCommand,
629
+ createGetDocumentHasBackgroundLayerCommand,
708
630
  createGetLayerPropertiesCommand,
709
631
  createModifyingBatchPlayContext,
710
632
  createRenameLayerCommand,
@@ -713,21 +635,19 @@ export {
713
635
  flattenTree,
714
636
  getBasicStackFrameAbsoluteFilePath,
715
637
  getFlattenedDomLayersList,
716
- getFlattenedLayerDescriptorsList,
717
638
  getLayerEffects,
718
- getLayerProperties,
719
- getLayerProperties2 as getLayerPropertiesFromUtTree,
639
+ getDocumentLayerDescriptors as getLayerPropertiesFromUtTree,
720
640
  mapTree,
721
641
  mapTreeRef,
722
642
  openFileByPath,
723
643
  parseUxpErrorSourcemaps,
724
644
  photoshopDomLayersToTree,
725
645
  photoshopGetApplicationInfo,
726
- photoshopLayerDescriptorsToUTLayers,
727
646
  readFromClipboard,
728
647
  suspendHistory,
729
648
  utLayerToDomLayer,
730
649
  utLayersToDomLayers,
731
650
  utLayersToTree,
651
+ utLayersToText as utTreeToText,
732
652
  uxpEntrypointsSchema
733
653
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bubblydoo/uxp-toolkit",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "author": "Hans Otto Wirtz <hansottowirtz@gmail.com>",
@@ -33,15 +33,18 @@
33
33
  "@types/node": "^20.8.7",
34
34
  "@types/photoshop": "^25.0.2",
35
35
  "chai": "^6.2.2",
36
+ "dedent": "^1.7.1",
36
37
  "rollup": "^4.57.0",
37
38
  "tsup": "^8.5.1",
38
39
  "typescript": "^5.8.3",
40
+ "vitest": "^4.0.18",
39
41
  "zod": "^4.3.6",
40
- "@bubblydoo/tsconfig": "0.0.2",
41
- "@bubblydoo/uxp-test-framework": "0.0.3"
42
+ "@bubblydoo/uxp-test-framework": "0.0.5",
43
+ "@bubblydoo/tsconfig": "0.0.3"
42
44
  },
43
45
  "scripts": {
44
46
  "build": "tsup",
47
+ "test": "vitest run",
45
48
  "uxp-test:build": "uxp-test build",
46
49
  "uxp-test:dev": "uxp-test dev"
47
50
  }
@@ -0,0 +1,36 @@
1
+ import z from "zod";
2
+ import { createCommand } from "../core/command";
3
+
4
+ export function createGetDocumentCommand(documentId: number) {
5
+ return createCommand({
6
+ modifying: false,
7
+ descriptor: {
8
+ _obj: "get",
9
+ _target: { _ref: [{ _ref: "document", _id: documentId }] },
10
+ },
11
+ schema: z.object({
12
+ title: z.string(),
13
+ documentID: z.number(),
14
+ visible: z.boolean(),
15
+ hasBackgroundLayer: z.boolean(),
16
+ }),
17
+ });
18
+ }
19
+
20
+ export function createGetDocumentHasBackgroundLayerCommand(documentId: number) {
21
+ return createCommand({
22
+ modifying: false,
23
+ descriptor: {
24
+ _obj: "get",
25
+ _target: {
26
+ _ref: [
27
+ { _property: "hasBackgroundLayer" },
28
+ { _ref: "document", _id: documentId },
29
+ ],
30
+ },
31
+ },
32
+ schema: z.object({
33
+ hasBackgroundLayer: z.boolean(),
34
+ }),
35
+ });
36
+ }