• Stars
    star
    188
  • Rank 198,113 (Top 5 %)
  • Language
    Elixir
  • License
    MIT License
  • Created over 7 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Liquid template engine in Elixir

Solid

Build Status Module Version Hex Docs Total Download License Last Updated

Solid is an implementation in Elixir of the template language Liquid. It uses nimble_parsec to generate the parser.

Basic Usage

iex> template = "My name is {{ user.name }}"
iex> {:ok, template} = Solid.parse(template)
iex> Solid.render!(template, %{ "user" => %{ "name" => "José" } }) |> to_string
"My name is José"

Installation

The package can be installed with:

def deps do
  [{:solid, "~> 0.14"}]
end

Custom tags

To implement a new tag you need to create a new module that implements the Tag behaviour:

defmodule MyCustomTag do
  import NimbleParsec
  @behaviour Solid.Tag

  @impl true
  def spec(_parser) do
    space = Solid.Parser.Literal.whitespace(min: 0)

    ignore(string("{%"))
    |> ignore(space)
    |> ignore(string("my_tag"))
    |> ignore(space)
    |> ignore(string("%}"))
  end

  @impl true
  def render(tag, _context, _options) do
    [text: "my first tag"]
  end
end
  • spec defines how to parse your tag;
  • render defines how to render your tag.

Now we need to add the tag to the parser

defmodule MyParser do
  use Solid.Parser.Base, custom_tags: [MyCustomTag]
end

And finally pass the custom parser as an option:

"{% my_tag %}"
|> Solid.parse!(parser: MyParser)
|> Solid.render()

Custom filters

While calling Solid.render one can pass a module with custom filters:

defmodule MyCustomFilters do
  def add_one(x), do: x + 1
end

"{{ number | add_one }}"
|> Solid.parse!()
|> Solid.render(%{ "number" => 41}, custom_filters: MyCustomFilters)
|> IO.puts()
# 42

Extra options can be passed as last argument to custom filters if an extra argument is accepted:

defmodule MyCustomFilters do
  def asset_url(path, opts) do
    opts[:host] <> path
  end
end

opts = [custom_filters: MyCustomFilters, host: "http://example.com"]

"{{ file_path | asset_url }}"
|> Solid.parse!()
|> Solid.render(%{ "file_path" => "/styles/app.css"}, opts)
|> IO.puts()
# http://example.com/styles/app.css

Strict rendering

Solid.render/3 doesn't raise or return errors unless strict_variables: true or strict_filters: true are passed as options.

If there are any missing variables/filters Solid.render/3 returns {:error, errors, result} where errors is the list of collected errors and result is the rendered template.

Solid.render!/3 raises if strict_variables: true is passed and there are missing variables. Solid.render!/3 raises if strict_filters: true is passed and there are missing filters.

Contributing

When adding new functionality or fixing bugs consider adding a new test case here inside test/cases. These cases are tested against the Ruby gem so we can try to stay as close as possible to the original implementation.

TODO

  • Integration tests using Liquid gem to build fixtures; #3
  • All the standard filters #8
  • Support to custom filters #11
  • Tags (if, case, unless, etc)
    • for
      • else
      • break
      • continue
      • limit
      • offset
      • Range (3..5)
      • reversed
      • forloop object
    • raw #18
    • cycle #17
    • capture #19
    • increment #16
    • decrement #16
  • Boolean operators #2
  • Whitespace control #10

Copyright and License

Copyright (c) 2016-2022 Eduardo Gurgel Pinho

This work is free. You can redistribute it and/or modify it under the terms of the MIT License. See the LICENSE.md file for more details.

More Repositories

1

httpoison

Yet Another HTTP client for Elixir powered by hackney
Elixir
2,199
star
2

poxa

Pusher server implementation compatible with Pusher client libraries.
Elixir
1,023
star
3

verk

A job processing system that just verks! 🧛‍
Elixir
719
star
4

tentacat

Simple Elixir wrapper for the GitHub API
Elixir
436
star
5

mimic

A mocking library for Elixir
Elixir
302
star
6

CMNavBarNotificationView

[unmaintained] An in-app notification view above the navigation bar "totally" based on MPNotificationView
Objective-C
124
star
7

httparrot

HTTP Request & Response Server. An incomplete clone of http://httpbin.org
Elixir
85
star
8

verk_web

A dashboard for the job processing system that just verks! 🧛‍
JavaScript
81
star
9

bertex

Elixir BERT encoder/decoder
Elixir
30
star
10

poxa-erlang

Open Pusher server implementation compatible with Pusher libraries.
Erlang
26
star
11

pusher

Elixir library to access the Pusher REST API.
Elixir
25
star
12

signaturex

Simple key/secret based authentication for APIs
Elixir
23
star
13

riex

[OLD] Riak & Elixir in a pool
Elixir
23
star
14

tldr_elixir_client

Elixir command line client for tldr
Elixir
15
star
15

wth

WTH is a command line tool much like old WTF that searchs on Urban Dictionary for a term definition.
Elixir
15
star
16

httpehaviour

Yet yet another HTTP client. This time using Behaviour
Elixir
14
star
17

watcher

GenEvent Watcher
Elixir
13
star
18

bertrpcex

A pool of BERT-RPC clients built on top of poolboy
Elixir
12
star
19

CMSignals

Qt Signals and Slots clone to Objective-C.
Objective-C
12
star
20

pusher_client

A websocket client to work with Pusher
Elixir
10
star
21

verk-stats

Verk Stats 🧛‍📊
Elixir
4
star
22

bertrpc

A pool of BERT-RPC clients build on top of poolboy.
Erlang
3
star
23

defpool

Elixir macro to use pooler on a clean way
Elixir
2
star
24

compiz-plugins-ideas

Some ideas for new compiz plugins
C
1
star