Thursday, March 8, 2007

Upgrading to Webgen 0.4

I use Webgen to build my website, and I've just finished upgrading to the latest Webgen release, 0.4.2, from version 0.3.8, which was over a year old. It was a bit of a pain, and the Webgen documentation is a little lacking, so I thought I'd share my experiences.

First, I could see that I needed to change the format of my block declarations in my content pages from

- {name: content, format: textile}
- {name: sidebar_heading, format: textile}
- {name: sidebar, format: textile}


blocks: [[content, textile], [sidebar_heading, textile], [sidebar, textile]]

Not a big deal, though I needed to do it in every file (I need to find a way to get rid of this duplication). I thought that would be enough to get me running, but to my surprise every page generated the message "Invalid structure of meta information".

The problem was that my files (originally created in Windows and now living on my Mac) had lines ending in \r\n and Webgen didn't like this. Things worked better when I changed each file to have lines ending simply in \n.

Next I had to replace references to block content in templates from from

{block: block_name}

After that I was 90% of the way there, with all the standard stuff covered. The next step was to handle two places where I'd used included content.

Webgen 0.4 changes the order of the steps in the evaluation of page files. The new order is:

  1. convert to HTML;

  2. then ERB;

  3. then webgen tags.

In earlier versions I believe the steps were performed in the reverse order. This change in ordering broke some of my "custom" code, where I was including common Textile content into a number of pages by reading it from a file via ERB. Since ERB is now run after the conversion to HTML from Textile I was getting the included Textile content rendered as HTML without translation.

One thing I was using this for was to include a common sidebar. However Webgen now supports nested templates, and that's a better way to solve the common sidebar problem. I now have a template that looks like this:

template: ../default.template
--- content
{block: content}
--- sidebar_heading, textile
--- sidebar, textile
<div class="training">
* <a href="{relocatable:}">Easy Access Training</a>
* <a href="{relocatable:}#softwareDevelopment">Software Development</a>
* <a href="{relocatable:}#coachingAndMentoring">Coaching and Mentoring</a>
* <a href="{relocatable:}#training">In-house Training</a>
For enquiries regarding any of our services, please <a href="">email us</a>.

Pages that want the common sidebar use this template and only need to provide the body content.

The other thing I was using an ERB include for was to provide a common set of textile link aliases (things like [three_rivers_essay] These need to be in the same file as the textile source at the time it's converted to HTML which is before either ERB or tags are handled, so it looked like I was out of luck. My solution was to write my own tag, called "site", which provides the same sort of functionality. A reference to the tag looks like {site: three_rivers_essay} or {site: {name: three_rivers_essay, text: "a different piece of text"}} - I'll include the plugin code at the end of the post.

It's good to see Webgen in active development, I like nested templates, and it's quite easy to write plugins. It would be good to see better documentation (hopefully that will come from the new activity as well) but Thomas Leitner provides excellent support via the forums.

class SiteTag ["Suncorp-Metway", ""],
"three_rivers_essay" => ["software tyranny", '']
# and so on
infos( :name => 'Custom/Site',
:summary => 'Return standard sites and labels')
register_tag 'site'
param('name', nil, 'The name of the site that will be linked to')
set_mandatory('name', true)
param('text', nil, 'The text that will be displayed for the link')
def process_tag(tag, chain)
def link
name = param('name')
definition = @@definitions[name]
raise('Could not find site named ' + name + ' in ' + @@definitions.to_s) unless definition
url = definition[1]
text = param('text') || definition[0]
return "<a href='#{url}'>#{text}</a>"

No comments:

Post a Comment