1. it's time for templates

    Our first thoughts when designing Zena were “we don’t need no templates, let’s just use plain old erb files.” But then comes the time when you want to share templates… And you do not want to read very carefully all the ruby in the template in case:

    • the author made something silly with the ruby code displaying things that should be kept hidden
    • the template is used to as a trojan horse to execute shell scripts

    As you can see, using someone else’s template could be quite harmful. And it is nice to exchange layouts, without risks. So what is the latex for templates ?

    no plain ruby in the template

    context based tags

    Tags should render differently depending on the current context, for example : #TITLE should render differently from #EACH_CHILD{ <li>#TITLE</li> }. Moreover, it should be easy to change the current context when designing new tags. For example, replacing the current ‘node’ context when rendering the inner part of a tag could look like :

    def documents
      ...
      out << expand_with(:node => 'document')
      ...
    end
    

    xhtml tags

    We want our web designers to be able to work with their very expensive visual applications to create stunning templates. The simplest solution is to use xhtml for our custom tags, putting all of them into an xml namespace. Our templating system will be called Zafu (zazen is for writing articles, zafu for templates and zena for the garden). We will therefore use z for our namespace. For example, to show a list of child nodes :

    <z:children>
      <h3>Children</h3>
      <ul>
        <z:each>
          <li><z:show attr=':v_title'/></li>
        </z:each>
      </ul>
    </z:children>

    Notice how we encapsulate the ‘ul’ tags and the title into children. This means that if we do not have any children, we do not render an empty ‘ul’ tag. Of course, you can choose to put the title outside if you like.

    compiled templates

    We want our application to run as fast as possible so the compilation of the template should only be done once and create a standard ‘erb’ file :

    <% if list = @node.children -%>
      <h3>Children</h3>
      <ul>
        <% list.each do |node| -%>
          <li><%= node.send(:version)[:title] %></li>
        <% end -%>
      </ul>
    <% end -%>

    extending

    Adding new tags should be very easy. Testing them too ! For example, this could be an easy way to define the ‘documents’ and ‘each’ tags :

    def documents(params)
      out << "<% if list = #{node}.children -%>"
      out << expand_with(:list => 'list')
      out << "<% end -%>"
    end
    
    def each(params)
      out << "<%#{list}.each do |node| %>"
      out << expand_with(:node=>'node')
      out << "<% end -%>"
    end
    

    This would be nice, but we have a problem with name clashes. A variable used for a scope could be used as a local variable above, or we could have nested ‘each’ calls, using the same variable and this is bad. A way to fix this would be to use unique identifiers for the variables :

    def each
      out << "<% #{list}.each do |#{var_inc}| -%>"
      out << expand_with(:node=>var)
      ...
    end
    

    With this improvement, the template above would render as, variables being varx where x is increased in each new context :

    <% if var1 = @node.children -%>
      <h3>Children</h3>
      <ul>
        <% var1.each do |var2| -%>
          <li><%= var2.send(:version)[:title] %></li>
        <% end -%>
      </ul>
    <% end -%>
    

    Another way around this issue would involve maintaining contexts during the template’s rendering (after compilation, when producing html). This would create some overhead on each rendering.

    Zafustore

    photo © zafustore

    zafu

    The templating system in Zena is called ‘zafu’, like the round cushion used for zazen.

    You will find more information on the exact syntax once it is up and running. I the meantime, you can look at the following file for some experiments we made with the markup :

    rb document

    2 Kb

    markup tests

    Some experiments to define the markup for zafu templates.

    Gaspard Bucher