Wikini

TableDesMatieres

PagePrincipale :: DerniersChangements :: DerniersCommentaires :: ParametresUtilisateur :: Vous êtes ec2-54-210-83-20.compute-1.amazonaws.com

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.

@@ -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 "&lt;";
 		else if ($thing == ">")
 			return "&gt;";
@@ -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 "{{}}";
 		}


<?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; }


{{toc}} ou {{toc header="Table of contents"}}

-- DavidDecotigny



Il n'y a pas de commentaire sur cette page. [Afficher commentaires/formulaire]