Conscript.js
The JavaScript parser for the Conscript condition-scripting language.
Install / Use
/learn @lamansky/Conscript.jsREADME
conscript.js
The JavaScript parser for the Conscript language. Conscript (pronounced CON-script) is a very simple language for writing potentially-complex sets of conditions according to which data should be evaluated. A script written in this language is called a “Conscription” and is usually only one line long. Think of it as being analogous to the WHERE component of a SQL query.
Here’s an example that uses Conscript in a calendar context:
const conscript = require('conscript')()
const date = new Date()
const vars = {
year: date.getUTCFullYear(),
month: date.getUTCMonth() + 1,
day: date.getUTCDate(),
}
// This turns the string into a test function
const test = conscript('month=10 & day=28')
if (test(vars)) {
// This will run if today is October 28
}
Installation
Requires Node.js 8.3.0 or above.
npm i conscript
API
The module exports a single function which returns a function which returns another function.
The first function is intended to be called at require-time, e.g. require('conscript')(globalOptions).
Parameter of the First Function
- Optional: Object argument: Global options that will apply to all subsequent calls. Possible options:
allowRegexLiterals(bool): Whether to permit regular expression literals in condition scripts. Defaults tofalse.debugOutput(function): A callback that will be invoked whenever thedebugoperator is used. The callback will be given two arguments: the evaluated syntax string, and the value.safeCall(bool): If set totrue, calling a non-function will fail silently and generatenull. If omitted or set tofalse, an error will be thrown. Defaults tofalse.safeNav(bool): If set totrue, accessing a property of a non-object will fail silently and generatenull. If omitted or set tofalse, an error will be thrown. Defaults tofalse.safeOp(bool): If set totrue, attempting to perform operations on values that are of the wrong type will fail silently. For math operations, the unhandled value will be converted to zero. For regular expression testing operations,falsewill always be returned. If this option is omitted or set tofalse, an error will be thrown in such cases. Defaults tofalse.safe(bool): A shortcut for settingsafeCall,safeNav, andsafeOpsimultaneously.unknownsAre(string): A mode for handling unknown identifiers. Possible values are:strings(default): Treat unknown identifiers as as strings.null: Convert unknown identifiers tonull.errors: Throw aReferenceErrorwhenever an unknown identifier is found.
Parameters of the Second Function
conscription(string): A condition script.- Optional:
options(object): Any options that should override the global options you set when you called the first function (see above).
Parameters of the Third Function
vars(function, object, or Map)- If
varsis a function, it is called whenever Conscript comes across an identifier, and is passed two arguments: the identifier name, and anotAVarsymbol to be returned if the identifier is not a variable. - If
varsis an object or Map, its keys are considered the variables to which the values are mapped.
- If
- Optional: Object argument:
defaultLeft(any): A value to be used as the left operand for operations that omit a left operand.
Return Value
Returns the result of the condition script. Usually this is true or false if you used a comparison operator, or in most use cases involving defaultLeft, but otherwise theoretically can be any value to which your script evaluates.
Conscript Syntax
Here are some of the language features which you can use in the Conscript string that you pass to the parser:
Literals
Number Literals
Floats and negative numbers are supported.
const conscript = require('conscript')()
conscript('2 > 1')() // true
conscript('1.1 > 1')() // true
conscript('-1 < 0')() // true
Infinity can be represented as either ∞ or Infinity (case-insensitive).
String Literals
String literals are enclosed with either double or single quotes.
const conscript = require('conscript')()
conscript('"test" = "test"')() // true
If the unknownsAre setting is set to strings (which is the default), then strings do not need to be quoted.
const conscript = require('conscript')({unknownsAre: 'strings'})
// Two unquoted strings ("test" and "string") separated by the `is` operator:
conscript('test is string')() // true
Boolean and Null Literals
Conscript supports true, false, and null literals. These are case-insensitive.
const conscript = require('conscript')()
conscript('true')() // true
conscript('!false')() // true
conscript('!null')() // true
Unlike JavaScript, Conscript does not distinguish between null and undefined. Only null is used. Also unlike JavaScript, Conscript does not consider null to be an object.
Array Literals
Arrays are created using square brackets and can contain variables or other literals.
const conscript = require('conscript')()
// The *= operator checks to see if the array on the left contains the value on the right.
conscript('[123, "test", var] *= "value"')({var: 'value'}) // true
Function Literals
Function literals are generally used as callback arguments for other functions. To create a function, define the named parameters list, surrounded by parentheses, then define the function body, surrounded by curly brackets.
All Conscript syntax produces some sort of value (Conscript does not use statements), so Conscript function declarations do not use return.
If needed, you can call a function immediately after defining it. Functions are called using a parenthesized list of arguments, as in JavaScript.
const conscript = require('conscript')()
// This is the same as `typeof (x => x === 1) === 'function'` in JavaScript
conscript('(x){x=1} is function')({}) // true
// This calls the function immediately after defining it
conscript('(x,y){x=y}(1,1)')({}) // true
Regular Expression Literals
Regular expressions are surrounded on either side by @. Flags (such as i) can go after the final @. Regular expressions are used in conjunction with the matches operator. The regex can go on the left and the string on the right, or vice versa.
The use of regular expression literals (e.g. @regex@) requires the allowRegexLiterals option to be set to true.
const conscript = require('conscript')({allowRegexLiterals: true})
conscript('@^ex@ matches "Example"')() // false
conscript('@^ex@ !matches "Example"')() // true
conscript('@^ex@i matches "Example"')() // true
conscript('"Example" matches @^ex@i')() // true
Variables
const conscript = require('conscript')()
conscript('x=1')({x: 1}) // true
conscript('x=1')({x: 2}) // false
When Conscript comes across an identifier (x in the example above), it will look for its value in the vars argument.
Normally, variable names must be alphanumeric. If you need support for more characters, use the ${var} construction:
const conscript = require('conscript')()
conscript('${hello world!}=123')({'hello world!': 123}) // true
If you need "variable variables," use the $(expression) construction:
const conscript = require('conscript')()
conscript('$(x)="z"')({x: 'y', y: 'z'}) // true
$ also functions as an object that contains all provided variables:
const conscript = require('conscript')()
conscript('$ is object & $x = $.x')({x: 1}) // true
You can implement determined-at-runtime variable names by passing a function instead of a dictionary object. (If you do this, the $ global object will be empty.)
const conscript = require('conscript')()
conscript('variable="variable"')(varName => varName) // true
You can pass functions as variables and can call them from within the condition string.
const conscript = require('conscript')()
const vars = {
sum (a, b) { return a + b },
}
conscript('sum(2,2)=4')(vars) // true
If the variable is not a function, the Conscript parser will throw an error. If you want non-function calls to fail silently, set the safeCall setting to true, like so:
const conscript = require('conscript')({safeCall: true})
conscript('sum(2,2)=4')({}) // false
Parentheses
Clauses can be grouped with parentheses, allowing for nested logical tests.
const conscript = require('conscript')()
conscript('(x>0&x<=y-1)|x=999')({x: 51, y: 100}) // true
Properties & Methods
Objects
If one of your variables is an object, you can access its properties like so:
const conscript = require('conscript')()
const vars = {
obj: {a: 1},
}
conscript('obj.a=1')(vars) // true
Normally, property names must be alphanumeric. If you need support for more characters, use the .{prop} construction:
const conscript = require('conscript')()
const vars = {
obj: {'number one': 1},
}
conscript('obj.{number one}=1')(vars) // true
If you need dynamic property access, use the .(expression) construction:
const conscript = require('conscript')()
const vars = {
arr: [0, 10, 20],
}
conscript('arr.(1 + 1) = 20')(vars) // true
Arrays & Strings
You can access array elements and string characters with the same syntax used to access object properties. Arrays and strings are zero-indexed.
const conscript = require('conscript')()
conscript('[1, 2, 3].0 = 1')() // true
conscript('"Test".1 = "e"')() // true
Besides numeric indexes, arrays and strings h
Related Skills
node-connect
341.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.5kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
341.2kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
84.5kCommit, push, and open a PR
