{"id":16125706,"url":"https://github.com/dy/subscript","last_synced_at":"2026-01-22T18:07:07.147Z","repository":{"id":42187106,"uuid":"417364857","full_name":"dy/subscript","owner":"dy","description":"Fast and tiny expression parser / evaluator.","archived":false,"fork":false,"pushed_at":"2025-03-13T02:58:18.000Z","size":1084,"stargazers_count":125,"open_issues_count":1,"forks_count":4,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-04T03:03:56.074Z","etag":null,"topics":["compute","dsl","eval","evaluator","expression-evaluator","expression-parser","jessie","jexl","jsep","justin","math","math-expression-evaluator","math-expression-parser","microlanguage","template"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-15T04:09:36.000Z","updated_at":"2025-04-03T06:05:35.000Z","dependencies_parsed_at":"2023-02-06T07:46:25.385Z","dependency_job_id":"f9c7e596-400f-4d93-a2ac-aee4f4c2c8cb","html_url":"https://github.com/dy/subscript","commit_stats":null,"previous_names":["spectjs/subscript"],"tags_count":86,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dy%2Fsubscript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dy%2Fsubscript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dy%2Fsubscript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dy%2Fsubscript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dy","download_url":"https://codeload.github.com/dy/subscript/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248636803,"owners_count":21137527,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compute","dsl","eval","evaluator","expression-evaluator","expression-parser","jessie","jexl","jsep","justin","math","math-expression-evaluator","math-expression-parser","microlanguage","template"],"created_at":"2024-10-09T21:30:49.796Z","updated_at":"2026-01-22T18:07:07.139Z","avatar_url":"https://github.com/dy.png","language":"JavaScript","readme":"\u003ch1 align=\"center\"\u003esub\u003csub\u003e\u003csup\u003e ✦ \u003c/sup\u003e\u003c/sub\u003escript\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003eTiny expression parser \u0026 evaluator.\u003c/p\u003e\n\u003cdiv align=\"center\"\u003e\n\n[![build](https://github.com/dy/subscript/actions/workflows/node.js.yml/badge.svg)](https://github.com/dy/subscript/actions/workflows/node.js.yml) [![npm](https://img.shields.io/npm/v/subscript)](http://npmjs.org/subscript) [![size](https://img.shields.io/bundlephobia/minzip/subscript?label=size)](https://bundlephobia.com/package/subscript) [![microjs](https://img.shields.io/badge/µjs-subscript-darkslateblue)](http://microjs.com/#subscript) \u003c!--[![demo](https://img.shields.io/badge/play-%F0%9F%9A%80-white)](https://dy.github.io/subscript/)--\u003e\n\n\u003c/div\u003e\n\n\n```js\nimport subscript from 'subscript'\n\nlet fn = subscript('a + b * 2')\nfn({ a: 1, b: 3 })  // 7\n```\n\n* **Fast** — Pratt parser engine, see [benchmarks](#performance)\n* **Portable** — universal expression format, see [spec](./spec.md)\n* **Extensible** — pluggable syntax, see [playground](https://dy.github.io/subscript/)\n* **Metacircular** — can parse and compile itself\n* **Safe** — sandboxed, blocks `__proto__`, `constructor`, no global access\n\n\n## Presets\n\n**Subscript** – common expressions:\n\n```js\nimport subscript from 'subscript'\n\nsubscript('a.b + c * 2')({ a: { b: 1 }, c: 3 })  // 7\n```\n\n**Justin** – JSON + expressions + templates + arrows:\n\n```js\nimport justin from 'subscript/justin.js'\n\njustin('{ x: a?.b ?? 0, y: [1, ...rest] }')({ a: null, rest: [2, 3] })\n// { x: 0, y: [1, 2, 3] }\n```\n\n**Jessie** – JSON + expressions + statements, functions (JS subset):\n\n```js\nimport jessie from 'subscript/jessie.js'\n\nlet fn = jessie(`\n  function factorial(n) {\n    if (n \u003c= 1) return 1\n    return n * factorial(n - 1)\n  }\n  factorial(5)\n`)\nfn({})  // 120\n```\n\nSee [docs](./docs.md#presets) for full description.\n\n## Extension\n\nAdd operators, literals or custom syntax:\n\n```js\nimport { binary, operator, compile } from 'subscript/justin.js'\n\n// add intersection operator\nbinary('∩', 80)  // register parser\noperator('∩', (a, b) =\u003e (  // register compiler\n  a = compile(a), b = compile(b),\n  ctx =\u003e a(ctx).filter(x =\u003e b(ctx).includes(x))\n))\n```\n\n```js\nimport justin from 'subscript/justin.js'\njustin('[1,2,3] ∩ [2,3,4]')({})  // [2, 3]\n```\n\nSee [docs.md](./docs.md) for full API.\n\n\n## Syntax Tree\n\nExpressions parse to a minimal JSON-compatible syntax tree:\n\n```js\nimport { parse } from 'subscript'\n\nparse('a + b * 2')\n// ['+', 'a', ['*', 'b', [, 2]]]\n```\n\nThree forms:\n\n```js\n'x'             // identifier — resolve from context\n[, value]       // literal — return as-is (empty slot = data)\n[op, ...args]   // operation — apply operator\n```\n\nSee [spec.md](./spec.md).\n\n\n## Safety\n\nBlocked by default:\n- `__proto__`, `__defineGetter__`, `__defineSetter__`\n- `constructor`, `prototype`\n- Global access (only context is visible)\n\n```js\nsubscript('constructor.constructor(\"alert(1)\")()')({})\n// undefined (blocked)\n```\n\n## Performance\n\n```\nParse 30k:  subscript 150ms · justin 183ms · jsep 270ms · expr-eval 480ms · jexl 1056ms\nEval 30k:   new Function 7ms · subscript 15ms · jsep+eval 30ms · expr-eval 72ms\n```\n\n## Utils\n\n### Codegen\n\nConvert tree back to code:\n\n```js\nimport { codegen } from 'subscript/util/stringify.js'\n\ncodegen(['+', ['*', 'min', [,60]], [,'sec']])\n// 'min * 60 + \"sec\"'\n```\n\n### Bundle\n\nBundle imports into a single file:\n\n```js\n// Node.js\nimport { bundleFile } from 'subscript/util/bundle.js'\nconsole.log(await bundleFile('jessie.js'))\n\n// Browser / custom sources\nimport { bundle } from 'subscript/util/bundle.js'\nconsole.log(await bundle('main.js', {\n  'main.js': `import { x } from './lib.js'; export default x * 2`,\n  'lib.js': `export const x = 21`\n}))\n// → \"const x = 21;\\nexport { x as default }\"\n```\n\n\n## Used by\n\n* [jz](https://github.com/dy/jz) — JS subset → WASM compiler\n\u003c!-- * [prepr](https://github.com/dy/prepr) --\u003e\n\u003c!-- * [glsl-transpiler](https://github.com/stackgl/glsl-transpiler) --\u003e\n\u003c!-- * [piezo](https://github.com/dy/piezo) --\u003e\n\n\u003c!--\n## Refs\n\n[jsep](https://github.com/EricSmekens/jsep), [jexl](https://github.com/TomFrost/Jexl), [expr-eval](https://github.com/silentmatt/expr-eval), [math.js](https://mathjs.org/).\n\n[mozjexl](https://github.com/mozilla/mozjexl), [jexpr](https://github.com/justinfagnani/jexpr), [expression-eval](https://github.com/donmccurdy/expression-eval), [string-math](https://github.com/devrafalko/string-math), [nerdamer](https://github.com/jiggzson/nerdamer), [math-codegen](https://github.com/mauriciopoppe/math-codegen), [math-parser](https://www.npmjs.com/package/math-parser), [nx-compile](https://github.com/nx-js/compiler-util), [built-in-math-eval](https://github.com/mauriciopoppe/built-in-math-eval) --\u003e\n\n\u003cp align=center\u003e\u003ca href=\"https://github.com/krsnzd/license/\"\u003eॐ\u003c/a\u003e\u003c/p\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdy%2Fsubscript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdy%2Fsubscript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdy%2Fsubscript/lists"}