Skip to content

Commit 76dd547

Browse files
kinowmr-c
andauthored
Add documentation about InlineJavascriptRequirement expressionLib (#242)
* Link to #$include in the note * 'Important' box wasn't terminated properly Co-authored-by: Michael R. Crusoe <[email protected]>
1 parent 611c806 commit 76dd547

File tree

5 files changed

+183
-3
lines changed

5 files changed

+183
-3
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Capitalize each word passed. Will split the text by spaces.
3+
* For instance, given "hello world", it returns "Hello World".
4+
*
5+
* @param {String} message - The input message.
6+
* @return {String} the message with each word with its initial letter capitalized.
7+
*/
8+
function capitalizeWords (message) {
9+
if (message === undefined || message === null || typeof message !== 'string' || message.trim().length === 0) {
10+
return '';
11+
}
12+
return message
13+
.split(' ')
14+
.map(function (token) {
15+
return token.charAt(0).toUpperCase() + token.slice(1);
16+
})
17+
.join(' ');
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
cwlVersion: v1.2
2+
class: CommandLineTool
3+
requirements:
4+
- class: InlineJavascriptRequirement
5+
expressionLib:
6+
- { $include: custom-functions.js }
7+
8+
baseCommand: echo
9+
10+
inputs:
11+
message:
12+
type: string
13+
14+
arguments: [$( capitalizeWords(inputs.message) )]
15+
16+
outputs: []
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
cwlVersion: v1.2
2+
class: CommandLineTool
3+
requirements:
4+
- class: InlineJavascriptRequirement
5+
expressionLib:
6+
- |
7+
/**
8+
* Capitalize each word passed. Will split the text by spaces.
9+
* For instance, given "hello world", it returns "Hello World".
10+
*
11+
* @param {String} message - The input message.
12+
* @return {String} the message with each word with its initial letter capitalized.
13+
*/
14+
function capitalizeWords (message) {
15+
if (message === undefined || message === null || typeof message !== 'string' || message.trim().length === 0) {
16+
return '';
17+
}
18+
return message
19+
.split(' ')
20+
.map(function (token) {
21+
return token.charAt(0).toUpperCase() + token.slice(1);
22+
})
23+
.join(' ');
24+
}
25+
26+
baseCommand: echo
27+
28+
inputs:
29+
message:
30+
type: string
31+
32+
arguments: [$( capitalizeWords(inputs.message) )]
33+
34+
outputs: []
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
cwlVersion: v1.2
2+
class: CommandLineTool
3+
requirements:
4+
- class: InlineJavascriptRequirement
5+
expressionLib:
6+
- { $include: custom-functions.js }
7+
- |
8+
/**
9+
* A merely illustrative example function that uses a function
10+
* from the included custom-functions.js file to create a
11+
* Hello World message.
12+
*
13+
* @param {Object} message - CWL document input message
14+
*/
15+
var createHelloWorldMessage = function (message) {
16+
return capitalizeWords(message);
17+
};
18+
19+
baseCommand: echo
20+
21+
inputs:
22+
message:
23+
type: string
24+
25+
arguments: [$( createHelloWorldMessage(inputs.message) )]
26+
27+
outputs: []

src/topics/expressions.md

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ When manipulating file names, extensions, paths etc, consider whether one of the
1111
[built in `File` properties][file-prop] like `basename`, `nameroot`, `nameext`,
1212
etc, could be used instead.
1313
See the [list of best practices](best-practices.md).
14+
```
1415

1516
```{literalinclude} /_includes/cwl/expressions/expression.cwl
1617
:language: cwl
@@ -112,7 +113,91 @@ only in certain fields. These are:
112113

113114
[file-prop]: https://www.commonwl.org/v1.0/CommandLineTool.html#File
114115

116+
## Using external libraries and inline JavaScript code with `expressionLib`
117+
118+
The requirement `InlineJavascriptRequirement` supports an `expressionLib` attribute
119+
that allows users to load external JavaScript files, or to provide inline JavaScript
120+
code.
121+
122+
Entries added to the `expressionLib` attribute are parsed with the JavaScript engine
123+
of a CWL runner. This can be used to include external files or to create JavaScript
124+
functions that can be called in other parts of the CWL document.
125+
126+
```{note}
127+
128+
The CWL standards (versions 1.0 through 1.2) [states](https://www.commonwl.org/v1.0/CommandLineTool.html#Expressions)
129+
that the only version of JavaScript valid in CWL expressions is
130+
[ECMAScript 5.1](https://262.ecma-international.org/5.1/). This means that any
131+
code that you include or write in your CWL Document must be compliant with
132+
ECMAScript 5.1.
133+
```
134+
135+
For example, we can use `InlineJavascriptRequirement` and write a JavaScript function
136+
inline in `expressionLib`. That function can then be used in other parts of the
137+
CWL document:
138+
139+
```{literalinclude} /_includes/cwl/expressions/hello-world-expressionlib-inline.cwl
140+
:language: cwl
141+
:caption: "`hello-world-expressionlib-inline.cwl`"
142+
:name: "`hello-world-expressionlib-inline.cwl`"
143+
:emphasize-lines: 5, 14, 32
144+
```
145+
146+
Running this CWL workflow will invoke the JavaScript function and result in
147+
the `echo` command printing the input message with capital initial letters:
148+
149+
```{runcmd} cwltool hello-world-expressionlib-inline.cwl --message "hello world"
150+
:caption: "Running `hello-world-expressionlib-inline.cwl`."
151+
:name: running-hell-world-expressionlib-inline-cwl
152+
:working-directory: src/_includes/cwl/expressions/
153+
```
154+
155+
Let's move the `capitalizeWords` function to an external file, `custom-functions.js`, and
156+
import it in our CWL document:
157+
158+
```{literalinclude} /_includes/cwl/expressions/custom-functions.js
159+
:language: javascript
160+
:caption: "`custom-functions.js`"
161+
:name: "`custom-functions.js`"
162+
```
163+
164+
```{literalinclude} /_includes/cwl/expressions/hello-world-expressionlib-external.cwl
165+
:language: cwl
166+
:caption: "`hello-world-expressionlib-external.cwl`"
167+
:name: "`hello-world-expressionlib-external.cwl`"
168+
:emphasize-lines: 5-6, 14
169+
```
170+
171+
The `custom-functions.js` file is included in the CWL document with the `$include: custom-functions.js`
172+
statement. That makes the functions and variables available to be used in other parts of
173+
the CWL document.
174+
175+
```{runcmd} cwltool hello-world-expressionlib-external.cwl --message "hello world"
176+
:caption: "Running `hello-world-expressionlib-external.cwl`."
177+
:name: running-hell-world-expressionlib-external-cwl
178+
:working-directory: src/_includes/cwl/expressions/
179+
```
115180

116-
% TODO
117-
% - (maybe not before other concepts? move this to after inputs/outputs/etc?)
118-
% - External libraries and expressionLib - https://github.com/common-workflow-language/user_guide/issues/126
181+
Finally, note that you can have both inline and external JavaScript code in your
182+
CWL document. In this final example we have added another entry to the `expressionLib`
183+
attribute with the new function `createHelloWorldMessage`, that calls the `capitalizeWords`
184+
function from the external file `custom-functions.js`.
185+
186+
```{literalinclude} /_includes/cwl/expressions/hello-world-expressionlib.cwl
187+
:language: cwl
188+
:caption: "`hello-world-expressionlib.cwl`"
189+
:name: "`hello-world-expressionlib.cwl`"
190+
:emphasize-lines: 5-17, 25
191+
```
192+
193+
```{runcmd} cwltool hello-world-expressionlib.cwl --message "hello world"
194+
:caption: "Running `hello-world-expressionlib.cwl`."
195+
:name: running-hell-world-expressionlib-cwl
196+
:working-directory: src/_includes/cwl/expressions/
197+
```
198+
199+
```{note}
200+
The `$include` statement can be used to include a file from the local disk or from a remote location.
201+
It works with both relative and absolute paths. Read the [text about `$include`](https://www.commonwl.org/v1.0/SchemaSalad.html#Include)
202+
from the CWL specification to learn more about it.
203+
```

0 commit comments

Comments
 (0)