A couple of comments on Simple Attribute-Based Template Exporting have asked for an example. I'll show off more of this code in my YAPC::NA 2012 and Open Source Bridge 2012 talk about how to write the wrong code (along with a handful of other techniques).

(I assume some knowledge of Template Toolkit (besides far too many books about finance, accounting, and investing, the Template Toolkit book is always within reach these days); I've set up a wrapper template which provides the standard look and feel of my application and I include/process other templates liberally. If you understand that much, you'll be able to follow along.)

One of the interesting templates in the system displays a list of chapters of a book in progress. A cron job rebuilds a static page from this template once a day. The template looks something much like:

[% USE Bootstrap -%] [%- canonical_url = 'http://sitename.example.com/book/' _ link -%] [%- add_og_properties({ 'fb:admins' => '436500086365356', 'og:title' => title _ ' | sitename.example.com', 'og:type' => 'article', 'og:image' => 'http://static.sitename.example.com/images/logo.png', 'og:url' => canonical_url, 'og:description' => text.chunk(300).0, 'og:site_name' => 'Sitename: site tag line', }) -%] [%- add_meta( 'pagetitle' => title _ ' | sitename.example.com', 'feed_url' => 'http://static.sitename.example.com/book/atom.xml' 'canonical_url' => canonical_url ) -%] [% article_text = BLOCK -%] <article> <h2>[% title | html %]</h2> <p>Published: <time datetime="[% date %]">[% nice_date %]</time></p> [% text %] </article> <ul class="pager"> [%- IF prev -%] <li><a href="[% prev.link %].html">← [% prev.title | html %]</a></li> [%- END -%] <li><a href="/onehourinvestor">index</a></li> [%- IF next -%] <li><a href="[% next.link %].html">[% next.title | html %] →</a></li> [%- END -%] </ul> [% INCLUDE 'components/social_links.tt', title => title %] [%- END -%] [%- row( maincontent( article_text ), sidebar( sideblock( process( 'components/cached/book_latest_chapters.tt' ) ), sideblock( process( 'components/cached/book_drafts.tt' ) ) ) ) -%]

The emboldened lines are most important; they put all of the content produced or assembled by this template in the HTML structure the site needs. That is to say, everything on the site needs to fit into something I call a row . A row can contain multiple elements, such as maincontent and a sidebar , or fullcontent by itself with no sidebar . A sidebar can contain multiple sideblock s.

(You can ignore the other functions; they put metadata in the right places to pass to wrapper templates.)

Within my template plugin (called Bootstrap ), each of these elements is a simple Perl function which takes one or more arguments and interpolates it into some HTML:

sub row :Export { return <<END_HTML; <div class="row"> @_ </div> END_HTML } sub sidebar :Export { return <<END_HTML; <div class="span4"> @_ </div> END_HTML }

(I initially tried to write these functions as templates within Template Toolkit itself, but there comes a point at which you want a real language. That point came very early for me.)

I lose no love over the varname = BLOCK pattern necessary to populate variables to pass to these plugin functions, but it works for now. In some of my templates—usually those with lots of text I might end up changing later—I extract that text into a separate template under components/content/ to make it easy to edit. (This idea came up during a client project where the client wanted to edit the legal clickthrough arrangement after users create accounts. I didn't want lawyers or anyone to have the ability to mess up the templating language, so I said "Edit this single file as plain HTML and you'll be fine." It worked great.)

While my programmer brain says "This is ugly, and you're a horrible person for committing this hack upon the world—you're calling Perl from your template system to generate HTML you're stuffing into a template and that puts your presentation elements in Perl code, you awful human being!", it keeps the presentation code in a single place where I can update it infrequently (being that I don't change the layout of the site dramatically) without having to change the divs and classes of multiple templates.

I'm not arguing that this technique as expressed here is right. It's probably not optimal; there may be easier approaches to achieve the same effects.

I am saying that this currently works very well for me. I'm not typing the same HTML over and over and over again, and I can tweak it much more easily than I did before when I was refining the look and feel. In fact, I've even forgotten the exact details of the layout, from the HTML/CSS point of view, and now think only in terms of rows, maincontent, and sidebars.

Working abstractions are very nice.