Introduction
L'action {{tableofcontent}} crée un sommaire automatique de la page en cours.
Tous les titres de la page (== à =====) sont scannés et un sommaire est généré. Pour de longues pages, c'est très pratique. Des liens automatiques vers les titres (à l'aide d'une ancre) permettent d'accéder rapidement à toutes les sous rubriques.
Les modifications à apporter sont assez complexes mais ne pose aucun problème particulier. Si personne n'y voit d'inconvénient, je l'ajouterai à la version CVS quand j'en aurai la possibilité.
Toutes les suggestions sont les bienvenues. Les discussions peuvent prendre place sur la page
ActionSommaireDiscussion.
- C'est un vieux sujet que ta proposition : cf. AncresAutomatiquesPourLesTitres. Mais ton approche est plus pragmatique : les ancres ne servent qu'au sommaire à et à rien d'autre ce qui évite de se poser des questions métaphysiques sur l'usage des ancres ;) C'est toujours mieux que rien du tout... Une dernière question cependant, que je pose à tout le monde : idéalement, une page wiki devrait être très courte et les wikistes expérimentés conseillent la séparation en plusieurs pages lorsqu'une page prend de l'embonpoint (rendant donc tout sommaire inutile). Qu'avez-vous expérimenté ? Il vrai que sur wikini.net par exemple, il y a certaines pages assez longues... Pour l'intégration dans WikiNi je ne suis pas contre, la modification étant peu impactante, mais je préfèrerai avoir d'autres avis là-dessus et un petit délai de réflexion. -- CharlesNepote
- C'est possible de créer des ancres qui possèdent le nom du titre. Je me suis inspiré, pour les numéros, de Dokuwiki. Pour éviter les problèmes de titres identiques (qui m'a fait renoncer à mettre le titre en toutes lettres), il suffit de le mettre sous la forme 1_Le_Titre, 2_La_Presentation etc. Si ça semble nécessaire je peux le faire. J'aimerais bien avoir d'autres avis également :) --JeremieCook
Bugs
Testé dans non nombreux cas, sans problème.
En cas d'erreur, prévenez moi que je corrige l'algorithme.
Le traitement avec les expressions régulières est très pénible. Penser à tous les de figure me semble assez illusoire (pour le nettoyage du code)
14/05/2005 --
JmPhilippe
Lorsqu'on pré-visualise une page, ce sont les titres de la page non modifiée qui apparaissent dans la page pré-visualisée. J'imagine qu'on peut récupérer le texte de la page modifiée, mais comment ????
02/06/2005 --
JmPhilippe
L'action ramasse aussi les titres qui sont dans des parties de code encadrées de %%. Là où ça devient vraiment gênant, c'est qu'il y a un nombre non négligeable de langages pour lesquels le signe == est utilisé pour les conditions... Je n'ai pas testé mais j'imagine qu'il y a le même genre de problème dans les parties de texte Html encadrées de "".
Formatters/wakka.php
Tout d'abord, une modification du fichier formatter de base. Pour ajouter les "ancres" qui permettront de faire un lien direct depuis le sommaire.
Le code était illisible, compliqué et fatiguant à comprendre parfaitement. J'ai commenté et éclairci les parties qui m'intéressaient. C'est un peu plus long, mais beaucoup plus facile à comprendre et modifier par la suite.
Il est même certainement possible de regrouper en un seul test les 5 types de header. Je m'en occuperai à l'occasion
1ere partie
Declaration de la variable statique numTitre vers le haut du fichier :
- function wakka2callback($things)
- {
- static $oldIndentLevel = 0;
- static $oldIndentLength= 0;
- static $indentClosers = array();
- static $newIndentSpace= array();
- static $br = 1;
- static $numTitre = 0; // <= Ajout de cette ligne
2ème partie
Le code de base :
// header level 5
else if ($thing == "==")
{
static $l5 = 0;
$br = 0;
return (++$l5 % 2 ? "<h5>" : "</h5>");
}
// header level 4
else if ($thing == "===")
{
static $l4 = 0;
$br = 0;
return (++$l4 % 2 ? "<h4>" : "</h4>");
}
// header level 3
else if ($thing == "====")
{
static $l3 = 0;
$br = 0;
return (++$l3 % 2 ? "<h3>" : "</h3>");
}
// header level 2
else if ($thing == "=====")
{
static $l2 = 0;
$br = 0;
return (++$l2 % 2 ? "<h2>" : "</h2>");
}
// header level 1
else if ($thing == "======")
{
static $l1 = 0;
$br = 0;
return (++$l1 % 2 ? "<h1>" : "</h1>");
}
à remplacer en :
// header level 5
else if ($thing == "==")
{
static $l5 = 0;
$br = 0;
// Nouvelle occurence
++$l5;
// Ouverture d'une balise de titre
if ($l5 % 2)
{
++$numTitre;
return "<h5><a name=\"$numTitre\">";
}
// Fermeture du titre precedent
else
{
return "</a></h5>\n";
}
}
// header level 4
else if ($thing == "===")
{
static $l4 = 0;
$br = 0;
// Nouvelle occurence
++$l4;
// Ouverture d'une balise de titre
if ($l4 % 2)
{
++$numTitre;
return "<h4><a name=\"$numTitre\">";
}
// Fermeture du titre precedent
else
{
return "</a></h4>\n";
}
}
// header level 3
else if ($thing == "====")
{
static $l3 = 0;
$br = 0;
// Nouvelle occurence
++$l3;
// Ouverture d'une balise de titre
if ($l3 % 2)
{
++$numTitre;
return "<h3><a name=\"$numTitre\">";
}
// Fermeture du titre precedent
else
{
return "</a></h3>\n";
}
}
// header level 2
else if ($thing == "=====")
{
static $l2 = 0;
$br = 0;
// Nouvelle occurence
++$l2;
// Ouverture d'une balise de titre
if ($l2 % 2)
{
++$numTitre;
return "<h2><a name=\"$numTitre\">";
}
// Fermeture du titre precedent
else
{
return "</a></h2>\n";
}
}
// header level 1
else if ($thing == "======")
{
static $l1 = 0;
$br = 0;
// Nouvelle occurence
++$l1;
// Ouverture d'une balise de titre
if ($l1 % 2)
{
++$numTitre;
return "<h1><a name=\"$numTitre\">";
}
// Fermeture du titre precedent
else
{
return "</a></h1>\n";
}
}
--
JeremieCook
Note : l'attribut "name" disparaît de la norme XHTML 1.1. Il serait peut-être plus judicieux d'utiliser "id" ? --
CharlesNepote
Création de l'action
Dans le répertoire actions, créer le fichier tableofcontent.php
en voila le contenu :
<?php
/*
toc.php : Affiche le sommaire de la page en cours
Copyright 2003 Jeremie COOK
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Fonction de creation de sommaire
function creerSommaire ($tokens)
{
$token = $tokens[1];
static $numTitre = 0;
return "<li>$token</li>";
}
// Recuperation du contenu de la page
$page = $this->LoadPage($this->getPageTag());
$toc = $page["body"];
// Mise en forme du sommaire
$toc = str_replace("\r", "", $toc);
$toc = chop($toc)."\n";
// Nettoyage des donnees (on ne garde que les titres)
$nonEgEg = "([^=]*=?[^=]+)*"; // Suite de caractères sans ==
$toc = preg_replace("($nonEgEg((=){2,5})$nonEgEg((=){2,5})$nonEgEg)ms", "\\2#NumTitre#\\4\\2 ", $toc);
// Ajout des liens (dans l'ordre)
$toc = preg_replace_callback("(#NumTitre#)ms",
create_function (
'$matches',
'static $numTitre = 0; return "#".++$numTitre."#";'
)
, $toc);
// Remplacement des balises
$toc = preg_replace("((=){6}#(([0-9]+))#($nonEgEg)(=){6} )", "<li><h1><a href=\"#\\3\">\\4</h1></a></li>\n", $toc);
$toc = preg_replace("((=){5}#(([0-9]+))#($nonEgEg)(=){5} )", "<li><h2><a href=\"#\\3\">\\4</h2></a></li>\n", $toc);
$toc = preg_replace("((=){4}#(([0-9]+))#($nonEgEg)(=){4} )", "<li><h3><a href=\"#\\3\">\\4</h3></a></li>\n", $toc);
$toc = preg_replace("((=){3}#(([0-9]+))#($nonEgEg)(=){3} )", "<li><h4><a href=\"#\\3\">\\4</h4></a></li>\n", $toc);
$toc = preg_replace("((=){2}#(([0-9]+))#($nonEgEg)(=){2} )", "<li><h5><a href=\"#\\3\">\\4</h5></a></li>\n", $toc);
$toc = preg_replace("/<br \/>$/","", trim($toc));
// Affichage
echo '<div id="sommaire">';
echo '<h2>Sommaire</h2>'."\n";
echo '<ul>'."\n";
echo $toc;
echo "\n".'</ul>'."\n";
echo '</div>';
?>
Fichier CSS
Reste à mettre quelques styles dans le CSS pour un format un peu plus présentable.
Je viens d'implémenter ces modifications. J'ai fait quelques modif dans le CSS pour obtenir un affichage "sympa". Seul problème, les ancres sont toutes nommées "1" !!! Je ne comprend pas ? --
JeanMorlet
Je viens d'ajouter dans cette page (1ere partie) la déclaration de la variable statique numTitre que j'avais oubliée dans le code à modifier. Une simple ligne parmi les déclarations et le problème doit être résolu. Pardon pour la confusion. --
JeremieCook
Bonjour,
Je viens d'installer en local cette fonction et j'ai le lien ancre qui reste bloqué à "#1". De plus, la page ne s'affiche pas sous IE alors qu'elle s'affiche sous Firefox mais avec "#1" à chaque titre. J'ai recommencé les modifs deux fois. Une idée ?
Michel
Bonjour, n'est-ce pas le même problème que ci dessus ? As tu correctement ajouté la déclaration static $numTitre = 0; // <= Ajout de cette ligne ?
Je trouve cette fonction intéressante, pourquoi ne pas l'intégrer dans la prochaine version ?
12/05/2005
Très pratique cette action mais je lui trouve quelques imperfections. J'en ai donc fait une variante disponible à la page
ActionSommaireDiscussion afin de résoudre les problèmes suivants :
- l'ancre <a name="..."></a> encadre le texte du titre dans le corps de la page, ce qui fait que le style du tag A joue sur le rendu des titres de la page lorsqu'on utilise l'action dans la page (et ce n'est bien sûr pas le cas sinon)
- les listes de liens créées pour générer le sommaire utilisent des tags H1, H2, etc., ce qui génère un sommaire assez encombrant vu la taille des titres, de plus si on change le style des titres, ça change aussi le style du sommaire...
- si le titre contient des caractères de formatage, ils ne sont pas transformés en code Html (par ex. //Titre// reste tel quel au lieu de devenir Titre)
- encore plus d'esthétisme dans le code Html généré !
On trouvera sur la page
ActionSommaireDiscussion le Php modifié ainsi que le CSS qui va bien. En espérant que ça serve...
--
JmPhilippe