@swaggerexpert/jsonpath 1.2.1 → 2.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/README.md +65 -202
- package/cjs/grammar.cjs +17 -17
- package/cjs/index.cjs +5 -5
- package/cjs/parse/callbacks/cst.cjs +0 -4
- package/cjs/parse/index.cjs +10 -12
- package/cjs/parse/{ast/JSONPathQueryCST.cjs → translators/CSTTranslator.cjs} +19 -2
- package/cjs/parse/translators/XMLTranslator.cjs +12 -0
- package/es/grammar.mjs +17 -17
- package/es/index.mjs +2 -2
- package/es/parse/callbacks/cst.mjs +0 -4
- package/es/parse/index.mjs +10 -12
- package/es/parse/{ast/JSONPathQueryCST.mjs → translators/CSTTranslator.mjs} +19 -2
- package/es/parse/translators/XMLTranslator.mjs +7 -0
- package/package.json +1 -1
- package/types/index.d.ts +25 -7
- package/cjs/parse/evaluators/translate.cjs +0 -13
- package/es/parse/evaluators/translate.mjs +0 -9
package/README.md
CHANGED
|
@@ -34,8 +34,10 @@ The development of this library contributed to the identification and formal sub
|
|
|
34
34
|
- [Installation](#installation)
|
|
35
35
|
- [Usage](#usage)
|
|
36
36
|
- [Parsing](#parsing)
|
|
37
|
-
- [
|
|
38
|
-
- [
|
|
37
|
+
- [Normalized paths](#normalized-paths)
|
|
38
|
+
- [Translators](#translators)
|
|
39
|
+
- [CST](#cst-translator)
|
|
40
|
+
- [XML](#xml-translator)
|
|
39
41
|
- [Statistics](#statistics)
|
|
40
42
|
- [Tracing](#tracing)
|
|
41
43
|
- [Errors](#errors)
|
|
@@ -69,231 +71,92 @@ import { parse } from '@swaggerexpert/jsonpath';
|
|
|
69
71
|
const parseResult = parse('$.store.book[0].title');
|
|
70
72
|
```
|
|
71
73
|
|
|
72
|
-
or
|
|
73
|
-
|
|
74
|
-
```js
|
|
75
|
-
import { parse, JSONPathQueryCST } from '@swaggerexpert/jsonpath';
|
|
76
|
-
|
|
77
|
-
const parseResult = parse('$.store.book[0].title', { ast: new JSONPathQueryCST() });
|
|
78
|
-
```
|
|
79
|
-
|
|
80
74
|
**parseResult** variable has the following shape:
|
|
81
75
|
|
|
82
76
|
```
|
|
83
77
|
{
|
|
84
|
-
result:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
length: 21,
|
|
89
|
-
matched: 21,
|
|
90
|
-
maxMatched: 21,
|
|
91
|
-
maxTreeDepth: 21,
|
|
92
|
-
nodeHits: 298
|
|
93
|
-
},
|
|
94
|
-
ast: <JSONPathQueryCST>,
|
|
95
|
-
computed: {
|
|
96
|
-
stack: [],
|
|
97
|
-
root: {
|
|
98
|
-
type: 'jsonpath-query',
|
|
99
|
-
text: '$.store.book[0].title',
|
|
100
|
-
start: 0,
|
|
101
|
-
length: 21,
|
|
102
|
-
children: [
|
|
103
|
-
{
|
|
104
|
-
type: 'root-identifier',
|
|
105
|
-
text: '$',
|
|
106
|
-
start: 0,
|
|
107
|
-
length: 1,
|
|
108
|
-
children: []
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
type: 'segments',
|
|
112
|
-
text: '.store.book[0].title',
|
|
113
|
-
start: 1,
|
|
114
|
-
length: 20,
|
|
115
|
-
children: [
|
|
116
|
-
{
|
|
117
|
-
type: 'segment',
|
|
118
|
-
text: '.store',
|
|
119
|
-
start: 1,
|
|
120
|
-
length: 6,
|
|
121
|
-
children: [
|
|
122
|
-
{
|
|
123
|
-
type: 'child-segment',
|
|
124
|
-
text: '.store',
|
|
125
|
-
start: 1,
|
|
126
|
-
length: 6,
|
|
127
|
-
children: [
|
|
128
|
-
{
|
|
129
|
-
type: 'text',
|
|
130
|
-
text: '.',
|
|
131
|
-
start: 1,
|
|
132
|
-
length: 1,
|
|
133
|
-
children: []
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
type: 'member-name-shorthand',
|
|
137
|
-
text: 'store',
|
|
138
|
-
start: 2,
|
|
139
|
-
length: 5,
|
|
140
|
-
children: []
|
|
141
|
-
}
|
|
142
|
-
]
|
|
143
|
-
}
|
|
144
|
-
]
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
type: 'segment',
|
|
148
|
-
text: '.book',
|
|
149
|
-
start: 7,
|
|
150
|
-
length: 5,
|
|
151
|
-
children: [
|
|
152
|
-
{
|
|
153
|
-
type: 'child-segment',
|
|
154
|
-
text: '.book',
|
|
155
|
-
start: 7,
|
|
156
|
-
length: 5,
|
|
157
|
-
children: [
|
|
158
|
-
{
|
|
159
|
-
type: 'text',
|
|
160
|
-
text: '.',
|
|
161
|
-
start: 7,
|
|
162
|
-
length: 1,
|
|
163
|
-
children: []
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
type: 'member-name-shorthand',
|
|
167
|
-
text: 'book',
|
|
168
|
-
start: 8,
|
|
169
|
-
length: 4,
|
|
170
|
-
children: []
|
|
171
|
-
}
|
|
172
|
-
]
|
|
173
|
-
}
|
|
174
|
-
]
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
type: 'segment',
|
|
178
|
-
text: '[0]',
|
|
179
|
-
start: 12,
|
|
180
|
-
length: 3,
|
|
181
|
-
children: [
|
|
182
|
-
{
|
|
183
|
-
type: 'child-segment',
|
|
184
|
-
text: '[0]',
|
|
185
|
-
start: 12,
|
|
186
|
-
length: 3,
|
|
187
|
-
children: [
|
|
188
|
-
{
|
|
189
|
-
type: 'bracketed-selection',
|
|
190
|
-
text: '[0]',
|
|
191
|
-
start: 12,
|
|
192
|
-
length: 3,
|
|
193
|
-
children: [
|
|
194
|
-
{
|
|
195
|
-
type: 'text',
|
|
196
|
-
text: '[',
|
|
197
|
-
start: 12,
|
|
198
|
-
length: 1,
|
|
199
|
-
children: []
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
type: 'selector',
|
|
203
|
-
text: '0',
|
|
204
|
-
start: 13,
|
|
205
|
-
length: 1,
|
|
206
|
-
children: [
|
|
207
|
-
{
|
|
208
|
-
type: 'index-selector',
|
|
209
|
-
text: '0',
|
|
210
|
-
start: 13,
|
|
211
|
-
length: 1,
|
|
212
|
-
children: []
|
|
213
|
-
}
|
|
214
|
-
]
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
type: 'text',
|
|
218
|
-
text: ']',
|
|
219
|
-
start: 14,
|
|
220
|
-
length: 1,
|
|
221
|
-
children: []
|
|
222
|
-
}
|
|
223
|
-
]
|
|
224
|
-
}
|
|
225
|
-
]
|
|
226
|
-
}
|
|
227
|
-
]
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
type: 'segment',
|
|
231
|
-
text: '.title',
|
|
232
|
-
start: 15,
|
|
233
|
-
length: 6,
|
|
234
|
-
children: [
|
|
235
|
-
{
|
|
236
|
-
type: 'child-segment',
|
|
237
|
-
text: '.title',
|
|
238
|
-
start: 15,
|
|
239
|
-
length: 6,
|
|
240
|
-
children: [
|
|
241
|
-
{
|
|
242
|
-
type: 'text',
|
|
243
|
-
text: '.',
|
|
244
|
-
start: 15,
|
|
245
|
-
length: 1,
|
|
246
|
-
children: []
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
type: 'member-name-shorthand',
|
|
250
|
-
text: 'title',
|
|
251
|
-
start: 16,
|
|
252
|
-
length: 5,
|
|
253
|
-
children: []
|
|
254
|
-
}
|
|
255
|
-
]
|
|
256
|
-
}
|
|
257
|
-
]
|
|
258
|
-
}
|
|
259
|
-
]
|
|
260
|
-
}
|
|
261
|
-
]
|
|
262
|
-
}
|
|
263
|
-
}
|
|
78
|
+
result: <ParseResult['result]>,
|
|
79
|
+
tree: <ParseResult['tree']>,
|
|
80
|
+
stats: <ParseResult['stats']>,
|
|
81
|
+
trace: <ParseResult['trace']>,
|
|
264
82
|
}
|
|
265
83
|
```
|
|
266
84
|
|
|
267
|
-
|
|
85
|
+
[TypeScript typings](https://github.com/swaggerexpert/jsonpath/blob/main/types/index.d.ts) are available for all fields attached to parse result object returned by the `parse` function.
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
##### Normalized paths
|
|
89
|
+
|
|
90
|
+
[comment]: <> (SPDX-FileCopyrightText: Copyright (c) 2024 IETF Trust and the persons identified as the document authors. All rights reserved.)
|
|
91
|
+
[comment]: <> (SPDX-License-Identifier: BSD-3-Clause)
|
|
92
|
+
|
|
93
|
+
[Normalized Path](https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths) is a JSONPath query with restricted syntax.
|
|
94
|
+
A Normalized Path represents the identity of a node in a specific value.
|
|
95
|
+
There is precisely one Normalized Path identifying any particular node in a value.
|
|
96
|
+
Normalized Paths provide a predictable format that simplifies testing and post-processing of nodelists, e.g., to remove duplicate nodes.
|
|
97
|
+
Normalized Paths use the canonical bracket notation, rather than dot notation.
|
|
98
|
+
Single quotes are used in Normalized Paths to delimit string member names. This reduces the number of characters that need escaping when Normalized Paths appear in strings delimited by double quotes.
|
|
99
|
+
|
|
100
|
+
Parsing in normalized path mode can be enabled by setting `normalized` option to `true`.
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
import { parse } from '@swaggerexpert/jsonpath';
|
|
104
|
+
|
|
105
|
+
parse("$['a']", { normalized: true });
|
|
106
|
+
parse("$[1]", { normalized: true });
|
|
107
|
+
parse("$[2]", { normalized: true });
|
|
108
|
+
parse("$['a']['b'][1]", { normalized: true });
|
|
109
|
+
parse("$['\\u000b']", { normalized: true });
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
##### Translators
|
|
113
|
+
|
|
114
|
+
`@swaggerexpert/jsonpath` provides several translators to convert the parse result into different tree representations.
|
|
115
|
+
|
|
116
|
+
###### CST translator
|
|
268
117
|
|
|
269
|
-
[Concrete Syntax Tree](https://en.wikipedia.org/wiki/Parse_tree) (Parse tree) is available on parse result
|
|
270
|
-
|
|
118
|
+
[Concrete Syntax Tree](https://en.wikipedia.org/wiki/Parse_tree) (Parse tree) representation is available on parse result
|
|
119
|
+
by default or when instance of `CSTTranslator` is provided via a `translator` option to the `parse` function.
|
|
271
120
|
CST is suitable to be consumed by other tools like IDEs, editors, etc...
|
|
272
121
|
|
|
273
122
|
```js
|
|
274
123
|
import { parse } from '@swaggerexpert/jsonpath';
|
|
275
124
|
|
|
276
|
-
const {
|
|
125
|
+
const { tree: CST } = parse('$.store.book[0].title');
|
|
277
126
|
```
|
|
278
127
|
|
|
279
128
|
or
|
|
280
129
|
|
|
281
130
|
```js
|
|
282
|
-
import { parse,
|
|
131
|
+
import { parse, CSTTranslator } from '@swaggerexpert/jsonpath';
|
|
283
132
|
|
|
284
|
-
const {
|
|
133
|
+
const { tree: CST } = parse('$.store.book[0].title', { translator: new CSTTranslator() });
|
|
285
134
|
```
|
|
286
135
|
|
|
287
|
-
|
|
136
|
+
CST tree has the following shape:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
interface CSTTree {
|
|
140
|
+
readonly root: CSTNode;
|
|
141
|
+
}
|
|
142
|
+
interface CSTNode {
|
|
143
|
+
readonly type: string,
|
|
144
|
+
readonly text: string,
|
|
145
|
+
readonly start: number,
|
|
146
|
+
readonly length: number,
|
|
147
|
+
readonly children: CSTNode[],
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
###### XML translator
|
|
288
152
|
|
|
289
153
|
```js
|
|
290
|
-
import { parse } from '@swaggerexpert/jsonpath';
|
|
154
|
+
import { parse, XMLTranslator } from '@swaggerexpert/jsonpath';
|
|
291
155
|
|
|
292
|
-
const
|
|
293
|
-
const xml = parseResult.ast.toXml();
|
|
156
|
+
const { tree: XML } = parse('$.store.book[0].title', { translator: new XMLTranslator() });
|
|
294
157
|
```
|
|
295
158
|
|
|
296
|
-
|
|
159
|
+
##### Statistics
|
|
297
160
|
|
|
298
161
|
`parse` function returns additional statistical information about the parsing process.
|
|
299
162
|
Collection of the statistics can be enabled by setting `stats` option to `true`.
|
|
@@ -307,7 +170,7 @@ stats.displayStats(); // returns operator stats
|
|
|
307
170
|
stats.displayHits(); // returns rules grouped by hit count
|
|
308
171
|
```
|
|
309
172
|
|
|
310
|
-
|
|
173
|
+
##### Tracing
|
|
311
174
|
|
|
312
175
|
`parse` function returns additional tracing information about the parsing process.
|
|
313
176
|
Tracing can be enabled by setting `trace` option to `true`. Tracing is essential
|
package/cjs/grammar.cjs
CHANGED
|
@@ -16,9 +16,9 @@ function grammar() {
|
|
|
16
16
|
// ALT = 41
|
|
17
17
|
// CAT = 60
|
|
18
18
|
// REP = 32
|
|
19
|
-
// RNM =
|
|
20
|
-
// TLS =
|
|
21
|
-
// TBS =
|
|
19
|
+
// RNM = 178
|
|
20
|
+
// TLS = 64
|
|
21
|
+
// TBS = 28
|
|
22
22
|
// TRG = 20
|
|
23
23
|
// --- SABNF superset opcodes
|
|
24
24
|
// UDT = 0
|
|
@@ -2247,17 +2247,17 @@ function grammar() {
|
|
|
2247
2247
|
children: [1, 2, 3]
|
|
2248
2248
|
}; // CAT
|
|
2249
2249
|
this.rules[69].opcodes[1] = {
|
|
2250
|
-
type:
|
|
2251
|
-
|
|
2252
|
-
}; //
|
|
2250
|
+
type: 4,
|
|
2251
|
+
index: 80
|
|
2252
|
+
}; // RNM(left-bracket)
|
|
2253
2253
|
this.rules[69].opcodes[2] = {
|
|
2254
2254
|
type: 4,
|
|
2255
2255
|
index: 70
|
|
2256
2256
|
}; // RNM(normal-selector)
|
|
2257
2257
|
this.rules[69].opcodes[3] = {
|
|
2258
|
-
type:
|
|
2259
|
-
|
|
2260
|
-
}; //
|
|
2258
|
+
type: 4,
|
|
2259
|
+
index: 81
|
|
2260
|
+
}; // RNM(right-bracket)
|
|
2261
2261
|
|
|
2262
2262
|
/* normal-selector */
|
|
2263
2263
|
this.rules[70].opcodes = [];
|
|
@@ -2281,9 +2281,9 @@ function grammar() {
|
|
|
2281
2281
|
children: [1, 2, 4]
|
|
2282
2282
|
}; // CAT
|
|
2283
2283
|
this.rules[71].opcodes[1] = {
|
|
2284
|
-
type:
|
|
2285
|
-
|
|
2286
|
-
}; //
|
|
2284
|
+
type: 4,
|
|
2285
|
+
index: 87
|
|
2286
|
+
}; // RNM(squote)
|
|
2287
2287
|
this.rules[71].opcodes[2] = {
|
|
2288
2288
|
type: 3,
|
|
2289
2289
|
min: 0,
|
|
@@ -2294,9 +2294,9 @@ function grammar() {
|
|
|
2294
2294
|
index: 72
|
|
2295
2295
|
}; // RNM(normal-single-quoted)
|
|
2296
2296
|
this.rules[71].opcodes[4] = {
|
|
2297
|
-
type:
|
|
2298
|
-
|
|
2299
|
-
}; //
|
|
2297
|
+
type: 4,
|
|
2298
|
+
index: 87
|
|
2299
|
+
}; // RNM(squote)
|
|
2300
2300
|
|
|
2301
2301
|
/* normal-single-quoted */
|
|
2302
2302
|
this.rules[72].opcodes = [];
|
|
@@ -2784,9 +2784,9 @@ function grammar() {
|
|
|
2784
2784
|
str += "\n";
|
|
2785
2785
|
str += "; https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths\n";
|
|
2786
2786
|
str += "normalized-path = root-identifier *(normal-index-segment)\n";
|
|
2787
|
-
str += "normal-index-segment =
|
|
2787
|
+
str += "normal-index-segment = left-bracket normal-selector right-bracket ; MODIFICATION: surrogate text rule used\n";
|
|
2788
2788
|
str += "normal-selector = normal-name-selector / normal-index-selector\n";
|
|
2789
|
-
str += "normal-name-selector =
|
|
2789
|
+
str += "normal-name-selector = squote *normal-single-quoted squote ; 'string', MODIFICATION: surrogate text rule used\n";
|
|
2790
2790
|
str += "normal-single-quoted = normal-unescaped /\n";
|
|
2791
2791
|
str += " ESC normal-escapable\n";
|
|
2792
2792
|
str += "normal-unescaped = ; omit %x0-1F control codes\n";
|
package/cjs/index.cjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.
|
|
4
|
+
exports.parse = exports.XMLTranslator = exports.Grammar = exports.CSTTranslator = void 0;
|
|
5
5
|
var _grammar = _interopRequireDefault(require("./grammar.cjs"));
|
|
6
6
|
exports.Grammar = _grammar.default;
|
|
7
7
|
var _index = _interopRequireDefault(require("./parse/index.cjs"));
|
|
8
8
|
exports.parse = _index.default;
|
|
9
|
-
var
|
|
10
|
-
exports.
|
|
11
|
-
var
|
|
12
|
-
exports.
|
|
9
|
+
var _CSTTranslator = _interopRequireDefault(require("./parse/translators/CSTTranslator.cjs"));
|
|
10
|
+
exports.CSTTranslator = _CSTTranslator.default;
|
|
11
|
+
var _XMLTranslator = _interopRequireDefault(require("./parse/translators/XMLTranslator.cjs"));
|
|
12
|
+
exports.XMLTranslator = _XMLTranslator.default;
|
|
13
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -10,10 +10,6 @@ const cst = ruleName => {
|
|
|
10
10
|
if (!(typeof data === 'object' && data !== null && !Array.isArray(data))) {
|
|
11
11
|
throw new _JSONPathParseError.default("parser's user data must be an object");
|
|
12
12
|
}
|
|
13
|
-
if (!data.stack) {
|
|
14
|
-
data.stack = [];
|
|
15
|
-
data.root = null;
|
|
16
|
-
}
|
|
17
13
|
|
|
18
14
|
// drop the empty nodes
|
|
19
15
|
if (phraseLength === 0) return;
|
package/cjs/parse/index.cjs
CHANGED
|
@@ -4,35 +4,33 @@ exports.__esModule = true;
|
|
|
4
4
|
exports.default = void 0;
|
|
5
5
|
var _apgLite = require("../apg-lite.cjs");
|
|
6
6
|
var _grammar = _interopRequireDefault(require("../grammar.cjs"));
|
|
7
|
-
var
|
|
8
|
-
var _JSONPathQueryCST = _interopRequireDefault(require("./ast/JSONPathQueryCST.cjs"));
|
|
7
|
+
var _CSTTranslator = _interopRequireDefault(require("./translators/CSTTranslator.cjs"));
|
|
9
8
|
var _JSONPathParseError = _interopRequireDefault(require("../errors/JSONPathParseError.cjs"));
|
|
10
9
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
10
|
const grammar = new _grammar.default();
|
|
12
11
|
const parse = (jsonPath, {
|
|
13
|
-
|
|
12
|
+
normalized = false,
|
|
14
13
|
stats = false,
|
|
15
14
|
trace = false,
|
|
16
|
-
|
|
15
|
+
translator = new _CSTTranslator.default(),
|
|
16
|
+
test = 3
|
|
17
17
|
} = {}) => {
|
|
18
18
|
if (typeof jsonPath !== 'string') {
|
|
19
19
|
throw new TypeError('JSONPath must be a string');
|
|
20
20
|
}
|
|
21
21
|
try {
|
|
22
|
+
var _parser$ast;
|
|
22
23
|
const parser = new _apgLite.Parser();
|
|
23
|
-
parser.ast =
|
|
24
|
+
if (translator) parser.ast = translator;
|
|
24
25
|
if (stats) parser.stats = new _apgLite.Stats();
|
|
25
26
|
if (trace) parser.trace = new _apgLite.Trace();
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
result
|
|
29
|
-
});
|
|
27
|
+
const startRule = normalized ? 'normalized-path' : 'jsonpath-query';
|
|
28
|
+
const result = parser.parse(grammar, startRule, jsonPath);
|
|
30
29
|
return {
|
|
31
30
|
result,
|
|
32
|
-
ast,
|
|
31
|
+
tree: (_parser$ast = parser.ast) == null ? void 0 : _parser$ast.getTree(),
|
|
33
32
|
stats: parser.stats,
|
|
34
|
-
trace: parser.trace
|
|
35
|
-
computed
|
|
33
|
+
trace: parser.trace
|
|
36
34
|
};
|
|
37
35
|
} catch (error) {
|
|
38
36
|
throw new _JSONPathParseError.default('Unexpected error during JSONPath parsing', {
|
|
@@ -5,7 +5,7 @@ exports.default = void 0;
|
|
|
5
5
|
var _apgLite = require("../../apg-lite.cjs");
|
|
6
6
|
var _cst = _interopRequireDefault(require("../callbacks/cst.cjs"));
|
|
7
7
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
-
class
|
|
8
|
+
class CSTTranslator extends _apgLite.Ast {
|
|
9
9
|
constructor() {
|
|
10
10
|
super();
|
|
11
11
|
|
|
@@ -82,6 +82,14 @@ class JSONPathQueryCST extends _apgLite.Ast {
|
|
|
82
82
|
// https://www.rfc-editor.org/rfc/rfc9535#section-2.5.2.1
|
|
83
83
|
this.callbacks['descendant-segment'] = (0, _cst.default)('descendant-segment');
|
|
84
84
|
|
|
85
|
+
// https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths
|
|
86
|
+
this.callbacks['normalized-path'] = (0, _cst.default)('normalized-path');
|
|
87
|
+
this.callbacks['normal-index-segment'] = (0, _cst.default)('normal-index-segment');
|
|
88
|
+
this.callbacks['normal-selector'] = (0, _cst.default)('normal-selector');
|
|
89
|
+
this.callbacks['normal-name-selector'] = (0, _cst.default)('normal-name-selector');
|
|
90
|
+
this.callbacks['normal-index-selector'] = (0, _cst.default)('normal-index-selector');
|
|
91
|
+
this.callbacks['normal-single-quoted'] = (0, _cst.default)('normal-single-quoted');
|
|
92
|
+
|
|
85
93
|
// Surrogate named rules
|
|
86
94
|
this.callbacks['dot-prefix'] = (0, _cst.default)('text');
|
|
87
95
|
this.callbacks['double-dot-prefix'] = (0, _cst.default)('text');
|
|
@@ -97,5 +105,14 @@ class JSONPathQueryCST extends _apgLite.Ast {
|
|
|
97
105
|
this.callbacks['left-paren'] = (0, _cst.default)('text');
|
|
98
106
|
this.callbacks['right-paren'] = (0, _cst.default)('text');
|
|
99
107
|
}
|
|
108
|
+
getTree() {
|
|
109
|
+
const data = {
|
|
110
|
+
stack: [],
|
|
111
|
+
root: null
|
|
112
|
+
};
|
|
113
|
+
this.translate(data);
|
|
114
|
+
delete data.stack;
|
|
115
|
+
return data;
|
|
116
|
+
}
|
|
100
117
|
}
|
|
101
|
-
var _default = exports.default =
|
|
118
|
+
var _default = exports.default = CSTTranslator;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _CSTTranslator = _interopRequireDefault(require("./CSTTranslator.cjs"));
|
|
6
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
class XMLTranslator extends _CSTTranslator.default {
|
|
8
|
+
getTree() {
|
|
9
|
+
return this.toXml();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
var _default = exports.default = XMLTranslator;
|
package/es/grammar.mjs
CHANGED
|
@@ -12,9 +12,9 @@ export default function grammar() {
|
|
|
12
12
|
// ALT = 41
|
|
13
13
|
// CAT = 60
|
|
14
14
|
// REP = 32
|
|
15
|
-
// RNM =
|
|
16
|
-
// TLS =
|
|
17
|
-
// TBS =
|
|
15
|
+
// RNM = 178
|
|
16
|
+
// TLS = 64
|
|
17
|
+
// TBS = 28
|
|
18
18
|
// TRG = 20
|
|
19
19
|
// --- SABNF superset opcodes
|
|
20
20
|
// UDT = 0
|
|
@@ -2243,17 +2243,17 @@ export default function grammar() {
|
|
|
2243
2243
|
children: [1, 2, 3]
|
|
2244
2244
|
}; // CAT
|
|
2245
2245
|
this.rules[69].opcodes[1] = {
|
|
2246
|
-
type:
|
|
2247
|
-
|
|
2248
|
-
}; //
|
|
2246
|
+
type: 4,
|
|
2247
|
+
index: 80
|
|
2248
|
+
}; // RNM(left-bracket)
|
|
2249
2249
|
this.rules[69].opcodes[2] = {
|
|
2250
2250
|
type: 4,
|
|
2251
2251
|
index: 70
|
|
2252
2252
|
}; // RNM(normal-selector)
|
|
2253
2253
|
this.rules[69].opcodes[3] = {
|
|
2254
|
-
type:
|
|
2255
|
-
|
|
2256
|
-
}; //
|
|
2254
|
+
type: 4,
|
|
2255
|
+
index: 81
|
|
2256
|
+
}; // RNM(right-bracket)
|
|
2257
2257
|
|
|
2258
2258
|
/* normal-selector */
|
|
2259
2259
|
this.rules[70].opcodes = [];
|
|
@@ -2277,9 +2277,9 @@ export default function grammar() {
|
|
|
2277
2277
|
children: [1, 2, 4]
|
|
2278
2278
|
}; // CAT
|
|
2279
2279
|
this.rules[71].opcodes[1] = {
|
|
2280
|
-
type:
|
|
2281
|
-
|
|
2282
|
-
}; //
|
|
2280
|
+
type: 4,
|
|
2281
|
+
index: 87
|
|
2282
|
+
}; // RNM(squote)
|
|
2283
2283
|
this.rules[71].opcodes[2] = {
|
|
2284
2284
|
type: 3,
|
|
2285
2285
|
min: 0,
|
|
@@ -2290,9 +2290,9 @@ export default function grammar() {
|
|
|
2290
2290
|
index: 72
|
|
2291
2291
|
}; // RNM(normal-single-quoted)
|
|
2292
2292
|
this.rules[71].opcodes[4] = {
|
|
2293
|
-
type:
|
|
2294
|
-
|
|
2295
|
-
}; //
|
|
2293
|
+
type: 4,
|
|
2294
|
+
index: 87
|
|
2295
|
+
}; // RNM(squote)
|
|
2296
2296
|
|
|
2297
2297
|
/* normal-single-quoted */
|
|
2298
2298
|
this.rules[72].opcodes = [];
|
|
@@ -2780,9 +2780,9 @@ export default function grammar() {
|
|
|
2780
2780
|
str += "\n";
|
|
2781
2781
|
str += "; https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths\n";
|
|
2782
2782
|
str += "normalized-path = root-identifier *(normal-index-segment)\n";
|
|
2783
|
-
str += "normal-index-segment =
|
|
2783
|
+
str += "normal-index-segment = left-bracket normal-selector right-bracket ; MODIFICATION: surrogate text rule used\n";
|
|
2784
2784
|
str += "normal-selector = normal-name-selector / normal-index-selector\n";
|
|
2785
|
-
str += "normal-name-selector =
|
|
2785
|
+
str += "normal-name-selector = squote *normal-single-quoted squote ; 'string', MODIFICATION: surrogate text rule used\n";
|
|
2786
2786
|
str += "normal-single-quoted = normal-unescaped /\n";
|
|
2787
2787
|
str += " ESC normal-escapable\n";
|
|
2788
2788
|
str += "normal-unescaped = ; omit %x0-1F control codes\n";
|
package/es/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as Grammar } from "./grammar.mjs";
|
|
2
2
|
export { default as parse } from "./parse/index.mjs";
|
|
3
|
-
export { default as
|
|
4
|
-
export { default as
|
|
3
|
+
export { default as CSTTranslator } from "./parse/translators/CSTTranslator.mjs";
|
|
4
|
+
export { default as XMLTranslator } from "./parse/translators/XMLTranslator.mjs";
|
|
@@ -5,10 +5,6 @@ const cst = ruleName => {
|
|
|
5
5
|
if (!(typeof data === 'object' && data !== null && !Array.isArray(data))) {
|
|
6
6
|
throw new JSONPathParseError("parser's user data must be an object");
|
|
7
7
|
}
|
|
8
|
-
if (!data.stack) {
|
|
9
|
-
data.stack = [];
|
|
10
|
-
data.root = null;
|
|
11
|
-
}
|
|
12
8
|
|
|
13
9
|
// drop the empty nodes
|
|
14
10
|
if (phraseLength === 0) return;
|
package/es/parse/index.mjs
CHANGED
|
@@ -1,33 +1,31 @@
|
|
|
1
1
|
import { Parser, Stats, Trace } from 'apg-lite';
|
|
2
2
|
import Grammar from "../grammar.mjs";
|
|
3
|
-
import
|
|
4
|
-
import JSONPathQueryCST from "./ast/JSONPathQueryCST.mjs";
|
|
3
|
+
import CSTTranslator from "./translators/CSTTranslator.mjs";
|
|
5
4
|
import JSONPathParseError from "../errors/JSONPathParseError.mjs";
|
|
6
5
|
const grammar = new Grammar();
|
|
7
6
|
const parse = (jsonPath, {
|
|
8
|
-
|
|
7
|
+
normalized = false,
|
|
9
8
|
stats = false,
|
|
10
9
|
trace = false,
|
|
11
|
-
|
|
10
|
+
translator = new CSTTranslator(),
|
|
11
|
+
test = 3
|
|
12
12
|
} = {}) => {
|
|
13
13
|
if (typeof jsonPath !== 'string') {
|
|
14
14
|
throw new TypeError('JSONPath must be a string');
|
|
15
15
|
}
|
|
16
16
|
try {
|
|
17
|
+
var _parser$ast;
|
|
17
18
|
const parser = new Parser();
|
|
18
|
-
parser.ast =
|
|
19
|
+
if (translator) parser.ast = translator;
|
|
19
20
|
if (stats) parser.stats = new Stats();
|
|
20
21
|
if (trace) parser.trace = new Trace();
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
result
|
|
24
|
-
});
|
|
22
|
+
const startRule = normalized ? 'normalized-path' : 'jsonpath-query';
|
|
23
|
+
const result = parser.parse(grammar, startRule, jsonPath);
|
|
25
24
|
return {
|
|
26
25
|
result,
|
|
27
|
-
ast,
|
|
26
|
+
tree: (_parser$ast = parser.ast) === null || _parser$ast === void 0 ? void 0 : _parser$ast.getTree(),
|
|
28
27
|
stats: parser.stats,
|
|
29
|
-
trace: parser.trace
|
|
30
|
-
computed
|
|
28
|
+
trace: parser.trace
|
|
31
29
|
};
|
|
32
30
|
} catch (error) {
|
|
33
31
|
throw new JSONPathParseError('Unexpected error during JSONPath parsing', {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Ast as AST } from 'apg-lite';
|
|
2
2
|
import cstCallback from "../callbacks/cst.mjs";
|
|
3
|
-
class
|
|
3
|
+
class CSTTranslator extends AST {
|
|
4
4
|
constructor() {
|
|
5
5
|
super();
|
|
6
6
|
|
|
@@ -77,6 +77,14 @@ class JSONPathQueryCST extends AST {
|
|
|
77
77
|
// https://www.rfc-editor.org/rfc/rfc9535#section-2.5.2.1
|
|
78
78
|
this.callbacks['descendant-segment'] = cstCallback('descendant-segment');
|
|
79
79
|
|
|
80
|
+
// https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths
|
|
81
|
+
this.callbacks['normalized-path'] = cstCallback('normalized-path');
|
|
82
|
+
this.callbacks['normal-index-segment'] = cstCallback('normal-index-segment');
|
|
83
|
+
this.callbacks['normal-selector'] = cstCallback('normal-selector');
|
|
84
|
+
this.callbacks['normal-name-selector'] = cstCallback('normal-name-selector');
|
|
85
|
+
this.callbacks['normal-index-selector'] = cstCallback('normal-index-selector');
|
|
86
|
+
this.callbacks['normal-single-quoted'] = cstCallback('normal-single-quoted');
|
|
87
|
+
|
|
80
88
|
// Surrogate named rules
|
|
81
89
|
this.callbacks['dot-prefix'] = cstCallback('text');
|
|
82
90
|
this.callbacks['double-dot-prefix'] = cstCallback('text');
|
|
@@ -92,5 +100,14 @@ class JSONPathQueryCST extends AST {
|
|
|
92
100
|
this.callbacks['left-paren'] = cstCallback('text');
|
|
93
101
|
this.callbacks['right-paren'] = cstCallback('text');
|
|
94
102
|
}
|
|
103
|
+
getTree() {
|
|
104
|
+
const data = {
|
|
105
|
+
stack: [],
|
|
106
|
+
root: null
|
|
107
|
+
};
|
|
108
|
+
this.translate(data);
|
|
109
|
+
delete data.stack;
|
|
110
|
+
return data;
|
|
111
|
+
}
|
|
95
112
|
}
|
|
96
|
-
export default
|
|
113
|
+
export default CSTTranslator;
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -4,22 +4,34 @@
|
|
|
4
4
|
export function parse(jsonpath: string, options?: ParseOptions): ParseResult;
|
|
5
5
|
|
|
6
6
|
export interface ParseOptions {
|
|
7
|
-
readonly
|
|
7
|
+
readonly normalized?: boolean;
|
|
8
8
|
readonly stats?: boolean;
|
|
9
9
|
readonly trace?: boolean;
|
|
10
|
+
readonly translator?: Translator | null;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
export interface
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
export interface Translator<TTree = unknown> {
|
|
14
|
+
getTree(): TTree;
|
|
15
|
+
}
|
|
16
|
+
export declare class CSTTranslator implements Translator<CSTTree> {
|
|
17
|
+
getTree(): CSTTree;
|
|
18
|
+
}
|
|
19
|
+
export declare class XMLTranslator implements Translator<XMLTree> {
|
|
20
|
+
getTree(): XMLTree;
|
|
15
21
|
}
|
|
16
22
|
|
|
17
|
-
export interface ParseResult {
|
|
23
|
+
export interface ParseResult<TTree = unknown> {
|
|
18
24
|
readonly result: {
|
|
19
25
|
readonly success: boolean;
|
|
26
|
+
readonly state: number;
|
|
27
|
+
readonly stateName: string;
|
|
28
|
+
readonly length: number;
|
|
29
|
+
readonly matched: number;
|
|
30
|
+
readonly maxMatched: number;
|
|
31
|
+
readonly maxTreeDepth: number
|
|
32
|
+
readonly nodeHits: number;
|
|
20
33
|
};
|
|
21
|
-
readonly
|
|
22
|
-
readonly computed: Record<string, CSTNode>;
|
|
34
|
+
readonly tree: TTree;
|
|
23
35
|
readonly stats?: Stats;
|
|
24
36
|
readonly trace?: Trace;
|
|
25
37
|
}
|
|
@@ -32,6 +44,12 @@ export interface CSTNode {
|
|
|
32
44
|
readonly children: CSTNode[],
|
|
33
45
|
}
|
|
34
46
|
|
|
47
|
+
export interface CSTTree {
|
|
48
|
+
readonly root: CSTNode;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type XMLTree = string;
|
|
52
|
+
|
|
35
53
|
export interface Stats {
|
|
36
54
|
displayStats(): string;
|
|
37
55
|
displayHits(): string;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
exports.__esModule = true;
|
|
4
|
-
exports.default = void 0;
|
|
5
|
-
const translateEvaluator = (ast, {
|
|
6
|
-
result
|
|
7
|
-
}) => {
|
|
8
|
-
if (!result.success) return null;
|
|
9
|
-
const parts = {};
|
|
10
|
-
ast.translate(parts);
|
|
11
|
-
return parts;
|
|
12
|
-
};
|
|
13
|
-
var _default = exports.default = translateEvaluator;
|