2000-10-19  悪魔の公開メール

「最近の出来事」で使っているスクリプトです。主な機能を挙げますと, 「時系列に並べられたHTML文章に対して,隣接するページを双方向に行き来するためのハイパーリンクを設置する。」,「『目次ページ』を作成する。」などです。このスクリプトは「最近の出来事」の度重なる仕様変更,機能拡張に耐えてきました。私が思っている以上に柔軟性が高いのかもしれません。

ところで,このスクリプトは一般化されておりませんので(また導入方法を記した文章もありません),ヨソのサイトに適用するのは無理です。結局,自分で一から作るのが近道だと思います。

reportcreater.pl

#!/usr/bin/perl

$_inputpath = "z:\\~yumi-ii\\master";
$_outputpath = "z:\\~yumi-ii\\area_murono\\htmlfiles\\diary";
$_contentpath = "z:\\~yumi-ii\\area_murono\\htmlfiles\\diary\\00index.html";

$email_address = q!murono@mtc.biglobe.ne.jp!;

%registry = (
  email_address => $email_address,
  sitename => q!yumi-ii/area_murono!,
  contentname => q!最近の出来事!,
  contenttitle => q!もくじ!,
  
  copyright => q!Copyright (c) MURONO 1997-2000!,
  content_type => q!HTML4.0, CSS1, SHIFT-JIS!,

  content => q!00index.html!,
  parent => q!../index.html!,
  http_location => q!www2s.biglobe.ne.jp/~yumi-ii/area_murono/htmlfiles/diary!,

  src => {
    chtml_exchanger => q!http://www.sjk.co.jp/c/w.exe!,
  },

  htmltag => {
    doctype => q#<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">#,
    meta => {
      content-type => q!<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">!,
    },
    link_rel => {
      navigation => q!<link rel=stylesheet href=".../styles/style-navi@2000090290.css" type="text/css">!,
      article => q!<link rel=stylesheet href=".../styles/style-content@2000090291.css" type="text/css">!,
      content => q!<link rel=stylesheet href=".../styles/style-index@2000090292.css" type="text/css">!,
      mailto => qq!<link rev=made href="mailto:$email_address">!,
    },
    script => {
      secure => q!<script language="JavaScript1.1" src=".../scripts/js-@2000090240.js"></script>!,
    },
    img => {
      imode => q!<img src=".../icons/img-imode@2000090110.gif" alt="*" width=16 height=16>!,
      home => q!<img src=".../icons/img-chpath@2000090113.gif" alt="*" width=16 height=16>!, 
      prev => q!<img src=".../icons/img-prev@2000090112.gif" alt="*" width=16 height=16>!,
      next => q!<img src=".../icons/img-next@2000090111.gif" alt="*" width=16 height=16>!,
    },
    email => qq!<a href="mailto:${email_address}">${email_address}</a>!,
  },

  const => {
    imode => q!iモード!,
    home => q!ホーム!,
    content => q!目次!,
    prev => q!前のページ!,
    next => q!次のページ!,
    accesskey => { # アクセスキー
      imode => q!accesskey="I"!,
      home => q!accesskey="0"!,
      content => q!accesskey="0"!,
      prev => q!accesskey="7"!,
      next => q!accesskey="9"!,
    },
    mnemonic => { # アクセスニーモニック
      imode => q!!, # なし
      home => q!(0)!,
      content => q!(0)!,
      prev => q!(7)!,
      next => q!(9)!,
    },
  },
);

# エイリアス
my $tag = $registry{htmltag};
my $img = $registry{htmltag}->{img};
my $mnemonic = $registry{const}->{mnemonic};
my $accesskey = $registry{const}->{accesskey};
my $str = $registry{const};
####

# ページ上部出力
sub outputHeader {
  my($suffix) = @_;
  print qq!$tag->{doctype}\n!;
  print qq!<html>\n!;
  print qq!<head>\n!;
  print qq!\t$tag->{meta}->{content-type}\n!;
  print qq!\t$tag->{link_rel}->{navigation}\n!;
  print qq!\t$tag->{link_rel}->{article}\n!;
  print qq!\t$tag->{link_rel}->{mailto}\n!;
  print qq!\t$tag->{script}->{secure}\n!;
  print qq!\t<title>$registry{sitename} $registry{contentname} ${suffix}</title>\n!;
  print qq!</head>\n!;
}

# ページ下部出力
sub outputFooter {
  my($suffix) = @_;
  print qq!<hr>\n!;
  print qq!<address>$registry{sitename} $registry{contentname} ${suffix}, !; 
  print qq!$registry{copyright}, $registry{htmltag}->{email}, $registry{content_type}!;
  print qq!</addres>\n!;
  print qq!</body>\n!;
  print qq!</html>\n!;
}

# ナヴィゲーションリンク出力
sub outputNavigationLink {
  my($align, $currentFilename, $prevFilename, $nextFilename) = @_;

  my $src_exchanger = qq!$registry{src}->{chtml_exchanger}?y=$registry{http_location}${currentFilename}!;
  my $src_prev = $prevFilename;
  my $src_next = $nextFilename;

  #### output ####
  print "<div class=navi>\n\t";

  if ($align eq "top") {
    print qq!<a href="$src_exchanger" $accesskey->{imode}>$img->{imode} $str->{imode}</a>!;
    print " ";
  }

  print qq!<a href="$registry{parent}" title="$registry{sitename}" !;
  print qq!onclick="gotoHome(this)">$img->{home} $str->{home}</a> / !;
  print qq!<a href="$registry{content}" title="$registry{contentname} $registry{contenttitle}" !;
  print qq!$accesskey->{content}> $img->{content} $registry{contenttitle} $mnemonic->{content}</a> !;

  my $s;
  $s = qq!$img->{prev} $str->{prev} $mnemonic->{prev}!;
  print $src_prev ? qq!<a href="$src_prev" $accesskey->{prev}>$s</a>! : $s;
  print " ";

  $s = qq!$img->{next} $str->{next} $mnemonic->{next}!;
  print $src_next ? qq!<a href="$src_next" $accesskey->{next}>$s</a>! : $s;
  print "\n</div>";
  print "\n";
}

# もくじページ出力
sub outputContents {
  $outputNavigationLink = sub { # 無名サブルーチン
    my($align) = @_;
    my $src_exchanger = qq!$registry{src}->{chtml_exchanger}?y=$registry{http_location}/$registry{content}!;
    #### output ####
    print "<div class=navi>\n";
    print "\t";
    if ($align eq "top") {
      print qq!<a href="$src_exchanger" $accesskey->{imode}>$img->{imode} $str->{imode}</a>!;
      print " ";
    }
    print qq!<a href="$registry{parent}" title="$registry{sitename}" onclick="gotoHome(this)" $accesskey->{home}>!;
    print qq!$img->{home} $str->{home} $mnemonic->{home}</a>!;
    print " "; 
    print qq!$img->{prev} $str->{prev} $mnemonic->{prev}!;
    print " ";
    print qq!$img->{next} $str->{next} $mnemonic->{next}!;
    print "\n</div>";
    print "\n";
  };

  my($path, @itemPropList) = @_;
  foreach (@itemPropList) {
    push (@itemList, qq!\t<li>$_->{htmlLink}\n!);
  }
  ####
  open(INDEX, ">$_contentpath");
  select INDEX;

  print <<EOB;
$tag->{doctype}
<html>
<head>
\t$tag->{meta}->{content-type}
\t$tag->{link_rel}->{navigation}
\t$tag->{link_rel}->{content}
\t$tag->{link_rel}->{mailto}
\t$tag->{script}->{secure}
\t<title>$registry{sitename} $registry{contentname} $registry{contenttitle}</title>
</head>
<body>
EOB
  &$outputNavigationLink("top");
  print <<EOB;
<hr>
<h1>最近の出来事</h1>
<p>ぼくの日記のようなものです。痛くないハズですが,痛くても知りません。
</p>
EOB
  print "<ul>\n";
  foreach (reverse(sort(@itemList))) {
    print;
  }
  print "</ul>\n";
  print "<hr>\n";
  &$outputNavigationLink("buttom");
  outputFooter("もくじ 1997-2000");
  close(INDEX);
}

main: {
  opendir(DIR, $_inputpath);
  my @dir = readdir(DIR);
  closedir(DIR);

  my @itemPropList;
  # ファイルリスト取得
  foreach $currentFilename (sort(@dir)) {
    next if ($currentFilename !~ /^(html-)|(dhtml-)/);

    open(HTMLFILE, "<$_inputpath\\$currentFilename");
    @data = <HTMLFILE>;
    close(HTMLFILE);

    my $subject, $numOfArticle;
    foreach (@data) {
      if (!$title && /^<h2><a name="(\d{10})">(.*)<\/a>/) {
        $numOfArticle = $2;
      }
      if (!$subject && /^<h3>(.*)<\/h3>/) {
        $subject = $1;
      }
    }
    $refer = { # 無名ハッシュテーブルインスタンスの参照
      filename => $currentFilename,
      numberOfArticle => $numOfArticle,
      subject => $subject,
      htmlLink => qq!<a href="./$currentFilename">$numOfArticle 「$subject」</a>!,
    };
    push(@itemPropList, $refer);
  }

  my @updated;
  # 更新チェック
  for ($index = 0; $index <= $#itemPropList; $index ++) {
    my $currentFilename = @itemPropList[$index]->{filename};
    ####  
    my $inputFilename = "$_inputpath\\$currentFilename";
    my $outputFilename = "$_outputpath\\$currentFilename";
    ####
    # 出力先ファイルが存在しない,あるいはマスターが更新されているとき
    if (!-e $outputFilename or (-M $inputFilename < -M $outputFilename)) {
      # NOV 17, 1999
      # ファイルテスト演算子 -M $file は,実行開始時刻を基準として,ファイルが
      # 修正されてから経過した日数を返す。値が大きいほど時刻の古いファイルである。
      @updated[$index] = 1;
      @updated[$index - 1] = 1 if ($index > 0);  #リンク先も更新対象
      @updated[$index + 1] = 1 if ($index < $#itemPropList);
    }
  }

  # 本文HTMLファイル出力
  for ($index = 0; $index <= $#itemPropList; $index ++) {
    # @updated[$index] が偽であればこのファイルを更新しない(真であれば更新する)
    next if (!@updated[$index]);

    $_ = @itemPropList[$index];
    my $currentFilename = $_->{filename};
    my $numberOfArticle = $_->{numberOfArticle};
    my $subject = $_->{subject};
    my $htmlLink = $_->{htmlLink};

    my $inputFilename = qq!$_inputpath\\$currentFilename!;
    my $outputFilename = qq!$_outputpath\\$currentFilename!;

    my $prevItemProp = @itemPropList[$index - 1] if ($index > 0);
    my $nextItemProp = @itemPropList[$index + 1] if ($index < $#itemPropList);
  
    # ファイルオープン
    open(OUTPUT, ">$outputFilename");
    select OUTPUT;
    write: {
      # ヘッダ出力
      outputHeader(qq!$numberOfArticle $subject!);
      print "<body>\n";
      outputNavigationLink("top", $currentFilename, $prevItemProp->{filename}, $nextItemProp->{filename});
      print "<hr>\n";

      # 本文出力
      open(INPUT, "<$inputFilename");
      print <INPUT>;
      close(INPUT);

      # フッタ出力
      print "<hr>\n";
      outputNavigationLink("buttom", $currentFilename, $prevItemProp->{filename}, $nextItemProp->{filename});
      outputFooter(qq!$numberOfArticle $subject!);
    }
    close(OUTPUT);

    select STDOUT;
    print "updated. = $inputFilename\n";
  }

  # もくじファイル出力
  outputContents($_outputpath, @itemPropList);
  print "complete.";
}