|
|
10.10.2004 |
|
|||||||||
| Ant Web Publishing Tutorial, Part 2 | |||||||||||
I'm quite interested in the concept of software components and how those ideas can be applied to Java code. Thoughts or ideas I have on this subject get dropped here for the benefit of humanity and my own hubris.
|
In Part 1 of this tutorial on web publishing with my Ant system, I gave a basic overview that would allow you to build fairly rich static web pages from templates. In this episode, I’m going to make things a little more interesting. The template system has a <img src="/images/${filename}.jpg"/>
But when I was building my work website, I didn’t have a special image for each file, but I had some of them. If I didn’t have an image for a particular file, then I wanted to have an image chosen by which directory they were stored in. That is, all of the “articles” would have the same image, all of the “news updates” would have another image, etc. For example, the data file,
In other words, I need the ability to add more data available to my templates in a dynamic (programmatic) way. Similar to my idea of being able to add formatting engines as plugins to my architecture, I did the same thing with adding auxiliary data. The idea is I would create a “plugin” that would calculated data for a template based on some conditions. For my specific need, I created a “filepairing” plugin that I shoved into my Ant <webtemplate …>
<auxdata name="image" engine="FilePairing">
<variable name="dir" value="htmldata/images"/>
</auxdata>
</webtemplate>
The The “engine” attribute specifies the plugin. In this case, it is called “FilePairing” and it gives the template a But I also need to specify this directory. Attribute values that are given to the plugin directly are specified using the Next step is to add a reference to it in my FreeMarker template: <#if $image?exists>
<p align="right">
<img src="/images/${image}" alt="" class="photo"/>
</p>
</#if>
This plugin serves a very specific need that I had on a couple of web sites, but that is the beauty of starting with an open architecture that allows plugins, and then building your own extensions to allow such plugins. It is now time to demonstrate something truly diabolical… I hate having to add a new file to a directory and then needing to go around and update the navigational bars. I believe those should be calculated. Allow me to introduce you to the When the system is apply a content file to a template, this plugin gives the template some information about all of that file’s siblings in the directory that holds the content file. The code to add to your build file is: <webtemplate …>
<auxdata name="siblings" engine="LocalNavBar" />
</webtemplate>
Yeah, it looks pretty harmless. In my template, I now need to access this data. The data comes to the template as a <ul class="menu">
<#list siblings as sib>
<li>
<a href="${sib.file}">${sib.title}</a>
</li>
</#list>
</ul>
If you were using Velocity, the code would look like: <ul class="menu">
#foreach( $sib in $siblings )
<li>
<a href="${sib.file}">${sib.title}</a>
</li>
#end
</ul>
But what if you didn’t like the order that it gave it to you? Well, FreeMarker allows you to sort a list, so if we wanted to sort by the file modification time, we could change things around to be: <#list siblings?sort_by("filedate") as sib>
<li>
<a href="${sib.file}">${sib.title}</a>
</li>
</#list>
If you had a special order that you wanted to maintain, then add a metadata line to your files. For instance, you could have your text files contain a “date” line: date=2004-10-04 Then you could You’re probably wondering what other file attributes are available. They are pretty much the same as what a template knows about the content file:
Yeah, that <auxdata name="siblings" engine="LocalNavBar">
<variable name="excerptSize" value="20"/>
</auxdata>
On a similar note, this plugin takes another optional variable that affects how it works, if you change your build file to contain: <webtemplate …>
<auxdata name="siblings" engine="LocalNavBar">
<variable name="index" value="true"/>
</auxdata>
</webtemplate>
By default, it ignores files whose name is “index”. The idea here is that the index file gives a table of contents of the other files and often appears like a parent, and not a sibling to the other files. But the “index” variable allows you to include those sorts of files. Let’s put it all together for a big conclusion. We begin with the Ant’s build file section: <webtemplate src="${dir.htm}" dest="${dir.html}"
template="default.ftl"
engine="FreeMarker" includes="**/*.htm" ext=".htm2"
propertyFile="${stg.main}/default.properties">
<auxdata name="siblings" engine="LocalNavBar">
<variable name="excerptSize" value="20"/>
<variable name="index" value="true"/>
</auxdata>
</webtemplate>
And we’ll make a navigational bar where the siblings are listed in order of size, because the longer the document, the more important it is. We will also display more information about each sibling, including the date it was last modified in a “long” format, i.e. April 8, 2003: <ul class="menu">
<#list siblings?sort_by("filesize") as sib>
<li>
<a href="${sib.file}">${sib.title}</a> …
${sib.excerpt} (${sib.filedate?string.long})
</li>
</#list>
</ul>
Thought originally posted on Sunday, 10 October 2004
© 2004-2005, Howard Abrams • Except where otherwise noted, all original content is licensed under a Creative Commons License (see details). |
||||||||||
|
|||||||||||