ADDED cfg/links Index: cfg/links ================================================================== --- cfg/links +++ cfg/links @@ -0,0 +1,14 @@ + this is just a space-delimited list of main links. the + first part should contain the URL to link to, relative to + the root of the generated site. + + for instance, if you have a file in src/stories/a-story.md, + you would write /src/stories/a-story.html. + + note that URLs cannot contain spaces! also, lines beginning + with a space are treated as comments and are ignored by the + parser. + +/index.html home +/about.html about +/doc/index.html tsunami docs ADDED cfg/sitename Index: cfg/sitename ================================================================== --- cfg/sitename +++ cfg/sitename @@ -0,0 +1,7 @@ + this is the text that is displayed in your header. + the first line is wrapped in

, the second in

+ any further lines are ignored. blank lines and lines + beginning with whitespace are ignored. + +tsunami +a simple website generator ADDED pub.pl Index: pub.pl ================================================================== --- pub.pl +++ pub.pl @@ -0,0 +1,297 @@ +#!/usr/bin/perl +use warnings; +use feature "unicode_strings"; +use utf8; +binmode STDOUT, ':utf8'; + +sub err { print "\e[1;31merror:\e[0m ".$_[0]."\n"; exit 1; } +if (! -e "pub.pl") { + err "\e[1mpub.pl\e[0m must be run from the directory it lives in"; +} + +sub filext { + my $name = shift; + my $ext = $name; + $ext =~ s/^([^.]*\.)*//; + if ($ext eq $name) { + return ""; + } else { + return $ext; + } +} +sub basename { + my $name = shift; + $name =~ s/\.[^.]*$//; + return $name; +} + +sub isws { my $c = shift; + return (($c eq " ") or ($c eq "\t")); +} + +sub readconf { + my $filename = shift; + open my $fd, "<:encoding(UTF-8)", "cfg/".$filename + or err "could not open $filename ($!)\nmake sure it exists"; + my @lines; + while (my $ln = <$fd>) { + chomp $ln; + if(isws(substr($ln,0,1))) {next;} # line is comment + if($ln eq "") {next;} # line is blank + push @lines, $ln; + } + close $fd; + return @lines; +} + +sub confpairs { + sub sep { + my $str = shift; my @seps = @_; my $low = -1; + foreach (@seps) { + my $pos = index($str, $_); if ($pos != -1) { + if (($low == -1) or ($pos < $low)) { $low = $pos; } + } + } + return $low; + } + my @lines = @_; + my @pairs; + foreach (@lines) { + my $ln = $_; + my $i = sep $ln, ' ', "\t"; + my $j = $i; + while ($j < length $ln) { if(isws(substr $ln, $j, 1)) { ++$j; } else {last;}} + my $key = substr $ln, 0, $i; + my $value = substr($ln, $j, length($ln)); + push @pairs, [$key, $value]; + } + return @pairs; +} + +my @header = readconf("sitename"); +my @links = readconf("links"); +my @linkpairs = confpairs(@links); + +sub depth { + my $path = shift; + my $ct = () = $path =~ /\//g; + return $ct; +} + +sub root { + my $depth = shift; + -- $depth; + if ($depth == 0) { + return "."; + } elsif ($depth == 1) { + return ".." + } else { + my $str = ".."; + for (my $i = 0; $i!=$depth; ++$i) { + $str .= "/.."; + } + return $str; + } +} + +sub page { + my ($path, $body) = @_; + my $root = root depth $path; + my $title; + if ($#header >= 0) { + $masthead = "\n\t\t

$header[0]

\n\t"; + $title = $header[0]; + if ($#header > 0) { + $masthead .= "\t

$header[1]

\n\t"; + } + } else { + err "no site name specified"; + } + my $nav = ""; + foreach (@linkpairs) { + my $dest = $root . $_->[0]; + my $lbl = $_->[1]; + $nav .= qq[$lbl\n\t\t\t]; + } + return qq[ + + + + $title + + + +
$masthead
+
+ +
+ $body +
+
+ +] +} + +sub filter { + $_[0] =~ s/&/&/g; + $_[0] =~ s//>/g; +} +use constant { + PLAIN => 1, + ORDLIST => 2, + STARLIST => 3 +}; +my %parsers = ( + 'md' => sub { my ($inpath, $outpath) = @_; + print "parsing markdown → \e[36m$outpath.html\e[0m"; + my $root = root depth $outpath; + open my $in, "<:encoding(UTF-8)", $inpath; + open my $out, ">:encoding(UTF-8)", $outpath.".html"; + my $pg = ""; + my $ctx = PLAIN; + while (my $ln = <$in>) { + chomp $ln; + if ($ln ne "") { + filter $ln; + my $lntype; + if ($ln =~ m{^\s*[0-9]*\.}) { + $lntype = ORDLIST; + $ln =~ s;^\s*[0-9]*\.\s*;;; + } elsif ($ln =~ m{^\s*\*\s+}) { + $lntype = STARLIST; + $ln =~ s-^\s*\*\s+--; + } else { + $lntype = PLAIN; + } + + if ($ln eq "---") { $pg .= "
\n"; next; } + + # im sorry ok + $ln =~ s;(?$1;g; + $ln =~ s;(?$1;g; + $ln =~ s;(?$1;g; + $ln =~ s;(?$1;g; + $ln =~ s;(?$1;g; + $ln =~ s;(?$1;g; + $ln =~ s;--;—;g; + $ln =~ s;-\\-;--;g; + $ln =~ s;-:-;÷;g; + $ln =~ s;-\\:-;-:-;g; + $ln =~ s;\\(.);$1;g; + $ln =~ s;([0-9])x([0-9]);$1×$2;g; + $ln =~ s;([0-9])\\x([0-9]);$1x$2;g; + + if ($lntype != $ctx) { #context change + if ($ctx == ORDLIST) { + $pg .= "\n"; + } elsif ($ctx == STARLIST) { + $pg .= "\n"; + } + $ctx = $lntype; + if ($ctx == ORDLIST) { + $pg .= "
    \n"; + } elsif ($ctx == STARLIST) { + $pg .= "