SkillAgentSearch skills...

Filtrex

A simple, safe, JavaScript Filter Expression compiler for end-users

Install / Use

/learn @joewalnes/Filtrex
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Filtrex

A simple, safe, JavaScript expression engine, allowing end-users to enter arbitrary expressions without p0wning you.

category == "meal" and (calories * weight > 2000.0 or subcategory in ("cake", "pie"))

Why?

There are many cases where you want a user to be able enter an arbitrary expression through a user interface. e.g.

  • Plot a chart (example)
  • Filter/searching across items using multiple fields (example)
  • Colorize items based on values (example)
  • Implement a browser based spreadsheet

Sure, you could do that with JavaScript and eval(), but I'm sure I don't have to tell you how stupid that would be.

Filtrex defines a really simple expression language that should be familiar to anyone who's ever used a spreadsheet and compile it into a JavaScript function at runtime.

Features

  • Simple! End user expression language looks like this transactions <= 5 and abs(profit) > 20.5
  • Fast! Expressions get compiled into JavaScript functions, offering the same performance as if it had been hand coded. e.g. function(item) { return item.transactions <=5 && Math.abs(item.profit) > 20.5; }
  • Safe! You as the developer have control of which data can be accessed and the functions that can be called. Expressions cannot escape the sandbox.
  • Pluggable! Add your own data and functions.
  • Predictable! Because users can't define loops or recursive functions, you know you won't be left hanging.

Get it

10 second tutorial

// Input from user (e.g. search filter)
var expression = 'transactions <= 5 and abs(profit) > 20.5';

// Compile expression to executable function
var myfilter = compileExpression(expression);

// Execute function
myfilter({transactions: 3, profit:-40.5}); // returns 1
myfilter({transactions: 3, profit:-14.5}); // returns 0

Under the hood, the above expression gets compiled to a clean and fast JavaScript function, looking something like this:

// Resulting function
function(item) {
  return item.transactions <= 5 && Math.abs(item.profit) > 20.5;
}

Expressions

There are only 2 types: numbers and strings. Numbers may be floating point or integers. Boolean logic is applied on the truthy value of values (e.g. any non-zero number is true, any non-empty string is true, otherwise false).

Values | Description --- | --- 43, -1.234 | Numbers "hello" | String foo, a.b.c, 'foo-bar' | External data variable defined by application (may be numbers or strings)

Numeric arithmetic | Description --- | --- x + y | Add x - y | Subtract x * y | Multiply x / y | Divide x % y | Modulo x ^ y | Power

Comparisons | Description --- | --- x == y | Equals x < y | Less than x <= y | Less than or equal to x > y | Greater than x >= y | Greater than or equal to x ~= y | Regular expression match x in (a, b, c) | Equivalent to (x == a or x == b or x == c) x not in (a, b, c) | Equivalent to (x != a and x != b and x != c)

Boolean logic | Description --- | --- x or y | Boolean or x and y | Boolean and not x | Boolean not x ? y : z | If boolean x, value y, else z ( x ) | Explicity operator precedence

Built-in functions | Description --- | --- abs(x) | Absolute value ceil(x) | Round floating point up floor(x) | Round floating point down log(x) | Natural logarithm max(a, b, c...) | Max value (variable length of args) min(a, b, c...) | Min value (variable length of args) random() | Random floating point from 0.0 to 1.0 round(x) | Round floating point sqrt(x) | Square root

Operator precedence follows that of any sane language.

Adding custom functions

When integrating in to your application, you can add your own custom functions.

// Custom function: Return string length.
function strlen(s) {
  return s.length;
}

// Compile expression to executable function
var myfilter = compileExpression(
                    'strlen(firstname) > 5',
                    {strlen:strlen}); // custom functions

myfilter({firstname:'Joe'});    // returns 0
myfilter({firstname:'Joseph'}); // returns 1

FAQ

Why the name?

Because it was originally built for FILTeR EXpressions.

What's Jison?

Jison is bundled with Filtrex – it's a JavaScript parser generator that does the underlying hard work of understanding the expression. It's based on Flex and Bison.

License?

MIT

Unit tests?

Here: Source, Results

What happens if the expression is malformed?

Calling compileExpression() with a malformed expression will throw an exception. You can catch that and display feedback to the user. A good UI pattern is to attempt to compile on each keystroke and continuously indicate whether the expression is valid.

Contributors

  • @joewalnes Joe Walnes – the author of this repository
  • @msantos Michael Santos – quoted symbols, regex matches and numerous fixes
  • @alexgorbatchev Alex Gorbatchev – NPM package and housekeeping
  • @m93a Michal Grňo – critical fixes of security bug

Like this? Want other thingies?

  • websocketd – Turn any program that uses STDIN/STDOUT into a WebSocket server. Like inetd, but for WebSockets.
  • ReconnectingWebSocket – Simplest way to add some robustness to your WebSocket connections.
  • Smoothie Charts – JavaScript charts for streaming data.
  • Visit The Igloo Lab to see and subscribe to other thingies I make.

And follow @joewalnes!

Related Skills

View on GitHub
GitHub Stars1.1k
CategoryDevelopment
Updated13d ago
Forks74

Languages

JavaScript

Security Score

95/100

Audited on Mar 17, 2026

No findings