Génération automatique de numérotation, table des matières et références

Voici un ensemble de nouveaux raccourcis typographiques pour gérer les titres de sections de façon plus évoluée. On obtient ainsi des titres à plusieurs niveaux, automatiquement numérotés et recensés avec une table des matières.

Nouveaux Raccourcis

Avec Tex (par exemple), on peut définir un certain nombre de titre de section et sous section. Ils seront ensuite numérotés automatiquement et si c’est nécessaire, une table des matières sera construite.

Par contre, dans SPIP, on ne peut définir qu’un niveau de section avec le raccourcis : {{{ma section}}}. Cette contrib utilise les points d’entrée dans inc_texte.php3 pour ajouter trois nouveaux raccourcis :

  1. {{{* ma section <référence>}}} {{{** ma sous section}}} etc...
  2. #TABLEMATIERES
  3. <référence>

Le premier jeux de raccourcis permet de faire une hiérarchisation des sections dans l’article. On pourra ainsi tapper :

{{{* Section de haut niveau }}}

du texte plein ...

{{{** Section de 2e niveau }}}

du texte plein ...

{{{*** Section de 3e niveau }}}

du texte plein ...

{{{*** autre Section de 3e niveau }}}

du texte plein ...

{{{* une autre Section de haut niveau }}}

du texte plein ...

et l’on obtiendra :


1 Section de haut niveau

du texte plein ...

1.1 Section de 2e niveau

du texte plein ...

1.1.1 Section de 3e niveau

du texte plein ...

1.1.2 autre Section de 3e niveau

du texte plein ...

2 une autre Section de haut niveau

du texte plein ...


La balise #TABLEMATIERES placée dans un article sera, quant à elle remplacée, par une liste des sections, avec des liens vers l’emplacement des sections dans la page [1]. Par exemple :


  • 1 Section de haut niveau
    • 1.1 Section de 2e niveau
      • 1.1.1 Section de 3e niveau
      • 1.1.2 autre Section de 3e niveau
  • 2 une autre Section de haut niveau

La dernière balise permet de référencer un numéro de section. Comme en Tex, on peut associer un raccourci à chaque section, grâce à : {{{** ma section <raccourci>}}}. On peut ensuite mettre dans le texte une référence qui sera plus tard remplacée par le numéro de la section et un lien dans le document.

on peut trouver un exemple ici.

Limitations

Deux sections ne peuvent pas avoir exactement le même titre (en comptant les espaces). On peut contourner cette limitation en mettant des espaces de plus à la fin de chaque titre.

On ne peut pas utiliser de < dans les titres de section. De même, pas de raccourcis docXXX, embXXX ou imgXXX.

Si vous voulez m’aider à réécrire cette expression régulière :

(($debut_intertitre(\\*+)([^<]*)(<([^>]*)>)?$fin_intertitre))

ça pourrait aider.

Code

Ce code s’insère dans mes_options.php3.

/*
 *   +----------------------------------+
 *    Nom :   Table des matieres                                               
 *   +----------------------------------+
 *    Date : aout 2004
 *    Auteur :  Mortimer Porte mortimer.pa@free.fr                                     
 *   +-------------------------------------+
 *    Fonctions de ce filtre :
 *     affiche une table des matières et génère automatiquement la numérotation des titres.
 *   +-------------------------------------+ 
 *  
 * Pour toute suggestion, remarque, proposition d'ajout
 * reportez-vous au forum de l'article :
 * http://www.spip-contrib.net/article.php3?id_article=627
*/
function table_des_matieres($texte) {
  global $debut_intertitre, $fin_intertitre;

   // définition de la balise pour les titres des sections %num% sera remplacé 
  // par la profondeur de la section
  $css_debut_intertitre = "\n<h3 class=\"spiphead%num%\">";
  $css_fin_intertitre = "</h3>\n";

  // on cherche les noms de section commençant par des *  
  $count = preg_match_all("(($debut_intertitre(\\*+)(.*?)(<(.*?)>)?$fin_intertitre))",$texte,$matches);
  $table = '';
  //initialisation du compteur
  $cnt[0] = 0;
  //initialisation du code de la table des matières
  $table = "\n<ins><div id=\"tablematiere\">\n";
  $lastlevel = 1;
  $cite[''] = '';

  //pour chaque titre trouvé
  for ($j=0; $j< $count; $j++) {
	$level = $matches[2][$j];
	$titre = $matches[3][$j];
	$ref = $matches[5][$j];
	if(strlen($level) == 1) {
           //on est au niveau de base
          //on réinitialise les compteurs
	  for ($i=1; $i < count($cnt); $i++) {
		$cnt[$i] = 0;
	  } 
          //on génère le titre et le numéros
	  $numeros = ++$cnt[0];
	  $titre = $numeros.' '.$titre;
	} else {
           //on est à un niveau plus profond
          // on construit le numéros
	  $numeros = $cnt[0].'.';
	  for ($i=1; $i < strlen($level)-1; $i++) {
		$numeros .= $cnt[$i].".";
	  }
	  $numeros = $numeros.(++$cnt[$i]);
          //on génère le titre
	  $titre = $numeros.' '.$titre;
	}

        //gestion de la liste dans la table
	if($lastlevel < strlen($level)) {
          //on ouvre une sous liste
	  $table .= "<ul>\n";
	}
	if($lastlevel > strlen($level)) {
          //on doit fermer les derniers niveaux
	  for ($i=0; $i < ($lastlevel - strlen($level)); $i++) {
             if($i+1==$lastlevel) {
               $table .= "\n</div></ins>";	// derniere fermeture
             } else {
               $table .= "</li>\n</ul>"; 
             }	
	  }
	}
	if($lastlevel >= strlen($level)) {
          //on doit fermer l'item précédent
	  if($cnt[0] > 1 || strlen($level) > 1) {
		$table .= "</li>\n";
	  }
	} 
       //on se rappelle du raccourcis
	$cite[$ref] = $numeros;
	$table .= "<li><a href=\"#$numeros\">$titre</a>";

       //on mémorise le niveau de ce titre
	$lastlevel = strlen($level);

        //on génère la balise avec le bon style pour le niveau
	$mdebut_intertitre = str_replace('%num%',$lastlevel,$css_debut_intertitre);
	$mfin_intertitre = str_replace('%num%',$lastlevel,$css_fin_intertitre);
        //on remplace le titre dans le texte
	$texte = str_replace($matches[0][$j],"$mdebut_intertitre<a name='$numeros'></a>$titre$mfin_intertitre",$texte);
  }
  //on fini la table
  for ($i=0; $i < $lastlevel; $i++) {
	$table .= "</li>\n</ul>";		
  }
  //on remplace les raccourcis par les numéros des sections.
  foreach ($cite as $ref => $num) {
	$texte = str_replace("<$ref>","<a href=\"#$num\">$num</a>",$texte);	
  }
  //on place la table des matières dans le texte
  $texte = str_replace('#TABLEMATIERES',$table,$texte);
  return $texte;
}

Il faut ensuite l’appeler depuis apres_propre, par exemple :

function apres_propre($texte) {
  $new_texte = table_des_matieres($texte);
  return $new_texte;
}

Style

le style de la table des matières ainsi que des différents niveaux sont gérés par du css. Il faut donc ajouter à vos fichier css, les classes spiphead1, spiphead2, ... (autant que de niveaux utilisés) ainsi que l’id #tablematiere

Notes

[1en utilisant des ancres html

Dernière modification de cette page le 21 janvier 2007

Discussion

14 discussions

  • REBOLtof

    Je viens d’installer cet contri, et je n’ai rencontré aucun problème ;-)
    Un grand merci pour le travail !!!

    ==xtof

    Répondre à ce message

  • 3

    Bonjour,
    tout d’abord, merci pour cette contribe vraiment sympa.
    juste une question.

    À priori l’encapsulation de la table de matière entraine une non conformité avec les exigences w3c. (problème avec la dernière balise fermante ul et celle de fermeture du paragraphe).

    J’ai essayé plusieurs modifs sans succés, d’autant plus que je ne vois pas en quoi le code généré est non conforme.

    quelqu’un a t il rencontré des problèmes similaires.

    merci encore.

    • Oui,

      pour l’histoire du ul, il faut remplacer enlever le <p class="spip"> avant <ul id='tablematiere'>

      Pour l’histoire du

      , je comprend pas...

    • c’est de la bidouille, mais cela marche pour être conforme avec w3c
      j’ai remplacé (en ayant aussi enlevé la balise ouvrante p class=« spip ») :
      $table .= « 

      \n

       » ;
      par
      $table .= « 

      \n

       » ;

      le site tidy online m’a un peu aidé.

    • c’est de la bidouille, mais cela marche pour être conforme avec w3c
      j’ai remplacé (en ayant aussi enlevé la balise ouvrante p class=« spip ») :

              $table .= "</li>\n</ul>";

      par

              $table .= "</li>\n</ul><p>";

      le site tidy online m’a un peu aidé.

    Répondre à ce message

  • 1

    Le fichier plugin est utilisable sans placer de filtre dans les squelettes et marche aussi du côté admin du site.

    • Pour utiliser le fichier plugin :

      1. mettre le fichier à la racine du site
      2. ajouter les lignes :
        if(!file_exists(_$DIR_RESTREINT_ABS.'inc_version.php3')) {
        include(../plug_table_matiere.php);
        } else {
        include(./plug_table_matiere.php);
        }
      3. modifier apres_propre comme indiqué dans l’article.

    Répondre à ce message

  • 1

    Donc après la pr1, ceci ne marchera plus.

    • Mortimer

      Il ne faut pas dire n’importe quoi non plus !

      Ceci n’est pas un plugin, mais juste l’utilisation d’un point d’entrée. Cela marche très bien avec la 1.7.2 et marchera très bien avec la version 1.8 finale.

      Ce qui a été enlevé de la 1.8, c’est ce qui est décrit ici :
      http://spip-contrib.net/spikini/Sys...

    Répondre à ce message

Ajouter un commentaire

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom