first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
# DateTimePlugin
## Purpose
Injects current date and time values into templates using a flexible, token-based formatting syntax. Because date-time generation depends on the system clock, the plugin accepts an injectable `Clock` from `@suaveplan/types` so tests can produce deterministic output without real-time coupling. All four token types — date, time, datetime, and Unix timestamp — are handled by a single plugin instance to minimise regex passes per render.
## Features
- `{_date}` — current date formatted as `YYYY-MM-DD`.
- `{_date:YYYY/MM/DD}` — custom date format using any combination of supported tokens.
- `{_time}` — current time formatted as `HH:mm:ss`.
- `{_time:HH:mm}` — custom time format.
- `{_datetime}` — full datetime `YYYY-MM-DD HH:mm:ss`.
- `{_datetime:YYYY/MM/DD HH:mm}` — custom datetime format.
- `{_timestamp}` — Unix milliseconds as a decimal string.
- `{_timestamp:s}` — Unix seconds (floored).
- Format tokens: `YYYY`, `MM`, `DD`, `HH`, `mm`, `ss`, `SSS`.
- Injectable `Clock` for deterministic testing.
## Usage: Basic Example
```ts
import { TemplateEngine, createDateTimePlugin } from "@suaveplan/templates";
const engine = new TemplateEngine().use(createDateTimePlugin());
// Actual output depends on system time; shown illustratively
engine.parse("Today is {_date}", {}); // "Today is 2024-06-15"
engine.parse("Time: {_time}", {}); // "Time: 14:30:00"
engine.parse("Epoch: {_timestamp}", {}); // "Epoch: 1718451000000"
```
## Usage: Advanced Example
```ts
import { TemplateEngine, createDateTimePlugin } from "@suaveplan/templates";
import type { Clock } from "@suaveplan/types";
// Deterministic clock for tests
const fixedClock: Clock = () => new Date("2024-06-15T14:30:00.500Z").getTime();
const engine = new TemplateEngine().use(createDateTimePlugin({ clock: fixedClock }));
engine.parse("{_date:YYYY/MM/DD}", {});
// → "2024/06/15"
engine.parse("{_datetime:DD-MM-YYYY HH:mm:ss}", {});
// → "15-06-2024 14:30:00"
engine.parse("{_timestamp:s}", {});
// → "1718459400"
```
## API Reference
### `DateTimePluginOptions`
| Property | Type | Description |
|----------|------|-------------|
| `clock` | `Clock` (optional) | Injectable clock; defaults to `() => Date.now()` |
### `createDateTimePlugin<TContext>(opts?): Plugin<TContext>`
Returns a `Plugin` with:
- `name: "datetime"`
- `priority: PluginPriority.HIGH` (80)
- `pattern: /\{_(date|time|datetime|timestamp)(?::([^}]+))?\}/g`
The pattern captures two groups:
1. Type keyword: `date`, `time`, `datetime`, or `timestamp`
2. Optional format string or modifier (`s` for Unix seconds)
**transform(match)**: Calls `clock()` to obtain the current epoch milliseconds, wraps it in a `Date`, and dispatches on the type keyword. Delegates formatting to `formatDate(date, pattern)`. Returns the original match string for unrecognised type keywords (defensive — cannot occur given the pattern).
## Implementation Notes
- The `Clock` type from `@suaveplan/types` is defined as `() => number`, returning epoch milliseconds. The plugin wraps this with `new Date(clock())` to feed `formatDate`.
- `formatDate` performs simple token-by-token string replacement in a defined order (longest tokens first) so there is no ambiguity between `MM` and `m` characters in the pattern.
- `{_timestamp:s}` uses `Math.floor(now.getTime() / 1000)` to truncate to seconds without rounding, matching the behaviour of POSIX `time()`.
- Runs at `HIGH` priority so date/time tokens are resolved before MEDIUM-priority transforms (which might want to further format the resulting string via `CaseTransformPlugin`).