use warnings;
use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
use Time::Local;
+use POSIX;
-my %cache;
-my %linkcache;
-my @now=localtime();
+my $time=time;
+my @now=localtime($time);
-sub import { #{{{
+sub import {
+ hook(type => "getsetup", id => "calendar", call => \&getsetup);
+ hook(type => "needsbuild", id => "calendar", call => \&needsbuild);
hook(type => "preprocess", id => "calendar", call => \&preprocess);
-} #}}}
+}
+
+sub getsetup () {
+ return
+ plugin => {
+ safe => 1,
+ rebuild => undef,
+ },
+ archivebase => {
+ type => "string",
+ example => "archives",
+ description => "base of the archives hierarchy",
+ safe => 1,
+ rebuild => 1,
+ },
+}
-sub is_leap_year (@) { #{{
+sub is_leap_year (@) {
my %params=@_;
return ($params{year} % 4 == 0 && (($params{year} % 100 != 0) || $params{year} % 400 == 0));
-} #}}}
+}
-sub month_days { #{{{
+sub month_days {
my %params=@_;
my $days_in_month = (31,28,31,30,31,30,31,31,30,31,30,31)[$params{month}-1];
if ($params{month} == 2 && is_leap_year(%params)) {
$days_in_month++;
}
return $days_in_month;
-} #}}}
+}
-sub format_month (@) { #{{{
+sub format_month (@) {
my %params=@_;
my $pagespec = $params{pages};
my $pyear = $params{pyear};
my $nyear = $params{nyear};
+ my %linkcache;
+ foreach my $p (pagespec_match_list($params{page}, $params{pagespec},
+ # add presence dependencies to update
+ # month calendar when pages are added/removed
+ deptype => deptype("presence"))) {
+ my $mtime = $IkiWiki::pagectime{$p};
+ my $src = $pagesources{$p};
+ my @date = localtime($mtime);
+ my $mday = $date[3];
+ my $month = $date[4] + 1;
+ my $year = $date[5] + 1900;
+ my $mtag = sprintf("%02d", $month);
+
+ # Only one posting per day is being linked to.
+ $linkcache{"$year/$mtag/$mday"} = "$src";
+ }
+
my @list;
my $calendar="\n";
# Calculate URL's for monthly archives.
my ($url, $purl, $nurl)=("$monthname",'','');
- if (exists $cache{$pagespec}{"$year/$month"}) {
+ if (exists $pagesources{"$archivebase/$year/$month"}) {
$url = htmllink($params{page}, $params{destpage},
"$archivebase/$year/".sprintf("%02d", $month),
linktext => " $monthname ");
}
- add_depends($params{page}, "$archivebase/$year/".sprintf("%02d", $month));
- if (exists $cache{$pagespec}{"$pyear/$pmonth"}) {
+ add_depends($params{page}, "$archivebase/$year/".sprintf("%02d", $month),
+ deptype("presence"));
+ if (exists $pagesources{"$archivebase/$pyear/$pmonth"}) {
$purl = htmllink($params{page}, $params{destpage},
"$archivebase/$pyear/" . sprintf("%02d", $pmonth),
linktext => " $pmonthname ");
}
- add_depends($params{page}, "$archivebase/$pyear/".sprintf("%02d", $pmonth));
- if (exists $cache{$pagespec}{"$nyear/$nmonth"}) {
+ add_depends($params{page}, "$archivebase/$pyear/".sprintf("%02d", $pmonth),
+ deptype("presence"));
+ if (exists $pagesources{"$archivebase/$nyear/$nmonth"}) {
$nurl = htmllink($params{page}, $params{destpage},
"$archivebase/$nyear/" . sprintf("%02d", $nmonth),
linktext => " $nmonthname ");
}
- add_depends($params{page}, "$archivebase/$nyear/".sprintf("%02d", $nmonth));
+ add_depends($params{page}, "$archivebase/$nyear/".sprintf("%02d", $nmonth),
+ deptype("presence"));
# Start producing the month calendar
$calendar=<<EOF;
my $tag;
my $mtag = sprintf("%02d", $month);
- if (defined $cache{$pagespec}{"$year/$mtag/$day"}) {
+ if (defined $pagesources{"$archivebase/$year/$mtag/$day"}) {
if ($day == $today) {
$tag='month-calendar-day-this-day';
}
</table>
EOF
- # Add dependencies to update the calendar whenever pages
- # matching the pagespec are added or removed.
- add_depends($params{page}, $params{pages});
- # Explicitly add all currently linked pages as dependencies, so
- # that if they are removed, the calendar will be sure to be updated.
- add_depends($params{page}, join(" or ", @list));
-
return $calendar;
}
# calculate URL's for previous and next years
my ($url, $purl, $nurl)=("$year",'','');
- if (exists $cache{$pagespec}{"$year"}) {
+ if (exists $pagesources{"$archivebase/$year"}) {
$url = htmllink($params{page}, $params{destpage},
"$archivebase/$year",
linktext => "$year");
}
- add_depends($params{page}, "$archivebase/$year");
- if (exists $cache{$pagespec}{"$pyear"}) {
+ add_depends($params{page}, "$archivebase/$year", deptype("presence"));
+ if (exists $pagesources{"$archivebase/$pyear"}) {
$purl = htmllink($params{page}, $params{destpage},
"$archivebase/$pyear",
linktext => "\←");
}
- add_depends($params{page}, "$archivebase/$pyear");
- if (exists $cache{$pagespec}{"$nyear"}) {
+ add_depends($params{page}, "$archivebase/$pyear", deptype("presence"));
+ if (exists $pagesources{"$archivebase/$nyear"}) {
$nurl = htmllink($params{page}, $params{destpage},
"$archivebase/$nyear",
linktext => "\→");
}
- add_depends($params{page}, "$archivebase/$nyear");
+ add_depends($params{page}, "$archivebase/$nyear", deptype("presence"));
# Start producing the year calendar
$calendar=<<EOF;
my $tag;
my $mtag=sprintf("%02d", $month);
if ($month == $params{month}) {
- if ($cache{$pagespec}{"$year/$mtag"}) {
+ if ($pagesources{"$archivebase/$year/$mtag"}) {
$tag = 'this_month_link';
}
else {
$tag = 'this_month_nolink';
}
}
- elsif ($cache{$pagespec}{"$year/$mtag"}) {
+ elsif ($pagesources{"$archivebase/$year/$mtag"}) {
$tag = 'month_link';
}
elsif ($future_month && $month >= $future_month) {
$tag = 'month_nolink';
}
- if ($cache{$pagespec}{"$year/$mtag"}) {
+ if ($pagesources{"$archivebase/$year/$mtag"}) {
$murl = htmllink($params{page}, $params{destpage},
"$archivebase/$year/$mtag",
linktext => "$monthabbr");
else {
$calendar.=qq{\t<td class="$tag">$monthabbr</td>\n};
}
- add_depends($params{page}, "$archivebase/$year/$mtag");
+ add_depends($params{page}, "$archivebase/$year/$mtag",
+ deptype("presence"));
$calendar.=qq{\t</tr>\n} if ($month % $params{months_per_row} == 0);
}
my %params=@_;
$params{pages} = "*" unless defined $params{pages};
$params{type} = "month" unless defined $params{type};
- $params{year} = 1900 + $now[5] unless defined $params{year};
$params{month} = sprintf("%02d", $params{month}) if defined $params{month};
- $params{month} = 1 + $now[4] unless defined $params{month};
$params{week_start_day} = 0 unless defined $params{week_start_day};
$params{months_per_row} = 3 unless defined $params{months_per_row};
+ if (! defined $params{year} || ! defined $params{month}) {
+ # Record that the calendar next changes at midnight.
+ $pagestate{$params{destpage}}{calendar}{nextchange}=($time
+ + (60 - $now[0]) # seconds
+ + (59 - $now[1]) * 60 # minutes
+ + (23 - $now[2]) * 60 * 60 # hours
+ );
+
+ $params{year} = 1900 + $now[5] unless defined $params{year};
+ $params{month} = 1 + $now[4] unless defined $params{month};
+ }
+ else {
+ delete $pagestate{$params{destpage}}{calendar};
+ }
+
# Calculate month names for next month, and previous months
my $pmonth = $params{month} - 1;
my $nmonth = $params{month} + 1;
$params{nyear} =$nyear;
my $calendar="\n";
- my $pagespec=$params{pages};
- my $page =$params{page};
-
- if (! defined $cache{$pagespec}) {
- foreach my $p (keys %pagesources) {
- next unless pagespec_match($p, $pagespec);
- my $mtime = $IkiWiki::pagectime{$p};
- my $src = $pagesources{$p};
- my @date = localtime($mtime);
- my $mday = $date[3];
- my $month = $date[4] + 1;
- my $year = $date[5] + 1900;
- my $mtag = sprintf("%02d", $month);
-
- # Only one posting per day is being linked to.
- $linkcache{"$year/$mtag/$mday"} = "$src";
- $cache{$pagespec}{"$year"}++;
- $cache{$pagespec}{"$year/$mtag"}++;
- $cache{$pagespec}{"$year/$mtag/$mday"}++;
- }
- }
if ($params{type} =~ /month/i) {
$calendar=format_month(%params);
$calendar=format_year(%params);
}
- return "\n<div class=\"calendar\">$calendar</div><!-- calendar -->\n";
+ return "\n<div><div class=\"calendar\">$calendar</div></div>\n";
+} #}}
+
+sub needsbuild (@) {
+ my $needsbuild=shift;
+ foreach my $page (keys %pagestate) {
+ if (exists $pagestate{$page}{calendar}{nextchange}) {
+ if ($pagestate{$page}{calendar}{nextchange} <= $time) {
+ # force a rebuild so the calendar shows
+ # the current day
+ push @$needsbuild, $pagesources{$page};
+ }
+ if (exists $pagesources{$page} &&
+ grep { $_ eq $pagesources{$page} } @$needsbuild) {
+ # remove state, will be re-added if
+ # the calendar is still there during the
+ # rebuild
+ delete $pagestate{$page}{calendar};
+ }
+ }
+ }
}
1