Skip to content

About

A regular expression transform for partial matching

Resources

Code of conduct

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Latest commit

Β 

History

106 Commits

Folders and files

Repository files navigation

regex-partial-match

A zero-dependency regular expression transform for partial matching, enabling validation of incomplete input strings against regex patterns.

🧩 Problem statement

Unlike C/C++ (via PCRE/PCRE2, RE2, Boost.Regex), Python (via third party regex module) or Java (via hitEnd), Javascript has no canonical / innate partial-matching for regular expressions.

πŸ“– Overview

This library transforms regular expressions to best-effort support partial matching, allowing you to test if an incomplete string could potentially match the full pattern. This is particularly useful for real-time input validation, autocomplete systems, progressive form validation, stream chunk matching, etc.

πŸ“¦ Installation

npm install regex-partial-match

πŸš€ Usage

Basic Usage

import PartialMatchRegExp from "regex-partial-match";

const pattern = /^hello world/;
const partial = new PartialMatchRegExp(pattern);

partial.test("h"); // true - could match
partial.test("hello"); // true - could match
partial.test("hello world"); // true - full match
partial.test("goodbye"); // false - cannot match

Telling a settled match from one still reading

test() and exec() answer "could this match?", which is true for a prefix and for a complete match alike. hitEnd(), modelled on the JDK's Matcher.hitEnd(), reports whether the engine reached the end of the input while producing the match, so more input could still change it. Together they give progressive validation its three states:

import PartialMatchRegExp, { hitEnd } from "regex-partial-match";

const partial = new PartialMatchRegExp(/^\d{4}-\d{2}-\d{2}/);

function state(input) {
  const match = partial.exec(input);

  if (match === null) return "invalid";
  return hitEnd(partial, match) ? "incomplete" : "complete";
}

state("20xx"); // 'invalid'    - reject
state("2024"); // 'incomplete' - no error, keep typing
state("2024-06"); // 'incomplete' - no error, keep typing
state("2024-06-15"); // 'complete'   - accept, enable submit

Note

hitEnd() answers "could more input change this match?", not "is this text a match?". /hello \w+/ matches "hello world" in full, and hitEnd() is still true: \w+ read the end of the input looking for more. For an exact-length pattern like the date above the two questions coincide, which is what makes the three states work; a validator for an open-ended pattern that wants "valid so far" should test the original pattern as well.

Upgrading from 1.x, where this was isComplete()? See the migration guide.

Smaller bundles

Each export has its own subpath for environments that don't tree-shake, and regex-partial-match/core leaves out the rules for carets and backreferences until you bind them back. See Entry points.

βš™οΈ How It Works

The library wraps each atomic element in a non-capturing group with a disjunction to the true end of the input, so the pattern matches any prefix of what the original would match:

/abc/ β†’ /(?:a|$(?![\s\S]))(?:b|$(?![\s\S]))(?:c|$(?![\s\S]))/

See How It Works for the full transform, where it over-accepts, how ^ is handled in groups and under the m flag, and how backreferences are matched.

βœ… Supported syntax

Every regular expression feature up to ES2025 is supported, including lookarounds, backreferences, unicode sets and modifiers, except that a \q{...} string in a v-flag class matches only in full. The library is compiled to ES2015, and a pattern needs only what its own syntax needs. See Compatibility for the full list, and the version each feature needs.

⚠️ Caveats

The one most people meet: an unanchored pattern always matches "" at the end of the input, so test() returns true for any input. Anchor with ^, or ask hitEnd(). Caveats lists the rest, with examples and workarounds.

πŸ’‘ Example

Stream Processing

import PartialMatchRegExp, { hitEnd } from "regex-partial-match";

const partial = new PartialMatchRegExp(/\{"[^"]+":(?:"[^"]*"|\d+)\}/);
let buffer = "";

function processChunk(chunk) {
  buffer += chunk;
  const matches = [];

  let match;
  while ((match = partial.exec(buffer)) && !hitEnd(partial, match)) {
    matches.push(match[0]);
    buffer = buffer.slice(match.index + match[0].length);
  }

  buffer = match ? buffer.slice(match.index) : "";

  return matches;
}

processChunk('{"na'); // [] - buffer: '{"na'
processChunk('me":"Jo'); // [] - buffer: '{"name":"Jo'
processChunk('hn"}{"age":'); // ['{"name":"John"}'] - buffer: '{"age":'
processChunk('25}{"ok'); // ['{"age":25}'] - buffer: '{"ok'
processChunk('":"yes"}'); // ['{"ok":"yes"}'] - buffer: ''

Each exec() finds the earliest match. One that didn't reach the end of the input is complete, so it's taken. The first one that did is a record still arriving, so the buffer keeps it and drops everything before it.

Useful for parsing log files, network streams, or any chunked data where records may be split across boundaries.

πŸ”Œ API

Export Import from
PartialMatchRegExp regex-partial-match, regex-partial-match/partialMatchRegExp A RegExp that also matches any prefix of a possible match
hitEnd(partial, match) regex-partial-match, regex-partial-match/hitEnd Whether a match read the end of the input, so more input could change it
features(partial) regex-partial-match, regex-partial-match/features The syntactic constructs a pattern uses
isPartialMatchRegExp(value) regex-partial-match, regex-partial-match/features Whether a value is a PartialMatchRegExp from any entry point
RegExp.prototype.toPartialMatchRegex() regex-partial-match/extend A PartialMatchRegExp from an existing RegExp
withModules(...modules) regex-partial-match/core A PartialMatchRegExp class with only the modules you bind

πŸ“œ License

ISC License - see LICENSE file for details.

πŸ™Œ Credits

Based on an algorithm created by Lucas Trzesniewski, re-created for NPM via ISC license, with permission.

🀝 Contributing

Contributions are welcome! Please open an issue or pull request on GitHub, and see Contributing.

πŸ”— Related projects

Project Description
incr-regex-package Incremental regex matcher
dfa Compiles a regular expression like syntax to fast deterministic finite automata, which could be used to partial match?
refa Can convert regular expressions to an Abstract Syntax Tree, which might afford partial-match capability?
@eslint-community/regexpp A regular expression parser for ECMAScript with AST generation and visitor implementation
Regex+ template literal, transforming native regular expressions
Awesome Regex Curated list of tools, tutorials, libraries, and other resources, covering all major regex flavours
replace-content-transformer A toolkit for stream content replacement, underpinned by regex-partial-match

About

A regular expression transform for partial matching

Resources

Code of conduct

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages