3 package IkiWiki::Plugin::tag;
10 hook(type => "getopt", id => "tag", call => \&getopt);
11 hook(type => "getsetup", id => "tag", call => \&getsetup);
12 hook(type => "checkconfig", id => "tag", call => \&checkconfig);
13 hook(type => "preprocess", id => "tag", call => \&preprocess_tag, scan => 1);
14 hook(type => "preprocess", id => "taglink", call => \&preprocess_taglink, scan => 1);
15 hook(type => "pagetemplate", id => "tag", call => \&pagetemplate);
19 eval q{use Getopt::Long};
21 Getopt::Long::Configure('pass_through');
22 GetOptions("tagbase=s" => \$config{tagbase});
34 description => "parent page tags are located under",
41 description => "autocreate new tag pages?",
47 # TODO document that this can be either an array or a hash with hashes as values
48 description => "extra categorization types",
49 example => "[category, column]"
54 if (defined $config{tagtypes}) {
55 my $tagtypes = $config{tagtypes};
56 if (ref($tagtypes) eq 'HASH') {
60 foreach my $tagtype (@$tagtypes) {
70 # Custom tagtypes have an automatic tagbase equal to the tagtype itself,
74 if ($tagtype eq 'tag') {
75 if (defined $config{tagbase}) {
76 return $config{tagbase};
81 my %tagtypes = tagtypes();
82 if (exists $tagtypes{tagbase}) {
83 return $tagtypes{tagbase};
90 sub tag_autocreate($) {
92 if ($tagtype eq 'tag') {
93 return $config{tag_autocreate};
95 my %tagtypes = tagtypes();
96 if (exists $tagtypes{tag_autocreate}) {
97 return $tagtypes{tag_autocreate};
99 return $config{tag_autocreate};
105 my %tagtypes = tagtypes();
106 while (my ($tagtype, $conf) = each %tagtypes) {
107 my $directive = (defined $conf->{directive}) ? $conf->{directive} : $tagtype ;
109 debug("defining '$tagtype' tagtype with directive '$directive'");
110 hook(type => "preprocess", id => $directive, call => sub { preprocess_custom_tag($tagtype, @_) });
112 debug("defining '$tagtype' tagtype with no directive");
119 my $tagtype=shift || 'tag';
120 my $tagbase=tagbase($tagtype);
123 if ($tag !~ m{^/} && $tagbase) {
124 $tag="/".$tagbase."/".$tag;
125 $tag=~y#/#/#s; # squash dups
131 sub htmllink_tag ($$$;@) {
137 return htmllink($page, $destpage, taglink($tag), %opts);
142 my $tagtype=shift || 'tag';
144 my $debug_ac = tag_autocreate($tagtype);
145 my $debug_tb = tagbase($tagtype);
146 debug("gentag $tag;$tagtype ac=$debug_ac tb=$debug_tb");
148 if (tag_autocreate($tagtype) ||
149 (tagbase($tagtype) && ! tag_autocreate($tagtype))) {
150 debug("gentag $tag;$tagtype TRUE");
151 my $tagpage=taglink($tag,$tagtype);
152 if ($tagpage=~/^\.\/(.*)/) {
159 my $tagfile = newpagefile($tagpage, $config{default_pageext});
161 add_autofile($tagfile, $tagtype, sub {
162 my $message=sprintf(gettext("creating %s page %s"), $tagtype, $tagpage);
165 my $template=template("autotag.tmpl");
166 $template->param(tagname => IkiWiki::basename($tag));
167 $template->param(tag => $tag);
168 $template->param(tagtype => $tagtype);
169 writefile($tagfile, $config{srcdir}, $template->output);
171 IkiWiki::disable_commit_hook();
172 IkiWiki::rcs_add($tagfile);
173 IkiWiki::rcs_commit_staged($message, undef, undef);
174 IkiWiki::enable_commit_hook();
180 sub preprocess_custom_tag ($@) {
186 my $page = $params{page};
187 delete $params{page};
188 delete $params{destpage};
189 delete $params{preview};
191 foreach my $tag (keys %params) {
195 add_link($page, taglink($tag,$tagtype), $tagtype);
197 gentag($tag, $tagtype);
203 sub preprocess_tag(@) {
204 return preprocess_custom_tag('tag', @_);
207 sub preprocess_taglink (@) {
212 return join(" ", map {
214 my $tag=linkpage($2);
215 add_link($params{page}, taglink($tag), 'tag');
217 return htmllink_tag($params{page}, $params{destpage}, $tag,
218 linktext => pagetitle($1));
221 my $tag=linkpage($_);
222 add_link($params{page}, taglink($tag), 'tag');
224 return htmllink_tag($params{page}, $params{destpage}, $tag);
228 $_ ne 'page' && $_ ne 'destpage' && $_ ne 'preview'
232 sub pagetemplate (@) {
234 my $page=$params{page};
235 my $destpage=$params{destpage};
236 my $template=$params{template};
238 my $tags = $typedlinks{$page}{tag};
240 $template->param(tags => [
242 link => htmllink_tag($page, $destpage, $_, rel => "tag")
244 ]) if defined $tags && %$tags && $template->query(name => "tags");
246 if ($template->query(name => "categories")) {
247 # It's an rss/atom template. Add any categories.
248 if (defined $tags && %$tags) {
249 $template->param(categories => [map { category => $_ },
255 package IkiWiki::PageSpec;
257 sub match_tagged ($$;@) {
259 my $glob=IkiWiki::Plugin::tag::taglink(shift);
260 return match_link($page, $glob, linktype => 'tag', @_);