mirror of
https://github.com/sbrow/thor.git
synced 2026-08-26 11:23:32 -04:00
feat: Added format pipe for dates.
This commit is contained in:
+15
-3
@@ -4,12 +4,13 @@ Thor's mustache engine implements the [Mustache spec](https://github.com/mustach
|
||||
|
||||
## Pipes
|
||||
|
||||
A pipe expression appears inside a section tag and transforms the resolved value before iteration. Pipes let templates request different views of the same data without privileged Go-side support.
|
||||
A pipe expression appears inside a section tag or an interpolation tag and transforms the resolved value before rendering. Pipes let templates request different views of the same data without privileged Go-side support.
|
||||
|
||||
### Syntax
|
||||
|
||||
```
|
||||
{{#<key> | <op> <arg> <arg>... | <op> <arg>... }} … {{/<key>}}
|
||||
{{<key> | <op> <arg> <arg>... | <op> <arg>...}}
|
||||
```
|
||||
|
||||
- The first whitespace-separated token after `|` is the op name; remaining tokens are its arguments.
|
||||
@@ -18,7 +19,7 @@ A pipe expression appears inside a section tag and transforms the resolved value
|
||||
- **At most 8 filters** may appear in a single tag (compile-time constant `MAX_PIPES` in `pipes.odin`). Exceeding it is a parse error.
|
||||
- **At most 2 args** per filter (compile-time constant `MAX_PIPE_ARGS`). Exceeding it is a parse error.
|
||||
- The close tag is the **bare key only**. Pipe expressions are not allowed in close tags — `{{/posts | group_by year}}` is a parse error.
|
||||
- Pipes are only supported in section tags (`{{#…}}` and `{{^…}}`) today. Variable interpolation (`{{x | op}}`) is a parse error.
|
||||
- Pipes work in both section tags (`{{#…}}` and `{{^…}}`) and interpolation tags (`{{…}}` and `{{&…}}`). In sections, the transformed value becomes the section's context. In interpolations, the transformed value is what gets rendered.
|
||||
|
||||
### Example
|
||||
|
||||
@@ -29,6 +30,9 @@ A pipe expression appears inside a section tag and transforms the resolved value
|
||||
<ul>{{#items}}<li>{{title}}</li>{{/items}}</ul>
|
||||
</section>
|
||||
{{/posts}}
|
||||
|
||||
<!-- Interpolation pipe: format a date string for display -->
|
||||
<time datetime="{{date}}">{{date | format}}</time>
|
||||
```
|
||||
|
||||
### Available ops
|
||||
@@ -52,10 +56,18 @@ Errors (returned as `Data_Error` at render time):
|
||||
- Any element is missing the named field.
|
||||
- Any element has an empty value for the named field.
|
||||
|
||||
#### `format` (no args yet)
|
||||
|
||||
Formats an ISO 8601 date string as a display string. Takes a string, returns a string (e.g. `"2026-03-15T08:49:54-04:00"` → `"15 Mar 2026"`). Invalid input (empty, too-short, non-string, or unparseable) returns a `Data_Error`. Templates that need to skip dateless pages should gate with a section — `{{#date}}<time datetime="{{.}}">{{. | format}}</time>{{/date}}` — so the section's truthiness check catches empty before the filter runs. Commonly used inline as `{{date | format}}` to render a display string while keeping the raw ISO available via `{{date}}` for the `datetime=` attribute.
|
||||
|
||||
Internally: parses the invariant `YYYY-MM-DD` prefix by char offset, stringifies `time.Month(month_num)` and slices `[:3]` for the abbreviation. Accepts any of these ISO 8601 forms (the date prefix is what matters): `2023-10-15T13:18:50-07:00`, `2023-10-15T13:18:50-0700`, `2023-10-15T13:18:50Z`, `2023-10-15T13:18:50`, `2023-10-15`.
|
||||
|
||||
Future: will accept Go reference-date format strings (e.g. `{{date | format "Mon Jan 2 2006"}}`) and pull default format/timezone from site configuration.
|
||||
|
||||
### Memory ownership
|
||||
|
||||
- **Parsed pipe filters** (`Pipe_Filter` values) are stored inline on each `Node` via `[dynamic; MAX_PIPES]Pipe_Filter`, and `args` is inline on each `Pipe_Filter` via `[dynamic; MAX_PIPE_ARGS]string`. Both use Odin's fixed-capacity dynamic array type, so no per-tag heap allocations occur at parse time. The storage dies with the `Template` when `delete_template` is called.
|
||||
- **Filter results** (e.g. the `[dynamic]Group` returned by `group_by`) are render-scoped allocations in `context.temp_allocator`. They die with the render call. No caller-side cleanup is needed.
|
||||
- **Filter results** (e.g. the `[dynamic]Group` returned by `group_by`, or the display string returned by `format`) are render-scoped allocations in `context.temp_allocator`. They die with the render call. No caller-side cleanup is needed.
|
||||
- The string data inside `Pipe_Filter` (op names, args) is borrowed from the template source — no cloning.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user