liquid.cr
liquid.cr copied to clipboard
Liquid template engine for Crystal
liquid - Liquid template engine for Crystal
Liquid templating language: http://shopify.github.io/liquid/
Installation
Add this to your application's shard.yml:
dependencies:
liquid:
github: TechMagister/liquid.cr
Usage
require "liquid"
txt = "
{% if kenny.sick %}
Kenny is sick.
{% elsif kenny.dead %}
You killed Kenny! You ***!!!
{% else %}
Kenny looks okay --- so far
{% endif %}
"
ctx = Liquid::Context.new
ctx.set "kenny", { "sick" => false, "dead" => true}
tpl = Liquid::Template.parse txt # tpl can be cached and reused
result = tpl.render ctx
# result = "
# You killed Kenny! You ***!!!
#
# "
Tags can be escaped:
\{% assign myvar = 15 %}
# or
{% raw %}
{% assign myvar = 15 %}
{% endraw %}
will both render {% assign myvar = 15 %}.
Blocks
Cache block (only supports caching using Redis): https://github.com/TechMagister/liquid-cache.cr
Filters
- [x] abs
- [x] append
- [x] camelcase | camelize
- [x] capitalize
- [x] ceil
- [x] compact
- [x] date
- [x] default
- [x] divided_by
- [x] downcase
- [x] escape
- [x] escape_once
- [x] first
- [x] floor
- [x] join
- [x] last
- [x] lstrip
- [x] map
- [x] minus
- [x] modulo
- [x] newline_to_br
- [x] pluralize
- [x] plus
- [x] prepend
- [x] remove
- [x] remove_first
- [x] replace
- [x] replace_first
- [x] reverse
- [x] round
- [x] rstrip
- [x] size
- [x] slice
- [ ] sort
- [ ] sort_natural
- [x] split
- [x] strip
- [x] strip_html
- [x] strip_newlines
- [ ] times
- [ ] truncate
- [ ] truncatewords
- [x] underscore
- [ ] uniq
- [x] upcase | uppercase
Helper Methods
- [x] size (for Array and String)
- [x] present / blank (added)
- [ ] first / last
Development
TODO:
- [x] Basic For loops
- [x] if/elsif/else/endif
- [ ] unless/endunless
- [x] Raw and comment blocks ({% raw %} and {% comment %})
- [x] Add variable assignment ({% assign var = "Hello World" %})
- [x] Add support for multiple operator (no operator precedence support (for now))
- [x] Add support for Array into for loop
- [x] Add support for Hash into for loop (
{% for val in myhash %}, access asval[0]andval[1]) - [ ] Add support for Hash into for loop ({% for key, val in myhash %}) (new)
- [x] Add support for Float
- [x] Add iteration over Arrays
- [x] Improve data interface
- [x] Add Filter support
- [x] Add
captureblock - [x] Add
incrementblock - [x] Add
decrementblock - [x] Add support for Array in expressions
- [x] Add support for Hash in expressions
- [x] Add "secret"
emptyArray ([]) for use in comparisons (equivalent to#blankhelper method) - [x] Add
containsoperator - [ ] Add
cyclekeyword - [ ] Add
starts_withkeyword (new) - [ ] Add
ends_withkeyword (new) - [ ] Add
continuekeyword - [ ] Add
breakkeyword - [ ] Add case/when
- [ ] Add syntax checking
- [ ] Improve expression parsing
- [x] Add optional strict mode on Context (see below)
- [ ] Add Everything that's missing [https://shopify.github.io/liquid/]
Context Strict Mode
NOTE: Will eventually use this to implement a strict_variables rendering flag (planning to implement strict_filters as well).
Enable at initialization:
ctx = Liquid::Context.new(strict: true)
Or on an existing Context:
ctx.strict = true
Raises KeyError on missing keys and IndexError on array out of bounds errors instead of silently emitting nil.
Append ? to emit nil in strict mode (very simplistic, just checks for ? at the end of the identifier)
ctx = Liquid::Context.new(strict: true)
ctx["obj"] = { something: "something" }
{{ missing }} -> KeyError
{{ missing? }} -> nil
{{ obj.missing }} -> KeyError
{{ obj.missing? }} -> nil
{{ missing.missing? }} -> nil
Note on order of operations in complex expressions
Currently, comparison operators are evaluated before and/or. Other than that, evaluations are evaluated from left to right. Parentheses are not supported.
Eventually, this will be fixed to evaluate expressions in a way that mirrors Crystal itself, but for now, it would be best to simply avoid writing complex expressions.
Contributing
- Fork it ( https://github.com/TechMagister/liquid.cr/fork )
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create a new Pull Request
Contributors
- TechMagister Arnaud Fernandés - creator, maintainer of original version
- docelic Davor Ocelic
- anamba Aaron Namba