Current section

Files

Jump to
solid lib solid.ex
Raw

lib/solid.ex

defmodule Solid do
@moduledoc """
Main module to interact with Solid
iex> Solid.parse("{{ variable }}") |> Solid.render(%{ "variable" => "value" }) |> to_string
"value"
"""
alias Solid.{Object, Tag}
defmodule Context do
defstruct vars: %{}
@type t :: %Context{vars: Map.t}
end
@doc """
It generates the compiled template
"""
@spec parse(String.t) :: any
def parse(text) do
:solid_parser.parse(text)
end
@doc """
It renders the compiled template using a `hash` with vars
"""
@spec render(any, Map.t) :: iolist
def render(text, hash \\ %{}) do
context =%Context{vars: hash}
do_render(text, context) |> elem(0)
end
defp do_render(text, context) do
case text do
[{:string, string}, []] ->
{[string], context}
[{:string, string}, [{:open_object, _}, {:text, tail}]] ->
{text, context} = do_render(tail, context)
{[string, "{{", text], context}
[{:string, string}, [{:open_tag, _}, {:text, tail}]] ->
{text, context} = do_render(tail, context)
{[string, "{%", text], context}
[{:string, string}, [{:tag, tag}, {:text, tail}]] ->
{tag_text, context} = render_tag(tag, context)
{tail_text, context} = do_render(tail, context)
{[string, tag_text, tail_text], context}
[{:string, string}, [{:object, object}, {:text, tail}]] ->
object_text = Object.render(object, context)
{tail_text, context} = do_render(tail, context)
{[string, object_text, tail_text], context}
end
end
defp render_tag(tag, context) do
{result, context} = Tag.eval(tag, context)
if result do
do_render(result, context)
else
{"", context}
end
end
end