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

Convert InDesign Applescript to javascript

Explorer ,
Mar 25, 2020 Mar 25, 2020

Hi Everyone,

At a previous job of mine, a colleague had developed and shared an awesome script that cleans all the whitespace out of InDesign layouts (Multiple Space to Single Space, Remove Leading Whitespace, Remove Trailing Whitespace, Multiple Return to Single Return). This thing works like magic.

 

Every job I've had since getting this script were in Mac environments. The only thing I had to do to make it work on later versions of InDesign was to edit "tell application" to the updated app. However, right now I'm working remotely and I've been forced to use my PC to get work done and it would be really helpful if I had a javascript version of it.

 

Of course you guys can use this and/or pass it around so long as you credit my colleague. His info is in the prologue of the script.

 

Warning: this script does not play well with designers who do not lay their text out properly. If you use double returns and multiple spaces or tabs in your layout instead of proper paragraph styles with "space after", this script will wreck the layout.

 

-----------------------------------------------------------------------------------
--
-- Script Name: Clean Text White Space.scpt
-- Version: 1.0
-- Author: Brendan McBryan
-- Contact: brendan.mcbryan@gmail.com
-- Date: March 3, 2011
-- Application: Adobe InDesign CS4
--
-- Description: This AppleScript is designed to be run from the scripts panel in InDesign CS4. It will run the most common Find & Change actions relating to cleaning up white space in Text. 
--
--The Actions included are: Multiple Space to Single Space, Remove Leading Whitespace, Remove Trailing Whitespace, Multiple Return to Single Return.
--
-----------------------------------------------------------------------------------
tell application "Adobe InDesign CC 2018"
	
	
	--MULTIPLE SPACE TO SINGLE SPACE
	--Clear the find/change preferences.
	set find grep preferences to nothing
	set change grep preferences to nothing
	
	--Load Find/Change variables for Multiple Space to Single Space
	set varFind to "[~m~>" & "~f~|~S~s~<~/~.~3~4~% ]{2,}" as string
	set varChange to "\\s" as string
	set include hidden layers of find change grep options to true
	set the find what of find grep preferences to varFind
	set the change to of change grep preferences to varChange
	
	-- Execute Multiple Space to Single Space
	tell active document
		set varFoundMultipleSpace to change grep
	end tell
	
	--REMOVE LEADEING WHITESPACE	
	--Clear the find/change preferences.
	set find grep preferences to nothing
	set change grep preferences to nothing
	
	--Load Find/Change variables for Remove Leading Whitespace
	set varFind to "^ " as string
	set varChange to "" as string
	set include hidden layers of find change grep options to true
	set the find what of find grep preferences to varFind
	set the change to of change grep preferences to varChange
	
	-- Execute Multiple Space to Remove Leading Whitespace
	tell active document
		set varFoundLeadingSpace to change grep
	end tell
	--MULTIPLE RETURN TO SINGLE RETURN
	--Clear the find/change preferences.
	set find grep preferences to nothing
	set change grep preferences to nothing
	
	--Load Find/Change variables for Multiple Return to Single Return
	set varFind to "~b~b+" as string
	set varChange to "\\r" as string
	set include hidden layers of find change grep options to true
	set the find what of find grep preferences to varFind
	set the change to of change grep preferences to varChange
	
	-- Execute Multiple Return to Single Return
	tell active document
		set varFoundMultipleReturn to change grep
	end tell
	
	--REMOVE TRAILING WHITESPACE
	--Clear the find/change preferences.
	set find grep preferences to nothing
	set change grep preferences to nothing
	
	--Load Find/Change variables for Remove Trailing Whitespace
	set varFind to "\\s+$" as string
	set varChange to "" as string
	set include hidden layers of find change grep options to true
	set the find what of find grep preferences to varFind
	set the change to of change grep preferences to varChange
	
	-- Execute Remove Trailing Whitespace
	tell active document
		set varFoundTrailingSpace to change grep
	end tell
	--Display Change Count	
	set varAnswer to the button returned of (display dialog ¬
		("Changed " & (count varFoundMultipleSpace) & " Multiple Spaces to Single Spaces" & return & ¬
			"Removed " & (count varFoundLeadingSpace) & " instances of Leading Space" & return & ¬
			"Changed " & (count varFoundMultipleReturn) & " Multiple Returns to Single Returns" & return & ¬
			"Removed " & (count varFoundTrailingSpace) & " instances of Trailing Space") ¬
			as string ¬
		buttons {"Undo", "Thanks!"} ¬
		with title "Success!")
	
	--Undo if requested
	if varAnswer = "Undo" then
		tell application "System Events"
			repeat 4 times
				keystroke "z" using command down
			end repeat
		end tell
	end if
	
end tell

 This script does a grep find and change for several things, prompts you with how many things it changed, and gives you the option to undo what it did.

 

Please let me know if anyone can help with this. Thanks!!

TOPICS
Scripting , Type
1.9K
Translate
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 1 Correct answer

Community Expert , Mar 25, 2020 Mar 25, 2020

Here's my go-to findchange. You'd put the existing strings from your applescript into the multidimensional "fcs" array. 

 

 

 

 

var myChangeGrep = function( findPrefs, changePrefs, story ) {

		for ( var i in findPrefs ) {
			app.findGrepPreferences[i] = findPrefs[i];
		}
		for ( var j in changePrefs ) {
			app.changeGrepPreferences[j] = changePrefs[j];
		}
		story.changeGrep( true );

		app.findGrepPreferences = NothingEnum.NOTHING;
		app.changeGrepPreferences = NothingEnum.NOTHING;
	};

var main =
...
Translate
Community Expert ,
Mar 25, 2020 Mar 25, 2020

Here's my go-to findchange. You'd put the existing strings from your applescript into the multidimensional "fcs" array. 

 

 

 

 

var myChangeGrep = function( findPrefs, changePrefs, story ) {

		for ( var i in findPrefs ) {
			app.findGrepPreferences[i] = findPrefs[i];
		}
		for ( var j in changePrefs ) {
			app.changeGrepPreferences[j] = changePrefs[j];
		}
		story.changeGrep( true );

		app.findGrepPreferences = NothingEnum.NOTHING;
		app.changeGrepPreferences = NothingEnum.NOTHING;
	};

var main = function() {
    var doc = app.activeDocument;
    var fcs = [
        ["findstring", "changestring"],
        ["findstring", "changestring"],
        //more arrays here
    ];

    app.findGrepPreferences = NothingEnum.NOTHING;
    app.changeGrepPreferences = NothingEnum.NOTHING;

    for (var i = 0; i < fcs.length; i++) {
         myChangeGrep({findWhat:fcs[i][0]}, {changeTo:fcs[i][1]}, doc); 
    }
}



main();

 

 

 

Translate
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
Explorer ,
Mar 25, 2020 Mar 25, 2020

That sounds promising. Unfortunately, I'm not much of a coder at all. Could you expand on your explanation a bit?

 

Thanks!

Translate
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
Community Expert ,
Mar 25, 2020 Mar 25, 2020

Everywhere where you have this expression:

 

 

set varFind to "\\s+$" as string
set varChange to "" as string

 

 

Fill in the "findstring" and "changestring" in the fcs array in my example: 

 

fcs = [

    ["\\s+$", ""],

    ["[~m~>" & "~f~|~S~s~<~/~.~3~4~% ]{2,}",  "\\s"],

    and so on

];

 

Translate
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
Explorer ,
Mar 25, 2020 Mar 25, 2020

Ok I tried making the followinng into a .jsx file:

 

var myChangeGrep = function( findPrefs, changePrefs, story ) {

		for ( var i in findPrefs ) {
			app.findGrepPreferences[i] = findPrefs[i];
		}
		for ( var j in changePrefs ) {
			app.changeGrepPreferences[j] = changePrefs[j];
		}
		story.changeGrep( true );

		app.findGrepPreferences = NothingEnum.NOTHING;
		app.changeGrepPreferences = NothingEnum.NOTHING;
	};

var main = function() {
    var doc = app.activeDocument;
    var fcs = [
        ["[~m~>" & "~f~|~S~s~<~/~.~3~4~% ]{2,}", "\\s"],
        ["^ ", ""],
        ["~b~b+", "\\r"],
        ["\\s+$", ""],
    ];

    app.findGrepPreferences = NothingEnum.NOTHING;
    app.changeGrepPreferences = NothingEnum.NOTHING;

    for (var i = 0; i < fcs.length; i++) {
         myChangeGrep({findWhat:fcs[i][0]}, {changeTo:fcs[i][1]}, doc); 
    }
}



main();

 

 

and i got the following error:

error.PNGexpand image

 

PS: I'm using InDesign CS6 right now. Maybe the FCS string is new code that this version of ID doesn't understand.

 

Also, is this script supposed to work on selected text or does it do the whole document? Either way the one I posted does the whole document and it would be great if we could get this version to do it that way as well.

 

Thanks!!!

Translate
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
Community Expert ,
Mar 25, 2020 Mar 25, 2020

This would do it on the whole doc. I think you need to escape your quote mark in the first array, or break it up into two arrays. Not exactly sure what that expression is looking for. 

 

["[~m~>" & "~f~|~S~s~<~/~.~3~4~% ]{2,}", "\\s"],

 

Translate
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
Explorer ,
Mar 26, 2020 Mar 26, 2020

Ok its working! I had to troubleshoot some weird things the script was doing but now I think its working.

var myChangeGrep = function( findPrefs, changePrefs, story ) {

		for ( var i in findPrefs ) {
			app.findGrepPreferences[i] = findPrefs[i];
		}
		for ( var j in changePrefs ) {
			app.changeGrepPreferences[j] = changePrefs[j];
		}
		story.changeGrep( true );

		app.findGrepPreferences = NothingEnum.NOTHING;
		app.changeGrepPreferences = NothingEnum.NOTHING;
	};

var main = function() {
    var doc = app.activeDocument;
    var fcs = [
        ["[~m~>~f~|~S~s~<~/~.~3~4~% ]{2,}", "\\s"],
        ["^ ", ""],
        ["~b~b+", "\r"],
        ["\\s+$", ""],
    ];

    app.findGrepPreferences = NothingEnum.NOTHING;
    app.changeGrepPreferences = NothingEnum.NOTHING;

    for (var i = 0; i < fcs.length; i++) {
         myChangeGrep({findWhat:fcs[i][0]}, {changeTo:fcs[i][1]}, doc); 
    }
}



main();

 

That first string that was giving us trouble was searching for multiple spaces. Luckily, InDesign had a preset GREP search that looks for the multiple spaces that worked correctly so I swapped that one in.

 

Also for some reason the trailing space part of the script was removing multiple trailing spaces but leaving 1 trailing space. For some reason, having

\\s+$

instead of

\s+$

in the find part of the string made it work properly even though the replace part of the string was just

""

 

Wow this is going great!

 

So the Applescript version has a dialogue box that opens after running the script. It display how many instances of each string it found. It also has an "undo" button and a "Thanks!" button. Pessing the undo button undoes the script by pressing cmd-z 4 times (on PC I guess it would have to be ctrl-z). Pressing "thanks" just closes the dialog box. So how would we go about doing this for the javascript version?

Translate
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
Community Expert ,
Mar 26, 2020 Mar 26, 2020

Outside my paygrade for free forum help! If you want to undo, you can hit undo four times. 

Translate
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
Explorer ,
Mar 26, 2020 Mar 26, 2020

Fair enough. You get all the stars today. Thanks for your help!!

Translate
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
Community Expert ,
Mar 26, 2020 Mar 26, 2020

I use an Applescript with a handler so the code is easier to read and edit, and the searches can be set as single lines:

 

tell application "Adobe InDesign 2020"
	activate
	--replaces multiple tabs with single tab
	my GrepSearch("\\t+", "\\t")
	--removes any white space at the start of a paragraph including multiple returns
	my GrepSearch("^\\s*", "")
	--replaces multiple spaces with one space
	my GrepSearch("\\p{zs}{2,}", "\\s")
	--replaces soft return with a hard return
	my GrepSearch("\\s?\\n", "\\r")
	--replaces non breaking spaces with spaces
	my GrepSearch("~s|~S", "\\s")
end tell

on GrepSearch(f, c)
	tell application "Adobe InDesign 2020"
		set find grep preferences to nothing
		set change grep preferences to nothing
		set find what of find grep preferences to f
		set change to of change grep preferences to c
		change grep
	end tell
end GrepSearch

 

Here’s the equivalent in JS—both search the entire document:

 

//replaces multiple tabs with single tab
grepSearch("\t+", "\t");
//removes any white space at the start of a paragraph including multiple returns
grepSearch("^\s*", "")
//replaces multiple spaces with one space
grepSearch("\p{zs}{2,}", "\s")
//replaces soft return with a hard return
grepSearch("\s?\n", "\r")
//replaces non breaking spaces with spaces
grepSearch("~s|~S", "\s")


function grepSearch(f,c){
    app.findGrepPreferences.findWhat=NothingEnum.NOTHING
    app.changeGrepPreferences.changeTo=NothingEnum.NOTHING
    app.findGrepPreferences.findWhat = f;
    app.changeGrepPreferences.changeTo = c;
    app.activeDocument.changeGrep( true )
}
Translate
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
Explorer ,
Mar 26, 2020 Mar 26, 2020

Thanks for posting! I'm not sure those search terms would be helpful in my workflow. The script I use is primarily to clean up text that I'm bringing in from Word docs from other people. This script cleans up all the garbage that comes from bad practices that people who are accustomed to using Word pick up and also people just not being careful. (Pasting in from word has it own annoyances too, like when you paste in a bulleted or numbered list, and now I can build a script to fix that).

 

I'm just curious why you would want to replace soft returns with hard returns and non breaking spaces with spaces. I need to use those all the time.

Translate
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
Explorer ,
Mar 26, 2020 Mar 26, 2020

Now it's my turn to give back a bit.

 

Here are scripts I just made that would help clean up your text brought in from word. Of course the correct way to have bulleted and numbered lists is with a proper InDesign paragraph style. But pasting lists in from Word comes with extra junk. So these scripts will clean that up.

 

Bulleted List script:

 

var myChangeGrep = function( findPrefs, changePrefs, story ) {

		for ( var i in findPrefs ) {
			app.findGrepPreferences[i] = findPrefs[i];
		}
		for ( var j in changePrefs ) {
			app.changeGrepPreferences[j] = changePrefs[j];
		}
		story.changeGrep( true );

		app.findGrepPreferences = NothingEnum.NOTHING;
		app.changeGrepPreferences = NothingEnum.NOTHING;
	};

var main = function() {
    var doc = app.activeDocument;
    var fcs = [
        ["~8\t", ""],
    ];

    app.findGrepPreferences = NothingEnum.NOTHING;
    app.changeGrepPreferences = NothingEnum.NOTHING;

    for (var i = 0; i < fcs.length; i++) {
         myChangeGrep({findWhat:fcs[i][0]}, {changeTo:fcs[i][1]}, doc); 
    }
}



main();

 

 

Numbered list script:

 

var myChangeGrep = function( findPrefs, changePrefs, story ) {

		for ( var i in findPrefs ) {
			app.findGrepPreferences[i] = findPrefs[i];
		}
		for ( var j in changePrefs ) {
			app.changeGrepPreferences[j] = changePrefs[j];
		}
		story.changeGrep( true );

		app.findGrepPreferences = NothingEnum.NOTHING;
		app.changeGrepPreferences = NothingEnum.NOTHING;
	};

var main = function() {
    var doc = app.activeDocument;
    var fcs = [
        ["\\d+\.\t", ""],
    ];

    app.findGrepPreferences = NothingEnum.NOTHING;
    app.changeGrepPreferences = NothingEnum.NOTHING;

    for (var i = 0; i < fcs.length; i++) {
         myChangeGrep({findWhat:fcs[i][0]}, {changeTo:fcs[i][1]}, doc); 
    }
}



main();

 

 

I hope this helps someone!

Translate
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
Community Expert ,
Mar 26, 2020 Mar 26, 2020
LATEST

For example both your searches run with a 10 line script:

 

 

grepSearch("~8\t", "");
grepSearch("\\d+\.\t", "")

function grepSearch(f,c){
    app.findGrepPreferences.findWhat=NothingEnum.NOTHING
    app.changeGrepPreferences.changeTo=NothingEnum.NOTHING
    app.findGrepPreferences.findWhat = f;
    app.changeGrepPreferences.changeTo = c;
    app.activeDocument.changeGrep( true )
}

 

I'm just curious why you would want to replace soft returns with hard returns and non breaking spaces with spaces. I need to use those all the time.

 

If the text is from an outside source usually I’m trying to completely strip the formatting from the Word doc. The author’s soft return or non breaking space might not be needed when the text is reformatted in InDesign. I certainly don’t want tabbed indents or returns as space between paragraphs

 

Translate
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
Community Expert ,
Mar 26, 2020 Mar 26, 2020

You can edit the function calls to be anything you want. A function or Applescript handler makes the code more effiecient—my 12 lines of code is running 5 grep searches.

To customize for your needs simply add or edit the function calls as needed

 

grepSearch("your grep search string", "your grep change string");

 

Note that in AppleScript you have to escape backslashes with a backslash

 

 

my GrepSearch("\\t+", "\\t")

--not my GrepSearch("\t+", "\t")

 

 

 

 

 

Translate
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