pacc 8.11.6 → 9.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 +7 -6
- package/package.json +2 -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 +115 -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 +23 -2
- package/types/expression.d.mts +0 -21
package/README.md
CHANGED
|
@@ -546,6 +546,7 @@ Retrive attribute values from an object.
|
|
|
546
546
|
|
|
547
547
|
* `object` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** attribute value source
|
|
548
548
|
* `definitions` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** 
|
|
549
|
+
* `filter` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** 
|
|
549
550
|
|
|
550
551
|
Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** values
|
|
551
552
|
|
|
@@ -565,12 +566,12 @@ Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/G
|
|
|
565
566
|
|
|
566
567
|
## tokens
|
|
567
568
|
|
|
568
|
-
Split
|
|
569
|
+
Split expression path into tokens.
|
|
569
570
|
|
|
570
571
|
### Parameters
|
|
571
572
|
|
|
572
573
|
* `string` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** 
|
|
573
|
-
* `
|
|
574
|
+
* `context` (optional, default `{}`)
|
|
574
575
|
|
|
575
576
|
## setAttribute
|
|
576
577
|
|
|
@@ -582,7 +583,7 @@ The name may be a property path like 'a.b.c'.
|
|
|
582
583
|
* `object` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** 
|
|
583
584
|
* `expression` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** 
|
|
584
585
|
* `value` **any** 
|
|
585
|
-
* `definition` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
|
|
586
|
+
* `definition` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** type def
|
|
586
587
|
|
|
587
588
|
## getAttribute
|
|
588
589
|
|
|
@@ -593,7 +594,7 @@ The name may be a property path like 'a.b.c' or a\[2]
|
|
|
593
594
|
|
|
594
595
|
* `object` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** 
|
|
595
596
|
* `expression` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** 
|
|
596
|
-
* `definition`
|
|
597
|
+
* `definition` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** 
|
|
597
598
|
|
|
598
599
|
Returns **any** value associated with the given property name
|
|
599
600
|
|
|
@@ -654,8 +655,8 @@ Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Globa
|
|
|
654
655
|
* `str` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** 
|
|
655
656
|
* `precedence` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** (optional, default `0`)
|
|
656
657
|
* `type` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** 
|
|
657
|
-
* `led` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** (optional, default `()=>
|
|
658
|
-
* `nud` (optional, default `
|
|
658
|
+
* `led` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** (optional, default `(parser,node)=>node`)
|
|
659
|
+
* `nud` (optional, default `parser=>this`)
|
|
659
660
|
|
|
660
661
|
Returns **[Token](#token)** 
|
|
661
662
|
|
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,65 @@ 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
|
+
sort: data => {
|
|
342
|
+
return data.sort();
|
|
343
|
+
},
|
|
344
|
+
truncate: (data, length) => {
|
|
345
|
+
data.length = length;
|
|
346
|
+
return data;
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
|
|
296
350
|
/**
|
|
297
|
-
* Split
|
|
351
|
+
* Split expression path into tokens.
|
|
298
352
|
* @generator
|
|
299
353
|
* @param {string} string
|
|
300
354
|
* @yields {Token}
|
|
301
355
|
*/
|
|
302
|
-
export function* tokens(string,
|
|
303
|
-
|
|
304
|
-
|
|
356
|
+
export function* tokens(string, context = {}) {
|
|
357
|
+
context.keywords ||= keywords;
|
|
358
|
+
context.parseFloat ||= parseFloat;
|
|
359
|
+
context.valueFor ||= (name, at) => globals[name];
|
|
305
360
|
|
|
306
361
|
let state, value, hex, quote;
|
|
307
362
|
|
|
308
363
|
const keywordOrIdentifier = () =>
|
|
309
|
-
|
|
364
|
+
context.keywords[value] || [IDENTIFIER, value];
|
|
310
365
|
const startString = c => {
|
|
311
366
|
value = "";
|
|
312
367
|
state = "string";
|
|
@@ -343,7 +398,7 @@ export function* tokens(string, options = {}) {
|
|
|
343
398
|
case " ":
|
|
344
399
|
switch (state) {
|
|
345
400
|
case "number":
|
|
346
|
-
yield [NUMBER,
|
|
401
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
347
402
|
state = undefined;
|
|
348
403
|
case undefined:
|
|
349
404
|
break;
|
|
@@ -372,7 +427,7 @@ export function* tokens(string, options = {}) {
|
|
|
372
427
|
case "'":
|
|
373
428
|
switch (state) {
|
|
374
429
|
case "number":
|
|
375
|
-
yield [NUMBER,
|
|
430
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
376
431
|
case undefined:
|
|
377
432
|
startString(c);
|
|
378
433
|
break;
|
|
@@ -400,7 +455,7 @@ export function* tokens(string, options = {}) {
|
|
|
400
455
|
case "|":
|
|
401
456
|
switch (state) {
|
|
402
457
|
case "number":
|
|
403
|
-
yield [NUMBER,
|
|
458
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
404
459
|
case undefined:
|
|
405
460
|
state = c;
|
|
406
461
|
break;
|
|
@@ -431,7 +486,7 @@ export function* tokens(string, options = {}) {
|
|
|
431
486
|
case "=":
|
|
432
487
|
switch (state) {
|
|
433
488
|
case "number":
|
|
434
|
-
yield [NUMBER,
|
|
489
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
435
490
|
case undefined:
|
|
436
491
|
state = c;
|
|
437
492
|
break;
|
|
@@ -472,7 +527,7 @@ export function* tokens(string, options = {}) {
|
|
|
472
527
|
case "}":
|
|
473
528
|
switch (state) {
|
|
474
529
|
case "number":
|
|
475
|
-
yield [NUMBER,
|
|
530
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
476
531
|
case undefined:
|
|
477
532
|
state = c;
|
|
478
533
|
break;
|
|
@@ -523,7 +578,7 @@ export function* tokens(string, options = {}) {
|
|
|
523
578
|
default:
|
|
524
579
|
switch (state) {
|
|
525
580
|
case "number":
|
|
526
|
-
yield [NUMBER,
|
|
581
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
527
582
|
case undefined:
|
|
528
583
|
state = "identifier";
|
|
529
584
|
value = c;
|
|
@@ -546,7 +601,7 @@ export function* tokens(string, options = {}) {
|
|
|
546
601
|
case "string":
|
|
547
602
|
throw new Error("unterminated string", { cause: string });
|
|
548
603
|
case "number":
|
|
549
|
-
yield [NUMBER,
|
|
604
|
+
yield [NUMBER, context.parseFloat(value)];
|
|
550
605
|
break;
|
|
551
606
|
case "identifier":
|
|
552
607
|
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,27 @@ 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
|
+
export function sort(data: any): any;
|
|
68
|
+
export function truncate(data: any, length: any): any;
|
|
69
|
+
}
|
|
49
70
|
export type Token = {
|
|
50
71
|
str: string;
|
|
51
72
|
};
|
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
|
-
}
|