jtlt 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGES.md +27 -0
  2. package/README.md +61 -164
  3. package/demo/calltemplate-params-demo.js +138 -0
  4. package/demo/codemirror.esm.js +28242 -0
  5. package/demo/codemirror.js +94 -0
  6. package/demo/index.css +7 -0
  7. package/demo/index.html +28 -0
  8. package/demo/index.js +210 -0
  9. package/demo/vendor/jamilih/dist/jml.mjs +2341 -0
  10. package/demo/vendor/jhtml/src/SAJJ/SAJJ.ObjectArrayDelegator.js +356 -0
  11. package/demo/vendor/jhtml/src/SAJJ/SAJJ.Stringifier.js +186 -0
  12. package/demo/vendor/jhtml/src/SAJJ/SAJJ.js +746 -0
  13. package/demo/vendor/jhtml/src/SAJJ/testing/SAJJ.html +33 -0
  14. package/demo/vendor/jhtml/src/SAJJ/testing/SAJJ.testing.js +25 -0
  15. package/demo/vendor/jhtml/src/jhtml-browser.js +5 -0
  16. package/demo/vendor/jhtml/src/jhtml-node.cts +3 -0
  17. package/demo/vendor/jhtml/src/jhtml-node.js +8 -0
  18. package/demo/vendor/jhtml/src/jhtml-node.mts +1 -0
  19. package/demo/vendor/jhtml/src/jhtml.cts +3 -0
  20. package/demo/vendor/jhtml/src/jhtml.js +602 -0
  21. package/demo/vendor/jhtml/src/jhtml.mts +1 -0
  22. package/demo/vendor/jsonpath-plus/dist/index-browser-esm.js +2158 -0
  23. package/demo/vendor/simple-get-json/dist/index-es.js +151 -0
  24. package/demo/xpath2-placeholder.js +1 -0
  25. package/dist/AbstractJoiningTransformer.d.ts +83 -9
  26. package/dist/AbstractJoiningTransformer.d.ts.map +1 -1
  27. package/dist/DOMJoiningTransformer.d.ts +85 -25
  28. package/dist/DOMJoiningTransformer.d.ts.map +1 -1
  29. package/dist/JSONJoiningTransformer.d.ts +159 -51
  30. package/dist/JSONJoiningTransformer.d.ts.map +1 -1
  31. package/dist/JSONPathTransformer.d.ts +37 -38
  32. package/dist/JSONPathTransformer.d.ts.map +1 -1
  33. package/dist/JSONPathTransformerContext.d.ts +334 -124
  34. package/dist/JSONPathTransformerContext.d.ts.map +1 -1
  35. package/dist/StringJoiningTransformer.d.ts +132 -41
  36. package/dist/StringJoiningTransformer.d.ts.map +1 -1
  37. package/dist/XPathTransformer.d.ts +35 -20
  38. package/dist/XPathTransformer.d.ts.map +1 -1
  39. package/dist/XPathTransformerContext.d.ts +281 -105
  40. package/dist/XPathTransformerContext.d.ts.map +1 -1
  41. package/dist/index-browser.d.ts +4 -0
  42. package/dist/index-browser.d.ts.map +1 -0
  43. package/dist/index-node.d.ts +4 -0
  44. package/dist/index-node.d.ts.map +1 -0
  45. package/dist/index.d.ts +330 -57
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/types.d.ts +204 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/docs/API.expanded.md +172 -5
  50. package/docs/API.md +92 -2
  51. package/docs/TO-DO.md +168 -0
  52. package/docs/calltemplate-params.md +251 -0
  53. package/eslint.config.js +11 -5
  54. package/package.json +35 -9
  55. package/pnpm-workspace.yaml +1 -0
  56. package/rollup.config.js +13 -0
  57. package/src/AbstractJoiningTransformer.js +54 -15
  58. package/src/DOMJoiningTransformer.js +275 -28
  59. package/src/JSONJoiningTransformer.js +351 -70
  60. package/src/JSONPathTransformer.js +48 -30
  61. package/src/JSONPathTransformerContext.js +729 -107
  62. package/src/StringJoiningTransformer.js +311 -57
  63. package/src/XPathTransformer.js +27 -12
  64. package/src/XPathTransformerContext.js +928 -99
  65. package/src/index-browser.js +5 -0
  66. package/src/index-node.js +7 -0
  67. package/src/index.js +502 -98
  68. package/tsconfig.json +5 -2
  69. package/typings/xpath2-js.d.ts +40 -1
  70. package/src/types/xpath2-js.d.ts +0 -2
package/CHANGES.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # jtlt CHANGES
2
2
 
3
+ ## 0.4.0
4
+
5
+ - feat: `number()` enhancements
6
+ - feat: `analyzeString()`
7
+ - feat: xpath 3.1
8
+ - feat: demo
9
+ - fix: set XPath default query to `//*`
10
+ - fix(types): outputType
11
+
12
+ ## 0.3.0
13
+
14
+ - feat: `if()`
15
+ - feat: `choose()`
16
+ - feat: propSets for DOM
17
+ - feat: add `comment()` and `processingInstruction()`
18
+ - feat: optional `path` may be omitted when `name` present (named-only templates)
19
+ - feat: XPath `copy()` (shallow) and `copyOf(select?)` (deep cloning / scalar append)
20
+ - feat: JSONPath cloning docs expanded (existing `copy`/`copyOf` clarified)
21
+ - fix: avoid appending `undefined` from `callTemplate` when template returns nothing
22
+ - fix: parameter fallback in `valueOf` for JSONPath param access
23
+ - fix: scalar XPath `copyOf()` prevents DOM hierarchy errors when expression returns Document
24
+ - feat: add `exposeDocuments` option
25
+ - feat: callTemplate in XPath
26
+ - feat: add `document()` (XSLT `xsl:document`-like) and `resultDocument()` (XSLT `xsl:result-document`-like) to all joiners
27
+ - feat: support `output({method})` values `json` and `xhtml` across joiners
28
+ - change: JSON joiner `$document` wrapper includes DOCTYPE only when `method` is `xml` or `xhtml`; XML declaration emitted for `xml`/`xhtml` unless `omitXmlDeclaration`
29
+
3
30
  ## 0.2.0
4
31
 
5
32
  - fix: point to `types` and add `exports`
package/README.md CHANGED
@@ -2,14 +2,16 @@
2
2
 
3
3
  JavaScript Template Language Transformations (JTLT, pronounced as
4
4
  "Jetlet")—a JavaScript equivalent of [XSLT](https://www.w3.org/Style/XSL/),
5
- for JSON/JavaScript object data sources.
5
+ for JSON/JavaScript object or XML data sources.
6
6
 
7
7
  As with XSLT, allows for declarative, linear declaration of
8
8
  (recursive) templates and can be transformed into different
9
- formats (e.g., HTML strings, JSON, DOM objects, etc.).
9
+ formats (e.g., strings, JSON, or DOM objects).
10
10
 
11
11
  ***Beta state!!!***
12
12
 
13
+ See the [Demo](https://brettz9.github.io/jtlt/demo/).
14
+
13
15
  ## Credits
14
16
 
15
17
  Packaged with [JSONPath Plus](https://github.com/s3u/JSONPath).
@@ -19,11 +21,11 @@ The sample file is from <https://goessner.net/articles/JsonPath/>
19
21
  ## Installation
20
22
 
21
23
  ```shell
22
- npm install .
24
+ npm install jtlt
23
25
  ```
24
26
 
25
27
  In the browser, you will also need to include the dependencies.
26
- See the [test file](test/test.html).
28
+ See the [test file](./test/browser/index.html).
27
29
 
28
30
  ## Basic usage
29
31
 
@@ -44,9 +46,9 @@ JTLT has two layers:
44
46
  - JSONPathTransformerContext: The execution context passed to templates. It mirrors the joiner API (e.g., string(), object(), array()) so templates can emit results. It also provides helpers like applyTemplates(), callTemplate(), valueOf(), variable(), and forEach().
45
47
  - XPathTransformer (experimental): Applies templates to
46
48
  XML/HTML DOM by matching XPath selectors (and optional modes).
47
- Supports two evaluation modes: version 1 (native
48
- XPathEvaluator) and version 2 (via xpath2.js). Falls back to
49
- built‑in default rules when no template matches.
49
+ Supports three evaluation modes: version 1 (native
50
+ XPathEvaluator), version 2 (via xpath2.js), and version 3 (via fontoxpath).
51
+ Falls back to built‑in default rules when no template matches.
50
52
  - XPathTransformerContext (experimental): Execution context for
51
53
  XPath. Offers get(), forEach(), valueOf(), variable(), key()
52
54
  and the same joiner helpers as the JSONPath context.
@@ -56,6 +58,15 @@ JTLT has two layers:
56
58
  - DOMJoiningTransformer: Builds a DocumentFragment/Element tree. element()/attribute()/text() add real nodes; primitives append as text nodes.
57
59
  - JSONJoiningTransformer: Builds real JS values (objects/arrays/primitives) without serialization.
58
60
 
61
+ ### Output formats and multi-document
62
+
63
+ - Output formats supported via `output({method})`: `xml`, `html`, `text`, `xhtml`, and `json`.
64
+ - `xml`/`xhtml` behave like XML: XML declaration (unless omitted) and optional DOCTYPE.
65
+ - `html` is HTML‑centric; `text` is raw text; `json` is JSON‑centric (no XML declaration/DOCTYPE).
66
+ - Multi-document APIs:
67
+ - `document(cb, cfg?)`: Create additional documents; when a joiner is configured with `{exposeDocuments: true}`, `get()` returns an array of documents.
68
+ - `resultDocument(href, cb, cfg?)`: Create additional documents with metadata (`href`, `format`, and `document`) accessible on `joiner._resultDocuments`.
69
+
59
70
  ### Common joiner methods
60
71
 
61
72
  - append(value): Central sink. Based on context, concatenates to string, pushes to array, or assigns to an object property.
@@ -84,55 +95,54 @@ Provide joiningConfig when constructing JTLT:
84
95
  - joiningConfig.xmlElements: Switch element() to XML serialization mode in the String joiner.
85
96
  - joiningConfig.preEscapedAttributes: Skip escaping attribute values in the String joiner.
86
97
 
87
- ### XPath (experimental)
88
-
89
- You can run templates against XML/HTML using XPath instead of JSONPath.
90
-
91
- - Construct with `new XPathTransformer({data, templates,
92
- joiningTransformer, xpathVersion})`.
93
- - `data` should be a Document or Element (e.g., from DOMParser with
94
- `text/xml`).
95
- - `xpathVersion`: `1` uses native XPath (browser like). `2` uses
96
- `xpath2.js` for XPath 2.0‑style evaluation.
97
- - In version 2, some functions may be missing; prefer simple path
98
- expressions. Use version 1 for wide XPath 1.0 function support.
99
-
100
- Example (string output):
98
+ ## Quick start (JSON source)
101
99
 
102
100
  ```js
103
- import {JSDOM} from 'jsdom';
104
- import {StringJoiningTransformer, XPathTransformer} from 'jtlt';
101
+ import {jtlt} from 'jtlt';
105
102
 
106
- const {window} = new JSDOM('<!doctype><html><body></body></html>');
107
- const parser = new window.DOMParser();
108
- const doc = parser.parseFromString(
109
- '<root><item>a</item><item>b</item></root>', 'text/xml'
110
- );
103
+ const data = {title: 'Hello', items: ['a', 'b']};
111
104
 
112
- const joiner = new StringJoiningTransformer('', {document: doc});
113
105
  const templates = [
114
- {name: 'root', path: '/', template () {
115
- this.applyTemplates('//item');
106
+ {path: '$', template () {
107
+ this.applyTemplates();
116
108
  }},
117
- {name: 'item', path: '//item', template (node) {
118
- this.element('li', {}, [], () => this.text(node.textContent));
109
+ {path: '$.title', template (v) {
110
+ this.string('<h1>', () => this.text(v));
111
+ this.string('</h1>');
112
+ }},
113
+ {path: '$.items[*]', template (v) {
114
+ this.element('li', {}, [], () => this.text(v));
119
115
  }}
120
116
  ];
121
117
 
122
- const out = new XPathTransformer({
123
- data: doc,
124
- templates,
125
- joiningTransformer: joiner,
126
- xpathVersion: 1 // or 2
127
- }).transform('');
128
- // -> <li>a</li><li>b</li>
118
+ const out = await jtlt({data, templates, outputType: 'string'});
119
+
120
+ console.log(out);
129
121
  ```
130
122
 
131
- Using the JTLT facade with XPath (no manual joiner needed):
123
+ Notes:
124
+
125
+ - Modes let you organize multiple passes or output targets.
126
+ - You can also call templates by name via this.callTemplate('name').
127
+ - For DOM output, use outputType: 'dom'. For JSON output, use 'json'.
128
+
129
+ ### Quick start (XML source with XPath)
130
+
131
+ You can run templates against XML/HTML using XPath instead of JSONPath.
132
+
133
+ - `data` should be a Document or Element (e.g., from `DOMParser` with
134
+ `text/xml`).
135
+ - `xpathVersion`: `1` uses native XPath (browser like). `2` uses
136
+ `xpath2.js` for XPath 2.0‑style evaluation. and `3.1` uses `fontoxpath`
137
+ for XPath 3.1.
138
+ - In version 2, some functions may be missing; prefer simple path
139
+ expressions. Use version 1 for standard XPath 1.0 function support.
140
+
141
+ Example (string output) using the JTLT facade with XPath:
132
142
 
133
143
  ```js
134
144
  import {JSDOM} from 'jsdom';
135
- import JTLT from 'jtlt';
145
+ import {jtlt} from 'jtlt';
136
146
 
137
147
  const {window} = new JSDOM('<!doctype><html><body></body></html>');
138
148
  const parser = new window.DOMParser();
@@ -156,49 +166,17 @@ const templates = [
156
166
  }
157
167
  ];
158
168
 
159
- const out = new JTLT({
169
+ const out = await jtlt({
160
170
  data: doc,
161
171
  templates,
162
172
  outputType: 'string',
163
173
  engineType: 'xpath',
164
174
  xpathVersion: 1, // or 2
165
175
  success: (res) => res
166
- }).transform('');
176
+ });
167
177
  // -> <li>a</li><li>b</li>
168
178
  ```
169
179
 
170
- ## Quick start
171
-
172
- ```js
173
- import JTLT from 'jtlt';
174
-
175
- const data = {title: 'Hello', items: ['a', 'b']};
176
-
177
- const templates = [
178
- {path: '$', template () {
179
- this.applyTemplates({mode: 'html'});
180
- }},
181
- {mode: 'html', path: '$.title', template (v) {
182
- this.string('<h1>', () => this.text(v));
183
- this.string('</h1>');
184
- }},
185
- {mode: 'html', path: '$.items[*]', template (v) {
186
- this.element('li', {}, [], () => this.text(v));
187
- }}
188
- ];
189
-
190
- const out = new JTLT({data, templates, outputType: 'string'}).
191
- transform('html');
192
-
193
- console.log(out);
194
- ```
195
-
196
- Notes:
197
-
198
- - Modes let you organize multiple passes or output targets.
199
- - You can also call templates by name via this.callTemplate('name').
200
- - For DOM output, use outputType: 'dom'. For JSON output, use 'json'.
201
-
202
180
  ## One-off queries with forQuery (XQuery-like)
203
181
 
204
182
  If you just want to run a single, non-recursive query (similar to an XQuery "for … where … return …"), you can skip defining templates and use `forQuery` to seed a root function that iterates a JSONPath and emits results.
@@ -427,15 +405,18 @@ Advantages (strong parallels with XSLT):
427
405
 
428
406
  Differences / current limitations:
429
407
 
430
- - Expression language: XPath 2.0 implementation is not fully feature complete.
408
+ - Expression language: XPath 2.0 implementation is not fully feature complete and the XPath 1.0 implementation from `jsdom` may not be either.
409
+ - As the syntax is JavaScript, it is not feasible to recursively transform
410
+ JTLT syntax with itself (at least not easily) as one can do with XSLT.
411
+ However, one can use arbitrary JavaScript, or using such as `jsep`,
412
+ allow a particuluar subset of JavaScript.
431
413
  - Stylesheet composition/precedence: no `xsl:import`/`xsl:include` equivalents; only basic priority and modes.
432
414
  - Schema awareness: no type-aware processing (a major XSLT/XQuery feature).
433
415
  - Multi-output (`xsl:result-document`): not built-in; pick one output type per transform.
434
416
 
435
417
  ## Differences between an exact equivalence with XSLT
436
418
 
437
- JTLT, having the freedom to start a new pattern from XSLT, and though
438
- seeking to learn from it, deviates somewhat from making an exact
419
+ JTLT deviates somewhat from making an exact
439
420
  equivalence with XSLT (to the extent JTLT and JSONPath implement
440
421
  what could possibly be transferred to JSON-based transformations
441
422
  from XSLT):
@@ -447,88 +428,4 @@ from XSLT):
447
428
 
448
429
  ## To-dos
449
430
 
450
- 1. Document and add test cases to cover current features! (Could adapt an XSLT/XQuery test suite)
451
-
452
- 1. Implement and demo equivalent to applying and calling templates, and
453
- root template
454
-
455
- 2. Demo chaining of methods, including [equivalents](https://www.saxonica.com/papers/XTech2005/mhkpaper.html#S4.)
456
- to XQuery's FLWOR expressions (see also Promises to-do), perhaps
457
- even making aliases so that XQuery's friendlier terms can be used
458
- instead of XSLT's.
459
-
460
- 2. Support processing of JSON documents with `$jtlt-stylesheet` to let
461
- documents define their own targeted stylesheets.
462
-
463
- 3. When sufficiently documented, add as example library/tool to
464
- JSONPath wiki.
465
-
466
- 4. Allow alternative to `element()`, `array()`, etc. methods by just
467
- detecting those types from return values (and generic of each
468
- type like `dom()` and `json()`).
469
-
470
- 5. Allow, depending on mode, containers to contain containers of other
471
- types (e.g., a JS container containing DOM objects, or temporary use
472
- of a string container, etc.).
473
-
474
- 1. Support XML and add [hXML](https://github.com/brettz9/hxml) methods.
475
-
476
- 2. Support [JHTML](https://github.com/brettz9/jhtml).
477
-
478
- 3. Support `appendJSON()`/`appendDOM()` and
479
- `appendType('json', ...)` (allowing type extensions).
480
-
481
- 6. Add `appendResult(function () {return result})`.
482
-
483
- 7. Add JSON update functions (equivalent to Xquery Update Facility for
484
- XML ([overview](http://www.xmlplease.com/xquery-update))) and create
485
- JSON serialization (as with XSLT expressed itself in declarative XML)
486
- so one can submit and evaluate
487
- through [HTTPQuery](https://github.com/brettz9/httpquery) (and also
488
- supply to JSONEditor, etc.). Utilize updating by reference.
489
-
490
- 8. Demo narrowing to subset of JavaScript (as with `jspe`) to make
491
- JTLT truly "declarative" as far as freedom from scripting
492
-
493
- ## Possible to-dos
494
-
495
- 1. Make schema-aware so that templates could target types. Most reusable
496
- application may be having a type-driven view of a JSON Schema instance
497
- (e.g., dates could be shown inside a calendar widget). Perhaps this
498
- schema-awareness could also drive a JSON editor (as with other existing
499
- projects) (even using same API as JSONEditor?) (or type-aware filtered
500
- search/raw queries). This would help not only for editors which edit a
501
- JSON file in full, but also for providing schema paths or other identifiers
502
- so that a transformed/queried subset of a file (or joining of multiple
503
- files) could point the way for edited contents to be saved back to the
504
- correct JSON file and position in the JSON file.
505
-
506
- 2. Add a [non-eval PR for JSONPath](https://github.com/s3u/JSONPath/pull/4).
507
- The OR condition (outside of filters) is another important feature as
508
- would be schema-aware path results.
509
-
510
- 3. Allow hybrid JSON/[Jamilih](https://github.com/brettz9/jamilih) or
511
- JSON/(X)HTML/XML so that one can add
512
- XPath or query into HTML in a relevant manner
513
-
514
- 4. Support pull parsing/streaming? Pass `done()` function to templates to
515
- signal completion?
516
-
517
- 5. Support Promise API in addition to callbacks (reconcile with
518
- current chaining; see also XQuery FLWOR to-do)
519
-
520
- 6. Add [XQuery Functions](https://code.google.com/p/jsxqueryparser/source/browse/trunk/jsxqueryparser/XQueryParser.js#1768)
521
- (also supporting DOM and JSON where possible) as plug-in (also any
522
- missing from XSLT/XQuery 3.0). Also add, if not present among these
523
- functions (or in XQuery), add equivalents to XSLT's
524
- `document()` and `unparsed-text()` for allowing non-JSON file
525
- retrieval (as well as variables/parameters) and also methods for
526
- iterating or retrieving IndexedDB, `localStorage`, and cookies
527
- (names, keys and values).
528
-
529
- 7. Add `outputType` which uses a DOM joiner but allows specialized
530
- serialized output (e.g., pretty-printed HTML) so the users
531
- don't need to build it themselves (likewise with stringified
532
- JSON output).
533
-
534
- 8. See code for other possible to-dos
431
+ See [TO-DO](./docs/TO.DO.md).
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Demo: Using valueOf() to access parameters in callTemplate
3
+ *
4
+ * This demonstrates the new feature where parameters passed via callTemplate
5
+ * can be accessed within the template using valueOf({select: '$paramName'})
6
+ * instead of having to receive them as function parameters.
7
+ */
8
+
9
+ /* eslint-disable no-console, no-new -- Demo file */
10
+
11
+ import JTLT from '../src/index-node.js';
12
+
13
+ console.log('=== Demo 1: Named parameters ===');
14
+ new JTLT({
15
+ data: {
16
+ users: [
17
+ {name: 'Alice', role: 'Admin'},
18
+ {name: 'Bob', role: 'User'}
19
+ ]
20
+ },
21
+ outputType: 'string',
22
+ templates: [
23
+ {
24
+ path: '$',
25
+ template () {
26
+ this.forEach('$.users[*]', function (user) {
27
+ this.callTemplate({
28
+ name: 'formatUser',
29
+ withParam: [
30
+ {name: 'userName', value: user.name},
31
+ {name: 'userRole', value: user.role},
32
+ {name: 'prefix', value: '> '}
33
+ ]
34
+ });
35
+ });
36
+ }
37
+ },
38
+ {
39
+ name: 'formatUser',
40
+ template () {
41
+ // Access parameters using valueOf with $paramName
42
+ this.valueOf({select: '$prefix'});
43
+ this.valueOf({select: '$userName'});
44
+ this.string(' (');
45
+ this.valueOf({select: '$userRole'});
46
+ this.string(')\n');
47
+ }
48
+ }
49
+ ],
50
+ success (result) {
51
+ console.log(result);
52
+ console.log('\n');
53
+ }
54
+ });
55
+
56
+ console.log('=== Demo 2: Indexed parameters (no names) ===');
57
+ new JTLT({
58
+ data: {value: 'Test'},
59
+ outputType: 'string',
60
+ templates: [
61
+ {
62
+ path: '$',
63
+ template () {
64
+ this.callTemplate({
65
+ name: 'format',
66
+ withParam: [
67
+ {value: 'First param'},
68
+ {value: 'Second param'},
69
+ {select: '$.value'}
70
+ ]
71
+ });
72
+ }
73
+ },
74
+ {
75
+ name: 'format',
76
+ template () {
77
+ // Access by index when name not provided
78
+ this.string('Param 0: ');
79
+ this.valueOf({select: '$0'});
80
+ this.string('\nParam 1: ');
81
+ this.valueOf({select: '$1'});
82
+ this.string('\nParam 2: ');
83
+ this.valueOf({select: '$2'});
84
+ this.string('\n');
85
+ }
86
+ }
87
+ ],
88
+ success (result) {
89
+ console.log(result);
90
+ console.log('\n');
91
+ }
92
+ });
93
+
94
+ console.log('=== Demo 3: Nested callTemplate ===');
95
+ new JTLT({
96
+ data: {company: 'ACME Corp'},
97
+ outputType: 'string',
98
+ templates: [
99
+ {
100
+ path: '$',
101
+ template () {
102
+ this.callTemplate({
103
+ name: 'outer',
104
+ withParam: [
105
+ {name: 'company', select: '$.company'}
106
+ ]
107
+ });
108
+ }
109
+ },
110
+ {
111
+ name: 'outer',
112
+ template () {
113
+ this.string('Company: ');
114
+ this.valueOf({select: '$company'});
115
+ this.string('\n');
116
+
117
+ // Call another template from within
118
+ /** @type {any} */ (this).callTemplate({
119
+ name: 'inner',
120
+ withParam: [
121
+ {name: 'message', value: 'Nested template call'}
122
+ ]
123
+ });
124
+ }
125
+ },
126
+ {
127
+ name: 'inner',
128
+ template () {
129
+ this.string(' Message: ');
130
+ this.valueOf({select: '$message'});
131
+ this.string('\n');
132
+ }
133
+ }
134
+ ],
135
+ success (result) {
136
+ console.log(result);
137
+ }
138
+ });