Search code examples
node.jsmacosnpmadobeextendscript

Use npm package in ExtendScript


Update

All of my work to get a fully functioning InDesign CC 2018/2019 CEP panel working is in https://github.com/theasci/cep-boostrap. I was able to successfully get npm packages working in both the client and host portions of the CEP panel and in the Scripts Panel. However, the node and ExtendScript versions are woefully old. See the repo READMEs for more details


Original Question

I have a large collection of scripts in AppleScript, mostly for InDesign CC 2018, that I'm trying to redo in ExtendScript (for portability). With the recent prerelease of the ExtendScript Debugger for Visual Studio Code, I've gotten the stack to work. I am able to log to the console and display alerts using the builtins $.write() and alert() through InDesign.

I'd like to use the goodness that is npm packages for heavy lifting but I'm failing to get them to load properly. For instance, I want to load the fairly simple node-logger (compared to winston), but loading all the shims I can find, doesn't seem to work.

Here is an example of my index.jsx file

// Any attempt to write to a read-only property causes a runtime error.
$.strict = true

// Run this script within the InDesign application
#target indesign

var rootDir = File($.fileName).path;

// Load ExtendScript monkey patches to allow for Node.js related functionality
$.evalFile(rootDir + '/vendor/node_modules/extendscript-es6-shim/index.js'); //loads fine
$.evalFile(rootDir + '/vendor/node_modules/extendscript.prototypes/lib/extendscript.prototypes.js'); //loads fine
$.evalFile(rootDir + '/vendor/es-require/lib/require.js'); //loads fine
$.evalFile(rootDir + '/vendor/node_modules/node-logger/logger.js'); //Error: require is not a function

alert("If you're here, it's working!");

My .vscode/launch.json looks like this

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "extendscript-debug",
            "request": "launch",
            "name": "Project name",
            "program": "${workspaceFolder}/source/index.jsx",
            "targetSpecifier": "indesign-13.064", 
            "engineName": "main",
        }
    ]
}

As you can see, I'm a bit over my head, since node and npm are new to me. It seems like ExtendScript doesn't have the require functionality it needs to pull in node modules. It also seems like people go the other direction: start in node and then execute ExtendScript.

Questions

  1. Do people load recent versions of npm packages into ExtendScript? If so, how?
  2. Should I do this? If not, what's the best way to use npm modules with ExtendScript to automate stuff within Adobe products?

Environment

  • Mac OSX El Capitan 10.11.6 (also tried on High Sierra, with same result)
  • Visual Studio Code 1.31.1
  • ExtendScript Debugger Plugin for VSCode 0.2.4
  • npm config list says user-agent = "npm/6.5.0 node/v11.9.0 darwin x64"

Thanks in advance for having pity on this poor soul.


Solution

  • ExtendScript is ES3, so I'm not sure which kind of magic those monkey patches are pulling in order to make this archaic format run like Node. It would seem to me though that something about that is failing in your case. As the node stuff is in a whole different kind of javascript, it's likely that this approach is not possible.

    You probably can have a separate node application that can interact with your jsx scripts. Mainly, it can manipulate your InDesign via running jsx scripts on it that perhaps carry arguments and return results to it.

    It would kind-of hinge on being able to replicate AppleScript's 'do javascript' command which runs is available within a 'tell an adobe application' block and can execute dynamically-made javascripts with arguments as well as return the results synchronously.

    I'm not sure how to make sure all the users have the right items installed on their systems - for running the Node. Maybe they all have to make some kind of installer. For example, when writing a simple jsx script all you have to do is provide the script to the users, but with this hypothetical setup it's not clear to me at this moment.

    Alternatively, the next step up is a CEP extension which can use Node and the browser in it and also can run jsx scripts and get the results, etc. The main obstacle with this is the amount of work needed to make the entire project work, it is an overwhelming amount of information at first and carries perhaps a lot more overhead than making a simple custom node application which uses jsx routines.

    If you find a way to provide easy-to-install cross-platform node-jsx application to users, that may be a quick method for delivering powerful scripted apps to the users in those cases where all the flare of a built-in browser UI is too much effort for the intended usage. For example, if you wish to do some application control in Node that jsx can't do, and are able to get by with the ExtendScript ScriptUI or other means for the UI then it would work out well.