Skip to main content
Content Starts Here Search Solutions

Solution Detail

 
Solution TitleHow to rewrite Switch scripts from AppleScript to JavaScript
Solution Number00000751
Solution Details
Starting from Switch 2017 scripts written using the AppleScript scripting language are deprecated. It is still possible to use already existing scripts in Switch flows (on Mac), however it is no longer possible to create and debug such scripts in SwitchScripter.

Although running existing Switch scripts in AppleScript is still supported it is recommended to rewrite them using the JavaScript scripting language as soon as possible. This Knowledge Base article provides some hints on how to do this.

A Switch script in any scripting language normally uses the following types of API:
  • Platform API: access to file system, network communication, processes management etc.
  • Switch scripting API: environment exposed by Switch that includes objects like Switch, Job, Connection, Dataset etc.
  • Third-party applications scripting API: automation interfaces offered by other applications, for example, command line interface, scripting API (that can be platform-dependent: VBScript on Windows, AppleScript on Mac), COM interfaces on Windows, SOAP or REST API etc.

The calls to the API types listed above are included in the general script logic that normally also involves other typical tasks like string manipulation, storing and sorting data in memory using containers, converting between types of data, searching in strings, serializing and parsing data etc. These tasks are performed using some “standard” set of features provided by the language: basic data types, library of objects (including containers) and algorithm implementations.

Rewriting an existing Switch script from AppleScript to JavaScript should be relatively straightforward unless AppleScript automates a third-party application using its AppleScript automation API.

The “standard” set of features and the platform API Switch supports in JavaScript is wide enough. It includes the object types like String, Date, ByteArray, RegExp, File, Dir, HTTP, SOAP, DataSource, Document, Process etc. That is why rewriting the related logic from AppleScript to JavaScript normally means just finding a similar or replacement object type or function call.

Note: If there is a feature in AppleScript that is important for you and there is no similar or replacement feature in JavaScript, you can submit a feature request using the Enfocus Support Portal.

The Switch environment exposed via the AppleScript version of the Switch scripting API is the same for any supported scripting language so all the objects like Switch, Job, Dataset are available in JavaScript as well.

The more difficult case is when the AppleScript includes calls to the scripting API of a third-party application (for example, a script that uses AppleScript API exposed by Adobe InDesign).

First of all it is necessary to check if the third-party application provides other automation interfaces like a command line interface or a REST API. If there are no other interfaces or using them from JavaScript is too difficult, then the strategy should be the following:
  1. Minimize the amount of the logic that needs to remain in AppleScript as much as possible and make sure this logic does not use the Switch scripting API.
  2. Write the main logic of the script in JavaScript and whenever required execute the minimized AppleScript logic from point 1 using the ‘osascript’ command line utility provided by Mac OSX.
  3. Implement input and output data transfers between main JavaScript and AppleScript snippets executed by ‘osascript’.
Here is an example of a Switch script in pseudo-AppleScript containing commands for the Adobe InDesign application:

tell application "Adobe InDesign CC 2017"
    -- open a document in Adobe InDesign using job path
    -- process the document (for example, update external links)
    -- export the resulting document in a temporary PDF file
    -- close the document
end tell

Assuming the only available automation interface for InDesign is AppleScript, the following steps should be performed:
  1. Minimizing AppleScript: the script code from ‘tell application’ to ‘end tell’ should contain only the calls that cannot be done from JavaScript. Objects like ‘Job’ and ‘Switch’ shall not be used: if there is a need to get a job path or a value of the flow element property, these will be input parameters passed to AppleScript in point 3)
  2. Main JavaScript: the Switch script may include the minimized AppleScript as a resource file or generate it at runtime and save it to a temporary file. Whenever it is time to perform processing in InDesign, the input data for the AppleScript is prepared, then the ‘osascript’ utility is started with a parameter that is the path to a file with minimized AppleScript:

    var theReturnValue = Process.execute( ‘/usr/bin/osascript "’ + theAppleScriptPath + ‘"’ ) ;

  3. The input data for AppleScript may include different parts of the Switch environment: job path, flow element properties values, temporary output path etc. This data can be serialized to a file on disk so it can later be read from AppleScript. Another way is to include this data as a set of variables initialized by constant values at the beginning of the AppleScript (in case the AppleScript is composed dynamically by the main JavaScript at runtime). The AppleScript output data like paths to resulting files and error messages can be passed back to JavaScript using some temporary file on disk.

It is also necessary to foresee the error handling (for the cases when ‘osascript’ fails or hangs).

The described approach can be considered as automating an application using a command line interface (‘osascript’ utility) with a command file parameter that is a small script in AppleScript.

Note: Starting from Mac OSX 10.10 Apple offers the JXA (JavaScript for Automation) technology. This means that the minimized AppleScript from point 1) can be actually written as a JavaScript using a similar API. However except for the same syntax there are no other advantages: such a JavaScript shall be executed using the ‘osascript’ utility in the same way as AppleScript.

Specifically for AppleScripts driving the Adobe InDesign application there are other possible approaches:

  • InDesign also exposes a JavaScript automation API so the AppleScript can be rewritten in JavaScript for InDesign and the same objects like ‘Application’, ‘Document’, ‘Layer’ can be used there. However, Switch cannot execute this script directly, so it has to ask to do this either through the Adobe ExtendScript Toolkit or the ‘osascript’ utility:
    • The main JavaScript generates JavaScript for InDesign at runtime (or reads it from a file path provided in the script element property)
    • Then the JavaScript uses the Process class to start one of the following:
      • The ‘osascript’ utility that will execute small fixed managing AppleScript
      • The Adobe ExtendScript Toolkit application
    • The utility or application starts InDesign and forces it to execute the generated JavaScript.
The fixed managing AppleScript is a script like:
tell application ‘Adobe InDesign’
    activate
    do script <JavaScript code> language javascript
end tell

The advantage of this approach is that the complete processing logic is in JavaScript rather than in AppleScript.
  • It is also possible to use the InDesign configurator and write a custom script for the ‘Open’, ‘Command’ or the ‘Save As’ properties that use the JavaScript automation API exposed by InDesign. Internally that JavaScript will be executed by Switch similarly like described above. The extra parameters can be passed using the properties ‘Argument 1’, ‘Argument 2’ etc. available in the configurator.
 
Does this solution help you answer your question?