Documentation
¶
Overview ¶
Package quill is a general-purpose, gradually-typed, fast template engine for Go.
Quill compiles and renders templates written in the Quill language: a brace-delimited, keyword-led surface with pipe filters, arrow functions, and a Pratt-parsed expression language. It pairs Twig-class composition -- template inheritance, blocks, macros, includes, embeds, and traits -- with a gradual type system, a compile-to-Go backend for the hot path, native branch-aware coverage, a policy sandbox, streaming output, and byte-exact whitespace control. It renders HTML pages, configuration files, emails, program source, or any other text with the same engine; no single use case is privileged. The runtime depends on nothing outside the Go standard library.
See the guide at https://avmnu-sng.github.io/quill-template-engine/ for the language reference, grammar, standard library, runtime semantics, and the extension API. This package is under active development; its API is not yet stable.
The facade ¶
Environment is the engine facade. Build one over a Loader with New (or over an in-memory template map with NewWithArray), then Render by name. Output escaping is off by default, like Go text/template, and undefined variables are strict by default; both, along with the sandbox, the type registry, coverage, streaming, the compiled backend, and host extensions, are configured through Option values.
The pipeline ¶
A template loads once and is memoized. Loading parses the source into an AST, runs the gradual type checker (package check) between parse and interpret, and prepares the module for the tree-walking interpreter (package interp). The checker consumes the annotations the parser threads through the AST -- the @types block, @set/@for targets, @macro/@block params and returns, and arrow params -- infers types where the spec defines it, and applies the gradual `any` fallback everywhere a value is unannotated. It rejects an ill-typed template with a positioned error before any byte is rendered, catching the runtime errors a static reader can see: a string/number arithmetic mismatch, rendering a list/map value, a for over a non-iterable typed iterand, a missing member/method, a call with the wrong arity or argument types, a bad map key kind, and a set/for/param annotation inconsistent with what flows into it. It narrows unions and nullables through `is` tests and null-safe access. Object member shapes and host callable signatures come from an optional host registry (check.Registry, installed via WithTypes); with no registry, Object types are opaque-but-known and host calls are dynamic, and the checker still enforces every in-template annotation.
Annotations never change runtime behavior. An unannotated template types entirely as `any`, so the checker is silent and the template renders byte-for-byte identically to a build that ignores types; removing every annotation from any template yields the same bytes.
Composition and the standard library ¶
The engine renders the full composition surface -- @extends/@block with parent(), @macro with defaults and variadics, @import/@from, @use trait reuse, @embed, and the statement- and function-form @include -- and the complete standard-library catalogue of filters, functions, and tests, including arrow functions through map/filter/sort/reduce/find, the `has some`/`has every` quantifiers, the `matches` regex operator, and the whitespace-control trim modifiers.
Performance ¶
Templates run on a tree-walking interpreter by default, and a compiled loop or module can be generated with the compile-to-Go backend (package compile) and installed with WithCompiled for the hot path. Rendering can either return a string (Render) or stream to an io.Writer (RenderTo) without buffering the whole output.
Extensions ¶
A host adds its own filters, functions, and tests through the ext package and layers them over the core library with WithExtensions (callable sets) or WithExtension (Extension bundles). A later host layer shadows an earlier one and every host layer shadows core.
Escaping and the sandbox ¶
Output escaping is off by default. HTML escaping is available globally (WithAutoescapeHTML) or as one of six strategies applied by the escape/e filter and the @escape region. A host-supplied SecurityPolicy (sandbox.Policy) restricts the permitted tags, filters, functions, per-type methods, and per-type properties, enforced at compile time for the tag/filter/function floor and at each host member-access site for the type-graph. The sandbox activates globally (WithSandboxActive), per @sandbox region, or per sandboxed include, and each violation raises a host-catchable *errors.Security. Allowlisting is uniform with no grandfathering: a host callable is gated exactly like a built-in.
Coverage ¶
An Environment with a cover.Collector attached (WithCoverage) records which units and branch arms each render exercised, unioning across renders and exported as text, LCOV, or HTML. Coverage is opt-in and zero-overhead when off, and instrumentation never changes rendered bytes.
Example ¶
Render a template by name from an in-memory template map. Output escaping is off by default.
package main
import (
"fmt"
quill "github.com/avmnu-sng/quill-template-engine"
"github.com/avmnu-sng/quill-template-engine/pkg/runtime"
)
func main() {
env := quill.NewWithArray(map[string]string{
"greet.quill": `Hello {{ name | upper }}{{ "!" if loud }}`,
})
out, err := env.Render("greet.quill", map[string]runtime.Value{
"name": runtime.Str("ada"),
"loud": runtime.Bool(true),
})
if err != nil {
panic(err)
}
fmt.Println(out)
}
Output: Hello ADA!
Index ¶
- Constants
- type Environment
- func (e *Environment) AutoescapeHTML() bool
- func (e *Environment) CompileString(name, body string) (*interp.Template, error)
- func (e *Environment) Coverage() *cover.Collector
- func (e *Environment) Display(w io.Writer, name string, vars map[string]runtime.Value) error
- func (e *Environment) Extensions() *ext.ExtensionSet
- func (e *Environment) LoadTemplate(name string) (*interp.Template, error)
- func (e *Environment) Logger() *log.Logger
- func (e *Environment) Policy() *sandbox.Policy
- func (e *Environment) RandomSeed() (int64, bool)
- func (e *Environment) RawSource(name string) (string, bool)
- func (e *Environment) Render(name string, vars map[string]runtime.Value) (string, error)
- func (e *Environment) RenderCache() *cache.RenderCache
- func (e *Environment) RenderString(name, body string, vars map[string]runtime.Value) (string, error)
- func (e *Environment) RenderStringTo(w io.Writer, name, body string, vars map[string]runtime.Value) error
- func (e *Environment) RenderStringValues(name, body string, vars map[string]any) (string, error)
- func (e *Environment) RenderTo(w io.Writer, name string, vars map[string]runtime.Value) error
- func (e *Environment) RenderToValues(w io.Writer, name string, vars map[string]any) error
- func (e *Environment) RenderValues(name string, vars map[string]any) (string, error)
- func (e *Environment) SandboxActive() bool
- func (e *Environment) StrictVariables() bool
- func (e *Environment) TabWidth() int
- func (e *Environment) TemplateExists(name string) bool
- type Option
- func WithAutoescapeHTML(on bool) Option
- func WithCompiled(manifests ...*compiled.Manifest) Option
- func WithCompiledVerify(report func(compiled.Divergence)) Option
- func WithCoverage(coll *cover.Collector) Option
- func WithExtension(exts ...ext.Extension) Option
- func WithExtensions(sets ...*ext.ExtensionSet) Option
- func WithLogger(l *log.Logger) Option
- func WithRandomSeed(seed int64) Option
- func WithSandboxActive(on bool) Option
- func WithSandboxPolicy(p *sandbox.Policy) Option
- func WithStrictVariables(on bool) Option
- func WithTabWidth(spaces int) Option
- func WithTypes(reg *check.Registry) Option
Examples ¶
Constants ¶
const Version = "0.3.0"
Version is the module's released semantic version, without the leading v. The release workflow requires the pushed tag to equal "v" + Version, so this constant is the single source of truth for the version the module reports.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Environment ¶
type Environment struct {
// contains filtered or unexported fields
}
Environment is the engine facade: it ties a Loader, a parse cache, and the callable registry together and renders templates by name or from a string. It implements interp.Engine so the tree-walking renderer can load parents, includes, and imports through it.
The defaults match the spec: autoescape is OFF by default (spec 04 Section 8.1) and strict_variables is ON (the strict-by-default undefined policy, spec 04 Section 6). Both are configurable via Option.
func New ¶
func New(ldr loader.Loader, opts ...Option) *Environment
New builds an Environment over a Loader with the given options. The registry is layered bottom-up: the core stdlib is the floor, then the engine-bound include/block-family callables, then each host extension set or bundle supplied via WithExtensions/WithExtension in option order. A later layer shadows an earlier one and every host layer shadows core (host callables shadow core, spec 03 Section 1).
func NewWithArray ¶
func NewWithArray(templates map[string]string, opts ...Option) *Environment
NewWithArray is a convenience constructor over an in-memory template map.
func (*Environment) AutoescapeHTML ¶
func (e *Environment) AutoescapeHTML() bool
AutoescapeHTML reports the default output strategy (interp.Engine).
func (*Environment) CompileString ¶
func (e *Environment) CompileString(name, body string) (*interp.Template, error)
CompileString parses and prepares an ad-hoc template body, backing template_from_string (interp.Engine, spec 03 Section 3.3). The body is not added to the loader; inheritance/include targets in it still resolve by name.
func (*Environment) Coverage ¶
func (e *Environment) Coverage() *cover.Collector
Coverage returns the host-attached coverage Collector, or nil when coverage is off (interp.Engine). The interpreter copies it into each render's cov field.
func (*Environment) Display ¶
Display renders the named template directly into w -- the push model of the Template contract, under its traditional name. It is RenderTo: a slot-free template closure streams with bounded memory, a slot-using one buffers then writes, and the bytes written equal Render's returned string.
func (*Environment) Extensions ¶
func (e *Environment) Extensions() *ext.ExtensionSet
Extensions returns the callable registry (interp.Engine).
func (*Environment) LoadTemplate ¶
func (e *Environment) LoadTemplate(name string) (*interp.Template, error)
LoadTemplate parses and prepares the named template (interp.Engine), with both steps memoized: the parse cache pins the module and the prepared memo pins the Template built from it, so a warm load is two map hits. LoadTemplate therefore returns the SAME *Template pointer across calls for an unchanged template; a Template is immutable after prepare and safe to share across concurrent renders. CompileString and the RenderString family stay uncached.
func (*Environment) Logger ¶
func (e *Environment) Logger() *log.Logger
Logger returns the sink the @log statement writes to (interp.Engine). It is never nil; without WithLogger it discards.
func (*Environment) Policy ¶
func (e *Environment) Policy() *sandbox.Policy
Policy returns the host-supplied sandbox security policy, or nil (interp.Engine).
func (*Environment) RandomSeed ¶
func (e *Environment) RandomSeed() (int64, bool)
RandomSeed returns the configured RNG seed and whether one was set (interp.Engine).
func (*Environment) RawSource ¶
func (e *Environment) RawSource(name string) (string, bool)
RawSource returns the unparsed source text of the named template, backing the source() function (interp.Engine, spec 03 Section 3.2).
func (*Environment) Render ¶
Render loads the named template and renders it with vars, returning the output. When an installed compiled unit (WithCompiled) passes the dispatch gate the render runs through the generated function with identical output and error bytes, including the partial output an errored render returns.
func (*Environment) RenderCache ¶
func (e *Environment) RenderCache() *cache.RenderCache
RenderCache returns the engine's rendered-body cache, backing @cache (interp.Engine, spec 01 Section 4.7).
func (*Environment) RenderString ¶
func (e *Environment) RenderString(name, body string, vars map[string]runtime.Value) (string, error)
RenderString parses an ad-hoc template body (not added to the loader) and renders it. Inheritance/include/import targets in the body still resolve through the loader by name.
func (*Environment) RenderStringTo ¶
func (e *Environment) RenderStringTo(w io.Writer, name, body string, vars map[string]runtime.Value) error
RenderStringTo parses an ad-hoc template body (not added to the loader) and renders it directly to w with RenderTo's streaming-vs-buffered behavior. Inheritance/include/import targets in the body still resolve through the loader by name.
func (*Environment) RenderStringValues ¶
RenderStringValues parses an ad-hoc template body (not added to the loader) and renders it from native Go bindings, marshaling each value through runtime.FromGo exactly as RenderValues does. Inheritance/include/import targets in the body still resolve through the loader by name.
func (*Environment) RenderTo ¶
RenderTo loads the named template and renders it directly to w. When the template closure uses no deferred-slot construct (@yield, @provide, slot()), the output streams to w incrementally with bounded memory; otherwise the full output is buffered, its slot placeholders are resolved, and the result is written to w in one call (nothing is written on a render error). The bytes written equal Render's returned string in both cases. RenderTo neither wraps nor flushes w; pass a bufio.Writer for buffered throughput and flush it after RenderTo returns (a @flush statement flushes such a writer mid-render). An installed compiled unit (WithCompiled) that passes the dispatch gate renders through the generated function: a slot-free unit streams to w exactly as the interpreter's slot-free path does, while a slots unit (Manifest.UsesSlots) buffers into a scratch builder that reaches w only on success, matching the interpreter's buffered-slots path which writes nothing on error -- so a mid-render error never leaks an unresolved placeholder to the caller's writer. Under WithCompiledVerify the dispatched render buffers both engines' outputs to compare them, then writes the interpreter's bytes: for a slot-free unit that includes an errored render's partial output (matching the streaming path), and for a slots unit it writes nothing on error (matching the buffered path).
Example ¶
Stream output to any io.Writer with RenderTo instead of buffering the whole result.
package main
import (
"os"
quill "github.com/avmnu-sng/quill-template-engine"
"github.com/avmnu-sng/quill-template-engine/pkg/runtime"
)
func main() {
env := quill.NewWithArray(map[string]string{
"list.quill": "@for n in nums {\nitem {{ n }}\n@}",
})
err := env.RenderTo(os.Stdout, "list.quill", map[string]runtime.Value{
"nums": runtime.Arr(runtime.NewList(
runtime.Int(1), runtime.Int(2), runtime.Int(3),
)),
})
if err != nil {
panic(err)
}
}
Output: item 1 item 2 item 3
func (*Environment) RenderToValues ¶
RenderToValues renders the named template directly to w like RenderTo, but from native Go bindings: each value in vars is marshaled through runtime.FromGo exactly as RenderValues does.
func (*Environment) RenderValues ¶
RenderValues renders the named template from native Go bindings: each value in vars is marshaled through runtime.FromGo, so a host can pass ordinary Go scalars, slices, maps, structs, and nested combinations without hand-building runtime.Value bindings. A value that is already a runtime.Value passes through unchanged, so hand-built and native bindings mix freely. An unsupported Go kind (a channel, a bare function, a complex number) returns the typed marshaling error and renders nothing.
Example ¶
Pass ordinary Go values -- structs, slices, scalars -- with RenderValues, which marshals each binding through runtime.FromGo.
package main
import (
"fmt"
quill "github.com/avmnu-sng/quill-template-engine"
)
func main() {
type User struct {
Name string `quill:"name"`
Admin bool `quill:"admin"`
Tags []string `quill:"tags"`
}
env := quill.NewWithArray(map[string]string{
"user.quill": `{{ user.name }} (admin: {{ user.admin }}) tags: {{ user.tags | join(", ") }}`,
})
out, err := env.RenderValues("user.quill", map[string]any{
"user": User{Name: "ada", Admin: true, Tags: []string{"x", "y"}},
})
if err != nil {
panic(err)
}
fmt.Println(out)
}
Output: ada (admin: true) tags: x, y
func (*Environment) SandboxActive ¶
func (e *Environment) SandboxActive() bool
SandboxActive reports the global sandbox activation gate (interp.Engine).
func (*Environment) StrictVariables ¶
func (e *Environment) StrictVariables() bool
StrictVariables reports the undefined-handling policy (interp.Engine).
func (*Environment) TabWidth ¶
func (e *Environment) TabWidth() int
TabWidth returns the spaces-per-indent-level width backing the tab filter, the tab/space/break functions, and the @tab region (interp.Engine, WithTabWidth).
func (*Environment) TemplateExists ¶
func (e *Environment) TemplateExists(name string) bool
TemplateExists reports whether the named template can be loaded (interp.Engine).
type Option ¶
type Option func(*Environment)
Option configures an Environment at construction.
func WithAutoescapeHTML ¶
WithAutoescapeHTML turns the default output strategy to html (off by default).
Example ¶
Turn on HTML escaping globally with WithAutoescapeHTML.
package main
import (
"fmt"
quill "github.com/avmnu-sng/quill-template-engine"
"github.com/avmnu-sng/quill-template-engine/pkg/runtime"
)
func main() {
env := quill.NewWithArray(
map[string]string{"page.quill": `<p>{{ body }}</p>`},
quill.WithAutoescapeHTML(true),
)
out, err := env.Render("page.quill", map[string]runtime.Value{
"body": runtime.Str("<b>hi</b>"),
})
if err != nil {
panic(err)
}
fmt.Println(out)
}
Output: <p><b>hi</b></p>
func WithCompiled ¶
WithCompiled installs generated compiled units (the compile backend's exported manifests) for by-name dispatch. Render, RenderTo, and the entry points delegating to them serve a template whose name matches an installed manifest through the generated render function instead of the interpreter, but only when the dispatch gate proves the bytes cannot differ: the manifest's compile-options fingerprint must equal this Environment's configuration, no sandbox policy or activation, coverage collector, or host type registry may be configured, a unit containing @log must not lose lines a non-discarding logger would receive, and every member source must byte-equal the text the loader currently serves (verified once and re-verified whenever the parse cache serves a re-parsed module). Any unprovable condition falls back to the interpreter, so installing a manifest changes render cost, never rendered bytes or errors. A host callable flagged NeedsEnvironment sees the serving path's own engine handle: the interpreter's and the generated code's handles are distinct concrete types exposing identical configuration through ext.EngineConfig, the injected handle's documented surface. A manifest missing its render function, entry name, or entry source is ignored; a later manifest for the same entry name replaces an earlier one. Templates whose output depends on UNSEEDED randomness are the documented exception: compiled and interpreted draws come from independent time-seeded sources, so their output compares distributionally, never byte-wise.
func WithCompiledVerify ¶
func WithCompiledVerify(report func(compiled.Divergence)) Option
WithCompiledVerify switches the installed compiled units (WithCompiled) from direct dispatch to shadow verification: a by-name render the dispatch gate would serve compiled instead runs both engines, byte-compares the outputs and error text, reports any divergence to the report callback, and always serves the interpreter's result. It is the trust-building mode for a new unit: production traffic renders exactly as before while every would-be compiled render is checked against the authoritative interpreter. Under verification a dispatched RenderTo buffers the render instead of streaming, since both outputs must exist to compare; the interpreter's bytes -- including the partial output of an errored render -- are then written to w, so the writer receives exactly what the streaming paths would have written. WithCompiledVerify(nil) is the same as not passing it: direct dispatch stays on.
func WithCoverage ¶
WithCoverage attaches a template-coverage Collector so every Render on this Environment records which units and branch arms it exercised, unioning across renders (package cover, docs/coverage.md). It mirrors WithAutoescapeHTML / WithStrictVariables. WithCoverage(nil) is the same as not passing it: coverage stays off and the interpreter pays no per-node cost. Coverage instrumentation only reads node positions and increments counters, so a template renders byte-identically with or without it (the binding invariant).
func WithExtension ¶
WithExtension layers one or more Extension bundles over the core stdlib. Each bundle is registered (its filters, functions, tests, constants, and enums folded in) in New, interleaved with WithExtensions layers in the order the options were passed, so shadow order is uniform across sets and bundles: later shadows earlier, and every host layer shadows core.
func WithExtensions ¶
func WithExtensions(sets ...*ext.ExtensionSet) Option
WithExtensions layers one or more host callable sets over the core stdlib. Each set is folded into the registry in New, after the core floor and the engine-bound callables, in the order given, so a later set shadows an earlier one and every host set shadows core (host shadows core, spec 03 Section 1). Multiple WithExtensions options accumulate in call order. Passing several sets in one call is equivalent to passing them across several options.
Example ¶
Register a host filter and function through the ext package and render with them.
package main
import (
"fmt"
quill "github.com/avmnu-sng/quill-template-engine"
"github.com/avmnu-sng/quill-template-engine/pkg/ext"
"github.com/avmnu-sng/quill-template-engine/pkg/runtime"
)
func main() {
set := ext.NewExtensionSet()
set.AddFunction(ext.NewFunction("clamp", func(x, lo, hi int64) int64 {
switch {
case x < lo:
return lo
case x > hi:
return hi
default:
return x
}
}))
env := quill.NewWithArray(
map[string]string{"demo.quill": `{{ clamp(42, 0, 10) }}`},
quill.WithExtensions(set),
)
out, err := env.Render("demo.quill", map[string]runtime.Value(nil))
if err != nil {
panic(err)
}
fmt.Println(out)
}
Output: 10
func WithLogger ¶
WithLogger sets the destination the @log statement writes to. The default is a discarding logger, so @log is inert until a host attaches a sink. @log produces no rendered output regardless of the logger.
func WithRandomSeed ¶
WithRandomSeed fixes the seed of the engine's randomness functions (random, shuffle), making their output deterministic and reproducible. This is the documented determinism mechanism for tests and golden output (spec 03 Section 3.2, X15); without it the functions draw from a time-seeded source. It is a host/environment knob, distinct from any template-author argument.
func WithSandboxActive ¶
WithSandboxActive turns the sandbox on globally so every render is sandboxed (the always-on activation path, design/escaping-safety Section 6.2). Without a policy an active sandbox denies everything.
func WithSandboxPolicy ¶
WithSandboxPolicy installs the host-supplied sandbox security policy: the allowlists for tags, filters, functions, per-type methods and properties, and the type-graph the per-type lookups walk (spec 04 Section 8.3). It does not by itself turn the sandbox on; activation is global (WithSandboxActive), per @sandbox region, or per sandboxed include. A policy is required for any of those to permit anything, since allowlisting is uniform with no grandfathering.
func WithStrictVariables ¶
WithStrictVariables sets strict-undefined handling (on by default). Setting it false enables the lenient mode: an undefined read becomes Null and a for over a non-iterable becomes an empty loop (spec 04 Section 6).
func WithTabWidth ¶
WithTabWidth sets the number of spaces one indent level expands to for the tab filter, the tab/space/break indentation functions, and the @tab region (spec 03 Section 5.1). The default is 4. A width below zero clamps to zero (an indent level then contributes nothing).
func WithTypes ¶
WithTypes installs the host static-typing registry the gradual type checker consults: the Object<"Name"> member shapes and host callable signatures (spec 04 Section 1, design/type-system.md Sections 4.4, 9.1). It does not enable or change any runtime behavior; it only sharpens the load-time checker so an annotation referencing a host type or a host callable can be verified. With no registry the checker still enforces every in-template annotation; Object types are then opaque and host calls dynamic.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
quill
command
Command quill renders a Quill template from disk with JSON data, measures template coverage, and compiles a template to a Go render function.
|
Command quill renders a Quill template from disk with JSON data, measures template coverage, and compiles a template to a Go render function. |
|
examples
|
|
|
braces
command
Command braces renders a brace-delimited config block: an nginx-style "server { ...
|
Command braces renders a brace-delimited config block: an nginx-style "server { ... |
|
coverage
command
Command coverage shows template coverage: it renders one template across two data cases through an Environment with a cover.Collector attached, then writes a text report and asserts a unit-coverage threshold.
|
Command coverage shows template coverage: it renders one template across two data cases through an Environment with a cover.Collector attached, then writes a text report and asserts a unit-coverage threshold. |
|
extension
command
Command extension shows how a host adds its own callables.
|
Command extension shows how a host adds its own callables. |
|
filters
command
Command filters shows the expression language: pipe filters, a postfix-if, a for loop with loop metadata, and the strict typed equality / coalesce rules.
|
Command filters shows the expression language: pipe filters, a postfix-if, a for loop with loop metadata, and the strict typed equality / coalesce rules. |
|
inheritance
command
Command inheritance shows template inheritance: a child @extends a base layout, overrides a @block, and pulls the base content in via parent().
|
Command inheritance shows template inheritance: a child @extends a base layout, overrides a @block, and pulls the base content in via parent(). |
|
internal
|
|
|
jsonval
Package jsonval converts decoded JSON into Quill runtime values.
|
Package jsonval converts decoded JSON into Quill runtime values. |
|
pkg
|
|
|
ast
Package ast is Quill's abstract syntax tree: a single uniform Node type whose Kind field discriminates every construct, with ordered Children and a 1-based source position.
|
Package ast is Quill's abstract syntax tree: a single uniform Node type whose Kind field discriminates every construct, with ordered Children and a 1-based source position. |
|
cache
Package cache memoizes parsed templates by name so a template referenced many times (a base layout, a shared macro file) is lexed and parsed once.
|
Package cache memoizes parsed templates by name so a template referenced many times (a base layout, a shared macro file) is lexed and parsed once. |
|
check
Package check is Quill's gradual type checker: a front-end pass that runs between parse and interpret, consumes the type annotations the parser already threads through the AST (the @types block, @set/@for targets, @macro/@block params and returns, and arrow params), infers static types where the spec defines it, applies the gradual `any` fallback for everything unannotated, and reports ill-typed templates with positioned errors BEFORE any byte is rendered (spec 04 Sections 1-3, design/type-system.md).
|
Package check is Quill's gradual type checker: a front-end pass that runs between parse and interpret, consumes the type annotations the parser already threads through the AST (the @types block, @set/@for targets, @macro/@block params and returns, and arrow params), infers static types where the spec defines it, applies the gradual `any` fallback for everything unannotated, and reports ill-typed templates with positioned errors BEFORE any byte is rendered (spec 04 Sections 1-3, design/type-system.md). |
|
compile
Package compile lowers a parsed Quill module to a single deterministic Go source file whose render function writes the template's output to an io.Writer.
|
Package compile lowers a parsed Quill module to a single deterministic Go source file whose render function writes the template's output to an io.Writer. |
|
compiled
Package compiled defines the manifest contract between generated render functions (the compile backend's output) and the Environment's compiled dispatch (quill.WithCompiled).
|
Package compiled defines the manifest contract between generated render functions (the compile backend's output) and the Environment's compiled dispatch (quill.WithCompiled). |
|
cover
Package cover measures which parts of a Quill template a set of renders actually exercised: which statements and interpolations ran (units), and which arms of each branch were taken (branches).
|
Package cover measures which parts of a Quill template a set of renders actually exercised: which statements and interpolations ran (units), and which arms of each branch were taken (branches). |
|
errors
Package errors is Quill's typed error family.
|
Package errors is Quill's typed error family. |
|
ext
Package ext is Quill's extension surface: the value objects for the three callable kinds (Filter, Function, Test) and the ExtensionSet registry that holds them.
|
Package ext is Quill's extension surface: the value objects for the three callable kinds (Filter, Function, Test) and the ExtensionSet registry that holds them. |
|
interp
Package interp is Quill's tree-walking renderer.
|
Package interp is Quill's tree-walking renderer. |
|
lex
Package lex is Quill's lexer: a byte-oriented, two-mode (TEXT/CODE) scanner for the @-sigil default statement form described in spec 01-language-reference Section 1, spec 02-grammar Section 2, and design/lexical.md.
|
Package lex is Quill's lexer: a byte-oriented, two-mode (TEXT/CODE) scanner for the @-sigil default statement form described in spec 01-language-reference Section 1, spec 02-grammar Section 2, and design/lexical.md. |
|
loader
Package loader resolves a template name to its source bytes.
|
Package loader resolves a template name to its source bytes. |
|
parse
Package parse turns a Quill template into an ast.Module.
|
Package parse turns a Quill template into an ast.Module. |
|
runtime
Package runtime is the root of Quill's value system: the sealed Value taxonomy, the ordered dual-view *Array, the Context variable scope, the host Object interface, and the typed operations (Equal, Order, Truthy, Empty, ToText, GetAttribute, iteration).
|
Package runtime is the root of Quill's value system: the sealed Value taxonomy, the ordered dual-view *Array, the Context variable scope, the host Object interface, and the typed operations (Equal, Order, Truthy, Empty, ToText, GetAttribute, iteration). |
|
sandbox
Package sandbox is Quill's host-supplied security policy: five allowlists (tags, filters, functions, per-type methods, per-type properties) plus the host TYPE-GRAPH that powers the per-type member lookups.
|
Package sandbox is Quill's host-supplied security policy: five allowlists (tags, filters, functions, per-type methods, per-type properties) plus the host TYPE-GRAPH that powers the per-type member lookups. |
|
source
Package source carries a Quill template's origin: a name and its raw bytes, with line endings normalized so that error positions and rendered output do not depend on the host platform's newline convention.
|
Package source carries a Quill template's origin: a name and its raw bytes, with line endings normalized so that error positions and rendered output do not depend on the host platform's newline convention. |