@@ -4,14 +4,16 @@ Have you ever wanted to use some dynamic JS capabilities when using the ssr char
44
55Now we have solved this problem for you. We have designed a simple and easy-to-understand template syntax to help you achieve dynamic rendering of charts.
66
7- ## Features
87
9- - 🔒 ** Secure by default** - No access to global objects or prototype chain, does not use ` eval ` or ` new Function `
10- - 🚀 ** High performance** - Supports pre-compilation of expressions for improved performance with repeated evaluations
11- - 🛠️ ** Extensible** - Register custom functions to easily extend functionality
12- - 🪩 ** Lightweight** - Zero dependencies, small footprint, only ` 7.8KB `
8+ ## ✨ Features
139
14- ## Installation
10+ - 🔒 ** Secure by default** - No access to global objects or prototype chain, does not use ` eval ` or ` new Function ` .
11+ - 🚀 ** High performance** - Supports pre-compilation of expressions for improved performance with repeated evaluations.
12+ - 🛠️ ** Extensible** - Register custom functions to easily extend functionality.
13+ - 🪩 ** Lightweight** - Zero dependencies, small footprint, only ` 7.8 Kb ` before gzip.
14+
15+
16+ ## 📥 Installation
1517
1618``` bash
1719npm install @antv/expr
@@ -21,7 +23,8 @@ yarn add @antv/expr
2123pnpm add @antv/expr
2224```
2325
24- ## Basic Usage
26+
27+ ## 🔨 Usage
2528
2629### Synchronous Expression Evaluation
2730
@@ -51,45 +54,23 @@ const result1 = evaluator({ price: 10, quantity: 5 }); // returns 50
5154const result2 = evaluator ({ price: 20 , quantity: 3 }); // returns 60
5255```
5356
54- ### Using Asynchronous Patterns (Optional)
55-
56- While the library is synchronous, you can still use asynchronous patterns if needed:
57-
58- ``` typescript
59- import { evaluate } from ' @antv/expr' ;
60-
61- // Wrap evaluation in an async function
62- async function asyncEvaluate(expr , context ) {
63- return new Promise ((resolve , reject ) => {
64- try {
65- resolve (evaluate (expr , context ));
66- } catch (error ) {
67- reject (error );
68- }
69- });
70- }
71-
72- // Use with async/await
73- const result = await asyncEvaluate (' x + y' , { x: 10 , y: 20 }); // returns 30
74- ```
75-
76- ### Registering Custom Functions
57+ ### Registering and Calling Functions
7758
7859``` typescript
7960import { register , evaluate } from ' @antv/expr' ;
8061
81- // Register custom functions
82- register (' sum' , (... args ) => args .reduce ((a , b ) => a + b , 0 ));
83- register (' average' , (array ) => array .reduce ((a , b ) => a + b , 0 ) / array .length );
62+ // Register functions
63+ register (' formatCurrency' , (amount ) => ` $${amount .toFixed (2 )} ` );
8464
85- // Use custom functions in expressions
86- const result = evaluate (' @sum(1, 2, 3, 4)' ); // returns 10
87- const avg = evaluate (' @average(data.values)' , {
88- data: { values: [10 , 20 , 30 , 40 ] }
89- }); // returns 25
90- ```
65+ // Function call with arguments
66+ const result = evaluate (' @max(a, b, c)' , { a: 5 , b: 9 , c: 2 }); // returns 9
9167
92- ## Supported Syntax
68+ // Expression as function arguments
69+ const result = evaluate (' @formatCurrency(price * quantity)' , {
70+ price: 10.5 , quantity: 3
71+ }); // returns '$31.50'
72+ ```
73+ Build-in Functions: ` abs ` , ` ceil ` , ` floor ` , ` round ` , ` sqrt ` , ` pow ` , ` max ` , ` min ` .
9374
9475### Variable References
9576
@@ -155,26 +136,32 @@ const result = evaluate('score >= 90 ? "A" : score >= 80 ? "B" : "C"', {
155136}); // returns 'B'
156137```
157138
158- ### Function Calls
139+ ### Timeout Handling
140+
141+ You can implement timeout handling by wrapping your evaluation in a ` Promise.race ` with a timeout:
159142
160143``` typescript
161- import { register , evaluate } from ' @antv/expr' ;
144+ import { evaluate } from " @antv/expr" ;
162145
163- // Register functions
164- register (' max' , Math .max );
165- register (' formatCurrency' , (amount ) => ` $${amount .toFixed (2 )} ` );
146+ // Create a function that evaluates with a timeout
147+ function evaluateWithTimeout(expr , context , timeoutMs ) {
148+ const evaluationPromise = new Promise ((resolve ) => {
149+ resolve (evaluate (expr , context ));
150+ });
166151
167- // Function call with arguments
168- const result = evaluate (' @max(a, b, c)' , { a: 5 , b: 9 , c: 2 }); // returns 9
152+ const timeoutPromise = new Promise ((_ , reject ) => {
153+ setTimeout (
154+ () => reject (new Error (` Evaluation timed out after ${timeoutMs }ms ` )),
155+ timeoutMs ,
156+ );
157+ });
169158
170- // Expression as function arguments
171- const result = evaluate (' @formatCurrency(price * quantity)' , {
172- price: 10.5 , quantity: 3
173- }); // returns '$31.50'
159+ return Promise .race ([evaluationPromise , timeoutPromise ]);
160+ }
174161```
175- ** Default Global Functions:** ` ['abs', 'ceil', 'floor', 'round', 'sqrt', 'pow', 'max', 'min'] `
176162
177- ## Benchmarks
163+
164+ ## 🚀Benchmarks
178165
179166Performance comparison of different evaluation methods: (baseline: new Function)
180167
@@ -191,64 +178,23 @@ gantt
191178 axisFormat %s
192179
193180 section Simple
194- evaluate after compile :done, 0, 159
195- evaluate without compile :done, 0, 636
181+ expr evaluate after compile :done, 0, 159
182+ expr evaluate without compile :done, 0, 636
196183 expr-eval Parser :done, 0, 2394
197184
198185 section Medium
199- evaluate after compile :done, 0, 216
200- evaluate without compile :done, 0, 981
186+ expr evaluate after compile :done, 0, 216
187+ expr evaluate without compile :done, 0, 981
201188 expr-eval Parser :done, 0, 3781
202189
203190 section Complex
204- evaluate after compile :done, 0, 159
205- evaluate without compile :done, 0, 489
191+ expr evaluate after compile :done, 0, 159
192+ expr evaluate without compile :done, 0, 489
206193 expr-eval Parser :done, 0, 3274
207194```
208195
209- ## Advanced Usage
210-
211- ### Timeout Handling
212-
213- You can implement timeout handling by wrapping your evaluation in a Promise.race with a timeout:
214-
215- ``` typescript
216- import { evaluate } from " @antv/expr" ;
217-
218- // Create a function that evaluates with a timeout
219- function evaluateWithTimeout(expr , context , timeoutMs ) {
220- const evaluationPromise = new Promise ((resolve , reject ) => {
221- try {
222- const result = evaluate (expr , context );
223- resolve (result );
224- } catch (error ) {
225- reject (error );
226- }
227- });
228-
229- const timeoutPromise = new Promise ((_ , reject ) => {
230- setTimeout (
231- () => reject (new Error (` Evaluation timed out after ${timeoutMs }ms ` )),
232- timeoutMs ,
233- );
234- });
235-
236- return Promise .race ([evaluationPromise , timeoutPromise ]);
237- }
238- ```
239- ## Security Features
240-
241- This library is designed with security in mind:
242-
243- - ✅ No access to global objects (` window ` , ` global ` , etc.)
244- - ✅ No access to prototype chain
245- - ✅ No use of ` eval ` or ` Function ` constructor
246- - ✅ Expression execution has timeout protection
247- - ✅ Configurable keyword blacklist
248196
249- ## API Reference
250-
251- ### Core Functions
197+ ## 📮API Reference
252198
253199#### ` evaluate(expression: string, context?: object): any `
254200
@@ -265,23 +211,16 @@ Synchronously compiles an expression, returning a function that can be used mult
265211- ` expression ` : The expression string to compile
266212- Returns: A function that accepts a context object and returns the evaluation result
267213
268- ### Registration
269-
270214#### ` register(name: string, fn: Function): void `
271215
272216Registers a custom function that can be used in expressions.
273217
274218- ` name ` : Function name (used with @ prefix in expressions)
275219- ` fn ` : Function implementation
276220
277- ### Error Handling
278-
279221All evaluation errors throw an ` ExpressionError ` type exception with detailed error information.
280222
281- ## Contributing
282-
283- Contributions are welcome! Please feel free to submit issues or pull requests.
284223
285224## License
286225
287- MIT
226+ MIT
0 commit comments