Smart Indentation Engine
View SourceA custom EEx engine that does its best to handle indentation in an intuitive way, so that you can enjoy both clean readable templates and well-formatted output.
Features
The engine ships with the following features:
- Smart Indentation - Preserves proper indentation in template output.
- Template Inclusion - Supports including (and re-indenting) partial templates.
- Assigns Binding - Access values from the
assignsbinding using the@syntax (e.g.,@foo). - Flexible Spacing - Works with both spaces and tabs.
Overview
This engine extends the default EEx.SmartEngine by
implementing the <%| tag to handles indentation in template blocks.
When you use it with control flow structures like if, for, case, etc., the
the engine automatically aligns the output to match the indentation of the
control statement.
Templates included with <%= include :template %> are also re-indented to match
the surrounding context.
Usage
Installation
def deps do
[
{:smart_indentation_engine, "~> 0.1"}
]
endQuick Example
Using the <%| tag for control flow:
Mix.install([
{:smart_indentation_engine, "~> 0.1"}
])
"""
<ul>
<%| for name <- ["world", "darkness my old friend"] do %>
<li>hello <%= name %></li>
<% end %>
</ul>
"""
|> EEx.eval_string([], engine: SmartIndentationEngine)Will produce the following output:
<ul>
<li>hello world</li>
<li>hello darkness my old friend</li>
</ul>
The ~TT Sigil
By importing the SmartIndentationEngine.Template module you'll have access to
the ~TT sigil that automatically uses the engine:
defmodule Template.BasicList do
import SmartIndentationEngine.Template
def render(_assigns \\ []) do
~TT"""
<ul>
<%| for name <- ["world", "darkness my old friend"] do %>
<li>hello <%= name %></li>
<% end %>
</ul>
"""
end
end
Template.BasicList.render()
Using @ for Assigns
defmodule Template.AssignedList do
import SmartIndentationEngine.Template
def render(assigns \\ []) do
~TT"""
<ul>
<%| for name <- @names do %>
<li>hello <%= name %></li>
<% end %>
</ul>
"""
end
end
Template.AssignedList.render(names: ["world", "darkness my old friend"])Template Inclusion
You can also include other templates using the include function. Included
templates will be reindented to match the surrounding context.
defmodule Template.IncludedList do
import SmartIndentationEngine.Template
def render(assigns \\ []) do
~TT"""
<div>
<h1>Nice to meet you, hope you guess my name!</h1>
<%= include :list, names: @names %>
</div>
"""
end
def list(assigns) do
~TT"""
<ul>
<%| for name <- @names do %>
<li>hello <%= name %></li>
<% end %>
</ul>
"""
end
end
Template.IncludedList.render(names: ["world", "darkness my old friend"])This produces:
<div>
<h1>Nice to meet you, hope you guess my name!</h1>
<ul>
<li>hello world</li>
<li>hello darkness my old friend</li>
</ul>
</div>How It Works
When you use the <%| marker with control structures, the engine:
- Captures the indentation context of the control statement
- Remove the empty lines introduced by the control statement
- Processes the content inside the block (handles nested structures and re-indents included templates)
- Dedents the block output to match captured indentation
License
The package is available as open source under the terms of the MIT License.