woocommerce/packages/js/expression-evaluation/README.md

315 lines
4.4 KiB
Markdown
Raw Normal View History

# @woocommerce/expression-evaluation
2023-10-08 12:13:54 +00:00
Evaluation of JavaScript-like expressions in an optional context.
Examples of simple expressions:
```js
1 + 2
```
```js
foo === 'bar'
```
```js
foo ? 'bar' : 'baz'
```
Examples of complex expressions:
```js
foo.bar.baz === 'qux'
```
```js
foo.bar
&& ( foo.bar.baz === 'qux' || foo.baz === 'quux' )
```
```js
foo.bar
&& ( foo.baz === "qux" || foo.baz === "quux" )
&& ( foo.quux > 1 && foo.quux <= 5 )
```
```js
foo.bar
&& ( foo.baz === "qux" || foo.baz === "quux" )
&& ( foo.quux > 1 && foo.quux <= 5 )
? "boo"
: "baa"
```
```js
foo
+ 5
/* This is a comment */
* ( bar ? baz : qux )
```
## API
### evaluate
Evaluates an expression in an optional context.
#### Usage
```js
import { evaluate } from '@woocommerce/expression-evaluation';
const result = evaluate( '1 + foo', { foo: 2 } );
console.log( result ); // 3
```
#### Parameters
- _expression_ `string`: The expression to evaluate.
- _context_ `Object`: Optional. The context to evaluate the expression in. Variables in the expression will be looked up in this object.
#### Returns
- `any`: The result of the expression evaluation.
## Expression syntax
### Grammar and types
The expression syntax is based on JavaScript. The formal grammar is defined in [parser.ts](./src/parser.ts).
An expression consists of a single statement.
Features like `if` statements, `for` loops, function calls, and variable assignments, are not supported.
The following types are supported:
- `null`
- Boolean: `true` and `false`
- Number: An integer or floating point number.
- String: A sequence of characters that represent text.
### Literals
Values in an expression can be written as literals.
#### null
```js
null
```
#### Boolean
```js
true
false
```
#### Number
```js
1
5.23
-9
```
#### String
String literals can be written with single or double quotes. This can be helpful if the string contains a single or double quote.
```js
'foo'
"foo"
'foo "bar"'
"foo 'bar'"
```
Quotes can be escaped with a backslash.
```js
'foo \'bar\''
"foo \"bar\""
```
### Context variables
Variables can be used in an expression. The value of a variable is looked up in the context.
```js
const result = evaluate( 'foo', { foo: 1 } );
console.log( result ); // 1
```
Nested properties can be accessed with the dot operator.
```js
const result = evaluate( 'foo.bar', { foo: { bar: 1 } } );
console.log( result ); // 1
```
### Operators
The following operators are supported.
#### Comparison operators
##### Equal (`==`)
Returns `true` if the operands are equal.
```js
1 == 1
```
##### Not equal (`!=`)
Returns `true` if the operands are not equal.
```js
1 != 2
```
##### Strict equal (`===`)
Returns `true` if the operands are equal and of the same type.
```js
1 === 1
```
##### Strict not equal (`!==`)
Returns `true` if the operands are not equal and/or not of the same type.
```js
1 !== "1"
```
##### Greater than (`>`)
Returns `true` if the left operand is greater than the right operand.
```js
2 > 1
```
##### Greater than or equal (`>=`)
Returns `true` if the left operand is greater than or equal to the right operand.
```js
2 >= 2
```
##### Less than (`<`)
Returns `true` if the left operand is less than the right operand.
```js
1 < 2
```
##### Less than or equal (`<=`)
Returns `true` if the left operand is less than or equal to the right operand.
```js
2 <= 2
```
#### Arithmetic operators
##### Addition (`+`)
Returns the sum of two operands.
```js
1 + 2
```
##### Subtraction (`-`)
Returns the difference of two operands.
```js
2 - 1
```
##### Multiplication (`*`)
Returns the product of two operands.
```js
2 * 3
```
##### Division (`/`)
Returns the quotient of two operands.
```js
6 / 2
```
##### Modulus (`%`)
Returns the remainder of two operands.
```js
5 % 2
```
##### Negation (`-`)
Returns the negation of an operand.
```js
-1
```
#### Logical operators
##### Logical AND (`&&`)
Returns `true` if both operands are `true`.
```js
true && true
```
##### Logical OR (`||`)
Returns `true` if either operand is `true`.
```js
true || false
```
##### Logical NOT (`!`)
Returns `true` if the operand is `false`.
```js
!false
```
#### Conditional (ternary) operator
Returns the first value if the condition is `true`, otherwise it returns the second value.
```js
true ? 1 : 2
```
### Comments
Comments can be used to document an expression. Comments are treated as whitespace and are ignored by the parser.
```js
/* This is a comment */
```