regexpp

A dependency-free, spec-accurate ECMAScript regular expression parser and validator with a full AST, powering ESLint's regex-aware rules.

Library
npm
v4.12.2
31stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
33/100Needs Attention
Development Activity0
Maintenance44
Community24
Maturity52
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
77/100Good
Architecture85
Code Quality88
Innovation78
Learning Curve55

@eslint-community/regexpp is a dependency-free TypeScript library that parses and validates JavaScript regular expressions strictly according to the ECMAScript specification, across every ES version from ES5 through the latest Annex B and Unicode-set-mode (v flag) syntax. It exposes both simple one-call helpers (parseRegExpLiteral, validateRegExpLiteral, visitRegExpAST) and the underlying RegExpParser/RegExpValidator/RegExpVisitor classes for callers who need incremental parsing, ECMAScript-version gating, or handler-based AST traversal.

Originally created by Toru Nagashima (mysticatea) and now maintained under the eslint-community GitHub org, it is the regex-parsing engine ESLint itself and dozens of ESLint plugins rely on to write regex-aware lint rules — anywhere a rule needs to inspect a regular expression literal as a real AST instead of pattern-matching the raw string.

What You Get

  • Spec-accurate parsing/validation across configurable ECMAScript versions (ES5 through the latest, including Annex B and v-flag Unicode-set mode)
  • Zero runtime dependencies — a self-contained scanner, validator, parser, and visitor in one package
  • A full typed AST (AST.Node union) with a structured RegExpVisitor for enter/leave traversal, matching the ESTree visitor conventions ESLint plugin authors already know
  • Dual CJS/ESM output with bundled .d.ts types, ready to import from either module system
  • Structured RegExpSyntaxError objects instead of ad hoc throw strings, so callers can handle parse failures programmatically

Common Use Cases

  • Writing ESLint rules that inspect regex literals - a rule author calls parseRegExpLiteral on a Literal node’s raw regex to check things like unnecessary escapes, unused capture groups, or catastrophic-backtracking-prone patterns.
  • Validating user-supplied regex patterns - a tool that accepts regex input from users (e.g. a config file or a search box) calls validateRegExpLiteral to reject invalid patterns before they hit the JS RegExp constructor.
  • Building regex linters or refactoring tools - visitRegExpAST walks the parsed tree to find, rewrite, or lint sub-patterns (character classes, backreferences, lookarounds) that string-based regex matching can’t reliably detect.
  • Cross-version regex compatibility checks - passing an ecmaVersion option lets a tool verify whether a given pattern is valid syntax under an older JS target before it ships to older runtimes.

Under The Hood

Architecture The library is built as a strict pipeline: reader.ts walks raw source as character codes, validator.ts’s RegExpValidator scans that stream against the ECMAScript grammar as an ecma-version-gated state machine with no AST allocation, and parser.ts’s RegExpParser extends the validator’s scanning to build a typed AST (ast.ts) as it goes — so the correctness-critical grammar logic lives in exactly one place and parsing reuses it rather than re-implementing it. visitor.ts then walks the resulting tree via paired enter/leave handlers, and group-specifiers.ts/ecma-versions.ts isolate the version-specific quirks (named group re-declaration rules, Annex B legacy syntax) from the rest of the pipeline. index.ts collapses all of this into three convenience functions for the common case. The tight coupling between parser and validator (inheritance, not composition) means changes to the core grammar carry a large blast radius across both.

Tech Stack Written in TypeScript (~5.0) with zero runtime dependencies declared in package.json. Builds via tsc plus Rollup (rollup-plugin-sourcemaps, @rollup/plugin-node-resolve) into dual CJS/ESM output (index.js/index.mjs), with .d.ts types bundled separately via dts-bundle. Ships targeting Node ^12 || ^14 || >=16. Linting runs through the org’s own @eslint-community/eslint-plugin-mysticatea config, closing the loop of the tool linting itself.

Code Quality Tests run via Mocha with nyc coverage over an extensive fixture set in test/fixtures/parser, where test/parser.ts asserts every fixture tagged -valid parses cleanly and every one tagged -invalid throws — plus dedicated suites for validator errors and visitor traversal. A scripts/extract-test262.ts script pulls conformance fixtures directly from the official ECMAScript test262 suite to keep the validator aligned with the spec rather than relying on hand-written cases alone. CI runs on every push (ci.yml) with a separate scheduled workflow (cron.yml) for keeping Unicode data tables current. Errors are surfaced as a dedicated RegExpSyntaxError type rather than generic throws.

API Design The public surface is intentionally minimal — three top-level functions cover the 90% case with zero configuration, while the underlying RegExpParser/RegExpValidator/RegExpVisitor classes are available for incremental parsing (start/end offsets), ECMAScript-version-gated strictness, or custom AST traversal via structured handler objects mirroring the ESTree visitor pattern ESLint rule authors already know. Every function’s parameters and return shape are documented inline in the README with links straight to the defining source line.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search