#!/usr/bin/perl -w
# dumblate.pl -- Template system for the weak
#
# dumblate is a small (and dumb) script to manage a set of text files
# and turn them into more readable HTML, or any other format for
# instance, using perl's Template system.
#
# Yes it's dumb. Hence the name. But I wanted to have a look at perl's
# Template, and BTW I needed some tiny blosxom-like templating system I
# could hack quickly.
#
# Usage: have a look at the code.
# Author: oz <oz@tuxaco.net>
use strict;
use warnings;
use File::Find;
use Template;
# Title
my $title = '/var/log/oz';
# Where are text files kept ?
my $text_path = '/where/the/sun/shines/';
my $extension = 'txt';
# Where do we generate pages
my $data_path = '/path/to/the/dark/side';
my $data_ext = 'html';
# Templates anyone ?
my $template_path = $text_path;
# ----------------------------------------------------------------------------
# If first arg exists, and is true in a perlish way, we should rebuild
# the whole archive.
my $rebuild_all = shift || 0;
umask 022;
my %entries;
print "* Welcome to dumblate!\n\n";
# Find text files
find( { wanted => sub {
my $file = $_;
return unless (-f $file)
&& ($File::Find::dir eq $text_path)
&& ($file =~ /\.$extension$/);
my $staticname = $file;
$staticname =~ s/^(.*)\.$extension$/$1\.$data_ext/g;
$staticname =~ s/^$text_path/$data_path/g;
$entries{$file} = { dest => $staticname };
}, no_chdir => 1 }, $text_path );
# Build entries
foreach my $file (sort keys %entries) {
my $item_title = undef;
if ($rebuild_all || ! -f $entries{$file}->{'dest'}) {
$entries{$file}->{'title'} = build($file, $entries{$file}->{'dest'});
} else {
$entries{$file}->{'title'} = grab_title($file);
}
# Make Relative URL
$entries{$file}->{'url'} = $entries{$file}->{'dest'};
$entries{$file}->{'url'} =~ s/$data_path\///g;
# Plus short name
$entries{$file}->{'num'} = $entries{$file}->{'url'};
$entries{$file}->{'num'} =~ s/\.html//g;
# Oh, and mtime too ?
$entries{$file}->{'date'} = scalar localtime( (stat($file))[9] );
}
# Build index
template('index', \%entries);
# ----------------------------------------------------------------------------
# Build one entry
sub build {
my ($source, $dest) = @_;
my $item_title;
my $item_body;
return 0 if (!defined $source || !defined $dest);
open(SRC, $source) or return warn("Can't read $source.\n");
$item_title = <SRC>;
chomp $item_title;
{
local $/ = undef;
$item_body = <SRC>;
}
chomp $item_body;
close(SRC);
template('entry', $item_title, $item_body, $dest);
return $item_title;
}
# Grab first line of file, which incidently is its designated title.
sub grab_title {
my ($source) = @_;
return undef unless defined $source;
open(SRC, $source) or return warn("Can't read $source.\n");
my $title = <SRC>;
close(SRC);
chomp $title;
return $title;
}
# Template things
sub template {
my $type = shift;
my $vars;
my $output;
my $item_title;
my $item_data;
# Building one entry
if ('entry' eq $type) {
($item_title, $item_data, $output) = @_;
$vars = {
title => $item_title,
body => $item_data,
};
print "Generating: $output ($item_title)\n";
}
# Building entry list (index.html)
if ('index' eq $type) {
$item_data = shift;
$output = "$data_path/$type.$data_ext";
$vars = {
entries => [],
title => $title,
};
foreach my $k (keys %$item_data) {
push @{$vars->{'entries'}}, $item_data->{$k};
}
print "Generating: $type.$data_ext\n";
}
# Writing template
open(my $out, ">$output") or
return warn("Can't write $output.\n");
my $tt = Template->new( ABSOLUTE => 1 );
$tt->process("$template_path/$type.tpl", $vars, $out)
or warn("Failed : " . $tt->error() . "\n");
close($out);
}