jtlt 0.2.0 → 0.3.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 (50) hide show
  1. package/CHANGES.md +18 -0
  2. package/README.md +16 -87
  3. package/demo/calltemplate-params-demo.js +138 -0
  4. package/demo/index.html +31 -0
  5. package/demo/index.js +30 -0
  6. package/demo/xpath2-placeholder.js +1 -0
  7. package/dist/AbstractJoiningTransformer.d.ts +83 -9
  8. package/dist/AbstractJoiningTransformer.d.ts.map +1 -1
  9. package/dist/DOMJoiningTransformer.d.ts +85 -25
  10. package/dist/DOMJoiningTransformer.d.ts.map +1 -1
  11. package/dist/JSONJoiningTransformer.d.ts +159 -51
  12. package/dist/JSONJoiningTransformer.d.ts.map +1 -1
  13. package/dist/JSONPathTransformer.d.ts +37 -38
  14. package/dist/JSONPathTransformer.d.ts.map +1 -1
  15. package/dist/JSONPathTransformerContext.d.ts +247 -121
  16. package/dist/JSONPathTransformerContext.d.ts.map +1 -1
  17. package/dist/StringJoiningTransformer.d.ts +132 -41
  18. package/dist/StringJoiningTransformer.d.ts.map +1 -1
  19. package/dist/XPathTransformer.d.ts +35 -20
  20. package/dist/XPathTransformer.d.ts.map +1 -1
  21. package/dist/XPathTransformerContext.d.ts +191 -99
  22. package/dist/XPathTransformerContext.d.ts.map +1 -1
  23. package/dist/index-browser.d.ts +4 -0
  24. package/dist/index-browser.d.ts.map +1 -0
  25. package/dist/index-node.d.ts +4 -0
  26. package/dist/index-node.d.ts.map +1 -0
  27. package/dist/index.d.ts +330 -57
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/types.d.ts +204 -0
  30. package/dist/types.d.ts.map +1 -0
  31. package/docs/API.expanded.md +167 -2
  32. package/docs/API.md +91 -1
  33. package/docs/TO-DO.md +144 -0
  34. package/docs/calltemplate-params.md +251 -0
  35. package/eslint.config.js +9 -5
  36. package/package.json +13 -7
  37. package/pnpm-workspace.yaml +1 -0
  38. package/src/AbstractJoiningTransformer.js +54 -15
  39. package/src/DOMJoiningTransformer.js +275 -28
  40. package/src/JSONJoiningTransformer.js +351 -70
  41. package/src/JSONPathTransformer.js +48 -30
  42. package/src/JSONPathTransformerContext.js +308 -104
  43. package/src/StringJoiningTransformer.js +311 -57
  44. package/src/XPathTransformer.js +27 -12
  45. package/src/XPathTransformerContext.js +467 -89
  46. package/src/index-browser.js +5 -0
  47. package/src/index-node.js +7 -0
  48. package/src/index.js +498 -97
  49. package/typings/xpath2-js.d.ts +40 -1
  50. package/src/types/xpath2-js.d.ts +0 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH;;;GAGG;AACH;;;;;GAKG;AACH;;;GAGG;AACH;;;GAGG;AACH;;;GAGG;AAEH;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;GAGG;AACH;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;GAWG;AAEH,oEAAoE;AAEpE;;;;;;GAMG;AAGH,gCAAiC,IAAI,CAAC;yCA3HzB,OAAO,iCAAiC,EAAE,OAAO;sCAIjD,OAAO,8BAA8B,EAAE,OAAO;yCAI9C,OAAO,iCAAiC,EAAE,OAAO,CAAC,QAAQ,CAAC,GACvE,OAAW,iCAAiC,EAAE,OAAO,CAAC,MAAM,CAAC,GAC7D,OAAW,iCAAiC,EAAE,OAAO,CAAC,KAAK,CAAC;oCAIhD,OAAO,4BAA4B,EAAE,OAAO;qCAI5C,OAAO,6BAA6B,EAAE,OAAO;uCAI7C,OAAO,+BAA+B,EAAE,OAAO;;;;6BAM/C,IAAI,IACJ,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,OAAO,EACpC,GAAG,CAAC,EAAE;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAC,KAClB,OAAO;;;;2BAKF,IAAI;UAEH,MAAM;;;;cAeN,gBAAgB,CAAC,IAAI,CAAC;;qCAIvB,cAAc,CAAC,0BAA0B,CAAC;kCAI1C,cAAc,CAAC,uBAAuB,CAAC;;;;;;;;;aAOtC,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI;;;;WAEzB,OAAO;;;;;;;;;;;qBAQA,WAAW,KAAK,OAAO;0CACvB,MAAM,KAAK,CAAC,GAAC,GAAG,GAAC,CAAC,GAAG;;;aAG5B,OAAO;;;;;;;kCAOR,eAAe,GAAG;IAC1B,SAAS,CAAC,EAAE,sBAAsB,EAAE,GAClC,gBAAgB,CAAC,0BAA0B,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,sBAAsB,GAC/B,gBAAgB,CAAC,0BAA0B,CAAC,CAAC;IAC/C,KAAK,CAAC,EAAE,gBAAgB,CAAC,0BAA0B,CAAC,CAAC;IACrD,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB;;;;+BAKS,eAAe,GAAG;IAC1B,SAAS,CAAC,EAAE,mBAAmB,EAAE,GAC/B,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;IAC5C,QAAQ,CAAC,EAAE,mBAAmB,GAC5B,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;IAC5C,KAAK,CAAC,EAAE,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;IAClD,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,GAAC,CAAC,CAAA;CACnB;0BAGU,mBAAmB,GAAG,gBAAgB;;;;;kCAKvC,WAAW,GAAG;IACtB,yBAAyB,CAAC,EAAE,OAAO,CAAA;CACpC"}
@@ -54,7 +54,7 @@ const out = new JTLT({
54
54
  ```ts
55
55
  interface TemplateObject {
56
56
  name?: string; // Optional identifier (for callTemplate)
57
- path: string; // JSONPath or XPath expression
57
+ path?: string; // JSONPath or XPath expression (required for pattern-matching)
58
58
  mode?: string; // Optional mode segregation
59
59
  priority?: number; // Numeric priority (higher wins); fallback uses specificity resolver
60
60
  template(nodeValue, cfg): any; // Executed with `this` bound to context
@@ -62,6 +62,8 @@ interface TemplateObject {
62
62
  ```
63
63
 
64
64
  Edge cases:
65
+ - Either `path` or `name` (or both) must be provided
66
+ - Templates with only `name` (no `path`) are callable only via `callTemplate`
65
67
  - For JSONPath: `path` examples: `$.items[*]`, `$['prop']`, `$..deep`.
66
68
  - For XPath: `//item`, `/root/item`, `//*[@id='x']`.
67
69
  - Root template: path `$` (JSONPath) or `/` (XPath).
@@ -93,7 +95,7 @@ Config additions:
93
95
  ```js
94
96
  import {XPathTransformer, StringJoiningTransformer} from 'jtlt';
95
97
  // Assume `doc` is an XML Document
96
- const joiner = new StringJoiningTransformer('', {document: doc});
98
+ const joiner = new StringJoiningTransformer('');
97
99
  const templates = [
98
100
  {
99
101
  name: 'root',
@@ -131,10 +133,19 @@ Methods (subset):
131
133
  - `applyTemplates(select, mode?, sort?)`
132
134
  - `forEach(select, cb, sort?)`
133
135
  - `valueOf(select?)`
136
+ - `if(select, cb)` — conditionally execute `cb` when selection is truthy
137
+ (non-empty result set or truthy scalar)
138
+ - `choose(select, whenCb, otherwiseCb?)` — like `if()`, but invokes
139
+ `otherwiseCb` when the condition is not met (akin to xsl:choose +
140
+ xsl:otherwise). Selection is evaluated relative to current context
141
+ object (its own `$`).
134
142
  - `variable(name, select)` – stores value/array from JSONPath.
135
143
  - `callTemplate(name, withParam?)`
136
144
  - `key(name, match, use)` / `getKey(name, value)`
137
145
  - Joiner passthrough: `string()`, `text()`, `element()`, `object()`, `array()`, `number()`, `boolean()`, etc.
146
+ \- Cloning helpers:
147
+ - `copy(propertySets?)` — Shallow clone of current context value (object/array). Nested references are preserved. Optional `propertySets` (array of registered names) merge into the top-level clone when object-like.
148
+ - `copyOf(select?, propertySets?)` — Deep clone (prefers `structuredClone`; falls back to JSON + manual). When `select` is provided, clones that target instead of the current value; primitives append directly. Optional `propertySets` merge when cloning objects.
138
149
 
139
150
  ### `XPathTransformerContext`
140
151
 
@@ -142,9 +153,18 @@ Parallels JSONPath context with XPath evaluation:
142
153
  - `get(select, asNodes?)` – returns node array when `asNodes=true` (v1 uses snapshot type; v2 coerces scalar to array).
143
154
  - `forEach(select, cb)` – iterates matches.
144
155
  - `applyTemplates(select, mode?)` – default initialization to `.` then `*` for subsequent calls.
156
+ - `if(select, cb)` — conditionally executes `cb` when XPath selects nodes
157
+ (non-empty) or evaluates to a truthy scalar value. In XPath v1 environments
158
+ without strict result typing, node-set existence is the primary check.
159
+ - `choose(select, whenCb, otherwiseCb?)` — same semantics as `if()` but with
160
+ fallback callback when condition fails. Relative XPath resolves from the
161
+ current context node; absolute paths (`/`, `//`) target the document root.
145
162
  - `variable(name, select)` – always stores node arrays for XPath.
146
163
  - `key(name, match, use)` – index by attribute value; `getKey` returns matching Element or context sentinel (`this`).
147
164
  - Default template rules: root traverses `.`, element traverses `*`, text nodes emit `nodeValue`, scalars emit `valueOf('.')`.
165
+ \- Cloning helpers:
166
+ - `copy()` — Shallow clone of the current context node (`cloneNode(false)`) appended to the joiner.
167
+ - `copyOf(select?)` — Deep clone of each node matched by `select` (node-set) or the current node if omitted, using `cloneNode(true)`. If `select` yields a scalar, that scalar is appended. Document nodes in scalar fallback emit their `documentElement` text. Chainable.
148
168
 
149
169
  ## Sorting API
150
170
 
@@ -226,6 +246,11 @@ When no user template matches:
226
246
  Common joiner methods summary:
227
247
  - `append(value)`
228
248
  - `get()`
249
+ - `document(cb, cfg?)` — Creates a new output document. Similar to XSLT's
250
+ `xsl:document`, this allows templates to generate multiple output documents.
251
+ The callback builds the document content, and optional `cfg` provides output
252
+ configuration (encoding, doctype, etc.). When `exposeDocuments` is enabled,
253
+ each document is added to the array returned by `get()`.
229
254
  - `object(seed?, cb?, usePropertySets?, propSets?)`
230
255
  - `array(seed?, cb?)`
231
256
  - `element(name, attrs?, children?, cb?)`
@@ -233,6 +258,146 @@ Common joiner methods summary:
233
258
  - `text(str)` vs `string(str, cb?)` vs `plainText(str)`
234
259
  - `number()`, `boolean()`, `null()`, `undefined()` (JS mode), `nonfiniteNumber()`, `function(fn)`
235
260
 
261
+ ### document() method details
262
+
263
+ The `document()` method creates a new output document in isolation:
264
+
265
+ **DOM Joiner**: Creates a new XMLDocument with proper declaration and DOCTYPE
266
+ when configured via `output()`.
267
+
268
+ **JSON Joiner**: Creates a new document wrapper object with `$document` property
269
+ containing the Jamilih representation.
270
+
271
+ **String Joiner**: Creates a new document string with XML declaration and
272
+ DOCTYPE when configured.
273
+
274
+ **Signature**: `document(callback, outputConfig?)`
275
+
276
+ **Example**:
277
+ ```js
278
+ joiner.document(() => {
279
+ joiner.output({
280
+ method: 'xml',
281
+ version: '1.0',
282
+ encoding: 'utf8',
283
+ doctypePublic: '-//W3C//DTD XHTML 1.0//EN',
284
+ doctypeSystem: 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'
285
+ });
286
+ joiner.element('html', {xmlns: 'http://www.w3.org/1999/xhtml'}, () => {
287
+ joiner.element('head', {}, () => {
288
+ joiner.element('title', {}, () => {
289
+ joiner.text('Document 1');
290
+ });
291
+ });
292
+ });
293
+ });
294
+
295
+ joiner.document(() => {
296
+ joiner.element('html', {}, () => {
297
+ joiner.element('body', {}, () => {
298
+ joiner.text('Document 2');
299
+ });
300
+ });
301
+ });
302
+
303
+ // When exposeDocuments is true, get() returns array of documents
304
+ const docs = joiner.get();
305
+ ```
306
+
307
+ The method preserves the current joiner state, resets it for the new document,
308
+ executes the callback, captures the result, then restores the previous state.
309
+
310
+ ### resultDocument() method details
311
+
312
+ The `resultDocument()` method creates output documents with associated metadata,
313
+ paralleling XSLT's `xsl:result-document` functionality. Unlike `document()`,
314
+ which stores documents in `_docs`, `resultDocument()` stores them in
315
+ `_resultDocuments` with metadata including href URI and output format.
316
+
317
+ **DOM Joiner**: Creates XMLDocument with href and format metadata.
318
+
319
+ **JSON Joiner**: Creates document wrapper object or raw JSON with metadata.
320
+
321
+ **String Joiner**: Creates document string with XML/HTML markup and metadata.
322
+
323
+ **Signature**: `resultDocument(href, callback, outputConfig?)`
324
+
325
+ **Parameters**:
326
+ - `href` (string): URI or path for the result document (e.g., `'output/page1.html'`)
327
+ - `callback` (function): Builds the document content with `this` bound to joiner
328
+ - `outputConfig` (optional): Output configuration (encoding, doctype, method, etc.)
329
+
330
+ **Result document structure**:
331
+ ```ts
332
+ {
333
+ href: string, // The URI/path provided
334
+ document: any, // The generated document (XMLDocument, object, or string)
335
+ format: string // Output format from config.method ('xml', 'html', 'text', 'xhtml', 'json')
336
+ }
337
+ ```
338
+
339
+ **Example use case - Multi-page site generation**:
340
+ ```js
341
+ const pages = [
342
+ {title: 'Home', slug: 'index', content: 'Welcome'},
343
+ {title: 'About', slug: 'about', content: 'About us'},
344
+ {title: 'Contact', slug: 'contact', content: 'Get in touch'}
345
+ ];
346
+
347
+ pages.forEach((page) => {
348
+ joiner.resultDocument(`output/${page.slug}.html`, () => {
349
+ joiner.output({
350
+ method: 'html',
351
+ doctypePublic: '-//W3C//DTD XHTML 1.0 Strict//EN',
352
+ doctypeSystem: 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'
353
+ });
354
+ joiner.element('html', {xmlns: 'http://www.w3.org/1999/xhtml'}, () => {
355
+ joiner.element('head', {}, () => {
356
+ joiner.element('title', {}, () => {
357
+ joiner.text(page.title);
358
+ });
359
+ });
360
+ joiner.element('body', {}, () => {
361
+ joiner.element('h1', {}, () => {
362
+ joiner.text(page.title);
363
+ });
364
+ joiner.element('p', {}, () => {
365
+ joiner.text(page.content);
366
+ });
367
+ });
368
+ });
369
+ });
370
+ });
371
+
372
+ // Write each result document to its href location
373
+ joiner._resultDocuments.forEach((result) => {
374
+ fs.writeFileSync(result.href, result.document);
375
+ console.log(`Generated: ${result.href} (${result.format})`);
376
+ });
377
+ ```
378
+
379
+ **Interoperability**: `document()` and `resultDocument()` can be used together in
380
+ the same transformation. `document()` populates `_docs` (accessible via `get()`
381
+ when `exposeDocuments` is true), while `resultDocument()` populates
382
+ `_resultDocuments` with metadata.
383
+
384
+ ### Output configuration and formats
385
+
386
+ Joiners accept an output configuration via `output(cfg)` and within `document()`/`resultDocument()`.
387
+
388
+ - `cfg.method`: one of `xml`, `html`, `text`, `xhtml`, or `json`.
389
+ - `xml` and `xhtml` are XML-like: an XML declaration is emitted unless `omitXmlDeclaration` is true; DOCTYPE is included when `doctypePublic` or `doctypeSystem` is provided. For the JSON joiner, DOCTYPE entries are included in `$document.childNodes` only when `method` is `xml` or `xhtml`.
390
+ - `html` emits HTML; the String and DOM joiners serialize accordingly. The JSON joiner does not include a DOCTYPE node in its `$document` wrapper for `html`.
391
+ - `text` emits raw text (no element wrappers). The JSON joiner will not add DOCTYPE; the String joiner writes plain strings.
392
+ - `json` indicates a JSON-centric output; for the JSON joiner, this is the natural mode and does not add XML declarations or DOCTYPE.
393
+ - `omitXmlDeclaration`: when false (or for `xml`/`xhtml` with default), include XML declaration with optional `version`, `encoding`, `standalone`.
394
+ - `doctypePublic`/`doctypeSystem`: when provided and `method` is `xml`/`xhtml`, include a DOCTYPE entry.
395
+
396
+ Notes for JSON joiner with `exposeDocuments`:
397
+
398
+ - When `exposeDocuments` is enabled in the joiner config, `get()` returns an array of `$document` wrappers. Each wrapper has a `childNodes` array where the root element is the last entry; the first entry may be a DOCTYPE object when `method` is `xml` or `xhtml`.
399
+ - For `html`, `text`, or `json` methods, no DOCTYPE is included in the JSON wrapper by default.
400
+
236
401
  ## Error handling
237
402
 
238
403
  - Equal priority templates: either last wins (default) or error if `errorOnEqualPriority=true`.
package/docs/API.md CHANGED
@@ -33,11 +33,101 @@ new JTLT({
33
33
  `variable(name, select)`, `key(name, match, use)`, `getKey(name, value)`.
34
34
  JSONPath variables store values; XPath variables store arrays of nodes.
35
35
 
36
+ Cloning:
37
+ `copy()` (shallow clone current JSON value or DOM node) and
38
+ `copyOf(select?)` (deep clone; optional selector overrides target; scalar
39
+ selectors append the scalar). JSONPath deep cloning uses `structuredClone`
40
+ fallbacks; XPath uses `cloneNode(true)`.
41
+
42
+ Conditional execution:
43
+ - `if(select, cb)` — runs `cb` when the selector matches (non-empty
44
+ result set) or coerces to a truthy scalar.
45
+ - `choose(select, whenCb, otherwiseCb?)` — like `if()`, but also runs
46
+ `otherwiseCb` when the condition fails.
47
+
36
48
  ## Joiners
37
49
 
38
50
  StringJoiningTransformer, DOMJoiningTransformer, JSONJoiningTransformer with
39
51
  helpers: `string`, `text`, `element`, `attribute`, `object`, `array`,
40
- `number`, `boolean`, `plainText`, `append`, `get`.
52
+ `number`, `boolean`, `plainText`, `append`, `get`, `document`.
53
+
54
+ ### document() method
55
+
56
+ Similar to XSLT's `xsl:document`, the `document()` method allows templates to
57
+ generate multiple output documents. It accepts a callback that builds the
58
+ document content, and an optional output configuration.
59
+
60
+ **Signature**: `document(callback, outputConfig?)`
61
+
62
+ When `exposeDocuments` is enabled, each document created with `document()` is
63
+ added to the array returned by `get()`.
64
+
65
+ **Example**:
66
+ ```js
67
+ joiner.document(() => {
68
+ joiner.output({method: 'xml', version: '1.0'});
69
+ joiner.element('doc1', {}, () => {
70
+ joiner.text('First document');
71
+ });
72
+ });
73
+
74
+ joiner.document(() => {
75
+ joiner.element('doc2', {}, () => {
76
+ joiner.text('Second document');
77
+ });
78
+ });
79
+
80
+ const docs = joiner.get(); // Returns array of 2 documents
81
+ ```
82
+
83
+ ### resultDocument() method
84
+
85
+ Similar to XSLT's `xsl:result-document`, the `resultDocument()` method allows
86
+ templates to generate multiple output documents **with metadata** (href URI,
87
+ format). Documents are stored in `joiner._resultDocuments` array.
88
+
89
+ **Signature**: `resultDocument(href, callback, outputConfig?)`
90
+
91
+ Each result document is stored with:
92
+ - `href`: The URI/path for the document (e.g., `'output/page1.html'`)
93
+ - `document`: The generated document content
94
+ - `format`: The output format (from `method` in config). One of `xml`, `html`, `text`, `xhtml`, or `json`.
95
+
96
+ **Example**:
97
+ ```js
98
+ joiner.resultDocument('output/doc1.xml', () => {
99
+ joiner.output({method: 'xml', version: '1.0'});
100
+ joiner.element('doc1', {}, () => {
101
+ joiner.text('First document');
102
+ });
103
+ });
104
+
105
+ joiner.resultDocument('output/doc2.html', () => {
106
+ joiner.output({method: 'html'});
107
+ joiner.element('html', {}, () => {
108
+ joiner.text('Second document');
109
+ });
110
+ }, {method: 'html'});
111
+
112
+ // Access result documents with metadata
113
+ joiner._resultDocuments.forEach((result) => {
114
+ console.log(result.href); // e.g., 'output/doc1.xml'
115
+ console.log(result.format); // e.g., 'xml'
116
+ console.log(result.document); // The document content
117
+ });
118
+ ```
119
+
120
+ ### Output configuration (quick reference)
121
+
122
+ - `method`: `xml` | `html` | `text` | `xhtml` | `json`
123
+ - `xml`/`xhtml`: XML declaration unless `omitXmlDeclaration`; DOCTYPE included when `doctypePublic`/`doctypeSystem` present. For the JSON joiner, a DOCTYPE entry appears in `$document.childNodes` only for these methods.
124
+ - `html`: HTML output; JSON joiner wrapper omits DOCTYPE.
125
+ - `text`: raw text; no DOCTYPE.
126
+ - `json`: native JSON output; no XML declaration or DOCTYPE.
127
+ - `omitXmlDeclaration`, `version`, `encoding`, `standalone`: control XML declaration (applicable to `xml`/`xhtml`).
128
+ - `doctypePublic`, `doctypeSystem`: control DOCTYPE (applicable to `xml`/`xhtml`).
129
+
130
+ Note: With `exposeDocuments` enabled on a joiner, `get()` returns an array of `$document` wrappers. In the JSON joiner, the root element is the last entry of `$document.childNodes`; a DOCTYPE may precede it for `xml`/`xhtml`.
41
131
 
42
132
  ## Sorting
43
133
 
package/docs/TO-DO.md ADDED
@@ -0,0 +1,144 @@
1
+ ## To-dos
2
+
3
+ 1. Document and add test cases to cover current features! (Could adapt an XSLT/XQuery test suite)
4
+
5
+ 1. Implement and demo equivalent to applying and calling templates, and
6
+ root template
7
+
8
+ 2. Demo chaining of methods, including [equivalents](https://www.saxonica.com/papers/XTech2005/mhkpaper.html#S4.)
9
+ to XQuery's FLWOR expressions (see also Promises to-do), perhaps
10
+ even making aliases so that XQuery's friendlier terms can be used
11
+ instead of XSLT's.
12
+
13
+ 2. Support processing of JSON documents with `$jtlt-stylesheet` to let
14
+ documents define their own targeted stylesheets.
15
+
16
+ 3. When sufficiently documented, add as example library/tool to
17
+ JSONPath wiki.
18
+
19
+ 4. Allow alternative to `element()`, `array()`, etc. methods by just
20
+ detecting those types from return values (and generic of each
21
+ type like `dom()` and `json()`).
22
+
23
+ 5. Allow, depending on mode, containers to contain containers of other
24
+ types (e.g., a JS container containing DOM objects, or temporary use
25
+ of a string container, etc.).
26
+
27
+ 1. Support XML and add [hXML](https://github.com/brettz9/hxml) methods.
28
+
29
+ 2. Support [JHTML](https://github.com/brettz9/jhtml).
30
+
31
+ 3. Support `appendJSON()`/`appendDOM()` and
32
+ `appendType('json', ...)` (allowing type extensions).
33
+
34
+ 6. Add `appendResult(function () {return result})`.
35
+
36
+ 7. Add JSON update functions (equivalent to Xquery Update Facility for
37
+ XML ([overview](http://www.xmlplease.com/xquery-update))) and create
38
+ JSON serialization (as with XSLT expressed itself in declarative XML)
39
+ so one can submit and evaluate
40
+ through [HTTPQuery](https://github.com/brettz9/httpquery) (and also
41
+ supply to JSONEditor, etc.). Utilize updating by reference.
42
+
43
+ 8. Demo narrowing to subset of JavaScript (as with `jspe`) to make
44
+ JTLT truly "declarative" as far as freedom from scripting
45
+
46
+ 9. Use [fontoxpath](https://github.com/FontoXML/fontoxpath)
47
+ for XPath 3.1 implementation?
48
+
49
+ ## Possible to-dos
50
+
51
+ 1. Make schema-aware so that templates could target types. Most reusable
52
+ application may be having a type-driven view of a JSON Schema instance
53
+ (e.g., dates could be shown inside a calendar widget). Perhaps this
54
+ schema-awareness could also drive a JSON editor (as with other existing
55
+ projects) (even using same API as JSONEditor?) (or type-aware filtered
56
+ search/raw queries). This would help not only for editors which edit a
57
+ JSON file in full, but also for providing schema paths or other identifiers
58
+ so that a transformed/queried subset of a file (or joining of multiple
59
+ files) could point the way for edited contents to be saved back to the
60
+ correct JSON file and position in the JSON file.
61
+
62
+ 2. Add a [non-eval PR for JSONPath](https://github.com/s3u/JSONPath/pull/4).
63
+ The OR condition (outside of filters) is another important feature as
64
+ would be schema-aware path results.
65
+
66
+ 3. Allow hybrid JSON/[Jamilih](https://github.com/brettz9/jamilih) or
67
+ JSON/(X)HTML/XML so that one can add
68
+ XPath or query into HTML in a relevant manner
69
+
70
+ 4. Support pull parsing/streaming? Pass `done()` function to templates to
71
+ signal completion?
72
+
73
+ 5. Support Promise API in addition to callbacks (reconcile with
74
+ current chaining; see also XQuery FLWOR to-do)
75
+
76
+ 6. Add [XQuery Functions](https://code.google.com/p/jsxqueryparser/source/browse/trunk/jsxqueryparser/XQueryParser.js#1768)
77
+ (also supporting DOM and JSON where possible) as plug-in (also any
78
+ missing from XSLT/XQuery 3.0). Also add, if not present among these
79
+ functions (or in XQuery), add equivalents to XSLT's
80
+ `document()` and `unparsed-text()` for allowing non-JSON file
81
+ retrieval (as well as variables/parameters) and also methods for
82
+ iterating or retrieving IndexedDB, `localStorage`, and cookies
83
+ (names, keys and values).
84
+
85
+ 7. Add `outputType` which uses a DOM joiner but allows specialized
86
+ serialized output (e.g., pretty-printed HTML) so the users
87
+ don't need to build it themselves (likewise with stringified
88
+ JSON output).
89
+
90
+ 8. See code for other possible to-dos
91
+
92
+ 9. Consider implementing the following elements from <https://www.w3.org/TR/xslt20/>
93
+ which are not yet implemented.
94
+
95
+ "xsl:analyze-string",
96
+ "xsl:apply-imports",
97
+ ~~"xsl:apply-templates",~~
98
+ ~~"xsl:attribute",~~
99
+ "xsl:attribute-set",
100
+ ~~"xsl:call-template",~~
101
+ "xsl:character-map",
102
+ ~~"xsl:choose",~~
103
+ ~~"xsl:comment",~~
104
+ ~~"xsl:copy",~~
105
+ ~~"xsl:copy-of",~~
106
+ "xsl:decimal-format",
107
+ ~~"xsl:document",~~
108
+ ~~"xsl:element",~~
109
+ "xsl:fallback",
110
+ ~~"xsl:for-each",~~
111
+ "xsl:for-each-group",
112
+ "xsl:function",
113
+ ~~"xsl:if",~~
114
+ "xsl:import",
115
+ "xsl:import-schema",
116
+ "xsl:include",
117
+ ~~"xsl:key",~~
118
+ "xsl:matching-substring",
119
+ ~~"xsl:message",~~
120
+ "xsl:namespace",
121
+ "xsl:namespace-alias",
122
+ "xsl:next-match",
123
+ "xsl:non-matching-substring",
124
+ "xsl:number",
125
+ ~~"xsl:otherwise",~~
126
+ ~~"xsl:output",~~
127
+ "xsl:output-character",
128
+ "xsl:param",
129
+ "xsl:perform-sort",
130
+ "xsl:preserve-space",
131
+ ~~"xsl:processing-instruction",~~
132
+ ~~"xsl:result-document",~~
133
+ "xsl:sequence",
134
+ ~~"xsl:sort",~~
135
+ "xsl:strip-space",
136
+ ~~"xsl:stylesheet",~~
137
+ ~~"xsl:template",~~
138
+ ~~"xsl:text",~~
139
+ ~~"xsl:transform",~~
140
+ ~~"xsl:value-of",~~
141
+ ~~"xsl:variable",~~
142
+ ~~"xsl:when",~~
143
+ ~~"xsl:with-param"~~
144
+