@jbrowse/jexl
v3.0.1
Published
A fork of the jexl lang for jbrowse
Readme
@jbrowse/jexl
A fork of the jexl lang for jbrowse
What's New in v3.0
Version 3.0 is a major simplification of Jexl with breaking changes:
- Synchronous only - All evaluation is synchronous. No async/await needed.
- No transforms - The pipe operator (
|) has been removed. Use functions instead. - No filter expressions - Relative filter syntax like
array[.property == value]has been removed. Regular bracket notation for indexing (array[0],object["key"]) still works.
See CHANGELOG.md for migration guide.
Quick Examples
const context = {
name: { first: 'Sterling', last: 'Archer' },
assoc: [
{ first: 'Lana', last: 'Kane' },
{ first: 'Cyril', last: 'Figgis' },
{ first: 'Pam', last: 'Poovey' }
],
age: 36
}
// Template strings with interpolation
jexl.eval('`Hello ${name.first} ${name.last}`', context)
// "Hello Sterling Archer"
jexl.eval('`Age in 5 years: ${age + 5}`', context)
// "Age in 5 years: 41"
// Math operations
jexl.eval('age * (3 - 1)', context)
// 72
// String concatenation
jexl.eval('name.first + " " + name.last', context)
// "Sterling Archer"
// Conditional logic
jexl.eval('age > 62 ? "retired" : "working"', context)
// "working"
// Array indexes
jexl.eval('assoc[1].first', context)
// "Cyril"Language Reference
Native Types
| Type | Examples |
| ---------------- | ---------------------------------------------------- |
| Booleans | true, false |
| Strings | "Hello \"user\"", 'Hey there!' |
| Template Strings | `Hello ${name}`, `Total: ${price * qty}` |
| Numerics | 6, -7.2, 5, -3.14159 |
| Objects | {hello: "world!"} |
| Arrays | ['hello', 'world!'] |
Template Strings
Template strings use backticks and support expression interpolation with ${}:
const context = { name: 'World', price: 10, qty: 3 }
jexl.eval('`Hello ${name}!`', context)
// "Hello World!"
jexl.eval('`Total: $${price * qty}`', context)
// "Total: $30"
// Escape backticks and dollar signs with backslash
jexl.eval('`Code: \\`example\\``')
// "Code: `example`"
jexl.eval('`Price: \\$100`')
// "Price: $100"Operators
Unary: ! (negate)
Binary:
- Arithmetic:
+,-,*,/,//(floor division),%,^(power) - Comparison:
==,!=,>,>=,<,<=,in - Logical:
&&,|| - Assignment:
=(assigns value to variable)
Ternary: condition ? consequent : alternate
Sequence: ; (separates multiple expressions)
Identifiers
Access context variables by name. Use dot notation or brackets for nested properties:
const context = {
name: { first: 'Malory', last: 'Archer' },
exes: ['Nikolai', 'Len', 'Burt'],
lastEx: 2
}
jexl.eval('name.first', context) // "Malory"
jexl.eval('name["last"]', context) // "Archer"
jexl.eval('exes[2]', context) // "Burt"
jexl.eval('exes[lastEx - 1]', context) // "Len"Functions
Call functions in expressions:
jexl.addFunction('min', Math.min)
jexl.addFunction('max', Math.max)
jexl.eval('min(5, 2, 9)')
// 2
jexl.eval('max(temperature, threshold)')
// evaluates with contextMultiple Expressions
Separate multiple expressions with semicolons. The result is the value of the last expression:
jexl.eval('5; 10; 15')
// 15
jexl.eval('1 + 1; 2 + 2; 3 + 3')
// 6Variable Assignment
Assign values to variables using = (no let, var, or const needed). Assignments mutate the context and return the assigned value:
jexl.eval('x = 5')
// 5
jexl.eval('x = 5; x * 2')
// 10
jexl.eval('x = 5; y = 10; x + y')
// 15
const context = {}
jexl.eval('x = 5; y = x * 2; y', context)
// 10
// context is now { x: 5, y: 10 }API
Evaluation
import jexl from '@jbrowse/jexl'
// Evaluate an expression
const result = jexl.eval('expression', context)
// Compile once, evaluate many times
const expr = jexl.compile('name.first + " " + name.last')
const result = expr.eval({ name: { first: 'John', last: 'Doe' } })Adding Custom Functions
// Add a single function
jexl.addFunction('round', Math.round)
jexl.addFunction('lower', (str) => str.toLowerCase())
// Add multiple functions
jexl.addFunctions({
min: Math.min,
max: Math.max,
abs: Math.abs
})
// Use in expressions
jexl.eval('round(3.7)') // 4
jexl.eval('lower(name)', { name: 'HELLO' }) // "hello"
jexl.eval('max(1, 5, 3)') // 5Adding Custom Operators
// Add a binary operator
jexl.addBinaryOp('~=', 20, (left, right) =>
left.toLowerCase() === right.toLowerCase()
)
jexl.eval('"Hello" ~= "hello"') // true
// Add a unary operator
jexl.addUnaryOp('~', (right) => Math.floor(right))
jexl.eval('~3.7') // 3License
MIT License, same as TomFrost/Jexl
