# `regex` — regex pattern matcher _(no submodules)_ ## Purpose Recognises substrings matching a set of regex patterns per Wheeler 2016 section 3.6. The default registry covers a `recent_year` pattern matching `19xx` and `20xx`. Callers extend the registry to flag additional patterns (hex strings, phone-number shapes, project-specific identifiers) without forking the scorer. ## Features - Default `recent_year` regex matches `19xx` and `20xx` - Registry-pluggable: callers can register their own named regexes - Global-flag enforced internally so every occurrence is reported - Every match carries the full `RegExpMatchArray` for downstream inspection ## Usage: Basic Example ```ts import { regexMatch } from "@suaveplan/password-strength/matchers/regex"; const matches = regexMatch("login1985"); console.log(matches[0].regexName); // "recent_year" console.log(matches[0].token); // "1985" ``` ## Usage: Advanced Example ```ts import { regexMatch } from "@suaveplan/password-strength/matchers/regex"; const matches = regexMatch("token=ABCDEF", { regexes: { hex: /[0-9A-F]+/g } }); for (const m of matches) { console.log(m.regexName, m.token); } ``` ## API Reference - `regexMatch(password: string, opts?: RegexMatchOptions): RegexMatch[]` - `opts.regexes`: `Record` — the registry. Defaults to `DEFAULT_REGEXES`. - `DEFAULT_REGEXES: Readonly>` — frozen default registry (currently `recent_year`). - `RegexMatchOptions`: `{ regexes?: Record }` ## Implementation Notes The matcher copies each registered regex with the `g` flag forced on so a global walk over the password emits every occurrence. The walk uses `String.prototype.matchAll` rather than mutating `lastIndex` so zero-width matches do not loop. The full `RegExpMatchArray` is preserved on each output record so callers can read capture groups when their regex uses them. ## Additional Implementation Notes The implementation follows the canonical zxcvbn algorithm from Wheeler 2016 with the suaveplan-style additions described in the package proposal: structured error codes via the `defineCodes` registry, Zod boundaries at every public entry point, OTel histograms and counters keyed to low-cardinality attributes, and a strict input-length guard at 200 characters. Consumers integrate with their existing observability stack by installing a meter provider before importing the package, and with their i18n stack via the `MessageResolver` callback type declared in `@suaveplan/types`. The bundled data tables are intentionally small to keep the package bundle compact; production deployments should swap in fuller frequency-ranked tables via `loadDictionaries`. The default English dictionary set is a frozen `DictionarySet` that the matcher never mutates; caller-supplied dictionaries override defaults by name.