2017-07-16 23:43:04 +02:00
|
|
|
# Liquid Template Parser
|
2017-07-02 14:47:10 +02:00
|
|
|
|
2021-06-26 08:43:59 +02:00
|
|
|
[![go badge][go-svg]][go-url]
|
|
|
|
[![Golangci-lint badge][golangci-lint-svg]][golangci-lint-url]
|
2021-06-26 08:54:25 +02:00
|
|
|
[![Go Report Card badge][go-report-card-svg]][go-report-card-url]
|
|
|
|
[![Go Doc][godoc-svg]][godoc-url]
|
|
|
|
[![MIT License][license-svg]][license-url]
|
2017-06-25 17:23:20 +02:00
|
|
|
|
2021-06-26 08:54:25 +02:00
|
|
|
`liquid` is a pure Go implementation of [Shopify Liquid
|
|
|
|
templates](https://shopify.github.io/liquid). It was developed for use in the
|
|
|
|
[Gojekyll](https://github.com/osteele/gojekyll) port of the Jekyll static site
|
|
|
|
generator.
|
2017-07-02 06:10:54 +02:00
|
|
|
|
2017-07-02 02:24:27 +02:00
|
|
|
<!-- TOC -->
|
|
|
|
|
2017-07-16 23:43:04 +02:00
|
|
|
- [Liquid Template Parser](#liquid-template-parser)
|
2018-06-05 22:01:28 +02:00
|
|
|
- [Installation](#installation)
|
|
|
|
- [Usage](#usage)
|
|
|
|
- [Command-Line tool](#command-line-tool)
|
|
|
|
- [Documentation](#documentation)
|
|
|
|
- [Status](#status)
|
|
|
|
- [Drops](#drops)
|
|
|
|
- [Value Types](#value-types)
|
2017-07-02 02:24:27 +02:00
|
|
|
- [References](#references)
|
2018-06-05 22:01:28 +02:00
|
|
|
- [Contributing](#contributing)
|
2018-05-30 22:54:10 +02:00
|
|
|
- [Contributors](#contributors)
|
2018-06-05 22:01:28 +02:00
|
|
|
- [Attribution](#attribution)
|
|
|
|
- [Other Implementations](#other-implementations)
|
|
|
|
- [Go](#go)
|
|
|
|
- [Other Languages](#other-languages)
|
|
|
|
- [License](#license)
|
2017-07-02 02:24:27 +02:00
|
|
|
|
|
|
|
<!-- /TOC -->
|
2017-06-25 17:23:20 +02:00
|
|
|
|
2018-06-05 22:01:28 +02:00
|
|
|
## Installation
|
2017-06-25 17:23:20 +02:00
|
|
|
|
2017-07-16 17:15:31 +02:00
|
|
|
`go get gopkg.in/osteele/liquid.v1` # latest snapshot
|
2017-07-10 05:15:05 +02:00
|
|
|
|
2017-07-21 02:49:35 +02:00
|
|
|
`go get -u github.com/osteele/liquid` # development version
|
2017-07-10 05:15:05 +02:00
|
|
|
|
|
|
|
## Usage
|
2017-06-25 17:23:20 +02:00
|
|
|
|
2017-07-10 05:15:05 +02:00
|
|
|
```go
|
2017-07-16 03:18:10 +02:00
|
|
|
engine := liquid.NewEngine()
|
2017-07-10 05:15:05 +02:00
|
|
|
template := `<h1>{{ page.title }}</h1>`
|
|
|
|
bindings := map[string]interface{}{
|
|
|
|
"page": map[string]string{
|
|
|
|
"title": "Introduction",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
out, err := engine.ParseAndRenderString(template, bindings)
|
|
|
|
if err != nil { log.Fatalln(err) }
|
|
|
|
fmt.Println(out)
|
|
|
|
// Output: <h1>Introduction</h1>
|
|
|
|
```
|
|
|
|
|
2018-06-05 22:01:28 +02:00
|
|
|
See the [API documentation][godoc-url] for additional examples.
|
|
|
|
|
2017-07-10 05:15:05 +02:00
|
|
|
### Command-Line tool
|
|
|
|
|
2021-06-26 08:54:25 +02:00
|
|
|
`go install gopkg.in/osteele/liquid.v0/cmd/liquid` installs a command-line
|
|
|
|
`liquid` executable. This is intended to make it easier to create test cases for
|
|
|
|
bug reports.
|
2017-07-10 05:15:05 +02:00
|
|
|
|
|
|
|
```bash
|
|
|
|
$ liquid --help
|
|
|
|
usage: liquid [FILE]
|
|
|
|
$ echo '{{ "Hello World" | downcase | split: " " | first | append: "!"}}' | liquid
|
|
|
|
hello!
|
|
|
|
```
|
2017-07-05 19:46:30 +02:00
|
|
|
|
2018-06-05 22:01:28 +02:00
|
|
|
## Documentation
|
|
|
|
|
|
|
|
### Status
|
|
|
|
|
|
|
|
These features of Shopify Liquid aren't implemented:
|
|
|
|
|
|
|
|
- Warn and lax [error modes](https://github.com/shopify/liquid#error-modes).
|
|
|
|
- Non-strict filters. An undefined filter is currently an error.
|
|
|
|
- Strict variables. An undefined variable is not an error.
|
|
|
|
|
|
|
|
### Drops
|
|
|
|
|
2021-06-26 08:54:25 +02:00
|
|
|
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() interface{}`, 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.
|
2018-06-05 22:01:28 +02:00
|
|
|
|
|
|
|
### Value Types
|
2017-07-21 18:06:39 +02:00
|
|
|
|
2021-06-26 08:54:25 +02:00
|
|
|
`Render` and friends take a `Bindings` parameter. This is a map of `string` to
|
|
|
|
`interface{}`, that associates template variable names with Go values.
|
2017-07-21 18:06:39 +02:00
|
|
|
|
|
|
|
Any Go value can be used as a variable value. These values have special meaning:
|
|
|
|
|
|
|
|
- `false` and `nil`
|
2021-06-26 08:54:25 +02:00
|
|
|
- These, and no other values, are recognized as false by `and`, `or`, `{% if
|
|
|
|
%}`, `{% elsif %}`, and `{% case %}`.
|
2017-07-21 18:06:39 +02:00
|
|
|
- Integers
|
2021-06-26 08:54:25 +02:00
|
|
|
- (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.
|
2017-07-21 18:06:39 +02:00
|
|
|
- Integers and floats
|
2021-06-26 08:54:25 +02:00
|
|
|
- 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 `==`.
|
2017-07-21 18:06:39 +02:00
|
|
|
- [There is currently no special treatment of complex numbers.]
|
|
|
|
- Integers, floats, and strings
|
2021-06-26 08:54:25 +02:00
|
|
|
- Integers, floats, and strings can be used in comparisons `<`, `>`, `<=`,
|
|
|
|
`>=`. Integers and floats can be usefully compared with each other. Strings
|
|
|
|
can be usefully compared with each other, but not with other values. Any
|
|
|
|
other comparison, e.g. `1 < "one"`, `1 > "one"`, is always false.
|
2017-07-21 18:06:39 +02:00
|
|
|
- Arrays (and slices)
|
2021-06-26 08:54:25 +02:00
|
|
|
- An array can be indexed by integer value: `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`)
|
2017-07-21 18:06:39 +02:00
|
|
|
- Maps
|
2021-06-26 08:54:25 +02:00
|
|
|
- A map can be indexed by a string: `hash["key"]`; `hash[s]` where `s` has a
|
|
|
|
string value
|
2017-07-21 18:06:39 +02:00
|
|
|
- A map can be accessed using property syntax `hash.key`
|
|
|
|
- Maps have a special `size` property, that returns the size of the map.
|
|
|
|
- Drops
|
2021-06-26 08:54:25 +02:00
|
|
|
- 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.]
|
2017-07-21 18:06:39 +02:00
|
|
|
- Structs
|
2018-05-30 22:54:10 +02:00
|
|
|
- A public field of a struct can be accessed by its name: `value.FieldName`, `value["fieldName"]`.
|
2017-07-23 17:49:09 +02:00
|
|
|
- A field tagged e.g. `liquid:”name”` is accessed as `value.name` instead.
|
2021-06-26 08:54:25 +02:00
|
|
|
- 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.
|
2017-07-21 18:06:39 +02:00
|
|
|
- If the second return value is non-nil, accessing the field panics instead.
|
2021-06-26 08:54:25 +02:00
|
|
|
- A function defined on a struct can be accessed by function name e.g.
|
|
|
|
`value.Func`, `value["Func"]`.
|
2017-07-21 18:06:39 +02:00
|
|
|
- The same rules apply as to accessing a func-valued public field.
|
2021-06-26 08:54:25 +02:00
|
|
|
- Note that despite being array- and map-like, structs do not have a special
|
|
|
|
`value.size` property.
|
2017-07-23 17:49:09 +02:00
|
|
|
- `[]byte`
|
2021-06-26 08:54:25 +02:00
|
|
|
- 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`.
|
2018-06-05 22:01:28 +02:00
|
|
|
- `MapSlice`
|
2021-06-26 08:54:25 +02:00
|
|
|
- An instance of `yaml.MapSlice` acts as a map. It implements `m.key`,
|
|
|
|
`m[key]`, and `m.size`.
|
2017-07-21 18:06:39 +02:00
|
|
|
|
2018-06-05 22:01:28 +02:00
|
|
|
### References
|
|
|
|
|
2021-06-26 08:54:25 +02:00
|
|
|
- [Shopify.github.io/liquid](https://shopify.github.io/liquid)
|
|
|
|
- [Liquid for Designers](https://github.com/Shopify/liquid/wiki/Liquid-for-Designers)
|
|
|
|
- [Liquid for Programmers](https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers)
|
|
|
|
- [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.
|
2018-06-05 22:01:28 +02:00
|
|
|
|
2017-07-05 15:51:00 +02:00
|
|
|
## Contributing
|
2017-06-25 18:36:28 +02:00
|
|
|
|
2017-07-05 15:51:00 +02:00
|
|
|
Bug reports, test cases, and code contributions are more than welcome.
|
|
|
|
Please refer to the [contribution guidelines](./CONTRIBUTING.md).
|
2017-06-28 00:06:26 +02:00
|
|
|
|
2018-06-05 22:01:28 +02:00
|
|
|
### Contributors
|
2017-06-28 00:06:26 +02:00
|
|
|
|
2018-06-05 22:01:28 +02:00
|
|
|
Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):
|
|
|
|
|
|
|
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
2021-06-27 05:06:14 +02:00
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<!-- markdownlint-disable -->
|
|
|
|
<table>
|
|
|
|
<tr>
|
|
|
|
<td align="center"><a href="https://osteele.com/"><img src="https://avatars2.githubusercontent.com/u/674?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Oliver Steele</b></sub></a><br /><a href="https://github.com/osteele/liquid/commits?author=osteele" title="Code">💻</a> <a href="https://github.com/osteele/liquid/commits?author=osteele" title="Documentation">📖</a> <a href="#ideas-osteele" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-osteele" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/osteele/liquid/pulls?q=is%3Apr+reviewed-by%3Aosteele" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/osteele/liquid/commits?author=osteele" title="Tests">⚠️</a></td>
|
|
|
|
<td align="center"><a href="https://github.com/thessem"><img src="https://avatars0.githubusercontent.com/u/973593?v=4?s=100" width="100px;" alt=""/><br /><sub><b>James Littlejohn</b></sub></a><br /><a href="https://github.com/osteele/liquid/commits?author=thessem" title="Code">💻</a> <a href="https://github.com/osteele/liquid/commits?author=thessem" title="Documentation">📖</a> <a href="https://github.com/osteele/liquid/commits?author=thessem" title="Tests">⚠️</a></td>
|
|
|
|
<td align="center"><a href="http://nosmileface.ru"><img src="https://avatars2.githubusercontent.com/u/12567?v=4?s=100" width="100px;" alt=""/><br /><sub><b>nsf</b></sub></a><br /><a href="https://github.com/osteele/liquid/commits?author=nsf" title="Code">💻</a> <a href="https://github.com/osteele/liquid/commits?author=nsf" title="Tests">⚠️</a></td>
|
|
|
|
<td align="center"><a href="https://tobias.salzmann.berlin/"><img src="https://avatars.githubusercontent.com/u/796084?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tobias Salzmann</b></sub></a><br /><a href="https://github.com/osteele/liquid/commits?author=Eun" title="Code">💻</a></td>
|
2021-07-05 08:29:24 +02:00
|
|
|
<td align="center"><a href="https://github.com/bendoerr"><img src="https://avatars.githubusercontent.com/u/253068?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ben Doerr</b></sub></a><br /><a href="https://github.com/osteele/liquid/commits?author=bendoerr" title="Code">💻</a></td>
|
2021-06-27 05:06:14 +02:00
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
<!-- markdownlint-restore -->
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
|
2018-06-05 22:01:28 +02:00
|
|
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
|
|
|
|
2021-06-26 08:54:25 +02:00
|
|
|
This project follows the
|
|
|
|
[all-contributors](https://github.com/kentcdodds/all-contributors)
|
|
|
|
specification. Contributions of any kind welcome!
|
2017-06-28 00:06:26 +02:00
|
|
|
|
2018-06-05 22:01:28 +02:00
|
|
|
### Attribution
|
2017-06-25 22:21:31 +02:00
|
|
|
|
2017-07-22 15:14:32 +02:00
|
|
|
| Package | Author | Description | License |
|
|
|
|
|-----------------------------------------------------|-----------------|----------------------|--------------------|
|
|
|
|
| [Ragel](http://www.colm.net/open-source/ragel/) | Adrian Thurston | scanning expressions | MIT |
|
|
|
|
| [gopkg.in/yaml.v2](https://github.com/go-yaml/yaml) | Canonical | MapSlice | Apache License 2.0 |
|
2017-06-28 00:06:26 +02:00
|
|
|
|
2021-06-26 08:54:25 +02:00
|
|
|
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`.
|
2017-06-26 14:23:50 +02:00
|
|
|
|
2021-06-26 08:54:25 +02:00
|
|
|
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.
|
2017-06-28 00:06:26 +02:00
|
|
|
|
2017-06-28 15:45:20 +02:00
|
|
|
## Other Implementations
|
|
|
|
|
2017-07-02 02:24:27 +02:00
|
|
|
### Go
|
|
|
|
|
2021-06-26 08:54:25 +02:00
|
|
|
- [karlseguin/liquid](https://github.com/karlseguin/liquid) is a dormant
|
|
|
|
implementation that inspired a lot of forks.
|
|
|
|
- [acstech/liquid](https://github.com/acstech/liquid) is a more active fork of
|
|
|
|
Karl Seguin's implementation.
|
|
|
|
- [hownowstephen/go-liquid](https://github.com/hownowstephen/go-liquid)
|
2017-06-28 15:45:20 +02:00
|
|
|
|
2017-07-02 02:24:27 +02:00
|
|
|
### Other Languages
|
2017-06-28 15:45:20 +02:00
|
|
|
|
2017-07-02 02:24:27 +02:00
|
|
|
See Shopify's [ports of Liquid to other environments](https://github.com/Shopify/liquid/wiki/Ports-of-Liquid-to-other-environments).
|
2017-06-28 15:45:20 +02:00
|
|
|
|
2017-06-26 14:23:50 +02:00
|
|
|
## License
|
|
|
|
|
|
|
|
MIT License
|
2017-07-07 11:41:37 +02:00
|
|
|
|
|
|
|
[coveralls-url]: https://coveralls.io/r/osteele/liquid?branch=master
|
|
|
|
[coveralls-svg]: https://img.shields.io/coveralls/osteele/liquid.svg?branch=master
|
|
|
|
|
2021-07-06 04:15:01 +02:00
|
|
|
[go-url]: https://github.com/osteele/liquid/actions?query=workflow%3A%22Build+Status%22
|
2021-06-26 09:07:52 +02:00
|
|
|
[go-svg]: https://github.com/osteele/liquid/actions/workflows/go.yml/badge.svg
|
2021-06-26 08:43:59 +02:00
|
|
|
|
2021-06-26 09:07:52 +02:00
|
|
|
[golangci-lint-url]: https://github.com/osteele/liquid/actions?query=workflow%3Agolangci-lint
|
|
|
|
[golangci-lint-svg]: https://github.com/osteele/liquid/actions/workflows/golangci-lint.yml/badge.svg
|
2021-06-26 08:43:59 +02:00
|
|
|
|
2017-07-07 11:41:37 +02:00
|
|
|
[godoc-url]: https://godoc.org/github.com/osteele/liquid
|
|
|
|
[godoc-svg]: https://godoc.org/github.com/osteele/liquid?status.svg
|
|
|
|
|
|
|
|
[license-url]: https://github.com/osteele/liquid/blob/master/LICENSE
|
|
|
|
[license-svg]: https://img.shields.io/badge/license-MIT-blue.svg
|
|
|
|
|
|
|
|
[go-report-card-url]: https://goreportcard.com/report/github.com/osteele/liquid
|
|
|
|
[go-report-card-svg]: https://goreportcard.com/badge/github.com/osteele/liquid
|