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.
- package/CHANGES.md +18 -0
- package/README.md +16 -87
- package/demo/calltemplate-params-demo.js +138 -0
- package/demo/index.html +31 -0
- package/demo/index.js +30 -0
- package/demo/xpath2-placeholder.js +1 -0
- package/dist/AbstractJoiningTransformer.d.ts +83 -9
- package/dist/AbstractJoiningTransformer.d.ts.map +1 -1
- package/dist/DOMJoiningTransformer.d.ts +85 -25
- package/dist/DOMJoiningTransformer.d.ts.map +1 -1
- package/dist/JSONJoiningTransformer.d.ts +159 -51
- package/dist/JSONJoiningTransformer.d.ts.map +1 -1
- package/dist/JSONPathTransformer.d.ts +37 -38
- package/dist/JSONPathTransformer.d.ts.map +1 -1
- package/dist/JSONPathTransformerContext.d.ts +247 -121
- package/dist/JSONPathTransformerContext.d.ts.map +1 -1
- package/dist/StringJoiningTransformer.d.ts +132 -41
- package/dist/StringJoiningTransformer.d.ts.map +1 -1
- package/dist/XPathTransformer.d.ts +35 -20
- package/dist/XPathTransformer.d.ts.map +1 -1
- package/dist/XPathTransformerContext.d.ts +191 -99
- package/dist/XPathTransformerContext.d.ts.map +1 -1
- package/dist/index-browser.d.ts +4 -0
- package/dist/index-browser.d.ts.map +1 -0
- package/dist/index-node.d.ts +4 -0
- package/dist/index-node.d.ts.map +1 -0
- package/dist/index.d.ts +330 -57
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts +204 -0
- package/dist/types.d.ts.map +1 -0
- package/docs/API.expanded.md +167 -2
- package/docs/API.md +91 -1
- package/docs/TO-DO.md +144 -0
- package/docs/calltemplate-params.md +251 -0
- package/eslint.config.js +9 -5
- package/package.json +13 -7
- package/pnpm-workspace.yaml +1 -0
- package/src/AbstractJoiningTransformer.js +54 -15
- package/src/DOMJoiningTransformer.js +275 -28
- package/src/JSONJoiningTransformer.js +351 -70
- package/src/JSONPathTransformer.js +48 -30
- package/src/JSONPathTransformerContext.js +308 -104
- package/src/StringJoiningTransformer.js +311 -57
- package/src/XPathTransformer.js +27 -12
- package/src/XPathTransformerContext.js +467 -89
- package/src/index-browser.js +5 -0
- package/src/index-node.js +7 -0
- package/src/index.js +498 -97
- package/typings/xpath2-js.d.ts +40 -1
- 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"}
|
package/docs/API.expanded.md
CHANGED
|
@@ -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
|
|
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(''
|
|
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
|
+
|