summaryrefslogtreecommitdiff
path: root/doc/todo/auto-create_tag_pages_according_to_a_template.mdwn
blob: 6118cb014bfef614ec621b4e2df425f077b66cb4 (plain)

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 on branch autotag:

git://git.liegesta.at/git/ikiwiki

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]]

First of, sorry that it took me so damn long to answer. I didn't lose interest but it took a while for me to find the time and motivation to address you suggestions. --[[David_Riebenbauer]]

  • 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?)

The first two points should be addressed in da5d29f95f6e693e8c14be1b896cf25cf4fdb3c0. And sure, I can add the spaces. --[[David_Riebenbauer]]

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.)

You're right. I must have been some confused by some other promplem I introduced then. Reverted. --[[David_Riebenbauer]]

Sorry, That one was reverted anyway. --[[David_Riebenbauer]]

I reverted the commit and addressed the issue in a358d74bef51dae31332ff27e897fe04834571e6 and 981400177d68a279f485727be3f013e68f0bf691. --[[David_Riebenbauer]]

This doesn't seem to have all the refinements that autoindex has:

  • autoindex attaches the record of deletions to the index page, which is (nearly) guaranteed to exist; this one attaches the record of deletions to the deleted page's page state. Won't that tend to result in losing the record along with the deleted page?

  • autoindex forgets that a page was deleted when that page is re-created

  • autoindex forgets that a page was deleted when it's no longer needed anyway (this may be harder for autotag?)

It'd probably be an interesting test of the core change to port autoindex to use it? (Adding the file to the RCS would be necessary to get parity with autoindex.) --[[smcv]]

Regarding the call from IkiWiki.pm to Render.pm, wouldn't this be quite easy to solve by moving verify_src_file to IkiWiki.pm? --[[smcv]]