feat(xmlgen): built-in helper library and caller resolvers (2/4) - #201
Open
sthanikan2000 wants to merge 1 commit into
Open
sthanikan2000 wants to merge 1 commit into
sthanikan2000 wants to merge 1 commit into
Conversation
The engine renders and escapes, but a template still has to turn form data
into the shapes a receiving system expects. This adds the vocabulary it does
that with.
Nine built-in helpers, pure and deterministic, needing no configuration:
part and split for a value the document spreads across several elements,
date for moving between layouts, decimal for a fixed-decimal amount, lookup
for an enum encoded as something else, zero, coalesce, join and trim. Having
these in the box is what keeps Generate(ctx, tmpl, data) sufficient for most
templates rather than something every caller has to furnish first.
zero earns its place: data decoded with UseNumber carries numbers as
json.Number, a string underneath, so {{ if .quantity }} is true even when the
quantity is 0. Without it a template that renders an empty-value marker for
a zero quietly renders the zero instead.
Resolvers are the escape hatch for what the data cannot supply at all -- a
code-list description from a database, a rate from another service. Each is
registered under its own name, so a template calling one that was not
supplied fails when the template is parsed rather than at execution on
whichever branch happens to reach it. Names are validated first because
text/template's Funcs panics on a name that is not a Go identifier: a
resolver called "code-list" would otherwise take down the process rather
than fail the request. A resolver's own error stays reachable through
text/template's wrapping, so errors.Is matches both ErrResolver and the
caller's sentinel.
Also adds Validate, which checks a template without rendering it, so a
broken one fails when it is stored rather than when someone submits.
Refs #189
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
sthanikan2000
added this pull request to stack #204
September 16, 2026 04:55
This was referenced Sep 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The engine in #199 renders and escapes, but a template still has to turn form data into the shapes a receiving system expects: a reference the document spreads across four elements, a date in another layout, an enum encoded as a number. With no vocabulary for that, every caller has to supply its own before rendering anything.
Changes
Nine built-in helpers — pure, deterministic, no configuration — plus an extension point for what the data cannot supply at all.
part{{ part .ref "/" 0 }}on"OFF1/A/42/2026"OFF1— past the end gives"", not an errorsplit{{ range split .codes "," }}join{{ join .tags "-" }}a-b-cdate{{ date .day "2006-01-02" "1/2/06" }}3/4/26— a non-matching layout is an error, never a guessdecimal{{ decimal .fob 2 }}on14001400.00lookup{{ lookup .flag "yes" "1" "no" "0" }}1— unmapped values pass throughzero{{ if zero .gain }}"",false, numeric zerocoalesce{{ coalesce .a .b "n/a" }}trim{{ trim .name }}Generate(ctx, tmpl, data)sufficient for most templates.text/template'sFuncspanics on a name that is not a Go identifier: a resolver called"code-list"would otherwise take down the process rather than fail the request.zeroexists becauseUseNumbercarries numbers asjson.Number, a string underneath — so{{ if .quantity }}is true even when the quantity is0, and a template rendering an empty-value marker for a zero would quietly render the zero instead.Validatechecks a template without data, so a broken one fails when it is stored rather than when someone submits.Testing
138 subtests cumulative (38 added), race-clean, 0 lint issues. Covers each helper's edge case, resolvers receiving the caller's real Go types,
ctxround-tripping, a resolver error matching bothErrResolverand the caller's own sentinel, a panicking resolver being recovered, invalid resolver names erroring rather than panicking, and call-counting across untaken branches and variable binding.Related
Implements #189. Stacked chain — 2 of 4:
#199 engine → #201 (this) → #202 golden fixtures → #200 failure paths