inline: Run format hook first
authorJoey Hess <joey@gnu.kitenet.net>
Fri, 26 Dec 2008 21:08:33 +0000 (16:08 -0500)
committerJoey Hess <joey@gnu.kitenet.net>
Fri, 26 Dec 2008 21:09:23 +0000 (16:09 -0500)
inline has a format hook that is an optimisation hack. Until this hook
runs, the inlined content is not present on the page. This can prevent
other format hooks, that process that content, from acting on inlined
content. In bug ##509710, we discovered this happened commonly for the
embed plugin, but it could in theory happen for many other plugins (color,
cutpaste, etc) that use format to fill in special html after sanitization.

The ordering was essentially random (hash key order). That's kinda a good
thing, because hooks should be independent of other hooks and able to run
in any order. But for things like inline, that just doesn't work.

To fix the immediate problem, let's make hooks able to be registered as
running "first". There was already the ability to make them run "last".

Now, this simple first/middle/last ordering is obviously not going to work
if a lot of things need to run first, or last, since then we'll be back to
being unable to specify ordering inside those sets. But before worrying about
that too much, and considering dependency ordering, etc, observe how few
plugins use last ordering: Exactly one needs it. And, so far, exactly one
needs first ordering. So for now, KISS.

Another implementation note: I could have sorted the plugins with
first/last/middle as the primary key, and plugin name secondary, to get a
guaranteed stable order. Instead, I chose to preserve hash order. Two
opposing things pulled me toward that decision:

1. Since has order is randomish, it will ensure that no accidental
   ordering assumptions are made.
2. Assume for a minute that ordering matters a lot more than expected.
   Drastically changing the order a particular configuration uses could
   result in a lot of subtle bugs cropping up. (I hope this assumption is
   false, partly due to #1, but can't rule it out.)

IkiWiki.pm
IkiWiki/Plugin/inline.pm
debian/changelog
doc/plugins/write.mdwn

index cc1e89acc04db45f18cb90a40e7a2a538b4350f4..54e00ec7b57bae548c1e559e246a3cc6763ea131 100644 (file)
@@ -1536,15 +1536,19 @@ sub run_hooks ($$) {
        my $sub=shift;
 
        if (exists $hooks{$type}) {
-               my @deferred;
+               my (@first, @middle, @last);
                foreach my $id (keys %{$hooks{$type}}) {
-                       if ($hooks{$type}{$id}{last}) {
-                               push @deferred, $id;
-                               next;
+                       if ($hooks{$type}{$id}{first}) {
+                               push @first, $id;
+                       }
+                       elsif ($hooks{$type}{$id}{last}) {
+                               push @last, $id;
+                       }
+                       else {
+                               push @middle, $id;
                        }
-                       $sub->($hooks{$type}{$id}{call});
                }
-               foreach my $id (@deferred) {
+               foreach my $id (@first, @middle, @last) {
                        $sub->($hooks{$type}{$id}{call});
                }
        }
index 8490b455fa8b50153f1368f31b8e6d1e27afd745..58da0beb86f2aac49afadcd403bd3147df847926 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+!/usr/bin/perl
 # Page inlining and blogging.
 package IkiWiki::Plugin::inline;
 
@@ -22,7 +22,7 @@ sub import {
                call => \&IkiWiki::preprocess_inline);
        hook(type => "pagetemplate", id => "inline",
                call => \&IkiWiki::pagetemplate_inline);
-       hook(type => "format", id => "inline", call => \&format);
+       hook(type => "format", id => "inline", call => \&format, first => 1);
        # Hook to change to do pinging since it's called late.
        # This ensures each page only pings once and prevents slow
        # pings interrupting page builds.
index 96a70fcc9a8809c259d0f313b51145b992ed5483..0fa6590f0efa6f390594dca2c9f631c090e84d47 100644 (file)
@@ -5,6 +5,8 @@ ikiwiki (2.72) UNRELEASED; urgency=low
   * camelcase: Add camelcase_ignore setting.
   * googlecalendar: Add runtime deprecation warning.
   * comments: Deal with users entering unqualified or partial urls.
+  * inline: Run format hook first, to ensure other format hooks can affect
+    inlined content.  Closes: #509710
 
  -- Joey Hess <joeyh@debian.org>  Mon, 22 Dec 2008 19:02:16 -0500
 
index b6fa96f913ff7c2cb89a1e9fa78b1241abad6958..9b5cf27f7c91028066cea797f197a8a5cc8601a1 100644 (file)
@@ -55,8 +55,8 @@ plugin, and a "call" parameter, which tells what function to call for the
 hook.
 
 An optional "last" parameter, if set to a true value, makes the hook run
-after all other hooks of its type. Useful if the hook depends on some other
-hook being run first.
+after all other hooks of its type, and an optional "first" parameter makes
+it run first. Useful if the hook depends on some other hook being run first.
 
 ## Types of hooks