+sub getopt () { #{{{
+ eval q{use Getopt::Long};
+ error($@) if $@;
+ Getopt::Long::Configure('pass_through');
+ GetOptions("tagbase=s" => \$config{tagbase});
+} #}}}
+
+sub getsetup () { #{{{
+ return
+ plugin => {
+ safe => 1,
+ rebuild => undef,
+ },
+ tagbase => {
+ type => "string",
+ example => "tag",
+ description => "parent page tags are located under",
+ safe => 1,
+ rebuild => 1,
+ },
+} #}}}
+
+sub tagpage ($) { #{{{
+ my $tag=shift;
+
+ if ($tag !~ m{^\.?/} &&
+ defined $config{tagbase}) {
+ $tag="/".$config{tagbase}."/".$tag;
+ $tag=~y#/#/#s; # squash dups
+ }
+
+ return $tag;
+} #}}}
+
+sub taglink ($$$;@) { #{{{
+ my $page=shift;
+ my $destpage=shift;
+ my $tag=shift;
+ my %opts=@_;
+
+ return htmllink($page, $destpage, tagpage($tag), %opts);
+} #}}}
+
+sub preprocess_tag (@) { #{{{