Trimming on EEx templates

Is there any way to make a EEx template trim all whitespace?
I’ve seen that at some point, in 1.4.16, this ability that was there for all templates was removed and only kept for HTML templates.
The issue now is that I can’t find a way to keep the old behavior for a non HTML template (markdown in my case), and my markdown generated files have a lot of extra \ns, and markdown is a bit sensitive when placing extra \n in some places.

I couldn’t find any simple workaround that doesn’t involve changing a lot the way I generate the output with templates.
I would like if there was a way to indicate that certain templates want trimming enabled but that seems like a feature request.

Any help or comments are appreciated, thanks!

As you said: " my markdown generated files have a lot of extra \n s, and markdown is a bit sensitive when placing extra \n in some places."

It seems that the problem is on your files, if markdown is ‘\n’ sensitive, make sure markdown is correct, first.

Solve a problem at its root, don’t patch on the leaves.

That’s my question, how to make markdown correct.
In particular this is what’s happening:

<%= if (false), do: "header" %>
<%= if (false), do: "body" %>
<%= if (true), do: "footer" %>

This outputs: \n\nfooter, but before 1.4.16 the \ns were trimmed on empty lines and the output was just footer.
How can I not output those extra \n on empty lines?

1 Like

Maybe like this?

<%= 
if (false), do: "header" 
%><%= 
if (false), do: "body" 
%><%= 
if (true), do: "footer" 
%>

BTW I like to use helpers to avoid putting logic in the template.

3 Likes

I believe you need to pass the trim: true option down to EEx, see the difference in IEx:

iex(3)> EEx.eval_string("<%= 1 %>\n\n<%= 2 %>", [])
"1\n\n2"
iex(4)> EEx.eval_string("<%= 1 %>\n\n<%= 2 %>", [], trim: true)
"1\n2"

Now, it doesn’t look like you can configure Phoenix.Template.EExEngine to set that option, so what I’d do is create your own MyApp.EExEngine that does, and configure Phoenix to use that instead.

4 Likes

Documentation of :trim seems to be wrong: It says that “at least one newline is retained”, but this doesn’t seem to be so:

iex(2)> EEx.eval_string("<%= 1 %>\n<%= 2 %>", [], trim: true)
"12"

ps. I don’t understand the meaning of that phrase at all - it seems to be saying that some newlines are retained while some are not, without specifying when newlines are retained and when not.

Good catch, the way it works today, perhaps it should have said “at most one newline is retained”. Please send a PR to clarify :slight_smile:

1 Like

That is still unclear - when is one newline retained and when not?

Oh, I just checked your example and it returns different value for me:

iex> EEx.eval_string("<%= 1 %>\n<%= 2 %>", [], trim: true)
"1\n2"

so perhaps there was a bug in the version you were running that has since been fixed. I’m on Elixir master.

1 Like

This could be a solution if I was using EEx directly, but I’m leveraging on Phoenix templates so all my non html templates are precompiled already with trim: false at the moment of rendering. And even if I could configure my template engine, the trimming option is one level above the engine and it’s set to false for all non html. I could solve it rewording my template a bit using the format @kokolegorille suggested. Thanks!

Maybe like this?
<%=
if (false), do: “header”
%><%=
if (false), do: “body”
%><%=
if (true), do: “footer”
%>

This worked! I had to do some bigger changes because my real case was more complicated than this example but it did the trick, thanks!
This is one case where more (lines) is less (output) :man_shrugging:

1 Like

It could have been 3 lines too, but the important thing is to link %><%= :slight_smile:

<%= if (false), do: "header" 
%><%= if (false), do: "body" 
%><%= if (true), do: "footer" %>
1 Like