#!/usr/bin/perl
#
use strict;
my $local_site; # site we are generating for
my $rootnode = undef;
my %sites;
########################### read config from file ##########################
my $config_file_ln = 0; # current line number
# read line, combining escaped (ending in \) lines into one, removing
# leading and trailing whitespace, comments and empty lines
sub read_line {
my $line = undef;
my $i;
for ($i = 0; <CONFIG_FILE>; ++$i) {
chomp;
++$config_file_ln;
s/^\s*//; s/\s*$//;
next if $_ eq '';
# comments
next if /^[\;\#]/ || /^\/\//;
$line = "$line$_";
if ($line =~ /\\$/) {
chop $line;
} else {
last;
}
}
return $line;
}
sub read_config_die {
print "line $config_file_ln: $_[0]\n";
exit;
}
sub read_node {
my ($node) = @_;
my $prevnode;
return if $node->{type} eq 'seperator';
my %valid_variables = (
title => 1,
description => 1,
site => 1,
body => 1,
email => 1,
);
while ($_ = read_line()) {
my @fields = split(/\s+/);
if ($fields[0] eq "end") {
if ($fields[1] && $fields[1] ne $node->{location}) {
read_config_die "'end $fields[1]' but this is " .
$node->{location};
}
last;
} elsif ($node->{type} eq "node"
&& $fields[0] =~/^(dir|seperator|link|file|node)$/ ) {
my $subnodes = [];
my $nodename = '';
$nodename = $fields[1] if ($fields[1]);
my $subnode = {
location => $nodename,
parent => $node,
type => $fields[0],
subnodes => $subnodes,
title => $nodename,
};
if ($prevnode) {
$subnode->{prevnode} = $prevnode;
$prevnode->{nextnode} = $subnode;
}
bless $subnode;
$subnodes = $node->{subnodes};
push(@$subnodes, $subnode);
read_node($subnode);
$prevnode = $subnode if $subnode->{type} eq 'node';
} elsif (/^\S+\s*\=/) {
# value
my ($variable, $value) = ($_, $_);
$variable =~ s/\s*\=.*$//;
$value =~ s/^\S+\s*\=\s*//;
if (!$valid_variables{$variable}) {
read_config_die "invalid variable $variable specified";
}
$node->{$variable} = $value;
} elsif ($fields[0] eq "site") {
$sites{$fields[1]} = $fields[2];
} else {
read_config_die "invalid line '$_'";
}
}
}
sub read_config {
%sites = {};
$sites{'*'} = 'all sites';
my $subnodes = [];
open(CONFIG_FILE, 'fnet.txt') or die "cant open fnet.txt";
$config_file_ln = 0;
$rootnode = {
location => '',
type => 'node',
site => '*',
subnodes => $subnodes,
};
read_node $rootnode;
close(CONFIG_FILE);
}
sub get_node_property {
my ($node, $property) = @_;
for (;; $node=$node->{parent}) {
if ($node->{$property}) {
return $node->{$property};
}
last if (!$node->{parent})
}
return undef;
}
sub get_node_site {
my ($node) = @_;
my $site = get_node_property($node, 'site');
$site = $local_site if ($site eq '*');
die "site $site not specified!" if (!$sites{$site});
return $site;
}
sub get_node_url {
my ($node) = @_;
my $url = '';
return $node->{location} if ($node->{type} eq 'link');
for (my $n = $node; $n->{parent}; $n = $n->{parent}) {
$url = '/' . $n->{location} . $url;
}
$url = $sites{get_node_site($node)} . $url;
$url .= '/' if ($node->{type} eq 'node' || $node->{type} eq 'dir');
return $url;
}
sub get_node_relative_url {
my ($source, $target) = @_;
return $target->{location} if ($target->{type} eq 'link');
if (get_node_site($source) ne get_node_site($target)) {
return get_node_url($target);
}
return $target->{location} if ($target->{type} eq 'file');
return $target->{location} . '/';
}
######################### sitemap #################################
my $depth = 0;
sub generate_sitemap_node {
my ($node) = @_;
my $subnodes = $node->{subnodes};
print SITEMAP '<a href="' . get_node_url($node) . '">';
print SITEMAP $node->{title};
print SITEMAP "</a>\n";
if ($node->{type} eq 'node') {
++$depth;
print SITEMAP ' ' x $depth . "<ul>\n";
foreach (@$subnodes) {
next if ($_->{type} eq 'link'
|| $_->{type} eq 'seperator');
print SITEMAP (' ' x $depth) . "<li>";
generate_sitemap_node $_, $depth;
}
print SITEMAP ' ' x $depth . "</ul>\n";
--$depth;
}
}
sub generate_sitemap {
my ($file) = @_;
open(SITEMAP, ">$file") or die "cant open $file";
print SITEMAP "<html>\n";
print SITEMAP "<head><title>Sitemap</title></head>\n";
print SITEMAP "<body " . get_node_property($rootnode, 'body') . ">\n";
print SITEMAP "<h2>Sitemap</h2>\n";
print SITEMAP "<hr>\n";
generate_sitemap_node $rootnode, 0;
print SITEMAP "<hr>\n";
print SITEMAP '<a href="' . get_node_property($rootnode, 'email') ;
print SITEMAP '">email</a>' . "\n";
print SITEMAP "</body>\n";
print SITEMAP "</html>\n";
close SITEMAP;
}
############################ main node pages ############################
sub generate_page_tree {
my ($node) = @_;
my $text = "";
if ($node->{parent}) {
$text = generate_page_tree($node->{parent});
}
$text .= '<a href="' . get_node_url($node) . '">';
$text .= $node->{title};
$text .= '</a>';
return $text . " > \n";
}
sub nodelink {
my ($rel, $node) = @_;
if ($node) {
print NODE_PAGE "<link ";
print NODE_PAGE "rel=\"$rel\" ";
print NODE_PAGE "href=\"" . get_node_url($node) . "\" ";
print NODE_PAGE "title=\"" . $node->{title} . "\" ";
print NODE_PAGE ">\n";
}
}
sub generate_page {
my ($node, $filename) = @_;
open (NODE_PAGE, ">$filename") or die "cant open $filename for writing";
print NODE_PAGE "<html>\n";
print NODE_PAGE "<head>\n";
print NODE_PAGE "<title>" . $node->{title} . "</title>\n";
# mozilla site nav links
print NODE_PAGE "<link rel=\"ToC\" href=\"" .
get_node_url($rootnode) . "sitemap.html\">\n";
nodelink "Top", $rootnode;
nodelink "Up", $node->{parent};
nodelink "Prev", $node->{prevnode};
nodelink "Next", $node->{nextnode};
print NODE_PAGE "</head>\n";
print NODE_PAGE "<body ". get_node_property($node, 'body') .">\n";
print NODE_PAGE "<h2>" . $rootnode->{title} . "</h2>\n";
if ($node->{parent}) {
print NODE_PAGE generate_page_tree($node->{parent});
print NODE_PAGE $node->{title};
}
if ($node->{description}) {
print NODE_PAGE "<br><br>\n" if $node->{parent};
print NODE_PAGE $node->{description} . "\n";
}
print NODE_PAGE "<ul>\n";
my $subnodes = $node->{subnodes};
foreach (@$subnodes) {
if ($_->{type} eq 'seperator') {
print NODE_PAGE "</ul><hr><ul>\n";
next;
}
print NODE_PAGE "<li> ";
print NODE_PAGE "<a href=\"" . get_node_relative_url($node, $_);
print NODE_PAGE "\">" . $_->{title} . "</a>\n";
if ($_->{description}) {
print NODE_PAGE "<br>" . $_->{description} . "\n";
}
}
print NODE_PAGE "</ul>\n";
print NODE_PAGE "<hr>\n";
print NODE_PAGE "<a href=\"" . get_node_property($node, 'email') . "\">email</a>\n";
print NODE_PAGE "</body>\n</html>\n";
close NODE_PAGE;
}
sub generate_tree {
my ($node, $dir) = @_;
mkdir $dir if $dir;
generate_page $node, $dir . 'index.shtml';
my $subnodes = $node->{subnodes};
foreach (@$subnodes) {
# only generate local nodes
if ($_->{type} eq 'node' && get_node_site($_) eq $local_site) {
generate_tree($_, $dir . $_->{location} . '/') ;
}
}
}
if (!$ARGV[0]) {
print "Usage: $0 site\n";
exit;
}
$local_site = $ARGV[0];
read_config;
die "Specified site $local_site does not exist!" if (!$sites{$local_site});
generate_sitemap('sitemap.html');
generate_tree($rootnode);