Standard template processors like erb, mustache, and eex return formatted output when they process a template. Normally this is just fine as most applications use common formats like HTML or JSON for their outputs.
Meta-templates, templates which produce other templates, are useful when an application needs to support multiple formats and/or format(s) which are unevenly implemented (Markdown I'm looking at you). This is the problem domain Greenbar was designed to address.
We created Greenbar to improve Cog's rendering abilities. Generating attractive and uniform content across multiple chat providers is quite challenging and also vital to building a good user experience.
Greenbar templates use a combination of Markdown and custom Greenbar-specific tags to describe a template. Templates are compiled to executable Elixir code and then cached for easy reuse. Executing a template generates a list of directives which describe how to build the final output.
Here's a simple template that says hello:
Hello ~$user~!
Have a __GREAT__ DAY!
After downloading and building Greenbar you can build the template like so:
iex(1)> template = """
...(1)> Hello ~$user~!
...(1)>
...(1)> Have a __GREAT__ DAY!
...(1)> """
"Hello ~$user~!\n\nHave a __GREAT__ DAY!\n"
iex(2)> {:ok, engine} = Greenbar.Engine.new
{:ok,
%Greenbar.Engine{tags: %{"br" => Greenbar.Tags.Break,
"count" => Greenbar.Tags.Count, "each" => Greenbar.Tags.Each,
"title" => Greenbar.Tags.Title}, templates: %{}}}
iex(3)> engine = Greenbar.Engine.compile!(engine, "hello", template)
%Greenbar.Engine{tags: %{"br" => Greenbar.Tags.Break,
"count" => Greenbar.Tags.Count, "each" => Greenbar.Tags.Each,
"title" => Greenbar.Tags.Title},
templates: %{"hello" => %Greenbar.Template{debug_source: nil,
hash: "c8c61d458c8070f04d76cb3e07dffcbd7dd0965080dba7f406b7b5c8a123dc5f",
name: "hello", source: "Hello ~$user~!\n\nHave a __GREAT__ DAY!\n",
template_fn: #Function<12.54118792/2 in :erl_eval.expr/5>,
timestamp: 1472755224456112954}}}
Let's execute the compiled template:
iex(4)> Greenbar.Engine.eval!(engine, "hello", %{"user" => "Zaphod"})
[%{name: :text, text: "Hello Zaphod!"}, %{name: :newline},
%{name: :text, text: "Have a "}, %{name: :bold, text: "GREAT"},
%{name: :text, text: " DAY!"}]
Standard Markdown notation for emphasis, strong, code line, and code blocks are implemented. Tables and (un)ordered lists are coming soon.
Template variables and tags are referenced using tildes. See test/support/templates.ex for more examples.
Greenbar tags are designed to be extensible. See lib/greenbar/tag.ex for details.