From 2ff726e87595d7496245f7c01e2bb217004979c0 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 29 Jan 2008 00:07:55 -0500 Subject: don't render internal-use pages, and document them --- IkiWiki/Render.pm | 1 + 1 file changed, 1 insertion(+) (limited to 'IkiWiki/Render.pm') diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 4fefadf09..5684f8092 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -193,6 +193,7 @@ sub render ($) { #{{{ my $type=pagetype($file); my $srcfile=srcfile($file); if (defined $type) { + return if $type=~/^_/; my $page=pagename($file); delete $depends{$page}; will_render($page, htmlpage($page), 1); -- cgit v1.2.3 From 7a4b7b1964f35527571aee78fb7048284e5d5061 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 29 Jan 2008 12:20:17 -0500 Subject: update RecentChanges action to point to page --- IkiWiki/Render.pm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'IkiWiki/Render.pm') diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 5684f8092..cfe039916 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -82,9 +82,11 @@ sub genpage ($$) { #{{{ if (length $config{cgiurl}) { $template->param(editurl => cgiurl(do => "edit", page => pagetitle($page, 1))); $template->param(prefsurl => cgiurl(do => "prefs")); - if ($config{rcs}) { - $template->param(recentchangesurl => cgiurl(do => "recentchanges")); - } + $actions++; + } + + if ($config{rcs}) { + $template->param(recentchangesurl => urlto("recentchanges", $page)); $actions++; } -- cgit v1.2.3 From 152f32547fb6fef046d8c21b218fa2dec96b6061 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 29 Jan 2008 12:39:28 -0500 Subject: indicate that an internal page will be rendered even if skipping it This is important to do because until will_render is called, ikiwiki doesn't know that the page exists. This avoids recentchanges re-writing every change page every run. --- IkiWiki/Render.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'IkiWiki/Render.pm') diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index cfe039916..02f6b4b1c 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -195,10 +195,10 @@ sub render ($) { #{{{ my $type=pagetype($file); my $srcfile=srcfile($file); if (defined $type) { - return if $type=~/^_/; my $page=pagename($file); delete $depends{$page}; will_render($page, htmlpage($page), 1); + return if $type=~/^_/; my $content=htmlize($page, $type, linkify($page, $page, -- cgit v1.2.3 From e1ce482e4146d1036e1ae512c73e54f69ff52f0d Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 29 Jan 2008 13:08:32 -0500 Subject: add refresh hook --- IkiWiki/Render.pm | 2 ++ 1 file changed, 2 insertions(+) (limited to 'IkiWiki/Render.pm') diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 02f6b4b1c..aa9b73141 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -259,6 +259,8 @@ sub refresh () { #{{{ $test=dirname($test); } } + + run_hooks(refresh => sub { shift->() }); # find existing pages my %exists; -- cgit v1.2.3 From 47ee266163202f15fca3b108fad294bec262405a Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 29 Jan 2008 15:05:49 -0500 Subject: improve support for internal pages This makes it a lot quicker to deal with lots of recentchanges pages appearing and disappearing. It avoids needing to clutter up pagespecs with exclusions for those pages, by making normal pagespecs not match them. --- IkiWiki.pm | 32 ++++++++++++++-------------- IkiWiki/Render.pm | 47 +++++++++++++++++++++++++++++++++--------- debian/changelog | 6 ++++-- doc/ikiwiki/pagespec.mdwn | 6 ++++-- doc/plugins/brokenlinks.mdwn | 2 +- doc/plugins/orphans.mdwn | 4 ++-- doc/plugins/pagecount.mdwn | 2 +- doc/plugins/recentchanges.mdwn | 2 ++ doc/plugins/write.mdwn | 18 +++++++++++----- 9 files changed, 80 insertions(+), 39 deletions(-) (limited to 'IkiWiki/Render.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index c70307b5f..db2605672 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -260,6 +260,12 @@ sub pagetype ($) { #{{{ return; } #}}} +sub isinternal ($) { #{{{ + my $page=shift; + return exists $pagesources{$page} && + $pagesources{$page} =~ /\._([^.]+)$/; +} #}}} + sub pagename ($) { #{{{ my $file=shift; @@ -1287,13 +1293,22 @@ sub match_glob ($$;@) { #{{{ $glob=~s/\\\?/./g; if ($page=~/^$glob$/i) { - return IkiWiki::SuccessReason->new("$glob matches $page"); + if (! IkiWiki::isinternal($page) || $params{internal}) { + return IkiWiki::SuccessReason->new("$glob matches $page"); + } + else { + return IkiWiki::FailReason->new("$glob matches $page, but the page is an internal page"); + } } else { return IkiWiki::FailReason->new("$glob does not match $page"); } } #}}} +sub match_internal ($$;@) { #{{{ + return match_glob($_[0], $_[1], @_, internal => 1) +} #}}} + sub match_link ($$;@) { #{{{ my $page=shift; my $link=lc(shift); @@ -1389,19 +1404,4 @@ sub match_creation_year ($$;@) { #{{{ } } #}}} -sub match_user ($$;@) { #{{{ - shift; - my $user=shift; - my %params=@_; - - return IkiWiki::FailReason->new('cannot match user') - unless exists $params{user}; - if ($user eq $params{user}) { - return IkiWiki::SuccessReason->new("user is $user") - } - else { - return IkiWiki::FailReason->new("user is not $user"); - } -} #}}} - 1 diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index aa9b73141..b5b461499 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -319,15 +319,19 @@ sub refresh () { #{{{ }, $dir); }; - my %rendered; + my (%rendered, @add, @del, @internal); # check for added or removed pages - my @add; foreach my $file (@files) { my $page=pagename($file); $pagesources{$page}=$file; if (! $pagemtime{$page}) { - push @add, $file; + if (isinternal($page)) { + push @internal, $file; + } + else { + push @add, $file; + } $pagecase{lc $page}=$page; if ($config{getctime} && -e "$config{srcdir}/$file") { $pagectime{$page}=rcs_getctime("$config{srcdir}/$file"); @@ -337,11 +341,15 @@ sub refresh () { #{{{ } } } - my @del; foreach my $page (keys %pagemtime) { if (! $exists{$page}) { - debug(sprintf(gettext("removing old page %s"), $page)); - push @del, $pagesources{$page}; + if (isinternal($page)) { + push @internal, $pagesources{$page}; + } + else { + debug(sprintf(gettext("removing old page %s"), $page)); + push @del, $pagesources{$page}; + } $links{$page}=[]; $renderedfiles{$page}=[]; $pagemtime{$page}=0; @@ -366,7 +374,12 @@ sub refresh () { #{{{ $mtime > $pagemtime{$page} || $forcerebuild{$page}) { $pagemtime{$page}=$mtime; - push @needsbuild, $file; + if (isinternal($page)) { + push @internal, $file; + } + else { + push @needsbuild, $file; + } } } run_hooks(needsbuild => sub { shift->(\@needsbuild) }); @@ -382,6 +395,15 @@ sub refresh () { #{{{ render($file); $rendered{$file}=1; } + foreach my $file (@internal) { + # internal pages are not rendered + my $page=pagename($file); + delete $depends{$page}; + foreach my $old (@{$renderedfiles{$page}}) { + delete $destsources{$old}; + } + $renderedfiles{$page}=[]; + } # rebuild pages that link to added or removed pages if (@add || @del) { @@ -397,13 +419,17 @@ sub refresh () { #{{{ } } - if (%rendered || @del) { + if (%rendered || @del || @internal) { + my @changed=(keys %rendered, @del); + # rebuild dependant pages foreach my $f (@files) { next if $rendered{$f}; my $p=pagename($f); if (exists $depends{$p}) { - foreach my $file (keys %rendered, @del) { + # only consider internal files + # if the page explicitly depends on such files + foreach my $file (@changed, $depends{$p}=~/internal\(/ ? @internal : ()) { next if $f eq $file; my $page=pagename($file); if (pagespec_match($page, $depends{$p}, location => $p)) { @@ -419,7 +445,7 @@ sub refresh () { #{{{ # handle backlinks; if a page has added/removed links, # update the pages it links to my %linkchanged; - foreach my $file (keys %rendered, @del) { + foreach my $file (@changed) { my $page=pagename($file); if (exists $links{$page}) { @@ -441,6 +467,7 @@ sub refresh () { #{{{ } } } + foreach my $link (keys %linkchanged) { my $linkfile=$pagesources{$link}; if (defined $linkfile) { diff --git a/debian/changelog b/debian/changelog index 8530bdd7e..c608531e1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -22,13 +22,15 @@ ikiwiki (2.21) UNRELEASED; urgency=low * prettydate,ddate: Don't ignore time formats passed to displaytime function. * Pages with extensions starting with "_" are internal-use, and will - not be rendered or web-edited. + not be rendered or web-edited, or matched by normal pagespecs. + * Add "internal()" pagespec that matches internal-use pages. * RecentChanges is now a static html page, that's updated whenever a commit is made to the wiki. It's built as a blog using inline, so it can have an rss feed that users can subscribe to. * Removed support for sending commit notification mails. Along with it went the svnrepo and notify settings, though both will be ignored if left in - setup files. + setup files. Also gone with it is the "user()" pagespec. + * Add refresh hook. -- Joey Hess Fri, 11 Jan 2008 15:09:37 -0500 diff --git a/doc/ikiwiki/pagespec.mdwn b/doc/ikiwiki/pagespec.mdwn index 5c6433ed3..e1a476202 100644 --- a/doc/ikiwiki/pagespec.mdwn +++ b/doc/ikiwiki/pagespec.mdwn @@ -33,8 +33,10 @@ functions: was created * "`created_before(page)`" - match only pages created before the given page was created -* "`user(name)`" - only available in page subscription preferences, match - only changes made by this user +* "`glob(foo)`" - match pages that match the given glob `foo`. Just writing + the glob by itself is actually a shorthand for this function. +* "`internal(foo)`" - like `glob()`, but matches even internal-use + pages that globs do not usually match. For example, to match all pages in a blog that link to the page about music and were written in 2005: diff --git a/doc/plugins/brokenlinks.mdwn b/doc/plugins/brokenlinks.mdwn index 5c906e17b..208d7120b 100644 --- a/doc/plugins/brokenlinks.mdwn +++ b/doc/plugins/brokenlinks.mdwn @@ -10,4 +10,4 @@ pages to search for broken links, default is search them all. If this plugin is turned on, here's a list of broken links on this wiki: -[[brokenlinks pages="* and !recentchanges/change_* and !recentchanges"]] +[[brokenlinks pages="* and !recentchanges"]] diff --git a/doc/plugins/orphans.mdwn b/doc/plugins/orphans.mdwn index 6c6ebd6f9..74f4bae08 100644 --- a/doc/plugins/orphans.mdwn +++ b/doc/plugins/orphans.mdwn @@ -15,6 +15,6 @@ orphans. Here's a list of orphaned pages on this wiki: [[orphans pages="* and !news/* and !todo/* and !bugs/* and !users/* and -!recentchanges/change_* and !recentchanges and !examples/* and !tips/* and -!sandbox/* and !wikiicons/* and !plugins/*"]] +!recentchanges and !examples/* and !tips/* and !sandbox/* and +!wikiicons/* and !plugins/*"]] """]] diff --git a/doc/plugins/pagecount.mdwn b/doc/plugins/pagecount.mdwn index c4cefd946..8f7029df8 100644 --- a/doc/plugins/pagecount.mdwn +++ b/doc/plugins/pagecount.mdwn @@ -10,5 +10,5 @@ pages to count, default is to count them all. This plugin is included in ikiwiki, but is not enabled by default. If it is turned on it can tell us that this wiki includes -[[pagecount pages="* and !recentchanges/change_* and !recentchanges"]] +[[pagecount pages="* and !recentchanges"]] pages, of which [[pagecount pages="*/Discussion"]] are discussion pages. diff --git a/doc/plugins/recentchanges.mdwn b/doc/plugins/recentchanges.mdwn index 9e0d8dc51..69073adf0 100644 --- a/doc/plugins/recentchanges.mdwn +++ b/doc/plugins/recentchanges.mdwn @@ -9,6 +9,8 @@ Typically only the RecentChanges page will use the plugin, but you can use it elsewhere too if you like. It's used like this: \[[recentchanges pages="*" num=100 template=change]] + \[[inline pages="internal(recentchanges/change_*)" + template=recentchanges show=0]] The pages describing recent changes will be created as [[subpages|subpage]] of the page where the `recentchanges` directive is placed. diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 9e27cc27f..4de7e434d 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -151,11 +151,6 @@ specifies the filename extension that a file must have to be htmlized using this plugin. This is how you can add support for new and exciting markup languages to ikiwiki. -Note that if you choose a filename extension that starts with "_", -ikiwiki will not render the page, or allow the page to be edited with the -web interface. This is useful for certian types of internal-use pages, but -should generally be avoided. - The function is passed named parameters: "page" and "content" and should return the htmlized content. @@ -536,6 +531,19 @@ destination file, as registered by `will_render`. Passed a page and an extension, returns the filename that page will be rendered to. +## Internal use pages + +Sometimes it's useful to put pages in the wiki without having them be +rendered to individual html files. Such internal use pages are collected +together to form the RecentChanges page, for example. + +To make an internal use page, register a filename extension that starts +with "_". Internal use pages cannot be edited with the web interface, are +not scanned for wikilinks (though wikilinks and preprocessor directives can +still appear on them, this is rarely a good idea), and are not matched by +regular PageSpecs glob patterns, but instead only by a special `internal()` +[[ikiwiki/PageSpec]]. + ## RCS plugins ikiwiki's support for [[revision_control_systems|rcs]] also uses pluggable -- cgit v1.2.3 From 8b31c53366bbee51b36501443eafd0f712ee6a4c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 29 Jan 2008 15:51:32 -0500 Subject: added configuration for recentchanges I kept it to a simple global configuration, rather than using the preprocessor directive for recentchanges, because that had chicken and egg problems and seemed overcomplicated. This should work reasonably well, though it would be good to add some more metadata so that more customised recentchanges pages can be made. --- IkiWiki/Plugin/recentchanges.pm | 54 +++++++++++++++++------------------------ IkiWiki/Render.pm | 4 +-- doc/cgi.mdwn | 6 +++-- doc/ikiwiki.setup | 3 +++ doc/plugins/recentchanges.mdwn | 8 ++---- doc/recentchanges.mdwn | 1 - doc/usage.mdwn | 6 ++--- docwiki.setup | 8 ++---- po/ikiwiki.pot | 2 +- t/pagespec_match.t | 3 --- 10 files changed, 38 insertions(+), 57 deletions(-) (limited to 'IkiWiki/Render.pm') diff --git a/IkiWiki/Plugin/recentchanges.pm b/IkiWiki/Plugin/recentchanges.pm index 8f707afc4..f5982604b 100644 --- a/IkiWiki/Plugin/recentchanges.pm +++ b/IkiWiki/Plugin/recentchanges.pm @@ -6,25 +6,30 @@ use strict; use IkiWiki 2.00; sub import { #{{{ - hook(type => "refresh", id => "recentchanges", - call => \&refresh); - hook(type => "preprocess", id => "recentchanges", - call => \&preprocess); - hook(type => "htmlize", id => "_change", - call => \&htmlize); + hook(type => "checkconfig", id => "recentchanges", call => \&checkconfig); + hook(type => "refresh", id => "recentchanges", call => \&refresh); + hook(type => "htmlize", id => "_change", call => \&htmlize); } #}}} -sub refresh ($) { #{{{ - my @changes=IkiWiki::rcs_recentchanges(100); - updatechanges("*", "recentchanges", \@changes); +sub checkconfig () { #{{{ + $config{recentchangespage}='recentchanges' unless defined $config{recentchangespage}; + $config{recentchangesnum}=100 unless defined $config{recentchangesnum}; } #}}} -sub preprocess (@) { #{{{ - my %params=@_; - - # TODO +sub refresh ($) { #{{{ + my %seen; - return ""; + # add new changes + foreach my $change (IkiWiki::rcs_recentchanges($config{recentchangesnum})) { + $seen{store($change, $config{recentchangespage})}=1; + } + + # delete old and excess changes + foreach my $page (keys %pagesources) { + if ($page=~/^\Q$config{recentchangespage}\E\/change_/ && ! $seen{$page}) { + unlink($config{srcdir}.'/'.$pagesources{$page}); + } + } } #}}} # Pages with extension _change have plain html markup, pass through. @@ -33,11 +38,10 @@ sub htmlize (@) { #{{{ return $params{content}; } #}}} -sub store ($$) { #{{{ +sub store ($$$) { #{{{ my $change=shift; - my $subdir=shift; - - my $page="$subdir/change_".IkiWiki::titlepage($change->{rev}); + + my $page="$config{recentchangespage}/change_".IkiWiki::titlepage($change->{rev}); # Optimisation to avoid re-writing pages. Assumes commits never # change (or that any changes are not important). @@ -102,23 +106,9 @@ sub store ($$) { #{{{ } #}}} sub updatechanges ($$) { #{{{ - my $pagespec=shift; my $subdir=shift; my @changes=@{shift()}; - my %seen; - - # add new changes - foreach my $change (@changes) { - $seen{store($change, $subdir)}=1; - } - - # delete old and excess changes - foreach my $page (keys %pagesources) { - if ($page=~/^\Q$subdir\E\/change_/ && ! $seen{$page}) { - unlink($config{srcdir}.'/'.$pagesources{$page}); - } - } } #}}} 1 diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index b5b461499..ed359bdd7 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -85,8 +85,8 @@ sub genpage ($$) { #{{{ $actions++; } - if ($config{rcs}) { - $template->param(recentchangesurl => urlto("recentchanges", $page)); + if ($config{rcs} && exists $config{recentchangespage}) { + $template->param(recentchangesurl => urlto($config{recentchangespage}, $page)); $actions++; } diff --git a/doc/cgi.mdwn b/doc/cgi.mdwn index 22d8c4332..1448fa4d5 100644 --- a/doc/cgi.mdwn +++ b/doc/cgi.mdwn @@ -1,3 +1,5 @@ -While ikiwiki is primarily a wiki compiler, which generates static html pages, it does use CGI for two important wiki features, online page editing and the [[RecentChanges]] display. +While ikiwiki is primarily a wiki compiler, which generates static html +pages, it does use CGI for online page editing. -To enable CGI, you need to create and install an ikiwiki.cgi wrapper. [[Setup]] explains how to do this. \ No newline at end of file +To enable CGI, you need to create and install an ikiwiki.cgi wrapper. +[[Setup]] explains how to do this. diff --git a/doc/ikiwiki.setup b/doc/ikiwiki.setup index af27f1d7e..9bf542981 100644 --- a/doc/ikiwiki.setup +++ b/doc/ikiwiki.setup @@ -115,6 +115,9 @@ use IkiWiki::Setup::Standard { #account_creation_password => "example", # Uncomment to force ikiwiki to run with a particular umask. #umask => 022, + # Default settings for the recentchanges page. + #recentchangespage => "recentchanges", + #recentchangesnum => 100, # To add plugins, list them here. #add_plugins => [qw{goodstuff search wikitext camelcase diff --git a/doc/plugins/recentchanges.mdwn b/doc/plugins/recentchanges.mdwn index 69073adf0..8647985c9 100644 --- a/doc/plugins/recentchanges.mdwn +++ b/doc/plugins/recentchanges.mdwn @@ -5,12 +5,8 @@ generates a page describing each recent change made to the wiki. These pages can be joined together with [[inline]] to generate the [[RecentChanges]] page. -Typically only the RecentChanges page will use the plugin, but you can -use it elsewhere too if you like. It's used like this: +Typically only the RecentChanges page will use the pages generated by this +plugin, but you can use it elsewhere too if you like. It's used like this: - \[[recentchanges pages="*" num=100 template=change]] \[[inline pages="internal(recentchanges/change_*)" template=recentchanges show=0]] - -The pages describing recent changes will be created as [[subpages|subpage]] -of the page where the `recentchanges` directive is placed. diff --git a/doc/recentchanges.mdwn b/doc/recentchanges.mdwn index d702b0f34..2dd218520 100644 --- a/doc/recentchanges.mdwn +++ b/doc/recentchanges.mdwn @@ -1,5 +1,4 @@ Recent changes to this wiki: -[[recentchanges pages="*" num=100 template=change]] [[inline pages="internal(recentchanges/change_*) and !*/Discussion" template=recentchanges show=0]] diff --git a/doc/usage.mdwn b/doc/usage.mdwn index 354e266f1..f34d5bad6 100644 --- a/doc/usage.mdwn +++ b/doc/usage.mdwn @@ -33,8 +33,7 @@ These options control the mode that ikiwiki operates in. * --cgi Enable [[CGI]] mode. In cgi mode ikiwiki runs as a cgi script, and - supports editing pages, signing in, registration, and displaying - [[RecentChanges]]. + supports editing pages, signing in, and registration. To use ikiwiki as a [[CGI]] program you need to use --wrapper or --setup to generate a wrapper. The wrapper will generally need to run suid 6755 to @@ -141,8 +140,7 @@ configuration options of their own. whatever the revision control system you select uses. In [[CGI]] mode, with a revision control system enabled, pages edited via - the web will be committed. Also, the [[RecentChanges]] link will be placed - on pages. + the web will be committed. No revision control is enabled by default. diff --git a/docwiki.setup b/docwiki.setup index 5793d87bf..e8f680a20 100644 --- a/docwiki.setup +++ b/docwiki.setup @@ -15,10 +15,6 @@ use IkiWiki::Setup::Standard { syslog => 0, userdir => "users", usedirs => 0, - rcs => 'git', - rss => 1, - cgiurl => "http://ikiwiki.info/ikiwiki.cgi", - url => "http://ikiwiki.info", - add_plugins => [qw{goodstuff version haiku polygen fortune - recentchanges }], + add_plugins => [qw{goodstuff version haiku polygen fortune}], + disable_plugins => [qw{recentchanges}], } diff --git a/po/ikiwiki.pot b/po/ikiwiki.pot index 98882d535..4e43f5da9 100644 --- a/po/ikiwiki.pot +++ b/po/ikiwiki.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-01-29 15:21-0500\n" +"POT-Creation-Date: 2008-01-29 15:46-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/t/pagespec_match.t b/t/pagespec_match.t index 3a641c6a8..cb98ab149 100755 --- a/t/pagespec_match.t +++ b/t/pagespec_match.t @@ -67,9 +67,6 @@ ok(! pagespec_match("foo", "creation_day(3)"), "other day"); ok(! pagespec_match("foo", "no_such_function(foo)"), "foo"); -ok(pagespec_match("foo", "foo and user(bar)", user => "bar"), "user"); -ok(! pagespec_match("foo", "foo and user(bar)", user => "baz"), "user fail"); - my $ret=pagespec_match("foo", "(invalid"); ok(! $ret, "syntax error"); ok($ret eq "syntax error", "error message"); -- cgit v1.2.3 From 9875bc10d14d50f543f4aab3ce4e9dae060b8c23 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 29 Jan 2008 15:53:49 -0500 Subject: avoid redundant recentpages action on the recentchanges page itself --- IkiWiki/Render.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'IkiWiki/Render.pm') diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index ed359bdd7..4495b9cfd 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -85,7 +85,8 @@ sub genpage ($$) { #{{{ $actions++; } - if ($config{rcs} && exists $config{recentchangespage}) { + if ($config{rcs} && exists $config{recentchangespage} && + $page ne $config{recentchangespage}) { $template->param(recentchangesurl => urlto($config{recentchangespage}, $page)); $actions++; } -- cgit v1.2.3 From 64a8c828b8cfa342118dd6e28b9dff43d83c6311 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 29 Jan 2008 17:16:51 -0500 Subject: * meta: Add pagespec functions to match against title, author, authorurl, license, and copyright. This can be used to create custom RecentChanges. * meta: To support the pagespec functions, metadata about pages has to be retained as pagestate. * Fix encoding bug when pagestate values contained spaces. --- IkiWiki.pm | 2 +- IkiWiki/Plugin/meta.pm | 122 +++++++++++++++++++++++++++-------------- IkiWiki/Render.pm | 1 + debian/changelog | 5 ++ doc/ikiwiki/pagespec.mdwn | 7 ++- doc/plugins/recentchanges.mdwn | 14 +++++ doc/plugins/write.mdwn | 18 +++--- docwiki.setup | 4 +- po/ikiwiki.pot | 32 +++++------ templates/change.tmpl | 2 +- 10 files changed, 136 insertions(+), 71 deletions(-) (limited to 'IkiWiki/Render.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index db2605672..016c664b5 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -973,7 +973,7 @@ sub saveindex () { #{{{ if (exists $pagestate{$page}) { foreach my $id (@hookids) { foreach my $key (keys %{$pagestate{$page}{$id}}) { - $line.=' '.$id.'_'.encode_entities($key)."=".encode_entities($pagestate{$page}{$id}{$key}); + $line.=' '.$id.'_'.encode_entities($key)."=".encode_entities($pagestate{$page}{$id}{$key}, " \t\n"); } } } diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index d2c6e7f8b..849a13e37 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -6,13 +6,7 @@ use warnings; use strict; use IkiWiki 2.00; -my %meta; -my %title; -my %permalink; -my %author; -my %authorurl; -my %license; -my %copyright; +my %metaheaders; sub import { #{{{ hook(type => "needsbuild", id => "meta", call => \&needsbuild); @@ -71,16 +65,16 @@ sub preprocess (@) { #{{{ # Metadata collection that needs to happen during the scan pass. if ($key eq 'title') { - $title{$page}=HTML::Entities::encode_numeric($value); + $pagestate{$page}{meta}{title}=HTML::Entities::encode_numeric($value); } elsif ($key eq 'license') { - push @{$meta{$page}}, ''; - $license{$page}=$value; + push @{$metaheaders{$page}}, ''; + $pagestate{$page}{meta}{license}=$value; return ""; } elsif ($key eq 'copyright') { - push @{$meta{$page}}, ''; - $copyright{$page}=$value; + push @{$metaheaders{$page}}, ''; + $pagestate{$page}{meta}{copyright}=$value; return ""; } elsif ($key eq 'link' && ! %params) { @@ -89,11 +83,11 @@ sub preprocess (@) { #{{{ return ""; } elsif ($key eq 'author') { - $author{$page}=$value; + $pagestate{$page}{meta}{author}=$value; # fallthorough } elsif ($key eq 'authorurl') { - $authorurl{$page}=$value; + $pagestate{$page}{meta}{authorurl}=$value; # fallthrough } @@ -111,8 +105,8 @@ sub preprocess (@) { #{{{ } } elsif ($key eq 'permalink') { - $permalink{$page}=$value; - push @{$meta{$page}}, scrub(''); + $pagestate{$page}{meta}{permalink}=$value; + push @{$metaheaders{$page}}, scrub(''); } elsif ($key eq 'stylesheet') { my $rel=exists $params{rel} ? $params{rel} : "alternate stylesheet"; @@ -123,17 +117,17 @@ sub preprocess (@) { #{{{ if (! length $stylesheet) { return "[[meta ".gettext("stylesheet not found")."]]"; } - push @{$meta{$page}}, '"; } elsif ($key eq 'openid') { if (exists $params{server}) { - push @{$meta{$page}}, ''; } - push @{$meta{$page}}, ''; } elsif ($key eq 'redir') { @@ -172,11 +166,11 @@ sub preprocess (@) { #{{{ if (! $safe) { $redir=scrub($redir); } - push @{$meta{$page}}, $redir; + push @{$metaheaders{$page}}, $redir; } elsif ($key eq 'link') { if (%params) { - push @{$meta{$page}}, scrub("'); } @@ -197,32 +191,80 @@ sub pagetemplate (@) { #{{{ my $destpage=$params{destpage}; my $template=$params{template}; - if (exists $meta{$page} && $template->query(name => "meta")) { + if (exists $metaheaders{$page} && $template->query(name => "meta")) { # avoid duplicate meta lines my %seen; - $template->param(meta => join("\n", grep { (! $seen{$_}) && ($seen{$_}=1) } @{$meta{$page}})); + $template->param(meta => join("\n", grep { (! $seen{$_}) && ($seen{$_}=1) } @{$metaheaders{$page}})); } - if (exists $title{$page} && $template->query(name => "title")) { - $template->param(title => $title{$page}); + if (exists $pagestate{$page}{meta}{title} && $template->query(name => "title")) { + $template->param(title => $pagestate{$page}{meta}{title}); $template->param(title_overridden => 1); } - $template->param(permalink => $permalink{$page}) - if exists $permalink{$page} && $template->query(name => "permalink"); - $template->param(author => $author{$page}) - if exists $author{$page} && $template->query(name => "author"); - $template->param(authorurl => $authorurl{$page}) - if exists $authorurl{$page} && $template->query(name => "authorurl"); - if (exists $license{$page} && $template->query(name => "license") && - ($page eq $destpage || ! exists $license{$destpage} || - $license{$page} ne $license{$destpage})) { - $template->param(license => htmlize($page, $destpage, $license{$page})); + foreach my $field (qw{author authorurl permalink}) { + $template->param($field => $pagestate{$page}{meta}{$field}) + if exists $pagestate{$page}{meta}{$field} && $template->query(name => $field); } - if (exists $copyright{$page} && $template->query(name => "copyright") && - ($page eq $destpage || ! exists $copyright{$destpage} || - $copyright{$page} ne $copyright{$destpage})) { - $template->param(copyright => htmlize($page, $destpage, $copyright{$page})); + + foreach my $field (qw{license copyright}) { + if (exists $pagestate{$page}{meta}{$field} && $template->query(name => $field) && + ($page eq $destpage || ! exists $pagestate{$destpage}{meta}{$field} || + $pagestate{$page}{meta}{$field} ne $pagestate{$destpage}{meta}{$field})) { + $template->param($field => htmlize($page, $destpage, $pagestate{$page}{meta}{$field})); + } } } # }}} +sub match { #{{{ + my $field=shift; + my $page=shift; + + # turn glob into a safe regexp + my $re=quotemeta(shift); + $re=~s/\\\*/.*/g; + $re=~s/\\\?/./g; + + my $val; + if (exists $pagestate{$page}{meta}{$field}) { + $val=$pagestate{$page}{meta}{$field}; + } + elsif ($field eq 'title') { + $val=pagetitle($page); + } + + if (defined $val) { + if ($val=~/^$re$/i) { + return IkiWiki::SuccessReason->new("$re matches $field of $page"); + } + else { + return IkiWiki::FailReason->new("$re does not match $field of $page"); + } + } + else { + return IkiWiki::FailReason->new("$page does not have a $field"); + } +} #}}} + +package IkiWiki::PageSpec; + +sub match_title ($$;@) { #{{{ + IkiWiki::Plugin::meta::match("title", @_); +} #}}} + +sub match_author ($$;@) { #{{{ + IkiWiki::Plugin::meta::match("author", @_); +} #}}} + +sub match_authorurl ($$;@) { #{{{ + IkiWiki::Plugin::meta::match("authorurl", @_); +} #}}} + +sub match_license ($$;@) { #{{{ + IkiWiki::Plugin::meta::match("license", @_); +} #}}} + +sub match_copyright ($$;@) { #{{{ + IkiWiki::Plugin::meta::match("copyright", @_); +} #}}} + 1 diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 4495b9cfd..76e8ef1f4 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -377,6 +377,7 @@ sub refresh () { #{{{ $pagemtime{$page}=$mtime; if (isinternal($page)) { push @internal, $file; + scan($file); } else { push @needsbuild, $file; diff --git a/debian/changelog b/debian/changelog index c608531e1..77202ed1f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -31,6 +31,11 @@ ikiwiki (2.21) UNRELEASED; urgency=low the svnrepo and notify settings, though both will be ignored if left in setup files. Also gone with it is the "user()" pagespec. * Add refresh hook. + * meta: Add pagespec functions to match against title, author, authorurl, + license, and copyright. This can be used to create custom RecentChanges. + * meta: To support the pagespec functions, metadata about pages has to be + retained as pagestate. + * Fix encoding bug when pagestate values contained spaces. -- Joey Hess Fri, 11 Jan 2008 15:09:37 -0500 diff --git a/doc/ikiwiki/pagespec.mdwn b/doc/ikiwiki/pagespec.mdwn index e1a476202..3cd6bb9f4 100644 --- a/doc/ikiwiki/pagespec.mdwn +++ b/doc/ikiwiki/pagespec.mdwn @@ -33,10 +33,13 @@ functions: was created * "`created_before(page)`" - match only pages created before the given page was created -* "`glob(foo)`" - match pages that match the given glob `foo`. Just writing +* "`glob(someglob)`" - match pages that match the given glob. Just writing the glob by itself is actually a shorthand for this function. -* "`internal(foo)`" - like `glob()`, but matches even internal-use +* "`internal(glob)`" - like `glob()`, but matches even internal-use pages that globs do not usually match. +* "`title(glob)`", "`author(glob)`", "`authorurl(glob)`", + "`license(glob)`", "`copyright(glob)`" - match pages that have the given + metadata, matching the specified glob. For example, to match all pages in a blog that link to the page about music and were written in 2005: diff --git a/doc/plugins/recentchanges.mdwn b/doc/plugins/recentchanges.mdwn index 8647985c9..b48dcbacf 100644 --- a/doc/plugins/recentchanges.mdwn +++ b/doc/plugins/recentchanges.mdwn @@ -10,3 +10,17 @@ plugin, but you can use it elsewhere too if you like. It's used like this: \[[inline pages="internal(recentchanges/change_*)" template=recentchanges show=0]] + +Here's an example of how to show only changes to "bugs/*". +This matches against the title of the change, which includes a list of +modified pages. + + \[[inline pages="internal(recentchanges/change_*) and title(*bugs/*)" + template=recentchanges show=0]] + +Here's an example of how to show only changes that Joey didn't make. +(Joey commits sometimes as user `joey`, and sometimes via openid.) + + \[[inline pages="internal(recentchanges/change_*) and + !author(joey) and !author(http://joey.kitenet.net*)" + template=recentchanges show=0]] diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 79da6a612..9c3a36b8f 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -533,18 +533,16 @@ rendered to. ## Internal use pages -Sometimes it's useful to put pages in the wiki without having them be -rendered to individual html files. Such internal use pages are collected -together to form the RecentChanges page, for example. +Sometimes it's useful to put pages in the wiki without the overhead of +having them be rendered to individual html files. Such internal use pages +are collected together to form the RecentChanges page, for example. To make an internal use page, register a filename extension that starts -with "_". Internal use pages cannot be edited with the web interface, are -not scanned for wikilinks (though wikilinks and preprocessor directives can -appear on them, this is rarely a good idea and should be done with caution), -and are not matched by regular PageSpecs glob patterns, but instead only by a -special `internal()` [[ikiwiki/PageSpec]]. - -Ikiwiki is optimised to handle lots of internal use pages, very quickly. +with "_". Internal use pages cannot be edited with the web interface, +generally shouldn't contain wikilinks or preprocessor directives (use +either on them with extreme caution), and are not matched by regular +PageSpecs glob patterns, but instead only by a special `internal()` +[[ikiwiki/PageSpec]]. ## RCS plugins diff --git a/docwiki.setup b/docwiki.setup index e8f680a20..ab9696b81 100644 --- a/docwiki.setup +++ b/docwiki.setup @@ -15,6 +15,8 @@ use IkiWiki::Setup::Standard { syslog => 0, userdir => "users", usedirs => 0, + rcs => "git", + rss => 1, + url => "http://ikiwiki.info/", add_plugins => [qw{goodstuff version haiku polygen fortune}], - disable_plugins => [qw{recentchanges}], } diff --git a/po/ikiwiki.pot b/po/ikiwiki.pot index 4e43f5da9..027e10e8a 100644 --- a/po/ikiwiki.pot +++ b/po/ikiwiki.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-01-29 15:46-0500\n" +"POT-Creation-Date: 2008-01-29 17:15-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -47,8 +47,8 @@ msgstr "" #: ../IkiWiki/CGI.pm:382 ../IkiWiki/Plugin/brokenlinks.pm:24 #: ../IkiWiki/Plugin/inline.pm:241 ../IkiWiki/Plugin/opendiscussion.pm:17 -#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:100 -#: ../IkiWiki/Render.pm:180 +#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:101 +#: ../IkiWiki/Render.pm:181 msgid "discussion" msgstr "" @@ -218,7 +218,7 @@ msgstr "" msgid "nonexistant template %s" msgstr "" -#: ../IkiWiki/Plugin/inline.pm:249 ../IkiWiki/Render.pm:104 +#: ../IkiWiki/Plugin/inline.pm:249 ../IkiWiki/Render.pm:105 msgid "Discussion" msgstr "" @@ -240,15 +240,15 @@ msgstr "" msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)" msgstr "" -#: ../IkiWiki/Plugin/meta.pm:124 +#: ../IkiWiki/Plugin/meta.pm:118 msgid "stylesheet not found" msgstr "" -#: ../IkiWiki/Plugin/meta.pm:148 +#: ../IkiWiki/Plugin/meta.pm:142 msgid "redir page not found" msgstr "" -#: ../IkiWiki/Plugin/meta.pm:161 +#: ../IkiWiki/Plugin/meta.pm:155 msgid "redir cycle is not allowed" msgstr "" @@ -503,47 +503,47 @@ msgstr "" msgid "getctime not implemented" msgstr "" -#: ../IkiWiki/Render.pm:280 ../IkiWiki/Render.pm:301 +#: ../IkiWiki/Render.pm:281 ../IkiWiki/Render.pm:302 #, perl-format msgid "skipping bad filename %s" msgstr "" -#: ../IkiWiki/Render.pm:350 +#: ../IkiWiki/Render.pm:351 #, perl-format msgid "removing old page %s" msgstr "" -#: ../IkiWiki/Render.pm:389 +#: ../IkiWiki/Render.pm:391 #, perl-format msgid "scanning %s" msgstr "" -#: ../IkiWiki/Render.pm:394 +#: ../IkiWiki/Render.pm:396 #, perl-format msgid "rendering %s" msgstr "" -#: ../IkiWiki/Render.pm:415 +#: ../IkiWiki/Render.pm:417 #, perl-format msgid "rendering %s, which links to %s" msgstr "" -#: ../IkiWiki/Render.pm:436 +#: ../IkiWiki/Render.pm:438 #, perl-format msgid "rendering %s, which depends on %s" msgstr "" -#: ../IkiWiki/Render.pm:475 +#: ../IkiWiki/Render.pm:477 #, perl-format msgid "rendering %s, to update its backlinks" msgstr "" -#: ../IkiWiki/Render.pm:487 +#: ../IkiWiki/Render.pm:489 #, perl-format msgid "removing %s, no longer rendered by %s" msgstr "" -#: ../IkiWiki/Render.pm:513 +#: ../IkiWiki/Render.pm:515 #, perl-format msgid "ikiwiki: cannot render %s" msgstr "" diff --git a/templates/change.tmpl b/templates/change.tmpl index 570d47559..f9941ae70 100644 --- a/templates/change.tmpl +++ b/templates/change.tmpl @@ -2,7 +2,7 @@ [[meta authorurl=""""""]] -[[meta title="""update of 's """]] +[[meta title="""update of 's """]]