mist

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2026 License: MIT Imports: 8 Imported by: 0

README

mist

CI

A single-pass renderer for a strict subset of Liquid, fast enough that it's cheap to try before falling back to a full engine.

mist evaluates as it scans: no tokenize, compile or AST step, and no allocations on the hot path. As soon as it meets anything outside the subset it returns ErrUnsupported, and you render with your full Liquid engine instead. For every template it accepts, its output matches liquidjs 10 (lenientIf: true) byte for byte.

out, err := mist.Render(nil, tpl, vars, strict)
switch {
case errors.Is(err, mist.ErrUnsupported):
	// outside the subset: render with the full engine
case errors.Is(err, mist.ErrUndefined):
	// strict mode, undefined variable; the full engine fails too
}

RenderChain renders a sequence of templates whose outputs feed later ones, such as snippets, then subject, then body, then layout. It stops at the first step mist can't handle, so only the remaining steps go to the full engine.

What's supported

Variables and paths ({{ a.b[0]['k'] }}), string/integer/boolean/nil literals, if/elsif/else/unless, for … in, assign, comment, raw, comparisons, and/or, and whitespace control. No filters yet. SPEC.md is the normative grammar and semantics.

Check whether templates are in the subset:

go run github.com/hownowstephen/mist/cmd/mistcheck@latest template.liquid

Testing

Beyond unit tests, mist is diffed against liquidjs on every template from Shopify/liquid-spec and Shopify/liquid's test suite, plus grammar-generated templates (100k new ones nightly) and fuzzing. See SPEC.md § Verification.

License

MIT

Documentation

Overview

Package mist renders a strict subset of Liquid in a single pass, bailing with ErrUnsupported on anything outside the subset so the caller can fall back to a full engine. See SPEC.md for the exact subset.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrUnsupported means the template is outside the subset; render it with the full engine instead.
	ErrUnsupported = errors.New("mist: unsupported")
	// ErrUndefined is a strict-mode undefined variable. The full engine fails too, though a
	// syntax error later in the template may take precedence there.
	ErrUndefined = errors.New("mist: undefined variable")
)

Functions

func Check

func Check(tpl string) (err error)

Check reports whether tpl is inside the subset, parsing every branch without data. Templates that pass can still bail at render time on data-dependent rules (see SPEC.md).

func Render

func Render(dst []byte, tpl string, vars map[string]any, strict bool) (out []byte, err error)

Render appends the rendered template to dst. On error out is nil.

Types

type Error

type Error struct {
	Kind error // ErrUnsupported or ErrUndefined
	Pos  int   // byte offset into the template
	Msg  string
}

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

type Result

type Result struct {
	Out string
	Err error // ErrUndefined; unsupported steps are never returned
}

func RenderChain

func RenderChain(steps []Step, vars map[string]any) (res []Result, n int, hydrated map[string]any)

RenderChain renders steps in order, binding each output into the vars seen by later steps exactly as the render service does. It stops at the first step mist can't render and returns n, its index; the caller renders steps[n:] with the full engine using the returned vars. The caller's maps are never mutated.

type Step

type Step struct {
	Body      string
	Key       []string // where the output is bound for later steps
	Strict    bool
	Premailer bool           // unsupported: inlined output may feed later steps
	Vars      map[string]any // replaces the chain vars for this step only
}

Step mirrors one entry of the render service's `render` array.

Directories

Path Synopsis
cmd
mistcheck command
Command mistcheck reports whether Liquid templates are inside the mist subset.
Command mistcheck reports whether Liquid templates are inside the mist subset.
scripts
gen command
Command gen writes random templates drawn from the SPEC.md grammar, with random data, in harvest.rb's format for oracle.mjs.
Command gen writes random templates drawn from the SPEC.md grammar, with random data, in harvest.rb's format for oracle.mjs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL