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
@@ -7,25 +7,25 @@ import JSONPathTransformerContext from './JSONPathTransformerContext.js';
7
7
  * optional `mode`), sorts by priority, and invokes the winning template.
8
8
  * If no template matches, built-in default rules emulate XSLT-like behavior
9
9
  * for objects, arrays, scalars, etc.
10
+ * @template T
10
11
  */
11
12
  class JSONPathTransformer {
12
13
  /**
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
14
+ * @param {import('./JSONPathTransformerContext.js').
15
+ * JSONPathTransformerContextConfig<T>} config - Configuration object
17
16
  */
18
17
  constructor (config) {
19
18
  let map = /** @type {Record<string, boolean>} */ ({});
20
19
  this._config = config;
21
- /** @type {any[]} */
20
+ /** @type {import('./index.js').JSONPathTemplateObject<T>[]} */
22
21
  this.rootTemplates = [];
23
- this.templates = config.templates;
24
- this.templates = this.templates.map(function (template) {
22
+ this.templates = config.templates.map(function (template) {
25
23
  if (Array.isArray(template)) {
26
24
  // Todo: We could allow a third argument (at beginning or
27
25
  // end?) to represent template name
28
- return {path: template[0], template: template[1]};
26
+ return /** @type {import('./index.js').JSONPathTemplateObject<T>} */ (
27
+ {path: template[0], template: template[1]}
28
+ );
29
29
  }
30
30
  return template;
31
31
  });
@@ -33,7 +33,8 @@ class JSONPathTransformer {
33
33
  if (template.name && map[template.name]) {
34
34
  throw new Error('Templates must all have different names.');
35
35
  }
36
- map[template.name] = true;
36
+ map[String(template.name)] = true;
37
+ // Only check for root templates if path is defined
37
38
  if (template.path === '$') {
38
39
  // eslint-disable-next-line unicorn/prefer-spread -- Refactor
39
40
  this.rootTemplates = this.rootTemplates.concat(templates.splice(i, 1));
@@ -55,12 +56,12 @@ class JSONPathTransformer {
55
56
  }
56
57
 
57
58
  /**
58
- * @param {string} mode - Transformation mode
59
- * @returns {*} The transformation result
59
+ * @param {string} [mode] - Transformation mode
60
+ * @returns {import('./index.js').ResultType<T>} The transformation result
60
61
  */
61
62
  transform (mode) {
62
63
  const jte = new JSONPathTransformerContext(
63
- /** @type {any} */ (this._config), this.templates
64
+ this._config, this.templates
64
65
  );
65
66
  const len = this.rootTemplates.length;
66
67
  const templateObj = len
@@ -69,13 +70,24 @@ class JSONPathTransformer {
69
70
  if (len > 1) {
70
71
  this._triggerEqualPriorityError();
71
72
  }
72
- const ret = templateObj.template.call(jte, undefined, {mode});
73
+ const ret = /** @type {import('./index.js').JSONPathTemplateObject<T>} */ (
74
+ templateObj
75
+ ).template.call(jte, undefined, {mode});
73
76
  if (typeof ret !== 'undefined') {
74
77
  // Will vary by jte._config.outputType
75
- /** @type {any} */ (jte)._getJoiningTransformer().append(ret);
78
+ // After the undefined check, ret is ResultType<T>
79
+ const joiner = jte._getJoiningTransformer();
80
+ if (typeof ret === 'string' ||
81
+ (typeof ret === 'object' && ret !== null && 'nodeType' in ret)) {
82
+ joiner.append(/** @type {string|Node} */ (ret));
83
+ } else {
84
+ /** @type {import('./JSONJoiningTransformer.js').default} */ (
85
+ joiner
86
+ ).append(ret);
87
+ }
76
88
  }
77
89
  const result = jte.getOutput();
78
- return result;
90
+ return /** @type {import('./index.js').ResultType<T>} */ (result);
79
91
  }
80
92
 
81
93
  /**
@@ -91,21 +103,24 @@ class JSONPathTransformer {
91
103
  }
92
104
 
93
105
  // To-do: Express as JSONPath expressions?
106
+
94
107
  static DefaultTemplateRules = {
95
108
  transformRoot: {
96
109
  /**
97
- * @param {*} value - Value
98
- * @param {{mode: string}} cfg - Configuration
110
+ * @template U
111
+ * @this {JSONPathTransformerContext<U>}
112
+ * @param {any} value - Value
113
+ * @param {{mode?: string}} cfg - Configuration
99
114
  * @returns {void}
100
115
  */
101
116
  template (value, cfg) {
102
- /** @type {any} */ (this).applyTemplates(null, cfg.mode);
117
+ this.applyTemplates(null, cfg.mode);
103
118
  }
104
119
  },
105
120
  transformPropertyNames: {
106
121
  /**
107
- * @param {*} value - Current context value
108
- * @returns {*}
122
+ * @param {any} value - Current context value
123
+ * @returns {any}
109
124
  */
110
125
  template (value) {
111
126
  // Emit property names for the current object context
@@ -117,36 +132,39 @@ class JSONPathTransformer {
117
132
  },
118
133
  transformObjects: {
119
134
  /**
120
- * @param {*} value - Value
121
- * @param {{mode: string}} cfg - Configuration
135
+ * @this {JSONPathTransformerContext}
136
+ * @param {any} value - Value
137
+ * @param {{mode?: string}} cfg - Configuration
122
138
  * @returns {void}
123
139
  */
124
140
  template (value, cfg) {
125
- /** @type {any} */ (this).applyTemplates(null, cfg.mode);
141
+ this.applyTemplates(null, cfg.mode);
126
142
  }
127
143
  },
128
144
  transformArrays: {
129
145
  /**
130
- * @param {*} value - Value
131
- * @param {{mode: string}} cfg - Configuration
146
+ * @this {JSONPathTransformerContext}
147
+ * @param {any} value - Value
148
+ * @param {{mode?: string}} cfg - Configuration
132
149
  * @returns {void}
133
150
  */
134
151
  template (value, cfg) {
135
- /** @type {any} */ (this).applyTemplates(null, cfg.mode);
152
+ this.applyTemplates(null, cfg.mode);
136
153
  }
137
154
  },
138
155
  transformScalars: {
139
156
  /**
140
- * @returns {*}
157
+ * @this {JSONPathTransformerContext}
158
+ * @returns {JSONPathTransformerContext}
141
159
  */
142
160
  template () {
143
- return /** @type {any} */ (this).valueOf({select: '.'});
161
+ return this.valueOf({select: '.'});
144
162
  }
145
163
  },
146
164
  transformFunctions: {
147
165
  /**
148
- * @param {Function} value - Function at current context
149
- * @returns {*}
166
+ * @param {( ...args: any[]) => any} value - Function at current context
167
+ * @returns {any}
150
168
  */
151
169
  template (value) {
152
170
  // Call the function and return its result