Indenting TT and HTML

When using Template::Toolkit to generate HTML, I have two goals:

  1. Have legible source code (TT+HTML)
  2. Have legible output code (HTML).

Let's start with the latter. That means the HTML output should look as if pretty printed1. Assuming an indentation size of 4 spaces, it would look like this:

<ul>
    <li>foo</li>
    <li>bar</li>
</ul>

What about the source code to generate that, say if the first item of the list needs to be different according to some condition? Here is a proposed recommendation:

<ul>
  [% IF condition %]
    <li>foo</li>
  [% ELSE %]
    <li>bar</li>
  [% END %]
</ul>

Imagine the TT is stripped from the code above. Then the HTML will be indented by 4 spaces, just like in the output. Perfect so far. But what about the TT code?

I propose 2 spaces on intervening TT code, because when TT intervenes between pieces of HTML, that's another level of indentation, on a different layer of programming language (TT).

Counter-proposals

If indenting were at 4 spaces all the way,

<ul>
    [% IF condition %]
        <li>foo</li>
    [% ELSE %]
        <li>bar</li>
    [% END %]
</ul>

then the output HTML will be indented at 8 spaces.

If TT were not indented,

<ul>
    [% IF condition %]
    <li>foo</li>
    [% ELSE %]
    <li>bar</li>
    [% END %]
</ul>

then the code doesn't reflect the fact that what's in the IF or ELSE blocks will be executed only if that branch is taken. All indentation styles indent blocks within IF branches, and for good reason which is why the next choice may be better, but is it better than the first choice?

<ul>
[% IF condition %]
    <li>foo</li>
[% ELSE %]
    <li>bar</li>
[% END %]
</ul>

HTML without its own nesting

A special case is HTML that does not have nesting, like a series of paragraphs aligned at column 1 in a Template::Toolkit file or block that's going to be included by another file. Assume the first paragraph has to be conditionally displayed:

<p>Intro</p>
[% IF condition %]
<p>body 1</p>
[% ELSE %]
<p>body 2</p>
[% END %]
<p>Conclusion</p>

The above doesn't reflect that "body 1" will only be displayed if condition is true, while "Intro" will always be displayed. Let's try to work that in:

<p>Intro</p>
[% IF condition %]
  <p>body 1</p>
[% ELSE %]
  <p>body 2</p>
[% END %]
<p>Conclusion</p>

The problem now is that in the HTML output, we'll have misleading indenting for "body 1" and "body 2". What we should do here is somehow "outdent" the [% IF ... %]. The only solution to that is to always indent the HTML:

  <p>Intro</p>
[% IF condition %]
  <p>body 1</p>
[% ELSE %]
  <p>body 2</p>
[% END %]
  <p>Conclusion</p>

Footnotes


  1. If the default indent value of '2' is not changed, there will be no indenting. Set it to 4 to see an indented result. ↩

Thanks!

Buy me a coffee to sponsor more cool posts like this!

My tags:
 
Popular tags:
  Perl Template_Toolkit HTML indent style