Move the variable-bag contract (PlaceholderMap, MissingPlaceholderFn,
DefaultMissingMarker) up to the pkg/docforge root (placeholder.go) — it is
format-neutral, consumed by the resolver layer and any future exporter.
The {{key}} substitution grammar (placeholderRegex, PUA preview sentinels,
replacePlaceholders) stays in pkg/docforge/docx: it is the .docx renderer's
own machinery, not a root concern.
New at the root (vars.go):
- VariableResolver{Namespace() string; Populate(bag PlaceholderMap)} —
a PUSH interface, deliberately not pull Resolve(key): some namespaces
emit a data-dependent key set (parties.claimant.0.name, .1.name, … one
per party) that a fixed key-by-key pull can't enumerate.
- ResolverSet + BuildBag() — composes resolvers into one bag, replacing
the hard-coded addFooVars-then-addBarVars sequencing in Build.
paliad side (submission_vars_resolvers.go): seven resolver types wrap the
UNCHANGED addXxxVars push-builders (firm/today/user/procedural_event/
project/parties/deadline), each capturing the entity it needs. The builder
bodies are byte-for-byte untouched, so the bag is identical by
construction; SubmissionVarsService.Build now wires the applicable
resolvers and calls ResolverSet.BuildBag(). Resolvers stay in paliad
because they read paliad's domain model; a second docforge consumer plugs
its own resolvers into a ResolverSet the same way.
Keys()/Catalogue() (the static key list that will data-drive the authoring
palette + kill the hardcoded VARIABLE_GROUPS in submission-draft.ts) is
deferred to the UI slice that consumes it, sourced from the frontend's
existing labels — building it now, ahead of its consumer, would be
speculative (PRD §4 B3 principle).
Verification: go build ./... clean, go vet clean, full module test green.
Alias-parity (procedural_event ≡ rule) and party-form tests pass unchanged
= bag byte-identical.
m/paliad#157
34 lines
1.3 KiB
Go
34 lines
1.3 KiB
Go
package docforge
|
|
|
|
import "strings"
|
|
|
|
// PlaceholderMap is the variable bag a ResolverSet builds and a format
|
|
// exporter fills into a template. Keys are dotted paths without braces
|
|
// (e.g. "project.case_number"); values are the substituted text — already
|
|
// locale-aware, pretty-printed, and sanitised by the resolvers that
|
|
// produced them.
|
|
//
|
|
// It is format-neutral: the .docx exporter substitutes these into OOXML,
|
|
// but a future PDF/HTML/Markdown exporter consumes the same bag. The
|
|
// {{key}} substitution grammar itself is the exporter's concern and lives
|
|
// with the adapter (pkg/docforge/docx), not here.
|
|
type PlaceholderMap map[string]string
|
|
|
|
// MissingPlaceholderFn translates an unbound placeholder key into the
|
|
// in-document marker token. DefaultMissingMarker returns the standard
|
|
// "[KEIN WERT: <key>]" / "[NO VALUE: <key>]" form.
|
|
type MissingPlaceholderFn func(key string) string
|
|
|
|
// DefaultMissingMarker returns the standard missing-value marker for the
|
|
// given UI language. Unbound placeholders render this marker inline so the
|
|
// lawyer sees the gap in the document rather than the render failing.
|
|
func DefaultMissingMarker(lang string) MissingPlaceholderFn {
|
|
prefix := "KEIN WERT"
|
|
if strings.EqualFold(lang, "en") {
|
|
prefix = "NO VALUE"
|
|
}
|
|
return func(key string) string {
|
|
return "[" + prefix + ": " + key + "]"
|
|
}
|
|
}
|