jtlt 0.1.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/.editorconfig +16 -0
- package/CHANGES.md +5 -0
- package/LICENSE-MIT.txt +21 -0
- package/README.md +534 -0
- package/dist/AbstractJoiningTransformer.d.ts +42 -0
- package/dist/AbstractJoiningTransformer.d.ts.map +1 -0
- package/dist/DOMJoiningTransformer.d.ts +113 -0
- package/dist/DOMJoiningTransformer.d.ts.map +1 -0
- package/dist/JSONJoiningTransformer.d.ts +160 -0
- package/dist/JSONJoiningTransformer.d.ts.map +1 -0
- package/dist/JSONPathTransformer.d.ts +95 -0
- package/dist/JSONPathTransformer.d.ts.map +1 -0
- package/dist/JSONPathTransformerContext.d.ts +263 -0
- package/dist/JSONPathTransformerContext.d.ts.map +1 -0
- package/dist/StringJoiningTransformer.d.ts +168 -0
- package/dist/StringJoiningTransformer.d.ts.map +1 -0
- package/dist/XPathTransformer.d.ts +51 -0
- package/dist/XPathTransformer.d.ts.map +1 -0
- package/dist/XPathTransformerContext.d.ts +260 -0
- package/dist/XPathTransformerContext.d.ts.map +1 -0
- package/dist/XSLTStyleJSONPathResolver.d.ts +16 -0
- package/dist/XSLTStyleJSONPathResolver.d.ts.map +1 -0
- package/dist/index.d.ts +168 -0
- package/dist/index.d.ts.map +1 -0
- package/docs/API.expanded.md +263 -0
- package/docs/API.md +69 -0
- package/eslint.config.js +30 -0
- package/package.json +53 -0
- package/pnpm-workspace.yaml +3 -0
- package/src/AbstractJoiningTransformer.js +73 -0
- package/src/DOMJoiningTransformer.js +237 -0
- package/src/JSONJoiningTransformer.js +472 -0
- package/src/JSONPathTransformer.js +159 -0
- package/src/JSONPathTransformerContext.js +807 -0
- package/src/StringJoiningTransformer.js +589 -0
- package/src/XPathTransformer.js +94 -0
- package/src/XPathTransformerContext.js +496 -0
- package/src/XSLTStyleJSONPathResolver.js +39 -0
- package/src/index.js +299 -0
- package/src/types/xpath2-js.d.ts +2 -0
- package/tsconfig-prod.json +19 -0
- package/tsconfig.json +14 -0
- package/typings/xpath2-js.d.ts +2 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import JSONPathTransformerContext from './JSONPathTransformerContext.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Applies named JSONPath-driven templates to JSON data.
|
|
5
|
+
*
|
|
6
|
+
* This engine finds templates whose `path` match the current node (plus an
|
|
7
|
+
* optional `mode`), sorts by priority, and invokes the winning template.
|
|
8
|
+
* If no template matches, built-in default rules emulate XSLT-like behavior
|
|
9
|
+
* for objects, arrays, scalars, etc.
|
|
10
|
+
*/
|
|
11
|
+
class JSONPathTransformer {
|
|
12
|
+
/**
|
|
13
|
+
* @param {object} config - Configuration object
|
|
14
|
+
* @param {boolean} [config.errorOnEqualPriority] - Whether to error on
|
|
15
|
+
* equal priority templates
|
|
16
|
+
* @param {any[]} config.templates - Array of template objects
|
|
17
|
+
*/
|
|
18
|
+
constructor (config) {
|
|
19
|
+
let map = /** @type {Record<string, boolean>} */ ({});
|
|
20
|
+
this._config = config;
|
|
21
|
+
/** @type {any[]} */
|
|
22
|
+
this.rootTemplates = [];
|
|
23
|
+
this.templates = config.templates;
|
|
24
|
+
this.templates = this.templates.map(function (template) {
|
|
25
|
+
if (Array.isArray(template)) {
|
|
26
|
+
// Todo: We could allow a third argument (at beginning or
|
|
27
|
+
// end?) to represent template name
|
|
28
|
+
return {path: template[0], template: template[1]};
|
|
29
|
+
}
|
|
30
|
+
return template;
|
|
31
|
+
});
|
|
32
|
+
this.templates.forEach((template, i, templates) => {
|
|
33
|
+
if (template.name && map[template.name]) {
|
|
34
|
+
throw new Error('Templates must all have different names.');
|
|
35
|
+
}
|
|
36
|
+
map[template.name] = true;
|
|
37
|
+
if (template.path === '$') {
|
|
38
|
+
// eslint-disable-next-line unicorn/prefer-spread -- Refactor
|
|
39
|
+
this.rootTemplates = this.rootTemplates.concat(templates.splice(i, 1));
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
map = /** @type {any} */ (null);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @returns {void}
|
|
47
|
+
*/
|
|
48
|
+
_triggerEqualPriorityError () {
|
|
49
|
+
if (this._config.errorOnEqualPriority) {
|
|
50
|
+
throw new Error(
|
|
51
|
+
'You have configured JSONPathTransformer to throw errors on finding ' +
|
|
52
|
+
'templates of equal priority and these have been found.'
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {string} mode - Transformation mode
|
|
59
|
+
* @returns {*} The transformation result
|
|
60
|
+
*/
|
|
61
|
+
transform (mode) {
|
|
62
|
+
const jte = new JSONPathTransformerContext(
|
|
63
|
+
/** @type {any} */ (this._config), this.templates
|
|
64
|
+
);
|
|
65
|
+
const len = this.rootTemplates.length;
|
|
66
|
+
const templateObj = len
|
|
67
|
+
? this.rootTemplates.pop()
|
|
68
|
+
: JSONPathTransformer.DefaultTemplateRules.transformRoot;
|
|
69
|
+
if (len > 1) {
|
|
70
|
+
this._triggerEqualPriorityError();
|
|
71
|
+
}
|
|
72
|
+
const ret = templateObj.template.call(jte, undefined, {mode});
|
|
73
|
+
if (typeof ret !== 'undefined') {
|
|
74
|
+
// Will vary by jte._config.outputType
|
|
75
|
+
/** @type {any} */ (jte)._getJoiningTransformer().append(ret);
|
|
76
|
+
}
|
|
77
|
+
const result = jte.getOutput();
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {string} select - JSONPath selector
|
|
83
|
+
* @returns {string} Absolute JSONPath
|
|
84
|
+
*/
|
|
85
|
+
static makeJSONPathAbsolute (select) {
|
|
86
|
+
// See todo in JSONPath to avoid need for '$' (but may still need
|
|
87
|
+
// to add ".")
|
|
88
|
+
return select[0] !== '$'
|
|
89
|
+
? ((select[0] === '[' ? '$' : '$.') + select)
|
|
90
|
+
: select;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// To-do: Express as JSONPath expressions?
|
|
94
|
+
static DefaultTemplateRules = {
|
|
95
|
+
transformRoot: {
|
|
96
|
+
/**
|
|
97
|
+
* @param {*} value - Value
|
|
98
|
+
* @param {{mode: string}} cfg - Configuration
|
|
99
|
+
* @returns {void}
|
|
100
|
+
*/
|
|
101
|
+
template (value, cfg) {
|
|
102
|
+
/** @type {any} */ (this).applyTemplates(null, cfg.mode);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
transformPropertyNames: {
|
|
106
|
+
/**
|
|
107
|
+
* @param {*} value - Current context value
|
|
108
|
+
* @returns {*}
|
|
109
|
+
*/
|
|
110
|
+
template (value) {
|
|
111
|
+
// Emit property names for the current object context
|
|
112
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
113
|
+
return Object.keys(value).join('');
|
|
114
|
+
}
|
|
115
|
+
return '';
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
transformObjects: {
|
|
119
|
+
/**
|
|
120
|
+
* @param {*} value - Value
|
|
121
|
+
* @param {{mode: string}} cfg - Configuration
|
|
122
|
+
* @returns {void}
|
|
123
|
+
*/
|
|
124
|
+
template (value, cfg) {
|
|
125
|
+
/** @type {any} */ (this).applyTemplates(null, cfg.mode);
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
transformArrays: {
|
|
129
|
+
/**
|
|
130
|
+
* @param {*} value - Value
|
|
131
|
+
* @param {{mode: string}} cfg - Configuration
|
|
132
|
+
* @returns {void}
|
|
133
|
+
*/
|
|
134
|
+
template (value, cfg) {
|
|
135
|
+
/** @type {any} */ (this).applyTemplates(null, cfg.mode);
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
transformScalars: {
|
|
139
|
+
/**
|
|
140
|
+
* @returns {*}
|
|
141
|
+
*/
|
|
142
|
+
template () {
|
|
143
|
+
return /** @type {any} */ (this).valueOf({select: '.'});
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
transformFunctions: {
|
|
147
|
+
/**
|
|
148
|
+
* @param {Function} value - Function at current context
|
|
149
|
+
* @returns {*}
|
|
150
|
+
*/
|
|
151
|
+
template (value) {
|
|
152
|
+
// Call the function and return its result
|
|
153
|
+
return value();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export default JSONPathTransformer;
|