Your prescription for increased productivity and profitability
Electronic publications with fixed formats rely on absolute positioning. This allows text to be positioned on top of images. Positioning elements on a page is determined in the CSS file. When you export an InDesign document as HTML, the application assumes you are creating a dynamic formatted document where element positioning can change depending on the device, user preference settings, and so on. Consequently, no information is written to the CSS as to the positioning of text or other elements. Of course, in updating the CSS file you can “guestimate” positioning. In this and the next two blogs, we will explore how a script can be used to accomplish this task for you. In the previous four blogs we walked through a script that exports the pages of a document as jpeg files. This leaves the document with all text frames residing on a layer named by the user. For writing our script, we can start with the modified document. That way we can get a list of all text frames using the layer reference.
--Assuming that the text layer is named "Text", we can get the list of the document's text frames set layerName to "Text" tell application "Adobe InDesign CS6" --assumes the modified document is open, with measurements set to points set docRef to document 1 tell docRef set layerRef to layer layerName of docRef end tell set frameList to text frames of layerRef end tell frameList
var layerName = "Text"; var docRef = app.documents.item(0); var layerRef = docRef.layers.itemByName(layerName); var frameList = layerRef.textFrames; frameList.length;
What we will want our script to do is get the information about each text frame and write the information to a text file. Then, when working with our project’s CSS file, that information will be readily available. When writing a script that needs to work with a number of items in a list, it is best to start with one item in the list for testing. Once this works as anticipated. the repeat loop is easy to add.
We will organize our script using a subroutine to return the text frame information as a string.
(*Returns information for text frame referenced*) on textFrameInfo(frameRef) tell application "Adobe InDesign CS6" --get the name of the page the frame is on set pName to name of parent page of frameRef --get the geometric bounds for the frame copy geometric bounds of frameRef to {y0, x0, y1, x1} --get the text for the text frame set tContent to text 1 of frameRef end tell --now do the calculations set frameWid to x1 - x0 set frameHgt to y1 - y0 --create the information string set textStr to "page " & pName & " xPosition: " & x0 & " yPosition: " & y0 & " frameWid: " & set textStr to textStr & " frameHgt: " & frameHgt & " Content: " & tContent return textStr end textFrameInfo
function textFrameInfo (frameRef) { var pName = frameRef.parentPage.name; var gBounds = frameRef.geometricBounds; var y0 = gBounds[0]; var x0 = gBounds[1]; var y1 = gBounds[2]; var x1 = gBounds[3]; var tContent = frameRef.texts.item(0); //do calculations var frameWid = x1 - x0; var frameHgt = y1 - y0; //create information string var textStr = "page " + pName + " xPosition: " + x0 + " yPosition: " + y0 +" frameWid: " + frameWid textStr += " frameHgt: " + frameHgt + " Content: " + tContent; return textStr; }
With this handler in place (at the bottom of the script), all we need to do is add the call to the handler. Placing the textStr variable at the end returns the result of the handler to the Result window for Script Editor (Console for ExtendScript).
--place the following at the bottom of the top portion of the script above: set frameRef to item 1 of frameList set textStr to textFrameInfo (frameRef) textStr
//place the following at the bottom of the top portion of the script above: var frameRef = frameList[0] var textStr = textFrameInfo (frameRef); textStr;
Once you make sure the information being returned is what you want, surround the call to the handler with a repeat loop:
repeat with i from 1 to length of frameList set frameRef to item i of frameList --notice the reference is to item i, not 1 set textStr to textFrameInfo (frameRef) end repeat
for (var i = 0; i < frameList.length; i++){ var frameRef = frameList[i] var textStr = textFrameInfo (frameRef); }
Lastly, the script will write the text strings returned to a plain text file. We will create the file in the same folder as the document. For this we need to get the path to the document and use this to construct a file path to the text file.
--inside the tell statement to the document set docPath to (file path of docRef) as string --before writing the text to the fie set filePath to docPath & "FrameInfo.txt"
AppleScript and ExtendScript are quite different in how they handle writing text to files. With AppleScript you set the end of file marker (eof) to 0 to write to a file without append. With ExtendScript the open method starts a new file without append. Otherwise text written to the file is appended.
With each iteration of our repeat loop, the text returned will be written to the file using another handler, “writeToFile_append”. This handler requires a path to the file, the text string, and a boolean (true/false) to indicate if the text is to be appended to the existing file.
(*Writes text string to file given path to file (filePath) and string to write (textStr). Returns length of file.*) on writeToFile_append(filePath, textStr, doAppend) try set fileRef to open for access file filePath with write permission on error errStr --in case file not closed is cause for error close access fileRef set fileRef to open for access file filePath with write permission end try set fileLength to (get eof fileRef) if doAppend = false then set eof fileRef to 0 write textStr to fileRef else write (return & textStr) to fileRef starting at ((get eof fileRef) + 1) end if set newLength to (get eof fileRef) close access fileRef return (newLength - fileLength) end writeToFile_append
The first time through the loop, we will not append the text. Thereafter, we will want the text to append. The top of our script will now read as follows:
set layerName to "Text" --assumes text layer is named "Text" set doAppend to false --initialize to false tell application "Adobe InDesign CS6" --assumes that there is a document open set docRef to document 1 tell docRef set docPath to (file path of docRef) as string --assumes all text frames have been moved to layer (layerName variable) set layerRef to layer layerName of docRef end tell set frameList to text frames of layerRef end tell --define file path for text file using folder for document set filePath to docPath & "FrameInfo.txt" repeat with i from 1 to length of frameList --change item reference to i, rather than 1 set frameRef to item i of frameList --call handler to get the text frame information set textStr to textFrameInfo(frameRef) if i = 2 then set doAppend to true writeToFile_append(filePath, textStr, doAppend) end repeat
To allow the script to open the file once and close when completed, the write functionality is included in the top portion of the script.
var fileRef = undefined; var layerName = "Text"; var docRef = app.documents.item(0); var dPath = docRef.filePath; var docPath = Folder.decode(dPath); var layerRef = docRef.layers.itemByName(layerName); var frameList = layerRef.textFrames; //establish path for file and write text to file var writePath = docPath + "/TestExtendScript.txt"; var fileRef = File(writePath); var fileOpen = fileRef.open("w", "TEXT", "????"); if (fileOpen == true) { for (var i = 0; i < frameList.length; i++){ var frameRef = frameList[i] var textStr = textFrameInfo (frameRef); fileRef.writeln(textStr); } fileRef.close(); }//end if
To test the script at this point you will need to open the text file created using any plain text editor. The script is just an outline of what we want the script to do as there are a number of assumptions being made. As is often quoted, “the devil is in the details.” We will look at the details in next week’s blog.