195 lines
7.2 KiB
Markdown
195 lines
7.2 KiB
Markdown
It would be great if I could tell ikiwiki to automatically instantiate pages for each [[tag|/tags]], according to a template, especially when `$tagbase` is set.
|
||
|
||
Tags are mainly specific to the object to which they’re stuck. However, I often use them the other way around, too: as concepts. And sometimes I’d like to see all pages related to a given concept (“tagged with a given tag”). The only way to do this with ikiwiki is to instantiate a page for each tag and slap a map on it. This is quite tedious and I’d really love to see Ikiwiki do so by default for all tags.
|
||
|
||
Also see: <http://madduck.net/blog/2008.01.06:new-blog/> and <http://users.itk.ppke.hu/~cstamas/code/ikiwiki/autocreatetagpage/>
|
||
|
||
[[!tag wishlist plugins/tag patch patch/core]]
|
||
|
||
I would love to see this as well. -- dato
|
||
|
||
---
|
||
|
||
I have create a patch to [[tag.pm|plugins/tag]] for add the option for auto create tag pages.
|
||
A new setting is used to enable or disable auto-create tag pages, `tag_autocreate`.
|
||
The new tag file is created during the preprocess phase.
|
||
The new tag file is then complied during the change phase.
|
||
|
||
_tag.pm from version 3.01_
|
||
|
||
|
||
--- tag.pm 2009-02-06 10:26:03.000000000 -0700
|
||
+++ tag_new.pm 2009-02-06 12:17:19.000000000 -0700
|
||
@@ -14,6 +14,7 @@
|
||
hook(type => "preprocess", id => "tag", call => \&preprocess_tag, scan => 1);
|
||
hook(type => "preprocess", id => "taglink", call => \&preprocess_taglink, scan => 1);
|
||
hook(type => "pagetemplate", id => "tag", call => \&pagetemplate);
|
||
+ hook(type => "change", id => "tag", call => \&change);
|
||
}
|
||
|
||
sub getopt () {
|
||
@@ -36,6 +37,36 @@
|
||
safe => 1,
|
||
rebuild => 1,
|
||
},
|
||
+ tag_autocreate => {
|
||
+ type => "boolean",
|
||
+ example => 0,
|
||
+ description => "Auto-create the new tag pages, uses autotagpage.tmpl ",
|
||
+ safe => 1,
|
||
+ rebulid => 1,
|
||
+ },
|
||
+}
|
||
+
|
||
+my $autocreated_page = 0;
|
||
+
|
||
+sub gen_tag_page($) {
|
||
+ my $tag=shift;
|
||
+
|
||
+ my $tag_file=$tag.'.'.$config{default_pageext};
|
||
+ return if (-f $config{srcdir}.$tag_file);
|
||
+
|
||
+ my $template=template("autotagpage.tmpl");
|
||
+ $template->param(tag => $tag);
|
||
+ writefile($tag_file, $config{srcdir}, $template->output);
|
||
+ $autocreated_page = 1;
|
||
+
|
||
+ if ($config{rcs}) {
|
||
+ IkiWiki::disable_commit_hook();
|
||
+ IkiWiki::rcs_add($tag_file);
|
||
+ IkiWiki::rcs_commit_staged(
|
||
+ gettext("Automatic tag page generation"),
|
||
+ undef, undef);
|
||
+ IkiWiki::enable_commit_hook();
|
||
+ }
|
||
}
|
||
|
||
sub tagpage ($) {
|
||
@@ -47,6 +78,10 @@
|
||
$tag=~y#/#/#s; # squash dups
|
||
}
|
||
|
||
+ if (defined $config{tag_autocreate} && $config{tag_autocreate} ) {
|
||
+ gen_tag_page($tag);
|
||
+ }
|
||
+
|
||
return $tag;
|
||
}
|
||
|
||
@@ -125,4 +160,18 @@
|
||
}
|
||
}
|
||
|
||
+sub change(@) {
|
||
+ return unless($autocreated_page);
|
||
+ $autocreated_page = 0;
|
||
+
|
||
+ # This refresh/saveindex is to complie the autocreated tag pages
|
||
+ IkiWiki::refresh();
|
||
+ IkiWiki::saveindex();
|
||
+
|
||
+ # This refresh/saveindex is to fix the Tags link
|
||
+ # With out this additional refresh/saveindex the tag link displays ?tag
|
||
+ IkiWiki::refresh();
|
||
+ IkiWiki::saveindex();
|
||
+}
|
||
+
|
||
|
||
|
||
This uses a [[template|wikitemplates]] called `autotagpage.tmpl`, here is my template file:
|
||
|
||
\[[!inline pages="link(<TMPL_VAR TAG>)" archive="yes"]]
|
||
|
||
|
||
A quirk I have not figured out is during the `sub change`, see my comments in the code.
|
||
I am not sure if that is the best way to handle it.
|
||
|
||
[[!tag patch]]
|
||
-- Jeremy Schultz <jeremy.schultz@uleth.ca>
|
||
|
||
No, this doesn't help:
|
||
|
||
+ # This refresh/saveindex is to fix the Tags link
|
||
+ # With out this additional refresh/saveindex the tag link displays ?tag
|
||
+ IkiWiki::refresh();
|
||
+ IkiWiki::saveindex();
|
||
|
||
On the second extra pass, it doesn't notice that it has to update the "?"-link. If I run ikiwiki once more, it is updated. I don't know yet how this should be fixed, because I don't know the internals of ikiwiki well enough. Something inhibits detecting the need to update in refresh() in Render.pm; perhaps, this condition:
|
||
|
||
if (! $pagemtime{$page}) {
|
||
...
|
||
push @add, $file;
|
||
...
|
||
}
|
||
|
||
is not satisfied for the newly created tag page. I shall put debug msgs into Render.pm to find out better how it works. --Ivan Z.
|
||
|
||
---
|
||
|
||
I've made another attempt at fixiing this
|
||
|
||
The current progress can be found at my [git repository][gitweb] on branch
|
||
`autotag`:
|
||
|
||
git://git.liegesta.at/git/ikiwiki
|
||
|
||
[gitweb]: http://git.liegesta.at/?p=ikiwiki.git;a=shortlog;h=refs/heads/autotag (gitweb for branch autotag)
|
||
|
||
It's not entirely finished yet, but already quite usable. Testing and comments
|
||
on code quality, implementation details, as well as other patches would be
|
||
appreciated.
|
||
|
||
Here's what it does right now:
|
||
|
||
* enabled by setting `tag_autocreate=1` in the configuration.
|
||
* Tag pages will be created in `tagbase` from the template `autotag.tmpl`.
|
||
* Will correctly render all links, and dependencies. Well, AFAIK.
|
||
* When a tag page is deleted it will automatically recreated from template. (I
|
||
consider this a feature, not a bug)
|
||
* Requires a rebuild on first use.
|
||
* Adds a function `add_autofile()` to the plugin API, to do all this.
|
||
|
||
Todo/Bugs:
|
||
|
||
* Will still create a page even if there's a page other than `$tag` under
|
||
`tagbase` satisfying the tag link.
|
||
* Call from `IkiWiki.pm` to `Render.pm`, which adds a module dependency in the
|
||
wrong direction.
|
||
* Add files to RCS.
|
||
* Unit tests.
|
||
* Proper documentation.
|
||
|
||
--[[David_Riebenbauer]]
|
||
|
||
> Starting review of this. Some of your commits are to very delicate,
|
||
> optimised, and security-sensitive ground, so I have to look at them very
|
||
> carefully. --[[Joey]]
|
||
>
|
||
> * In the refactoring in f3abeac919c4736429bd3362af6edf51ede8e7fe,
|
||
> you introduced at least 2 bugs, one a possible security hole.
|
||
> Now one part of the code tests `if ($file)` and the other
|
||
> caller tests `if ($f)`. These two tests both tested `if (! defined $f)`
|
||
> before. Notice that the variable needs to be the untainted variable
|
||
> for both. Also notice that `if ($f)` fails if `$f` contains `0`,
|
||
> which is a very common perl gotcha.
|
||
> * Your refactored code changes `-l $_ || -d _` to `-l $file || -d $file`.
|
||
> The latter makes one more stat system call; note the use of a
|
||
> bare `_` in the first to make perl reuse the stat buffer.
|
||
> * (As a matter of style, could you put a space after the commas in your
|
||
> perl?)
|
||
>
|
||
> I'd like to cherry-pick the above commit, once it's in shape, before
|
||
> looking at the rest in detail. So just a few other things that stood out.
|
||
>
|
||
> * Commit 4af4d26582f0c2b915d7102fb4a604b176385748 seems unnecessary.
|
||
> `srcfile($file, 1)` already is documented to return undef if the
|
||
> file does not exist. (But without the second parameter, it throws
|
||
> an error.)
|
||
>
|
||
> * Commit f58f3e1bec41ccf9316f37b014ce0b373c8e49e1 adds a line
|
||
> that is intented by a space, not a tab.
|
||
>
|
||
> * Commit f58f3e1bec41ccf9316f37b014ce0b373c8e49e1 says that auto-added
|
||
> files will be recreated if the user deletes them. That seems bad.
|
||
> `autoindex` goes to some trouble to not recreate deleted files.
|