Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
I've used a couple of different template systems but right now my favorite is a simple system based on Template::Toolkit. I used a custom template provider to do the kind of includes I want to do. It looks for includes in the current directory, then the parent dir etc.. Which makes it really easy (for instance) to use a standard index.html file which can include a different header.html file in some subdirectories.

Read along for code. warning: the following code is probably full of bugs, and could be written better, but it's what I use for my (small) site without any problems. Do with it what you want.

Oh yes: it needs a file called "process.files" in the current dir which is just a text file containing (one per line) the path of the files to be generated and an optional title of that file (seperated from the path by a space).

Source templates go in src dir, destination goes to build directory.

#!/usr/bin/perl -w use strict; use lib './lib'; use Template; use Template::Context; use Template::Exception; use FindProvider; use Cwd; use File::Basename; use File::Find; use File::Copy; my $cwd = getcwd; my $incpath = "$cwd/src"; my $outpath = "$cwd/build"; my %names; my %shortnames; my (@paths); open(CONFIG,"< process.files") or die "Cannot open process.files: $!"; while (<CONFIG>) { next if /^\s*#/ || /^$/; chomp; my ($path,$name) = split / /,$_,2; push @paths,$path; if ($name =~ /(.+)\|(.+)/) { $names{$path} = $1; $shortnames{$path} = $2; } else { $names{$path} = $name; $shortnames{$path} = $name; } warn "$path => $name\n"; } close CONFIG; my $provider = FindProvider->new({ INCLUDE_PATH => $incpath, ABSOLUTE => 1, }); my $context = Template::Context->new({ EVAL_PERL => 1, INCLUDE_PATH => $incpath, LOAD_TEMPLATES => [$provider], }); my $tt = Template->new({ CONTEXT => $context, OUTPUT_PATH => $outpath, }); if (-d $outpath) { warn "Removing build dir\n"; system ("rm -rf $outpath") == 0 or die "Cannot remove $outpath: $! +"; } warn "Creating build dir"; mkdir $outpath,0755 or die "Cannot create $outpath: $!"; for my $file (@paths) { my ($base,$dir,$sfx) = fileparse($file,".html"); chdir "$incpath/$dir" or die "Cannot chdir to $dir: $!"; unless (-d "$outpath/$dir") { mkdir "$outpath/$dir",0755 or die "Cannot make $outpath/$dir: +$!"; } warn "Processing $dir/$base$sfx\n"; $tt->process("$base$sfx",{ path => $file, title => $names{$file}, short => $shortnames{$file}, paths => \@paths, find => \&find_template, parent => \&parent, children => \&children, titles => \%names, short => \%shortnames, root => root($file), subnav => [subnav($file)], dir => \&dir, top => \&top, },"$dir/$base$sfx") || die $tt->error; } chdir $incpath; find({ wanted => sub { return unless /(?:\.css|\.png|\.jpg|\.pdf|\.txt|\.ico|\.cgi|\. +asc)$/; return unless -f $_; warn "Copying $_\n"; copy($_,"$outpath/$_") or die "Cannot copy $_: $!"; }, no_chdir => 1, },'.'); sub find_template { my ($file) = @_; my $cwd = getcwd; my $rel = $file; warn "cwd = $cwd, rel = $file"; while (index($cwd,$incpath) == 0) { if (-f "$cwd/$file") { return $rel; } $cwd =~ s#/[^/]+/?$## or last; $rel = "../$rel"; } die Template::Exception->new('find error',"Cannot find $file anywh +ere in path\n"); } sub parent { my ($path) = @_; return unless $path =~ m#/#; $path =~ s#/[^/]+/?$##; $path .= "/index.html"; return $path if $names{$path}; return; } sub children { my ($path) = @_; $path =~ s#[^/]+$##; my @children; for (@paths) { if (m#^\Q$path\E[^/]+/[^/]+$#) { push @children,$_; warn "child: $_\n"; } } return @children; } sub root { my ($path) = @_; warn "path =$path"; $path =~ s#^\./##; $path =~ s#[^/]+$##; $path =~ s#[^/]+#..#g; return $path; } sub subnav { my $file = shift; if ($file =~ m#/#) { return children(top($file)); } } sub top { my $file = shift; if ($file !~ m#/#) { return $file; } if ($file =~ m#^([^/]+)/index\.html#) { return $file; } if ($file =~ m#^([^/]+)/#) { return "$1/index.html"; } die "No top"; } sub dir { my $file = shift; $file =~ s/index\.html$//; return $file; }
Code for FindProvider.pm:
package FindProvider; use strict; use base qw(Template::Provider); use Template::Constants qw(STATUS_DECLINED); use Cwd qw(); use File::Basename; sub fetch { my ($self,$filename) = @_; if (ref $filename or index($filename,'..') >= 0 or index($filename +,'/') >= 0) { return $self->SUPER::fetch($filename); } my $path = ${$self->paths()}[0]; my $cwd = Cwd::getcwd(); while (index($cwd,$path) ==0) { # only recurse if current director +y is in the first path if (-f "$cwd/$filename") { return $self->SUPER::fetch("$cwd/$filename"); } $cwd =~ s#/[^/]+/?$##; } return undef,STATUS_DECLINED; } 1;

In reply to Re: What are your favorite tools for building a static site? by Joost
in thread What are your favorite tools for building a static site? by webfiend

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (7)
As of 2024-04-18 10:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found