Skip to main content
orib7317974
Known Participant
July 20, 2023
Answered

How do I make a script both executable on its own an serve as a library for other scripts?

  • July 20, 2023
  • 5 replies
  • 1441 views

I'd like to script1 to include script2 so that it can use its code.

I'd also like script2 to have a main function and call it, but only if script2 is run directly from InDesign.

How do I do that?

(I'm using JavaScript.)

This topic has been closed for replies.
Correct answer m1b

Hi @orib7317974, the normal way would be to save a library file that does not execute anything—just use it to define objects and functions etc. And then make a script file that only has 2 lines: 1. //@include 'library.js' and 2. a single function call main(), or MyLibrary.myFunction() sort of thing. What you are asking is actually an awkward way to do it.

- Mark

5 replies

rob day
Community Expert
Community Expert
July 21, 2023

Hi @orib7317974 , Also this resource might help:

 

https://extendscript.docsforadobe.dev/

 

The section on includes:

https://extendscript.docsforadobe.dev/extendscript-tools-features/preprocessor-directives.html

.jsxinc is suggested for the include file, but as others have noted .jsx also works.

 

Any functions, variables, or constants you write in the include file are effectively public—you can call them from the script that includes the code. So this file has an exposed function—gerWorldString(), constant—MAGIC_NUMBER, and variable—vNum:

 

 

/**
* External function example saved with .jsxinc in the same directory as script 
* @ param s string
* @ return string + parameter 
*/

function getWorldString(s){
  return "From Hello World: " + s
}

/**
* A read only constant
*/
const MAGIC_NUMBER = 1.045

/**
* A read write variable
*/
var vNum = 5

 

 

 

I named the file HelloWorld.jsxinc and included it with a script in the same directory. From that script I can call the public functions, constants, and variables:

 

 

#include "HelloWorld.jsxinc"


$.writeln(getWorldString("Hi There!"))
//From Hello World: Hi There!

$.writeln(MAGIC_NUMBER)
//retuns 1.045

$.writeln(vNum)
//returns 5

vNum = 10;
$.writeln(vNum);
//returns 10

 

 

orib7317974
Known Participant
July 23, 2023

@rob day , @Laubender , thank you for this additional information!

Community Expert
July 20, 2023

Another note on the syntax Mark used with the include command:

 

If you search the forum you'll find most of the (older) code snippets using include with this syntax:

#include

Why, because most of the old code was written with and tested with the ESTK (ExtendScript Toolkit App) and also, at least I think so, because //@include was not documented for a long time.

 

Both versions of the syntax will work when you run the script from the Scripts > User panel or with the old ExtendScript Toolkit App ( still installable and usable on Windows 10 or 11 ) . However, when running the script with the Adobe ExtendScript debugger from VSCode you have to use this syntax:

//@include

In this case the // does not state the beginning of a comment. The directive @include behind the // is executed.

So be careful when writing comments. Or use this for commenting your code:

 

/*

//@include is a powerful way to access code from a different script file sharing the same script language.

*/

 

Regards,
Uwe Laubender
( Adobe Community Expert )

Community Expert
July 23, 2023

I have seen #include work with Adobe ExtendScript debugger for VSCode. The debugging of included file also works for me. Am I missing something here? I speak this about my experience on a MAC.

-Manan

-Manan
Community Expert
July 24, 2023

@Manan Joshi said: "I have seen #include work with Adobe ExtendScript debugger for VSCode. The debugging of included file also works for me. Am I missing something here? I speak this about my experience on a MAC."

 

Ah! Thanks for this observation. Have to test this both on Mac and Windows again.

In regrads to #include vs //@include I have to admit that I followed suggestions here in the forum. So I could be wrong that #include would not work with Adobe ExtendScript debugger for VSCode.

 

Thanks,
Uwe Laubender
( Adobe Community Expert )

Community Expert
July 20, 2023

Hi @orib7317974 ,

note, that you can also use app.doScript().

That would be especially useful if you are in a situation where you like to use a mix of scripting languages.

Example: when on macOS you could include the executable code of an AppleScript file in your ExtendScript code.

 

See into ExtendScript DOM documentation compiled by Gregor Fellenz:

https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Application.html#d1e42253__d1e45802

app.doScript( yourAppleScriptFile , ScriptLanguage.APPLESCRIPT_LANGUAGE );

 

With the current version of InDesign 2023 including a UXP Script should also be possible with app.doScript(). Did not test it yet:

app.doScript( yourUXPScriptFile , ScriptLanguage.UXPSCRIPT );

 

Or you have no script file at all, but the code of an AppleScript or an UXP Script at hand and provide it as string for the first argument of the doScript() method. Search the forum, there are many examples with AppleScript running from a doScript() method...

 

Regards,
Uwe Laubender
( Adobe Community Expert )

orib7317974
Known Participant
July 20, 2023

This is interesting, thank you for pointing that out!

m1b
Community Expert
m1bCommunity ExpertCorrect answer
Community Expert
July 20, 2023

Hi @orib7317974, the normal way would be to save a library file that does not execute anything—just use it to define objects and functions etc. And then make a script file that only has 2 lines: 1. //@include 'library.js' and 2. a single function call main(), or MyLibrary.myFunction() sort of thing. What you are asking is actually an awkward way to do it.

- Mark

orib7317974
Known Participant
July 20, 2023

Thanks for your reply, @m1b.

Maybe I'll just do it your way.

orib7317974
Known Participant
July 20, 2023

Oh, I think I found the answer:

I can use app.activeScript.displayName.
orib7317974
Known Participant
July 20, 2023

Ok, but is there some global variable available to a script holding its file name (so that I can compare it against app.activeScript.displayName in a way that doesn't require updating the code in case I update the file name of the script)?