Only the liquid package itself, and the sub-package types that are used in that top-level package, are guaranteed stable. For example, `render.Context` is documented as the parameter type for tag definitions; it therefore won't change incompatibly, if ever, until at least version 2 (at which point `gopkg.in/osteele/liquid.v1` will continue to pin to the v1 implementation).
`Render` and friends take a `Bindings` parameter. This is a map of `string` to `interface{}`, that associates template variable names with Go values.
Any Go value can be used as a variable value. These values have special meaning:
-`false` and `nil`
- These, and no other values, are recognized as false by `and`, `or, `{% if %}`, `{% elsif %}`, and `{% case %}`.
- Integers
- (Only) integers can be used as array indices: `array[1]`; `array[n]`, where `array` has an array value and `n` has an integer value.
- (Only) integers can be used as the endpoints of a range: `{% for item in (1..5) %}`, `{% for item in (start..end) %}` where `start` and `end` have integer values.
- Integers and floats
- Integers and floats are converted to their join type for comparison: `1 == 1.0` evaluates to `true`. Similarly, `int8(1)`, `int16(1)`, `uint8(1)` etc. are all `==`.
- [There is currently no special treatment of complex numbers.]
- Integers, floats, and strings
- Integers, floats, and strings can be used in comparisons `<`, `>`, `<=`, `>=`. Integers and floats can be meaningfully compared with each other. Strings can be meaningfully compared with each other but not with other values. Any other comparison, e.g. `1 < "one"`, `1 > "one"`, will always be false.
- Arrays (and slices)
- An array can be indexed by integer `array[1]`; `array[n]` where `n` has an integer value.
- Arrays have `first`, `last`, and `size` properties: `array.first == array[0]`, `array[array.size-1] == array.last` (where `array.size > 0`)
- Maps
- A map can be indexed by a string: `hash[“key”]`; `hash[s]` where `s` has a string value
- A map can be accessed using property syntax `hash.key`
- Maps have a special `size` property, that returns the size of the map.
- Drops
- A value `value` of a type that implements the `Drop` interface acts as the value `value.ToLiquid()`. There is no guarantee about how many times `ToLiquid` will be called. [This is in contrast to Shopify Liquid, which both uses a different interface for drops, and makes stronger guarantees.]
- If the value of the field is a function that takes no arguments and returns either one or two arguments, accessing it invokes the function, and the value of the property is its first return value.
- If the second return value is non-nil, accessing the field panics instead.
- A value of type `[]byte` is rendered as the corresponding string, and presented as a string to filters that expect one. A `[]byte` is not (currently) equivalent to a `string` for all uses; for example, `a < b`, `a contains b`, `hash[b]` will not behave as expected where `a` or `b` is a `[]byte`.
* [Help.shopify.com](https://help.shopify.com/themes/liquid) goes into more detail, but includes features that aren't present in core Liquid as used by Jekyll.
Michael Hamrah's [Lexing with Ragel and Parsing with Yacc using Go](https://medium.com/@mhamrah/lexing-with-ragel-and-parsing-with-yacc-using-go-81e50475f88f) was essential to understanding `go yacc`.
The [original Liquid engine](https://shopify.github.io/liquid), 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.