Jun 21, 2013

InDesign Server Scripts in AEM DAM

Posted by Ugo Cei

AEM DAM supports InDesign documents in a limited way out of the box, but many more options are available through the use of the Adobe InDesign Server product. In this blog post, we'll have a look at what extra features are enabled when an InDesign Server is present and also at what else can be obtained by customizing the InDesign Server Scripts that are included in AEM DAM.

What is Adobe InDesign Server?

Adobe InDesign Server is an engine that leverages the design, layout, and typographical capabilities of InDesign CS6 to let you programmatically create automated documents. InDesign operations can be scripted using an implementation of JavaScript that Adobe calls ExtendScript.

How is InDesign used by AEM DAM?

The DAM Update Asset workflow that is included in AEM has a step called Media Extraction. The configuration for the step includes a list of scripts that are executed sequentially when an INDD document is uploaded to DAM or updated. By default, those are:

Generates a JPEG thumbnail of the document's front page.

Generates an HTML representation of the InDesign document

Generates an IDML file (XML-based markup describing the structure and contents of the document).

InDesign exposes its services using SOAP on a TCP port that must be specified on the command line that is used to start the server. Here is the command used to tell InDesign Server to listen on TCP port 8080:

<path-to-installation-directory>/InDesignServer -port 8080

On AEM's side, the connection is configured in the Cloud Services > Cloud Proxy Configuration > IDS worker section of the Tools console (http://server:port/etc/cloudservices/proxy/ids.html). By default, AEM is configure to connect to InDesign at http://localhost:8080, so you don't normally have to change that, unless port 8080 is used by some other application or InDesign Server is running on a remote host.

InDesign Scripting

Giving a tutorial on InDesign scripting is beyond the scope of this post, but you can peruse the Adobe InDesign CS6 Server Scripting Guide to learn how to do it (see the Resources section). It is instructive to look at the existing scripts, if all you need is to extend the base functionality, as we will do in the next section. You can find those in CRX, under /etc/dam/indesign/scripts.

Sample Scripts

We will show two sample scripts to illustrate some of the capabilities of InDesign. These scripts are based on the original ThumbnailExport.jsx one and extend it to generate thumbnails for all the pages in a document, in either JPEG or PDF format.

You can find these two scripts in this package. To activate them, add them to the list of scripts invoked by the Media Extraction step in the DAM Update Asset workflow.

Let's have a look at the PdfExportPages.jsx script. If you compare it with ThumbnailExport.jsx, you will notice the similarities. The main difference is the addition of code to loop over all pages in the current document:

for (var i = 0 ; i < document.pages.length ; ++i) {
    exportPage(document, i, exportFolder.fullName, fileName, resourcePath, host, credentials);

Here is the full source code of the script:

// Export any Indesign document as PDF

//==== get soap arguments ====
if (app.scriptArgs.isDefined("credentials")) {
    var credentials = app.scriptArgs.getValue("credentials");
} else {
    throw "CQ host credentials argument is missing";
if (app.scriptArgs.isDefined("cqHost")) {
    var host = app.scriptArgs.getValue("cqHost");
} else {
    throw "cqHost argument is missing";
if (app.scriptArgs.isDefined("resource")) {
    var resourcePath = app.scriptArgs.getValue("resource");
} else {
    throw "resource argument is missing";

try {
    //==== create a temporary folder under InDesign server tmp directory to fetch and export ====
    // added randomness to the folder name
    var exportFolder = new Folder("tmp-" + (new Date().getTime() - Math.floor((Math.random()*10000)+1) ));
    fileName = resourcePath.substring (resourcePath.lastIndexOf ('/'), resourcePath.lastIndexOf ('.'));
    var sourceFile = new File(exportFolder.fullName + fileName + '.indd');

    app.consoleout('Fetching resource from CQ: '+resourcePath);
    fetchResource (host,  credentials, resourcePath, sourceFile);

    var document =;

    with (app.pdfExportPreferences) {
        viewDocumentAfterExport = false;
        exportingSpread = true;
    for (var i = 0 ; i < document.pages.length ; ++i) {
        exportPage(document, i, exportFolder.fullName, fileName, resourcePath, host, credentials);

    // close the document

    //==== remove the original resource and send the export back to CQ ====

    returnValue = "PDF exported and posted successfully";
} finally {
    //==== remove the temp folder ====
app.consoleout('Finished PDF export...');

function exportPage(document, pageNo, folderName, fileName, resourcePath, host, credentials) {
    //app.pdfExportPresets.item("[Press Quality]");
    var pageName = document.pages.item(pageNo).name;
    app.pdfExportPreferences.pageRange = pageName;
    //The name of the exported files will be the base name + the
    //page name + ".pdf". If the page name contains a colon (as it will
    //if the document contains sections), then remove the colon.
    var regExp = /:/gi;
    pageName = pageName.replace(regExp, "_");
    var pageFileName = fileName + "_" + pageName + ".pdf";
    var filePath = folderName + pageFileName;
    app.consoleout('Writing page ' + i + ' to ' + filePath);
    var outputFile = new File(filePath);
    document.exportFile(ExportFormat.pdfType, outputFile);
    //==== send file to CQ ====
    var target = resourcePath.substring (0, resourcePath.lastIndexOf ('/')) + "/subassets";
    app.consoleout('Posting this file to CQ: ' + filePath);
    app.consoleout('Posting to location: ' + target);
    putResource (host, credentials, outputFile, pageFileName, 'application/pdf', target);