Mirari
Affichage d'une page
Page "mirari.dev.bbcode" créée par Zephyr le 21/02/2009 à 16h33 48s :

Mirari :: Développement :: Transformation des balises (BBCode) en XHTML valide

Vous êtes sur l'une des pages d'informations pour développeurs (cliquez ici pour revenir en arrière).

1. Présentation du script

Mirari utilise un script de transformation des balises BBCode (comme [b]ceci[/b] par exemple) sur les pages d'information ainsi que dans les news et leurs commentaires. L'objectif ici était de disposer d'un script rapide et capable de générer du code XHTML valide, ce qui signifie être en mesure de produire un code XHTML qui passe le validateur du w3c quel que soit le texte qu'on lui donne en entrée. Voici quelques-uns des problèmes que l'on peut rencontrer :

  • Balises ouvertes et non fermées, ou fermées et non ouvertes (qui ne doivent pas être prises en compte et laissées inchangées dans le texte)
  • Balises avec des paramètres invalides (même remarque que dans le cas précédent)
  • Balises avec une imbrication incorrecte, [b][u]comme[/b] ceci[/u] (les balises doivent alors être décroisées <b><u>comme</u></b><u> ceci</u> par exemple)
  • Mauvaise imbrication d'éléments de types "block" et "inline", [b][align=left]comme[/align] ceci[/b] (l'enchainement doit être rectifié pour éviter ce genre de cas)
  • Balises qui se chevauchent, [list]* [b]comme * ceci[/b][/list] (le style gras doit être fermé avant le </li><li> provoqué par le changement de ligne, puis réouvert ensuite)
  • etc...

Après un petit tour sur le net je n'ai trouvé aucune bibliothèque qui réunisse les deux critères évoqués ci-dessus : aucune n'était assez résistante face à une syntaxe invalide, et beaucoup étaient relativement lentes, c'est pourquoi je propose ici ma tentative, qui est utilisée sur ce site et a été codée de façon à être facilement adaptable.

2. Utilisation

Vous pouvez télécharger le script en cliquant sur ce lien ou l'essayer en vous rendant ici. Pour l'inclure dans vos propres pages web et l'utiliser tel quel, seuls les deux fichiers "format.php" et "format.mirari.php" sont nécessaires (voyez le paragraphe 3 pour davantage d'informations concernant leurs rôles).

Depuis votre page PHP, commencez par inclure ces deux scripts de la façon habituelle :

require ('code/format.php');
require ('code/format.mirari.php');

L'utilisation se réalise ensuite en deux étapes :

  • Compilation des modifieurs (l'ensemble des balises) pour accelérer les futurs traitements
  • Traitement des chaines de caractère en utilisant les données compilées

La compilation permet transformer les structures décrivant les balises, contenues dans le fichier "format.mirari.php" sous la forme de deux variables "$_formatModifiers" et "$_formatArguments", vers un format interne plus rapide à traiter. Il suffit donc d'appeler la fonction suivante :

$format = formatCompile ($_formatModifiers, $_formatArguments);

Notez qu'il vous sera peut-être nécessaire d'ajouter les lignes nécessaires pour déclarer "$_formatModifiers" et "$_formatArguments" en tant que variables globales. Une fois la compilation effectuée, vous pouvez traiter vos chaines de caractère de la façon suivante :

$string = formatString ($string, $format, 'iso-8859-1');

La fonction "formatString" va transformer la chaine "$string" en y appliquant toutes les balises définies. De plus, elle va échapper toutes les entités HTML présentes dans la chaine, et transformer les retours à la ligne en balises "<br />".

Notez qu'un seul appel à la fonction "formatCompile" est nécessaire, une fois la variable "$format" obtenue vous pouvez traiter autant de chaines que vous souhaitez jusqu'à la fin de l'exécution du script.

3. Personnalisation

Les informations qui suivent vous permettront de modifier le fichier "format.mirari.php" pour y ajouter vos propres balises. Ce fichier contient deux variables et un ensemble de fonctions de traitement dont les rôles respectifs sont les suivants :


  • La variable "$_formatArguments" indique les caractères autorisés dans les arguments de vos futures balises, nous reviendrons sur sa structure par la suite.
  • La variable "$_formatModifiers" contient la liste des modifieurs (cf. plus bas) et des fontions de traitement à appeler pour chacune d'entre elles.
  • À la suite du fichier sont placées toutes les fonctions de traitement référencées par la variable "$_formatModifiers"

Bien sûr, libre à vous de renommer toutes les variables et fonctions du fichier, à condition d'adapter les appels à la fonction "formatCompile" dans vos scripts.

La variable "$_formatModifiers" est un tableau dont chaque élément est un "modifieur", c'est à dire un ensemble de balises prévues pour fonctionner ensembles, comme [b] et [/b] par exemple, ainsi que toutes les informations qui leurs sont liées. Chaque modifieur est un tableau associatif qui peut définir les clés suivantes :

  • 'limit' : Argument optionnel qui indique combien de fois au maximum le modifieur sera pris en compte dans le texte (les occurrences suivantes seront ignorées).
  • 'prec' : Argument optionnel qui indique la priorité du modifieur, utilisée afin de traiter correctement les imbrications de balise. Une balise d'une priorité donnée ne peut pas être "coupée" par une balise de priorité supérieure ; elle sera fermée puis réouverte à la suite.
  • 'tags' : Tableau associatif contenant les balises et leur type. Il existe des balises ouvrantes (comme [b]), fermantes (comme [/b]), intermédiaires (comme * dans une liste) ou autonomes (comme [hr]). Les clés du tableau indiquent les balises et leurs éventuels arguments (cf. plus bas), et les valeurs indiquent leurs types : 0 pour une balise autonome, 1 pour une ouvrante, 2 pour une intermédiaire et 3 pour une fermante.
  • 'init' : Argument optionnel, nom de la fonction appelée quand une balise ouvrante est rencontrée. Prototype : ($tag, &$args), où "$tag" contient la balise rencontrée et "&$args" le tableau des arguments (qui peut être modifié ou completé)
  • 'step' : Argument optionnel, nom de la fonction appelée quand une balise intermédiaire est rencontrée. Prototype : ($tag, $str, &$args), où "$tag" contient la balise rencontrée, "$str" le texte capturé depuis la dernière balise ouvrante ou intermédiaire et "&$args" le tableau des arguments (qui peut être modifié ou completé).
  • 'stop' : Nom de la fonction appelée quand le modifieur est fermé (par une balise autonome ou fermante, ou parcequ'une balise de priorité supérieure a été ouverte entre-temps). Prototype : ($str, &$args), où "$str" contient le texte capturé depuis la dernière balise ouvrante ou intermédiaire et "&$args" le tableau des arguments. Cette fonction doit retourner le texte transformé (résultat de l'application de la balise), ou bien la valeur "null" pour annuler son effet.

Le principe est simple : chaque fois qu'une balise définie dans l'un des attributs 'tags' des modifieurs est rencontrée, la fonction correspondante est appelée. Le tableau "$args" est conservé pendant toutes les phases de traitement d'un modifieur, vous permettant d'y stocker des données temporaires si besoin. La fonction finale, référencée par l'attribut 'stop', doit retourner le texte à insérer à la place de celui qui était contenu dans les balises.

Un exemple sera peut-être plus parlant ; le modifieur le plus basique possible ne possède qu'une fonction fermante, comme ceci :

array
(
    'tags'  => array ('[b]' => 1, '[/b]' => 3),
    'stop'  => 'formatBold'
)

Ainsi, une balise "[b]" dans le texte marquera le début de ce modifieur. Une fois la balise fermante "[/b]" rencontrée, la fonction "formatBold" sera appelée. Elle peut être définie de la manière suivante :

function    formatBold ($str, &$args) // $args est inutile ici
{
    return '<b>' . $str . '</b>'; // ajout des balises HTML permettant de mettre le texte en gras
}

De cette façon, tout texte compris entre des blalises [b] et [/b] dans votre chaine initiale sera encadré par les balises XHTML <b> et </b>, qui auront pour effet de provoquer son affichage en gras.

Enfin, une balise peut spécifier un ou plusieurs arguments variables, qui se présentent sous la forme d'un identifiant entre parenthèses. Cet identifiant fait référence à une clé du tableau "$_formatArguments", dont la valeur correspondante indique les caractères autorisés pour cet argument. Prenons l'exemple suivant :

array
(
    'tags'  => array ('[img]' => 1, '[img=(i),(i)]' => 1, '[/img]' => 3),
    'stop'  => 'formatImage'
)

Deux balises ouvrantes sont possibles pour ce modifieur : l'une sans paramètre, l'autre avec deux paramètres de type "i". Il reste à définir quels sont les caractères utilisés pour un paramètre de type "i", par exemple les chiffres de 0 à 9. Il suffit de définir le tableau "$_formatArguments" avec le couple suivant :

$_formatArguments = array
(
    'i' => '0123456789'
);

De cette façon, la balise [img=8,32] sera reconnue, mais pas la balise [img=a,b] puisque ses arguments contiennent des caractères non définis dans "$_formatArguments['i']". Les arguments de vos balises seront automatiquement insérés dans le tableau "$args" passé en paramètre aux fonctions de traitement. Le premier argument sera placé dans "$args[0]", le second dans "$args[1]", etc.

Notez que les caractères '(' et ')' sont utilisés pour déclarer des paramètres et ne peuvent donc pas être utilisés en tant que caractères normaux. Si vous désirez créer des balises contenant des parenthèses, il vous faudra redéfinir les caractères spéciaux de début et de fin de déclaration d'argument en modifiant les constantes FORMAT_START et FORMAT_STOP au début du fichier "format.php". De même, le caractère '\' est par défaut réservé pour échapper les balises et empêcher leur prise en compte, vous pouvez changer ce caractère en modifiant la constante FORMAT_ESCAPE.

Le fichier "format.mirari.php" fourni dans l'archive contient toutes les balises utilisées dans les articles et news de Mirari, vous pouvez vous en inspirer à titre d'exemple. J'espère que malgré cette courte documentation rédigée à l'arrache, ces quelques lignes de code pourront servir à quelque d'autre que moi :)

Dernière modification par Zephyr le 20/10/2009 à 13h09 56s

Afficher la liste des pages créées
Rechercher parmi les pages
Vous pouvez créer une page si vous possédez un compte utilisateur
© RCa 2011 :: 8 ms