#!/usr/bin/perl -w # makeslides - a slide maker # see tpc_2001_presentation.txt for a sample input file # written with MacPerl, should work fine on any perl # pudge@pobox.com # thanks to Rocco Caputo for super-fresh HTML/CSS # formatting help and other patches use File::Basename; use File::Copy; use File::Spec::Functions; use URI; use strict; use vars qw($VERSION $HEAD); my(%data, %files); local *F; $VERSION = '2001062601'; ################################################################# # get init data # the first few lines of your file have specific data in them my $filename = $ARGV[0]; chomp(my $mttl = <>); # Title of Talk # Hold on a second! The first line may be an emacs directive. If it # is, shift everything down a line. chomp($mttl = <>) if $mttl =~ /-\*-.*-\*-/; chomp(my $mwht = <>); # Event Name chomp(my $mwhu = <>); # Event URL chomp(my $mdte = <>); # Event Date chomp(my $mwho = <>); # Presenter Names ################################################################# # setup my $pre = 'pre'; # what to use for "pre" tags my($file, $dir, $suf) = fileparse($filename, '\.txt'); my $ndir = $dir . $file; ################################################################# # create directory; must not already exist mkdir $ndir, 0777 or die "Can't create `$ndir': $!"; chdir $ndir or die "Can't chdir `$ndir': $!"; ################################################################# # CSS file: name it $inputfile.css, else we use the CSS # data in DATA my $oldstyle = catfile(updir, "$file.css"); if (-e $oldstyle) { copy($oldstyle, 'styles.css') or die $!; } else { local *STYLES; open(STYLES, ">styles.css") or die "Can't create `styles.css': $!"; print STYLES ; close STYLES; } ################################################################# # parse file into data structure # # slide titles begin at column 1 with nonspace data # # slides then have first-level headers, with optional # second-level headers # # first-level should be indented with one tab, second with two # tabs, with "* " as the first characters after the tabs # # to denote an entire section of code, begin with "
 " right
# after the "* ", followed by the code
my($n, $p);
while (<>) {
	last if /^__END__$/;  # embed comments at the end

	if (/^\S/) {
		chomp;
		$data{++$n}{head} = $_;
		$p = 0;
	} elsif (/^(?: {4}| {8}|\t)\* (<$pre>\s?)?(.*)$/s) {
		++$p;
		push @{$data{$n}{$p}}, "<$pre>" if $1;
		push @{$data{$n}{$p}}, $2;
	} elsif ($n && $p) {
		push @{$data{$n}{$p}}, $_;
	}
}

#################################################################
# parse out the code from after __END__ ... each bit of code
# will be denoted with a line like __CODE_this_is_my_code__ which
# will create a file called "this_is_my_code.html", which can
# be linked to from another slide with:
#    [LINK "this_is_my_code.html" "Click Here For My Code"]
my($code, $codename);
unless (eof) {
	while (<>) {
		if (/^__CODE_(\w+)__$/) {
			savecode($code, $codename) if $codename;
			$codename = $1;
			$code = "";
		} else {
			$code .= $_;
		}
	}
}
savecode($code, $codename) if $codename;

sub savecode {
	my($code, $codename) = @_;

	$code =~ s/&/&/g;
	$code =~ s//>/g;

	$code =~ s/\n/
/gi; # pp breaks $code =~ s/(?:
\s*){2,}
/

/gi; $code =~ s/\t/ /g; # can mess up internal tabs, oh well $code =~ s{((?: )+)(?: (\S))?} { ("  " x (length($1)/2)) . ($2 ? " $2" : "") }eg; open(F, ">" . $codename . ".html") or die "Can't create `$codename.html': $!"; print F < Code: $codename

$code

EOT close(F); } ################################################################# # make pages # this breaks down our data from the %data hash and creates pages # note the following pseudocode: # * create HREF links with [LINK "URL" "LABEL"] # * URLs will be matched and converted to HREFs automatically # * stuff in C<> will be wrapped in # * lines starting with
 will have 
added at the end # automatically foreach my $key (sort num keys %data) { my(@items, $head); $head = delete $data{$key}{head}; foreach my $field (sort num keys %{$data{$key}}) { my $fref = $data{$key}{$field}; my $text = '
  • '; if ($fref->[1] && $fref->[1] =~ /^\t\t\* /) { $text .= shift @$fref; $text .= "
    • "; for (@$fref) { s|^\t\t\* |
    • \n\t
    • |; $text .= $_; } $text =~ s|
      • \n*
      • |
          |g; $text .= "\n
        "; } else { $text .= join('', @$fref); } $text =~ s/\s+$//s; $text =~ s/&(?!#?[a-zA-Z0-9]+;)/&/g; $text =~ s|C<(.+?)>|$1|gs; $text =~ s|\[LINK "(.+?)" "(.+?)"\]|$2|g; if (grep {/<$pre>/} @{$fref}) { $text .= "\n\n"; } else { $text .= "\n\n"; } $text =~ s!((?:]+)>?)!$1!gs; push @items, $text; } my $file = sprintf "slide%3.3d.html", $key; $files{$file} = { items => \@items, head => $head, }; } ################################################################# # print pages # actually save the pages out to files, adding in headers and footers # and LINK tags with the right things in them my @files = sort keys %files; for my $i (0 .. $#files) { my $file = $files[$i]; open(F, ">" . $file) or die "Can't create `$file': $!"; my(%prev, %next); if ($i > 0) { $prev{head} = < EOT $prev{foot} = << $files{$files[$i-1]}{head}
        EOT } if ($files[-1] ne $file) { $next{head} = < EOT $next{foot} = <$files{$files[$i+1]}{head} >
        EOT } # Leave space for missing heads or feet so the back and # forward links are always on the same lines in the page # footer. $prev{head} ||= ''; $next{head} ||= ''; $prev{foot} ||= '
        '; $next{foot} ||= '
        '; print F < $mttl - $files{$file}{head} $prev{head}$next{head}

        $files{$file}{head}

        EOT print F "\n
          \n\n", join("\n", @{$files{$file}{items}}), "\n
        \n"; print F <
        EOT close(F); } ################################################################# # print our index page, which is just a big page with stuff in it open(F, "> index.html") or die "Can't create index.html: $!"; print F < $mttl

        $mttl

        $mwht

        $mdte

        $mwho

        Begin

        EOT close(F); ################################################################# # create table of contents page open(F, "> toc.html") or die "Can't create toc.html: $!"; print F < $mttl - Table of Contents

        $mttl - Table of Contents

          EOT for my $file (sort keys %files) { print F qq[
        1. $files{$file}{head}
        2. \n]; } print F "
        \n"; print F <
        EOT close(F); ################################################################# # a few leftovers sub num {$a <=> $b} BEGIN { # the standard header + doctype etc. # ?xml? is optional, basically, and MSIE chokes on it when reading # a file locally with this in it, so i leave it out # chomp($HEAD = <<'EOT'); EOT } __END__ body, ul, ol, p { background-color: #DDDDDD; color: #222222; font-family: Verdana, Helvetica, Arial, sans-serif; } tt, pre { font-family: Monaco, Courier, monospace; font-size: 20pt; font-weight: normal; } table.navigation { background-color: #660000; } td.navigation { color: #FFFFFF; vertical-align: top; font-size: 20pt; font-family: Verdana, Helvetica, Arial, sans-serif; } h1, h2, h3, table { font-family: Verdana, Helvetica, Arial, sans-serif; } body, p { font-size: 20pt } h1 { font-size: 36pt } h2 { font-size: 32pt } h3 { font-size: 20pt } ul, li, ol { font-size: 26pt } li { padding-bottom: 8pt } .codepage { background-color: #FFFFFF } .indexpage { text-align: center } p.indexpage { font-size: 42pt } h1.indexpage { font-size: 58pt } h2.indexpage { font-size: 42pt } h3.indexpage { font-size: 28pt } a:visited, a:active { color: #222222; text-decoration: none; } a:link { color: #222222; text-decoration: underline; } a:hover { color: #660000; text-decoration: underline; } a.td:link, a.td:visited, a.td:active { color: #FFFFFF; } a.td:hover { color: #DDDDDD; }