first commit
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
# 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<TContext>(): Plugin<TContext>`
|
||||
|
||||
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.
|
||||
Reference in New Issue
Block a user