| 1 | package App::Chalow::Template; |
|---|
| 2 | use strict; |
|---|
| 3 | use warnings; |
|---|
| 4 | |
|---|
| 5 | use Template; |
|---|
| 6 | |
|---|
| 7 | # 超適当 |
|---|
| 8 | use FindBin; |
|---|
| 9 | my $assets_dir = $FindBin::Bin . 'assets'; |
|---|
| 10 | my $template = Template->new({ INCLUDE_PATH => "$assets_dir/template" }); |
|---|
| 11 | |
|---|
| 12 | ### インデックスページ(index.html)を作る |
|---|
| 13 | sub index { |
|---|
| 14 | my($class, $cl, $opt_topn, $month_page, $changelog_name, $changelog_description, $css_file, $what_time_is_it_now, $signature, $month_page_list, $latest_item_list, $category_list, $rss_filename, $outputdir, $replace_once, $update_by_size, $utf8_mode, $quiet_mode, |
|---|
| 15 | $calendar_style, |
|---|
| 16 | $index_page_template |
|---|
| 17 | ) = @_; |
|---|
| 18 | |
|---|
| 19 | #index_page_template |
|---|
| 20 | |
|---|
| 21 | ### 最近の何日かだけインデックスページに載せるための処理 |
|---|
| 22 | my @recent = (reverse sort keys %{$cl->{all}})[0..$opt_topn]; |
|---|
| 23 | |
|---|
| 24 | my @top_n_entries; |
|---|
| 25 | |
|---|
| 26 | for (my $i = 0; $i < $opt_topn and $recent[$i]; $i++) { |
|---|
| 27 | my $ymd = $recent[$i]; |
|---|
| 28 | my ($ym, $d) = ($ymd =~ /^(\d{4}-\d\d)-(\d\d)$/); |
|---|
| 29 | # $top_n_str .= $month_page->{$ym}{$ymd}{str}; |
|---|
| 30 | push @top_n_entries, {content => $month_page->{$ym}{$ymd}{str}}; |
|---|
| 31 | } |
|---|
| 32 | my ($ymd, $ym, $d) = ($recent[0] =~ /^((\d{4}-\d\d)-(\d\d))$/); |
|---|
| 33 | |
|---|
| 34 | # 日付リンク一覧 |
|---|
| 35 | my $day_list = make_day_list_str($ym, $calendar_style, $cl); |
|---|
| 36 | |
|---|
| 37 | ### ページの組み上げ |
|---|
| 38 | my $ostr; |
|---|
| 39 | $template->process('index.tt', { |
|---|
| 40 | cl_name => $changelog_name, |
|---|
| 41 | changelog_description => $changelog_description, |
|---|
| 42 | css_file => $css_file, |
|---|
| 43 | lastupdate => $what_time_is_it_now, |
|---|
| 44 | signature => $signature, |
|---|
| 45 | ymd => $ymd, |
|---|
| 46 | ym => $ym, |
|---|
| 47 | ndays => $opt_topn, |
|---|
| 48 | day_list => $day_list, |
|---|
| 49 | month_page_list => $month_page_list, |
|---|
| 50 | latest_item_list => $latest_item_list, |
|---|
| 51 | category_list => $category_list, |
|---|
| 52 | rss_file => $rss_filename, |
|---|
| 53 | entries => \@top_n_entries, |
|---|
| 54 | }, \$ostr); |
|---|
| 55 | |
|---|
| 56 | =pod |
|---|
| 57 | |
|---|
| 58 | my $t = HTML::Template->new(scalarref => \$index_page_template, |
|---|
| 59 | loop_context_vars => 1, |
|---|
| 60 | die_on_bad_params => 0); |
|---|
| 61 | $t->param(cl_name => $changelog_name); |
|---|
| 62 | $t->param(changelog_description => $changelog_description); |
|---|
| 63 | $t->param(css_file => $css_file); |
|---|
| 64 | $t->param(lastupdate => $what_time_is_it_now); |
|---|
| 65 | $t->param(signature => $signature); |
|---|
| 66 | |
|---|
| 67 | $t->param(ymd => $ymd); # 最新エントリの日付 |
|---|
| 68 | $t->param(ym => $ym); # 最新エントリの月 |
|---|
| 69 | $t->param(ndays => $opt_topn); |
|---|
| 70 | $t->param(day_list => $day_list); |
|---|
| 71 | $t->param(month_page_list => $month_page_list); |
|---|
| 72 | $t->param(latest_item_list => $latest_item_list); |
|---|
| 73 | $t->param(category_list => $category_list); |
|---|
| 74 | $t->param(rss_file => $rss_filename); # 050821 |
|---|
| 75 | $t->param(entries => \@top_n_entries); |
|---|
| 76 | |
|---|
| 77 | my $ostr = $t->output(); |
|---|
| 78 | |
|---|
| 79 | =cut |
|---|
| 80 | |
|---|
| 81 | $ostr ||= ''; |
|---|
| 82 | output_to_file("$outputdir/index.html", \$ostr, |
|---|
| 83 | $replace_once, |
|---|
| 84 | $update_by_size, |
|---|
| 85 | $utf8_mode, |
|---|
| 86 | $quiet_mode, |
|---|
| 87 | ); |
|---|
| 88 | } |
|---|
| 89 | |
|---|
| 90 | |
|---|
| 91 | sub item { |
|---|
| 92 | my($class, $cl, $opt_topn, $month_page, $changelog_name, $changelog_description, $css_file, $what_time_is_it_now, $signature, $month_page_list, $latest_item_list, $category_list, $rss_filename, $outputdir, $replace_once, $update_by_size, $utf8_mode, $quiet_mode, |
|---|
| 93 | $clog_url, |
|---|
| 94 | $calendar_style, |
|---|
| 95 | $output_cat_pages, |
|---|
| 96 | $cat_page_cgi, |
|---|
| 97 | $inside_ref, |
|---|
| 98 | $page_mode, $day_page_mode, |
|---|
| 99 | $item_page_template |
|---|
| 100 | ) = @_; |
|---|
| 101 | |
|---|
| 102 | my @day_list = reverse sort keys %{$cl->{all}}; |
|---|
| 103 | |
|---|
| 104 | for (my $idx = 0; $idx < @day_list; $idx++) { |
|---|
| 105 | my ($ymd, $ym) = ($day_list[$idx] =~ /^((\d+-\d+)-\d+)/); |
|---|
| 106 | my $ent = $cl->{all}->{$ymd}; |
|---|
| 107 | |
|---|
| 108 | for (my $i = $ent->{curid}; $i >= 1; $i--) { |
|---|
| 109 | my $item = $ent->{$i}; |
|---|
| 110 | my $ymdi = "$ymd-$i"; |
|---|
| 111 | |
|---|
| 112 | ### カテゴリ |
|---|
| 113 | my $catstr = make_cat_link_html($ent->{$i}{cat}, $output_cat_pages, $cat_page_cgi); |
|---|
| 114 | |
|---|
| 115 | ### 日付リンクによるリファラー |
|---|
| 116 | my @inside_refs = get_inside_ref("$ymdi", $inside_ref); |
|---|
| 117 | |
|---|
| 118 | ### item の基礎情報 |
|---|
| 119 | my $item_url = datestr2url("$ymdi", $page_mode, $day_page_mode); |
|---|
| 120 | my $item_ymdi = $ymdi; |
|---|
| 121 | my $item_id = $ymdi; $item_id =~ s/-//g; # Ex. "200309241" |
|---|
| 122 | |
|---|
| 123 | # 前後のページ |
|---|
| 124 | my $ymdi_before; |
|---|
| 125 | my $ymdi_after; |
|---|
| 126 | if ($i > 1) { |
|---|
| 127 | $ymdi_before = $ymd."-".($i-1); |
|---|
| 128 | } elsif ($idx < @day_list - 1) { |
|---|
| 129 | my $day_b = $day_list[$idx + 1]; |
|---|
| 130 | $ymdi_before = $day_b."-".$cl->{all}->{$day_b}{curid}; |
|---|
| 131 | } |
|---|
| 132 | if ($i != $ent->{curid}) { |
|---|
| 133 | $ymdi_after = $ymd."-".($i+1); |
|---|
| 134 | } elsif ($idx > 0) { |
|---|
| 135 | my $day_a = $day_list[$idx - 1]; |
|---|
| 136 | $ymdi_after = $day_a."-1"; |
|---|
| 137 | } |
|---|
| 138 | |
|---|
| 139 | ### ページの組み上げ |
|---|
| 140 | my $ccc = $item->{c}; $ccc =~ s!^<br>!!g;# ad hoc |
|---|
| 141 | my $ostr; |
|---|
| 142 | $template->process('item.tt', { |
|---|
| 143 | cl_name => $changelog_name, |
|---|
| 144 | changelog_description => $changelog_description, |
|---|
| 145 | css_file => $css_file, |
|---|
| 146 | lastupdate => $what_time_is_it_now, |
|---|
| 147 | signature => $signature, |
|---|
| 148 | ymd => $ymd, |
|---|
| 149 | ym => $ym, |
|---|
| 150 | |
|---|
| 151 | month_page_list => $month_page_list, |
|---|
| 152 | latest_item_list => $latest_item_list, |
|---|
| 153 | category_list => $category_list, |
|---|
| 154 | |
|---|
| 155 | back => $ymdi_before, |
|---|
| 156 | next => $ymdi_after, |
|---|
| 157 | |
|---|
| 158 | content => $ccc, |
|---|
| 159 | header_text => $item->{ho}, |
|---|
| 160 | cat => $catstr, |
|---|
| 161 | author => $item->{a}, |
|---|
| 162 | referrer => join(" ", @inside_refs), |
|---|
| 163 | id => $item_id, |
|---|
| 164 | ymdi => $item_ymdi, |
|---|
| 165 | url => $item_url, |
|---|
| 166 | rss_file => $rss_filename, |
|---|
| 167 | title => $ent->{$i}->{ho}, |
|---|
| 168 | clog_url => $clog_url, |
|---|
| 169 | }, \$ostr); |
|---|
| 170 | |
|---|
| 171 | |
|---|
| 172 | =pod |
|---|
| 173 | |
|---|
| 174 | my $t = HTML::Template->new(scalarref => \$item_page_template, |
|---|
| 175 | loop_context_vars => 1, |
|---|
| 176 | die_on_bad_params => 0); |
|---|
| 177 | |
|---|
| 178 | $t->param(cl_name => $changelog_name); |
|---|
| 179 | $t->param(changelog_description => $changelog_description); |
|---|
| 180 | $t->param(css_file => $css_file); |
|---|
| 181 | $t->param(lastupdate => $what_time_is_it_now); |
|---|
| 182 | $t->param(signature => $signature); |
|---|
| 183 | |
|---|
| 184 | $t->param(ymd => $ymd); |
|---|
| 185 | $t->param(ym => $ym); |
|---|
| 186 | |
|---|
| 187 | $t->param(month_page_list => $month_page_list); |
|---|
| 188 | $t->param(latest_item_list => $latest_item_list); |
|---|
| 189 | $t->param(category_list => $category_list); |
|---|
| 190 | $t->param(back => $ymdi_before); |
|---|
| 191 | $t->param(next => $ymdi_after); |
|---|
| 192 | |
|---|
| 193 | my $ccc = $item->{c}; $ccc =~ s!^<br>!!g;# ad hoc |
|---|
| 194 | $t->param(content => $ccc); |
|---|
| 195 | $t->param(header_text => $item->{ho}); |
|---|
| 196 | $t->param(header => $item->{h}); |
|---|
| 197 | $t->param(cat => $catstr); |
|---|
| 198 | $t->param(author => $item->{a}); |
|---|
| 199 | $t->param(referrer => join(" ", @inside_refs)); |
|---|
| 200 | $t->param(id => $item_id); # 200101011 |
|---|
| 201 | $t->param(ymdi => $item_ymdi); # 2001-01-01-1 |
|---|
| 202 | $t->param(url => $item_url); # 2001-01-01-1.html |
|---|
| 203 | $t->param(rss_file => $rss_filename); # 050821 |
|---|
| 204 | $t->param(title => $ent->{$i}->{ho}); |
|---|
| 205 | $t->param(clog_url => $clog_url); |
|---|
| 206 | |
|---|
| 207 | my $ostr = $t->output(); |
|---|
| 208 | |
|---|
| 209 | =cut |
|---|
| 210 | |
|---|
| 211 | ### ファイルに出力 |
|---|
| 212 | $ostr ||= ''; |
|---|
| 213 | output_to_file("$outputdir/$ymdi.html", \$ostr, |
|---|
| 214 | $replace_once, |
|---|
| 215 | $update_by_size, |
|---|
| 216 | $utf8_mode, |
|---|
| 217 | $quiet_mode, |
|---|
| 218 | ); |
|---|
| 219 | } |
|---|
| 220 | } |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | |
|---|
| 224 | ### 日付リンク一覧を作成 - 文字列を返す |
|---|
| 225 | sub make_day_list_str { |
|---|
| 226 | my ($ym, $calendar_style, $cl) = @_; |
|---|
| 227 | if ($calendar_style == 1) { |
|---|
| 228 | return make_calendar_table($ym, make_day_list($ym, $cl)); |
|---|
| 229 | } else { |
|---|
| 230 | return join(" ", @{make_day_list($ym)}); |
|---|
| 231 | } |
|---|
| 232 | } |
|---|
| 233 | |
|---|
| 234 | # 日付リンク一覧を作成 - リストへのポインタを返す |
|---|
| 235 | my %daylist; |
|---|
| 236 | sub make_day_list { |
|---|
| 237 | my ($ym, $cl) = @_; |
|---|
| 238 | my $lday = get_last_day_of_month($ym); |
|---|
| 239 | return $daylist{$ym} if (defined $daylist{$ym}); # cache |
|---|
| 240 | for (my $d = 1; $d <= $lday; $d++) { |
|---|
| 241 | my $day = ($d < 10) ? "0".$d : $d; |
|---|
| 242 | if (defined $cl->{all}->{$ym."-".$day}) { |
|---|
| 243 | my $day_url = datestr2url($ym."-".$day); |
|---|
| 244 | push @{$daylist{$ym}}, qq(<a href="$day_url">$day</a>); |
|---|
| 245 | } else { |
|---|
| 246 | push @{$daylist{$ym}}, $day; |
|---|
| 247 | } |
|---|
| 248 | } |
|---|
| 249 | return $daylist{$ym}; |
|---|
| 250 | } |
|---|
| 251 | |
|---|
| 252 | ### 年月を入力としその月の最終日を出力する関数 since 030105 |
|---|
| 253 | # EXAMPLES |
|---|
| 254 | # get_last_day_of_month(12, 2002), get_last_day_of_month("2002-12") |
|---|
| 255 | sub get_last_day_of_month { |
|---|
| 256 | my ($m, $y) = @_; |
|---|
| 257 | ($y, $m) = split("-", $m) unless (defined $y); |
|---|
| 258 | return (31, ((($y % 4 == 0) and ($y % 100)) or ($y % 400 == 0)) ? 29 : 28, |
|---|
| 259 | 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[$m - 1]; |
|---|
| 260 | } |
|---|
| 261 | |
|---|
| 262 | |
|---|
| 263 | ### 指定されたファイルへ文字列を出力 |
|---|
| 264 | sub output_to_file { |
|---|
| 265 | my ($fname, $contp, |
|---|
| 266 | $replace_once, |
|---|
| 267 | $update_by_size, |
|---|
| 268 | $utf8_mode, |
|---|
| 269 | $quiet_mode, |
|---|
| 270 | ) = @_; |
|---|
| 271 | $$contp =~ s/<!-- ReplaceOnce -->/$replace_once/; |
|---|
| 272 | |
|---|
| 273 | if (($update_by_size || 0 == 1) && -s $fname == length($$contp)) { |
|---|
| 274 | return; |
|---|
| 275 | } |
|---|
| 276 | |
|---|
| 277 | if ($utf8_mode) { # ad hoc 050821 |
|---|
| 278 | $$contp =~ s/;charset=EUC-JP">/;charset=UTF-8">/; |
|---|
| 279 | } |
|---|
| 280 | |
|---|
| 281 | print "output to \"$fname\"\n" if (!defined $quiet_mode); |
|---|
| 282 | open(F, "> $fname") || die "$fname: $!\n"; |
|---|
| 283 | binmode(F); |
|---|
| 284 | print F $$contp; |
|---|
| 285 | close(F); |
|---|
| 286 | } |
|---|
| 287 | |
|---|
| 288 | ### make category link(anchor) string for item header |
|---|
| 289 | sub make_cat_link_html { |
|---|
| 290 | my ($catp, $output_cat_pages, $cat_page_cgi) = @_; |
|---|
| 291 | my $catstr; |
|---|
| 292 | if (defined $catp) { |
|---|
| 293 | if ($output_cat_pages) { |
|---|
| 294 | $catstr = |
|---|
| 295 | join("", map |
|---|
| 296 | {"[<a href=\"".get_category_filename($_)."\">$_</a>]"} |
|---|
| 297 | @$catp); |
|---|
| 298 | } elsif ($cat_page_cgi eq "") { |
|---|
| 299 | $catstr = join("", map {"[".$_."]"} @$catp); |
|---|
| 300 | } else { |
|---|
| 301 | $catstr = |
|---|
| 302 | join("", map |
|---|
| 303 | {my $tmp = $cat_page_cgi; |
|---|
| 304 | $tmp =~ s/%%CAT%%/urlencode($_)/ge; |
|---|
| 305 | "[<a href=\"$tmp\">$_</a>]"} |
|---|
| 306 | @$catp); |
|---|
| 307 | } |
|---|
| 308 | |
|---|
| 309 | } |
|---|
| 310 | return $catstr; |
|---|
| 311 | } |
|---|
| 312 | |
|---|
| 313 | ### inside referrer のリンク作成 |
|---|
| 314 | sub get_inside_ref { |
|---|
| 315 | my ($id, $inside_ref) = @_; |
|---|
| 316 | if (defined $inside_ref->{"$id"}) { |
|---|
| 317 | return map {datestr2anchor("[".$_."]")} |
|---|
| 318 | (sort {$b cmp $a} keys %{$inside_ref->{"$id"}}); |
|---|
| 319 | } |
|---|
| 320 | return (); |
|---|
| 321 | } |
|---|
| 322 | |
|---|
| 323 | sub datestr2url { |
|---|
| 324 | my ($d, $page_mode, $day_page_mode) = @_; |
|---|
| 325 | if ($page_mode == 2) { # アイテムモード |
|---|
| 326 | $d =~ s!(\d{4}-\d\d-\d\d(-\d+)?)!$1.html!; |
|---|
| 327 | } elsif ($day_page_mode or $page_mode ==1) { # 日モード |
|---|
| 328 | unless ($d =~ s!((\d{4}-\d\d-\d\d)-\d+)!$2.html\#$1!) { |
|---|
| 329 | $d =~ s!(\d{4}-\d\d-\d\d)!$1.html!; |
|---|
| 330 | } |
|---|
| 331 | } else { # 月モード |
|---|
| 332 | $d =~ s!((\d{4}-\d\d)-\d\d(-\d+)?)!$2.html#$1!; |
|---|
| 333 | } |
|---|
| 334 | return $d; |
|---|
| 335 | } |
|---|
| 336 | |
|---|
| 337 | 1; |
|---|