pacc 8.11.6 → 9.0.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/package.json +1 -1
- package/src/ast.mjs +55 -35
- package/src/expand.mjs +1 -1
- package/src/module.mjs +1 -1
- package/src/multiple.mjs +10 -13
- package/src/{expression.mjs → parser.mjs} +2 -36
- package/src/settergetter.mjs +34 -44
- package/src/tokens.mjs +108 -60
- package/types/ast.d.mts +6 -2
- package/types/module.d.mts +1 -1
- package/types/multiple.d.mts +2 -1
- package/types/parser.d.mts +2 -0
- package/types/settergetter.d.mts +4 -3
- package/types/tokens.d.mts +21 -2
- package/types/expression.d.mts +0 -21
package/package.json
CHANGED
package/src/ast.mjs
CHANGED
|
@@ -4,39 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export function pathEval(node, current, context) {
|
|
7
|
-
let collection = false;
|
|
8
|
-
let first = true;
|
|
9
7
|
for (const item of node.path) {
|
|
10
|
-
|
|
11
|
-
case "string":
|
|
12
|
-
case "number":
|
|
13
|
-
switch (typeof current) {
|
|
14
|
-
case "undefined":
|
|
15
|
-
current = context.getGlobal(item);
|
|
16
|
-
break;
|
|
17
|
-
default:
|
|
18
|
-
if (collection) {
|
|
19
|
-
current = current.map(x => x[item]);
|
|
20
|
-
} else {
|
|
21
|
-
current =
|
|
22
|
-
current instanceof Map ? current.get(item) : current[item];
|
|
23
|
-
|
|
24
|
-
if (first && current === undefined) {
|
|
25
|
-
current = context.getGlobal(item);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
break;
|
|
30
|
-
case "object":
|
|
31
|
-
if (typeof current.values === "function") {
|
|
32
|
-
current = current.values();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
current = current.filter(c => item.eval(item, c, context));
|
|
36
|
-
collection = true;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
first = false;
|
|
8
|
+
current = item.eval(item, current, context);
|
|
40
9
|
}
|
|
41
10
|
|
|
42
11
|
return current;
|
|
@@ -46,9 +15,60 @@ export function functionEval(node, current, context) {
|
|
|
46
15
|
const args = node.args.map(a =>
|
|
47
16
|
typeof a === "object" ? a.eval(a, current, context) : a
|
|
48
17
|
);
|
|
49
|
-
return context.
|
|
18
|
+
return context.valueFor(node.name)(...args);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function keyedAccessOrGlobalEval(node, current, context) {
|
|
22
|
+
return keyedAccessEval(node, current, context) ?? context.valueFor(node.key);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function keyedAccessEval(node, current, context) {
|
|
26
|
+
if (current === undefined) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
if (current instanceof Map) {
|
|
30
|
+
return current.get(node.key);
|
|
31
|
+
}
|
|
32
|
+
if (current instanceof Set) {
|
|
33
|
+
return current.has(node.key) ? node.key : undefined;
|
|
34
|
+
}
|
|
35
|
+
if (current instanceof Iterator) {
|
|
36
|
+
return current.map(item => item[node.key]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
switch (typeof current[node.key]) {
|
|
40
|
+
case "function": {
|
|
41
|
+
const value = current[node.key]();
|
|
42
|
+
|
|
43
|
+
if (typeof value[Symbol.iterator] === "function") {
|
|
44
|
+
return [...value];
|
|
45
|
+
//return value[Symbol.iterator]();
|
|
46
|
+
}
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
case "undefined":
|
|
50
|
+
return context.valueFor(node.key, current);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return current[node.key];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function filterEval(node, current, context) {
|
|
57
|
+
if (typeof current.values === "function") {
|
|
58
|
+
current = current.values();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return current.filter(item => node.filter.eval(node.filter, item, context));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function nullFilterEval(node, current, context) {
|
|
65
|
+
if (typeof current.values === "function") {
|
|
66
|
+
current = current.values();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return current;
|
|
50
70
|
}
|
|
51
71
|
|
|
52
|
-
export const
|
|
53
|
-
eval:
|
|
72
|
+
export const ASTNullFilter = {
|
|
73
|
+
eval: nullFilterEval
|
|
54
74
|
};
|
package/src/expand.mjs
CHANGED
package/src/module.mjs
CHANGED
|
@@ -7,7 +7,7 @@ export * from "./filter.mjs";
|
|
|
7
7
|
export * from "./multiple.mjs";
|
|
8
8
|
export * from "./common-attributes.mjs";
|
|
9
9
|
export * from "./properties.mjs";
|
|
10
|
-
export * from "./
|
|
10
|
+
export * from "./parser.mjs";
|
|
11
11
|
export * from "./expand.mjs";
|
|
12
12
|
export * from "./environment.mjs";
|
|
13
13
|
export {
|
package/src/multiple.mjs
CHANGED
|
@@ -15,21 +15,17 @@ export function setAttributes(object, source, definitions, cb) {
|
|
|
15
15
|
let value = getAttribute(source, name);
|
|
16
16
|
|
|
17
17
|
if (value === undefined) {
|
|
18
|
-
if (
|
|
18
|
+
if (
|
|
19
|
+
def.default === undefined ||
|
|
20
|
+
getAttribute(object, name) !== undefined
|
|
21
|
+
) {
|
|
19
22
|
continue;
|
|
20
|
-
} else {
|
|
21
|
-
if (getAttribute(object, name, def) !== undefined) {
|
|
22
|
-
continue;
|
|
23
|
-
}
|
|
24
|
-
value = def.default;
|
|
25
23
|
}
|
|
24
|
+
value = def.default;
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
} else {
|
|
31
|
-
setAttribute(object, name, value, def);
|
|
32
|
-
}
|
|
27
|
+
setAttribute(object, name, value, def);
|
|
28
|
+
|
|
33
29
|
if (cb) {
|
|
34
30
|
cb(def, name, value);
|
|
35
31
|
}
|
|
@@ -40,12 +36,13 @@ export function setAttributes(object, source, definitions, cb) {
|
|
|
40
36
|
* Retrive attribute values from an object.
|
|
41
37
|
* @param {Object} object attribute value source
|
|
42
38
|
* @param {Object} definitions
|
|
39
|
+
* @param {Function} [filter]
|
|
43
40
|
* @return {Object} values
|
|
44
41
|
*/
|
|
45
|
-
export function getAttributes(object, definitions) {
|
|
42
|
+
export function getAttributes(object, definitions, filter) {
|
|
46
43
|
const result = {};
|
|
47
44
|
|
|
48
|
-
for (const [path, def] of attributeIterator(definitions)) {
|
|
45
|
+
for (const [path, def] of attributeIterator(definitions, filter)) {
|
|
49
46
|
const name = path.join(".");
|
|
50
47
|
|
|
51
48
|
const value = getAttribute(object, name, def);
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { tokens, EOF } from "./tokens.mjs";
|
|
2
2
|
|
|
3
3
|
export function parseOnly(input, context = {}) {
|
|
4
|
-
context.getGlobal ||= a => globals[a];
|
|
5
|
-
|
|
6
4
|
input = tokens(input, context);
|
|
7
|
-
|
|
5
|
+
|
|
8
6
|
let node, token, value;
|
|
9
7
|
|
|
10
8
|
function advance() {
|
|
@@ -42,7 +40,7 @@ export function parseOnly(input, context = {}) {
|
|
|
42
40
|
expression(precedence) {
|
|
43
41
|
const last = token;
|
|
44
42
|
advance();
|
|
45
|
-
node = last.nud
|
|
43
|
+
node = last.nud(parser);
|
|
46
44
|
|
|
47
45
|
while (token.precedence > precedence) {
|
|
48
46
|
const last = token;
|
|
@@ -63,35 +61,3 @@ export function parse(input, context) {
|
|
|
63
61
|
const result = parseOnly(input, context);
|
|
64
62
|
return result.eval ? result.eval(result, context.root, context) : result;
|
|
65
63
|
}
|
|
66
|
-
|
|
67
|
-
export const globals = {
|
|
68
|
-
in: (a, b) => {
|
|
69
|
-
if (b?.[Symbol.iterator]) {
|
|
70
|
-
for (const x of b) {
|
|
71
|
-
if (x === a) {
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return false;
|
|
77
|
-
},
|
|
78
|
-
ceil: Math.ceil,
|
|
79
|
-
floor: Math.floor,
|
|
80
|
-
abs: Math.abs,
|
|
81
|
-
min: Math.min,
|
|
82
|
-
max: Math.max,
|
|
83
|
-
encodeURI: encodeURI,
|
|
84
|
-
decodeURI: decodeURI,
|
|
85
|
-
encodeURIComponent: encodeURIComponent,
|
|
86
|
-
decodeURIComponent: decodeURIComponent,
|
|
87
|
-
trim: a => a.trim(),
|
|
88
|
-
uppercase: a => a.toUpperCase(),
|
|
89
|
-
lowercase: a => a.toLowerCase(),
|
|
90
|
-
substring: (s, a, b) => s.substring(a, b),
|
|
91
|
-
length: s => s.length,
|
|
92
|
-
join: (separator, ...args) =>
|
|
93
|
-
args
|
|
94
|
-
.map(item => (item instanceof Iterator ? Array.from(item) : item))
|
|
95
|
-
.flat()
|
|
96
|
-
.join(separator)
|
|
97
|
-
};
|
package/src/settergetter.mjs
CHANGED
|
@@ -19,8 +19,9 @@ import {
|
|
|
19
19
|
NUMBER,
|
|
20
20
|
BOOLEAN
|
|
21
21
|
} from "./tokens.mjs";
|
|
22
|
-
import { parseOnly } from "./
|
|
22
|
+
import { parseOnly, parse } from "./parser.mjs";
|
|
23
23
|
import { toInternal } from "./attributes.mjs";
|
|
24
|
+
import { keyedAccessOrGlobalEval, keyedAccessEval, pathEval } from "./ast.mjs";
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Set object attribute.
|
|
@@ -28,31 +29,43 @@ import { toInternal } from "./attributes.mjs";
|
|
|
28
29
|
* @param {Object} object
|
|
29
30
|
* @param {string} expression
|
|
30
31
|
* @param {any} value
|
|
31
|
-
* @param {Object} definition type def
|
|
32
|
+
* @param {Object} [definition] type def
|
|
32
33
|
*/
|
|
33
34
|
export function setAttribute(object, expression, value, definition) {
|
|
34
|
-
|
|
35
|
+
if(definition?.set) {
|
|
36
|
+
definition.set.call(object, value, definition);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
const context = {};
|
|
41
|
+
const ast = parseOnly(expression, context);
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
if (anchor) {
|
|
40
|
-
anchor[anchorKey] = object = typeof key === "string" ? {} : [];
|
|
41
|
-
anchor = undefined;
|
|
42
|
-
}
|
|
43
|
+
let parent, parentItem;
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
switch (ast.eval) {
|
|
46
|
+
case keyedAccessEval:
|
|
47
|
+
case keyedAccessOrGlobalEval:
|
|
48
|
+
object[ast.key] = toInternal(value, definition);
|
|
49
|
+
break;
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
case pathEval:
|
|
52
|
+
for (const item of ast.path) {
|
|
53
|
+
if (typeof object !== "object") {
|
|
54
|
+
object = typeof item.key === "number" ? [] : {};
|
|
55
|
+
parent[parentItem.key] = object;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
parent = object;
|
|
59
|
+
parentItem = item;
|
|
60
|
+
|
|
61
|
+
object = item.eval(item, object, context);
|
|
62
|
+
}
|
|
53
63
|
|
|
54
|
-
|
|
55
|
-
|
|
64
|
+
parent[parentItem.key] = toInternal(value, definition);
|
|
65
|
+
break;
|
|
66
|
+
|
|
67
|
+
default:
|
|
68
|
+
console.log("UKNOWN AST",ast);
|
|
56
69
|
}
|
|
57
70
|
}
|
|
58
71
|
|
|
@@ -61,34 +74,11 @@ export function setAttribute(object, expression, value, definition) {
|
|
|
61
74
|
* The name may be a property path like 'a.b.c' or a[2]
|
|
62
75
|
* @param {Object} object
|
|
63
76
|
* @param {string} expression
|
|
77
|
+
* @param {Object} [definition]
|
|
64
78
|
* @returns {any} value associated with the given property name
|
|
65
79
|
*/
|
|
66
80
|
export function getAttribute(object, expression, definition) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
for (const key of path) {
|
|
70
|
-
if (object !== undefined) {
|
|
71
|
-
switch (typeof object[key]) {
|
|
72
|
-
case "function":
|
|
73
|
-
object = object[key]();
|
|
74
|
-
if (typeof object[Symbol.iterator] === "function") {
|
|
75
|
-
object = [...object];
|
|
76
|
-
}
|
|
77
|
-
break;
|
|
78
|
-
default:
|
|
79
|
-
object = object[key];
|
|
80
|
-
break;
|
|
81
|
-
case "undefined":
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (object === undefined && definition) {
|
|
88
|
-
object = definition.default;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return object;
|
|
81
|
+
return parse(expression, { root: object }) ?? definition?.default;
|
|
92
82
|
}
|
|
93
83
|
|
|
94
84
|
/**
|
package/src/tokens.mjs
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
pathEval,
|
|
3
|
+
ASTNullFilter,
|
|
4
|
+
keyedAccessEval,
|
|
5
|
+
keyedAccessOrGlobalEval,
|
|
6
|
+
filterEval,
|
|
7
|
+
functionEval
|
|
8
|
+
} from "./ast.mjs";
|
|
2
9
|
|
|
3
10
|
/**
|
|
4
11
|
* Token lookup
|
|
@@ -22,8 +29,8 @@ function createToken(
|
|
|
22
29
|
str,
|
|
23
30
|
precedence = 0,
|
|
24
31
|
type,
|
|
25
|
-
led = () =>
|
|
26
|
-
nud =
|
|
32
|
+
led = (parser, node) => node,
|
|
33
|
+
nud = parser => this
|
|
27
34
|
) {
|
|
28
35
|
const token = { str, precedence, type };
|
|
29
36
|
|
|
@@ -146,18 +153,16 @@ export /** @type {Token} */ const LESS_EQUAL = createBinopToken(
|
|
|
146
153
|
);
|
|
147
154
|
export /** @type {Token} */ const OPEN_ROUND = createToken(
|
|
148
155
|
"(",
|
|
149
|
-
|
|
156
|
+
100,
|
|
150
157
|
"prefix",
|
|
151
|
-
|
|
158
|
+
(parser, left) => {
|
|
152
159
|
const args = parser.expression(0);
|
|
153
160
|
parser.expect(CLOSE_ROUND);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return left;
|
|
161
|
+
return {
|
|
162
|
+
eval: functionEval,
|
|
163
|
+
name: left.key,
|
|
164
|
+
args: Array.isArray(args) ? args : [args]
|
|
165
|
+
};
|
|
161
166
|
},
|
|
162
167
|
parser => {
|
|
163
168
|
const result = parser.expression(0);
|
|
@@ -167,38 +172,40 @@ export /** @type {Token} */ const OPEN_ROUND = createToken(
|
|
|
167
172
|
);
|
|
168
173
|
|
|
169
174
|
export /** @type {Token} */ const CLOSE_ROUND = createToken(")", 0);
|
|
175
|
+
|
|
176
|
+
function createFilter(parser) {
|
|
177
|
+
if (parser.token === CLOSE_BRACKET) {
|
|
178
|
+
parser.advance();
|
|
179
|
+
return ASTNullFilter;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const filter = parser.expression(0);
|
|
183
|
+
parser.expect(CLOSE_BRACKET);
|
|
184
|
+
|
|
185
|
+
switch (typeof filter) {
|
|
186
|
+
case "string":
|
|
187
|
+
case "number":
|
|
188
|
+
return { eval: keyedAccessEval, key: filter };
|
|
189
|
+
default:
|
|
190
|
+
return { eval: filterEval, filter };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
170
194
|
export /** @type {Token} */ const OPEN_BRACKET = createToken(
|
|
171
195
|
"[",
|
|
172
|
-
|
|
196
|
+
80,
|
|
173
197
|
"prefix",
|
|
174
198
|
(parser, left) => {
|
|
175
|
-
|
|
176
|
-
parser.advance();
|
|
177
|
-
left.path.push(ASTTrue);
|
|
178
|
-
} else {
|
|
179
|
-
const predicate = parser.expression(0);
|
|
180
|
-
parser.expect(CLOSE_BRACKET);
|
|
181
|
-
left.path.push(predicate);
|
|
182
|
-
}
|
|
183
|
-
return left;
|
|
184
|
-
},
|
|
185
|
-
parser => {
|
|
186
|
-
if (parser.token === CLOSE_BRACKET) {
|
|
187
|
-
parser.advance();
|
|
188
|
-
return ASTTrue;
|
|
189
|
-
}
|
|
199
|
+
const node = createFilter(parser);
|
|
190
200
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
switch (typeof node) {
|
|
195
|
-
case "string":
|
|
196
|
-
case "number":
|
|
197
|
-
return { eval: pathEval, path: [node] };
|
|
201
|
+
if (left.key) {
|
|
202
|
+
return { eval: pathEval, path: [left, node] };
|
|
198
203
|
}
|
|
199
204
|
|
|
200
|
-
|
|
201
|
-
|
|
205
|
+
left.path.push(node);
|
|
206
|
+
return left;
|
|
207
|
+
},
|
|
208
|
+
parser => createFilter(parser)
|
|
202
209
|
);
|
|
203
210
|
|
|
204
211
|
export /** @type {Token} */ const CLOSE_BRACKET = createToken("]", 0);
|
|
@@ -207,19 +214,27 @@ export /** @type {Token} */ const CLOSE_CURLY = createToken("}");
|
|
|
207
214
|
export /** @type {Token} */ const QUESTION = createToken("?", 20, "infix");
|
|
208
215
|
export /** @type {Token} */ const COLON = createToken(":", undefined, "infix");
|
|
209
216
|
export /** @type {Token} */ const SEMICOLON = createToken(";");
|
|
210
|
-
export /** @type {Token} */ const COMMA = createToken(
|
|
217
|
+
export /** @type {Token} */ const COMMA = createToken(
|
|
218
|
+
",",
|
|
219
|
+
20,
|
|
220
|
+
"infix",
|
|
221
|
+
(left, right) => (Array.isArray(left) ? [...left, right] : [left, right])
|
|
222
|
+
);
|
|
211
223
|
|
|
212
224
|
export /** @type {Token} */ const DOT = createToken(
|
|
213
225
|
".",
|
|
214
226
|
80,
|
|
215
227
|
"infix",
|
|
216
228
|
(left, right) => {
|
|
229
|
+
if (right.eval === keyedAccessOrGlobalEval) {
|
|
230
|
+
right.eval = keyedAccessEval;
|
|
231
|
+
}
|
|
217
232
|
if (left.path) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
right.path.unshift(left);
|
|
233
|
+
left.path.push(right);
|
|
234
|
+
return left;
|
|
221
235
|
}
|
|
222
|
-
|
|
236
|
+
|
|
237
|
+
return { eval: pathEval, path: [left, right] };
|
|
223
238
|
}
|
|
224
239
|
);
|
|
225
240
|
export /** @type {Token} */ const AMPERSAND = createToken("&");
|
|
@@ -242,7 +257,7 @@ export /** @type {Token} */ const IDENTIFIER = createToken(
|
|
|
242
257
|
undefined,
|
|
243
258
|
undefined,
|
|
244
259
|
parser => {
|
|
245
|
-
return { eval:
|
|
260
|
+
return { eval: keyedAccessOrGlobalEval, key: parser.value };
|
|
246
261
|
}
|
|
247
262
|
);
|
|
248
263
|
|
|
@@ -279,11 +294,6 @@ export /** @type {Token} */ const EOF = createToken(
|
|
|
279
294
|
}
|
|
280
295
|
);
|
|
281
296
|
|
|
282
|
-
export const keywords = {
|
|
283
|
-
true: [BOOLEAN, true],
|
|
284
|
-
false: [BOOLEAN, false]
|
|
285
|
-
};
|
|
286
|
-
|
|
287
297
|
const esc = {
|
|
288
298
|
b: "\b",
|
|
289
299
|
f: "\f",
|
|
@@ -293,20 +303,58 @@ const esc = {
|
|
|
293
303
|
v: "\v"
|
|
294
304
|
};
|
|
295
305
|
|
|
306
|
+
export const keywords = {
|
|
307
|
+
true: [BOOLEAN, true],
|
|
308
|
+
false: [BOOLEAN, false]
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
export const globals = {
|
|
312
|
+
in: (a, b) => {
|
|
313
|
+
if (b?.[Symbol.iterator]) {
|
|
314
|
+
for (const x of b) {
|
|
315
|
+
if (x === a) {
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return false;
|
|
321
|
+
},
|
|
322
|
+
ceil: Math.ceil,
|
|
323
|
+
floor: Math.floor,
|
|
324
|
+
abs: Math.abs,
|
|
325
|
+
min: Math.min,
|
|
326
|
+
max: Math.max,
|
|
327
|
+
encodeURI: encodeURI,
|
|
328
|
+
decodeURI: decodeURI,
|
|
329
|
+
encodeURIComponent: encodeURIComponent,
|
|
330
|
+
decodeURIComponent: decodeURIComponent,
|
|
331
|
+
trim: a => a.trim(),
|
|
332
|
+
uppercase: a => a.toUpperCase(),
|
|
333
|
+
lowercase: a => a.toLowerCase(),
|
|
334
|
+
substring: (s, a, b) => s.substring(a, b),
|
|
335
|
+
length: s => s.length,
|
|
336
|
+
join: (separator, ...args) =>
|
|
337
|
+
args
|
|
338
|
+
.map(item => (item instanceof Iterator ? Array.from(item) : item))
|
|
339
|
+
.flat()
|
|
340
|
+
.join(separator)
|
|
341
|
+
};
|
|
342
|
+
|
|
296
343
|
/**
|
|
297
|
-
* Split
|
|
344
|
+
* Split expression path into tokens.
|
|
298
345
|
* @generator
|
|
299
346
|
* @param {string} string
|
|
300
347
|
* @yields {Token}
|
|
301
348
|
*/
|
|
302
|
-
export function* tokens(string,
|
|
303
|
-
|
|
304
|
-
|
|
349
|
+
export function* tokens(string, context = {}) {
|
|
350
|
+
context.keywords ||= keywords;
|
|
351
|
+
context.parseFloat ||= parseFloat;
|
|
352
|
+
context.valueFor ||= (name,at) => globals[name];
|
|
305
353
|
|
|
306
354
|
let state, value, hex, quote;
|
|
307
355
|
|
|
308
356
|
const keywordOrIdentifier = () =>
|
|
309
|
-
|
|
357
|
+
context.keywords[value] || [IDENTIFIER, value];
|
|
310
358
|
const startString = c => {
|
|
311
359
|
value = "";
|
|
312
360
|
state = "string";
|
|
@@ -343,7 +391,7 @@ export function* tokens(string, options = {}) {
|
|
|
343
391
|
case " ":
|
|
344
392
|
switch (state) {
|
|
345
393
|
case "number":
|
|
346
|
-
yield [NUMBER,
|
|
394
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
347
395
|
state = undefined;
|
|
348
396
|
case undefined:
|
|
349
397
|
break;
|
|
@@ -372,7 +420,7 @@ export function* tokens(string, options = {}) {
|
|
|
372
420
|
case "'":
|
|
373
421
|
switch (state) {
|
|
374
422
|
case "number":
|
|
375
|
-
yield [NUMBER,
|
|
423
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
376
424
|
case undefined:
|
|
377
425
|
startString(c);
|
|
378
426
|
break;
|
|
@@ -400,7 +448,7 @@ export function* tokens(string, options = {}) {
|
|
|
400
448
|
case "|":
|
|
401
449
|
switch (state) {
|
|
402
450
|
case "number":
|
|
403
|
-
yield [NUMBER,
|
|
451
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
404
452
|
case undefined:
|
|
405
453
|
state = c;
|
|
406
454
|
break;
|
|
@@ -431,7 +479,7 @@ export function* tokens(string, options = {}) {
|
|
|
431
479
|
case "=":
|
|
432
480
|
switch (state) {
|
|
433
481
|
case "number":
|
|
434
|
-
yield [NUMBER,
|
|
482
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
435
483
|
case undefined:
|
|
436
484
|
state = c;
|
|
437
485
|
break;
|
|
@@ -472,7 +520,7 @@ export function* tokens(string, options = {}) {
|
|
|
472
520
|
case "}":
|
|
473
521
|
switch (state) {
|
|
474
522
|
case "number":
|
|
475
|
-
yield [NUMBER,
|
|
523
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
476
524
|
case undefined:
|
|
477
525
|
state = c;
|
|
478
526
|
break;
|
|
@@ -523,7 +571,7 @@ export function* tokens(string, options = {}) {
|
|
|
523
571
|
default:
|
|
524
572
|
switch (state) {
|
|
525
573
|
case "number":
|
|
526
|
-
yield [NUMBER,
|
|
574
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
527
575
|
case undefined:
|
|
528
576
|
state = "identifier";
|
|
529
577
|
value = c;
|
|
@@ -546,7 +594,7 @@ export function* tokens(string, options = {}) {
|
|
|
546
594
|
case "string":
|
|
547
595
|
throw new Error("unterminated string", { cause: string });
|
|
548
596
|
case "number":
|
|
549
|
-
yield [NUMBER,
|
|
597
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
550
598
|
break;
|
|
551
599
|
case "identifier":
|
|
552
600
|
yield keywordOrIdentifier();
|
package/types/ast.d.mts
CHANGED
|
@@ -4,8 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export function pathEval(node: any, current: any, context: any): any;
|
|
6
6
|
export function functionEval(node: any, current: any, context: any): any;
|
|
7
|
-
export
|
|
8
|
-
|
|
7
|
+
export function keyedAccessOrGlobalEval(node: any, current: any, context: any): any;
|
|
8
|
+
export function keyedAccessEval(node: any, current: any, context: any): any;
|
|
9
|
+
export function filterEval(node: any, current: any, context: any): any;
|
|
10
|
+
export function nullFilterEval(node: any, current: any, context: any): any;
|
|
11
|
+
export namespace ASTNullFilter {
|
|
12
|
+
export { nullFilterEval as eval };
|
|
9
13
|
}
|
|
10
14
|
export type AST = {
|
|
11
15
|
eval?: Function;
|
package/types/module.d.mts
CHANGED
|
@@ -7,7 +7,7 @@ export * from "./filter.mjs";
|
|
|
7
7
|
export * from "./multiple.mjs";
|
|
8
8
|
export * from "./common-attributes.mjs";
|
|
9
9
|
export * from "./properties.mjs";
|
|
10
|
-
export * from "./
|
|
10
|
+
export * from "./parser.mjs";
|
|
11
11
|
export * from "./expand.mjs";
|
|
12
12
|
export * from "./environment.mjs";
|
|
13
13
|
export { setAttribute, getAttribute, getAttributeAndOperator } from "./settergetter.mjs";
|
package/types/multiple.d.mts
CHANGED
|
@@ -10,9 +10,10 @@ export function setAttributes(object: any, source: any, definitions: any, cb: Fu
|
|
|
10
10
|
* Retrive attribute values from an object.
|
|
11
11
|
* @param {Object} object attribute value source
|
|
12
12
|
* @param {Object} definitions
|
|
13
|
+
* @param {Function} [filter]
|
|
13
14
|
* @return {Object} values
|
|
14
15
|
*/
|
|
15
|
-
export function getAttributes(object: any, definitions: any): any;
|
|
16
|
+
export function getAttributes(object: any, definitions: any, filter?: Function): any;
|
|
16
17
|
/**
|
|
17
18
|
* Retrive attribute values from an object.
|
|
18
19
|
* @param {Object} object attribute value source
|
package/types/settergetter.d.mts
CHANGED
|
@@ -4,17 +4,18 @@
|
|
|
4
4
|
* @param {Object} object
|
|
5
5
|
* @param {string} expression
|
|
6
6
|
* @param {any} value
|
|
7
|
-
* @param {Object} definition type def
|
|
7
|
+
* @param {Object} [definition] type def
|
|
8
8
|
*/
|
|
9
|
-
export function setAttribute(object: any, expression: string, value: any, definition
|
|
9
|
+
export function setAttribute(object: any, expression: string, value: any, definition?: any): void;
|
|
10
10
|
/**
|
|
11
11
|
* Deliver attribute value.
|
|
12
12
|
* The name may be a property path like 'a.b.c' or a[2]
|
|
13
13
|
* @param {Object} object
|
|
14
14
|
* @param {string} expression
|
|
15
|
+
* @param {Object} [definition]
|
|
15
16
|
* @returns {any} value associated with the given property name
|
|
16
17
|
*/
|
|
17
|
-
export function getAttribute(object: any, expression: string, definition
|
|
18
|
+
export function getAttribute(object: any, expression: string, definition?: any): any;
|
|
18
19
|
/**
|
|
19
20
|
* Deliver attribute value and operator.
|
|
20
21
|
* The name may be a property path like 'a.b.c <='.
|
package/types/tokens.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Split
|
|
2
|
+
* Split expression path into tokens.
|
|
3
3
|
* @generator
|
|
4
4
|
* @param {string} string
|
|
5
5
|
* @yields {Token}
|
|
6
6
|
*/
|
|
7
|
-
export function tokens(string: string,
|
|
7
|
+
export function tokens(string: string, context?: {}): Generator<any, void, unknown>;
|
|
8
8
|
export namespace PLUS {
|
|
9
9
|
let str: string;
|
|
10
10
|
}
|
|
@@ -46,6 +46,25 @@ export namespace keywords {
|
|
|
46
46
|
let _false: (boolean | Token)[];
|
|
47
47
|
export { _false as false };
|
|
48
48
|
}
|
|
49
|
+
export namespace globals {
|
|
50
|
+
export function _in(a: any, b: any): boolean;
|
|
51
|
+
export { _in as in };
|
|
52
|
+
export let ceil: (x: number) => number;
|
|
53
|
+
export let floor: (x: number) => number;
|
|
54
|
+
export let abs: (x: number) => number;
|
|
55
|
+
export let min: (...values: number[]) => number;
|
|
56
|
+
export let max: (...values: number[]) => number;
|
|
57
|
+
export let encodeURI: typeof globalThis.encodeURI;
|
|
58
|
+
export let decodeURI: typeof globalThis.decodeURI;
|
|
59
|
+
export let encodeURIComponent: typeof globalThis.encodeURIComponent;
|
|
60
|
+
export let decodeURIComponent: typeof globalThis.decodeURIComponent;
|
|
61
|
+
export function trim(a: any): any;
|
|
62
|
+
export function uppercase(a: any): any;
|
|
63
|
+
export function lowercase(a: any): any;
|
|
64
|
+
export function substring(s: any, a: any, b: any): any;
|
|
65
|
+
export function length(s: any): any;
|
|
66
|
+
export function join(separator: any, ...args: any[]): string;
|
|
67
|
+
}
|
|
49
68
|
export type Token = {
|
|
50
69
|
str: string;
|
|
51
70
|
};
|
package/types/expression.d.mts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export function parseOnly(input: any, context?: {}): any;
|
|
2
|
-
export function parse(input: any, context: any): any;
|
|
3
|
-
export namespace globals {
|
|
4
|
-
export function _in(a: any, b: any): boolean;
|
|
5
|
-
export { _in as in };
|
|
6
|
-
export let ceil: (x: number) => number;
|
|
7
|
-
export let floor: (x: number) => number;
|
|
8
|
-
export let abs: (x: number) => number;
|
|
9
|
-
export let min: (...values: number[]) => number;
|
|
10
|
-
export let max: (...values: number[]) => number;
|
|
11
|
-
export let encodeURI: typeof globalThis.encodeURI;
|
|
12
|
-
export let decodeURI: typeof globalThis.decodeURI;
|
|
13
|
-
export let encodeURIComponent: typeof globalThis.encodeURIComponent;
|
|
14
|
-
export let decodeURIComponent: typeof globalThis.decodeURIComponent;
|
|
15
|
-
export function trim(a: any): any;
|
|
16
|
-
export function uppercase(a: any): any;
|
|
17
|
-
export function lowercase(a: any): any;
|
|
18
|
-
export function substring(s: any, a: any, b: any): any;
|
|
19
|
-
export function length(s: any): any;
|
|
20
|
-
export function join(separator: any, ...args: any[]): string;
|
|
21
|
-
}
|