@bubblydoo/uxp-toolkit 0.0.8 → 0.0.10
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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +12 -0
- package/dist/{chunk-3CLJMC63.js → chunk-JBXCIUBZ.js} +49 -90
- package/dist/commands-library/index.d.ts +38 -39
- package/dist/commands-library/index.js +171 -171
- package/dist/index.d.ts +41 -83
- package/dist/index.js +203 -152
- package/dist/{psLayerRef-OY3h7srv.d.ts → psLayerRef-CGbTO4a5.d.ts} +36 -37
- package/package.json +9 -7
- package/src/commands-library/addLayerToSelection.ts +4 -4
- package/src/commands-library/applyLayerMask.ts +2 -2
- package/src/commands-library/convertMode.ts +2 -2
- package/src/commands-library/createColorLookupAdjustmentLayer.ts +2 -2
- package/src/commands-library/expandFolder.ts +4 -4
- package/src/commands-library/exportLUTs.ts +4 -4
- package/src/commands-library/getDocument.ts +7 -7
- package/src/commands-library/getLayer.ts +13 -13
- package/src/commands-library/hasVectorMask.ts +2 -2
- package/src/commands-library/index.ts +18 -18
- package/src/commands-library/loadLayerMaskAsSelection.ts +2 -2
- package/src/commands-library/multiGetDocument.ts +14 -14
- package/src/commands-library/rasterizeLayerStyle.ts +3 -3
- package/src/commands-library/rasterizeVectorMask.ts +2 -2
- package/src/commands-library/removeLayerMask.ts +2 -2
- package/src/commands-library/renameLayer.ts +6 -6
- package/src/commands-library/renameLayer.uxp-test.ts +13 -13
- package/src/commands-library/renderGrid.ts +2 -2
- package/src/commands-library/selectLayer.ts +3 -3
- package/src/commands-library/set3DLUTColorLookup.ts +2 -2
- package/src/core/batchPlay.ts +3 -3
- package/src/core/command.test-d.ts +11 -8
- package/src/core/command.ts +20 -23
- package/src/core/executeAsModal.ts +11 -67
- package/src/core/suspendHistory.ts +3 -3
- package/src/core/suspendHistory.uxp-test.ts +8 -8
- package/src/core-wrappers/executeAsModalAndSuspendHistory.ts +8 -6
- package/src/dom/getFlattenedDomLayersList.ts +6 -7
- package/src/dom/photoshopDomLayersToTree.ts +5 -5
- package/src/error-sourcemaps/sourcemaps.ts +27 -26
- package/src/error-sourcemaps/sourcemaps.uxp-test.ts +9 -8
- package/src/errors/ut-error.ts +2 -2
- package/src/filesystem/isFileOrFolder.ts +9 -0
- package/src/filesystem/openFileByPath.ts +10 -6
- package/src/general-tree/flattenTree.ts +1 -1
- package/src/general-tree/layerRef.ts +2 -2
- package/src/general-tree/mapTree.ts +1 -1
- package/src/general-tree/mapTreeRef.ts +1 -1
- package/src/general-tree/treeTypes.ts +0 -2
- package/src/index.ts +42 -43
- package/src/metadata-storage/metadataStorage.ts +31 -31
- package/src/metadata-storage/metadataStorage.uxp-test.ts +11 -11
- package/src/node-compat/path/resolvePath.ts +6 -4
- package/src/other/applicationInfo.ts +11 -11
- package/src/other/applicationInfo.uxp-test.ts +6 -6
- package/src/other/clipboard.ts +2 -2
- package/src/other/clipboard.uxp-test.ts +9 -8
- package/src/other/uxpEntrypoints.ts +2 -2
- package/src/ut-tree/getDocumentLayerDescriptors.ts +6 -6
- package/src/ut-tree/getLayerEffects.ts +5 -5
- package/src/ut-tree/hasBackgroundLayer.uxp-test.ts +25 -23
- package/src/ut-tree/photoshopLayerDescriptorsToUTLayers.test.ts +29 -29
- package/src/ut-tree/photoshopLayerDescriptorsToUTLayers.ts +62 -62
- package/src/ut-tree/photoshopLayerDescriptorsToUTLayers.uxp-test.ts +29 -29
- package/src/ut-tree/psLayerRef.ts +2 -2
- package/src/ut-tree/utLayersToText.test.ts +32 -32
- package/src/ut-tree/utLayersToText.ts +19 -19
- package/src/ut-tree/utLayersToTree.ts +4 -4
- package/src/util/utLayerPickKeysType.ts +3 -3
- package/src/util/utLayerToLayer.ts +14 -13
- package/test/index.ts +11 -11
- package/test/meta-tests/builtinModules.uxp-test.ts +28 -26
- package/test/meta-tests/executeAsModal.uxp-test.ts +14 -12
- package/test/meta-tests/suspendHistory.uxp-test.ts +10 -9
- package/tsconfig.json +5 -5
- package/tsup.config.ts +5 -5
- package/typedoc.json +6 -0
- package/uxp-tests.json +1 -1
- package/vitest-photoshop-alias-plugin.ts +23 -21
- package/vitest.config.ts +6 -6
package/dist/index.js
CHANGED
|
@@ -7,9 +7,43 @@ import {
|
|
|
7
7
|
createGetDocumentHasBackgroundLayerCommand,
|
|
8
8
|
createGetLayerCommand,
|
|
9
9
|
createModifyingBatchPlayContext,
|
|
10
|
-
createMultiGetDocumentCommand
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
createMultiGetDocumentCommand
|
|
11
|
+
} from "./chunk-JBXCIUBZ.js";
|
|
12
|
+
|
|
13
|
+
// src/core/executeAsModal.ts
|
|
14
|
+
import { core } from "photoshop";
|
|
15
|
+
async function executeAsModal(commandName, fn, opts) {
|
|
16
|
+
let error;
|
|
17
|
+
let result;
|
|
18
|
+
await core.executeAsModal(async (executionContext) => {
|
|
19
|
+
const abortController = new AbortController();
|
|
20
|
+
executionContext.onCancel = () => {
|
|
21
|
+
abortController.abort();
|
|
22
|
+
};
|
|
23
|
+
const extendedExecutionContext = {
|
|
24
|
+
isCancelled: executionContext.isCancelled,
|
|
25
|
+
reportProgress: executionContext.reportProgress,
|
|
26
|
+
hostControl: executionContext.hostControl,
|
|
27
|
+
signal: abortController.signal,
|
|
28
|
+
...createModifyingBatchPlayContext()
|
|
29
|
+
};
|
|
30
|
+
try {
|
|
31
|
+
result = await fn(extendedExecutionContext);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.error("error in executeAsModal");
|
|
34
|
+
console.error(e);
|
|
35
|
+
error = e;
|
|
36
|
+
}
|
|
37
|
+
}, {
|
|
38
|
+
commandName,
|
|
39
|
+
...opts
|
|
40
|
+
});
|
|
41
|
+
if (error) {
|
|
42
|
+
throw error;
|
|
43
|
+
} else {
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
13
47
|
|
|
14
48
|
// src/core/suspendHistory.ts
|
|
15
49
|
async function suspendHistory(document, historyStateName, fn) {
|
|
@@ -21,15 +55,15 @@ async function suspendHistory(document, historyStateName, fn) {
|
|
|
21
55
|
}
|
|
22
56
|
|
|
23
57
|
// src/core-wrappers/executeAsModalAndSuspendHistory.ts
|
|
24
|
-
|
|
58
|
+
async function executeAsModalAndSuspendHistory(commandName, document, fn) {
|
|
25
59
|
return await executeAsModal(commandName, async (ctx) => {
|
|
26
60
|
return await suspendHistory(document, commandName, (suspendHistoryContext) => fn(ctx, suspendHistoryContext));
|
|
27
61
|
});
|
|
28
|
-
}
|
|
62
|
+
}
|
|
29
63
|
|
|
30
64
|
// src/dom/getFlattenedDomLayersList.ts
|
|
31
65
|
import { constants } from "photoshop";
|
|
32
|
-
|
|
66
|
+
function getFlattenedDomLayersList(layers) {
|
|
33
67
|
const allLayers = [];
|
|
34
68
|
const stack = [];
|
|
35
69
|
for (let i = layers.length - 1; i >= 0; i--) {
|
|
@@ -37,7 +71,8 @@ var getFlattenedDomLayersList = (layers) => {
|
|
|
37
71
|
}
|
|
38
72
|
while (stack.length > 0) {
|
|
39
73
|
const layer = stack.pop();
|
|
40
|
-
if (!layer)
|
|
74
|
+
if (!layer)
|
|
75
|
+
continue;
|
|
41
76
|
allLayers.push(layer);
|
|
42
77
|
if (layer.kind === constants.LayerKind.GROUP) {
|
|
43
78
|
const children = layer.layers;
|
|
@@ -49,10 +84,10 @@ var getFlattenedDomLayersList = (layers) => {
|
|
|
49
84
|
}
|
|
50
85
|
}
|
|
51
86
|
return allLayers;
|
|
52
|
-
}
|
|
87
|
+
}
|
|
53
88
|
|
|
54
89
|
// src/dom/photoshopDomLayersToTree.ts
|
|
55
|
-
|
|
90
|
+
function photoshopDomLayersToTree(layers) {
|
|
56
91
|
const filteredLayers = layers.filter((layer) => layer.parent === null);
|
|
57
92
|
const generateTree = (layers2) => {
|
|
58
93
|
return layers2.map((layer) => ({
|
|
@@ -62,15 +97,132 @@ var photoshopDomLayersToTree = (layers) => {
|
|
|
62
97
|
}));
|
|
63
98
|
};
|
|
64
99
|
return generateTree(filteredLayers);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/error-sourcemaps/sourcemaps.ts
|
|
103
|
+
import ErrorStackParser from "error-stack-parser";
|
|
104
|
+
import { SourceMapConsumer } from "source-map-js";
|
|
105
|
+
import { storage } from "uxp";
|
|
106
|
+
|
|
107
|
+
// src/errors/ut-error.ts
|
|
108
|
+
var UTError = class extends Error {
|
|
109
|
+
constructor(message, opts = {}) {
|
|
110
|
+
super(message, opts);
|
|
111
|
+
this.name = "UTError";
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// src/node-compat/path/resolvePath.ts
|
|
116
|
+
import { resolve as nativeResolve } from "path";
|
|
117
|
+
function pathResolve(...pathSegments) {
|
|
118
|
+
const urlOrString = nativeResolve(...pathSegments);
|
|
119
|
+
if (typeof urlOrString === "string") {
|
|
120
|
+
return urlOrString;
|
|
121
|
+
}
|
|
122
|
+
if (isUrl(urlOrString)) {
|
|
123
|
+
return urlOrString.toString();
|
|
124
|
+
}
|
|
125
|
+
throw new Error("Unexpected URL object");
|
|
126
|
+
}
|
|
127
|
+
function isUrl(urlOrString) {
|
|
128
|
+
return urlOrString instanceof URL;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/error-sourcemaps/sourcemaps.ts
|
|
132
|
+
async function parseUxpErrorSourcemaps(error, opts = {}) {
|
|
133
|
+
const parsedError = parseErrorIntoBasicStackFrames(error);
|
|
134
|
+
const unsourcemappedHeaderLines = opts.unsourcemappedHeaderLines ?? 0;
|
|
135
|
+
const loadedFilesCache = {};
|
|
136
|
+
const fs = storage.localFileSystem;
|
|
137
|
+
const parsedMappedError = [];
|
|
138
|
+
for (const frame of parsedError) {
|
|
139
|
+
if (!frame.fileName || !frame.lineNumber || !frame.columnNumber) {
|
|
140
|
+
parsedMappedError.push(frame);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
const entryPath = `plugin:${frame.fileName}`;
|
|
144
|
+
const file = loadedFilesCache[entryPath] ?? await fs.getEntryWithUrl(entryPath);
|
|
145
|
+
loadedFilesCache[entryPath] = file;
|
|
146
|
+
if (!file.isFile) {
|
|
147
|
+
parsedMappedError.push(frame);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const sourcemapFileEntryPath = `${entryPath}.map`;
|
|
151
|
+
const sourcemapFile = loadedFilesCache[sourcemapFileEntryPath] ?? await fs.getEntryWithUrl(sourcemapFileEntryPath);
|
|
152
|
+
loadedFilesCache[sourcemapFileEntryPath] = sourcemapFile;
|
|
153
|
+
if (!sourcemapFile.isFile) {
|
|
154
|
+
parsedMappedError.push(frame);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const sourcemapContents = await sourcemapFile.read({});
|
|
158
|
+
const sourcemap = JSON.parse(sourcemapContents);
|
|
159
|
+
const smc = new SourceMapConsumer(sourcemap);
|
|
160
|
+
const mappedFrame = smc.originalPositionFor({
|
|
161
|
+
line: frame.lineNumber - unsourcemappedHeaderLines,
|
|
162
|
+
column: frame.columnNumber
|
|
163
|
+
});
|
|
164
|
+
if (mappedFrame.source && mappedFrame.line && mappedFrame.column) {
|
|
165
|
+
parsedMappedError.push({
|
|
166
|
+
...frame,
|
|
167
|
+
fileName: mappedFrame.source,
|
|
168
|
+
lineNumber: mappedFrame.line,
|
|
169
|
+
columnNumber: mappedFrame.column
|
|
170
|
+
});
|
|
171
|
+
} else {
|
|
172
|
+
parsedMappedError.push(frame);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return parsedMappedError;
|
|
176
|
+
}
|
|
177
|
+
function parseErrorIntoBasicStackFrames(error) {
|
|
178
|
+
try {
|
|
179
|
+
const frames = ErrorStackParser.parse(error);
|
|
180
|
+
return frames.map((frame) => {
|
|
181
|
+
return {
|
|
182
|
+
functionName: frame.functionName,
|
|
183
|
+
fileName: frame.fileName,
|
|
184
|
+
lineNumber: frame.lineNumber,
|
|
185
|
+
columnNumber: frame.columnNumber
|
|
186
|
+
};
|
|
187
|
+
});
|
|
188
|
+
} catch (e) {
|
|
189
|
+
throw new UTStacktraceParsingError("Failed to parse error stack trace", { cause: e });
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async function getBasicStackFrameAbsoluteFilePath(frame) {
|
|
193
|
+
const pluginFolder = await storage.localFileSystem.getPluginFolder();
|
|
194
|
+
const absoluteFileName = pathResolve(
|
|
195
|
+
pluginFolder.nativePath,
|
|
196
|
+
"index.js",
|
|
197
|
+
frame.fileName
|
|
198
|
+
).replace(/^plugin:/, "");
|
|
199
|
+
return `${absoluteFileName}:${frame.lineNumber}:${frame.columnNumber}`;
|
|
200
|
+
}
|
|
201
|
+
var UTStacktraceParsingError = class extends UTError {
|
|
202
|
+
name = "UTStacktraceParsingError";
|
|
203
|
+
constructor(message, opts = {}) {
|
|
204
|
+
super(message, opts);
|
|
205
|
+
}
|
|
65
206
|
};
|
|
66
207
|
|
|
208
|
+
// src/filesystem/isFileOrFolder.ts
|
|
209
|
+
function isFile(entry) {
|
|
210
|
+
return entry.isFile === true;
|
|
211
|
+
}
|
|
212
|
+
function isFolder(entry) {
|
|
213
|
+
return entry.isFolder === true;
|
|
214
|
+
}
|
|
215
|
+
|
|
67
216
|
// src/filesystem/openFileByPath.ts
|
|
68
217
|
import { app } from "photoshop";
|
|
69
|
-
import { storage } from "uxp";
|
|
218
|
+
import { storage as storage2 } from "uxp";
|
|
70
219
|
async function openFileByPath(path) {
|
|
71
|
-
const fs =
|
|
72
|
-
const
|
|
73
|
-
|
|
220
|
+
const fs = storage2.localFileSystem;
|
|
221
|
+
const entry = await fs.getEntryWithUrl(path);
|
|
222
|
+
if (!isFile(entry)) {
|
|
223
|
+
throw new Error("Entry is not a file");
|
|
224
|
+
}
|
|
225
|
+
const doc = await executeAsModal("Open file", () => app.open(entry));
|
|
74
226
|
return doc;
|
|
75
227
|
}
|
|
76
228
|
|
|
@@ -110,9 +262,6 @@ function mapTreeRef(tree, mapFn) {
|
|
|
110
262
|
|
|
111
263
|
// src/other/applicationInfo.ts
|
|
112
264
|
import { z } from "zod";
|
|
113
|
-
async function photoshopGetApplicationInfo() {
|
|
114
|
-
return await batchPlayCommand(photoshopApplicationInfoCommand);
|
|
115
|
-
}
|
|
116
265
|
var photoshopAppInfoSchema = z.object({
|
|
117
266
|
active: z.boolean(),
|
|
118
267
|
autoShowHomeScreen: z.boolean(),
|
|
@@ -157,6 +306,9 @@ var photoshopApplicationInfoCommand = createCommand({
|
|
|
157
306
|
},
|
|
158
307
|
schema: photoshopAppInfoSchema
|
|
159
308
|
});
|
|
309
|
+
async function photoshopGetApplicationInfo() {
|
|
310
|
+
return await batchPlayCommand(photoshopApplicationInfoCommand);
|
|
311
|
+
}
|
|
160
312
|
|
|
161
313
|
// src/other/clipboard.ts
|
|
162
314
|
async function copyToClipboard(text) {
|
|
@@ -180,7 +332,7 @@ var uxpEntrypointsSchema = z2.object({
|
|
|
180
332
|
});
|
|
181
333
|
|
|
182
334
|
// src/ut-tree/getDocumentLayerDescriptors.ts
|
|
183
|
-
|
|
335
|
+
async function getDocumentLayerDescriptors(documentId) {
|
|
184
336
|
const [layersResult, documentHasBackgroundLayerResult] = await batchPlayCommands([
|
|
185
337
|
createMultiGetDocumentCommand(documentId),
|
|
186
338
|
createGetDocumentHasBackgroundLayerCommand(documentId)
|
|
@@ -196,7 +348,7 @@ var getDocumentLayerDescriptors = async (documentId) => {
|
|
|
196
348
|
docId: documentId
|
|
197
349
|
};
|
|
198
350
|
});
|
|
199
|
-
}
|
|
351
|
+
}
|
|
200
352
|
|
|
201
353
|
// src/ut-tree/getLayerEffects.ts
|
|
202
354
|
async function getLayerEffects(layerRef) {
|
|
@@ -204,7 +356,8 @@ async function getLayerEffects(layerRef) {
|
|
|
204
356
|
const data = result.layerEffects || {};
|
|
205
357
|
const effects = {};
|
|
206
358
|
for (const effect in data) {
|
|
207
|
-
if (effect !== "scale")
|
|
359
|
+
if (effect !== "scale")
|
|
360
|
+
effects[effect] = Array.isArray(data[effect]) ? data[effect].some((e) => e.enabled) : !!data[effect]?.enabled;
|
|
208
361
|
}
|
|
209
362
|
return effects;
|
|
210
363
|
}
|
|
@@ -256,20 +409,20 @@ var blendModes = [
|
|
|
256
409
|
"luminosity",
|
|
257
410
|
"passThrough"
|
|
258
411
|
];
|
|
259
|
-
|
|
412
|
+
function getLayerKind(layer) {
|
|
260
413
|
const kind = layerKindMap.get(layer.layerKind);
|
|
261
414
|
if (!kind) {
|
|
262
415
|
throw new Error(`Unknown layer kind: ${layer.layerKind}`);
|
|
263
416
|
}
|
|
264
417
|
return kind;
|
|
265
|
-
}
|
|
266
|
-
|
|
418
|
+
}
|
|
419
|
+
function getBlendMode(layer) {
|
|
267
420
|
const mode = layer.mode._value;
|
|
268
421
|
if (!blendModes.includes(mode)) {
|
|
269
422
|
throw new Error(`Unknown blend mode: ${mode}`);
|
|
270
423
|
}
|
|
271
424
|
return mode;
|
|
272
|
-
}
|
|
425
|
+
}
|
|
273
426
|
function photoshopLayerDescriptorsToUTLayers(layers) {
|
|
274
427
|
const root = [];
|
|
275
428
|
const stack = [{ layers: root }];
|
|
@@ -301,12 +454,12 @@ function photoshopLayerDescriptorsToUTLayers(layers) {
|
|
|
301
454
|
}
|
|
302
455
|
return root;
|
|
303
456
|
}
|
|
304
|
-
|
|
457
|
+
function determineLayerSection(layer) {
|
|
305
458
|
const section = layer.layerSection._value;
|
|
306
459
|
const isGroupEnd = layer.name === "</Layer group>" || layer.name === "</Layer set>" || section === "layerSectionEnd";
|
|
307
460
|
const isGroupStart = section === "layerSectionStart";
|
|
308
461
|
return isGroupStart ? "start" : isGroupEnd ? "end" : "normal";
|
|
309
|
-
}
|
|
462
|
+
}
|
|
310
463
|
function getEffects(layer) {
|
|
311
464
|
const effects = {};
|
|
312
465
|
if (layer.layerEffects) {
|
|
@@ -317,25 +470,6 @@ function getEffects(layer) {
|
|
|
317
470
|
return effects;
|
|
318
471
|
}
|
|
319
472
|
|
|
320
|
-
// src/ut-tree/utLayersToTree.ts
|
|
321
|
-
function utLayersToTree(layer) {
|
|
322
|
-
return layer.map((layer2) => ({
|
|
323
|
-
ref: {
|
|
324
|
-
name: layer2.name,
|
|
325
|
-
docId: layer2.docId,
|
|
326
|
-
id: layer2.id,
|
|
327
|
-
visible: layer2.visible,
|
|
328
|
-
kind: layer2.kind,
|
|
329
|
-
blendMode: layer2.blendMode,
|
|
330
|
-
isClippingMask: layer2.isClippingMask,
|
|
331
|
-
effects: layer2.effects,
|
|
332
|
-
background: layer2.background
|
|
333
|
-
},
|
|
334
|
-
name: layer2.name,
|
|
335
|
-
children: layer2.layers ? utLayersToTree(layer2.layers) : void 0
|
|
336
|
-
}));
|
|
337
|
-
}
|
|
338
|
-
|
|
339
473
|
// src/ut-tree/utLayersToText.ts
|
|
340
474
|
var VISIBLE_ICON = "\u25EF";
|
|
341
475
|
var INVISIBLE_ICON = "\u2298";
|
|
@@ -354,7 +488,8 @@ function utLayersToText(tree, depth = 0) {
|
|
|
354
488
|
const visible = layer.visible ? VISIBLE_ICON : INVISIBLE_ICON;
|
|
355
489
|
const line = [visible, prefix, clippingMask, group, name, effects, blend].filter(Boolean).join(" ");
|
|
356
490
|
if (layer.layers) {
|
|
357
|
-
return line
|
|
491
|
+
return `${line}
|
|
492
|
+
${utLayersToText(layer.layers, depth + 1)}`;
|
|
358
493
|
}
|
|
359
494
|
return line;
|
|
360
495
|
}).join("\n");
|
|
@@ -363,6 +498,25 @@ function isSpecialBlendMode(layer) {
|
|
|
363
498
|
return layer.kind === "group" ? layer.blendMode !== "passThrough" : layer.blendMode !== "normal";
|
|
364
499
|
}
|
|
365
500
|
|
|
501
|
+
// src/ut-tree/utLayersToTree.ts
|
|
502
|
+
function utLayersToTree(layer) {
|
|
503
|
+
return layer.map((layer2) => ({
|
|
504
|
+
ref: {
|
|
505
|
+
name: layer2.name,
|
|
506
|
+
docId: layer2.docId,
|
|
507
|
+
id: layer2.id,
|
|
508
|
+
visible: layer2.visible,
|
|
509
|
+
kind: layer2.kind,
|
|
510
|
+
blendMode: layer2.blendMode,
|
|
511
|
+
isClippingMask: layer2.isClippingMask,
|
|
512
|
+
effects: layer2.effects,
|
|
513
|
+
background: layer2.background
|
|
514
|
+
},
|
|
515
|
+
name: layer2.name,
|
|
516
|
+
children: layer2.layers ? utLayersToTree(layer2.layers) : void 0
|
|
517
|
+
}));
|
|
518
|
+
}
|
|
519
|
+
|
|
366
520
|
// src/util/utLayerToLayer.ts
|
|
367
521
|
import { app as app2 } from "photoshop";
|
|
368
522
|
function utLayerToDomLayer(layer) {
|
|
@@ -380,7 +534,8 @@ function utLayerToDomLayer(layer) {
|
|
|
380
534
|
return domLayer;
|
|
381
535
|
}
|
|
382
536
|
function utLayersToDomLayers(layers) {
|
|
383
|
-
if (layers.length === 0)
|
|
537
|
+
if (layers.length === 0)
|
|
538
|
+
return [];
|
|
384
539
|
const docId = layers[0].docId;
|
|
385
540
|
if (!layers.every((l) => l.docId === docId)) {
|
|
386
541
|
throw new Error("All layers must be from the same document.");
|
|
@@ -400,112 +555,6 @@ function utLayersToDomLayers(layers) {
|
|
|
400
555
|
return domLayer;
|
|
401
556
|
});
|
|
402
557
|
}
|
|
403
|
-
|
|
404
|
-
// src/error-sourcemaps/sourcemaps.ts
|
|
405
|
-
import ErrorStackParser from "error-stack-parser";
|
|
406
|
-
import { SourceMapConsumer } from "source-map-js";
|
|
407
|
-
import { storage as storage2 } from "uxp";
|
|
408
|
-
|
|
409
|
-
// src/node-compat/path/resolvePath.ts
|
|
410
|
-
import { resolve as nativeResolve } from "path";
|
|
411
|
-
function pathResolve(...pathSegments) {
|
|
412
|
-
const urlOrString = nativeResolve(...pathSegments);
|
|
413
|
-
if (typeof urlOrString === "string") {
|
|
414
|
-
return urlOrString;
|
|
415
|
-
}
|
|
416
|
-
if (isUrl(urlOrString)) {
|
|
417
|
-
return urlOrString.toString();
|
|
418
|
-
}
|
|
419
|
-
throw new Error("Unexpected URL object");
|
|
420
|
-
}
|
|
421
|
-
function isUrl(urlOrString) {
|
|
422
|
-
return urlOrString instanceof URL;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// src/errors/ut-error.ts
|
|
426
|
-
var UTError = class extends Error {
|
|
427
|
-
constructor(message, opts = {}) {
|
|
428
|
-
super(message, opts);
|
|
429
|
-
this.name = "UTError";
|
|
430
|
-
}
|
|
431
|
-
};
|
|
432
|
-
|
|
433
|
-
// src/error-sourcemaps/sourcemaps.ts
|
|
434
|
-
async function parseUxpErrorSourcemaps(error, opts = {}) {
|
|
435
|
-
const parsedError = parseErrorIntoBasicStackFrames(error);
|
|
436
|
-
const unsourcemappedHeaderLines = opts.unsourcemappedHeaderLines ?? 0;
|
|
437
|
-
const loadedFilesCache = {};
|
|
438
|
-
const fs = storage2.localFileSystem;
|
|
439
|
-
const parsedMappedError = [];
|
|
440
|
-
for (const frame of parsedError) {
|
|
441
|
-
if (!frame.fileName || !frame.lineNumber || !frame.columnNumber) {
|
|
442
|
-
parsedMappedError.push(frame);
|
|
443
|
-
continue;
|
|
444
|
-
}
|
|
445
|
-
const entryPath = "plugin:" + frame.fileName;
|
|
446
|
-
const file = loadedFilesCache[entryPath] ?? await fs.getEntryWithUrl(entryPath);
|
|
447
|
-
loadedFilesCache[entryPath] = file;
|
|
448
|
-
if (!file.isFile) {
|
|
449
|
-
parsedMappedError.push(frame);
|
|
450
|
-
continue;
|
|
451
|
-
}
|
|
452
|
-
const sourcemapFileEntryPath = entryPath + ".map";
|
|
453
|
-
const sourcemapFile = loadedFilesCache[sourcemapFileEntryPath] ?? await fs.getEntryWithUrl(sourcemapFileEntryPath);
|
|
454
|
-
loadedFilesCache[sourcemapFileEntryPath] = sourcemapFile;
|
|
455
|
-
if (!sourcemapFile.isFile) {
|
|
456
|
-
parsedMappedError.push(frame);
|
|
457
|
-
continue;
|
|
458
|
-
}
|
|
459
|
-
const sourcemapContents = await sourcemapFile.read({});
|
|
460
|
-
const sourcemap = JSON.parse(sourcemapContents);
|
|
461
|
-
const smc = new SourceMapConsumer(sourcemap);
|
|
462
|
-
const mappedFrame = smc.originalPositionFor({
|
|
463
|
-
line: frame.lineNumber - unsourcemappedHeaderLines,
|
|
464
|
-
column: frame.columnNumber
|
|
465
|
-
});
|
|
466
|
-
if (mappedFrame.source && mappedFrame.line && mappedFrame.column) {
|
|
467
|
-
parsedMappedError.push({
|
|
468
|
-
...frame,
|
|
469
|
-
fileName: mappedFrame.source,
|
|
470
|
-
lineNumber: mappedFrame.line,
|
|
471
|
-
columnNumber: mappedFrame.column
|
|
472
|
-
});
|
|
473
|
-
} else {
|
|
474
|
-
parsedMappedError.push(frame);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
return parsedMappedError;
|
|
478
|
-
}
|
|
479
|
-
function parseErrorIntoBasicStackFrames(error) {
|
|
480
|
-
try {
|
|
481
|
-
const frames = ErrorStackParser.parse(error);
|
|
482
|
-
return frames.map((frame) => {
|
|
483
|
-
return {
|
|
484
|
-
functionName: frame.functionName,
|
|
485
|
-
fileName: frame.fileName,
|
|
486
|
-
lineNumber: frame.lineNumber,
|
|
487
|
-
columnNumber: frame.columnNumber
|
|
488
|
-
};
|
|
489
|
-
});
|
|
490
|
-
} catch (e) {
|
|
491
|
-
throw new UTStacktraceParsingError("Failed to parse error stack trace", { cause: e });
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
async function getBasicStackFrameAbsoluteFilePath(frame) {
|
|
495
|
-
const pluginFolder = await storage2.localFileSystem.getPluginFolder();
|
|
496
|
-
const absoluteFileName = pathResolve(
|
|
497
|
-
pluginFolder.nativePath,
|
|
498
|
-
"index.js",
|
|
499
|
-
frame.fileName
|
|
500
|
-
).replace(/^plugin:/, "");
|
|
501
|
-
return `${absoluteFileName}:${frame.lineNumber}:${frame.columnNumber}`;
|
|
502
|
-
}
|
|
503
|
-
var UTStacktraceParsingError = class extends UTError {
|
|
504
|
-
name = "UTStacktraceParsingError";
|
|
505
|
-
constructor(message, opts = {}) {
|
|
506
|
-
super(message, opts);
|
|
507
|
-
}
|
|
508
|
-
};
|
|
509
558
|
export {
|
|
510
559
|
batchPlay,
|
|
511
560
|
batchPlayCommand,
|
|
@@ -521,6 +570,8 @@ export {
|
|
|
521
570
|
getDocumentLayerDescriptors,
|
|
522
571
|
getFlattenedDomLayersList,
|
|
523
572
|
getLayerEffects,
|
|
573
|
+
isFile,
|
|
574
|
+
isFolder,
|
|
524
575
|
mapTree,
|
|
525
576
|
mapTreeRef,
|
|
526
577
|
openFileByPath,
|
|
@@ -1,70 +1,69 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { ActionDescriptor } from 'photoshop
|
|
1
|
+
import * as photoshop from 'photoshop';
|
|
2
|
+
import { action, ActionDescriptor } from 'photoshop';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
declare function createMultiGetDocumentCommand(docId: number): UTCommandNonModifying<{
|
|
6
|
+
list: {
|
|
7
|
+
name: string;
|
|
8
|
+
layerID: number;
|
|
9
|
+
visible: boolean;
|
|
10
|
+
group: boolean;
|
|
11
|
+
layerSection: {
|
|
12
|
+
_value: "layerSectionStart" | "layerSectionEnd" | "layerSectionContent";
|
|
13
|
+
_enum: "layerSectionType";
|
|
14
|
+
};
|
|
15
|
+
layerKind: number;
|
|
16
|
+
itemIndex: number;
|
|
17
|
+
background: boolean;
|
|
18
|
+
mode: {
|
|
19
|
+
_enum: "blendMode";
|
|
20
|
+
_value: string;
|
|
21
|
+
};
|
|
22
|
+
layerEffects?: Record<string, {
|
|
23
|
+
enabled?: boolean | undefined;
|
|
24
|
+
} | {
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
}[]> | undefined;
|
|
27
|
+
}[];
|
|
28
|
+
}>;
|
|
5
29
|
|
|
6
30
|
type P = Parameters<typeof action.batchPlay>;
|
|
7
31
|
type CorrectBatchPlayOptions = P[1] & {
|
|
8
32
|
immediateRedraw?: boolean;
|
|
9
33
|
};
|
|
10
|
-
declare function batchPlay(actions: P[0], options?: CorrectBatchPlayOptions): Promise<
|
|
34
|
+
declare function batchPlay(actions: P[0], options?: CorrectBatchPlayOptions): Promise<photoshop.ActionDescriptor[]>;
|
|
11
35
|
|
|
12
|
-
interface UTCommandBase<T
|
|
36
|
+
interface UTCommandBase<T> {
|
|
13
37
|
descriptor: ActionDescriptor;
|
|
14
38
|
schema: z.ZodSchema<T>;
|
|
15
39
|
}
|
|
16
|
-
interface UTCommandModifying<T
|
|
40
|
+
interface UTCommandModifying<T> extends UTCommandBase<T> {
|
|
17
41
|
modifying: true;
|
|
18
42
|
}
|
|
19
|
-
interface UTCommandNonModifying<T
|
|
43
|
+
interface UTCommandNonModifying<T> extends UTCommandBase<T> {
|
|
20
44
|
modifying: false;
|
|
21
45
|
}
|
|
22
|
-
declare function createCommand<TReturn
|
|
46
|
+
declare function createCommand<TReturn, TModifying extends boolean>(obj: {
|
|
23
47
|
descriptor: ActionDescriptor;
|
|
24
48
|
schema: z.ZodSchema<TReturn>;
|
|
25
49
|
modifying: TModifying;
|
|
26
50
|
}): TModifying extends true ? UTCommandModifying<TReturn> : UTCommandNonModifying<TReturn>;
|
|
27
51
|
type UTCommandResult<C> = C extends UTCommandBase<infer T> ? T : never;
|
|
28
52
|
type BatchPlayOptions = Parameters<typeof batchPlay>[1];
|
|
29
|
-
declare function batchPlayCommandBase<T
|
|
53
|
+
declare function batchPlayCommandBase<T>(command: UTCommandBase<T>, options?: BatchPlayOptions): Promise<T>;
|
|
30
54
|
declare function batchPlayCommandsBase<TCommands extends Array<UTCommandBase<any>>>(commands: readonly [...TCommands], options?: BatchPlayOptions): Promise<{
|
|
31
55
|
[K in keyof TCommands]: UTCommandResult<TCommands[K]>;
|
|
32
56
|
}>;
|
|
33
|
-
declare function batchPlayCommand<T
|
|
57
|
+
declare function batchPlayCommand<T>(command: UTCommandNonModifying<T>, options?: BatchPlayOptions): Promise<T>;
|
|
34
58
|
declare function batchPlayCommands<TCommands extends Array<UTCommandNonModifying<any>>>(commands: readonly [...TCommands], options?: BatchPlayOptions): Promise<{ [K in keyof TCommands]: UTCommandResult<TCommands[K]>; }>;
|
|
35
59
|
declare function createModifyingBatchPlayContext(): {
|
|
36
60
|
batchPlayCommand: typeof batchPlayCommandBase;
|
|
37
61
|
batchPlayCommands: typeof batchPlayCommandsBase;
|
|
38
62
|
};
|
|
39
63
|
|
|
40
|
-
|
|
41
|
-
list: {
|
|
42
|
-
name: string;
|
|
43
|
-
layerID: number;
|
|
44
|
-
visible: boolean;
|
|
45
|
-
group: boolean;
|
|
46
|
-
layerSection: {
|
|
47
|
-
_value: "layerSectionStart" | "layerSectionEnd" | "layerSectionContent";
|
|
48
|
-
_enum: "layerSectionType";
|
|
49
|
-
};
|
|
50
|
-
layerKind: number;
|
|
51
|
-
itemIndex: number;
|
|
52
|
-
background: boolean;
|
|
53
|
-
mode: {
|
|
54
|
-
_enum: "blendMode";
|
|
55
|
-
_value: string;
|
|
56
|
-
};
|
|
57
|
-
layerEffects?: Record<string, {
|
|
58
|
-
enabled?: boolean | undefined;
|
|
59
|
-
} | {
|
|
60
|
-
enabled: boolean;
|
|
61
|
-
}[]> | undefined;
|
|
62
|
-
}[];
|
|
63
|
-
}>;
|
|
64
|
-
|
|
65
|
-
type PsLayerRef = {
|
|
64
|
+
interface PsLayerRef {
|
|
66
65
|
id: number;
|
|
67
66
|
docId: number;
|
|
68
|
-
}
|
|
67
|
+
}
|
|
69
68
|
|
|
70
69
|
export { type CorrectBatchPlayOptions as C, type PsLayerRef as P, type UTCommandBase as U, type UTCommandModifying as a, type UTCommandNonModifying as b, createModifyingBatchPlayContext as c, type UTCommandResult as d, batchPlay as e, batchPlayCommand as f, batchPlayCommands as g, createCommand as h, createMultiGetDocumentCommand as i };
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bubblydoo/uxp-toolkit",
|
|
3
|
-
"version": "0.0.8",
|
|
4
|
-
"license": "MIT",
|
|
5
3
|
"type": "module",
|
|
4
|
+
"version": "0.0.10",
|
|
6
5
|
"author": "Hans Otto Wirtz <hansottowirtz@gmail.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/bubblydoo/uxp-toolkit/tree/main/packages/uxp-toolkit",
|
|
7
8
|
"repository": {
|
|
8
9
|
"type": "git",
|
|
9
10
|
"url": "https://github.com/bubblydoo/uxp-toolkit.git"
|
|
10
11
|
},
|
|
11
|
-
"homepage": "https://github.com/bubblydoo/uxp-toolkit/tree/main/packages/uxp-toolkit",
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
@@ -32,10 +32,8 @@
|
|
|
32
32
|
"xmlbuilder2": "^4.0.3"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@adobe-uxp-types/uxp": "^0.0.9",
|
|
36
35
|
"@types/chai": "^5.2.3",
|
|
37
36
|
"@types/node": "^20.8.7",
|
|
38
|
-
"@types/photoshop": "^25.0.2",
|
|
39
37
|
"chai": "^6.2.2",
|
|
40
38
|
"dedent": "^1.7.1",
|
|
41
39
|
"rollup": "^4.57.0",
|
|
@@ -43,13 +41,17 @@
|
|
|
43
41
|
"typescript": "^5.8.3",
|
|
44
42
|
"vitest": "^4.0.18",
|
|
45
43
|
"zod": "^4.3.6",
|
|
44
|
+
"@adobe-uxp-types/photoshop": "0.1.1",
|
|
45
|
+
"@adobe-uxp-types/uxp": "0.1.1",
|
|
46
46
|
"@bubblydoo/tsconfig": "0.0.3",
|
|
47
|
-
"@bubblydoo/uxp-test-framework": "0.0.
|
|
47
|
+
"@bubblydoo/uxp-test-framework": "0.0.10"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "tsup",
|
|
51
51
|
"test": "vitest run",
|
|
52
52
|
"uxp-test:build": "uxp-test build",
|
|
53
|
-
"uxp-test:dev": "uxp-test dev"
|
|
53
|
+
"uxp-test:dev": "uxp-test dev",
|
|
54
|
+
"typecheck": "tsc --noEmit",
|
|
55
|
+
"docs-json": "typedoc --json docs.json"
|
|
54
56
|
}
|
|
55
57
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import type { PsLayerRef } from '../ut-tree/psLayerRef';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { createCommand } from '../core/command';
|
|
4
4
|
|
|
5
5
|
export function createAddLayerToSelectionCommand(
|
|
6
6
|
layerRef: PsLayerRef,
|
|
7
|
-
previousLayerRef: PsLayerRef
|
|
7
|
+
previousLayerRef: PsLayerRef,
|
|
8
8
|
) {
|
|
9
9
|
return createCommand({
|
|
10
10
|
modifying: true,
|