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
Cela fait plusieurs demandes et propositions, qui trainent de manière récurrente dans les améliorations demandées : quelqu'un pourrait-il me dire ce qui bloque, car il semble que depuis Avril 2004, ce sujet n'ait plus bougé ? --
JdX
- Je crois que le principal problème est qu'il y a plusieurs pages de discussions sur le sujet (ActionSommaire, AncresAutomatiquesPourLesTitres) avec leurs solutions respectives - chacune présentant ses avantages et inconvaniants. Il faudrait donc faire un choix entre ces solutions, avec éventuellement une fusion des solutions, ce qui nécessiterait donc encore davantage de discussions - les protagonistes d'origine n'étant bien souvent plus actifs sur WikiNiPointNet. Il serait donc intéressant de regrouper/trier toutes les discussions dans une ou plusieurs pages, et de laisser dans les pages existantes uniquement les solutions en elles-mêmes (avec des références vers les pages de discussion), pour pouvoir faire avancer le chmilblik. -- LordFarquaad
Bonjour,
Je viens de
tester les deux fonctions {toc} et {tableofcontent} que vous proposez dans ce wikini. Malheureusement, je ne suis pas tout à fait satisfaite du résultat.
En effet, j'imaginais qu'il serait judicieux de ne pas avoir les titres et sous-titres au même niveau, mais plutôt décalés, comme on peut le voir sous
ce site propulsé par Mediawiki par exemple. Est-ce possible ?
Petite remarque, je n'ai aucune compétence en php et ne fait que recopier vos exemples !
CoRinne
- Oui c'est possible et je compte l'implémenter dès que j'aurais du temps pour m'occuper de cette action. Par contre, il s'agira d'une option pour garder quand même le comportement actuel. A savoir qu'il faut définir, je pense, un système de lien ancré pour qu'il n'y ai pas que les action de sommaire qui puisse faire des liens interne à la page. -- JulienLanglois