# RegexPlugin ## Purpose Applies inline regular-expression operations to resolved context values. The plugin enables match extraction, capture group access, and global search-and-replace — all expressed within the template syntax — so callers can reshape value strings without pre-processing the context object. By centralising regex logic here the main application code stays free of ad-hoc string manipulation. ## Features - `{path:/pattern/flags}` — extract the first match of the regex against the resolved value. - `{path:/pattern/flags:N}` — extract capture group N (0 = full match, 1 = first group, etc.). - `{path:/pattern/flags:replace:replacement}` — replace all occurrences using `String.replace`. - Supports all standard regex flags: `g`, `i`, `m`, `s`, `u`, `y`. - Returns `""` for nullish resolved values or when no match is found. - Returns the original match string for invalid regex patterns (safe degradation). - Skips `_`-prefixed paths (reserved for dynamic plugins). ## Usage: Basic Example ```ts import { TemplateEngine, createRegexPlugin } from "@suaveplan/templates"; const engine = new TemplateEngine().use(createRegexPlugin()); engine.parse("{phone:/\\D/g:replace:}", { phone: "+1 (555) 867-5309" }); // → "15558675309" engine.parse("{email:/@.+$/}", { email: "alice@example.com" }); // → "@example.com" ``` ## Usage: Advanced Example ```ts import { TemplateEngine, createRegexPlugin } from "@suaveplan/templates"; const engine = new TemplateEngine().use(createRegexPlugin()); // Capture groups: extract year from ISO date engine.parse( "Year: {date:/^(\\d{4})-(\\d{2})-(\\d{2})$/:1}", { date: "2024-06-15" } ); // → "Year: 2024" // Replace non-alphanumeric characters engine.parse("{code:/[a-z]/gi:replace:X}", { code: "abc123" }); // → "XXX123" // Out-of-range group returns empty string engine.parse("{value:/(a)(b)/:9}", { value: "ab" }); // → "" ``` ## API Reference ### `createRegexPlugin(): Plugin` Returns a `Plugin` with: - `name: "regex"` - `priority: PluginPriority.MEDIUM` (50) - `pattern: /\{([a-zA-Z_$][\w.$]*):\/([^/]+)\/([gimsuy]*)?(?::(\w+)(?::([^}]*))?)?\\}/g` The pattern captures five groups: 1. Variable path (e.g. `phone`) 2. Regex pattern body (e.g. `\\D`) 3. Flags string (e.g. `g`, may be empty) 4. Operation keyword (`replace` or a decimal digit string) 5. Replacement string when operation is `replace` **transform(match, context)**: Resolves the path via `getNestedValue`, converts the result to a string, then applies the specified operation. Returns `SKIP_PLUGIN` when `path` or `pattern` capture groups are absent. Returns the original match text when the regex constructor throws (malformed pattern). Returns `""` for nullish values or when no match exists. ## Implementation Notes - The regex engine used is the native JS `RegExp` constructor, so all platform-supported flags and syntax are available. - When no operation is specified, `String.match()` is used and only the zeroth element (the full match) is returned; this is equivalent to requesting group 0 explicitly. - Group extraction uses `String.match()` rather than `RegExp.exec()`, which means the `g` flag causes `match()` to return all full matches in an array with no group information. Callers wanting capture groups should omit the `g` flag. - The `replace` operation delegates directly to `String.replace()`, which respects the `g` flag: without it only the first occurrence is replaced; with it all occurrences are replaced. - Invalid regex patterns are caught silently and the original match text is returned, preventing template rendering from crashing due to user-supplied regex strings. - Runs at `MEDIUM` priority so it executes before variable-resolution plugins but after control-flow plugins.