#!/usr/bin/env perl # # Copyright (C) 2001-2018 Graeme Walker # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # === # # make-website # # usage: make-website [--host=] # # Pulls together a doxygen-based website. Developed against # doxygen version 1.8.14. # use strict ; use FileHandle ; use File::Basename ; use Getopt::Long ; my %opt = () ; GetOptions( \%opt , "host=s" ) or die "usage error" ; die "usage error" if scalar(@ARGV) == 0 ; my $cfg_upload_version = $ARGV[0] ; my $cfg_author = "Graeme Walker" ; my $cfg_copyright = "Copyright (C) 2018 $cfg_author" ; my $cfg_output_dir = "website" ; my %colour = ( h => 195 , s => 255 , v => 100 ) ; # #0090c0 my %cfg_meta = ( description => "E-MailRelay: a simple SMTP store-and-forward MTA and POP3 server" , keywords => "MTA SMTP relay proxy e-mail store forward POP3 server" , author => $cfg_author , robots => "index,follow" , ) ; my @cfg_mainpage = qw( userguide.md reference.md windows.md ) ; my $cfg_css = "emailrelay-doxygen.css" ; my ( $cfg_icon ) = grep { -e $_ } ( "../icon/emailrelay-icon-small.png" , "../src/main/icon/emailrelay-icon-small.png" ) ; my $cfg_doxygen_cfg = "website.tmp.cfg" ; my $cfg_mainpage_md = "website.tmp.mainpage.md" ; my $cfg_pages_md = "website.tmp.pages.md" ; my $cfg_header = "website.tmp.header.html" ; my %cfg_hosts = ( sourceforge => { url_base => "https://sourceforge.net/projects/emailrelay" , download_url => "__base__/files/emailrelay/__version__" , button_url => "__base__/files/latest/download" , button_img_src => 'https://a.fsdn.com/con/app/sf-download-button' , button_img_attributes => 'src="__src__" width=276 height=48 srcset="__src__?button_size=2x 2x"' , svn_trunk => 'https://svn.code.sf.net/p/emailrelay/code/trunk' , } , local => { url_base => "https://sourceforge.net/projects/emailrelay" , download_url => "files/" , button_url => "files/" , button_img_src => 'download-button.png' , button_img_attributes => 'src="__src__"' , svn_trunk => 'https://svn.code.sf.net/p/emailrelay/code/trunk' , } ) ; my %cfg_host = defined($opt{host}) ? %{$cfg_hosts{$opt{host}}} : %{$cfg_hosts{sourceforge}} ; $cfg_host{button_url} =~ s/__base__/$cfg_host{url_base}/g ; $cfg_host{download_url} =~ s/__base__/$cfg_host{url_base}/g ; $cfg_host{download_url} =~ s/__version__/$cfg_upload_version/g ; $cfg_host{button_img_attributes} =~ s/__src__/$cfg_host{button_img_src}/g ; my $cfg_project_md = '[SourceForge]('.$cfg_host{url_base}.')' ; my $cfg_download_page_md = '[download page]('.$cfg_host{download_url}.')' ; my $cfg_svn_trunk = $cfg_host{svn_trunk} ; my $cfg_button_html = '' . 'Download E-MailRelay' ; my $cfg_button_marker = "i i i i i i i i i i i i i" ; my %config = ( INPUT => "$cfg_mainpage_md $cfg_pages_md" , HTML_OUTPUT => $cfg_output_dir , PROJECT_NAME => "E-MailRelay" , GENERATE_TREEVIEW => "YES" , TREEVIEW_WIDTH => 120 , DISABLE_INDEX => "YES" , HTML_COLORSTYLE_HUE => $colour{h} , HTML_COLORSTYLE_SAT => $colour{s} , HTML_COLORSTYLE_GAMMA => $colour{v} , HTML_EXTRA_STYLESHEET => $cfg_css , #PROJECT_LOGO => $cfg_icon , TOC_INCLUDE_HEADINGS => 3 , SHOW_FILES => "NO" , SEARCHENGINE => "NO" , #LAYOUT_FILE => $layout , HTML_HEADER => $cfg_header , GENERATE_LATEX => "NO" , QUIET => "YES" , ) ; sub make_config { my ( $fname ) = @_ ; my $fh_in = new FileHandle( "doxygen -g - |" ) or die ; my $fh = new FileHandle( $fname , "w" ) or die ; my $line_number = 0 ; while(<$fh_in>) { chomp( my $line = $_ ) ; if( $line_number++ == 0 && $line =~ m/^# Doxyfile/ ) { my ( $a , $b , $c ) = ( $line =~ m/# Doxyfile (\d+).?(\d*).?(\d*)/ ) ; $a = ( defined($a) && $a ne "" ) ? $a : 0 ; $b = ( defined($b) && $b ne "" ) ? $b : 0 ; $c = ( defined($c) && $c ne "" ) ? $c : 0 ; my $version = $a * 1000000 + $b * 1000 + $c ; if( $version < 1008014 ) { warn "warning: doxygen is too old: [$version]: please use 1.8.14 or later" ; } } for my $key ( keys %config ) { if( $line =~ m/^$key\s+/ ) { my $value = $config{$key} ; $line = "$key = $value" ; last ; } } print $fh $line , "\n" ; } $fh_in->close() or die ; $fh->close() or die ; } sub make_mainpage_md { my ( $fname_out ) = @_ ; my $fh = new FileHandle( $fname_out , "w" ) or die ; my $done_toc ; print $fh "\\mainpage E-MailRelay\n\n" ; for my $fname ( @cfg_mainpage ) { my $fh_in = new FileHandle( $fname , "r" ) or die "cannot open [$fname]" ; my @lines = () ; while(<$fh_in>) { chomp( my $line = $_ ) ; push @lines , $line ; } $fh_in->close() or die ; my $lines = scalar( @lines ) ; my $line_number = 0 ; while( $line_number < $lines ) { my $line = @lines[$line_number++] ; my $next_line = @lines[$line_number] ; if( $next_line =~ m/^=====+$/ ) { @lines[$line_number] = undef ; $line =~ s/E-MailRelay // ; ( my $id = basename($fname) . "_$line" ) =~ s/[- '?.]/_/g ; print $fh "\\section $id $line\n" ; if( ! $done_toc ) { print $fh "\n[TOC]\n" ; $done_toc = 1 ; } } elsif( $next_line =~ m/^-----+$/ ) { @lines[$line_number] = undef ; $line =~ s/^E-MailRelay // ; ( my $id = basename($fname) . "_$line" ) =~ s/[- '?.]/_/g ; print $fh "\\subsection $id $line\n" ; } elsif( $line =~ m/^______+$/ ) { @lines[$line_number] = undef ; # no footer text } elsif( defined($line) ) { $line =~ s/`%/`%%/g ; # only required for markdown-in-doxygen print $fh $line , "\n" ; } } } $fh->close() or die ; } sub make_pages_md { my ( $fname ) = @_ ; my $text = ' \page Download Download E-MailRelay is hosted on '.$cfg_project_md.' and you can get release tarballs from the project '.$cfg_download_page_md.'. The green button automatically downloads the latest release for a target environment that is deduced from your browser version.
'.$cfg_button_marker.'
\page Source Source You can get source code tarballs from the SourceForge '.$cfg_download_page_md.' or use subversion to get the latest code: svn co '.$cfg_svn_trunk.' emailrelay If the project is re-hosted it will be announced at [graemewalker.org](https://graemewalker.org/emailrelay). Browseable source code documentation generated by doxygen is available [here](doxygen/namespaces.html). \page Change_Log Change Log ' ; $text =~ s/\t/ /mg ; $text =~ s/^ //mg ; my $fh_out = new FileHandle( $fname , "w" ) or die ; print $fh_out $text ; { my $fh = new FileHandle( "changelog.md" , "r" ) or die ; my @lines = () ; while(<$fh>) { chomp( my $line = $_ ) ; push @lines , $line ; } $fh->close() or die ; my $lines = scalar( @lines ) ; my $line_number = 0 ; while( $line_number < $lines ) { my $line = @lines[$line_number++] ; my $next_line = @lines[$line_number] ; if( $next_line =~ m/^=====+$/ ) { @lines[$line_number] = undef ; } elsif( $next_line =~ m/^---+$/ ) { @lines[$line_number] = undef ; ( my $id = "changelog_$line" ) =~ s/[- '?.>]/_/g ; print $fh_out "\\section $id $line\n" ; } elsif( defined($line) ) { print $fh_out $line , "\n" ; } } } $fh_out->close() or die ; } sub make_header { my ( $header_out , $config_in ) = @_ ; my $header_tmp = ".header.$$.tmp" ; my $footer_tmp = ".footer.$$.tmp" ; my $layout_tmp = ".layout.$$.tmp" ; system( "doxygen -w html $header_tmp $footer_tmp $layout_tmp $config_in" ) ; unlink( $footer_tmp ) ; unlink( $layout_tmp ) ; my $fh_in = new FileHandle( $header_tmp , "r" ) or die ; my $fh = new FileHandle( "$header_out.tmp" , "w" ) or die ; my $active = 1 ; my $seen = 0 ; while(<$fh_in>) { chomp( my $line = $_ ) ; if( $line =~ m/BEGIN TITLEAREA/ ) { print $fh $line , "\n" ; print $fh "
\n" ; $seen = 1 ; $active = 0 ; } elsif( $line =~ m/END TITLEAREA/ ) { print $fh "
\n" ; print $fh $line , "\n" ; $active = 1 ; } elsif( $active ) { print $fh $line , "\n" ; } } die if ! $seen ; $fh_in->close() or die ; $fh->close() or die ; rename( "$header_out.tmp" , $header_out ) or die ; unlink( $header_tmp ) ; } sub run_doxygen { unlink( "$cfg_output_dir/doxygen/index.html" ) ; # in case symlinked system( "doxygen $cfg_doxygen_cfg" ) == 0 or die ; system( "cp ".(-d "graphics"?"graphics/":"")."*.png $cfg_output_dir/" ) == 0 or die ; unlink( "$cfg_output_dir/doxygen.png" ) ; } sub fixup_footers { my ( @files ) = @_ ; for my $path_in ( @files ) { my $path_tmp = ".$$.tmp" ; my $fh_in = new FileHandle( $path_in , "r" ) or die ; my $fh_out = new FileHandle( $path_tmp , "w" ) or die ; while(<$fh_in>) { chomp( my $line = $_ ) ; # brittle, but the customised footer feature does not work if( $line =~ m/; ; <$fh_in> ; <$fh_in> ; } print $fh_out $line , "\n" ; } $fh_in->close() or die ; $fh_out->close() or die ; rename( $path_tmp , $path_in ) or die ; } } sub fixup_mainpage { my $path_in = "$cfg_output_dir/index.html" ; # from mainpage.md my $path_tmp = ".$$.tmp" ; my $fh_in = new FileHandle( $path_in , "r" ) or die ; my $fh_out = new FileHandle( $path_tmp , "w" ) or die ; my $p = 0 ; my $done_meta ; while(<$fh_in>) { chomp( my $line = $_ ) ; # count paragraphs if( $line =~ m/^

/ ) { $p++ ; } # add meta tags if( $line =~ m;^\s*$; && !$done_meta ) { $line = $line . "\n" . join( "\n" , map { "" } keys %cfg_meta ) ; $done_meta = 1 ; } # fix the title if( $line eq "E-MailRelay: E-MailRelay" ) { $line = "E-MailRelay" ; } # add an icon if( $line =~ m;^

; ) { my $fname = basename($cfg_icon) ; $line =~ s%
([^<]*)(<.*)%
$1$2% ; } # remove redundant heading if( $line =~ m;

\s*$;p ) { $line = ${^PREMATCH} ; <$fh_in> ; } # add anchors and links for --foo if( $line =~ m;^
  • --[-a-z]+.*

    $; ) { $line =~ s;--([a-z][-a-z]+);--$1; ; $line =~ s/id="__([a-z][-a-z]+)-([-a-z]+)"/id="__$1_$2"/g ; $line =~ s/id="__([a-z][-a-z]+)-([-a-z]+)"/id="__$1_$2"/g ; $line =~ s/id="__([a-z][-a-z]+)-([-a-z]+)"/id="__$1_$2"/g ; $line =~ s;

    ;

    ; ; } elsif( $line =~ m/--[a-z][-a-z]+/ ) { $line =~ s;([^!])--([a-z][-a-z]+);$1--$2;g ; $line =~ s/href="#__([a-z][-a-z]+)-([-a-z]+)"/href="#__$1_$2"/g ; $line =~ s/href="#__([a-z][-a-z]+)-([-a-z]+)"/href="#__$1_$2"/g ; $line =~ s/href="#__([a-z][-a-z]+)-([-a-z]+)"/href="#__$1_$2"/g ; } print $fh_out $line , "\n" ; # add a big green button if( $line =~ m/^

    / && $p == 5 ) { print $fh_out "

    \n" ; print $fh_out $cfg_button_html ; print $fh_out "
    \n" ; } } $fh_in->close() or die ; $fh_out->close() or die ; rename( $path_tmp , $path_in ) or die ; } sub fixup { my ( $fname , $from , $to ) = @_ ; my $path_in = "$cfg_output_dir/$fname" ; my $path_tmp = ".$$.tmp" ; my $fh_in = new FileHandle( $path_in , "r" ) or die ; my $fh_out = new FileHandle( $path_tmp , "w" ) or die ; while(<$fh_in>) { chomp( my $line = $_ ) ; $line =~ s/$from/$to/g ; print $fh_out $line , "\n" ; } $fh_in->close() or die ; $fh_out->close() or die ; rename( $path_tmp , $path_in ) or die ; } sub copy_doxygen_tree { my $this_dir = dirname($0) ; die "no doxygen tree" if ( ! -d "$this_dir/doxygen" ) ; #if( -d "$this_dir/doxygen" ) { system( "cp -r $this_dir/doxygen $cfg_output_dir" ) ; if( -e "$cfg_output_dir/doxygen/index.html" ) { unlink( "$cfg_output_dir/doxygen/index.html" ) or die ; } system( "cd $cfg_output_dir/doxygen && ln -s ../Source.html index.html" ) == 0 or die ; } } sub copy_icon { system( "cp $cfg_icon $cfg_output_dir/" ) == 0 or die ; } sub create_robots_file { my $fh = new FileHandle( "$cfg_output_dir/robots.txt" , "w" ) or die ; print $fh 'User-agent: *' , "\n" ; print $fh 'Disallow: /doxygen/' , "\n" ; $fh->close() or die ; } sub cleanup { unlink( $cfg_header ) or die ; unlink( $cfg_doxygen_cfg ) or die ; unlink( $cfg_mainpage_md ) or die ; unlink( $cfg_pages_md ) or die ; } make_config( $cfg_doxygen_cfg ) ; make_mainpage_md( $cfg_mainpage_md ) ; make_pages_md( $cfg_pages_md ) ; make_header( $cfg_header , $cfg_doxygen_cfg ) ; run_doxygen() ; fixup_mainpage() ; fixup_footers( glob("$cfg_output_dir/*.html") ) ; fixup( "Download.html" , $cfg_button_marker , $cfg_button_html ) ; copy_doxygen_tree() ; copy_icon() ; unlink( "$cfg_output_dir/pages.html" ) ; create_robots_file() ; cleanup() ; print "success\n" ;