• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

How to Pass Arguments from AppleScript to Javascript .jsx (Illustrator ExtendScript)

Participant ,
Apr 24, 2024 Apr 24, 2024

Copy link to clipboard

Copied

Objective:
Create a MacOS droplet. When images are dropped onto it (jpg, jpeg, png, tif, psb, psd, heic) it will grab those images, activate Illustrator and process them via an Illustrator ExtendScript JavaScript (script.jsx). If the droplet is simply opened without dropping files onto it, it'll activate Illustrator then will proceed with the script.jsx which will see no files were passed to it, thereby opening a dialog to accept the images and proceed with the image processing.

 

Methodology:
I'm using AppleScript to create the droplet that will accept the images to get them into a variable. It then activates Illustrator and tries to pass the variable into script.jsx with a do javascript command. That JavaScript will either proceed to process the images if there were any passed to it, or it will display its own dialog to capture the images. The droplet is created in Automator with Run AppleScript action and the script.jsx is saved in the droplet's Contents/Resources folder.

 

Question/Challenge:
How do I properly format/send the arguments from AppleScript so they are stored in the same format as you would get from the File.openDialog command within Illustrator Extendscript?

 

AppleScript Code:

 

on run {input, parameters}
	set imagePaths to {}
	-- Check if input is not empty
	if input is not {} then
		-- Get the file paths of dropped images
		repeat with fileAlias in input
			set posixPath to POSIX path of fileAlias
			set fileExtension to (name extension of (info for posixPath)) as string
			if fileExtension is in {"jpg", "png", "tif", "psd", "psb", "heic"} then
				set end of imagePaths to posixPath
			end if
		end repeat
	end if
	
	set scriptName to "script.jsx"
	set scriptPath to POSIX path of (path to me) & "Contents/Resources/" & scriptName
	set scriptText to (do shell script "cat " & quoted form of scriptPath)
		
	tell application "Adobe Illustrator"
		activate
		do javascript scriptText with arguments {imagePaths}
	end tell
end run

 

 

JavaScript Code:

function main(imagePaths) {

    if (imagePaths.length > 0) { // Input received
            // Set the files variable to the incoming file list from Applescript droplet
            var files = imagePaths;
        } else { // No input received
            // Prompt user to select images if none were supplied from droplet
            var imageFormats = "*.jpg;*.jpeg;*.png;*.tif;*.psd;*.psb";
            var files = File.openDialog("Select images(s) to add to layout:", imageFormats, true);
            if (!files) {
                // User canceled, exit script
                alert("Script canceled by user.");
                return;
            } 

        // rest of code here
    }
}

// Catch error if nothing is passed from AppleScript (no images dropped)
try {
    main(arguments[0]);
} catch (e) {
    // Set imagePaths to empty array
    var imagePaths = [];
    main(imagePaths);
}

 

 

TOPICS
Scripting

Views

357

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 3 Correct answers

Engaged , Apr 24, 2024 Apr 24, 2024

@Chris.S, here's a solution that should work for you. Please note, since you are already using AppleScript, if the droplet is double-clicked (meaning no files are actually provided to the script), I use the much more native (and customizeable) AppleScript to prompt for user for the files. Then the script continues as if the choosen files were dropped on to it.

 

The dropped or choosen paths will come into Ai as an array where you can then make them `File` objects and do whatever you please. If you

...

Votes

Translate

Translate
Engaged , Apr 25, 2024 Apr 25, 2024

@Chris.S, sorry I completely missed the mention of Automator in your original post...

 

So, it seems when running a droplet the getting the `path to me` actually gets the path to the Script Editor app. to fix this, I just use Finder to get the `path to me` which works. As you can see in the script below, I cleaned up a few things and renamed a few variables but it is mostly the same. The really only update is grabbing the `dropletPath` and adding that with the `scriptPath` before using the `do jav

...

Votes

Translate

Translate
Participant , Apr 25, 2024 Apr 25, 2024

Amazing! Thank you again for your help @jduncan. This did the trick.

 

BTW, the reason I moved "on run" below "on open" originally was because it would go straight to "on run" and not process the "on open" when put in Automator. I thought it was because it was doing on run first and that moving it below on open it would do the on open first. I guess I was wrong and that it was likely more to do with calling it from Automator.

This approach is way better than Automator. Thank you again!

 

Votes

Translate

Translate
Adobe
Engaged ,
Apr 24, 2024 Apr 24, 2024

Copy link to clipboard

Copied

@Chris.S, here's a solution that should work for you. Please note, since you are already using AppleScript, if the droplet is double-clicked (meaning no files are actually provided to the script), I use the much more native (and customizeable) AppleScript to prompt for user for the files. Then the script continues as if the choosen files were dropped on to it.

 

The dropped or choosen paths will come into Ai as an array where you can then make them `File` objects and do whatever you please. If you don't want to ask for the files from the user within AppleScript, you could simple run the script and check if no arguments are provided.

 

Hope this helps. Cheers!

 

droplet.app (AppleScript saved as an application)

property theExtensionsToProcess : {"jpg", "png", "tif", "psd", "psb", "heic"}
property scriptPath : "~/Desktop/script.jsx"

on run
	set choosenItems to (choose file with multiple selections allowed)
	open every item of choosenItems
end run

on open droppedItems
	set paths to {}
	
	repeat with a from 1 to length of droppedItems
		set theCurrentItem to item a of droppedItems
		set currentFilePath to POSIX path of theCurrentItem
		set theExtension to (name extension of (info for currentFilePath)) as string
		
		if (theExtensionsToProcess contains theExtension) then
			set end of paths to currentFilePath
		end if
	end repeat
	
	-- check if no valid paths were found (could add an alert)
	if ((count of paths) is 0) then
		return
	end if
	
	tell application "Adobe Illustrator"
		activate
		do javascript file scriptPath with arguments paths
	end tell
	
end open

 

 script.jsx

if (arguments.length > 0) {
  var filePaths = [];
  for (var i = 0; i < arguments.length; i++) {
    filePaths.push(new File(arguments[i]));
  }
  alert(filePaths.length + " paths provided\n" + filePaths.join("\n"));
} else {
  alert("No args provided.");
}

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Apr 24, 2024 Apr 24, 2024

Copy link to clipboard

Copied

Thank you @jduncan! The .jsx code workked brilliantly. BTW: The reason I had the .jsx asking for the files if nothing was dropped on the AppleScript droplet is because that way I can use the same .jsx code whether it's run directly from Illustrator or embedded in the Applescript droplet wrapper.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Apr 24, 2024 Apr 24, 2024

Copy link to clipboard

Copied

@Chris.S, yeah that is what I figured... It's a simple fix, just update the `on run` block in the AppleScript to the code below, and then the else statement in the jsx script will be where you add you JSX choose file code.

 

on run
	tell application "Adobe Illustrator"
		activate
		do javascript file scriptPath
	end tell
end run

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Apr 25, 2024 Apr 25, 2024

Copy link to clipboard

Copied

@jduncan, thank you. A few observations:

  1. My AS, with your JSX from Automator... worked, but had problems with the second path when more than one file was dropped onto it. Assuming that was because of how my AS was capturing that array.
  2.  Your AS from Automator App. Automator didn't seem to like it. Assuming because the Run Applescript command wasn't liking the on open droppedItems.
  3.  Your AS from ScriptEditor App. This works (with on run moved to the end), and I like it better than Automator because I don't have to replace my .jsx everytime I edit it. However, I can't seem to get my scriptPath correct. It works when I run it from the desktop (commented out below), but when I try to use it from the app's Contents/Resources/Scripts folder, it doesn't like it. Any thoughts how to get that to work properly? That part actually works from within Automator as it's formatted. If I could get it to work from ScriptEditor, that woudl be ideal:

 

property theExtensionsToProcess : {"jpg", "png", "tif", "psd", "psb", "heic"}
property scriptPath : POSIX path of (path to me) & "Contents/Resources/Scripts/script.jsx"
-- property scriptPath : "~/Desktop/script.jsx"

on open droppedItems
	set paths to {}
	
	repeat with a from 1 to length of droppedItems
		set theCurrentItem to item a of droppedItems
		set currentFilePath to POSIX path of theCurrentItem
		set theExtension to (name extension of (info for currentFilePath)) as string
		
		if (theExtensionsToProcess contains theExtension) then
			set end of paths to currentFilePath
		end if
	end repeat
	
	-- check if no valid paths were found (could add an alert)
	if ((count of paths) is 0) then
		return
	end if
	
	tell application "Adobe Illustrator"
		activate
		do javascript file scriptPath with arguments paths
	end tell
	
end open

on run
	tell application "Adobe Illustrator"
		activate
		do javascript file scriptPath
	end tell
end run
​

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Apr 25, 2024 Apr 25, 2024

Copy link to clipboard

Copied

@Chris.S, sorry I completely missed the mention of Automator in your original post...

 

So, it seems when running a droplet the getting the `path to me` actually gets the path to the Script Editor app. to fix this, I just use Finder to get the `path to me` which works. As you can see in the script below, I cleaned up a few things and renamed a few variables but it is mostly the same. The really only update is grabbing the `dropletPath` and adding that with the `scriptPath` before using the `do javascript method`.

 

Also, I'm not sure why you had to move the `on run` method to the end but whatever works...

 

And to answer #1 from your response, if I had to guess the paths were being passed in from Automator as one string (not an array like straight AppleScript) and that is probably why it wasn't seeing all paths...

 

Let me know if this works the way you want.

 

property acceptedExtentions : {"jpg", "png", "tif", "psd", "psb", "heic"}
property scriptPath : "Contents/Resources/Scripts/script.jsx"

-- do this when the droplet is double-clicked
on run
	runScript({})
end run

-- do this when files are dropped on the droplet
on open droppedItems
	set paths to {}
	
	-- get path to each dropped file
	repeat with a from 1 to length of droppedItems
		set theCurrentItem to item a of droppedItems
		set currentFilePath to POSIX path of theCurrentItem
		set theExtension to (name extension of (info for currentFilePath)) as string
		-- add path to paths array if extension an accepted type
		if (acceptedExtentions contains theExtension) then
			set end of paths to currentFilePath
		end if
	end repeat
	
	-- check if no valid paths were found (could add an alert)
	if ((count of paths) is 0) then
		return
	end if
	
	runScript(paths)
	
end open

-- run the script from within Ai with the supplied arguments
on runScript(args)
	tell application "Finder"
		set dropletPath to POSIX path of (path to me)
	end tell
	tell application "Adobe Illustrator"
		activate
		do javascript file (dropletPath & scriptPath) with arguments args
	end tell
end runScript

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Apr 25, 2024 Apr 25, 2024

Copy link to clipboard

Copied

Amazing! Thank you again for your help @jduncan. This did the trick.

 

BTW, the reason I moved "on run" below "on open" originally was because it would go straight to "on run" and not process the "on open" when put in Automator. I thought it was because it was doing on run first and that moving it below on open it would do the on open first. I guess I was wrong and that it was likely more to do with calling it from Automator.

This approach is way better than Automator. Thank you again!

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
May 02, 2024 May 02, 2024

Copy link to clipboard

Copied

@jduncan... any tips how to get droppedItems to report all of the files when there are multiple images with very long names (~50 characters)? It's failing/acting sporadically when I get about 4 or more of those guys in my list of dropped items, but no issues with lots of files with shorter names.

 

When running the simplified code below to troubleshoot, I noticed the count of droppedItems wasn't being reported correctly as I got about 5 of the long names/paths into the list. After further troubleshooting I believe it's due to the filename lengths and what droppedItems can store in one variable. Sometimes it will split droppedItems in 2 (as if 1 file was dropped on it, and then 3 more, running it twice). It doesn't seem to have a problem with many shorter filenames.

 

Simplified Applescript droplet:

 

 

on open droppedItems
	set paths to {}
	display alert "droppedItems:" message ((count of droppedItems) as text)
end open

 

 

 

Comparable JavaScript droplet (saved from Automator) with the same issue:

 

 

function run(input, parameters) {
    var itemCount = input.length;
    var app = Application.currentApplication();
    app.includeStandardAdditions = true;
    app.displayAlert("Number of dropped items:", {message: itemCount});
}

 

 

 

System: 2023 16" MPB M3 Max, 128GB, Sonoma 14.4.1

Tried restarting and running Disk Utility/First Aid.

 

On another note, I also had to add a delay if Illustrator wasn't already active from the original code as that was causing some problems for me, but I got that worked out I believe.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
May 03, 2024 May 03, 2024

Copy link to clipboard

Copied

@Chris.S, this was a head scratcher... I tried with the list of files below and all seems okay. Obviously something is going wrong within AppleScript, and if the files were downloaded it seems that could be the issue (read here). When I added a single download file to the list below, it wasn't counted correctly. So, I ran `xattr -rc *` (from the terminal) within the directory containing all of the files and then it was counted correctly. Let me know if this helps?

 

here_is_a_really_long_name_that_will_probably_cause_some_problems_1.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_2.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_3.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_4.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_5.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_6.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_7.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_8.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_9.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_10.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_11.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_12.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_13.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_14.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_15.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_16.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_17.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_18.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_19.txt
here_is_a_really_long_name_that_will_probably_cause_some_problems_20.txt
little_longer_than_short_name_1.txt
little_longer_than_short_name_2.txt
little_longer_than_short_name_3.txt
little_longer_than_short_name_4.txt
little_longer_than_short_name_5.txt
little_longer_than_short_name_6.txt
little_longer_than_short_name_7.txt
little_longer_than_short_name_8.txt
little_longer_than_short_name_9.txt
little_longer_than_short_name_10.txt
little_longer_than_short_name_11.txt
little_longer_than_short_name_12.txt
little_longer_than_short_name_13.txt
little_longer_than_short_name_14.txt
little_longer_than_short_name_15.txt
little_longer_than_short_name_16.txt
little_longer_than_short_name_17.txt
little_longer_than_short_name_18.txt
little_longer_than_short_name_19.txt
little_longer_than_short_name_20.txt
short_name_1.txt
short_name_2.txt
short_name_3.txt
short_name_4.txt
short_name_5.txt
short_name_6.txt
short_name_7.txt
short_name_8.txt
short_name_9.txt
short_name_10.txt
short_name_11.txt
short_name_12.txt
short_name_13.txt
short_name_14.txt
short_name_15.txt
short_name_16.txt
short_name_17.txt
short_name_18.txt
short_name_19.txt
short_name_20.txt

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
May 03, 2024 May 03, 2024

Copy link to clipboard

Copied

Thank you @jduncan. I guess the length of the filenames was a red herring... I renamed them to A, B, C, etc. and still had the issue. These were transferred/downloaded to Box, so the culprit must lie there. Seems it's only some images though as it's fine for others that came from Box. Will play around with them and the proposed solution when I have more time next week. Funny, I had come across the link you shared but didn't think it applied here as I had some other files I was testing that also came from Box with shorter filenames which didn't have the issue which led me down the wrong "path"... go figure!

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
May 06, 2024 May 06, 2024

Copy link to clipboard

Copied

@jduncan , it definitely was the quarantining that was causing the odd behavior. Thank you for the tip! Below is the code I ended up with, using Stay Open when saving the droplet...

 

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
property filesToOpen : {}
property acceptedExtentions : {"jpg", "png", "tif", "psd", "psb", "heic"}
property scriptPath : "Contents/Resources/Scripts/script.jsx"
property paths : {}

on run
	runScript({})
	tell me to quit
end run

-- do this when files are dropped on the droplet
on open droppedItems
	set my filesToOpen to my filesToOpen & droppedItems
	-- cancel any pending performSelector: requests
	current application's NSObject's cancelPreviousPerformRequestsWithTarget:me
	-- handle files after a short delay in case further events are received
	tell me to performSelector:"doOpen" withObject:(missing value) afterDelay:0.5
end open

on doOpen()
	copy my filesToOpen to droppedItems
	set my filesToOpen to {} -- reset for next time
	-- get path to each dropped file
	repeat with a from 1 to length of droppedItems
		set theCurrentItem to item a of droppedItems
		set currentFilePath to POSIX path of theCurrentItem
		set theExtension to (name extension of (info for currentFilePath)) as string
		-- add path to paths array if extension an accepted type
		if (acceptedExtentions contains theExtension) then
			set end of paths to currentFilePath
		end if
	end repeat
	-- check if no valid paths were found 
	if ((count of paths) is 0) then
		return
	end if
	runScript(paths)
end doOpen

-- run the script from within Ai with the supplied arguments
on runScript(args)
	tell application "Finder"
		set dropletPath to POSIX path of (path to me)
	end tell
	
	-- Construct full path to the script
	set scriptFullPath to dropletPath & scriptPath
	
	
	-- Check if Illustrator is running
	tell application "System Events"
		set illustratorRunning to (exists process "Adobe Illustrator")
	end tell
	
	if illustratorRunning then
		-- Illustrator is open, execute the JavaScript directly
		tell application "Adobe Illustrator"
			activate
			do javascript file scriptFullPath with arguments args
		end tell
	else
		-- Illustrator is not open, launch it
		tell application "Adobe Illustrator" to activate
		-- Wait a moment for Illustrator to open
		delay 1
		
		-- Check if Illustrator opened successfully
		tell application "System Events"
			set illustratorRunning to (exists process "Adobe Illustrator")
		end tell
		
		if illustratorRunning then
			-- Illustrator is now open. Run the JavaScript
			tell application "Adobe Illustrator"
				do javascript file scriptFullPath with arguments args
			end tell
		else
			display alert "Error" message "Open Adobe Illustrator and try again."
		end if
	end if
	tell me to quit
end runScript

on quit
	continue quit
end quit

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
May 06, 2024 May 06, 2024

Copy link to clipboard

Copied

LATEST

@Chris.S, this is great info. I'm glad you found out the best way to process those pesky quarantied files. I had planned to look into this week for my own knowledge but it seems you have it working. Thanks for sharing!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines