#!/usr/bin/perl # Ikiwiki "blocks" relationship plugin. package IkiWiki::Plugin::blocks; use warnings; use strict; use IkiWiki 3.00; sub import { hook(type => "getsetup", id => "blocks", call => \&getsetup); hook(type => "checkconfig", id => "skeleton", call => \&checkconfig); } sub getsetup () { return plugin => { safe => 1, rebuild => 1, }, blocks_names => { type => "string", example => "blocks/blockedby", description => "comma separated list of defined relationship pairs, the forward and backward name separated by a slash", safe => 1, rebuild => 1, }, } sub checkconfig () { my $blocksnames; if (defined $config{blocks_names}) { $blocksnames = $config{blocks_names}; } else { $blocksnames = "blocks/blockedby"; } while ( $blocksnames =~ /([^ ]+)/g ) { if ( $1 =~ m@([a-zA-Z0-9]+)(/([a-zA-Z0-9]+))?@ ) { my $from = $1; my $to = $3; hook( type => "preprocess", shortcut => 1, # gets interpreted by listdirectives; see doc/bugs/cannot_preview_shortcuts.mdwn / ikiwiki commit 354d22e2 no_override => 1, id => $from, scan => 1, call => sub { preprocess_blocks($from, 1, @_); } ); if ($to) { hook( type => "preprocess", shortcut => 1, no_override => 1, id => $to, scan => 1, call => sub { preprocess_blocks($from, 0, @_); } ); } my $backward_match; my $backward_name; my $forward_match; my $forward_name; $backward_match = sub ($$;@) { my $page=shift; my $glob=shift; return IkiWiki::PageSpec::match_backlink($page, $glob, linktype => $from, @_); }; $backward_name = "IkiWiki::PageSpec::match_$from"; if ($to) { $forward_match = sub ($$;@) { my $page=shift; my $glob=shift; return IkiWiki::PageSpec::match_link($page, $glob, linktype => $from, @_); }; $forward_name = "IkiWiki::PageSpec::match_$to"; } { no strict 'refs'; if ($to) { *$forward_name = $forward_match; } *$backward_name = $backward_match; } } else { error gettext("Malformed option in blocks_names"); } } } sub preprocess_blocks ($$@) { # with flip=0, the directive occurring on page A pointing at page B # means that A $relation B, with flip=1, it means B $relation A my $relation = shift; my $flip = shift; if (! @_) { return ""; } my %params=@_; my $page = $params{page}; delete $params{page}; delete $params{destpage}; delete $params{preview}; foreach my $blocks (keys %params) { $blocks=linkpage($blocks); # hidden WikiLink if ( $flip == 0 ) { add_link($page, $blocks, $relation); } else { add_link($blocks, $page, $relation); } } return ""; } 1