X-Git-Url: https://git.exim.org/exim-website.git/blobdiff_plain/296dcdc148c40473ee48be93a9a8325ef947ea55..596e5400822242a1076979102fa590054834b68a:/script/gen.pl?ds=sidebyside diff --git a/script/gen.pl b/script/gen.pl index 4c545f5..7bc1309 100755 --- a/script/gen.pl +++ b/script/gen.pl @@ -6,6 +6,7 @@ use File::Copy; use File::Find; use File::Slurp; use File::Spec; +use Getopt::Long; use JavaScript::Minifier::XS; use XML::LibXML; use XML::LibXSLT; @@ -58,12 +59,12 @@ sub do_web { if ( $path =~ /(.+)\.css$/ ) { print "CSS to : docroot:/$path\n"; my $content = read_file("$opt{tmpl}/web/$path"); - write_file( "$opt{docroot}/$path", CSS::Minifier::XS::minify($content) ); + write_file( "$opt{docroot}/$path", $opt{minify} ? CSS::Minifier::XS::minify($content) : $content ); } elsif ( $path =~ /(.+)\.js$/ ) { print "JS to : docroot:/$path\n"; my $content = read_file("$opt{tmpl}/web/$path"); - write_file( "$opt{docroot}/$path", JavaScript::Minifier::XS::minify($content) ); + write_file( "$opt{docroot}/$path", $opt{minify} ? JavaScript::Minifier::XS::minify($content) : $content ); } else { ## Copy @@ -163,7 +164,11 @@ sub xref_fixup { foreach my $chapter ( $xml->findnodes('/book/chapter') ) { ++$chapter_counter; - my $chapter_id = $chapter->getAttribute('id'); + my $chapter_id = $chapter->getAttribute('id'); + unless ($chapter_id) { # synthesise missing id + $chapter_id = sprintf( 'chapter_noid_%04d', $chapter_counter ); + $chapter->setAttribute( 'id', $chapter_id ); + } my $chapter_title = $chapter->findvalue('title'); $index{$chapter_id} = { chapter_id => $chapter_counter, chapter_title => $chapter_title }; @@ -173,13 +178,23 @@ sub xref_fixup { foreach my $section ( $chapter->findnodes('section') ) { ++$section_counter; - my $section_id = $section->getAttribute('id'); + my $section_id = $section->getAttribute('id'); + unless ($section_id) { # synthesise missing id + $section_id = sprintf( 'section_noid_%04d_%04d', $chapter_counter, $section_counter ); + $section->setAttribute( 'id', $section_id ); + } my $section_title = $section->findvalue('title'); - $index{$section_id} = - { chapter_id => $chapter_counter, chapter_title => $chapter_title, section_id => $section_counter }; + $index{$section_id} = { + chapter_id => $chapter_counter, + chapter_title => $chapter_title, + section_id => $section_counter, + section_title => $section_title + }; } } + ## Build indexes as new chapters + build_indexes( $xml, $prepend_chapter, \%index ); ## Replace all of the xrefs in the XML foreach my $xref ( $xml->findnodes('//xref') ) { @@ -187,7 +202,8 @@ sub xref_fixup { if ( exists $index{$linkend} ) { $xref->setAttribute( 'chapter_id', $index{$linkend}{'chapter_id'} ); $xref->setAttribute( 'chapter_title', $index{$linkend}{'chapter_title'} ); - $xref->setAttribute( 'section_id', $index{$linkend}{'section_id'} ) if $index{$linkend}{'section_id'}; + $xref->setAttribute( 'section_id', $index{$linkend}{'section_id'} ) if ( $index{$linkend}{'section_id'} ); + $xref->setAttribute( 'section_title', $index{$linkend}{'section_title'} ) if ( $index{$linkend}{'section_title'} ); $xref->setAttribute( 'url', sprintf( '%sch%02d.html', $prepend_chapter, $index{$linkend}{'chapter_id'} ) . ( $index{$linkend}{'section_id'} ? '#' . $linkend : '' ) ); @@ -195,6 +211,80 @@ sub xref_fixup { } } +## Build indexes +sub build_indexes { + my ( $xml, $prepend_chapter, $xref ) = @_; + + my $index_hash = {}; + my $current_id; + foreach my $node ( $xml->findnodes('//section | //chapter | //indexterm') ) { + if ( $node->nodeName eq 'indexterm' ) { + my $role = $node->getAttribute('role') || 'concept'; + my $primary = $node->findvalue('child::primary'); + my $first = uc( substr( $primary, 0, 1 ) ); # first char + my $secondary = $node->findvalue('child::secondary') || ''; + $index_hash->{$role}{$first}{$primary}{$secondary} ||= []; + push @{ $index_hash->{$role}{$first}{$primary}{$secondary} }, $current_id; + } + else { + $current_id = $node->getAttribute('id'); + } + } + + # now we build a set of new chapters with the index data in + my $book = ( $xml->findnodes('/book') )[0]; + foreach my $role ( sort { $a cmp $b } keys %{$index_hash} ) { + my $chapter = XML::LibXML::Element->new('chapter'); + $book->appendChild($chapter); + $chapter->setAttribute( 'id', 'index_' . $role ); + $chapter->appendTextChild( 'title', ( ucfirst($role) . ' Index' ) ); + foreach my $first ( sort { $a cmp $b } keys %{ $index_hash->{$role} } ) { + my $section = XML::LibXML::Element->new('section'); + my $list = XML::LibXML::Element->new('itemizedlist'); + $chapter->appendChild($section); + $section->setAttribute( 'id', 'index_' . $role . '_' . $first ); + $section->appendTextChild( 'title', $first ); + $section->appendChild($list); + foreach my $primary ( sort { $a cmp $b } keys %{ $index_hash->{$role}{$first} } ) { + my $item = XML::LibXML::Element->new('listitem'); + my $para = XML::LibXML::Element->new('para'); + $list->appendChild($item); + $item->appendChild($para); + $para->appendText($primary); + my $slist; + foreach my $secondary ( sort { $a cmp $b } keys %{ $index_hash->{$role}{$first}{$primary} } ) { + my $spara; + my $sitem; + if ( $secondary eq '' ) { + $spara = $para; # skip having extra layer of heirarchy + } + else { + unless ($slist) { + $slist = XML::LibXML::Element->new('itemizedlist'); + $item->appendChild($slist); + } + $sitem = XML::LibXML::Element->new('listitem'); + $spara = XML::LibXML::Element->new('para'); + $slist->appendChild($sitem); + $slist->appendChild($spara); + $spara->appendText($secondary); + } + $spara->appendText(': '); + my $count = 0; + foreach my $ref ( @{ $index_hash->{$role}{$first}{$primary}{$secondary} } ) { + $spara->appendText(', ') + if ( $count++ ); + my $xrefel = XML::LibXML::Element->new('xref'); + $xrefel->setAttribute( linkend => $ref ); + $xrefel->setAttribute( longref => 1 ); + $spara->appendChild($xrefel); + } + } + } + } + } +} + ## Handle the transformation sub transform { my ( $xml, $xsl_path, $out_path ) = @_; @@ -242,67 +332,33 @@ sub mkdirp { ## Parse arguments sub parse_arguments { - my %opt = (); - ## --help - help(0) if int(@ARGV) == 0 || grep( /^--help|-h$/, @ARGV ); - - my @collection = @ARGV; - while (@collection) { - my $key = shift @collection; - - if ( $key eq '--web' ) { - - ## --web - $opt{web} = 1; - } - elsif ( $key =~ /^--(spec|filter)$/ ) { + my %opt = ( spec => [], filter => [], help => 0, web => 0, minify => 1 ); + GetOptions( \%opt, 'help|h!', 'web!', 'spec=s{1,}', 'filter=s{1,}', 'latest=s', 'tmpl=s', 'docroot=s', 'minify!' ) + || help( 1, 'Bad options' ); - ## --spec and --filter - my $continue = 1; - while ( $continue && @collection ) { - my $value = shift @collection; - - if ( $value =~ /^--/ ) { - unshift @collection, $value; - $continue = 0; - } - else { - $value = File::Spec->rel2abs($value); - help( 1, 'No such file: ' . $value ) unless -f $value; - push @{ $opt{$1} }, $value unless grep( $_ eq $value, @{ $opt{$1} } ); - } - } - help( 1, 'Missing value for ' . $key ) unless exists $opt{$1}; - } - elsif ( $key eq '--latest' ) { + ## --help + help(0) if ( $opt{help} ); - ## --latest - my $value = shift @collection; - help( 1, 'Missing value for ' . $key ) unless defined $value; - help( 1, 'Invalid value for ' . $key ) unless $value =~ /^\d+(?:\.\d+)*$/; - $opt{latest} = $value; - } - elsif ( $key =~ /^--(tmpl|docroot)$/ ) { - - ## --tmpl and --docroot - my $value = shift @collection; - help( 1, 'Missing value for ' . $key ) unless defined $value; - $value = File::Spec->rel2abs($value); - help( 1, 'No such directory: ' . $value ) unless -d $value; - $opt{$1} = $value; - $opt{$1} =~ s#/+$##; - } - else { - help( 1, 'Bad argument: ' . $key ); - } + ## --spec and --filter lists + foreach my $set (qw[spec filter]) { + $opt{$set} = [ map { my $f = File::Spec->rel2abs($_); help( 1, 'No such file: ' . $_ ) unless -f $f; $f } @{ $opt{$set} } ]; } + ## --latest + help( 1, 'Missing value for latest' ) unless ( exists( $opt{latest} ) && defined( $opt{latest} ) ); + help( 1, 'Invalid value for latest' ) unless $opt{latest} =~ /^\d+(?:\.\d+)*$/; + + ## --tmpl and --docroot + foreach my $set (qw[tmpl docroot]) { + help( 1, 'Missing value for ' . $set ) unless ( exists( $opt{$set} ) && defined( $opt{$set} ) ); + my $f = File::Spec->rel2abs( $opt{$set} ); + help( 1, 'No such directory: ' . $opt{$set} ) unless -d $f; + $opt{$set} = $f; + } + help( 1, 'Excess arguments' ) if ( scalar(@ARGV) ); help( 1, 'Must include at least one of --web, --spec or --filter' ) - unless exists $opt{web} || exists $opt{spec} || exists $opt{filter}; - foreach (qw( latest tmpl docroot )) { - help( 1, 'Missing argument: --' . $_ ) unless exists $opt{$_}; - } + unless ( defined $opt{web} || scalar( @{ $opt{spec} } ) || scalar( @{ $opt{web} } ) ); return %opt; }