Render eex templates in-place without trimming whitespace?

Hey all, I’ve got the following EEX template for my layout (clearly just the base template lightly modified), the chief difference being that I’ve moved my favicon, Google Analytics and Google Fonts tags into partials to clean things up a bit:

<!-- app.html.eex -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=0.9">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>FunctionHaus</title>
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
    <%= render LayoutView, "_fonts.html" %>
    <%= render LayoutView, "_favicons.html" %>
    <%= render LayoutView, "_google_analytics.html" %>
  </head>
  <body>
    <!-- etc... -->
  </body>
</html>

The issue that I’m having is that when those sub-templates (can I say “partials”?) are rendered, all of the whitespace at the beginning of the rendered lines is trimmed, and the resulting HTML isn’t whitespaced properly:

<!-- RENDERED TEMPLATE OUTPUT -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=0.9">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>FunctionHaus</title>
    <link rel="stylesheet" href="/css/app.css">
<link href="https://fonts.googleapis.com/css?family=Lato:900i|Lato:400|Lato:700|Patua+One" rel="stylesheet">
    <link rel="shortcut icon" type="image/png" href="/images/favicon.png"/>
<!-- <link rel="shortcut icon" type="image/png" href="http://mysite.com/images/favicon.png"/> -->

<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-12345678910-1', 'auto');
  ga('send', 'pageview');

</script>
  </head>
  <body>
    <!-- etc... -->
  </body>
</html>

Is there a way to enforce whitespace in the template render from the point at which the template is rendered, rather than having to add the whitespace to the sub-template itself?

Thanks,
Mike

You can run it through an html formatter, but I don’t see the point, whitespace is inconsequential after newlines in regards to DOM parsing.

That’s an extra step that I’d prefer not to take. I suppose it’s not enormously important, and obviously there are no functional implications, but I prefer clean HTML markup to arbitrarily formatted markup. Seems like in-place formatting should the default behavior for render, the workarounds are all pretty messy and there’s no coherent reason not to presume that the user wants properly-whitespaced HTML.

How would it format it? eex is a text templating language, it is not specific to HTML in any way or form? I use it to generate MIME mail messages and more as well and I certainly would not want it screwing with whitespace in it or the message would become invalid.

I haven’t looked over the EEx.Engine source, but couldn’t it just not
truncate the leading whitespace on a line that only contains an evaluation?

Hmm? Elaborate?

I’ll look into the module implementation and get back to you later with more specifics. Setting up CircleCI for an app at the moment. Thanks for your attention here, it’s appreciated.

No problem, I am quite curious how such a thing would be solved in a manner that would not break other text formats. :slight_smile:

1 Like

Hi, I just did this and it seems to work (whitespace gets preserved):

  <%= for partial <- ["_fonts.html", "_favicons.html", "_google_analytics.html"] do %>
    <%= render LayoutView, partial %><% end %>

edit: err, kind of. the stuff in the script block doesn’t work since it’s multiline :\

1 Like