Not a developer? Go to MovableType.com

Documentation

Templating in MT

his provides a summary of some of the new features and tags available in Movable Type's new templating engine.

Movable Type publishes content using text-based templates. A typical MT template has content that looks like this:

    <MTEntries lastn="5">
    <h1><$MTEntryTitle$></h1>
    <div class="entry-body">
        <$MTEntryBody remove_html="1"$>
    </div>
    </MTEntries>

This template is producing HTML (or XHTML) content, as it is intermingled with HTML-based tags. When MT processes a template it only looks at things that look like <MT...> or <$MT...$>. Everything else is output verbatim, which means that MT templates can produce many different kinds of documents, HTML being one of them.

In MT the above <MTEntries...> tag is known as a 'block' tag, one that wraps around other content. The above <$MTEntryBody$> tag is known as a 'function' tag, one that outputs a value of some kind (the '$' characters are optional here, but they can help to identify this kind of tag when looking at your template). In previous releases, block tags were called 'container' tags, function tags were just called tags. The 'remove\_html' attribute used in the <$MTEntryBody$> tag is one of MT's 'modifiers'-- a special keyword that causes the value of the tag to be processed on some way (in this case, to strip it of any HTML content).

There. That's the fundamental concept to writing MT templates. Now you just need to know what tags are available to use and what they do. There's a reference for that, but this document is going to proceed with describing some of the new MT features.

MT emplating Enhancements

MT tags are now case-insensitive

MT templates are no longer case-sensitive. By this, I mean that you can write a tag like <MTEntries> as <mtentries> or <MtEntries>. This makes MT much more forgiving when it comes to composing templates. You no longer have to remember if you should write <MTSubCategories> or <MTSubcategories> for instance.

MT tags will allow a 'namespace' delimiter

This is a small point, but some will appreciate that you can now write MT templates with a XML-like namespace delimiter, such as <MT:Entries> (or <mt:entries>). For some, this is more aesthetically pleasing.

MT tag attributes can interpolate variables

The best way to describe this is to demonstrate:

    <MTSetVar name="lastn" value="5">
    <MTEntries lastn="$lastn">
       ...
    </MTEntries>

Here, the value of the 'lastn' attribute of the 'Entries' block tag is being supplied by a template variable (coincidentally named 'lastn'). We currently do NOT support complex expressions like this:

    <MTEntries categories="$cat1 OR $cat2">

'Array' of values for attributes

A syntax we borrowed from the Smarty templating language (which we use as the behind-the-scenes engine for our dynamic publishing) is the ability to assign multiple values to an attribute. For instance:

    <MTVar name="my_var" regex_replace="/[^a-z]+/g","_">

Here, a comma is used to delimit (a colon may also be used, which is what Smarty supports) multiple values for the 'regex_replace' modifier. Here, the first value is used as the pattern and the second value is used as the replacement. This expression actually works in MT, since we've added a 'regex_replace' modifier to the core (something the dynamic publishing side has always supported, since it was supplied through Smarty).

MT core Tag Enhancements

Movable Type now uses it's own template language for processing it's application templates. This means a departure from using the HTML::Template Perl module, and it means that MT templates must provide more flexible conditional and 'looping' processing. So we have extended the template language and some of the core tags to allow for more control.

<MTIf>

Movable Type introduces a new conditional 'If' tag that lets you test and compare template variables. Some sample uses:

    <mt:if name="my_var">
        'my_var' is set to something
    </mt:if>

It also supports the 'Else' clause:

    <mt:if name="my_var">
        'my_var' is set to something
    <mt:else>
        'my_var' is not set
    </mt:if>

(Note that with MT, the 'Else' tag may optionally be closed. If it is left unclosed, MT will assume it is closed with the next closing block tag.)

The If tag supports a number of operations...

    <mt:if name="my_var" eq="some value">

This does an 'equal' test, comparing the value of 'my_var' with the content of the 'eq' attribute. Other operational attributes include: 'ne' (not equal), 'gt' (greater than), 'lt' (less than), 'ge' (greater than or equal), 'le' (less than or equal), and 'like' (which supports a regular expression test).

The 'like' operator tests for a regular expression match like this:

    <mt:if name="my_var" like="^[A-Za-z]+$">

<MTUnless>

An Unless tag is provided as a counterpart to the If tag. It inverses the logic of the test.

<MTLoop>

If a MT variable contains an array of content, a MT Loop block tag may be used to process that array of data. As it does, the value of each element of the array is taken and put in context as the insides of the Loop tag are processed. If the array element is a Perl hash, it will place the content of that hash into the variable space of the template so that the <MTVar> tag can output them. If the array element is some simple value, that value is placed into the pseudo-variable '__value__' which may also be accessed by the <MTVar> tag. This is the counterpart to the HTML::Template 'TMPL_LOOP' tag and is primarily used in MT application templates.

    <MTLoop name="my_list">
        <MTVar name="name"> - <MTVar name="value">
    </MTLoop>

Such a loop would expect a template variable 'my_list' that has this content:

    [ { name => 'foo', value => 'bar' },
      { name => 'flip', value => 'flop' } ]

Loops also populate other 'HTML::Template' pseudo-variables, such as '__counter__' (the array element number being processed, starting with '1'), '__odd__' (set when the loop element is odd), '__even__' (set when the loop element is even), '__first__' (set for the first item in the loop), '__last__' (set for the last item in the loop).

<MTVar>, <MTGetVar>, <MTSetVar>, <MTSetVarBlock>, <MTSetVarTemplate>

Template variables can be set/retrieved with this family of tags. 'GetVar' is an alias for 'Var' (which is just shorter to write, but you'd expect 'GetVar' to be available, since we use 'SetVar' for setting variables). 'SetVar' is a function-style tag, for setting simple values. 'SetVarBlock' is a block tag, for setting complex values. 'SetVarTemplate' is for assigning a MT template to a variable. More on this in a minute.

So for simple variable assignment:

    <MTSetVar name="my_var" value="value">

And to output a variable:

    <MTVar name="my_var">

If you want to assign something that uses MT tags, you'll have to use 'SetVarBlock' to wrap the MT tags (since you can't place MT tags inside attributes of another MT tag):

    <MTSetVarBlock name="my_var">
        <MTEntryTitle>
    </MTSetVarBlock>

This assigns the evaluated result of what is inside the block to the 'my_var' variable. So in this case, the title of the MT entry in context is assigned to the 'my_var' variable.

Which brings us to 'SetVarTemplate'. There will be cases where you may want to assign a MT template _expression_ to a variable. For instance:

    <MTSetVarTemplate name="entry_metadata">
        <MTEntryDate> - <MTEntryID>
    </MTSetVarTemplate>

This winds up assigning a mini-template to the 'entry_metadata' variable. The content itself is not evaluated immediately... and because of that, it isn't necessary for a entry context to be available at the time the variable is assigned.

Now, once you actually write:

    <MTVar name="entry_metadata">

The mini-template in 'entry_metadata' is processed and evaluated, producing the content of that template, in the context the 'Var' tag is used in.

<MTInclude>

The MT include tag has been around for a while, but there are a few very important changes to it that should be mentioned.

  • Includes now are always processed for MT tags. In prior releases, if you did an include that drew content from a file (using the 'file') attribute, it would be output verbatim, but now the default behavior is to evaluate the content as a MT template. We may add another attribute to prevent MT tag processing, but no option exists for that at this point.
  • A new 'name' attribute is supported which lets MT templates draw from the MT application template directory. This attribute is for use by MT application templates.
  • MT Include tags will 'pass-through' any unrecognized attribute/value pairs as template variables to the included template. This makes it possible to say...
    <MTInclude module="Header" page_title="My Special Page">

Summary

All of these changes make MT templates much more flexible and powerful, without complicating the basic syntax that many have found to be so approachable and easy to learn.

Back

Leave a Comment

3 Comments

Dave Baker

Dave Baker on October 8, 2007, 12:08 p.m. Reply

Great stuff! But a nit to pick:

Movable Type 4 now uses it’s own template language for processing it’s application templates.

should be =>

Movable Type 4 now uses its own template language for processing its application templates.

jackvinson.myopenid.com

jackvinson.myopenid.com on November 5, 2007, 12:58 p.m. Reply

Where is the list of variables that MT4 uses by default? And the list of options for those variables. For example: the name and options for the page layout variable.

Richard

Richard on November 6, 2009, 8:27 a.m. Reply

I learned today in the forum:


<mt:SubCategories category="<$mt:Var name="category"">
you can't do that, try this instead
<mt:SubCategories category="$category">

Where does it say this in the documentation?