From: https://www.google.com/accounts/o8/id?id=AItOawlqWSY9PNYRysA9vrU-JiQh7-s7q6SOcIE Date: Thu, 15 Mar 2012 22:52:13 +0000 (-0400) Subject: Copy 'template.pm' re-write from website X-Git-Url: https://sipb.mit.edu/gitweb.cgi/ikiwiki.git/commitdiff_plain/b9b4bfd29dc1b106c133402a3c4a97aeaf07fe2e Copy 'template.pm' re-write from website --- diff --git a/doc/todo/allow_TMPL__95__LOOP_in_template_directives.mdwn b/doc/todo/allow_TMPL__95__LOOP_in_template_directives.mdwn new file mode 100644 index 000000000..a8d100551 --- /dev/null +++ b/doc/todo/allow_TMPL__95__LOOP_in_template_directives.mdwn @@ -0,0 +1,258 @@ +[[!tag patch]] + +[[!templte id="note" text=""" +Simply copied this from my website +[[http://www.camco.ie/code/ikiwiki,3.20120202,20120313a/]] +feel free to reformat / delete"""]] + +The following re-write allows for multiple definitions of the +same tag value in a template definition. This, in turn, allows +us to use TMPL_LOOPS in our template directives; all-be-it in a +rather limited way. + +I would, personally, only use this feature for very basic loops +and, although nested loops *might* be possible (with a little +more tinkering) it think any attempt would be better served by +[[Kathyrn Anderson's|http://www.katspace.org/]] [[field et +al.|http://ikiwiki.info/plugins/contrib/field/]] plugin. + +It *is* (primarily) intended to allow insertion of organised CSS +blocks (i.e. `
`) through template directives (since i can't +seem to get HTML and Markup to mix the way I want). + +[[!template id="note" text=""" +Apologies for the re-write. I struggle reading perl code that +I didn't write and (probably too often) re-format to reduce my +head-aches. Anyway it didn't make sense to post the patch since +everything's changed now. +"""]] + +# `lib/perl5/IkiWiki/Plugin/template.pm` + +[[!format perl """ + + #!/usr/bin/perl + # Structured template plugin. + package IkiWiki::Plugin::template ; + + use warnings ; + use strict ; + use IkiWiki 3.00 ; + use Encode ; + + sub mktmpl_hash( $ ; $ ; @ ) ; + # declare to supress warning in recursive call + sub mktmpl_hash( $ ; $ ; @ ) + # make hash for the template, filling + # values from the supplied params + { + my $template = shift( @_ ) + || error( "mktmpl_hash: no template provided" ) ; + my $param_src = shift( @_ ) + || error( "mktmpl_hash: no parameters" ) ; + + my $path ; + if( $#_ > 0 ) + { + $path = [ @_ ] ; + } else { + $path = shift(@_) || [] ; + } ; + + my %params ; + + my @path_vars ; + if( $#{$path} < 0 ) + { + @path_vars = $template->query() ; + } else { + @path_vars = $template->query( loop => $path ) ; + } ; + + foreach my $var ( @path_vars ) + { + push( @{$path}, $var ) ; + my $param_type = $template->query( name => $path ) ; + if( $param_type eq 'VAR' ) + { + my @var_path = split( /_/, $var ) ; + if( $var_path[0] ne '' ) + { + $path->[-1] = join( '_', @var_path[1..$#var_path] ) + if( $var_path[0] eq 'raw' ) ; + $params{$var} = shift( @{$param_src->{$path->[-1]}} ) + || return(undef) ; + } ; + } elsif( $param_type eq 'LOOP' ) + { + $params{$var} = [] ; + push( @{$params{$var}}, $_ ) + while( $_ = mktmpl_hash($template,$param_src,$path) ) ; + } ; + pop( @{$path} ) ; + } ; + return( \%params ) ; + } ; + + sub proc_tmpl_hash( $ ; $ ; $ ; $ ) ; + # declare to supress warning in recursive call + sub proc_tmpl_hash( $ ; $ ; $ ; $ ) + # walk the hash, preprocess and + # convert to html + { + my $tmpl_hash = shift( @_ ) ; + my $page = shift( @_ ) ; + my $destpage = shift( @_ ) ; + my $scan = shift( @_ ) ; + foreach my $key ( keys(%{$tmpl_hash}) ) + { + unless( ref($tmpl_hash->{$key}) ) + # here we assume that + # any reference is an + # array and allow it to + # fail if that's false + { + $tmpl_hash->{$key} = + IkiWiki::preprocess( + $page, + $destpage, + $tmpl_hash->{$key}, + $scan ) ; + my @key_path = split( /_/, $key ) ; + $tmpl_hash->{$key} = + IkiWiki::htmlize( + $page, + $destpage, + pagetype($pagesources{$page}), + $tmpl_hash->{$key}, ) + unless( $key_path[0] eq 'raw' ) ; + } else { + proc_tmpl_hash( $_, $page, $destpage, $scan ) + foreach( @{$tmpl_hash->{$key}} ) ; + } ; + } ; + } ; + + # "standard" ikiwiki definitions / hooks + + sub import + { + hook( type => "getsetup", + id => "template", + call => \&getsetup ) ; + hook( type => "preprocess", + id => "template", + call => \&preprocess, + scan => 1 ) ; + } ; + + sub getsetup() + { + return( + plugin => { + safe => 1, + rebuild => undef, + section => "widget", + }, ) ; + } ; + + sub preprocess( @ ) + { + # first process arguments into arrays of values + my %params ; + + my( $key, $value ) ; + while( ($key,$value)=splice(@_,0,2) ) + { + if( exists($params{$key}) ) + { + push( @{$params{$key}}, $value ) ; + } else { + $params{$key} = [ $value ] ; + } ; + } ; + + # set context + my $scan = ! defined( wantarray() ) ; + # This needs to run even in scan + # mode, in order to process links + # and other metadata included via + # the template. + + # check for critical values + if( ! exists($params{id}) ) + { + error( gettext("missing id parameter") ) ; + } ; + + # set some convenience variables + my $id = $params{id}->[$#{$params{id}}] ; + my $page = $params{page}->[$#{$params{page}}] ; + my $destpage = $params{destpage}->[$#{$params{destpage}}] ; + # ... and an essential one for the production pass + $params{basename} = IkiWiki::basename($page) ; + + # load the template + my $template ; + eval { + $template = + template_depends( $id, $page, + blind_cache=>1 ) ; + # The bare id is used, so + # a page templates/$id can + # be used as the template. + } ; + if( $@ ) + { + error( + sprintf( + gettext("failed to process template %s"), + htmllink( + $page, + $destpage, + "/templates/$id") + )." $@" + ) ; + } ; + + # create and process the parameters + my $tmpl_hash = mktmpl_hash( $template, \%params ) ; + proc_tmpl_hash( $tmpl_hash, $page, $destpage, $scan ) ; + # ... and load the template with the values + $template->param( $tmpl_hash ) ; + + # return the processed page chunk + return( IkiWiki::preprocess($page, + $destpage, + $template->output(),$scan) + ) ; + } ; + + 1 ; + +"""]] + +## sample template + + # + + + + + + + + +
+ +## sample iki page + + \[[!meta title="this is my loops page"]] + + \[[!template id="loops" + header0="this is a table" + data0="cell0:0" + data1="cell0:1" + data0="cell1:0" + data0="cell1:1" + ]]