Installing IdExtenso locally is super easy: go to, click Code (the green button) and Download ZIP.

Downloading IdExtenso from GitHub.

Extract the contents of into your development folder, that is, at any location that suits you! The only important point is that you must remember the path to that location, either absolute or relative from your own JSX script. IdExtenso's package looks like this:

Main IdExtenso's files and folders.

The vital elements are the [core] and [etc] folders, and the $$.jsxinc file, referred to as the InDesign scripting “Entry Point.” ($$.estk.jsxinc and $$.spin.jsxinc are alternate entry points that you might use while targeting ExtendScript ToolKit, other Adobe apps, or when you want to add a spinner to your script. We won't discuss those advanced topics here.)

For now, just make sure that you can access $$.jsxinc using a #include directive from your script(s). In absolute form, the line may look like

    #include '/my/path/to/IdExtenso-master/$$.jsxinc'


    //@include '/my/path/to/IdExtenso-master/$$.jsxinc'

to get rid of linter warnings.

For my part I prefer relative paths, as I develop most of my InDesign scripts within a dedicated subfolder of the IdExtenso package. For example, including the Entry Point from any direct subfolder —say [tests]— simply requires the directive #include '../$$.jsxinc'.

Tip. — Having your final scripts outside of InDesign's Scripts panel is not an issue. Just put a shortcut to the actual JSX file in the [Scripts Panel] folder!

Embed and trace your Code in IdExtenso

Rule paramount: IdExtenso must be included, then loaded. These are two distinct stages:

    #include '/my/path/to/IdExtenso-master/$$.jsxinc'

    // (2) LOADING STAGE

    // (3) Your Code Here

Why is this so important? Because the including stage can be extended for declaring additional modules —either those available in the [etc] folder, or even extra stuff that you may design and implement yourself in the future!

• The framework is syntactically operational as soon as $$.jsxinc is included. This means that the root object $$ is declared and already provides minimal routines and syntactic sugars for adding features in IdExtenso's dialect. (I will not say too much about it for now.)

• However, it is only after the loading stage $$.load() that all included modules and dependencies become fully available. There is a very simple way to figure it out: included stuff may need to interact for computing, linking, or sharing resources. And some data cannot be processed before knowing which components have to play.

To sum up, the role of the including stage is to declare features, the role of the loading stage is to consolidate some data before processing. And the first thing you want to know about the $$.load() method is that it supports a logLevel argument, either in string or numeric form:

logLevel Description
0 or "MUTE" or undefined Turn off the Log system: none of the messages sent to it will be reported and the log file won't show up.
-1 or "TRACE" Turn on the Log in TRACE mode: any message sent using either $$.trace() or $$.warn() will be reported.
+1 or "WARN" Turn on the Log in WARN mode: only the warning messages, sent using $$.warn(), will be reported.

The logging system (implemented in core/$$.Log.jsxlib) is a core mechanism that allows you to optionally record what happened during the execution of your script. Your code can now contain typically two new commands:

$$.trace("My custom message") for reporting various data or informative messages.

$$.warn("My custom alert") for reporting critical messages, very useful in debugging.

If IdExtenso is loaded in TRACE mode, all messages are reported whatever their level, so you will get a full recording of logged events, including warnings. In WARN mode, the logging system will only react to $$.warn(), ignoring $$.trace() commands. And if you load IdExtenso in MUTE mode, no message will be processed at all. When powered, the log file automatically shows up as the script is stopping.

Note. — If the ESTK console is active, it also displays log messages during the execution.

Our Base Example (Version 2)

Below is our base code wrapped in IdExtenso …with logging commands and additional goodies:

Some changes might freak you out, so let's explain them briefly:

Most literal strings "bla bla" are now formatted __("bla bla"), and sometimes with more arguments! Why that? Because we anticipate the localization of the script in other languages. The special __() function is always available in IdExtenso, even if the localization module (YALT) is not included yet. So far, __ (two underscores) is an alias of the native $.global.localize function, which greatly helps format strings with nested placeholders (%1, %2, etc.)

Line 14. — The old getParentSpread function just vanished! Well, IdExtenso provides its own $$.parentSpread() routine, no need to reinvent the wheel ;-)

Line 39. — Better is to keep the user informed if nothing is selected. The method $$.failure(someMessage) has been designed for that purpose. By the way, all core messaging methods are detailed here.

Line 46. — What is In short, callee refers to the very function that embodies the present code. Although deprecated in modern JavaScript (for reasons that I fight vigorously!), callee is IMHO one of the most important ExtendScript features, in that it lets you develop and connect functional bricks without the arbitrary requirement of knowing their name. This is a debate that would take me far beyond this tutorial, so let's summarize it to its simplest form: IdExtenso is almost entirely rooted in the principle of first-class functions.

Line 92-94. — Yes, you have now a $$.JSON() method for inspecting the inner structure of everything ;-) But why using (+$$.trace) && $$.trace(…) instead of just $$.trace(…)? First, note that (+$$.trace) is a special shortcut that tells you whether the TRACE mode is active (it returns 0 otherwise.) Hence the syntax (+$$.trace) && doSomething() operates as a conditional statement: doSomething() won't be executed at all if the TRACE mode is disabled. The conditional execution becomes useful when doSomething() is time-consuming, which is possibly the case of invoking $$.JSON(). Use this trick whenever $$.trace or $$.warn requires the calculation of a complex argument. In MUTE mode (which is the state of the final release of your script), no time wil be spent for computing that argument.

Line 126. — Oh! I forgot to tell you. IdExtenso pays attention to memory and garbage collection. If possible and relevant, it tells to any loaded module that it's time to unload its data. Using $$.unload() at the end of your script is the clean way of freeing up memory once the task is finished.

Now you just have to run this new version in InDesign and give a look at the log:

IdExtenso's log file in TRACE mode.

Interesting, isn't it?

STEP 1 | … | STEP 3 | STEP 4 | STEP 5