InDesign ExtendScript API is surprisingly robust
April 12th, 2021
I've recently had a chance to work with InDesign's ExtendScript, and I found it surprisingly full of features. Since it can be interfaced with via JavaScript, I thought it'd be nice to take a look at some of them and see what type of control it gives us over our design files.
Lack of support for modern ES standard
This is worth mentioning at the start, ExtendScript as of now supports only the ES3 version of JavaScript. This obviously results in a specific approach to writing script files. One example is the lack of JSON global object, which means if you want to work with JSON structures, either importing or exporting it, you will require a polyfill.
Syntax extension
ExtendScript extends the JS syntax with directives and language modifications. These new features are described in the ESTK documentation on Adobe's website. For instance look at how the following syntax differs from the ES JS devs usually know:
/* Custom directives */
#include "JSON.jsx"
/* Operator overloading */
function TestClass(initialValue) {
this.value = initialValue;
}
TestClass.prototype["+"] = function (operand) {
return this.value + operand;
}
var example = new TestClass(5);
// This will return 10
example + 5;
Besides the official resources, I recommend looking at the InDesign ExtendScript API reference. It has a nice search functionality and is intuitive to use when digging into different classes found in the InDesign Object Model.
Creating and saving files
// https://www.indesignjs.de/extendscriptAPI/indesign-latest/#File.html
var file = new File("default-filename.js");
var data = "Content of the file";
// Allow user to select where his file will be saved
var userPath = file.saveDlg();
file.changePath(userPath);
file.encoding = "UTF-8";
file.open("w");
file.write(data);
file.close();
file.copy();
// OS-Specific alert window
alert("File saved!");
Iterating over every page + fetching page contents
var doc = app.activeDocument;
for (var i = 0; i < doc.pages.length; i++) {
// https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Page.html
var page = doc.pages[i];
// A text frame can contain "tables" array, which is simply what
// it's name would suggest, a table nested inside a text frame.
// Table class: https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Table.html
// Array of https://www.indesignjs.de/extendscriptAPI/indesign-latest/#TextFrame.html
var textsAndTables = page.textFrames;
// Array of https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Graphic.html
var images = page.allGraphics;
}
Gathering position and size of elements
// https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Page.html
var pageWidth = page.bounds[3] - page.bounds[1];
var pageHeight = page.bounds[2] - page.bounds[0];
// https://www.indesignjs.de/extendscriptAPI/indesign-latest/#TextFrame.html
var frameWidth = textFrame.geometricBounds[3] - textFrame.geometricBounds[1];
var frameHeight = textFrame.geometricBounds[2] - textFrame.geometricBounds[0];
var posX = textFrame.geometricBounds[1];
var posY = textFrame.geometricBounds[0];
Summary
As you can see, via the ExtendScript API you can access most if not all of your document's elements. On a very expansive design document I counted only TextFrames, Tables in Text Frames and Images, so I was not blocked with doing anything I needed.
I only scratched the surface here as I don't usually work with InDesign or anything related to it. You can find a lot more examples with different configurations and use cases on many different forums across the web. ExtendScript can modify your elements, create new elements, read and modify so called "scriptLabels". It can also react to user's UI interaction.
Official docs: https://www.adobe.com/devnet/scripting/estk.html
Unofficial ExtendScript reference: https://www.indesignjs.de/extendscriptAPI/indesign-latest