Les balises #TITRE_PARENT et #TITRE_OBJET

... ou comment éviter une boucle SPIP

Un outil du Couteau Suisse : une balise (ou plusieurs !) pour afficher le titre du parent d’un objet (article, rubrique, brève, mot-clé...), ou simplement le titre d’un objet SPIP. Sans boucle supplémentaire !

Présentation

Cet outil est une fonctionnalité du plugin « Le Couteau Suisse ». Pour avoir accès au paramétrage de la balise #TITRE_PARENT, il vous faut donc avoir préalablement installé ce plugin, puis activé l’outil « Balises #TITRE_PARENT/OBJET » sur la page d’administration du plugin en espace privé.

Cet article est une version approfondie et adaptée au Couteau Suisse de l’article suivant : Balise #TITRE_PARENT, écrit par James. Lecteur, il te sera facile de repérer les quelques paragraphes que je me suis permis de reproduire ici pour faciliter le suivi du fil de raisonnement. Il s’agit bien ici de poursuivre le travail de James, en direction de tous les objets de SPIP ayant une rubrique parente, voire même de tous les objets SPIP ayant un parent dont on peut récupérer le #TITRE (ou le #NOM) — le tout moyennant une mise en garde importante en fin d’article.

Voici donc quelques balises qui évitent d’ajouter une boucle dans un squelette pour afficher le titre du parent d’un objet.

Rappel du sujet...

tetue nous dit ici qu’à l’instar de #URL_RUBRIQUE ou de #ID_RUBRIQUE, une nouvelle balise pouvant afficher le titre de la rubrique parente d’un article serait bien pratique et plus rapide que l’écriture d’une boucle supplémentaire.

Voici alors l’inclusion que propose Grégoire :

<BOUCLE_lstRub(RUBRIQUES)>
   <BOUCLE_art(ARTICLES){id_rubrique}>
   <br /> Art :  #ID_ARTICLE - #TITRE
   [(#REM) titre de la rubrique maintenant]
   <br />#_lstRub:TITRE
   [(#REM) ça marche avec les URL aussi]
   </BOUCLE_art>
</BOUCLE_lstRub>

Enfin, d’après James :

Mais une balise #TITRE_PARENT simplifierait drôlement la vie :

<a href="#URL_RUBRIQUE">#TITRE_PARENT</a>

Elle permettrait d’afficher facilement le titre de la rubrique parente dans les boucles articles, brèves, rubriques...

La chose est faite. Ce plugin [1] ajoute à l’arsenal des balises utilisables sur votre site la fameuse balise, sans boucle supplémentaire.

Techniquement, le fichier outils/titre_parent_fonctions.php est le seul fichier réellement essentiel à SPIP pour fournir la fonctionnalité. En effet, le plugin n’a pour rôle que de proposer ce fichier comme extension au compilateur de SPIP.

Il se décompose en trois concepts : les filtres SPIP, les balises SPIP et les traitements SPIP sur les balises.

Les filtres

La fonction « cs_titre_id() » est le filtre « |cs_titre_id » qui permet de récupérer le titre de la table parent d’un objet $id. Il faut donc absolument appliquer ce filtre à un #ID dont on est sûr qu’il est le parent de l’objet en cours dans la boucle, et par défaut, une rubrique. Quatre exemples pour éclaircir cette idée :

-  <BOUCLE_a(ARTICLES)>[(#ID_RUBRIQUE|cs_titre_id)]</BOUCLE_a>
-  <BOUCLE_b(BREVES)>[(#ID_BREVE|cs_titre_id)]</BOUCLE_b>
-  <BOUCLE_r(RUBRIQUES)>[(#ID_PARENT|cs_titre_id)]</BOUCLE_r>
-  <BOUCLE_m(MOTS)>[(#ID_GROUPE|cs_titre_id{groupes_mots,id_groupe})]</BOUCLE_m>

Je le reconnais, pour utiliser « |cs_titre_id », il faut avoir une bonne connaissance de la structure des tables SPIP et reconnaître les liaisons entre les objets enfants et leurs parents. Ce filtre explore par défaut la table des rubriques, mais il est possible de spécifier d’autres tables en utilisant les deux arguments prévus à cette effet : table, champ id. Le 3e exemple ci-dessus explore la table des groupes de mots-clés ("groupes_mots") et récupère le titre du groupe dont le champ "id_groupe" est bien égal à #ID_GROUPE, le groupe parent du mot-clé traité par la boucle.

Voici le code du filtre « |cs_titre_id » :

// Renvoie le titre trouve dans la $table_parent, là où $champ = $id
function cs_titre_id($id, $table_parent='rubriques', $champ='id_rubrique') {
	// retour nul si pas de parent a priori
	if(!$id) return '';
	// Utiliser la bonne requete en fonction de la version de SPIP
	if(function_exists('sql_getfetsel')) {
		// SPIP 2.0
		if($titre = sql_getfetsel('titre', "spip_$table_parent", " $champ=$id"))
			return $titre;
	} else {
		if($r = spip_query("SELECT titre FROM spip_$table_parent WHERE $champ=$id"))
			// s'il existe un champ, on le retourne
			if($row = spip_fetch_array($r)) return $row['titre'];
	}
	// sinon, rien !
	return '';
}

Histoire de simplifier un peu, voici deux autres filtres bien plus pratiques : |titre_rubrique et |titre_groupe. En fait ils sont tous les deux basés sur le précédent :
-  Le premier, appliqué à un #ID_RUBRIQUE (de tout objet sauf les rubriques elles-mêmes) donne le titre de la rubrique parente. Appliqué à #ID_PARENT (champ disponible dans la table des rubriques), ce filtre renverra la rubrique mère de la rubrique en cours.
-  Le second, appliqué à #ID_GROUPE, balise disponible uniquement si l’objet est un mot-clé, donne le titre du groupe parent.

Voici comment nos quatres exemples précédents peuvent maintenant s’écrire :
-  <BOUCLE_a(ARTICLES)>[(#ID_RUBRIQUE|titre_rubrique)]</BOUCLE_a>
-  <BOUCLE_b(BREVES)>[(#ID_BREVE|titre_rubrique)]</BOUCLE_b>
-  <BOUCLE_r(RUBRIQUES)>[(#ID_PARENT|titre_rubrique)]</BOUCLE_r>
-  <BOUCLE_m(MOTS)>[(#ID_GROUPE|titre_groupe)]</BOUCLE_m>

Voici le code de ces deux filtres :

// filtre 'titre_rubrique' a utiliser sur #ID_RUBRIQUE d'un objet ou #ID_PARENT d'une rubrique
// Ex :  : <BOUCLE_a(ARTICLES)>[(#ID_RUBRIQUE|titre_rubrique)]</BOUCLE_a>
// Ex :  : <BOUCLE_b(BREVES)>[(#ID_RUBRIQUE|titre_rubrique)]</BOUCLE_b>
// Ex :  : <BOUCLE_r(RUBRIQUES)>[(#ID_PARENT|titre_rubrique)]</BOUCLE_r>
function titre_rubrique($id_rubrique, $table='rubriques', $id='id_rubrique') {
	return cs_titre_id($id_rubrique, $table, $id);
}

// filtre 'titre_groupe' a utiliser sur #ID_GROUPE d'un mot-clef
// Ex :  : <BOUCLE_m(MOTS)>[(#ID_GROUPE|titre_groupe)]</BOUCLE_m>
function titre_groupe($id_mot, $table='groupes_mots', $id='id_groupe') {
	return cs_titre_id($id_mot, $table, $id);
}

Dans l’absolu, ces filtres suffisent déjà à simplifier l’écriture de vos squelettes, mais...

<BOUCLE_a(ARTICLES)>[(#ID_RUBRIQUE|titre_rubrique)]</BOUCLE_a>

Les balises

Mais allez, oubliez tout ce qu’on vient de dire, il y a encore plus simple ! Laissons tomber les filtres et créons des balises !

La balise #TITRE_PARENT ne sert qu’à une chose, faire croire au compilateur SPIP qu’il existe un champ ’titre_parent’ dans la base de données. Le code va subtilement lui faire chercher autre chose, un « vrai » champ de la base de données et on profite de l’aubaine pour appliquer directement le filtre qu’on vient d’imaginer. Voici comment sont devenus nos exemples proposés ci-dessus :

-  <BOUCLE_a(ARTICLES)>#TITRE_PARENT</BOUCLE_a>
-  <BOUCLE_b(BREVES)>#TITRE_PARENT</BOUCLE_b>
-  <BOUCLE_r(RUBRIQUES)>#TITRE_PARENT</BOUCLE_r>
-  <BOUCLE_m(MOTS)>#TITRE_PARENT</BOUCLE_m>

Joli n’est-ce pas ?

La fonction « balise_TITRE_PARENT_dist() » définit donc la balise #TITRE_PARENT. Cette fonction est appelée par le compilateur au recalcul de la page, pour remplacer le symbole « #TITRE_PARENT » par l’appel du code PHP, voilà comment.

Le fichier HTML dans lequel on va placer #TITRE_PARENT, qu’on appelle squelette, est décortiqué par le compilateur pour y découvrir des symboles qu’il va transformer en une portion de code plus complexe.

Ces portions de code vont être empilées dans une mémoire à laquelle on accédera plus tard pour recomposer un nouveau fichier, écrit en PHP.

La définition d’une balise SPIP sert donc à préciser par quelle portion de code sera remplacé le symbole auquel il fait référence, le tout étant stocké au bon endroit dans la pile. Cet endroit est un objet technique appelé Champ (parce qu’il fait référence au champ dans une table de base de données). Celui-ci est capable d’explorer la pile de code qu’on a mémorisé et pour faciliter l’exploration de cette pile mémoire, ainsi que la composition du code, on peut utiliser les fonctions du compilateur. C’est le fameux paramètre $p. Voici le code de cette balise :

// Rubrique parente de tout objet possédant un 'id_rubrique' ou groupe de mot-clef
function balise_TITRE_PARENT_dist($p) {
	// examen du contexte
	switch ($p->type_requete) {
		case 'rubriques':
			$table_parent = 'rubriques';
			$champ_parent = 'id_rubrique';
			$id = 'id_parent';
			break;
		case 'mots':
			$table_parent = 'groupes_mots';
			$id = $champ_parent = 'id_groupe';
			break;
		default:
			$table_parent = 'rubriques';
			$id = $champ_parent = 'id_rubrique';
			break;
	}
	// id de l'objet a trouver pour retourner son titre
	$id = champ_sql($id, $p);
	// le code php a executer
	$p->code = "cs_titre_id(intval($id), '$table_parent', '$champ_parent')";
	return $p;
}

On enregistre donc dans ce champ le code PHP qu’on souhaite. Ici, un appel au filtre ’cs_titre_id’ détaillé plus haut, avec en paramètre, la référence à de « vrais » champs de la la table de base de données : le numéro du père connu du fils. D’où l’utilisation de la fonction champ_sql, qui explore la pile pour atteindre le « vrai » champ SQL qui nous intéresse ici.

Encore un petit plaisir ? Voici une deuxième balise qui permet d’obtenir facilement le titre du groupe auquel appartient un mot-clé. Bien sûr, ceci est très pédagogique, mais que ne donnerait-on pour simplifier la lecture de nos squelettes ! Voici le code de la balise #TITRE_GROUPE :

// juste le groupe d'un mot-clef
function balise_TITRE_GROUPE_dist($p) {
	$p->code = "''";
	return $p->type_requete=='mots'?balise_TITRE_PARENT_dist($p):$p;
}

Pour les connaisseurs, il existe en fait un champ ’type’ dans la table des mots-clés, qui reproduit exactement ce que l’on veut ici. La balise #TITRE_GROUPE renvoie donc le même résultat que #TYPE ; seuls les traitements peuvent être différents (cf. paragraphe suivant).

Les traitements sur les balises

Une fois que le compilateur à entièrement exploré le fichier HTML et constitué cette fameuse pile mémoire, il va fabriquer un fichier en PHP qui aura donc remplacé tous les symboles par du « vrai » code. Ce résultat est visible quand on affiche le débusqueur (&var_mode=debug).

Mais avant d’imprimer le code qu’on a demandé dans le fichier, SPIP va ajouter d’autres traitements, autrement dit, il va appliquer d’autres filtres. Par exemple, la typographie, la fonction propre() qui transformera les raccourcis SPIP en HTML ou autre. Tout ces traitements sont regroupés dans une variable $table_des_traitements.

Un SPIP installé connaît les traitements qu’il doit appliquer au champ qui lui sont connu. Mais #TITRE_PARENT, il ne le connaît pas encore. Or, c’est le titre d’une rubrique, il faut appliquer la typographie des #TITREs traditionnels. On explique donc au compilateur que #TITRE_PARENT est à traiter comme un #TITRE normal et par conséquent, la typographie standard lui sera appliquée avant son affichage.

/// invoquer la table des traitements
include_spip('public/interfaces');
global $table_des_traitements;


// TITRE_PARENT et TITRE_GROUPE sont des TITREs !
if (!isset($table_des_traitements['TITRE_PARENT']))
	$table_des_traitements['TITRE_PARENT'] = $table_des_traitements['TITRE'];
if (!isset($table_des_traitements['TITRE_GROUPE']))
	$table_des_traitements['TITRE_GROUPE'] = $table_des_traitements['TITRE'];
}

Petite finesse ici : Les experts pourront toute de même personnaliser le traitement qu’ils tiennent à réserver à ces nouvelles balises. Aussi, si un traitement spécifique leur est affecté dans le fichier config/mes_options.php, on ne l’écrase pas.

La suite : la syntaxe étendue...

Pourquoi ne pas étendre cette idée #TITRE_OBJET à tous les objets de SPIP ? L’idée serait de programmer une balise « ouverte » (#TITRE_QQCHOSE) qui donnerait le titre de n’importe quel objet référencé dans n’importe quelle table, grâce à son simple « id_qqchose ».

Saviez-vous que la table ’spip_forum’ par exemple possède tous ces champs : id_forum, id_parent, id_thread, id_rubrique, id_article, id_breve, id_auteur, id_message, id_syndic ? Et donc, autant de liaisons avec tous ces objets...

M’enfin, avec nos filtres décrits en tout début d’article, on peut, même sans balise dédiée, accéder à tous les titres sans boucle supplémentaire. Il suffit juste d’avoir un peu les idées claires :

<BOUCLE_f1(FORUMS){tout}>
	&bull; Message #ID_FORUM, enfant du message : 
	[(#ID_PARENT|cs_titre_id{forum,id_forum})]
	<br />
</BOUCLE_f1>

<BOUCLE_f2(FORUMS){tout}>
	&bull; Message #ID_FORUM, attaché à l'article : 
	[(#ID_ARTICLE|cs_titre_id{articles,id_article})]
	<br />
</BOUCLE_f2>

Après activation de la fonctionnalité au niveau de la configuration de l’outil « balise #TITRE_PARENT », le Couteau Suisse donne accès à ces nouvelles balises raccourcis (uniquement vous utilisez SPIP v2.0 minimum). Il s’agit donc d’un ensemble de balises #TITRE_XXX qui pourront vous donner le titre de l’objet ’xxx’, à condition que le champ ’id_xxx’ soit présent dans la table en cours (#ID_XXX utilisable dans la boucle en cours).

Par exemple, dans une boucle sur (ARTICLES), #TITRE_SECTEUR donnera le titre du secteur dans lequel est placé l’article en cours, puisque l’identifiant #ID_SECTEUR (ou le champ ’id_secteur’) est disponible dans ce cas.

Ces « balises ouvertes » existent déjà dans SPIP : #LOGO_QQCHOSE, #URL_QQCHOSE, #FORMULAIRE_QQCHOSE, etc.

Dans le cas de notre table ’spip_forum’, les nouvelles balises #TITRE_THREAD, #TITRE_RUBRIQUE, #TITRE_ARTICLE, #TITRE_BREVE, #TITRE_AUTEUR, #TITRE_MESSAGE renverrons les titres contenus dans la table, si les identifiants respectifs (#ID_THREAD, #ID_RUBRIQUE, etc.) ont été renseignés par SPIP au moment de la création de l’objet ’forum’.

Une exception à connaitre : équivalente à la balise #NOM placée dans une boucle sur (AUTEURS), la balise #TITRE_AUTEUR renvoie le ’nom’ de l’auteur et non le ’titre’.

Un paramètre fixe ?

Afin de récupérer le titre du message X ou de la rubrique Y, voici encore un moyen d’éviter d’écrire une boucle : le plugin s’en charge à votre place. Ajoutez simplement un paramètre numérique à n’importe quelle balise #TITRE_XXX comme ceci : #TITRE_XXX{yyy}.

Exemple : #TITRE_ARTICLE{10} renverra le titre de l'article #10. Simple, n’est-ce pas ?

... À moins que vous eussiez préféré la syntaxe originelle de SPIP :
<BOUCLE_art(ARTICLES){id_article=10}>#TITRE</BOUCLE_art>

Rappel : les balises #TITRE_XXX ne sont disponibles que si vous avez coché « oui » à « Activer l’utilisation étendue des balises #TITRE_XXX » (Rendez-vous dans la configuration de l’outil « Balises #TITRE_PARENT/OBJET »). Par défaut, ces balises ne sont pas actives.

Mise en garde !!

L’un des intérêts de cette contribution est la pédagogie. Dans vos squelettes, n’abusez pas des balises décrites ici, car chacune crée un appel à la base de données. Hors, il faut tout faire pour éviter les appels trop fréquents, histoire de ne pas surcharger le serveur, surtout s’il est mutualisé. Certains hébergeurs limitent parfois le nombre d’accès afin d’éviter les abus.

-  La règle est donc : une seule balise #TITRE_QQCHOSE par boucle au maximum, et surtout, aucun doublon de balise dans la rédaction.

J’appelle ici un doublon de balise, une balise #TITRE_OBJET placée dans une boucle (OBJETS), qui vient en doublon de la balise #TITRE déjà proposée par SPIP. La première effectue un accès à la base de donnée alors que la second aucun : c’est la boucle qui s’occupe de cet accès.

Exemple incorrect (doublon de balise) :

<BOUCLE_lstRub(RUBRIQUES)>
   <BOUCLE_Art(ARTICLES){id_rubrique}>
   <br /> Art :  #ID_ARTICLE - #TITRE
   [(#REM) titre de la rubrique mère maintenant]
   <br />#TITRE_PARENT
   </BOUCLE_Art>
</BOUCLE_lstRub>

Exemple correct :

<BOUCLE_Rub(RUBRIQUES)>
   <BOUCLE_Art(ARTICLES){id_rubrique}>
   <br /> Art :  #ID_ARTICLE - #TITRE
   [(#REM) titre de la rubrique maintenant]
   <br />#_Rub:TITRE
   </BOUCLE_Art>
</BOUCLE_Rub>

Rappelez-vous donc bien ceci : la balise #TITRE_QQCHOSE proposée ici est un raccourci très pratique d’une boucle SPIP. Exemple : utilisée dans une boucle (MOTS), la balise #TITRE_GROUPE est le raccourci de :
<BOUCLE_grp(GROUPES){id_mot}>#TITRE</BOUCLE_grp>.

Notes

[1NDLR : lire ici « cet outil du Couteau Suisse »

Merci à Mathieu Drouet (IZO) pour le logo :)

Discussion

7 discussions

  • 1

    Bonjour,

    Peux-ton utiliser #TITRE_PARENT comme critère ?

    • Ah c’est une bonne idée, mais le critère n’existe pas pour l’instant. A voir donc avec le système classique de boucles de SPIP.

    Répondre à ce message

  • 1

    Bonjour,

    J’utilise le couteau suisse 1.8.133, dans la boucle ci-après impossible de classer le résultat par titre alpha…

    Une idée ?

    <BOUCLE_rub(RUBRIQUES){titre=#TITRE*} {exclus} {par multi titre, titre} >
    <a href="#URL_RUBRIQUE">[(#TITRE_PARENT|supprimer_numero)]</a>
    </BOUCLE_rub>

    Merci,

    Clem

    • Ah je pense que c’est normal car tu fais le tri dans ta boucle sur les rubriques filles, alors que tu appelles le titre des rubriques parent... Ton tri ne sert à rien du coup.

      Une idée serait que tu stockes les données dans un tableau dans un premier temps, puis une 2e boucle triera le tableau pour l’affichage...

    Répondre à ce message

  • 1

    Salut, bien pratique ce titre_parent, merci de l’avoir intégré au couteau suisse (quand il est déjà installé ca permet de ne pas rajouter un plug en plus..).

    petite question cpdt, une rubrique « niveau 0 » contient une sous rubrique « Niveau 1 » qui elle meme contient une rubrique « niveau 2 » dans laquelle est l’article (une actualité).

    si je fais #TITRE_PARENT, c’est le nom de la rubrique « niveau 2 » qui est appelé
    si je fais #TITRE_SECTEUR, c’est le nom de la rubrique « niveau 0 » qui est appelé,
    Comment faire pour appeler simplement le nom de la rubrique « niveau 1 » ?

    Merci d’avance.

    • A mon avis, il faut revenir aux fondamentaux : la boucle ;-)

      <BOUCLE_rubrique(RUBRIQUES){id_rubrique}>
          <h1>#_rubrique:TITRE</h1>
          <h2>#_rubrique:TITRE_PARENT</h2>
      </BOUCLE_rubrique>

      (code non testé)

    Répondre à ce message

  • 1

    dommage d’avoir a installer l’ensemble du « couteau suisse » pour disposer de la seule balise #TITRE_OBJET...

    • Ceci est un éternel débat. Le Couteau Suisse est un panier d’outils qui se compile tout seul et qui sait se montrer très discret lors de l’exécution du site. Il facilite grandement la tâche des webmestres.

      Maintenant, si tu crains le trop pour le petit rien, alors isole le fichier de la lame en question et inclus-le facilement dans ton squelette. Je pense qu’il y a peu de modifs pour que ça marche ainsi.

    Répondre à ce message

  • 1
    Romy Têtue

    Je m’étonne d’être citée dans cette page : contrairement à ce que cela laisse entendre, je ne me souviens pas avoir eu la moindre discussion à ce sujet avec l’auteur de la présence page, Patrice Vanneufville ! Je demande à ce que cette citation soit immédiatement retirée. Ce serait mieux de faire un lien vers l’article source, Balise #TITRE_PARENT, plutôt de de le plagier aussi grossièrement.

    • Patrice Vanneufville

      Romy, il ne s’agit pas d’une discussion privée, mais bien d’un message public que tu as posté ici : http://trac.rezo.net/trac/spip/tick....

      Le lien vers l’article source a toujours été présent ci-dessus !! Mais puisque tu ne l’as pas clairement vu, je viens de le mettre davantage en valeur.

    Répondre à ce message

  • 4

    ah oui, effectivement, une petite ligne de code à ajouter... Tu te charges du commit ?

    • si je savais comment faire tout serait plus simple ;)

    • OK, cette fonctionnalité est désormais disponible (fichier zip de 20h35 ce soir).

    • Hello, je pense qu’il y a un bug j’essaie d’utiliser [(#TITRE_RUBRIQUE{1})] il me ressort :

      id_rubrique - rubriques - rubrique - ’1’ - Espace institutionnel

      (spip 2.0.3, dernier version du plugin)

    • Oui, c’est exact, toutes mes excuses, du code debug trainait par là... C’est réparé.

    Répondre à ce message

  • Il serait bien pratique de pouvoir faire qqchose comme
    [(#TITRE_ARTICLE{11})] pour resortir le titre d’un object en lui passant un id en paramètre sans avoir à faire de boucle autour

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

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