Table des matières
En regardant le code de
WackoWiki: (interwiki), on s'aperçoit que sa méthode est un peu lourde (2 rendus complets de la page avec recherche/remplacement de chaînes), et pose des problèmes si on utilise qqch du genre
ActionInclude car la TOC est générée aussi sur les pages incluses.
Bref, voici une autre proposition, qui permet de générer la doc de façon plus légère en faisant un rendu partiel de la page, et en ignorant le contenu des pages incluses avec un
ActionInclude.
- Dans formatters/wakka.php :
@@ -15,10 +15,23 @@
static $newIndentSpace= array();
static $br = 1;
+ /* > 0 when parsing an included page */
+ static $nested_level = 0;
+ static $l5 = 0;
+ static $l4 = 0;
+ static $l3 = 0;
+ static $l2 = 0;
+ static $l1 = 0;
+
global $wiki;
+ // escaped text
+ if (preg_match("/^\"\"(.*)\"\"$/s", $thing, $matches))
+ {
+ return $matches[1];
+ }
// convert HTML thingies
- if ($thing == "<")
+ else if ($thing == "<")
return "<";
else if ($thing == ">")
return ">";
@@ -67,37 +80,37 @@
// header level 5
else if ($thing == "==")
{
- static $l5 = 0;
$br = 0;
- return (++$l5 % 2 ? "<h5>" : "</h5>");
+ return (++$l5 % 2 ? "<a name=\"TOC_"
+ .$nested_level."_5_$l5\"></A><h5>" : "</h5>");
}
// header level 4
else if ($thing == "===")
{
- static $l4 = 0;
$br = 0;
- return (++$l4 % 2 ? "<h4>" : "</h4>");
+ return (++$l4 % 2 ? "<a name=\"TOC_"
+ .$nested_level."_4_$l4\"></A><h4>" : "</h4>");
}
// header level 3
else if ($thing == "====")
{
- static $l3 = 0;
$br = 0;
- return (++$l3 % 2 ? "<h3>" : "</h3>");
+ return (++$l3 % 2 ? "<a name=\"TOC_"
+ .$nested_level."_3_$l3\"></A><h3>" : "</h3>");
}
// header level 2
else if ($thing == "=====")
{
- static $l2 = 0;
$br = 0;
- return (++$l2 % 2 ? "<h2>" : "</h2>");
+ return (++$l2 % 2 ? "<a name=\"TOC_"
+ .$nested_level."_2_$l2\"></A><h2>" : "</h2>");
}
// header level 1
else if ($thing == "======")
{
- static $l1 = 0;
$br = 0;
- return (++$l1 % 2 ? "<h1>" : "</h1>");
+ return (++$l1 % 2 ? "<a name=\"TOC_"
+ .$nested_level."_1_$l1\"></A><h1>" : "</h1>");
}
// separators
else if (preg_match("/-{4,}/", $thing, $matches))
@@ -253,7 +318,14 @@
else if (preg_match("/^\{\{(.*?)\}\}$/s", $thing, $matches))
{
if ($matches[1])
- return $wiki->Action($matches[1]);
+ {
+ $old_lx = array($l1, $l2, $l3, $l4, $l5);
+ $nested_level++;
+ $retval = $wiki->Action($matches[1]);
+ $nested_level--;
+ list($l1, $l2, $l3, $l4, $l5) = $old_lx;
+ return $retval;
+ }
else
return "{{}}";
}
- Fichier actions/toc.php :
<?php
$tag = $this->GetPageTag();
$page = $this->LoadPage($tag);
$toc_body = $page["body"];
echo "<div class=\"toc\">\n";
if ($this->GetParameter("header"))
echo "<h1>".$this->Format($this->GetParameter("header"))."</h1>\n";
else
echo "<h1>Table des matières</h1>\n";
global $wiki;
$wiki=$this;
if (!function_exists("translate2toc"))
{
function translate2toc($text)
{
global $wiki;
$cur_text = $text;
$l1=0;
$l2=0;
$l3=0;
$l4=0;
$l5=0;
while ($cur_text)
{
if (! preg_match("/(={2,6})(.*)/ms", $cur_text, $matches))
break;
$cur_text=$matches[2];
$class="";
$endmatch="";
if ($matches[1] == "======")
{ $l1++; $class="toc1"; $toc="TOC_0_1_".(2*$l1 - 1);
$endmatch="/(.*)======(.*?)/msU"; }
else if ($matches[1] == "=====")
{ $l2++; $class="toc2"; $toc="TOC_0_2_".(2*$l2 - 1);
$endmatch="/(.*)=====(.*?)/msU"; }
else if ($matches[1] == "====")
{ $l3++; $class="toc3"; $toc="TOC_0_3_".(2*$l3 - 1);
$endmatch="/(.*)====(.*?)/msU"; }
else if ($matches[1] == "===")
{ $l4++; $class="toc4"; $toc="TOC_0_4_".(2*$l4 - 1);
$endmatch="/(.*)===(.*?)/msU"; }
else if ($matches[1] == "==")
{ $l5++; $class="toc5"; $toc="TOC_0_5_".(2*$l5 - 1);
$endmatch="/(.*)==(.*?)/msU"; }
else
echo "????\n";
if (! preg_match($endmatch, $cur_text, $matches))
break;
echo "<div class=\"$class\"><A Href=\"#$toc\">"
.$wiki->Format(trim($matches[1]))."</A></div>\n";
$cur_text = $matches[2];
}
}
}
translate2toc(preg_replace("/\"\".*?\"\"/ms", "", $toc_body));
echo "</div>\n";
?>
Dans les expressions régulière il est possible d'utiliser des références arrières comme ceci:
Le
\1 signifie "la même chose que dans la première parenthèse capturante". Ca évite donc d'avoir à faire tous ces tests pour savoir le nombre de "=" et le tag fermant. Par ailleurs il serait préférable d'utiliser la fonction php
strlen().
Par ailleurs je me demande si ça ne pourraît pas être d'abord un véritable formateur (qui extrairait simplement du texte la table des matières), pouvant être appelé soit par une action (comme c'est le cas actuellement),
soit par un handler ! Il suffirait donc d'ajouter
/toc à l'url de la page pour en avoir le sommaire !
Je crois qu'il y a encore pas mal de choses à améliorer là dedans ;-) --
LordFarquaad
div.toc { margin-bottom: 0px; padding-bottom: 0px; }
div.toc1 { margin-left: 1em; }
div.toc1 img { border: 0px; }
div.toc2 { margin-left: 2em; }
div.toc2 img { border: 0px; }
div.toc3 { margin-left: 3em; }
div.toc3 img { border: 0px; }
div.toc4 { margin-left: 4em; }
div.toc4 img { border: 0px; }
div.toc5 { margin-left: 5em; }
div.toc5 img { border: 0px; }
- Et voilà, pour inclure une TOC dans une page, il suffit d'écrire :
{{toc}} ou
{{toc header="Table of contents"}}
--
DavidDecotigny