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.";
}