Merge branch 'ready/templatebody'
authorSimon McVittie <smcv@debian.org>
Mon, 15 Sep 2014 20:52:03 +0000 (21:52 +0100)
committerSimon McVittie <smcv@debian.org>
Mon, 15 Sep 2014 20:52:03 +0000 (21:52 +0100)
1  2 
IkiWiki.pm
doc/ikiwiki/directive/edittemplate.mdwn

diff --combined IkiWiki.pm
index 4ad365c1d90991e9098ea2439c231b46d4c43ee1,9511c8303dfadc056107ae35e5fb6dca3417911b..d5d11ee857c02b1520fc6a971032cc592df78d23
@@@ -14,7 -14,7 +14,7 @@@ use vars qw{%config %links %oldlinks %p
        %pagestate %wikistate %renderedfiles %oldrenderedfiles
        %pagesources %delpagesources %destsources %depends %depends_simple
        @mass_depends %hooks %forcerebuild %loaded_plugins %typedlinks
-       %oldtypedlinks %autofiles @underlayfiles $lastrev};
+       %oldtypedlinks %autofiles @underlayfiles $lastrev $phase};
  
  use Exporter q{import};
  our @EXPORT = qw(hook debug error htmlpage template template_depends
@@@ -34,6 -34,11 +34,11 @@@ our $DEPEND_CONTENT=1
  our $DEPEND_PRESENCE=2;
  our $DEPEND_LINKS=4;
  
+ # Phases of processing.
+ sub PHASE_SCAN () { 0 }
+ sub PHASE_RENDER () { 1 }
+ $phase = PHASE_SCAN;
  # Optimisation.
  use Memoize;
  memoize("abs2rel");
@@@ -152,7 -157,8 +157,8 @@@ sub getsetup () 
                type => "internal",
                default => [qw{mdwn link inline meta htmlscrubber passwordauth
                                openid signinedit lockedit conditional
-                               recentchanges parentlinks editpage}],
+                               recentchanges parentlinks editpage
+                               templatebody}],
                description => "plugins to enable by default",
                safe => 0,
                rebuild => 1,
@@@ -1819,8 -1825,7 +1825,8 @@@ sub loadindex () 
                        open ($in, "<", "$config{wikistatedir}/indexdb") || return;
                }
                else {
 -                      $config{gettime}=1; # first build
 +                      # gettime on first build
 +                      $config{gettime}=1 unless defined $config{gettime};
                        return;
                }
        }
@@@ -2022,11 -2027,19 +2028,19 @@@ sub template_depends ($$;@) 
        if (defined $page && defined $tpage) {
                add_depends($page, $tpage);
        }
-       
        my @opts=(
                filter => sub {
                        my $text_ref = shift;
                        ${$text_ref} = decode_utf8(${$text_ref});
+                       run_hooks(readtemplate => sub {
+                               ${$text_ref} = shift->(
+                                       id => $name,
+                                       page => $tpage,
+                                       content => ${$text_ref},
+                                       untrusted => $untrusted,
+                               );
+                       });
                },
                loop_context_vars => 1,
                die_on_bad_params => 0,
@@@ -2460,19 -2473,6 +2474,19 @@@ sub pagespec_match ($$;@) 
        return $sub->($page, @params);
  }
  
 +# e.g. @pages = sort_pages("title", \@pages, reverse => "yes")
 +#
 +# Not exported yet, but could be in future if it is generally useful.
 +# Note that this signature is not the same as IkiWiki::SortSpec::sort_pages,
 +# which is "more internal".
 +sub sort_pages ($$;@) {
 +      my $sort = shift;
 +      my $list = shift;
 +      my %params = @_;
 +      $sort = sortspec_translate($sort, $params{reverse});
 +      return IkiWiki::SortSpec::sort_pages($sort, @$list);
 +}
 +
  sub pagespec_match_list ($$;@) {
        my $page=shift;
        my $pagespec=shift;
@@@ -2578,48 -2578,21 +2592,48 @@@ our @ISA = 'IkiWiki::SuccessReason'
  
  package IkiWiki::SuccessReason;
  
 +# A blessed array-ref:
 +#
 +# [0]: human-readable reason for success (or, in FailReason subclass, failure)
 +# [1]{""}:
 +#      - if absent or false, the influences of this evaluation are "static",
 +#        see the influences_static method
 +#      - if true, they are dynamic (not static)
 +# [1]{any other key}:
 +#      the dependency types of influences, as returned by the influences method
 +
  use overload (
 +      # in string context, it's the human-readable reason
        '""'    => sub { $_[0][0] },
 +      # in boolean context, SuccessReason is 1 and FailReason is 0
        '0+'    => sub { 1 },
 +      # negating a result gives the opposite result with the same influences
        '!'     => sub { bless $_[0], 'IkiWiki::FailReason'},
 +      # A & B = (A ? B : A) with the influences of both
        '&'     => sub { $_[1]->merge_influences($_[0], 1); $_[1] },
 +      # A | B = (A ? A : B) with the influences of both
        '|'     => sub { $_[0]->merge_influences($_[1]); $_[0] },
        fallback => 1,
  );
  
 +# SuccessReason->new("human-readable reason", page => deptype, ...)
 +
  sub new {
        my $class = shift;
        my $value = shift;
        return bless [$value, {@_}], $class;
  }
  
 +# influences(): return a reference to a copy of the hash
 +# { page => dependency type } describing the pages that indirectly influenced
 +# this result, but would not cause a dependency through ikiwiki's core
 +# dependency logic.
 +#
 +# See [[todo/dependency_types]] for extensive discussion of what this means.
 +#
 +# influences(page => deptype, ...): remove all influences, replace them
 +# with the arguments, and return a reference to a copy of the new influences.
 +
  sub influences {
        my $this=shift;
        $this->[1]={@_} if @_;
        return \%i;
  }
  
 +# True if this result has the same influences whichever page it matches,
 +# For instance, whether bar matches backlink(foo) is influenced only by
 +# the set of links in foo, so its only influence is { foo => DEPEND_LINKS },
 +# which does not mention bar anywhere.
 +#
 +# False if this result would have different influences when matching
 +# different pages. For instance, when testing whether link(foo) matches bar,
 +# { bar => DEPEND_LINKS } is an influence on that result, because changing
 +# bar's links could change the outcome; so its influences are not the same
 +# as when testing whether link(foo) matches baz.
 +#
 +# Static influences are one of the things that make pagespec_match_list
 +# more efficient than repeated calls to pagespec_match.
 +
  sub influences_static {
        return ! $_[0][1]->{""};
  }
  
 +# Change the influences of $this to be the influences of "$this & $other"
 +# or "$this | $other".
 +#
 +# If both $this and $other are either successful or have influences,
 +# or this is an "or" operation, the result has all the influences from
 +# either of the arguments. It has dynamic influences if either argument
 +# has dynamic influences.
 +#
 +# If this is an "and" operation, and at least one argument is a
 +# FailReason with no influences, the result has no influences, and they
 +# are not dynamic. For instance, link(foo) matching bar is influenced
 +# by bar, but enabled(ddate) has no influences. Suppose ddate is disabled;
 +# then (link(foo) and enabled(ddate)) not matching bar is not influenced by
 +# bar, because it would be false however often you edit bar.
 +
  sub merge_influences {
        my $this=shift;
        my $other=shift;
        my $anded=shift;
  
 +      # This "if" is odd because it needs to avoid negating $this
 +      # or $other, which would alter the objects in-place. Be careful.
        if (! $anded || (($this || %{$this->[1]}) &&
                         ($other || %{$other->[1]}))) {
                foreach my $influence (keys %{$other->[1]}) {
        }
  }
  
 +# Change $this so it is not considered to be influenced by $torm.
 +
  sub remove_influence {
        my $this=shift;
        my $torm=shift;
index 6269f5dd8a23935f1970fe62b998ecc15f569885,b3177daa806af4b7bf2e37d12ee795bff97d2239..70bd2ad258c78c2a2655544323e127fa9a09d459
@@@ -18,29 -18,25 +18,37 @@@ the directive displaying a note about t
  "silent=yes".
  
  Often the template page contains a simple skeleton for a particular type of
- page. For the bug report pages in the above example, it might look
- something like:
+ page, wrapped in a [[templatebody]] directive. For the bug report pages in
the above example, it might look something like:
  
+       \[[!templatebody <<ENDBODY
        Package: 
        Version: 
        Reproducible: y/n
        Details:
+       ENDBODY]]
  
  The template page can also contain [[!cpan HTML::Template]] directives,
 -like other ikiwiki [[templates]]. Currently only one variable is
 -set: `<TMPL_VAR name>` is replaced with the name of the page being
 -created.
 +like other ikiwiki [[templates]].
 +
 +These variables might be set:
 +
 +* `<TMPL_VAR name>` is replaced with the name of the page being
 +  created.
 +  
 +* `<TMPL_VAR uuid>` is replaced with a version 4 (random) UUID
 +  suitable for use in `\[[!meta guid="urn:uuid:<TMPL_VAR uuid>"]]`.
 +  (Requires the `UUID::Tiny` Perl module if not running on Linux.)
 +
 +* `<TMPL_VAR time>` is replaced with the current (template generation)
 +  time using a fixed format (RFC 3339, `%Y-%m-%dT%H:%M:%SZ`),
 +  suitable for use in `\[[!meta date="<TMPL_VAR time>"]]`
 +  (see [[meta]]) or `\[[!date "<TMPL_VAR time>"]]` (see [[date]]).
  
+ Text outside the [[templatebody]] directive is not part of the template,
+ and can be used to document it.
+ If the template does not contain a [[templatebody]] directive, the entire
+ source of the page is used for the template. This is deprecated.
  [[!meta robots="noindex, follow"]]