jtlt 0.12.0 → 0.13.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 +5 -0
- package/README.md +9 -5
- package/demo/calltemplate-params-demo.js +19 -15
- package/demo/codemirror.esm.js +140 -70
- package/demo/codemirror.js +9 -5
- package/demo/index.js +2 -1
- package/demo/vendor/fontoxpath/dist/fontoxpath.esm.js +508 -499
- package/demo/vendor/jamilih/dist/jml.mjs +516 -225
- package/demo/vendor/jsonpath-plus/dist/index-browser-esm.js +11 -5
- package/dist/AbstractJoiningTransformer.d.ts +12 -20
- package/dist/AbstractJoiningTransformer.d.ts.map +1 -1
- package/dist/DOMJoiningTransformer.d.ts +502 -19
- package/dist/DOMJoiningTransformer.d.ts.map +1 -1
- package/dist/JSONJoiningTransformer.d.ts +41 -25
- package/dist/JSONJoiningTransformer.d.ts.map +1 -1
- package/dist/JSONPathTransformer.d.ts +20 -20
- package/dist/JSONPathTransformer.d.ts.map +1 -1
- package/dist/JSONPathTransformerContext.d.ts +103 -80
- package/dist/JSONPathTransformerContext.d.ts.map +1 -1
- package/dist/StringJoiningTransformer.d.ts +42 -28
- package/dist/StringJoiningTransformer.d.ts.map +1 -1
- package/dist/XPathTransformer.d.ts +11 -11
- package/dist/XPathTransformer.d.ts.map +1 -1
- package/dist/XPathTransformerContext.d.ts +47 -45
- package/dist/XPathTransformerContext.d.ts.map +1 -1
- package/dist/XSLTStyleJSONPathResolver.d.ts +1 -1
- package/dist/XSLTStyleJSONPathResolver.d.ts.map +1 -1
- package/dist/index-browser.d.ts +2 -2
- package/dist/index-browser.d.ts.map +1 -1
- package/dist/index-node.d.ts +2 -2
- package/dist/index-node.d.ts.map +1 -1
- package/dist/index.d.ts +126 -167
- package/dist/index.d.ts.map +1 -1
- package/docs/API.expanded.md +6 -4
- package/docs/API.md +1 -1
- package/docs/TO-DO.md +4 -2
- package/eslint.config.js +17 -1
- package/package.json +23 -22
- package/pnpm-workspace.yaml +32 -4
- package/rollup.config.js +42 -0
- package/src/AbstractJoiningTransformer.js +8 -1
- package/src/DOMJoiningTransformer.js +56 -27
- package/src/JSONJoiningTransformer.js +64 -44
- package/src/JSONPathTransformer.js +86 -85
- package/src/JSONPathTransformerContext.js +95 -48
- package/src/StringJoiningTransformer.js +48 -23
- package/src/XPathTransformer.js +18 -14
- package/src/XPathTransformerContext.js +173 -123
- package/src/index-browser.js +1 -0
- package/src/index-node.js +2 -0
- package/src/index.js +125 -68
- package/test.html +17 -0
- package/test.js +45 -0
- package/tsconfig-prod.json +1 -0
- package/tsconfig.json +3 -2
- package/dist/types.d.ts +0 -204
- package/dist/types.d.ts.map +0 -1
package/eslint.config.js
CHANGED
|
@@ -16,12 +16,17 @@ export default [
|
|
|
16
16
|
|
|
17
17
|
// Temporary only:
|
|
18
18
|
'no-unused-vars': 0,
|
|
19
|
+
'unicorn/prefer-private-class-fields': 0,
|
|
20
|
+
'unicorn/no-undeclared-class-members': 0,
|
|
19
21
|
|
|
20
22
|
// AI was frequently making egregious mistakes here, so make fixable
|
|
21
23
|
'jsdoc/check-alignment': 'error',
|
|
22
24
|
|
|
23
25
|
// We frequently use callbacks for nested interactions
|
|
24
|
-
'promise/prefer-await-to-callbacks': 0
|
|
26
|
+
'promise/prefer-await-to-callbacks': 0,
|
|
27
|
+
|
|
28
|
+
// A strong basis of this library is being able to reference `this`
|
|
29
|
+
'unicorn/no-this-outside-of-class': 0
|
|
25
30
|
}
|
|
26
31
|
},
|
|
27
32
|
{
|
|
@@ -33,5 +38,16 @@ export default [
|
|
|
33
38
|
'no-undef': 'off',
|
|
34
39
|
'sonarjs/no-global-this': 'off'
|
|
35
40
|
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
files: ['test/**/*.js', 'test.js'],
|
|
44
|
+
rules: {
|
|
45
|
+
'unicorn/prefer-https': 0, // Old namespaces
|
|
46
|
+
// Too many are JSON properties called "children"
|
|
47
|
+
'unicorn/better-dom-traversing': 0,
|
|
48
|
+
'mocha/handle-done-callback': 0, // Buggy?
|
|
49
|
+
'mocha/no-done-twice': 0,
|
|
50
|
+
'mocha/no-code-after-done': 0 // Buggy
|
|
51
|
+
}
|
|
36
52
|
}
|
|
37
53
|
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jtlt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Brett Zamir",
|
|
6
6
|
"contributors": [],
|
|
@@ -25,39 +25,40 @@
|
|
|
25
25
|
"url": "https://github.com/brettz9/jtlt.git"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@codemirror/lang-javascript": "^6.2.
|
|
28
|
+
"@codemirror/lang-javascript": "^6.2.5",
|
|
29
29
|
"@codemirror/lang-json": "^6.0.2",
|
|
30
30
|
"@codemirror/lang-xml": "^6.1.0",
|
|
31
|
-
"@codemirror/language": "^6.
|
|
32
|
-
"@codemirror/state": "^6.
|
|
31
|
+
"@codemirror/language": "^6.12.4",
|
|
32
|
+
"@codemirror/state": "^6.7.1",
|
|
33
33
|
"@lezer/highlight": "^1.2.3",
|
|
34
34
|
"codemirror": "^6.0.2",
|
|
35
|
-
"fontoxpath": "^3.
|
|
36
|
-
"jamilih": "0.
|
|
37
|
-
"jhtml": "0.7.
|
|
38
|
-
"jsdom": "
|
|
39
|
-
"jsonpath-plus": "10.
|
|
35
|
+
"fontoxpath": "^3.34.0",
|
|
36
|
+
"jamilih": "0.69.0",
|
|
37
|
+
"jhtml": "0.7.3",
|
|
38
|
+
"jsdom": "30.0.1",
|
|
39
|
+
"jsonpath-plus": "10.4.0",
|
|
40
40
|
"prsc": "^4.0.0",
|
|
41
|
-
"simple-get-json": "
|
|
41
|
+
"simple-get-json": "11.0.1",
|
|
42
42
|
"whynot": "^5.0.0",
|
|
43
43
|
"xpath2.js": "1.0.0-alpha-6",
|
|
44
44
|
"xspattern": "^3.1.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@arethetypeswrong/cli": "^0.18.
|
|
48
|
-
"@node-static/node-static": "^0.
|
|
47
|
+
"@arethetypeswrong/cli": "^0.18.5",
|
|
48
|
+
"@node-static/node-static": "^0.9.1",
|
|
49
49
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
50
50
|
"@types/chai": "^5.2.3",
|
|
51
|
-
"@types/jsdom": "^
|
|
51
|
+
"@types/jsdom": "^30.0.0",
|
|
52
52
|
"@types/mocha": "^10.0.10",
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"eslint
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
53
|
+
"baseline-browser-mapping": "^2.11.19",
|
|
54
|
+
"c8": "^12.0.0",
|
|
55
|
+
"chai": "^6.2.2",
|
|
56
|
+
"eslint": "^10.9.1",
|
|
57
|
+
"eslint-config-ash-nazg": "^42.6.0",
|
|
58
|
+
"mocha": "^11.8.0",
|
|
59
|
+
"open": "^11.0.1",
|
|
60
|
+
"rollup": "^4.63.0",
|
|
61
|
+
"typescript": "^7.0.2"
|
|
61
62
|
},
|
|
62
63
|
"bugs": "https://github.com/brettz9/jtlt/issues",
|
|
63
64
|
"description": "Uses an approach similar to [XSLT](https://www.w3.org/Style/XSL/) for declarative, linear declaration of templates, but with JSON or JavaScript object data sources. As with XSLT, can be transformed into different formats (e.g., HTML strings, JSON, DOM objects, etc.).",
|
|
@@ -69,7 +70,7 @@
|
|
|
69
70
|
],
|
|
70
71
|
"scripts": {
|
|
71
72
|
"start": "open http://localhost:8021/demo/ && static -p 8021",
|
|
72
|
-
"attw": "attw --pack",
|
|
73
|
+
"attw": "attw --pack . --profile esm-only",
|
|
73
74
|
"tsc": "tsc",
|
|
74
75
|
"build": "tsc -p tsconfig-prod.json && npm run rollup",
|
|
75
76
|
"rollup": "rollup -c",
|
package/pnpm-workspace.yaml
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
allowBuilds:
|
|
2
|
+
is-hidden-file: true
|
|
3
|
+
libxmljs: true
|
|
4
|
+
unrs-resolver: true
|
|
5
|
+
minimumReleaseAgeExclude:
|
|
6
|
+
- '@rollup/rollup-android-arm-eabi@4.63.0'
|
|
7
|
+
- '@rollup/rollup-android-arm64@4.63.0'
|
|
8
|
+
- '@rollup/rollup-darwin-arm64@4.63.0'
|
|
9
|
+
- '@rollup/rollup-darwin-x64@4.63.0'
|
|
10
|
+
- '@rollup/rollup-freebsd-arm64@4.63.0'
|
|
11
|
+
- '@rollup/rollup-freebsd-x64@4.63.0'
|
|
12
|
+
- '@rollup/rollup-linux-arm-gnueabihf@4.63.0'
|
|
13
|
+
- '@rollup/rollup-linux-arm-musleabihf@4.63.0'
|
|
14
|
+
- '@rollup/rollup-linux-arm64-gnu@4.63.0'
|
|
15
|
+
- '@rollup/rollup-linux-arm64-musl@4.63.0'
|
|
16
|
+
- '@rollup/rollup-linux-loong64-gnu@4.63.0'
|
|
17
|
+
- '@rollup/rollup-linux-loong64-musl@4.63.0'
|
|
18
|
+
- '@rollup/rollup-linux-ppc64-gnu@4.63.0'
|
|
19
|
+
- '@rollup/rollup-linux-ppc64-musl@4.63.0'
|
|
20
|
+
- '@rollup/rollup-linux-riscv64-gnu@4.63.0'
|
|
21
|
+
- '@rollup/rollup-linux-riscv64-musl@4.63.0'
|
|
22
|
+
- '@rollup/rollup-linux-s390x-gnu@4.63.0'
|
|
23
|
+
- '@rollup/rollup-linux-x64-gnu@4.63.0'
|
|
24
|
+
- '@rollup/rollup-linux-x64-musl@4.63.0'
|
|
25
|
+
- '@rollup/rollup-openbsd-x64@4.63.0'
|
|
26
|
+
- '@rollup/rollup-openharmony-arm64@4.63.0'
|
|
27
|
+
- '@rollup/rollup-win32-arm64-msvc@4.63.0'
|
|
28
|
+
- '@rollup/rollup-win32-ia32-msvc@4.63.0'
|
|
29
|
+
- '@rollup/rollup-win32-x64-gnu@4.63.0'
|
|
30
|
+
- '@rollup/rollup-win32-x64-msvc@4.63.0'
|
|
31
|
+
- rollup@4.63.0
|
|
32
|
+
- jhtml@0.7.2 || 0.7.3
|
package/rollup.config.js
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
import {nodeResolve} from '@rollup/plugin-node-resolve';
|
|
2
2
|
|
|
3
|
+
// Store resolved paths for deduplication
|
|
4
|
+
const resolvedCodemirror = new Map();
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @returns {import('rollup').Plugin}
|
|
8
|
+
*/
|
|
9
|
+
function dedupeCodemirror () {
|
|
10
|
+
return {
|
|
11
|
+
name: 'dedupe-codemirror',
|
|
12
|
+
/**
|
|
13
|
+
* @param {string} source
|
|
14
|
+
* @param {string|undefined} importer
|
|
15
|
+
* @param {any} options
|
|
16
|
+
* @returns {Promise<string|null>|null}
|
|
17
|
+
*/
|
|
18
|
+
resolveId (source, importer, options) {
|
|
19
|
+
if (source === 'codemirror' ||
|
|
20
|
+
source.startsWith('@codemirror/') ||
|
|
21
|
+
source.startsWith('@lezer/')
|
|
22
|
+
) {
|
|
23
|
+
if (!resolvedCodemirror.has(source)) {
|
|
24
|
+
/* eslint-disable promise/prefer-await-to-then -- sync */
|
|
25
|
+
const promise = this.resolve(
|
|
26
|
+
source, importer, {skipSelf: true, ...options}
|
|
27
|
+
).then(
|
|
28
|
+
/**
|
|
29
|
+
* @param {any} res
|
|
30
|
+
* @returns {string|null}
|
|
31
|
+
*/
|
|
32
|
+
(res) => (res ? res.id : null)
|
|
33
|
+
);
|
|
34
|
+
/* eslint-enable promise/prefer-await-to-then -- sync */
|
|
35
|
+
resolvedCodemirror.set(source, promise);
|
|
36
|
+
}
|
|
37
|
+
return resolvedCodemirror.get(source);
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
3
44
|
export default {
|
|
4
45
|
input: 'demo/codemirror.js',
|
|
5
46
|
output: {
|
|
@@ -8,6 +49,7 @@ export default {
|
|
|
8
49
|
banner: '// Do not edit this file; it was auto-generated'
|
|
9
50
|
},
|
|
10
51
|
plugins: [
|
|
52
|
+
dedupeCodemirror(),
|
|
11
53
|
nodeResolve()
|
|
12
54
|
]
|
|
13
55
|
};
|
|
@@ -212,6 +212,8 @@ class AbstractJoiningTransformer {
|
|
|
212
212
|
if (!name.includes(':') && !name.startsWith('Q{')) {
|
|
213
213
|
throw new Error(
|
|
214
214
|
`Function name "${name}" must be in a namespace ` +
|
|
215
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
216
|
+
// eslint-disable-next-line unicorn/no-incorrect-template-string-interpolation -- Not an HTML template
|
|
215
217
|
`(use prefix:name or Q{uri}name)`
|
|
216
218
|
);
|
|
217
219
|
}
|
|
@@ -406,7 +408,12 @@ class AbstractJoiningTransformer {
|
|
|
406
408
|
_replaceCharacterMaps (str) {
|
|
407
409
|
this._outputConfig?.useCharacterMaps?.forEach((name) => {
|
|
408
410
|
this._characterMap[name].forEach(({character, string}) => {
|
|
409
|
-
str = str.replaceAll(
|
|
411
|
+
str = str.replaceAll(
|
|
412
|
+
character,
|
|
413
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
414
|
+
// eslint-disable-next-line unicorn/no-unsafe-string-replacement -- Safe with replacement
|
|
415
|
+
string.replaceAll('$', '$$$$')
|
|
416
|
+
);
|
|
410
417
|
});
|
|
411
418
|
});
|
|
412
419
|
return str;
|
|
@@ -7,6 +7,7 @@ import AbstractJoiningTransformer from './AbstractJoiningTransformer.js';
|
|
|
7
7
|
* @returns {void}
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
/* eslint-disable @stylistic/max-len -- Long */
|
|
10
11
|
/**
|
|
11
12
|
* Joining transformer that accumulates into a DOM tree.
|
|
12
13
|
*
|
|
@@ -15,14 +16,35 @@ import AbstractJoiningTransformer from './AbstractJoiningTransformer.js';
|
|
|
15
16
|
* attribute(), and text()), though string/number/boolean will append text
|
|
16
17
|
* nodes for convenience.
|
|
17
18
|
* @extends {AbstractJoiningTransformer<"dom">}
|
|
19
|
+
* @template {import('./AbstractJoiningTransformer.js').DOMJoiningTransformerConfig} [TConfig=import('./AbstractJoiningTransformer.js').DOMJoiningTransformerConfig]
|
|
18
20
|
*/
|
|
19
21
|
class DOMJoiningTransformer extends AbstractJoiningTransformer {
|
|
22
|
+
/* eslint-enable @stylistic/max-len -- Long */
|
|
20
23
|
/**
|
|
21
24
|
* @param {DocumentFragment|Element} o - Initial DOM node
|
|
22
25
|
* @param {import('./AbstractJoiningTransformer.js').
|
|
23
26
|
* DOMJoiningTransformerConfig} cfg - Configuration object
|
|
24
27
|
*/
|
|
28
|
+
|
|
29
|
+
/* eslint-disable @stylistic/max-len -- Long */
|
|
30
|
+
/**
|
|
31
|
+
* @template {import('./AbstractJoiningTransformer.js').DOMJoiningTransformerConfig} T
|
|
32
|
+
* @param {DocumentFragment|Element|undefined} dom - DOM element or fragment
|
|
33
|
+
* @param {T} cfg - Configuration options
|
|
34
|
+
* @returns {DOMJoiningTransformer<T>}
|
|
35
|
+
*/
|
|
36
|
+
static create (dom, cfg) {
|
|
37
|
+
/* eslint-enable @stylistic/max-len -- Long */
|
|
38
|
+
return new DOMJoiningTransformer(dom, cfg);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* eslint-disable @stylistic/max-len -- Long */
|
|
42
|
+
/**
|
|
43
|
+
* @param {DocumentFragment|Element|undefined} o - DOM element or fragment
|
|
44
|
+
* @param {import('./AbstractJoiningTransformer.js').DOMJoiningTransformerConfig} cfg - Configuration options
|
|
45
|
+
*/
|
|
25
46
|
constructor (o, cfg) {
|
|
47
|
+
/* eslint-enable @stylistic/max-len -- Long */
|
|
26
48
|
super(cfg);
|
|
27
49
|
this._dom = o || cfg.document.createDocumentFragment();
|
|
28
50
|
/** @type {any} */
|
|
@@ -62,13 +84,16 @@ class DOMJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
62
84
|
}
|
|
63
85
|
|
|
64
86
|
/**
|
|
65
|
-
* @returns {
|
|
87
|
+
* @returns {TConfig['exposeDocuments'] extends true ?
|
|
88
|
+
* XMLDocument[] : DocumentFragment|Element}
|
|
66
89
|
*/
|
|
67
90
|
get () {
|
|
91
|
+
/* eslint-disable @stylistic/max-len -- Long */
|
|
68
92
|
if (this._cfg.exposeDocuments) {
|
|
69
|
-
return this._docs;
|
|
93
|
+
return /** @type {TConfig['exposeDocuments'] extends true ? XMLDocument[] : DocumentFragment | Element} */ (/** @type {unknown} */ (this._docs));
|
|
70
94
|
}
|
|
71
|
-
return this._dom;
|
|
95
|
+
return /** @type {TConfig['exposeDocuments'] extends true ? XMLDocument[] : DocumentFragment | Element} */ (/** @type {unknown} */ (this._dom));
|
|
96
|
+
/* eslint-enable @stylistic/max-len -- Long */
|
|
72
97
|
}
|
|
73
98
|
|
|
74
99
|
/**
|
|
@@ -93,7 +118,8 @@ class DOMJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
93
118
|
|
|
94
119
|
/**
|
|
95
120
|
* @param {Record<string, unknown>} obj - Object to serialize
|
|
96
|
-
* @param {(this: DOMJoiningTransformer) => void} [cb] - Callback
|
|
121
|
+
* @param {((this: DOMJoiningTransformer) => void)|null} [cb] - Callback
|
|
122
|
+
* function.
|
|
97
123
|
* @param {any[]} [usePropertySets] - Property sets to use
|
|
98
124
|
* @param {Record<string, unknown>} [propSets] - Additional property sets
|
|
99
125
|
* @returns {DOMJoiningTransformer}
|
|
@@ -234,6 +260,7 @@ class DOMJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
234
260
|
* @param {Record<string, string>} atts
|
|
235
261
|
* @param {(Node|string)[]} childNodes
|
|
236
262
|
* @param {(this: DOMJoiningTransformer) => void} cb
|
|
263
|
+
* @param {string[]} [useAttributeSets] - Attribute set names to apply
|
|
237
264
|
* @returns {DOMJoiningTransformer}
|
|
238
265
|
*/
|
|
239
266
|
/**
|
|
@@ -339,12 +366,10 @@ class DOMJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
339
366
|
({xmlns} = atts ?? {});
|
|
340
367
|
}
|
|
341
368
|
|
|
342
|
-
const doc =
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
dtd
|
|
347
|
-
)
|
|
369
|
+
const doc = this._cfg.document.implementation.createDocument(
|
|
370
|
+
xmlns ?? null,
|
|
371
|
+
elementName,
|
|
372
|
+
dtd
|
|
348
373
|
);
|
|
349
374
|
/* c8 ignore stop */
|
|
350
375
|
|
|
@@ -381,13 +406,15 @@ class DOMJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
381
406
|
// Apply attribute sets if specified
|
|
382
407
|
if (useAttributeSets && useAttributeSets.length) {
|
|
383
408
|
useAttributeSets.forEach((setName) => {
|
|
384
|
-
if (this._attributeSet
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
409
|
+
if (Object.hasOwn(this._attributeSet, setName)) {
|
|
410
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
411
|
+
// eslint-disable-next-line unicorn/no-unreadable-for-of-expression -- Long
|
|
412
|
+
for (const [att, attVal] of Object.entries(
|
|
413
|
+
this._attributeSet[setName]
|
|
414
|
+
)) {
|
|
415
|
+
el.setAttribute(att, this._replaceCharacterMaps(
|
|
416
|
+
attVal
|
|
417
|
+
));
|
|
391
418
|
}
|
|
392
419
|
}
|
|
393
420
|
});
|
|
@@ -431,13 +458,15 @@ class DOMJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
431
458
|
// Apply attribute sets if specified
|
|
432
459
|
if (useAttributeSets && useAttributeSets.length) {
|
|
433
460
|
useAttributeSets.forEach((setName) => {
|
|
434
|
-
if (this._attributeSet
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
461
|
+
if (Object.hasOwn(this._attributeSet, setName)) {
|
|
462
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
463
|
+
// eslint-disable-next-line unicorn/no-unreadable-for-of-expression -- Not complex
|
|
464
|
+
for (const [att, attVal] of Object.entries(
|
|
465
|
+
this._attributeSet[setName]
|
|
466
|
+
)) {
|
|
467
|
+
el.setAttribute(att, this._replaceCharacterMaps(
|
|
468
|
+
attVal
|
|
469
|
+
));
|
|
441
470
|
}
|
|
442
471
|
}
|
|
443
472
|
});
|
|
@@ -673,9 +702,7 @@ class DOMJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
673
702
|
// or extract from the current DOM state
|
|
674
703
|
const resultDoc = this._docs.length > 0
|
|
675
704
|
? /** @type {XMLDocument} */ (this._docs.at(-1))
|
|
676
|
-
:
|
|
677
|
-
this._cfg.document.implementation.createDocument(null, 'root', null)
|
|
678
|
-
);
|
|
705
|
+
: this._cfg.document.implementation.createDocument(null, 'root', null);
|
|
679
706
|
|
|
680
707
|
// Store with metadata, using the output config that was set during callback
|
|
681
708
|
this._resultDocuments.push({
|
|
@@ -700,6 +727,8 @@ class DOMJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
700
727
|
*/
|
|
701
728
|
_usePropertySets (obj, psName) {
|
|
702
729
|
// Merge named property set from this.propertySets into obj
|
|
730
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
731
|
+
// eslint-disable-next-line unicorn/no-computed-property-existence-check -- TS
|
|
703
732
|
if (this.propertySets && this.propertySets[psName]) {
|
|
704
733
|
return {
|
|
705
734
|
...obj,
|
|
@@ -47,6 +47,7 @@ function _makeDatasetAttribute (n0) {
|
|
|
47
47
|
* }} ElementInfo
|
|
48
48
|
*/
|
|
49
49
|
|
|
50
|
+
/* eslint-disable @stylistic/max-len -- Long */
|
|
50
51
|
/**
|
|
51
52
|
* JSON-based joining transformer for building JSON/JavaScript objects.
|
|
52
53
|
*
|
|
@@ -55,14 +56,27 @@ function _makeDatasetAttribute (n0) {
|
|
|
55
56
|
* boolean/null add primitives accordingly. It does not perform HTML escaping
|
|
56
57
|
* or string serialization; it builds real JS values.
|
|
57
58
|
* @extends {AbstractJoiningTransformer<"json">}
|
|
59
|
+
* @template {import('./AbstractJoiningTransformer.js').JSONJoiningTransformerConfig} [TConfig=import('./AbstractJoiningTransformer.js').JSONJoiningTransformerConfig]
|
|
58
60
|
*/
|
|
59
61
|
class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
60
62
|
/**
|
|
61
|
-
* @
|
|
62
|
-
* @param {
|
|
63
|
-
*
|
|
63
|
+
* @template {import('./AbstractJoiningTransformer.js').JSONJoiningTransformerConfig} T
|
|
64
|
+
* @param {any[]|Record<string, unknown>} [o] - Initial JSON object or array
|
|
65
|
+
* @param {T} [cfg] - Configuration options
|
|
66
|
+
* @returns {JSONJoiningTransformer<T>}
|
|
67
|
+
*/
|
|
68
|
+
static create (o, cfg) {
|
|
69
|
+
/* eslint-enable @stylistic/max-len -- Long */
|
|
70
|
+
return new JSONJoiningTransformer(o, cfg);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* eslint-disable @stylistic/max-len -- Long */
|
|
74
|
+
/**
|
|
75
|
+
* @param {any[]|Record<string, unknown>} [o] - Initial JSON object or array
|
|
76
|
+
* @param {import('./AbstractJoiningTransformer.js').JSONJoiningTransformerConfig} [cfg] - Configuration options
|
|
64
77
|
*/
|
|
65
78
|
constructor (o, cfg) {
|
|
79
|
+
/* eslint-enable @stylistic/max-len -- Long */
|
|
66
80
|
super(cfg);
|
|
67
81
|
/** @type {any[]|Record<string, unknown>} */
|
|
68
82
|
this._obj = o || [];
|
|
@@ -119,16 +133,17 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
119
133
|
return this;
|
|
120
134
|
}
|
|
121
135
|
|
|
136
|
+
/* eslint-disable @stylistic/max-len -- Long */
|
|
122
137
|
/**
|
|
123
138
|
* Gets the current object or array. If unwrapSingleResult config option is
|
|
124
139
|
* enabled and the root array contains exactly one element, returns that
|
|
125
140
|
* element directly (unwrapped).
|
|
126
|
-
* @returns {any[]|Record<string, unknown>|any}
|
|
141
|
+
* @returns {TConfig['exposeDocuments'] extends true ? any[] : any[]|Record<string, unknown>|any}
|
|
127
142
|
*/
|
|
128
143
|
get () {
|
|
129
144
|
// If exposeDocuments is set, return the array of documents
|
|
130
145
|
if (this._cfg.exposeDocuments) {
|
|
131
|
-
return this._docs;
|
|
146
|
+
return /** @type {TConfig['exposeDocuments'] extends true ? any[] : any[]|Record<string, unknown>|any} */ (/** @type {unknown} */ (this._docs));
|
|
132
147
|
}
|
|
133
148
|
// Removed this._doc logic; use this._docs only
|
|
134
149
|
// Unwrap single-element arrays at the root level if configured
|
|
@@ -136,7 +151,8 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
136
151
|
Array.isArray(this._obj) && this._obj.length === 1) {
|
|
137
152
|
return this._obj[0];
|
|
138
153
|
}
|
|
139
|
-
return this._obj;
|
|
154
|
+
return /** @type {TConfig['exposeDocuments'] extends true ? any[] : any[]|Record<string, unknown>|any} */ (/** @type {unknown} */ (this._obj));
|
|
155
|
+
/* eslint-enable @stylistic/max-len -- Long */
|
|
140
156
|
}
|
|
141
157
|
|
|
142
158
|
/**
|
|
@@ -166,7 +182,7 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
166
182
|
|
|
167
183
|
/* c8 ignore next 13 -- JSDoc block incorrectly counted as coverable by c8 */
|
|
168
184
|
/**
|
|
169
|
-
* @param {Record<string, unknown>|ObjectCallback} [objOrCb]
|
|
185
|
+
* @param {null|Record<string, unknown>|ObjectCallback} [objOrCb]
|
|
170
186
|
* Seed object or callback.
|
|
171
187
|
* @param {ObjectCallback|any[]} [cbOrUsePropertySets] Callback or sets.
|
|
172
188
|
* @param {any[]|Record<string, unknown>} [usePropertySetsOrPropSets]
|
|
@@ -247,7 +263,7 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
247
263
|
|
|
248
264
|
/**
|
|
249
265
|
* Creates a new array and executes a callback in its context.
|
|
250
|
-
* @param {any[]|ArrayCallback} [arrOrCb] Seed array or callback.
|
|
266
|
+
* @param {any[]|ArrayCallback|null} [arrOrCb] Seed array or callback.
|
|
251
267
|
* @param {ArrayCallback} [cb] Callback when first arg was array.
|
|
252
268
|
* @returns {JSONJoiningTransformer}
|
|
253
269
|
*/
|
|
@@ -424,7 +440,7 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
424
440
|
if (useAttributeSets && useAttributeSets.length) {
|
|
425
441
|
const mergedAtts = {};
|
|
426
442
|
useAttributeSets.forEach((setName) => {
|
|
427
|
-
if (this._attributeSet
|
|
443
|
+
if (Object.hasOwn(this._attributeSet, setName)) {
|
|
428
444
|
Object.assign(mergedAtts, this._attributeSet[setName]);
|
|
429
445
|
}
|
|
430
446
|
});
|
|
@@ -436,11 +452,10 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
436
452
|
!Array.isArray(attsObj.dataset)
|
|
437
453
|
) {
|
|
438
454
|
const ds = attsObj.dataset;
|
|
439
|
-
for (const k
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
}
|
|
455
|
+
for (const [k, val] of Object.entries(ds)) {
|
|
456
|
+
// eslint-disable-next-line unicorn/no-unsafe-string-replacement -- Safe
|
|
457
|
+
const dashed = k.replaceAll(camelCase, _makeDatasetAttribute);
|
|
458
|
+
attsObj['data-' + dashed] = this._replaceCharacterMaps(val);
|
|
444
459
|
}
|
|
445
460
|
delete attsObj.dataset;
|
|
446
461
|
}
|
|
@@ -454,9 +469,9 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
454
469
|
}
|
|
455
470
|
|
|
456
471
|
// Apply character maps to all regular attribute values
|
|
457
|
-
for (const key
|
|
458
|
-
if (
|
|
459
|
-
attsObj[key] = this._replaceCharacterMaps(
|
|
472
|
+
for (const [key, val] of Object.entries(attsObj)) {
|
|
473
|
+
if (typeof val === 'string') {
|
|
474
|
+
attsObj[key] = this._replaceCharacterMaps(val);
|
|
460
475
|
}
|
|
461
476
|
}
|
|
462
477
|
|
|
@@ -493,14 +508,16 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
493
508
|
if (isRoot) {
|
|
494
509
|
// todo: indent, cdataSectionElements
|
|
495
510
|
const {
|
|
496
|
-
omitXmlDeclaration, doctypePublic, doctypeSystem, method
|
|
511
|
+
omitXmlDeclaration, bareDoctype, doctypePublic, doctypeSystem, method
|
|
497
512
|
} = this._outputConfig ?? {};
|
|
498
513
|
|
|
499
|
-
const dtd =
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
514
|
+
const dtd = bareDoctype !== false
|
|
515
|
+
? [{$DOCTYPE: {
|
|
516
|
+
name: elementName,
|
|
517
|
+
publicId: doctypePublic ?? null, // Public ID (optional)
|
|
518
|
+
systemId: doctypeSystem ?? null // System ID (optional)
|
|
519
|
+
}}]
|
|
520
|
+
: [];
|
|
504
521
|
|
|
505
522
|
let xmlDeclaration;
|
|
506
523
|
/* c8 ignore start -- third OR condition short-circuits */
|
|
@@ -520,7 +537,7 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
520
537
|
const doc = {$document: {
|
|
521
538
|
...(xmlDeclaration ? {xmlDeclaration} : {}),
|
|
522
539
|
childNodes: [
|
|
523
|
-
...(method === 'xml' || method === 'xhtml' ?
|
|
540
|
+
...(method === 'xml' || method === 'xhtml' ? dtd : []),
|
|
524
541
|
jmlEl
|
|
525
542
|
]
|
|
526
543
|
}};
|
|
@@ -630,24 +647,25 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
630
647
|
!Array.isArray(val)
|
|
631
648
|
) {
|
|
632
649
|
const datasetObj = /** @type {Record<string, unknown>} */ (val);
|
|
633
|
-
for (const k
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
}
|
|
650
|
+
for (const [k, v] of Object.entries(datasetObj)) {
|
|
651
|
+
// eslint-disable-next-line unicorn/no-unsafe-string-replacement -- Safe
|
|
652
|
+
const dashed = k.replaceAll(camelCase, _makeDatasetAttribute);
|
|
653
|
+
attsObj['data-' + dashed] = this._replaceCharacterMaps(
|
|
654
|
+
/** @type {string} */ (v)
|
|
655
|
+
);
|
|
640
656
|
}
|
|
641
657
|
return this;
|
|
642
658
|
}
|
|
643
659
|
if (name === '$a' && Array.isArray(val)) {
|
|
644
660
|
val.forEach((pair) => {
|
|
645
|
-
if (Array.isArray(pair) && pair.length > 1) {
|
|
646
|
-
|
|
647
|
-
// Track each ordered attribute
|
|
648
|
-
this._trackAttributePrefix(attrName);
|
|
649
|
-
attsObj[attrName] = this._replaceCharacterMaps(pair[1]);
|
|
661
|
+
if (!(Array.isArray(pair) && pair.length > 1)) {
|
|
662
|
+
return;
|
|
650
663
|
}
|
|
664
|
+
|
|
665
|
+
const attrName = String(pair[0]);
|
|
666
|
+
// Track each ordered attribute
|
|
667
|
+
this._trackAttributePrefix(attrName);
|
|
668
|
+
attsObj[attrName] = this._replaceCharacterMaps(pair[1]);
|
|
651
669
|
});
|
|
652
670
|
return this;
|
|
653
671
|
}
|
|
@@ -806,7 +824,7 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
806
824
|
// We have output config but document wasn't pushed to _docs
|
|
807
825
|
// Create the document wrapper manually
|
|
808
826
|
const {
|
|
809
|
-
omitXmlDeclaration, doctypePublic, doctypeSystem, method
|
|
827
|
+
omitXmlDeclaration, bareDoctype, doctypePublic, doctypeSystem, method
|
|
810
828
|
} = this._outputConfig;
|
|
811
829
|
|
|
812
830
|
const elementData = Array.isArray(this._obj) && this._obj.length > 0
|
|
@@ -815,11 +833,13 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
815
833
|
|
|
816
834
|
const elementName = Array.isArray(elementData) ? elementData[0] : 'root';
|
|
817
835
|
|
|
818
|
-
const dtd =
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
836
|
+
const dtd = bareDoctype !== false
|
|
837
|
+
? [{$DOCTYPE: {
|
|
838
|
+
name: elementName,
|
|
839
|
+
publicId: doctypePublic ?? null,
|
|
840
|
+
systemId: doctypeSystem ?? null
|
|
841
|
+
}}]
|
|
842
|
+
: [];
|
|
823
843
|
|
|
824
844
|
let xmlDeclaration;
|
|
825
845
|
/* c8 ignore start -- third OR condition short-circuits */
|
|
@@ -838,7 +858,7 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
838
858
|
resultDoc = {$document: {
|
|
839
859
|
...(xmlDeclaration ? {xmlDeclaration} : {}),
|
|
840
860
|
childNodes: [
|
|
841
|
-
...(method === 'xml' || method === 'xhtml' ?
|
|
861
|
+
...(method === 'xml' || method === 'xhtml' ? dtd : []),
|
|
842
862
|
elementData
|
|
843
863
|
]
|
|
844
864
|
}};
|
|
@@ -872,7 +892,7 @@ class JSONJoiningTransformer extends AbstractJoiningTransformer {
|
|
|
872
892
|
*/
|
|
873
893
|
_usePropertySets (obj, psName) {
|
|
874
894
|
// Merge the named property set (if present) into the provided object
|
|
875
|
-
if (this.propertySets
|
|
895
|
+
if (Object.hasOwn(this.propertySets, psName)) {
|
|
876
896
|
return Object.assign(obj, this.propertySets[psName]);
|
|
877
897
|
}
|
|
878
898
|
return obj;
|