A way to bundle a group of functions in SugarCube into library/macro?

Twine Version: 2.10.0
Sugarcube 2.37.3

Say I have a dozen functions on the setup object. Is there a way/method to consolidate them into a … for lack of a better word, a library?

setup.myfunct1 = function (inputString){
//code here
};

setup.myfunc2 = function (inputString){
//code here
}

Would a macro work? If so, can anyone help me understand how I would — for instance — wrap an addition and a subtraction function in that way?

I have read about macros in the official documentation and just not wrapping my head around them yet.

The boring answer is :

Depend on what your functions are doing.

pretty much exclusively string manipulation functions:

mystring.replace() using regex

and

mystring.replaceAll()

JavaScript supports a number of techniques for bundling related functions / methods together, some of which are directly supported by Twine & the SugarCube story format.

SugarCube’s uses its own Private Scoped contexts to execute its JavaScript based runtime engine and any JavaScript that is included within the Story HTML file. One Private Scoped context can not access the contents of another such context, however those created by SugarCube itself can access the internals of the runtime engine, which is how you’re able to use the methods you’re defining on the special setup variable.

A Private Scoped context can also access things outside its own scope if that thing has been defined in a “global” like way. Three of the main techniques used to define something in a “global” like way are:

1: Defining that thing directly on the web-browser’s own window interface.

This is how some third-party JavaScript libraries make their Methods / Classes / Modules available. However, window is also where the web-browser developers define methods & the like, so there could be potential issues if you override something they define or they override something you defined.

window.doit = function (){
    /* code here */
};

Things defined this way can be called directly from code being run by SugarCube…

/* From a Passage */
<<run doit()>>

/* From a SugarCube Event handler */
$(document).one(':passagedisplay', function (ev) {
	doit();
});

2: Defining that thing on a Namespace, that is defined on the window interface.

The name of the Namespace should unique to your project, so it doesn’t conflict with any being used by a third-party library you might want to include.

/* an example using my own personal Namespace */
window.GE = window.GE || {};

GE.doit = function (){
    /* code here */
};

Things defined this way are called similar to how things defined on setup are…

/* From a Passage */
<<run GE.doit()>>

/* From a SugarCube Event handler */
$(document).one(':passagedisplay', function (ev) {
	GE.doit();
});

3: Defining things in a JavaScript Class, that is defined on the window interface.

Again the name being used needs to be something that isn’t likely to be taken by the web-browser itself or by any third-party library you intend to use.

If you intend to use JavaScript classes then you should read the Non-generic object types (classes) guide in the SugarCube documentation, especially if you intend to store instances of those classes in Story variables.