279 lines
6.8 KiB
Markdown
279 lines
6.8 KiB
Markdown
[[!tag patch todo]]
|
|
|
|
[[!template 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 [[plugins/template]] definition. This, in turn, allows
|
|
us to use TMPL_LOOPS in our [[ikiwiki/directive/template]] directives; all-be-it in a
|
|
rather limited way.
|
|
|
|
> I'm willing to consider such a feature, but it needs to be presented in
|
|
> the form of a patch that is reviewable, not a gratuitous rewrite.
|
|
> --[[Joey]]
|
|
|
|
>> Yes, my apologies for that. The two worker functions `mktmpl_hash`
|
|
and `proc_tmpl_hash` are new. The `preprocess` function then starts
|
|
by arranging the parameters into an array. This array is passed to the
|
|
`mktmpl_hash` and it creates a hash, suitable for passing into the
|
|
HTML::Template directly. The `proc_tmpl_hash` then walks the hash
|
|
structure and processes the parameters.
|
|
|
|
>> I know ... you weren't looking for an explanation, just a patch
|
|
... totally understand. Point I'm trying to make, it's a 90% re-write
|
|
anyway (and my `style(8)` will probably piss most people off).
|
|
|
|
>> Anyway, would love to contribute so will try to get to doing this
|
|
"correctly" and post as a patch.
|
|
|
|
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. `<div>`) 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.
|
|
"""]]
|
|
|
|
NB: this *should* be 100% backwards compatible.
|
|
|
|
# `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
|
|
|
|
# <TMPL_VAR HEADER0>
|
|
|
|
<table>
|
|
<TMPL_LOOP TEST0>
|
|
<tr>
|
|
<td><TMPL_VAR DATA0></td>
|
|
<td><TMPL_VAR DATA1></td>
|
|
</tr>
|
|
</TMPL_LOOP>
|
|
</table>
|
|
|
|
## 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"
|
|
data1="cell1:1"
|
|
]]
|