web commit by http://ethan.betacantrips.com/: new plugin
parent
4a07e28acc
commit
e47be9748b
|
@ -0,0 +1,266 @@
|
||||||
|
This is another blogging support thing, and it relies on
|
||||||
|
[[pagespec_relative_to_a_target]] (but only to figure out whether a given page
|
||||||
|
has a child). Basically, you give it a page called missingparents.mdwn,
|
||||||
|
something like this:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
[[missingparents pages="posts/* and !posts/*/*" generate="""[[template id=year text="$page"]]"""]]
|
||||||
|
[[missingparents pages="posts/*/* and !posts/*/*/*" generate="""[[template id=month text="$page"]]"""]]
|
||||||
|
[[missingparents pages="posts/*/*/* and !posts/*/*/*/*" generate="""[[template id=day text="$page"]]"""]]
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
And it scans the whole wiki for pages that match the pagespecs but are missing
|
||||||
|
parents. If any are found, they are generated automatically using the text in
|
||||||
|
the "generate" parameter (except $page is substituted for the page title).
|
||||||
|
*These generated pages aren't kept in version control*, but of course they're
|
||||||
|
ordinary wiki pages and can be edited by the web form or otherwise added, at
|
||||||
|
which point the missingparents plugin lets go of them. (TODO: CGI.pm needs to
|
||||||
|
know to rcs_add these pages if they are edited, and it doesn't.) If all of the
|
||||||
|
children of a missingparent page goes away, the missingparent itself is
|
||||||
|
unlinked automatically, and all missingparents are deleted on wiki rebuild.
|
||||||
|
|
||||||
|
To implement this, I needed to tell ikiwiki that pages were being added and
|
||||||
|
removed in a non-standard way, and so created functions newpage and delpage
|
||||||
|
in the IkiWiki namespace to do these things. delpage is modeled on the
|
||||||
|
Render.pm code that deletes pages, so I re-used it in Render.pm. I also
|
||||||
|
needed a way to add files to be deleted on a refresh(), so I added a
|
||||||
|
needsdelete hook, parallel in form to needsbuild.
|
||||||
|
|
||||||
|
This patch, or one like it, would enable better blogging support, by adding
|
||||||
|
the ability to hierarchically organize blog posts and automatically generate
|
||||||
|
structural pages for year, month, or day. Please apply. --Ethan
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
Index: IkiWiki/Render.pm
|
||||||
|
===================================================================
|
||||||
|
--- IkiWiki/Render.pm (revision 3926)
|
||||||
|
+++ IkiWiki/Render.pm (working copy)
|
||||||
|
@@ -322,17 +322,7 @@
|
||||||
|
if (! $exists{$page}) {
|
||||||
|
debug(sprintf(gettext("removing old page %s"), $page));
|
||||||
|
push @del, $pagesources{$page};
|
||||||
|
- $links{$page}=[];
|
||||||
|
- $renderedfiles{$page}=[];
|
||||||
|
- $pagemtime{$page}=0;
|
||||||
|
- prune($config{destdir}."/".$_)
|
||||||
|
- foreach @{$oldrenderedfiles{$page}};
|
||||||
|
- delete $pagesources{$page};
|
||||||
|
- foreach (keys %destsources) {
|
||||||
|
- if ($destsources{$_} eq $page) {
|
||||||
|
- delete $destsources{$_};
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ delpage($page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -377,6 +367,10 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (@del) {
|
||||||
|
+ run_hooks(needsdelete => sub { shift->(\@del) });
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (%rendered || @del) {
|
||||||
|
# rebuild dependant pages
|
||||||
|
foreach my $f (@files) {
|
||||||
|
Index: IkiWiki/Plugin/missingparents.pm
|
||||||
|
===================================================================
|
||||||
|
--- IkiWiki/Plugin/missingparents.pm (revision 0)
|
||||||
|
+++ IkiWiki/Plugin/missingparents.pm (revision 0)
|
||||||
|
@@ -0,0 +1,136 @@
|
||||||
|
+#!/usr/bin/perl
|
||||||
|
+# missingparents plugin: detect missing parents of pages and create them
|
||||||
|
+package IkiWiki::Plugin::missingparents;
|
||||||
|
+
|
||||||
|
+use warnings;
|
||||||
|
+use strict;
|
||||||
|
+use IkiWiki 2.00;
|
||||||
|
+use IkiWiki::Plugin::relative;
|
||||||
|
+
|
||||||
|
+my %ownfiles;
|
||||||
|
+my @pagespecs;
|
||||||
|
+
|
||||||
|
+sub import { #{{{
|
||||||
|
+ hook(type => "checkconfig", id => "missingparents", call => \&checkconfig);
|
||||||
|
+ hook(type => "needsdelete", id => "missingparents", call => \&needsdelete);
|
||||||
|
+ hook(type => "needsbuild", id => "missingparents", call => \&needsbuild);
|
||||||
|
+ hook(type => "savestate", id => "missingparents", call => \&savestate);
|
||||||
|
+ hook(type => "preprocess", id => "missingparents", call => \&preprocess_missingparents);
|
||||||
|
+} # }}}
|
||||||
|
+
|
||||||
|
+sub checkconfig () { #{{{
|
||||||
|
+ IkiWiki::preprocess("missingparents", "missingparents",
|
||||||
|
+ readfile(srcfile("missingparents.mdwn")));
|
||||||
|
+ loadstate();
|
||||||
|
+ if ($config{rebuild}){
|
||||||
|
+ foreach my $file (keys %ownfiles) {
|
||||||
|
+ unlink $config{srcdir}.'/'.$file;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+} #}}}
|
||||||
|
+
|
||||||
|
+sub preprocess_missingparents (@) { #{{{
|
||||||
|
+ my %params=@_;
|
||||||
|
+
|
||||||
|
+ if (! defined $params{pages} || ! defined $params{generate}) {
|
||||||
|
+ return "[[missingparents ".gettext("missing pages or generate parameter")."]]";
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ push @pagespecs, \%params;
|
||||||
|
+
|
||||||
|
+ #translators: This is used to display what missingparents are defined.
|
||||||
|
+ #translators: First parameter is a pagespec, the second
|
||||||
|
+ #translators: is text for pages that match that pagespec.
|
||||||
|
+ return sprintf(gettext("missingparents in %s will be %s"),
|
||||||
|
+ '`'.$params{pages}.'`', '`\\'.$params{generate}.'`');
|
||||||
|
+} # }}}
|
||||||
|
+
|
||||||
|
+my $state_loaded=0;
|
||||||
|
+sub loadstate() { #{{{
|
||||||
|
+ my $filename = "$config{wikistatedir}/missingparents";
|
||||||
|
+ if (-e $filename) {
|
||||||
|
+ open (IN, $filename) ||
|
||||||
|
+ die "$filename: $!";
|
||||||
|
+ while (<IN>) {
|
||||||
|
+ chomp;
|
||||||
|
+ $ownfiles{$_} = 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ close IN;
|
||||||
|
+
|
||||||
|
+ $state_loaded=1;
|
||||||
|
+ }
|
||||||
|
+} #}}}
|
||||||
|
+
|
||||||
|
+sub savestate() { #{{{
|
||||||
|
+ my $filename = "$config{wikistatedir}/missingparents.new";
|
||||||
|
+ my $cleanup = sub { unlink ($filename) };
|
||||||
|
+ open (OUT, ">$filename") || error("open $filename: $!", $cleanup);
|
||||||
|
+ foreach my $data (keys %ownfiles) {
|
||||||
|
+ print OUT "$data\n" if $ownfiles{$data};
|
||||||
|
+ }
|
||||||
|
+ rename($filename, "$config{wikistatedir}/missingparents") ||
|
||||||
|
+ error("rename $filename: $!", $cleanup);
|
||||||
|
+} #}}}
|
||||||
|
+
|
||||||
|
+sub needsdelete (@) { #{{{
|
||||||
|
+ my $files=shift;
|
||||||
|
+
|
||||||
|
+ my @mydel;
|
||||||
|
+ my $pruned = 1;
|
||||||
|
+ do {
|
||||||
|
+ $pruned = 0;
|
||||||
|
+ foreach my $file (keys %ownfiles) {
|
||||||
|
+ my $page = pagename($file);
|
||||||
|
+ if (! IkiWiki::PageSpec::match_has_child($page, "")) {
|
||||||
|
+ # No children -- get rid of it
|
||||||
|
+ push @mydel, $page;
|
||||||
|
+ delete $ownfiles{$file};
|
||||||
|
+ IkiWiki::delpage($page);
|
||||||
|
+ unlink $config{srcdir}."/".$file;
|
||||||
|
+ $pruned = 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ } while($pruned);
|
||||||
|
+ foreach my $page (@mydel){
|
||||||
|
+ push @{$files}, $page;
|
||||||
|
+ }
|
||||||
|
+} #}}}
|
||||||
|
+
|
||||||
|
+sub check_matches($) { #{{{
|
||||||
|
+ my $page = shift;
|
||||||
|
+ return if $IkiWiki::pagesources{$page};
|
||||||
|
+
|
||||||
|
+ foreach my $miss (@pagespecs) {
|
||||||
|
+ next unless pagespec_match($page, $miss->{pages});
|
||||||
|
+ my $text = $miss->{generate};
|
||||||
|
+ $text =~ s/\$page/$page/;
|
||||||
|
+ my $output = $page.".mdwn";
|
||||||
|
+ writefile($output, "$config{srcdir}/", $text);
|
||||||
|
+ IkiWiki::newpage($output, $page);
|
||||||
|
+ return $output;
|
||||||
|
+ }
|
||||||
|
+ return "";
|
||||||
|
+} #}}}
|
||||||
|
+
|
||||||
|
+sub needsbuild ($) { #{{{
|
||||||
|
+ my $files=shift;
|
||||||
|
+ my @new;
|
||||||
|
+
|
||||||
|
+ foreach my $file (@{$files}) {
|
||||||
|
+ my $page = pagename $file;
|
||||||
|
+ my $newfile = "";
|
||||||
|
+ foreach my $parent (split '/', $page) {
|
||||||
|
+ $newfile .= $parent;
|
||||||
|
+ my $output = check_matches($newfile);
|
||||||
|
+ push @new, $output if $output;
|
||||||
|
+ $newfile .= "/";
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ foreach my $file (@new) {
|
||||||
|
+ $ownfiles{$file} = 1;
|
||||||
|
+ push @{$files}, $file;
|
||||||
|
+ }
|
||||||
|
+} #}}}
|
||||||
|
+
|
||||||
|
+1
|
||||||
|
Index: IkiWiki/Plugin/rst.pm
|
||||||
|
===================================================================
|
||||||
|
--- IkiWiki/Plugin/rst.pm (revision 3926)
|
||||||
|
+++ IkiWiki/Plugin/rst.pm (working copy)
|
||||||
|
@@ -25,7 +25,7 @@
|
||||||
|
html = publish_string(stdin.read(), writer_name='html',
|
||||||
|
settings_overrides = { 'halt_level': 6,
|
||||||
|
'file_insertion_enabled': 0,
|
||||||
|
- 'raw_enabled': 0 }
|
||||||
|
+ 'raw_enabled': 1 }
|
||||||
|
);
|
||||||
|
print html[html.find('<body>')+6:html.find('</body>')].strip();
|
||||||
|
";
|
||||||
|
Index: IkiWiki.pm
|
||||||
|
===================================================================
|
||||||
|
--- IkiWiki.pm (revision 3926)
|
||||||
|
+++ IkiWiki.pm (working copy)
|
||||||
|
@@ -16,7 +16,7 @@
|
||||||
|
use Exporter q{import};
|
||||||
|
our @EXPORT = qw(hook debug error template htmlpage add_depends pagespec_match
|
||||||
|
bestlink htmllink readfile writefile pagetype srcfile pagename
|
||||||
|
- displaytime will_render gettext urlto targetpage
|
||||||
|
+ displaytime will_render gettext urlto targetpage newpage delpage
|
||||||
|
%config %links %renderedfiles %pagesources %destsources);
|
||||||
|
our $VERSION = 2.00; # plugin interface version, next is ikiwiki version
|
||||||
|
our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE
|
||||||
|
@@ -330,6 +336,30 @@
|
||||||
|
error("failed renaming $newfile to $destdir/$file: $!", $cleanup);
|
||||||
|
} #}}}
|
||||||
|
|
||||||
|
+sub newpage($$) { #{{{
|
||||||
|
+ my $file=shift;
|
||||||
|
+ my $page=shift;
|
||||||
|
+
|
||||||
|
+ $pagemtime{$page} = $pagectime{$page} = time;
|
||||||
|
+ $pagesources{$page} = $file;
|
||||||
|
+ $pagecase{lc $page} = $page;
|
||||||
|
+} #}}}
|
||||||
|
+
|
||||||
|
+sub delpage($) { #{{{
|
||||||
|
+ my $page=shift;
|
||||||
|
+ $links{$page}=[];
|
||||||
|
+ $renderedfiles{$page}=[];
|
||||||
|
+ $pagemtime{$page}=0;
|
||||||
|
+ prune($config{destdir}."/".$_)
|
||||||
|
+ foreach @{$oldrenderedfiles{$page}};
|
||||||
|
+ delete $pagesources{$page};
|
||||||
|
+ foreach (keys %destsources) {
|
||||||
|
+ if ($destsources{$_} eq $page) {
|
||||||
|
+ delete $destsources{$_};
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+} #}}}
|
||||||
|
+
|
||||||
|
my %cleared;
|
||||||
|
sub will_render ($$;$) { #{{{
|
||||||
|
my $page=shift;
|
||||||
|
</pre>
|
Loading…
Reference in New Issue