This guide will show you how to use CEP (Common Extensibility Platform) and ExtendScript to export a saved asset from Adobe Creative Cloud applications.
By the end of this guide, we will have a CEP extension that:
- Gives the user multiple options for export by clicking on buttons in a panel
- Exports the active document as one of the following formats:
- JPG
- PNG
- Original
- Technology Used
- Prerequisites
- Configuration
- Client-side: HTML Markup
- Client-side: Creative Cloud host app interaction
- Host app: Automation with ExtendScript
- Other Resources
- Supported Host Applications: Photoshop, Illustrator, InDesign
- Libraries/Frameworks/APIs:
- Adobe-specific: CEP, ExtendScript for Photoshop, Illustrator, and InDesign
This guide will assume that you have read and completed the following resources.
The following steps will help you get the sample extension for this guide up and running:
-
Install the
./com.cep.export/
directory in yourextensions
folder. (See the Cookbook if you are unsure where yourextensions
folder is.) -
Download
CSInterface.js
from the Adobe CEP repo and move it to./com.cep.export/client/js/lib/CSInterface.js
As noted in the Getting Started guide, the manifest.xml
file is where, among other things, you indicate which Creative Cloud host apps and versions your extension supports.
This sample is designed to be compatible with three different Adobe applications: Photoshop, Illustrator, and InDesign.
Make sure to include these within the <HostList>
element:
<HostList>
<Host Name="PHXS" Version="16.0" />
<Host Name="PHSP" Version="16.0" />
<Host Name="ILST" Version="16.0" />
<Host Name="IDSN" Version="13.0" />
</HostList>
Note that the versions indicated in the example code above only target a single version of each host app, for the sake of demo simplicity. Most extension developers will want to target a range of host app versions. To learn how to support multiple host app versions, see the Cookbook.
The user interface for CEP extensions is written in HTML. For this sample, the HTML document is located at ./com.cep.export/client/index.html
and contains the following code (see comments #1-2):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Export Example App</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<h1>Export Example App</h1>
<!-- 1) A div with buttons for different export types -->
<div id="button-group">
<button id="export-original" class="btn btn-primary btn-block">Original</button>
<button id="export-pdf" class="btn btn-primary btn-block">PDF</button>
<button id="export-jpg" class="btn btn-primary btn-block">JPG</button>
<button id="export-png" class="btn btn-primary btn-block">PNG</button>
</div>
<!-- 2) Your scripts, including CEP's CSInterface.js library -->
<script type="text/javascript" src="js/lib/CSInterface.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>
Note that, while this guide will not cover styling an extension with CSS, the CSS stylesheet for this sample panel can be found at ./com.cep.export/client/styles/style.css
.
Make a variable for the button group container div
and each of the buttons that we just added to our index.html
file:
var buttonGroup = document.querySelector("#button-group");
var pdfButton = document.querySelector("#export-pdf");
var jpgButton = document.querySelector("#export-jpg");
var pngButton = document.querySelector("#export-png");
var originalButton = document.querySelector("#export-original");
We'll work with these UI elements in the next step.
Now we'll add a click handlers to each of the buttons:
pdfButton.addEventListener('click', function(){exportWithType('pdf');}, false);
jpgButton.addEventListener('click', function(){exportWithType('jpg');}, false);
pngButton.addEventListener('click', function(){exportWithType('png');}, false);
originalButton.addEventListener('click', function(){exportWithType();}, false);
Notice how each of these click handlers attaches an anonymous function to the click event that in turn calls an exportWithType()
function. This is a helper function that we'll create in an upcoming section.
For any CEP panel, you'll need an instance of CSInterface
, which, among other things, gives you a way to communicate with the host app's scripting engine:
var csInterface = new CSInterface();
We'll make use of this csInterface
variable in the next step.
To communicate with the host app's scripting engine, we'll make use of the csInterface.evalScript()
method. (If you need a refresher on the .evalScript()
method, refer to the Getting Started guide.)
In this sample extension, users can export the current asset as four different file types to the current asset's directory. To achieve this, the following exportWithType(type)
helper function calls evalScript()
to communicate with the host application:
function exportWithType(type) {
csInterface.evalScript(`exportFile("${type}")`, function(path) {
alert("File saved at " + path);
});
}
We could interpret the .evalScript()
call above as meaning:
Hey host app, call the
exportFile()
function from my ExtendScript file.
We’ll need to make sure that ExtendScript function exists in the next section.
Many CC host apps like Photoshop, Illustrator, and InDesign (and many more) can be automated with ExtendScript, which provides many deep features to automate work in CC host apps; you can explore more ExtendScript features in our Scripting Guides.
The ExtendScript file for this extension is located at ./com.cep.export/host/index.jsx
.
In this sample extension's index.jsx
file, we will only need to create one function:
function exportFile(type) {
// Code will go here
}
This function takes the type
string argument that we provided in the client-side .evalScript()
call.
Through ExtendScript, we can, among other things, interact with the host app's DOM to interact with elements in an open document. The available DOM properties and methods vary for each host app. However, there are some common elements that apply in all three host applications that this extension is built for.
You can keep the common code at the top of the function like this (see comments #1-4):
function exportFile(type) {
/* 1) get the full file path */
var filePath = app.activeDocument.fullName;
/* 2) split the path to get the extension of the file */
var splitPath = filePath.toString().split('.');
var originalExtension = splitPath[splitPath.length-1];
/* 3) split the path to get the folder path */
var folderPath = filePath.toString().split('/').slice(0,-1).join('/') + '/';
/* 4) sanitize the full path */
var sanitizedFilePath = File(filePath).fsName;
...
}
Since the host-side scripting features are different from app to app, you will need to handle the work based on the app the extension is running in, like this:
if (app.name == "Adobe Illustrator") {
// ...
} else if (app.name == "Adobe Photoshop") {
// ...
} else if (app.name == "Adobe InDesign") {
// ...
}
// ...
Now this extension will behave differently according to whether it's running in Illustrator, Photoshop, or InDesign.
Within each if
block, we will handle each export type with further logic.
The example below is for Photoshop (see comments #1-6):
if (type == "pdf") {
/* 1) Set PDF save options */
pdfSaveOptions = new PDFSaveOptions();
pdfSaveOptions.optimization = true;
/* 2) Use saveAs() to export the PDF document (note that you cannot use exportFile() for a PDF) */
app.activeDocument.saveAs(File(sanitizedFilePath), pdfSaveOptions);
} else if (type == "jpg") {
/* 3) Set JPEG save options */
var exportOptions = new ExportOptionsJPEG();
exportOptions.blurAmount = 2;
exportOptions.matte = true;
exportOptions.qualitySetting = 100;
/* 4) Use exportFile() to export the JPEG document */
app.activeDocument.exportFile(File(sanitizedFilePath), ExportType.JPEG, exportOptions);
} else if (type == "png") {
/* 5) Set PNG save options */
var exportOptions = new ExportOptionsPNG8();
exportOptions.matte = true;
/* 6) Use exportFile() to export the PNG document */
app.activeDocument.exportFile(File(sanitizedFilePath), ExportType.PNG8, exportOptions);
}
Note that the above example is written for Photoshop. ExtendScript methods and properties may differ depending on the host app, but the same login will apply. See this guide's sample extension code for further examples.
If you want to explore further with ExtendScript, refer to the following reference docs: