GitHub - osteele/liquid: A Liquid template engine in Go (original) (raw)

Liquid Template Parser

go badge Golangci-lint badge Go Report Card badge Go Doc MIT License

liquid is a pure Go implementation of Shopify Liquid templates. It was developed for use in theGojekyll port of the Jekyll static site generator.

Installation

go get github.com/osteele/liquid # latest version

go get -u github.com/osteele/liquid # development version

Usage

engine := liquid.NewEngine() template := <h1>{{ page.title }}</h1> bindings := map[string]any{ "page": map[string]string{ "title": "Introduction", }, } out, err := engine.ParseAndRenderString(template, bindings) if err != nil { log.Fatalln(err) } fmt.Println(out) // Output:

Introduction

See the API documentation for additional examples.

Jekyll Compatibility

This library was originally developed for Gojekyll, a Go port of Jekyll. As such, it includes optional Jekyll-specific extensions that are not part of the Shopify Liquid specification.

To enable Jekyll compatibility mode:

engine := liquid.NewEngine() engine.EnableJekyllExtensions()

Jekyll extensions include:

Example:

engine := liquid.NewEngine() engine.EnableJekyllExtensions() // Enable Jekyll-specific features

template := {% assign page.meta.author = "John Doe" %}{{ page.meta.author }} bindings := map[string]any{ "page": map[string]any{ "title": "Home", }, } out, _ := engine.ParseAndRenderString(template, bindings) // Output: John Doe

Note: Jekyll extensions are disabled by default to maintain compatibility with standard Shopify Liquid.

Command-Line tool

go install github.com/osteele/liquid/cmd/liquid@latest installs a command-lineliquid executable. This is intended to make it easier to create test cases for bug reports.

$ liquid --help usage: liquid [FILE] $ echo '{{ "Hello World" | downcase | split: " " | first | append: "!"}}' | liquid hello!

Security

Important: If you plan to process untrusted templates (templates authored by users you don't fully trust), please review the Security Policy documentation.

Key security considerations:

For detailed information about security guarantees, limitations, and production deployment recommendations, see SECURITY.md. For implementing resource limits, see the FRender documentation.

Documentation

This section provides a comprehensive guide to using and extending the Liquid template engine. Documentation is organized by topic:

Getting Started

Core Concepts

Advanced Usage

Security & Performance

Internals

Contributing


Status

These features of Shopify Liquid aren't implemented:

Drops

Drops have a different design from the Shopify (Ruby) implementation. A Ruby drop sets liquid_attributes to a list of attributes that are exposed to Liquid. A Go drop implements ToLiquid() any, that returns a proxy object. Conventionally, the proxy is a map or struct that defines the exposed properties. See http://godoc.org/github.com/osteele/liquid#Drop for additional information.

Value Types

Render and friends take a Bindings parameter. This is a map of string toany, that associates template variable names with Go values.

Any Go value can be used as a variable value. These values have special meaning:

Template Store

The template store allows for usage of varying template storage implementations (embedded file system, database, service, etc). In order to use:

  1. Create a struct that implements TemplateStore
    type TemplateStore interface {
    ReadTemplate(templatename string) ([]byte, error)
    }
  2. Register with the engine
    engine.RegisterTemplateStore(myTemplateStore)

FileTemplateStore is the default mechanism for backwards compatibility.

Refer to example for an example implementation.

Advanced Rendering

Custom Writers (FRender)

For advanced use cases like streaming to files, implementing timeouts, or limiting output size, use the FRender method to render directly to any io.Writer:

var buf bytes.Buffer err := template.FRender(&buf, bindings)

This is particularly useful for:

See the FRender documentation for detailed examples and security best practices.

References

Contributing

Bug reports, test cases, and code contributions are more than welcome. Please refer to the contribution guidelines.

Contributors

Thanks goes to these wonderful people (emoji key):

Oliver SteeleπŸ’» πŸ“– πŸ€” πŸš‡ πŸ‘€ ⚠️ James LittlejohnπŸ’» πŸ“– ⚠️ nsfπŸ’» ⚠️ Tobias SalzmannπŸ’» Ben DoerrπŸ’» Daniil GentiliπŸ’» Carolyn Van SlyckπŸ’»
Kimmo LehtoπŸ’» Victor "Vito" GamaπŸ’» Utpal SarkarπŸ’» ⚠️ Misko LeeπŸ’» Andre LehmannπŸ’» James O'GormanπŸ’» πŸ› Olivier FavreπŸ’»
Peter AbaπŸ“– Christopher HillπŸ’» πŸ› Steve AtkinsπŸ’» πŸ› Preston PriceπŸ’» jamslingerπŸ’» πŸ› Andreas DeiningerπŸ’» Matteo Agius-D'ArrigoπŸ’»
Cody KriegerπŸ’» StΓ©phane JAISπŸ’» James NewmanπŸ’» πŸ› chrisπŸ’» Dmitry PanovπŸ’» Gauthier HacoutπŸ›

This project follows theall-contributorsspecification. Contributions of any kind welcome!

Attribution

Package Author Description License
Ragel Adrian Thurston scanning expressions MIT
gopkg.in/yaml.v2 Canonical MapSlice Apache License 2.0

Michael Hamrah's Lexing with Ragel and Parsing with Yacc using Gowas essential to understanding go yacc.

The original Liquid engine, of course, for the design and documentation of the Liquid template language. Many of the tag and filter test cases are taken directly from the Liquid documentation.

Other Implementations

Go

Other Languages

See Shopify's ports of Liquid to other environments.

License

MIT License