Creating ePub Documents with Scripts IV

Wednesday, January 30, 2013

This is the fourth in our series to demonstrate how a simple ePub document can be created using scripts. To create the skeleton for our document, a script named ePubDocFromPreset was used. This script depended on a stylesheet and a document preset having been created prior to running the script. When the script is run, the user is given a dialog box in which to enter a name for the project, and designate the document preset and the stylesheet to be used. The script then creates the document using the document preset and imports styles from the stylesheet. The document is saved in a folder named the same as the project name residing in the Documents folder for the user. If this folder does not exist, it is created.

The project folder needs to have a plain text file containing a single story flow for the document. For the images, there needs to be a folder named "images" with an image for each page of the document, and optionally a cover image. The images are expected to be jpeg and named using the following convention: "pg01.jpg" thru "pg99.jpg". It is not anticipated that the completed book would be more than 99 pages long. The cover page needs to be named Cover.jpg.

When your book's resources are in the project folder, the script PopulateWRepeatingStyles is used to place the text and images. To determine the paragraph styles to use for styling the text and for placing the image, a dialog box is presented to the user. Here the user also designates the object style to use for the image anchor.

The text is styled using an interesting algorithm within a repeating loop (see last week's blog). This is possible because the text follows a standard pattern throughout.

The subroutine that places the text gets the name of all image files in the Images folder. Because image files are named consistent with its target page (pg01.jpg, and so on), the script is able to place the files using the insertion point for the paragraph having the designated paragraph style.

As its last step, the subroutine assigns the object style to the images using the style designated by the user in the custom dialog.

The function placeImages requires a reference to the active document, the name of the imageFolder (images), and the name of the object style that will apply the anchor settings. If there is no object style (No Style), a default anchor style is created.


(*Places images found in imageFolder and anchors using object style*)
on placeImages(docRef, imageFolder, anchorStyleName)
   --get name of all jpeg files in folder named images	
   tell application "Finder"
	if not (exists folder (imageFolder)) then
	     error "Image folder not found in Users Directory"
	     set projectFolder to folder (imageFolder)
	     set fileList to name of every file of projectFolder whose file type = {"jpg"} or name extension = "jpg"
	end if
   end tell

   tell application "Adobe InDesign CS6"
	tell docRef
            --get reference to object style; if it does not exist, then create the style
		set anchoredStyle to object style anchorStyleName
	     on error
		display alert ("creating anchor style " & anchorStyleName)
		set anchoredStyle to my createAnchorStyle(docRef)
	    end try
            --repeat through the pages and place the images using the first insertion point of the defined paragraph
	    repeat with i from 1 to count of pages
		set thisName to "pg" & (text 1 thru -1 of "0" & i) & ".jpg"
		if thisName is in fileList then
		        set fileRef to imageFolder & ":" & thisName
			set frameRef to text frame 1 of page i
			set paraRef to object reference of paragraph targetStyleIndex of frameRef
			tell insertion point 1 of paraRef
			     set placedList to place file fileRef
			     set imageRef to item 1 of placedList
			end tell
			set containerRef to parent of imageRef
			set applied object style of containerRef to anchoredStyle	
		end if
	     end repeat
	end tell
     end tell
end placeImages 


/*Places images found in imageFolder and anchors using object style*/
function placeImages (docRef, imageFolder, anchorStyleName) {
    var pageRef = docRef.pages.item(0);
    //returns array of image files using function listFiles_FolderRef
    var imageList = listFiles_FolderRef (imageFolder, fileExt);
    //checks for anchored style; creates default style if not found
    if (docRef.objectStyles.item(anchorStyleName).isValid) {
             var anchoredStyle = docRef.objectStyles.item(anchorStyleName);
     } else {
            alert ("Creating anchor style " + anchorStyleName);
             var anchoredStyle = createAnchorStyle (docRef);
    //parse imageList and get list of names only
    var imageNameList = [];
    var imageName;
    var lastIdx;
    for (var i = 0; i < imageList.length; i++) {
        imageName = imageList[i].toString();
        lastIdx = imageName.lastIndexOf("/");
        imageNameList.push(imageName.substr(lastIdx + 1));
    //repeat through pages and place image named for page number
    var pageCount = docRef.pages.count();
    var thisPageRef;
    for (var i = 0; i < pageCount; i++) {
        var thisName = "pg" + ("0" + (i+1)).substr(-2) + ".jpg";
        thisPageRef = docRef.pages.item(i);
         var frameRef = thisPageRef.textFrames.item(0);
          var paraRef = frameRef.paragraphs.item(targetStyleIndex);
          try {
             var placedList = paraRef.insertionPoints.item(0).place(File(imageFolder + "/" + thisName));
              var imageRef = placedList[0];
              var containerRef = imageRef.parent;
              containerRef.appliedObjectStyle = anchoredStyle;
          } catch(e){
              //do nothing; add functionality here if desired

The placeImage function in ExtendScript requires two helper functions:

  • listFiles_FolderRef() - returns list of files in folder having extension matching value for global variable fileExt (defined at top of script)
  • createAnchorStyle() - creates default anchor style if "No Style" is selected in the custom dialog for the name of the object style.

AppleScript only requires createAnchorStyle(). This is one place you will find a big difference between AppleScript and ExtendScript. With ExtendScript, having to support both Windows' and Apple's file system adds a fair amount of code to the script. That is the price one pays for a script supporting both platforms. The code for listFiles_FolderRef follows:


//returns list of files found in folder referenced based on file extension
function listFiles_FolderRef (filePath, fileExt){
	//get folder reference using value for filePath variable 
	var folderRef = Folder(filePath);
	//determine system you are running on
	if (File.fs == "Windows") {
		var fileList = folderRef.getFiles("*" + fileExt);
	} else {
		checkExt = fileExt.toUpperCase();
		var fileList = folderRef.getFiles (listByExt);
	if (fileList.length == 0) {
		throw ("No files found");
	return fileList;
	/*filter function for getFiles on Macintosh; checking for extension*/	
	function listByExt (objRef) {
		if (objRef instanceof File) {
			return objRef.name.toUpperCase().indexOf(checkExt)!= -1;
		} else {
			return false;

In contrast, AppleScript can get the file list with a one-line statement addressed to the Finder:

tell application "Finder"
     set fileList to name of every file of projectFolder whose file type = {"jpg"} or name extension ="jpg"
end tell

Make sure you understand the functionality for the placeImages subroutine. You are sure to use much of its code in scripts of your own. All that is left at this point is to bullet-proof the script. Among the processes you might add would be to have the user select image files if not found.

Trackback Link
Post has no trackbacks.