AEM DAM sup­ports InDe­sign doc­u­ments in a lim­ited way out of the box, but many more options are avail­able through the use of the Adobe InDe­sign Server prod­uct. In this blog post, we’ll have a look at what extra fea­tures are enabled when an InDe­sign Server is present and also at what else can be obtained by cus­tomiz­ing the InDe­sign Server Scripts that are included in AEM DAM.

What is Adobe InDe­sign Server?

Adobe InDe­sign Server is an engine that lever­ages the design, lay­out, and typo­graph­i­cal capa­bil­i­ties of InDe­sign CS6 to let you pro­gram­mat­i­cally cre­ate auto­mated doc­u­ments. InDe­sign oper­a­tions can be scripted using an imple­men­ta­tion of JavaScript that Adobe calls ExtendScript.

How is InDe­sign used by AEM DAM?

The DAM Update Asset work­flow that is included in AEM has a step called Media Extrac­tion. The con­fig­u­ra­tion for the step includes a list of scripts that are exe­cuted sequen­tially when an INDD doc­u­ment is uploaded to DAM or updated. By default, those are:

Gen­er­ates a JPEG thumb­nail of the document’s front page.
Gen­er­ates an HTML rep­re­sen­ta­tion of the InDe­sign doc­u­ment
Gen­er­ates an IDML file (XML-based markup describ­ing the struc­ture and con­tents of the document).

InDe­sign exposes its ser­vices using SOAP on a TCP port that must be spec­i­fied on the com­mand line that is used to start the server. Here is the com­mand used to tell InDe­sign Server to lis­ten on TCP port 8080:

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

On AEM’s side, the con­nec­tion is con­fig­ured in the Cloud Ser­vices > Cloud Proxy Con­fig­u­ra­tion > IDS worker sec­tion of the Tools con­sole (http://server:port/etc/cloudservices/proxy/ids.html). By default, AEM is con­fig­ure to con­nect to InDe­sign at http://localhost:8080, so you don’t nor­mally have to change that, unless port 8080 is used by some other appli­ca­tion or InDe­sign Server is run­ning on a remote host.

InDe­sign Scripting

Giv­ing a tuto­r­ial on InDe­sign script­ing is beyond the scope of this post, but you can peruse the Adobe InDe­sign CS6 Server Script­ing Guide to learn how to do it (see the Resources sec­tion). It is instruc­tive to look at the exist­ing scripts, if all you need is to extend the base func­tion­al­ity, as we will do in the next sec­tion. You can find those in CRX, under /etc/dam/indesign/scripts.

Sam­ple Scripts

We will show two sam­ple scripts to illus­trate some of the capa­bil­i­ties of InDe­sign. These scripts are based on the orig­i­nal ThumbnailExport.jsx one and extend it to gen­er­ate thumb­nails for all the pages in a doc­u­ment, in either JPEG or PDF format.

You can find these two scripts in this pack­age. To acti­vate them, add them to the list of scripts invoked by the Media Extrac­tion step in the DAM Update Asset workflow.

Let’s have a look at the PdfExportPages.jsx script. If you com­pare it with ThumbnailExport.jsx, you will notice the sim­i­lar­i­ties. The main dif­fer­ence is the addi­tion of code to loop over all pages in the cur­rent document:

for (var i = 0 ; i < document.pages.length ; ++i) {
exportPage(document, i, exportFolder.fullName, file­Name, resour­cePath, host, cre­den­tials);

Here is the full source code of the script:

// Export any Inde­sign doc­u­ment as PDF

//==== get soap argu­ments ====
if (app.scriptArgs.isDefined(“credentials”)) {
var cre­den­tials = app.scriptArgs.getValue(“credentials”);
} else {
throw “CQ host cre­den­tials argu­ment is miss­ing”;
if (app.scriptArgs.isDefined(“cqHost”)) {
var host = app.scriptArgs.getValue(“cqHost”);
} else {
throw “cqHost argu­ment is miss­ing”;
if (app.scriptArgs.isDefined(“resource”)) {
var resour­cePath = app.scriptArgs.getValue(“resource”);
} else {
throw “resource argu­ment is miss­ing”;

try {
//==== cre­ate a tem­po­rary folder under InDe­sign server tmp direc­tory to fetch and export ====
// added ran­dom­ness to the folder name
var export­Folder = new Folder(“tmp-” + (new Date().getTime() — Math.floor((Math.random()*10000)+1) ));
file­Name = resourcePath.substring (resourcePath.lastIndexOf (‘/’), resourcePath.lastIndexOf (‘.’));
var source­File = new File(exportFolder.fullName + file­Name + ‘.indd’);

app.consoleout(‘Fetching resource from CQ: ‘+resour­cePath);
fetchRe­source (host,  cre­den­tials, resour­cePath, sourceFile);

var doc­u­ment =;

with (app.pdfExportPreferences) {
view­Doc­u­mentAfter­Ex­port = false;
export­ing­Spread = true;
for (var i = 0 ; i < document.pages.length ; ++i) {
exportPage(document, i, exportFolder.fullName, file­Name, resour­cePath, host, cre­den­tials);

// close the doc­u­ment

//==== remove the orig­i­nal resource and send the export back to CQ ====

return­Value = “PDF exported and posted suc­cess­fully”;
} finally {
//==== remove the temp folder ====
app.consoleout(‘Finished PDF export…’);

func­tion exportPage(document, pageNo, fold­er­Name, file­Name, resour­cePath, host, cre­den­tials) {
//app.pdfExportPresets.item(“[Press Qual­ity]”);
var page­Name = document.pages.item(pageNo).name;
app.pdfExportPreferences.pageRange = page­Name;
//The name of the exported files will be the base name + the
//page name + “.pdf”. If the page name con­tains a colon (as it will
//if the doc­u­ment con­tains sec­tions), then remove the colon.
var reg­Exp = /:/gi;
page­Name = pageName.replace(regExp, “_”);
var page­File­Name = file­Name + “_” + page­Name + “.pdf”;
var filePath = fold­er­Name + page­File­Name;
app.consoleout(‘Writing page ’ + i + ’ to ’ + filePath);
var out­put­File = new File(filePath);
document.exportFile(ExportFormat.pdfType, out­put­File);
//==== send file to CQ ====
var tar­get = resourcePath.substring (0, resourcePath.lastIndexOf (‘/’)) + “/subassets”;
app.consoleout(‘Posting this file to CQ: ’ + filePath);
app.consoleout(‘Posting to loca­tion: ’ + tar­get);
putRe­source (host, cre­den­tials, out­put­File, page­File­Name, ‘application/pdf’, tar­get);