Convert an Action into UXP Code (Equivalent of `XTools`' `ActionFileToJavaScript`)


Is there an equivalent to XToolsActionFileToJavascript?
I have an action and I’d like to convert it into UXP batch play.
Alchemist generate code which is hard to navigate through and sometimes misses some actions.

What about converting JSX function (Executing Action Descriptor) to UXP automatically?
Is there anything for that?

Happy New Year!

1 Like

You can vote here: UXP code from Photoshop Actions · Issue #6 · jardicc/alchemist · GitHub

Also, I made this polyfill it is working but I stopped development because Raw data type has unknown implementation in UXP batchplay. And file path data type must have token and those are async therefore the whole call stack has to be async/await therefore you have to rewrite everything into async/await therefore polyfill makes no sense when descriptor has file reference.

Also, I can make a feature to send descriptor from ExtendScript into Alchemist without touching descriptor at all so it would use Native way of conversion into JSON format.


What kind of operations involves RAW Data Type?
If I have a path of the action file (atn) can I just run it from UXP even if it is not loaded in Photoshop?
Or just load it, run it, delete it?

Raw is used e.g. for liquify and puppet warp.

I think you can load and run .atn file. But you need to use token for .atn filepath.

1 Like

What would you suggest doing with actions we have as atn file and ExtendScript in order to bring the functionality into UXP?

In CEP we used the ExtendScript code which was produced by the XTools automated conversion.

So you are saying there is a way to load an action file?

I have a plugin that uses the liquify tool and I am having to run the action from UXP. It works fine. However, I am having the user load the action themselves which I don’t want to do. I want to store the action in the plugin folder and have the plugin load it automatically. The Adobe documentation shows how to play, delete, and duplicate actions. However, there is nothing mentioned about loading an action file, at least nothing I found. If you know how to do this then I would really appreciate if you could share the info or point me to documentation about it :slight_smile:

@ddbell, Have you tried using batchPlay to just “open” the file in Photoshop using a path relative to the plugin folder? I think the plugin folder maybe does NOT require a token, thought I’m not entirely sure. Photoshop will recognize the file as an action file and install it appropriately when it executes the “open” command.

Have you been able to load an action through the open command in UXP?

I just tried this but I couldn’t get it to work. It will open an image file from the plugins folder. However, it won’t open/load an .atn file. I tried both the DOM open command and using batchPlay. For batchPlay, Alchemist didn’t record anything when opening the .atn file. So I tried using a batchPlay function created from opening an image which didn’t work.

Both the DOM and batchPlay work for opening an image. Neither work for opening (loading) an .atn file.

I would say that it’s (currently) not possible to load an .atn file in UXP.
Why? Well, here are some thoughts and tests:

Loading a style (.asl) file can be done like this:

const entry = //...getting entry
  if(entry) {
    const token = //...getting token
    const desc = {
      _obj: 'set',
      _target: [
          _ref: 'property',
          _property: 'style',
          _ref: 'application',
          _enum: 'ordinal',
          _value: 'targetEnum',
      to: {
        _path: token,
        _kind: 'local',
      append: true,
    await photoshop.action.batchPlay([desc],{})

This process is also recordable via Alchemist. Loading .atn files works differently though. Simply replacing the ‘style’ property with ‘action’ does not work. Using a ‘set’-descriptor seems to be specific for importing styles only, well at least it can’t be used for loading actions.

As Alchemist records neither File>Open nor loading an .atn file from the actions panel, I tried to look for extendscript code. Some examples show, that app.load(file) could be used to load .atn files. However, the app object from CEP is not available anymore, instead we got a new app object which only has an open() function. As @ddbell mentioned, this doesn’t seem to open .atn files correctly.

In the forum post I linked above, Mikaeru also provides an ActionManager alternative:

var descriptor = new ActionDescriptor ();
descriptor.putPath (app.stringIDToTypeID ("target"), file);
app.executeAction (app.stringIDToTypeID ("open"), descriptor);

Running this in a .jsx file works fine (you have to get the file first) - the .atn file gets loaded and added to the actions panel correctly.

Converting it to UXP/Batchplay, gives the following descriptor:

      _obj: 'open',
      _target: { _path: "C:\Users\Simon\Desktop\test\dist\actions.atn"}

If you’d want to use a path like that, you’d probably have to escape the backslashes by adding another one ("C:\\Users\\Simon\\Desktop\\test\\dist\\actions.atn"), however we can’t use direct paths in UXP anyway since file access is based on tokens now. This leads to the following test code:

const entry = //... get Entry
if(entry) {
  const token = //... get Token
  const desc = {
    _obj: 'open',
    _target: { _path: token}
  try {
    const res = photoshop.action.batchPlay([desc],{synchronousExecution: true})
  } catch (e) {console.log(e)}

This does not work however. It results in the following error (which doesn’t make a lot of sense):

Illegal data type. Undefined is not supported for this operation

I tried it with the path also which obviously failed and also tried to change _target to target.
Interestingly, using target with the path gave me an

invalid file token used

error, which was expected and gave me hope that it would work with the token. Unfortunately it doesn’t - the batchPlay just runs through without any errors, but the action file is not loaded.

1 Like

@ddbell I was able to load an action file in a manner as in this thread: Can I open a Photoshop file with UXP?

However, I was working from a “vanilla-ps-js” plugin that I was playing with from within the dedicated UXP > extensions folder at the time. Here’s the path I see to the plugin I was playing with:

C:\Program Files\Common Files\Adobe\UXP\extensions\vanilla-ps-js

I’ve found that developing from within this “extensions” folder is not ideal as it let me do things that plugins installed from outside this “extensions” folder sometimes can’t, like ignoring the need for a token. So maybe that was part of the reason it worked. I’ve not tried the code outside this experiment or outside this “extensions” folder, so I guess it’s possible this makes a difference. But I was definitely able to load the .atn file at the time.

I also checked and see that I had actually used a token for this instead of a path as I was experimenting with using tokens at that time.

Anyway, I’ll include the batchPlay I used below in case it helps.

await require('photoshop').action.batchPlay([{ "_obj": "open", "dontRecord": false, "forceNotify": true, "null": { "_path": await getTokenForPath("yourActionPathAndName.atn"), _kind: "local"}, "_options": { "dialogOptions": "dontDisplay" } }], { "synchronousExecution": false }).then(result=>console.log(result), error=>console.log(error))

Your approach doesn’t work for me either. (in a normal plugin environment, haven’t tested the specific folder you mentioned)

Your method doesn’t work for me either. It must be the way you are doing it in the Extensions that allows it to work.

Hopefully, Adobe will make an update and allow this in the future.