Phoenix custom template engine

I have a directory with some svg files which I need to inline in certain places, and I would like to compile these to EEx templates to avoid unnecessary file i/o. I tried creating a module using the template_engines option for Phoenix.Template, however it never finds any of the svg templates. Doing exactly the same thing but just setting .eex as the extension works.

A minimal repo is here:

And the code to read my svg directory:

defmodule SvgTemplate do
  use Phoenix.Template,
    root: Path.join(__DIR__, "fixtures/svg_templates"),
    template_engines: %{
      svg: Phoenix.Template.EExEngine

  def render(template, assigns) do
    render_template(template, assigns)

test "renders from svg templates" do

  assert SvgTemplate.render("hello", %{}) == "hello from svg"

Any ideas what I am doing wrong?

After a bit of advanced debugging (IO.inspect all over Phoenix.Template), I think I know what is going on here and will raise an issue with the Phoenix team. The docs say the following:

If you want to support a given engine only on a certain template,
you can pass it as an option on use Phoenix.Template:
use Phoenix.Template, template_engines: %{
foo: Phoenix.Template.FooEngine

However, within the Phoenix.Template, it is storing the template engines in Application, so will never take into account engines defined at the module level.

Putting svg as a global config value works as expected.

Good catch. The template engines is not really an option, it was a bug in the documentation. Removed here.


Thanks for confirming José.

It’s fine for my use case, however I was thinking if it would be possible to define the engines at the module attribute level instead. I had a quick go at implementing it, but I’ve not done much with macros before.

Had a little go and this seems to work:

Are there any downsides to this approach, or even the feature in general?

1 Like

I like this! That would effectively make the option work. I dropped some comments. If you can send a PR it would be great, please copy me. :slight_smile: