{"_id":"@a5i/eregex-wasm","_rev":"2-96ac43f07a61038acb376d9b4774d4af","name":"@a5i/eregex-wasm","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.4":{"name":"@a5i/eregex-wasm","version":"0.1.4","keywords":["regex","regular-expression","mrab-regex","eregex","wasm"],"license":"Apache-2.0","_id":"@a5i/eregex-wasm@0.1.4","maintainers":[{"name":"alexpav","email":"alexey.pavlyukov@gmail.com"}],"homepage":"https://github.com/a5i/eregex#readme","bugs":{"url":"https://github.com/a5i/eregex/issues"},"dist":{"shasum":"e85de262f6cae6d3c31171844665c2dbd980020d","tarball":"https://registry.npmjs.org/@a5i/eregex-wasm/-/eregex-wasm-0.1.4.tgz","fileCount":7,"integrity":"sha512-bUd9JiS/LVfTU3jEB5F/rCI3xF4uCrnzqaAUhHXW0vAYacfzSv4cXdqV9RuvIUGy3No+DeutsTF85K3FNyklrQ==","signatures":[{"sig":"MEUCIQD5VFEemb9zU4lWSTEduwPbGE0LytVvImIQDtx03rAqfQIgIZz/DwvGXhGF/0TJ5UhFdstNUVVyWVZgtHPlwD/9lZg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@a5i%2feregex-wasm@0.1.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":227120},"main":"index.js","types":"index.d.ts","_npmUser":{"name":"alexpav","email":"alexey.pavlyukov@gmail.com"},"repository":{"url":"git+https://github.com/a5i/eregex.git","type":"git"},"_npmVersion":"10.9.8","description":"WebAssembly bindings for eregex, an advanced regular expression engine inspired by mrab-regex","directories":{},"_nodeVersion":"22.22.3","collaborators":["eregex contributors"],"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/eregex-wasm_0.1.4_1782081907061_0.22537336584061385","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@a5i/eregex-wasm","collaborators":["eregex contributors"],"description":"WebAssembly bindings for eregex, an advanced regular expression engine inspired by mrab-regex","version":"0.1.5","license":"Apache-2.0","repository":{"type":"git","url":"git+https://github.com/a5i/eregex.git"},"main":"index.js","types":"index.d.ts","keywords":["regex","regular-expression","mrab-regex","eregex","wasm"],"_id":"@a5i/eregex-wasm@0.1.5","bugs":{"url":"https://github.com/a5i/eregex/issues"},"homepage":"https://github.com/a5i/eregex#readme","_nodeVersion":"22.22.3","_npmVersion":"10.9.8","dist":{"integrity":"sha512-LyBL8AnceMuVl98iSibEr/afuNJs4G9gER4yC/WvH76jJP+i6A1251Vj4w7FL9xvi/Rt1XN9BWSEV188V2mytQ==","shasum":"a771c61aa9ff32de6f265e1a2e587a6eb18f354c","tarball":"https://registry.npmjs.org/@a5i/eregex-wasm/-/eregex-wasm-0.1.5.tgz","fileCount":7,"unpackedSize":227120,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@a5i%2feregex-wasm@0.1.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCegaDoAYbAjZDMRvguvbwEirewzxCuANZF2f8JXujgXwIgF7tFk8BnSC6VLDA9Dx8a01kRrueadXZi2SCeB1z30wI="}]},"_npmUser":{"name":"alexpav","email":"alexey.pavlyukov@gmail.com"},"directories":{},"maintainers":[{"name":"alexpav","email":"alexey.pavlyukov@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/eregex-wasm_0.1.5_1782082544914_0.4534998068075189"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-21T22:45:06.940Z","modified":"2026-06-21T22:55:45.384Z","0.1.4":"2026-06-21T22:45:07.200Z","0.1.5":"2026-06-21T22:55:45.052Z"},"bugs":{"url":"https://github.com/a5i/eregex/issues"},"license":"Apache-2.0","homepage":"https://github.com/a5i/eregex#readme","keywords":["regex","regular-expression","mrab-regex","eregex","wasm"],"repository":{"type":"git","url":"git+https://github.com/a5i/eregex.git"},"description":"WebAssembly bindings for eregex, an advanced regular expression engine inspired by mrab-regex","maintainers":[{"name":"alexpav","email":"alexey.pavlyukov@gmail.com"}],"readme":"# @a5i/eregex-wasm\n\nWebAssembly bindings for [`eregex`](https://github.com/a5i/eregex) — an\nadvanced regular expression engine for Rust inspired by mrab-regex (the Python\n`regex` module).\n\nThis package exposes eregex's full API to JavaScript / TypeScript via\n[`wasm-bindgen`](https://rustwasm.github.io/wasm-bindgen/) + [`wasm-pack`](https://rustwasm.github.io/docs/wasm-pack/).\nAll matching logic runs in compiled Rust shipped as a single `.wasm` artifact;\nthe JavaScript layer is a thin adapter.\n\nIt mirrors the native Node bindings ([`@a5i/eregex`](https://www.npmjs.com/package/@a5i/eregex),\nnapi-rs) method-for-method: the same `Regex` / `Match` / `PartialMatch`\nclasses, the same flag constants, the same `null`-on-absent semantics. Code\nwritten against one works unchanged against the other.\n\n| package          | technology                  | best for                                  |\n| ---------------- | --------------------------- | ----------------------------------------- |\n| `@a5i/eregex`     | napi-rs    | fastest native execution on Node          |\n| `@a5i/eregex-wasm`| wasm-bindgen | a single portable binary; also bundler/browser-buildable |\n\n## Build\n\nThe package is built from the Rust core with `wasm-pack`:\n\n```bash\ncd crates/eregex-wasm\nrustup target add wasm32-unknown-unknown   # one-time\ncargo install wasm-pack --locked           # one-time (or use a CI action)\nnpm run build\n# → pkg/eregex_wasm.js + pkg/eregex_wasm_bg.wasm + pkg/index.js (assembled)\n```\n\n`npm run build` runs `wasm-pack build --target nodejs --release` and then\n`scripts/assemble-pkg.cjs`, which drops the hand-written `index.js` entry into\n`pkg/` and sets it as `main`. The assembled `pkg/` is what gets published to\nnpm.\n\nThe `pkg/` directory is generated; it is not checked in.\n\n## Quick start\n\n```js\nconst { Regex, IGNORECASE, parseFlags } = require('@a5i/eregex-wasm');\n\nconst re = new Regex(String.raw`(\\w+)\\s+(\\w+)`);\nconst m = re.find('hello world');\nconsole.log(m.matched);      // 'hello world'\nconsole.log(m.group(1));     // 'hello'\nconsole.log(m.group(2));     // 'world'\n\n// Flags: pass a bitset of the exported constants, or parse a string.\nnew Regex('hello', IGNORECASE).isMatch('HELLO');         // true\nnew Regex('hello', parseFlags('i')).isMatch('HELLO');    // true\n\n// Repeated captures (signature mrab-regex feature).\nnew Regex(String.raw`(\\w)+`).find('abc').captures(1);    // ['a', 'b', 'c']\n\n// Replace with named groups.\nnew Regex(String.raw`(?P<a>\\d)(?P<b>\\d)`).replaceAll('12 34', '${b}${a}'); // '21 43'\n```\n\n## `Regex`\n\n```ts\nclass Regex {\n  constructor(pattern: string, flags?: number)\n  get pattern(): string\n  get flags(): number         // resolved flags (defaults UNICODE + VERSION1 are added)\n  get captureCount(): number  // capturing groups (group 0 excluded)\n  groupNames(): string[]\n  groupIndex(name: string): number | null\n\n  isMatch(haystack: string): boolean\n  find(haystack: string): Match | null\n  findAt(haystack: string, start: number): Match | null\n  matchAtStart(haystack: string): Match | null   // like re.match\n  fullMatch(haystack: string): Match | null       // like re.fullmatch\n  findAll(haystack: string): Match[]\n  findPartial(haystack: string): PartialMatch | null\n\n  replace(haystack: string, repl: string): string\n  replaceAll(haystack: string, repl: string): string\n  split(haystack: string): string[]\n  dump(): string                                  // parsed AST (debug aid)\n}\n```\n\n`flags` is a bitwise OR of the exported constants: `IGNORECASE`, `MULTILINE`,\n`DOTALL`, `UNICODE`, `ASCII`, `VERBOSE`, `FULLCASE`, `WORD`, `LOCALE`,\n`VERSION0`, `VERSION1`. `parseFlags(\"ims\")` parses a flag string for\n`RegExp`-familiar ergonomics.\n\n## `Match`\n\n```ts\nclass Match {\n  get matched(): string       // whole match (group 0)\n  get input(): string         // original haystack\n  get start(): number         // byte offset\n  get end(): number\n  get span(): { start: number; end: number }\n  get captureCount(): number\n  get groups(): (string | null)[]             // current text, group 0 first\n  get namedGroups(): Record<string, string>\n  get allCaptures(): (string | null)[][]      // repeated-capture history\n  get capturesDict(): Record<string, (string | null)[]>\n\n  group(index: number): string | null\n  namedGroup(name: string): string | null\n  captures(index: number): (string | null)[]\n  capturesByName(name: string): (string | null)[]\n  spanOf(index: number): { start: number; end: number } | null\n}\n```\n\nAll offsets are **byte offsets** (UTF-8), matching Python's `re` and the Rust\ncore. `null` is returned for groups that did not participate.\n\n## `PartialMatch`\n\n`findPartial` is end-anchored: the match must consume the input to its end.\n\n```ts\nclass PartialMatch {\n  get status(): 'full' | 'partial'\n  get isFull(): boolean\n  get isPartial(): boolean\n  get matched(): string\n  get start(): number\n  get end(): number\n  get captureCount(): number\n\n  group(index: number): string | null\n  namedGroup(name: string): string | null\n  groupState(index: number): 'matched' | 'partial' | 'none'\n}\n```\n\n- `null` from `findPartial` → the input **cannot** be a prefix of any match.\n- `status === 'partial'` → the input is a valid prefix of some full match\n  (more input could complete it).\n\n```js\nconst re = new Regex(String.raw`token=([a-z]+)([0-9]+)`);\nconst p = re.findPartial('x token=abc');\np.isPartial;            // true\np.group(1);             // 'abc'\np.groupState(1);        // 'matched'\np.groupState(2);        // 'partial'   (entered but not completed)\n\nre.findPartial('x token=abc!'); // null — '!' rules out any continuation\n```\n\n## Module-level helpers\n\n```ts\nescape(s: string): string\nescapeSpecialOnly(s: string): string\nescapeLiteralSpaces(s: string): string\nisMatch(pattern: string, haystack: string): boolean  // compiles pattern once\nparseFlags(flagStr: string): number\nflags(): { IGNORECASE: number; MULTILINE: number; /* ... */ }\n```\n\n## Notes on the wasm target\n\n- Built for `wasm32-unknown-unknown` and packaged with `--target nodejs`, so\n  it loads as a plain CommonJS module in Node 10+ with no bundler required.\n- `wasm-bindgen` cannot export `const` values, so the flag bits are produced\n  by `flags()` and spread onto the module by `index.js`. Callers see ordinary\n  numeric properties (`@a5i/eregex-wasm.IGNORECASE`, ...).\n- Absent values come back as JS `null` (not `undefined`): nullable returns are\n  routed through `serde-wasm-bindgen`, which maps `Option::None → null`, so\n  `=== null` and `deepStrictEqual(..., null)` behave exactly like the native\n  package.\n- To target browsers or bundlers instead of Node, rebuild with\n  `wasm-pack build --target web` (or `bundler`) and drop the `index.js`\n  CommonJS wrapper.\n\n## Testing\n\n```bash\nnpm test          # runs test/smoke.js against the assembled pkg/\nnpm run test:all  # build, then test\n```\n\n## Layout\n\nThis is one facet of eregex's binding story. The same Rust core (`eregex`)\nalso ships native Node bindings (`@a5i/eregex`, napi-rs) and Python bindings\n(`eregex`, pyo3). See the project root for the core crate and its feature\nmatrix.\n\n## License\n\nApache-2.0, matching the upstream `mrab-regex` project.\n","readmeFilename":"README.md"}