Over the last few days I built a small custom EEx engine that tackles a frustration I’ve had for a while trying to get proper indentation with EEx templates. I thought some of you might find it useful too.
I’ve been doing a lot of Codegen lately and when writing EEx templates with loops and conditionals, I often end up facing a choice between:
- Messy template code to get properly formatted output
- Clean template code but with weird (or even invalid) spacing in the output
This library attempts to fix this by extending EEx.SmartEngine
with a special <%|
tag that injects some context-aware string manipulation into the AST to ensure that the output is indented in a way that makes sense (at least to me ).
It also provides a ~TT
sigil for convenience and supports including (and re-indenting) “partial” templates.
Quick Example
defmodule Template.DockerCompose do
import SmartIndentationEngine.Template
def render(assigns) do
~TT"""
services:
<%| for {name, config} <- @services do %>
<%= name %>:
<%= include :service, config: config %>
<% end %>
"""
end
def service(assigns) do
~TT"""
image: <%= @config.image %>
ports:
<%| for port <- @config.ports do %>
- <%= port %>
<% end %>
# ...
"""
end
end
Template.DockerCompose.render(
services: %{
livebook: %{
image: "ghcr.io/livebook-dev/livebook:0.15.5",
ports: [8080, 8081]
}
}
)
This will produce the following output:
services:
livebook:
image: ghcr.io/livebook-dev/livebook:0.15.5
ports:
- 8080
- 8081
# ...
Give It a Try!
I just published it on Hex: smart_indentation_engine.
If you’re working with EEx templates, I’d love for you to try it out. Let me know what you think, if you encounter any issues, edge cases, or if you have ideas for improvements!