pedigree: rewrote with different design

(and updated testsuite + docs accordingly)

Signed-off-by: intrigeri <intrigeri@boum.org>
master
intrigeri 2008-07-15 12:35:12 +02:00
parent 9b8ba60dac
commit 55000fd779
4 changed files with 77 additions and 223 deletions

View File

@ -18,20 +18,22 @@ sub pedigree ($) { #{{{
my $path="";
my $title=$config{wikiname};
my $i=0;
my $depth=0;
my $height=0;
my @pagepath=(split("/", $page));
my $pagedepth=@pagepath;
foreach my $dir (@pagepath) {
next if $dir eq 'index';
$depth=$i;
$height=($pagedepth - $depth);
push @ret, {
url => urlto($path, $page),
page => $title,
absdepth => $i,
distance => ($pagedepth - $i),
is_root => ($i eq 0),
is_second_ancestor => ($i eq 1),
is_grand_mother => ($i eq ($pagedepth - 2)),
is_mother => ($i eq ($pagedepth - 1)),
depth => $depth,
height => $height,
"depth_$depth" => 1,
"height_$height" => 1,
};
$path.="/".$dir;
$title=IkiWiki::pagetitle($dir);
@ -40,51 +42,14 @@ sub pedigree ($) { #{{{
return @ret;
} #}}}
sub forget_oldest ($@) { #{{{
my $offset=shift;
my @pedigree=@_;
my @ret;
my $parent;
unless ($offset ge scalar(@pedigree)) {
for (my $i=0; $i < $offset; $i++) {
shift @pedigree;
}
while (@pedigree) {
# Doing so does not modify the original @pedigree, we've
# got our own copy of its "content" (i.e. a pile of
# references to hashes)...
$parent=shift @pedigree;
# ... but we have no copy of the referenced hashes, so we
# actually are modifying them in-place, which
# means the second (and following) calls to
# this function overwrite the previous one's
# reldepth values => known bug if PEDIGREE_BUT_ROOT and
# PEDIGREE_BUT_TWO_OLDEST are used in the same template
$parent->{reldepth}=($parent->{absdepth} - $offset);
push @ret, $parent;
}
}
return @ret;
} #}}}
sub pagetemplate (@) { #{{{
my %params=@_;
my $page=$params{page};
my $template=$params{template};
my @pedigree=pedigree($page)
if ($template->query(name => "pedigree")
or $template->query(name => "pedigree_but_root")
or $template->query(name => "pedigree_but_two_oldest")
);
$template->param(pedigree => \@pedigree)
if ($template->query(name => "pedigree"));
$template->param(pedigree_but_root => [forget_oldest(1, @pedigree)])
if ($template->query(name => "pedigree_but_root"));
$template->param(pedigree_but_two_oldest => [forget_oldest(2, @pedigree)])
if ($template->query(name => "pedigree_but_two_oldest"));
if ($template->query(name => "pedigree")) {
$template->param(pedigree => [pedigree($page)]);
}
} # }}}
1

View File

@ -1,98 +1,74 @@
[[!template id=plugin name=pedigree author="intrigeri"]]
[[!tag type/useful]]
This plugin provides a bunch of loops that one can use in his/her
`HTML::Template`'s to iterate over all or a subset of a page's
parents. One can think of pedigree as "`PARENTLINKS` on steroids".
This plugin offers a `HTML::Template` loop that iterates over all or
a subset of a page's parents, providing a few bonus possibilities,
such as styling the parent links depending on their place in the path.
One can think of pedigree as "`PARENTLINKS` on steroids".
[[!toc ]]
Content
=======
Loop variables
--------------
This plugin provides one template loop, called `PEDIGREE`, that
returns the same parents list as `PARENTLINKS` would; as a bonus,
every path element returned by the `PEDIGREE` loop has the following
variables set:
Inside any loop provided by the pedigree plugin, every path element
has not only the `URL` and `PAGE` variables, as with `PARENTLINKS`,
but also the following ones:
* `ABSDEPTH` (positive integer): depth of the path leading to the
* `URL` (string): url to the current path element
* `PAGE` (string): title of the current path element
* `DEPTH` (positive integer): depth of the path leading to the
current path element, counting from the wiki's root, which has
`ABSDEPTH=0`
* `DISTANCE` (positive integer): distance, expressed in path elements,
`DEPTH=0`
* `HEIGHT` (positive integer): distance, expressed in path elements,
from the current page to the current path element; e.g. this is
1 for the current page's mother, 2 for its grand-mother, etc.
* `IS_ROOT` (boolean): true if, and only if, this path element is the
wiki's root
* `IS_SECOND_ANCESTOR` (boolean): true if, and only if, this path
element is the first one after the wiki's root, on the path leading
to the current page
* `IS_GRAND_MOTHER` (boolean): true if, and only if, this path element
is the current page's grand-mother
* `IS_MOTHER` (boolean): true if, and only if, this path element
is the current page's mother
Loops
-----
### `PEDIGREE`
Returns the same parents list as `PARENTLINKS` would, along with
additional loop variables as explained above.
### `PEDIGREE_BUT_ROOT`
Returns the same parents list as `PEDIGREE` would, **but** the wiki
root (i.e. homepage).
In addition to pedigree's common loop variables, `PEDIGREE_BUT_ROOT`
provides `RELDEPTH` (positive integer), whose value, for a given
parent, is its relative depth, i.e. the depth of the path leading to
it, counting from the first element returned by this loop.
### `PEDIGREE_BUT_TWO_OLDEST`
Returns the same parents list as `PEDIGREE` would, **but** the wiki
root (i.e. homepage) and the next path component.
In addition to pedigree's common loop variables,
`PEDIGREE_BUT_TWO_OLDEST` provides `RELDEPTH`: depth of the path
leading to the current parent, relative to the first element returned
by this loop.
* `DEPTH_n` (boolean): true if, and only if, `DEPTH==n`
* `HEIGHT_n` (boolean): true if, and only if, `HEIGHT==n`
Usage
=====
The `DEPTH_n` and `HEIGHT_n` variables allow the template writer to
skip arbitrary elements in the parents list: they are arbitrary
page-range selectors.
The `DEPTH` and `HEIGHT` variables allow the template writer to apply
general treatment, depending on one of these variables, to *every*
parent: they are counters.
Styling parents depending on their depth
----------------------------------------
Say you want the parent links to be styled depending on their depth in
the path leading to the current page; just add the following lines in
`page.tmpl`:
<TMPL_LOOP NAME="PEDIGREE">
<a href="<TMPL_VAR NAME="URL">" class="parentdepth<TMPL_VAR NAME="ABSDEPTH">">
<TMPL_VAR NAME="PAGE">
</a> /
</TMPL_LOOP>
Then write the appropriate CSS bits for `a.parentdepth1`, etc.
Skip some parents, style the others depending on their distance
---------------------------------------------------------------
Say you want to display the parents links, skipping the wiki homepage,
styled depending on their distance from the current page; just add the
the path going from the wiki root to the current page; just add the
following lines in `page.tmpl`:
<TMPL_LOOP NAME="PEDIGREE_BUT_ROOT">
<a href="<TMPL_VAR NAME="URL">" class="parentdistance<TMPL_VAR NAME="DISTANCE">">
<TMPL_LOOP NAME="PEDIGREE">
<a href="<TMPL_VAR NAME="URL">" class="depth<TMPL_VAR NAME="DEPTH">">
<TMPL_VAR NAME="PAGE">
</a> /
</TMPL_LOOP>
Then write the appropriate CSS bits for `a.parentdistance1`, etc.
Then write the appropriate CSS bits for `a.depth1`, etc.
Skip some parents, style the others depending on their distance to the current page
-----------------------------------------------------------------------------------
Say you want to display all the parents links but the wiki homepage,
styled depending on their distance to the current page; just add the
following lines in `page.tmpl`:
<TMPL_LOOP NAME="PEDIGREE">
<TMPL_IF NAME="DEPTH_0">
<TMPL_ELSE>
<a href="<TMPL_VAR NAME="URL">" class="height<TMPL_VAR NAME="HEIGHT">">
<TMPL_VAR NAME="PAGE">
</a> /
</TMPL_LOOP>
Then write the appropriate CSS bits for `a.height1`, etc.
Full-blown example
------------------
@ -106,9 +82,9 @@ and/or CSS generated for some special path components; e.g.:
<div id="oldestparents">
<ul>
<TMPL_LOOP NAME="PEDIGREE">
<TMPL_IF NAME="IS_GRAND_MOTHER">
<TMPL_IF NAME="HEIGHT_2">
<TMPL_ELSE>
<TMPL_IF NAME="IS_MOTHER">
<TMPL_IF NAME="HEIGHT_1">
<TMPL_ELSE>
<li><a href="<TMPL_VAR NAME="URL">"><TMPL_VAR NAME="PAGE"></a></li>
</TMPL_IF>
@ -119,12 +95,12 @@ and/or CSS generated for some special path components; e.g.:
<!-- dedicated div's for mother and grand'ma -->
<TMPL_LOOP NAME="PEDIGREE">
<TMPL_IF NAME="IS_GRAND_MOTHER">
<TMPL_IF NAME="HEIGHT_2">
<div id="grandma">
<a href="<TMPL_VAR NAME="URL">"><TMPL_VAR NAME="PAGE"></a>
</div>
<TMPL_ELSE>
<TMPL_IF NAME="IS_MOTHER">
<TMPL_IF NAME="HEIGHT_1">
<div id="mother">
<a href="<TMPL_VAR NAME="URL">"><TMPL_VAR NAME="PAGE"></a>
</div>
@ -135,11 +111,3 @@ and/or CSS generated for some special path components; e.g.:
<!-- eventually, the current page title -->
<TMPL_VAR NAME="TITLE">
</div>
Known bugs
==========
If `PEDIGREE_BUT_ROOT` and `PEDIGREE_BUT_TWO_OLDEST` are used in the
same `HTML::Template`, `RELDEPTH` has wrong values inside the
`PEDIGREE_BUT_ROOT` loop. This can be fixed if anyone needs this to
be working.

View File

@ -24,61 +24,15 @@ $expected{'pedigree'} =
{
"" => [],
"ikiwiki" => [],
"ikiwiki/pagespec" => [
{absdepth => 0,
distance => 2,
is_root => 1,
is_second_ancestor => '',
is_grand_mother => 1,
is_mother => '',
},
{absdepth => 1,
distance => 1,
is_root => '',
is_second_ancestor => 1,
is_grand_mother => '',
is_mother => 1,
},
],
"ikiwiki/pagespec/attachment" => [
{absdepth => 0,
distance => 3,
is_root => 1,
is_second_ancestor => '',
is_grand_mother => '',
is_mother => '',
},
{absdepth => 1,
distance => 2,
is_root => '',
is_second_ancestor => 1,
is_grand_mother => 1,
is_mother => '',
},
{absdepth => 2,
distance => 1,
is_root => '',
is_second_ancestor => '',
is_grand_mother => '',
is_mother => 1,
},
],
};
$expected{'pedigree_but_root'} =
{
"" => [],
"ikiwiki" => [],
"ikiwiki/pagespec" => [],
"ikiwiki/pagespec/attachment" => [],
};
$expected{'pedigree_but_two_oldest'} =
{
"" => [],
"ikiwiki" => [],
"ikiwiki/pagespec" => [],
"ikiwiki/pagespec/attachment" => [],
"ikiwiki/pagespec" =>
[ {depth => 0, height => 2, },
{depth => 1, height => 1, },
],
"ikiwiki/pagespec/attachment" =>
[ {depth => 0, height => 3, depth_0 => 1, height_3 => 1},
{depth => 1, height => 2, },
{depth => 2, height => 1, },
],
};
# Test function
@ -87,15 +41,6 @@ sub test_loop($$) {
my $expected=shift;
my $template;
my %params;
my $offset;
if ($loop eq 'pedigree') {
$offset=0;
} elsif ($loop eq 'pedigree_but_root') {
$offset=1;
} elsif ($loop eq 'pedigree_but_two_oldest') {
$offset=2;
}
ok($template=template('pedigree.tmpl'), "template created");
ok($params{template}=$template, "params populated");
@ -103,12 +48,6 @@ sub test_loop($$) {
while ((my $page, my $exp) = each %{$expected}) {
my @path=(split("/", $page));
my $pagedepth=@path;
my $expdepth;
if (($pagedepth - $offset) >= 0) {
$expdepth=$pagedepth - $offset;
} else {
$expdepth=0;
}
my $msgprefix="$page $loop";
# manually run the plugin hook
@ -117,28 +56,18 @@ sub test_loop($$) {
IkiWiki::Plugin::pedigree::pagetemplate(%params);
my $res=$template->param($loop);
is(scalar(@$res), $expdepth, "$msgprefix: path length");
is(scalar(@$res), $pagedepth, "$msgprefix: path length");
# logic & arithmetic validation tests
for (my $i=0; $i<$expdepth; $i++) {
for (my $i=0; $i<$pagedepth; $i++) {
my $r=$res->[$i];
is($r->{distance}, $pagedepth - $r->{absdepth},
"$msgprefix\[$i\]: distance = pagedepth - absdepth");
ok($r->{absdepth} ge 0, "$msgprefix\[$i\]: absdepth>=0");
ok($r->{distance} ge 0, "$msgprefix\[$i\]: distance>=0");
unless ($loop eq 'pedigree') {
ok($r->{reldepth} ge 0, "$msgprefix\[$i\]: reldepth>=0");
TODO: {
local $TODO = "Known bug" if
(($loop eq 'pedigree_but_root')
&& ($i >= $offset));
is($r->{reldepth} + $offset, $r->{absdepth},
"$msgprefix\[$i\]: reldepth+offset=absdepth");
}
}
is($r->{height}, $pagedepth - $r->{depth},
"$msgprefix\[$i\]: height = pagedepth - depth");
ok($r->{depth} ge 0, "$msgprefix\[$i\]: depth>=0");
ok($r->{height} ge 0, "$msgprefix\[$i\]: height>=0");
}
# comparison tests, iff the test-suite has been written
if (scalar(@$exp) eq $expdepth) {
for (my $i=0; $i<$expdepth; $i++) {
if (scalar(@$exp) eq $pagedepth) {
for (my $i=0; $i<$pagedepth; $i++) {
my $e=$exp->[$i];
my $r=$res->[$i];
map { is($r->{$_}, $e->{$_}, "$msgprefix\[$i\]: $_"); } keys %$e;
@ -151,6 +80,4 @@ sub test_loop($$) {
}
# Main
map {
test_loop($_, $expected{$_});
} ('pedigree', 'pedigree_but_root', 'pedigree_but_two_oldest');
test_loop('pedigree', $expected{'pedigree'});

View File

@ -2,9 +2,3 @@
<TMPL_LOOP NAME="PEDIGREE">
</TMPL_LOOP>
<TMPL_LOOP NAME="PEDIGREE_BUT_ROOT">
</TMPL_LOOP>
<TMPL_LOOP NAME="PEDIGREE_BUT_TWO_OLDEST">
</TMPL_LOOP>