A modern starter for writing Adobe Extendscript
(yes, another one)
Writing Extendscript (Ecmascript 3) is rather annoying once you're used to modern Javascript. You expect to use array methods and common practices such as .env
files, no-nonsense bundling, rebuilding on changes, etc.
Other starters don't actually transform modern Javascript, so you have to write helper functions for your beloved array methods which totally defeats the point of writing modern Javascript. You might polyfill them, but that pollutes the global scope (which is bad for everyone if you found a shitty implementation on Stack Overflow).
- Modern Javascript with ponyfills (see babel-preset-extendscript)
- Ecmascript modules for importing and exporting
- Fast bundling with esbuild (TODO: insert obligatory lightning bolt emoji)
- Rebundles on file changes
- Minifies the release version
- Converts to binary with extendscript-debugger
- Wraps bundle in an IIFE to avoid global variables
- Exposes environment variables to Javascript files
- Includes JSON automatically as a ponyfill
- Copies static files from
/static
(with esbuild-copy-static-files) - Imports
?text
suffixed paths as strings - Imports icons as binary strings
- Duplicate
.env.example
and remove the.example
extension - Run
npm install && npm start
in your terminal - Run
/build/extender.jsx
in your Adobe app of choice
npm install && npm start
This will start watching your source files and builds into the build
folder.
npm run release
This will bundle, minify and jsxbin your source files into the dist
folder.
All variables are replaced by their values upon bundling.
By default the bundler exposes:
DEVMODE
whenNODE_ENV
isdevelopment
or not,PRODUCT_NAME
which isname
frompackage.json
,PRODUCT_DISPLAY_NAME
which isdisplayName
frompackage.json
andPRODUCT_VERSION
which isversion
frompackage.json
If you have a .env
file it will automatically expose the variables by their name to all Javascript files.
Every .js
file in the root of the source/
folder is considered an entrypoint. Multiple entrypoints will result in multiple scripts being bundled separately, keeping the same name as their entrypoint. If there's a single entrypoint it will be renamed to name
from package.json
.
Press F5
in VSCode to launch the debugger and you will be prompted for the host application. To avoid the prompt set the hostAppSpecifier
in launch.json
You can't use breakpoints in your source files, because the Extendscript Debugger doesn't support source maps. Instead, use a debugger
statement in your source files or set breakpoints in the bundled file (/build/{PRODUCT_NAME}.jsx
).
To import JavaScript files as strings you can suffix the path with ?text
and import them with a custom default name. This is useful when you have snippets that you want to import as strings. Having them as separate files allows you to format and lint them separately, use TypeScript definitions on them, etc. Note that they will be imported as-is and don't get transpiled. This works for any other text based files.
See src/main.js
Using icons in scriptUI is easiest when you add them to your source code. To do this you can import the icons directly as .png
or .jpg
. They are then transformed to a binary string that can be read by File.decode()
.
See src/main.js
You can import Node modules by simply using import xyz from 'xyz'
. Note that they can't contain browser or Node APIs. Also note that quite some modern Javascript is not yet ponyfilled by babel-preset-extendscript.
The contents of /static
will be copied to the outdir
whenever you run the bundler. This is useful for icons, readme files, etc. Note that any changes in this folder will not be watched, so you need to run the bundler again or save a change in your source files.
Only whitespaces are removed and variable names are shortened. The syntax remains intact to avoid Extendscript errors.
Types for Adobe is part of the package, so you can simply use triple-slash directives to get the type definitions for your target app. Or create a tsconfig.json
to define which types to use in the whole project.
See src/main.js
You should even be able to make it work with Typescript if that's your thing.
You can still write regular old Extendscript without the modern syntax.