amis-formula 1.3.13 → 2.0.0-beta.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 +1 -1
- package/__mocks__/styleMock.js +6 -0
- package/__mocks__/svgMock.js +5 -0
- package/__tests__/__snapshots__/lexer.test.ts.snap +31 -0
- package/__tests__/__snapshots__/parser.test.ts.snap +2306 -0
- package/__tests__/evalute.test.ts +437 -0
- package/__tests__/fomula.test.ts +194 -0
- package/__tests__/jest.setup.js +22 -0
- package/__tests__/lexer.test.ts +55 -0
- package/__tests__/parser.test.ts +201 -0
- package/dist/evalutor.d.ts +5 -0
- package/dist/filter.d.ts +6 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +3032 -3841
- package/dist/lexer.d.ts +1 -29
- package/dist/parser.d.ts +1 -26
- package/dist/types.d.ts +83 -0
- package/package.json +1 -1
- package/rollup.config.js +3 -1
- package/scripts/genDoc.ts +162 -0
- package/scripts/lib.ts +55 -0
- package/src/evalutor.ts +1938 -0
- package/src/filter.ts +48 -0
- package/src/index.ts +35 -0
- package/src/lexer.ts +775 -0
- package/src/parser.ts +875 -0
- package/src/types.ts +119 -0
- package/tsconfig.json +36 -0
- package/.prettierrc +0 -20
- package/dist/util.d.ts +0 -36
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
import {evaluate, parse} from '../src';
|
|
2
|
+
|
|
3
|
+
test('evalute:simple', () => {
|
|
4
|
+
expect(
|
|
5
|
+
evaluate('a is ${a}', {
|
|
6
|
+
a: 123
|
|
7
|
+
})
|
|
8
|
+
).toBe('a is 123');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('evalute:filter', () => {
|
|
12
|
+
expect(
|
|
13
|
+
evaluate(
|
|
14
|
+
'a is ${a | abc}',
|
|
15
|
+
{
|
|
16
|
+
a: 123
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
filters: {
|
|
20
|
+
abc(input: any) {
|
|
21
|
+
return `${input}456`;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
).toBe('a is 123456');
|
|
27
|
+
|
|
28
|
+
expect(
|
|
29
|
+
evaluate(
|
|
30
|
+
'a is ${a | concat:233}',
|
|
31
|
+
{
|
|
32
|
+
a: 123
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
filters: {
|
|
36
|
+
concat(input: any, arg: string) {
|
|
37
|
+
return `${input}${arg}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
).toBe('a is 123233');
|
|
43
|
+
|
|
44
|
+
expect(
|
|
45
|
+
evaluate(
|
|
46
|
+
'a is ${concat(a, a)}',
|
|
47
|
+
{
|
|
48
|
+
a: 123
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
filters: {
|
|
52
|
+
concat(input: any, arg: string) {
|
|
53
|
+
return `${input}${arg}`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
)
|
|
58
|
+
).toBe('a is 123123');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('evalute:filter2', () => {
|
|
62
|
+
expect(
|
|
63
|
+
evaluate(
|
|
64
|
+
'a is ${[1, 2, 3] | concat:4 | join}',
|
|
65
|
+
{},
|
|
66
|
+
{
|
|
67
|
+
filters: {
|
|
68
|
+
concat(input: any, ...args: Array<any>) {
|
|
69
|
+
return input.concat.apply(input, args);
|
|
70
|
+
},
|
|
71
|
+
join(input: any) {
|
|
72
|
+
return input.join(',');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
).toBe('a is 1,2,3,4');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('evalute:filter3', () => {
|
|
81
|
+
expect(
|
|
82
|
+
evaluate(
|
|
83
|
+
'a is ${[1, 2, 3] | concat:"4" | join}',
|
|
84
|
+
{},
|
|
85
|
+
{
|
|
86
|
+
filters: {
|
|
87
|
+
concat(input: any, ...args: Array<any>) {
|
|
88
|
+
return input.concat.apply(input, args);
|
|
89
|
+
},
|
|
90
|
+
join(input: any) {
|
|
91
|
+
return input.join(',');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
).toBe('a is 1,2,3,4');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('evalute:filter4', () => {
|
|
100
|
+
expect(
|
|
101
|
+
evaluate(
|
|
102
|
+
'a is ${[1, 2, 3] | concat:${a + 3} | join}',
|
|
103
|
+
{
|
|
104
|
+
a: 4
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
filters: {
|
|
108
|
+
concat(input: any, ...args: Array<any>) {
|
|
109
|
+
return input.concat.apply(input, args);
|
|
110
|
+
},
|
|
111
|
+
join(input: any) {
|
|
112
|
+
return input.join(',');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
).toBe('a is 1,2,3,7');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('evalute:oldVariable', () => {
|
|
121
|
+
expect(
|
|
122
|
+
evaluate('a is $a', {
|
|
123
|
+
a: 4
|
|
124
|
+
})
|
|
125
|
+
).toBe('a is 4');
|
|
126
|
+
|
|
127
|
+
expect(
|
|
128
|
+
evaluate('b is $b', {
|
|
129
|
+
a: 4
|
|
130
|
+
})
|
|
131
|
+
).toBe('b is ');
|
|
132
|
+
|
|
133
|
+
expect(
|
|
134
|
+
evaluate('a.b is $a.b', {
|
|
135
|
+
a: {
|
|
136
|
+
b: 233
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
).toBe('a.b is 233');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test('evalute:ariable2', () => {
|
|
143
|
+
expect(
|
|
144
|
+
evaluate('a is $$', {
|
|
145
|
+
a: 4
|
|
146
|
+
})
|
|
147
|
+
).toBe('a is [object Object]');
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test('evalute:ariable3', () => {
|
|
151
|
+
expect(
|
|
152
|
+
evaluate(
|
|
153
|
+
'$$',
|
|
154
|
+
{
|
|
155
|
+
a: 4
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
defaultFilter: 'raw'
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
).toMatchObject({
|
|
162
|
+
a: 4
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test('evalute:object-variable', () => {
|
|
167
|
+
const data = {
|
|
168
|
+
key: 'x',
|
|
169
|
+
obj: {
|
|
170
|
+
x: 1,
|
|
171
|
+
y: 2
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
expect(evaluate('a is ${obj.x}', data)).toBe('a is 1');
|
|
176
|
+
expect(evaluate('a is ${obj[x]}', data)).toBe('a is 1');
|
|
177
|
+
expect(evaluate('a is ${obj[`x`]}', data)).toBe('a is 1');
|
|
178
|
+
expect(evaluate('a is ${obj["x"]}', data)).toBe('a is 1');
|
|
179
|
+
expect(evaluate('a is ${obj[key]}', data)).toBe('a is 1');
|
|
180
|
+
expect(evaluate('a is ${obj[`${key}`]}', data)).toBe('a is 1');
|
|
181
|
+
expect(evaluate('a is ${obj[${key}]}', data)).toBe('a is 1');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test('evalute:literal-variable', () => {
|
|
185
|
+
const data = {
|
|
186
|
+
key: 'x',
|
|
187
|
+
index: 0,
|
|
188
|
+
obj: {
|
|
189
|
+
x: 1,
|
|
190
|
+
y: 2
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
expect(evaluate('a is ${({x: 1})["x"]}', data)).toBe('a is 1');
|
|
195
|
+
expect(evaluate('a is ${({x: 1}).x}', data)).toBe('a is 1');
|
|
196
|
+
expect(evaluate('a is ${(["a", "b"])[index]}', data)).toBe('a is a');
|
|
197
|
+
expect(evaluate('a is ${(["a", "b"])[1]}', data)).toBe('a is b');
|
|
198
|
+
expect(evaluate('a is ${(["a", "b"]).0}', data)).toBe('a is a');
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test('evalute:tempalte', () => {
|
|
202
|
+
const data = {
|
|
203
|
+
key: 'x'
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
expect(evaluate('abc${`11${3}22`}xyz', data)).toBe('abc11322xyz');
|
|
207
|
+
expect(evaluate('abc${`${3}22`}xyz', data)).toBe('abc322xyz');
|
|
208
|
+
expect(evaluate('abc${`11${3}`}xyz', data)).toBe('abc113xyz');
|
|
209
|
+
expect(evaluate('abc${`${3}`}xyz', data)).toBe('abc3xyz');
|
|
210
|
+
expect(evaluate('abc${`${key}`}xyz', data)).toBe('abcxxyz');
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test('evalute:literal', () => {
|
|
214
|
+
const data = {
|
|
215
|
+
dynamicKey: 'alpha'
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
expect(
|
|
219
|
+
evaluate('${{a: 1, 0: 2, "3": 3}}', data, {
|
|
220
|
+
defaultFilter: 'raw'
|
|
221
|
+
})
|
|
222
|
+
).toMatchObject({
|
|
223
|
+
a: 1,
|
|
224
|
+
0: 2,
|
|
225
|
+
3: 3
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
expect(
|
|
229
|
+
evaluate('${{a: 1, 0: 2, "3": 3, [`4`]: 4}}', data, {
|
|
230
|
+
defaultFilter: 'raw'
|
|
231
|
+
})
|
|
232
|
+
).toMatchObject({
|
|
233
|
+
a: 1,
|
|
234
|
+
0: 2,
|
|
235
|
+
3: 3,
|
|
236
|
+
4: 4
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
expect(
|
|
240
|
+
evaluate('${{a: 1, 0: 2, "3": 3, [`${dynamicKey}233`]: 4}}', data, {
|
|
241
|
+
defaultFilter: 'raw'
|
|
242
|
+
})
|
|
243
|
+
).toMatchObject({
|
|
244
|
+
a: 1,
|
|
245
|
+
0: 2,
|
|
246
|
+
3: 3,
|
|
247
|
+
alpha233: 4
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
expect(
|
|
251
|
+
evaluate('${[1, 2, `2${dynamicKey}2`, {a: 1, 0: 2, [`2`]: "3"}]}', data, {
|
|
252
|
+
defaultFilter: 'raw'
|
|
253
|
+
})
|
|
254
|
+
).toMatchObject([1, 2, `2alpha2`, {a: 1, 0: 2, [`2`]: '3'}]);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
test('evalute:variableName', () => {
|
|
258
|
+
const data = {
|
|
259
|
+
'a-b': 'c',
|
|
260
|
+
'222': 10222,
|
|
261
|
+
'222_221': 233,
|
|
262
|
+
'222_abcde': 'abcde',
|
|
263
|
+
'222-221': 333
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
expect(evaluate('${a-b}', data)).toBe('c');
|
|
267
|
+
expect(evaluate('${222}', data)).toBe(222);
|
|
268
|
+
expect(evaluate('${222_221}', data)).toBe('233');
|
|
269
|
+
expect(evaluate('${222-221}', data)).toBe(1);
|
|
270
|
+
expect(evaluate('${222_abcde}', data)).toBe('abcde');
|
|
271
|
+
expect(
|
|
272
|
+
evaluate('${&["222-221"]}', data, {
|
|
273
|
+
defaultFilter: 'raw'
|
|
274
|
+
})
|
|
275
|
+
).toBe(333);
|
|
276
|
+
expect(
|
|
277
|
+
evaluate('222', data, {
|
|
278
|
+
variableMode: true
|
|
279
|
+
})
|
|
280
|
+
).toBe(10222);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
test('evalute:3-1', () => {
|
|
284
|
+
const data = {};
|
|
285
|
+
|
|
286
|
+
expect(evaluate('${3-1}', data)).toBe(2);
|
|
287
|
+
expect(evaluate('${-1 + 2.5 + 3}', data)).toBe(4.5);
|
|
288
|
+
expect(evaluate('${-1 + -1}', data)).toBe(-2);
|
|
289
|
+
expect(evaluate('${3 * -1}', data)).toBe(-3);
|
|
290
|
+
|
|
291
|
+
expect(evaluate('${3 + +1}', data)).toBe(4);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
test('evalate:0.1+0.2', () => {
|
|
295
|
+
expect(evaluate('${0.1 + 0.2}', {})).toBe(0.3);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
test('evalute:variable:com.xxx.xx', () => {
|
|
299
|
+
const data = {
|
|
300
|
+
'com.xxx.xx': 'abc',
|
|
301
|
+
'com xxx%xx': 'cde',
|
|
302
|
+
'com[xxx]': 'eee'
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
expect(evaluate('${com\\.xxx\\.xx}', data)).toBe('abc');
|
|
306
|
+
expect(evaluate('${com\\ xxx\\%xx}', data)).toBe('cde');
|
|
307
|
+
expect(evaluate('${com\\[xxx\\]}', data)).toBe('eee');
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
test('evalute:anonymous:function', () => {
|
|
311
|
+
const data = {
|
|
312
|
+
arr: [1, 2, 3],
|
|
313
|
+
arr2: [
|
|
314
|
+
{
|
|
315
|
+
a: 1
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
a: 2
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
a: 3
|
|
322
|
+
}
|
|
323
|
+
],
|
|
324
|
+
outter: 4
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
expect(evaluate('${() => 233}', data)).toMatchObject({
|
|
328
|
+
args: [],
|
|
329
|
+
return: {type: 'literal', value: 233},
|
|
330
|
+
type: 'anonymous_function'
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
expect(evaluate('${ARRAYMAP(arr, () => 1)}', data)).toMatchObject([1, 1, 1]);
|
|
334
|
+
expect(evaluate('${ARRAYMAP(arr, item => item)}', data)).toMatchObject([
|
|
335
|
+
1, 2, 3
|
|
336
|
+
]);
|
|
337
|
+
expect(evaluate('${ARRAYMAP(arr, item => item * 2)}', data)).toMatchObject([
|
|
338
|
+
2, 4, 6
|
|
339
|
+
]);
|
|
340
|
+
expect(
|
|
341
|
+
evaluate('${ARRAYMAP(arr2, (item, index) => `a${item.a}${index}`)}', data)
|
|
342
|
+
).toMatchObject(['a10', 'a21', 'a32']);
|
|
343
|
+
expect(
|
|
344
|
+
evaluate(
|
|
345
|
+
'${ARRAYMAP(arr2, (item, index) => `a${item.a}${index}${outter}`)}',
|
|
346
|
+
data
|
|
347
|
+
)
|
|
348
|
+
).toMatchObject(['a104', 'a214', 'a324']);
|
|
349
|
+
expect(
|
|
350
|
+
evaluate(
|
|
351
|
+
'${ARRAYMAP(arr2, (item, index) => {x: item.a, index: index})}',
|
|
352
|
+
data
|
|
353
|
+
)
|
|
354
|
+
).toMatchObject([
|
|
355
|
+
{
|
|
356
|
+
x: 1,
|
|
357
|
+
index: 0
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
x: 2,
|
|
361
|
+
index: 1
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
x: 3,
|
|
365
|
+
index: 2
|
|
366
|
+
}
|
|
367
|
+
]);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
test('evalute:anonymous:function2', () => {
|
|
371
|
+
const data = {
|
|
372
|
+
arr: [1, 2, 3],
|
|
373
|
+
arr2: [
|
|
374
|
+
{
|
|
375
|
+
x: 1,
|
|
376
|
+
y: [
|
|
377
|
+
{
|
|
378
|
+
z: 1
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
z: 1
|
|
382
|
+
}
|
|
383
|
+
]
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
x: 2,
|
|
387
|
+
y: [
|
|
388
|
+
{
|
|
389
|
+
z: 2
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
z: 2
|
|
393
|
+
}
|
|
394
|
+
]
|
|
395
|
+
}
|
|
396
|
+
]
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
expect(
|
|
400
|
+
evaluate(
|
|
401
|
+
'${ARRAYMAP(ARRAYMAP(arr, item => item * 2), item => item + 2)}',
|
|
402
|
+
data
|
|
403
|
+
)
|
|
404
|
+
).toMatchObject([4, 6, 8]);
|
|
405
|
+
|
|
406
|
+
expect(
|
|
407
|
+
evaluate('${ARRAYMAP(arr2, item => ARRAYMAP(item.y, i => i.z))}', data)
|
|
408
|
+
).toMatchObject([
|
|
409
|
+
[1, 1],
|
|
410
|
+
[2, 2]
|
|
411
|
+
]);
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
test('evalute:array:func', () => {
|
|
415
|
+
const data = {
|
|
416
|
+
arr1: [0, 1, false, 2, '', 3],
|
|
417
|
+
arr2: ['a', 'b', 'c'],
|
|
418
|
+
arr3: [1, 2, 3],
|
|
419
|
+
arr4: [2, 4, 6]
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
expect(evaluate('${COMPACT(arr1)}', data)).toMatchObject([1, 2, 3]);
|
|
423
|
+
|
|
424
|
+
expect(evaluate("${COMPACT([0, 1, false, 2, '', 3])}", data)).toMatchObject([
|
|
425
|
+
1, 2, 3
|
|
426
|
+
]);
|
|
427
|
+
|
|
428
|
+
expect(evaluate('${JOIN(arr2, "~")}', data)).toMatch('a~b~c');
|
|
429
|
+
|
|
430
|
+
expect(evaluate('${SUM(arr3)}', data)).toBe(6);
|
|
431
|
+
|
|
432
|
+
expect(evaluate('${AVG(arr4)}', data)).toBe(4);
|
|
433
|
+
|
|
434
|
+
expect(evaluate('${MIN(arr4)}', data)).toBe(2);
|
|
435
|
+
|
|
436
|
+
expect(evaluate('${MAX(arr4)}', data)).toBe(6);
|
|
437
|
+
});
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import moment from 'moment';
|
|
2
|
+
import {evaluate, parse} from '../src';
|
|
3
|
+
|
|
4
|
+
const defaultContext = {
|
|
5
|
+
a: 1,
|
|
6
|
+
b: 2,
|
|
7
|
+
c: 3,
|
|
8
|
+
d: 4,
|
|
9
|
+
e: 5
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function evalFormual(expression: string, data: any = defaultContext) {
|
|
13
|
+
return evaluate(expression, data, {
|
|
14
|
+
evalMode: true
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
test('formula:expression', () => {
|
|
19
|
+
expect(evalFormual('a + 3')).toBe(4);
|
|
20
|
+
expect(evalFormual('b * 3')).toBe(6);
|
|
21
|
+
expect(evalFormual('b * 3 + 4')).toBe(10);
|
|
22
|
+
expect(evalFormual('c * (3 + 4)')).toBe(21);
|
|
23
|
+
expect(evalFormual('d / (a + 1)')).toBe(2);
|
|
24
|
+
expect(evalFormual('5 % 3')).toBe(2);
|
|
25
|
+
expect(evalFormual('3 | 4')).toBe(7);
|
|
26
|
+
expect(evalFormual('4 ^ 4')).toBe(0);
|
|
27
|
+
expect(evalFormual('4 ^ 4')).toBe(0);
|
|
28
|
+
expect(evalFormual('4 & 4')).toBe(4);
|
|
29
|
+
expect(evalFormual('4 & 3')).toBe(0);
|
|
30
|
+
expect(evalFormual('~-1')).toBe(0);
|
|
31
|
+
expect(evalFormual('!!1')).toBe(true);
|
|
32
|
+
expect(evalFormual('!!""')).toBe(false);
|
|
33
|
+
expect(evalFormual('1 || 2')).toBe(1);
|
|
34
|
+
expect(evalFormual('1 && 2')).toBe(2);
|
|
35
|
+
expect(evalFormual('1 && 2 || 3')).toBe(2);
|
|
36
|
+
expect(evalFormual('1 || 2 || 3')).toBe(1);
|
|
37
|
+
expect(evalFormual('1 || 2 && 3')).toBe(1);
|
|
38
|
+
expect(evalFormual('(1 || 2) && 3')).toBe(3);
|
|
39
|
+
expect(evalFormual('1 == "1"')).toBe(true);
|
|
40
|
+
expect(evalFormual('1 === "1"')).toBe(false);
|
|
41
|
+
expect(evalFormual('1 < 1')).toBe(false);
|
|
42
|
+
expect(evalFormual('1 <= 1')).toBe(true);
|
|
43
|
+
expect(evalFormual('1 > 1')).toBe(false);
|
|
44
|
+
expect(evalFormual('1 >= 1')).toBe(true);
|
|
45
|
+
expect(evalFormual('3 >> 1')).toBe(1);
|
|
46
|
+
expect(evalFormual('3 << 1')).toBe(6);
|
|
47
|
+
expect(evalFormual('10 ** 3')).toBe(1000);
|
|
48
|
+
|
|
49
|
+
expect(evalFormual('10 ? 3 : 2')).toBe(3);
|
|
50
|
+
expect(evalFormual('0 ? 3 : 2')).toBe(2);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('formula:expression2', () => {
|
|
54
|
+
expect(evalFormual('a[0]', {a: [1, 2, 3]})).toBe(1);
|
|
55
|
+
expect(evalFormual('a[b]', {a: [1, 2, 3], b: 1})).toBe(2);
|
|
56
|
+
expect(evalFormual('a[b - 1]', {a: [1, 2, 3], b: 1})).toBe(1);
|
|
57
|
+
expect(evalFormual('a[b ? 1 : 2]', {a: [1, 2, 3], b: 1})).toBe(2);
|
|
58
|
+
expect(evalFormual('a[c ? 1 : 2]', {a: [1, 2, 3], b: 1})).toBe(3);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('formula:if', () => {
|
|
62
|
+
expect(evalFormual('IF(true, 2, 3)')).toBe(2);
|
|
63
|
+
expect(evalFormual('IF(false, 2, 3)')).toBe(3);
|
|
64
|
+
expect(evalFormual('IF(false, 2, IF(true, 3, 4))')).toBe(3);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('formula:and', () => {
|
|
68
|
+
expect(!!evalFormual('AND(0, 1)')).toBe(false);
|
|
69
|
+
expect(!!evalFormual('AND(1, 1)')).toBe(true);
|
|
70
|
+
expect(!!evalFormual('AND(1, 1, 1, 0)')).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('formula:or', () => {
|
|
74
|
+
expect(!!evalFormual('OR(0, 1)')).toBe(true);
|
|
75
|
+
expect(!!evalFormual('OR(1, 1)')).toBe(true);
|
|
76
|
+
expect(!!evalFormual('OR(1, 1, 1, 0)')).toBe(true);
|
|
77
|
+
expect(!!evalFormual('OR(0, 0, 0, 0)')).toBe(false);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('formula:xor', () => {
|
|
81
|
+
expect(evalFormual('XOR(0, 1)')).toBe(false);
|
|
82
|
+
expect(evalFormual('XOR(1, 0)')).toBe(false);
|
|
83
|
+
expect(evalFormual('XOR(1, 1)')).toBe(true);
|
|
84
|
+
expect(evalFormual('XOR(0, 0)')).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('formula:ifs', () => {
|
|
88
|
+
expect(!!evalFormual('IFS(0, 1, 2)')).toBe(true);
|
|
89
|
+
expect(!!evalFormual('IFS(0, 1, 2, 2, 3)')).toBe(true);
|
|
90
|
+
expect(!!evalFormual('IFS(0, 1, 0, 2, 0)')).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
test('formula:math', () => {
|
|
93
|
+
expect(evalFormual('ABS(1)')).toBe(1);
|
|
94
|
+
expect(evalFormual('ABS(-1)')).toBe(1);
|
|
95
|
+
expect(evalFormual('ABS(0)')).toBe(0);
|
|
96
|
+
|
|
97
|
+
expect(evalFormual('MAX(1, -1, 2, 3, 5, -9)')).toBe(5);
|
|
98
|
+
expect(evalFormual('MIN(1, -1, 2, 3, 5, -9)')).toBe(-9);
|
|
99
|
+
|
|
100
|
+
expect(evalFormual('MOD(3, 2)')).toBe(1);
|
|
101
|
+
|
|
102
|
+
expect(evalFormual('PI()')).toBe(Math.PI);
|
|
103
|
+
|
|
104
|
+
expect(evalFormual('ROUND(3.5)')).toBe(4);
|
|
105
|
+
expect(evalFormual('ROUND(3.4)')).toBe(3);
|
|
106
|
+
|
|
107
|
+
expect(evalFormual('ROUND(3.456789, 2)')).toBe(3.46);
|
|
108
|
+
expect(evalFormual('CEIL(3.456789)')).toBe(4);
|
|
109
|
+
expect(evalFormual('FLOOR(3.456789)')).toBe(3);
|
|
110
|
+
|
|
111
|
+
expect(evalFormual('SQRT(4)')).toBe(2);
|
|
112
|
+
expect(evalFormual('AVG(4, 6, 10, 10, 10)')).toBe(8);
|
|
113
|
+
|
|
114
|
+
// 示例来自 https://support.microsoft.com/zh-cn/office/devsq-%E5%87%BD%E6%95%B0-8b739616-8376-4df5-8bd0-cfe0a6caf444
|
|
115
|
+
expect(evalFormual('DEVSQ(4,5,8,7,11,4,3)')).toBe(48);
|
|
116
|
+
// 示例来自 https://support.microsoft.com/zh-cn/office/avedev-%E5%87%BD%E6%95%B0-58fe8d65-2a84-4dc7-8052-f3f87b5c6639
|
|
117
|
+
expect(evalFormual('ROUND(AVEDEV(4,5,6,7,5,4,3), 2)')).toBe(1.02);
|
|
118
|
+
// 示例来自 https://support.microsoft.com/zh-cn/office/harmean-%E5%87%BD%E6%95%B0-5efd9184-fab5-42f9-b1d3-57883a1d3bc6
|
|
119
|
+
expect(evalFormual('ROUND(HARMEAN(4,5,8,7,11,4,3), 3)')).toBe(5.028);
|
|
120
|
+
|
|
121
|
+
expect(evalFormual('LARGE([1,3,5,4,7,6], 3)')).toBe(5);
|
|
122
|
+
expect(evalFormual('LARGE([1,3,5,4,7,6], 1)')).toBe(7);
|
|
123
|
+
|
|
124
|
+
expect(evalFormual('UPPERMONEY(7682.01)')).toBe('柒仟陆佰捌拾贰元壹分');
|
|
125
|
+
expect(evalFormual('UPPERMONEY(7682)')).toBe('柒仟陆佰捌拾贰元整');
|
|
126
|
+
|
|
127
|
+
// 非数字类型转换是否正常?
|
|
128
|
+
expect(evalFormual('"3" + "3"')).toBe(6);
|
|
129
|
+
expect(evalFormual('"3" - "3"')).toBe(0);
|
|
130
|
+
expect(evalFormual('AVG(4, "6", "10", 10, 10)')).toBe(8);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('formula:text', () => {
|
|
134
|
+
expect(evalFormual('LEFT("abcdefg", 2)')).toBe('ab');
|
|
135
|
+
expect(evalFormual('RIGHT("abcdefg", 2)')).toBe('fg');
|
|
136
|
+
expect(evalFormual('LENGTH("abcdefg")')).toBe(7);
|
|
137
|
+
expect(evalFormual('LEN("abcdefg")')).toBe(7);
|
|
138
|
+
expect(evalFormual('ISEMPTY("abcdefg")')).toBe(false);
|
|
139
|
+
expect(evalFormual('ISEMPTY("")')).toBe(true);
|
|
140
|
+
expect(evalFormual('CONCATENATE("a", "b", "c", "d")')).toBe('abcd');
|
|
141
|
+
expect(evalFormual('CHAR(97)')).toBe('a');
|
|
142
|
+
expect(evalFormual('LOWER("AB")')).toBe('ab');
|
|
143
|
+
expect(evalFormual('UPPER("ab")')).toBe('AB');
|
|
144
|
+
expect(evalFormual('SPLIT("a,b,c")')).toMatchObject(['a', 'b', 'c']);
|
|
145
|
+
expect(evalFormual('TRIM(" ab ")')).toBe('ab');
|
|
146
|
+
expect(evalFormual('STARTSWITH("xab", "ab")')).toBe(false);
|
|
147
|
+
expect(evalFormual('STARTSWITH("xab", "x")')).toBe(true);
|
|
148
|
+
expect(evalFormual('ENDSWITH("xab", "x")')).toBe(false);
|
|
149
|
+
expect(evalFormual('ENDSWITH("xab", "b")')).toBe(true);
|
|
150
|
+
expect(evalFormual('UPPERFIRST("xab")')).toBe('Xab');
|
|
151
|
+
expect(evalFormual('PADSTART("5", 3, "0")')).toBe('005');
|
|
152
|
+
expect(evalFormual('PADSTART(5, 3, 0)')).toBe('005');
|
|
153
|
+
expect(evalFormual('CAPITALIZE("star")')).toBe('Star');
|
|
154
|
+
expect(evalFormual('ESCAPE("&")')).toBe('&');
|
|
155
|
+
expect(evalFormual('TRUNCATE("amis.baidu.com", 7)')).toBe('amis...');
|
|
156
|
+
expect(evalFormual('BEFORELAST("amis.baidu.com", ".")')).toBe('amis.baidu');
|
|
157
|
+
expect(evalFormual('BEFORELAST("amis", ".")')).toBe('amis');
|
|
158
|
+
expect(evalFormual('STRIPTAG("<b>amis</b>")')).toBe('amis');
|
|
159
|
+
expect(evalFormual('LINEBREAK("am\nis")')).toBe('am<br/>is');
|
|
160
|
+
expect(evalFormual('CONTAINS("xab", "x")')).toBe(true);
|
|
161
|
+
expect(evalFormual('CONTAINS("xab", "b")')).toBe(true);
|
|
162
|
+
expect(evalFormual('REPLACE("xabab", "ab", "cd")')).toBe('xcdcd');
|
|
163
|
+
expect(evalFormual('SEARCH("xabab", "ab")')).toBe(1);
|
|
164
|
+
expect(evalFormual('SEARCH("xabab", "cd")')).toBe(-1);
|
|
165
|
+
expect(evalFormual('SEARCH("xabab", "ab", 2)')).toBe(3);
|
|
166
|
+
expect(evalFormual('MID("xabab", 2, 2)')).toBe('ba');
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test('formula:date', () => {
|
|
170
|
+
expect(evalFormual('TIMESTAMP(DATE(2021, 11, 21, 0, 0, 0), "x")')).toBe(
|
|
171
|
+
new Date(2021, 11, 21, 0, 0, 0).getTime()
|
|
172
|
+
);
|
|
173
|
+
expect(
|
|
174
|
+
evalFormual('DATETOSTR(DATE(2021, 11, 21, 0, 0, 0), "YYYY-MM-DD")')
|
|
175
|
+
).toBe('2021-12-21');
|
|
176
|
+
expect(evalFormual('DATETOSTR(DATE("2021-12-21"), "YYYY-MM-DD")')).toBe(
|
|
177
|
+
'2021-12-21'
|
|
178
|
+
);
|
|
179
|
+
expect(evalFormual('DATETOSTR(TODAY(), "YYYY-MM-DD")')).toBe(
|
|
180
|
+
moment().format('YYYY-MM-DD')
|
|
181
|
+
);
|
|
182
|
+
expect(evalFormual('DATETOSTR(NOW(), "YYYY-MM-DD")')).toBe(
|
|
183
|
+
moment().format('YYYY-MM-DD')
|
|
184
|
+
);
|
|
185
|
+
expect(evalFormual('YEAR(STRTODATE("2021-10-24 10:10:10"))')).toBe(2021);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test('formula:last', () => {
|
|
189
|
+
expect(evalFormual('LAST([1, 2, 3])')).toBe(3);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test('formula:basename', () => {
|
|
193
|
+
expect(evalFormual('BASENAME("/home/amis/a.json")')).toBe('a.json');
|
|
194
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const originalWarn = console.warn.bind(console.warn);
|
|
2
|
+
|
|
3
|
+
require('moment-timezone');
|
|
4
|
+
const moment = require('moment');
|
|
5
|
+
moment.tz.setDefault('Asia/Shanghai');
|
|
6
|
+
|
|
7
|
+
global.beforeAll(() => {
|
|
8
|
+
console.warn = msg => {
|
|
9
|
+
// warning 先关了,实在太吵。
|
|
10
|
+
// const str = msg.toString();
|
|
11
|
+
// if (
|
|
12
|
+
// str.includes('componentWillMount') ||
|
|
13
|
+
// str.includes('componentWillReceiveProps')
|
|
14
|
+
// ) {
|
|
15
|
+
// return;
|
|
16
|
+
// }
|
|
17
|
+
// originalWarn(msg);
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
global.afterAll(() => {
|
|
21
|
+
console.warn = originalWarn;
|
|
22
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {lexer as createLexer, parse} from '../src';
|
|
2
|
+
|
|
3
|
+
function getTokens(input: string, options?: any) {
|
|
4
|
+
const lexer = createLexer(input, options);
|
|
5
|
+
const tokens: Array<any> = [];
|
|
6
|
+
|
|
7
|
+
while (true) {
|
|
8
|
+
const token = lexer.next();
|
|
9
|
+
if (token) {
|
|
10
|
+
tokens.push(token);
|
|
11
|
+
|
|
12
|
+
if (token.type === 'EOF') {
|
|
13
|
+
break;
|
|
14
|
+
}
|
|
15
|
+
} else {
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return tokens.map(token => `<${token.type}> ${token.value}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
test('lexer:simple', () => {
|
|
24
|
+
expect(
|
|
25
|
+
getTokens('expression result is ${a + b}', {
|
|
26
|
+
evalMode: false
|
|
27
|
+
})
|
|
28
|
+
).toMatchSnapshot();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('lexer:filter', () => {
|
|
32
|
+
expect(
|
|
33
|
+
getTokens('\\$abc is ${abc | date: YYYY-MM-DD HH\\:mm\\:ss}', {
|
|
34
|
+
evalMode: false
|
|
35
|
+
})
|
|
36
|
+
).toMatchSnapshot();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// test('lexer:test', () => {
|
|
40
|
+
// console.log(getTokens("{a: 1, 'b': 2, `c`: 3, d: {}}", {evalMode: true}));
|
|
41
|
+
// });
|
|
42
|
+
|
|
43
|
+
test('lexer:exception', () => {
|
|
44
|
+
expect(() =>
|
|
45
|
+
getTokens('\\aabc is ', {
|
|
46
|
+
evalMode: false
|
|
47
|
+
})
|
|
48
|
+
).toThrow('Unexpected token a in 1:3');
|
|
49
|
+
|
|
50
|
+
expect(() =>
|
|
51
|
+
getTokens('${a | filter: \\x2}', {
|
|
52
|
+
evalMode: false
|
|
53
|
+
})
|
|
54
|
+
).toThrow('Unexpected token x in 1:17');
|
|
55
|
+
});
|