pacc 8.11.5 → 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 -56
- 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,14 +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
|
-
|
|
161
|
+
return {
|
|
162
|
+
eval: functionEval,
|
|
163
|
+
name: left.key,
|
|
164
|
+
args: Array.isArray(args) ? args : [args]
|
|
165
|
+
};
|
|
157
166
|
},
|
|
158
167
|
parser => {
|
|
159
168
|
const result = parser.expression(0);
|
|
@@ -163,38 +172,40 @@ export /** @type {Token} */ const OPEN_ROUND = createToken(
|
|
|
163
172
|
);
|
|
164
173
|
|
|
165
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
|
+
|
|
166
194
|
export /** @type {Token} */ const OPEN_BRACKET = createToken(
|
|
167
195
|
"[",
|
|
168
|
-
|
|
196
|
+
80,
|
|
169
197
|
"prefix",
|
|
170
198
|
(parser, left) => {
|
|
171
|
-
|
|
172
|
-
parser.advance();
|
|
173
|
-
left.path.push(ASTTrue);
|
|
174
|
-
} else {
|
|
175
|
-
const predicate = parser.expression(0);
|
|
176
|
-
parser.expect(CLOSE_BRACKET);
|
|
177
|
-
left.path.push(predicate);
|
|
178
|
-
}
|
|
179
|
-
return left;
|
|
180
|
-
},
|
|
181
|
-
parser => {
|
|
182
|
-
if (parser.token === CLOSE_BRACKET) {
|
|
183
|
-
parser.advance();
|
|
184
|
-
return ASTTrue;
|
|
185
|
-
}
|
|
199
|
+
const node = createFilter(parser);
|
|
186
200
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
switch (typeof node) {
|
|
191
|
-
case "string":
|
|
192
|
-
case "number":
|
|
193
|
-
return { eval: pathEval, path: [node] };
|
|
201
|
+
if (left.key) {
|
|
202
|
+
return { eval: pathEval, path: [left, node] };
|
|
194
203
|
}
|
|
195
204
|
|
|
196
|
-
|
|
197
|
-
|
|
205
|
+
left.path.push(node);
|
|
206
|
+
return left;
|
|
207
|
+
},
|
|
208
|
+
parser => createFilter(parser)
|
|
198
209
|
);
|
|
199
210
|
|
|
200
211
|
export /** @type {Token} */ const CLOSE_BRACKET = createToken("]", 0);
|
|
@@ -203,19 +214,27 @@ export /** @type {Token} */ const CLOSE_CURLY = createToken("}");
|
|
|
203
214
|
export /** @type {Token} */ const QUESTION = createToken("?", 20, "infix");
|
|
204
215
|
export /** @type {Token} */ const COLON = createToken(":", undefined, "infix");
|
|
205
216
|
export /** @type {Token} */ const SEMICOLON = createToken(";");
|
|
206
|
-
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
|
+
);
|
|
207
223
|
|
|
208
224
|
export /** @type {Token} */ const DOT = createToken(
|
|
209
225
|
".",
|
|
210
226
|
80,
|
|
211
227
|
"infix",
|
|
212
228
|
(left, right) => {
|
|
229
|
+
if (right.eval === keyedAccessOrGlobalEval) {
|
|
230
|
+
right.eval = keyedAccessEval;
|
|
231
|
+
}
|
|
213
232
|
if (left.path) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
right.path.unshift(left);
|
|
233
|
+
left.path.push(right);
|
|
234
|
+
return left;
|
|
217
235
|
}
|
|
218
|
-
|
|
236
|
+
|
|
237
|
+
return { eval: pathEval, path: [left, right] };
|
|
219
238
|
}
|
|
220
239
|
);
|
|
221
240
|
export /** @type {Token} */ const AMPERSAND = createToken("&");
|
|
@@ -238,7 +257,7 @@ export /** @type {Token} */ const IDENTIFIER = createToken(
|
|
|
238
257
|
undefined,
|
|
239
258
|
undefined,
|
|
240
259
|
parser => {
|
|
241
|
-
return { eval:
|
|
260
|
+
return { eval: keyedAccessOrGlobalEval, key: parser.value };
|
|
242
261
|
}
|
|
243
262
|
);
|
|
244
263
|
|
|
@@ -275,11 +294,6 @@ export /** @type {Token} */ const EOF = createToken(
|
|
|
275
294
|
}
|
|
276
295
|
);
|
|
277
296
|
|
|
278
|
-
export const keywords = {
|
|
279
|
-
true: [BOOLEAN, true],
|
|
280
|
-
false: [BOOLEAN, false]
|
|
281
|
-
};
|
|
282
|
-
|
|
283
297
|
const esc = {
|
|
284
298
|
b: "\b",
|
|
285
299
|
f: "\f",
|
|
@@ -289,20 +303,58 @@ const esc = {
|
|
|
289
303
|
v: "\v"
|
|
290
304
|
};
|
|
291
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
|
+
|
|
292
343
|
/**
|
|
293
|
-
* Split
|
|
344
|
+
* Split expression path into tokens.
|
|
294
345
|
* @generator
|
|
295
346
|
* @param {string} string
|
|
296
347
|
* @yields {Token}
|
|
297
348
|
*/
|
|
298
|
-
export function* tokens(string,
|
|
299
|
-
|
|
300
|
-
|
|
349
|
+
export function* tokens(string, context = {}) {
|
|
350
|
+
context.keywords ||= keywords;
|
|
351
|
+
context.parseFloat ||= parseFloat;
|
|
352
|
+
context.valueFor ||= (name,at) => globals[name];
|
|
301
353
|
|
|
302
354
|
let state, value, hex, quote;
|
|
303
355
|
|
|
304
356
|
const keywordOrIdentifier = () =>
|
|
305
|
-
|
|
357
|
+
context.keywords[value] || [IDENTIFIER, value];
|
|
306
358
|
const startString = c => {
|
|
307
359
|
value = "";
|
|
308
360
|
state = "string";
|
|
@@ -339,7 +391,7 @@ export function* tokens(string, options = {}) {
|
|
|
339
391
|
case " ":
|
|
340
392
|
switch (state) {
|
|
341
393
|
case "number":
|
|
342
|
-
yield [NUMBER,
|
|
394
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
343
395
|
state = undefined;
|
|
344
396
|
case undefined:
|
|
345
397
|
break;
|
|
@@ -368,7 +420,7 @@ export function* tokens(string, options = {}) {
|
|
|
368
420
|
case "'":
|
|
369
421
|
switch (state) {
|
|
370
422
|
case "number":
|
|
371
|
-
yield [NUMBER,
|
|
423
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
372
424
|
case undefined:
|
|
373
425
|
startString(c);
|
|
374
426
|
break;
|
|
@@ -396,7 +448,7 @@ export function* tokens(string, options = {}) {
|
|
|
396
448
|
case "|":
|
|
397
449
|
switch (state) {
|
|
398
450
|
case "number":
|
|
399
|
-
yield [NUMBER,
|
|
451
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
400
452
|
case undefined:
|
|
401
453
|
state = c;
|
|
402
454
|
break;
|
|
@@ -427,7 +479,7 @@ export function* tokens(string, options = {}) {
|
|
|
427
479
|
case "=":
|
|
428
480
|
switch (state) {
|
|
429
481
|
case "number":
|
|
430
|
-
yield [NUMBER,
|
|
482
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
431
483
|
case undefined:
|
|
432
484
|
state = c;
|
|
433
485
|
break;
|
|
@@ -468,7 +520,7 @@ export function* tokens(string, options = {}) {
|
|
|
468
520
|
case "}":
|
|
469
521
|
switch (state) {
|
|
470
522
|
case "number":
|
|
471
|
-
yield [NUMBER,
|
|
523
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
472
524
|
case undefined:
|
|
473
525
|
state = c;
|
|
474
526
|
break;
|
|
@@ -519,7 +571,7 @@ export function* tokens(string, options = {}) {
|
|
|
519
571
|
default:
|
|
520
572
|
switch (state) {
|
|
521
573
|
case "number":
|
|
522
|
-
yield [NUMBER,
|
|
574
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
523
575
|
case undefined:
|
|
524
576
|
state = "identifier";
|
|
525
577
|
value = c;
|
|
@@ -542,7 +594,7 @@ export function* tokens(string, options = {}) {
|
|
|
542
594
|
case "string":
|
|
543
595
|
throw new Error("unterminated string", { cause: string });
|
|
544
596
|
case "number":
|
|
545
|
-
yield [NUMBER,
|
|
597
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
546
598
|
break;
|
|
547
599
|
case "identifier":
|
|
548
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
|
-
}
|