This package provides a small template filling engine used by the project to render Feishu card payloads from webhook data. The engine supports:
- simple placeholders:
{{key}}and dotted paths{{object.subkey}} - filters:
| length,| default('fallback') - simple conditionals:
{{#if expr}}...{{/if}}(non-nested)
Placeholders resolve into values from the data map passed to FillTemplate.
Examples:
{{sender.login}}→ resolvesdata["sender"]["login"]{{issue.title}}→ resolvesdata["issue"]["title"]
| length— returns length for strings, arrays, maps; numeric/other values return a stringified length result.| default('fallback')— if value is missing or empty string, uses the provided fallback. The fallback may itself be an expression, e.g.{{issue.link | default(issue.html_url | default(''))}}.
Example:
A simple, non-nested if block is supported. Syntax:
{{#if some_expr}}
...content that may include placeholders...
{{/if}}Behavior:
- The engine evaluates
some_exprusing the same expression language used by placeholders. - If the expression is truthy, the inner content is kept and processed for placeholders.
- If falsy, the entire block is removed from the output.
- Blocks cannot be nested (the engine scans and replaces top-level
{{#if ...}} ... {{/if}}blocks).
Truthiness rules (used by {{#if}}):
nil/null→ falsebool→ its boolean valuestring→ false if empty, true otherwise[]anyandmap[string]any→ true if length > 0- numbers → false if "0", true otherwise
- other types → considered true
-
Show labels only if present:
{{#if issue_labels_joined}}**Labels:** {{issue_labels_joined}}{{/if}} -
Use default fallback for missing user link:
{{sender_link_md | default(sender.login)}} -
Nested placeholders inside an
ifblock will be evaluated when the block is kept:{{#if issue.body}} **Description:** {{issue.body | truncate(200)}} {{/if}}
{{#if}}blocks are not nested. If you need nested conditionals orelse, we can extend the parser.- No
forloop construct yet; can be added if needed. - The expression language is intentionally small and deterministic.
If you want me to extend the engine to support {{else}}, {{#unless}}, nested blocks, or loops, tell me which feature you'd like next and I will implement it.
{{issue.labels | length}} labels {{sender.name | default('unknown')}}