Hello !
J'aimerais mettre à jour le code qui permet de rendre le bbcode de yAronet pour corriger principalement deux défauts, dont l'un est la complexité du code causée par certaines balises comme
[pre] qui doit empêcher l'interprétation de toutes les autres balises (sauf
[/pre]). J'ai une version qui fonctionne quasiment, mais il me reste un problème de priorité pour lequel je n'ai pas trouvé de solution satisfaisante.
Les balises sont reconnues en suivant une règle très simple :
- On commence par repérer les balises dans le texte, sachant qu'une balise correspond à n'importe quelle suite de caractères qui peut donner lieu à une inteprétation (par exemple
[b]), puis on les regroupe en séquences de balises compatibles (par exemple la balise
[b] suivie de
[/b] plus loin dans le texte forment une séquence de balises compatibles).
- Une fois formées les séquences de balises sont résolues dans le sens de lecture, c'est à dire qu'une séquence qui commence avant une autre a la priorité. Autrement dit,
[b]machin[b]truc[/b] donne
<b>machin[b]truc</b> : la première balise
[b] a priorité sur la seconde, c'est donc elle qui est retenue pour faire partie de la séquence.
- La même règle s'applique dans le cas de balises qui se superposent, par exemple on trouve trois balises dans
[url=http://www.google.fr]google[/url] :
[url=http://www.google.fr],
http://www.google.fr (puisque les URLs sont reconnues automatiquement) et
[/url]. Les deux premières balises sont superposées et c'est la première qui va avoir la priorité (en revanche sans la balise fermante
[/url] la première balise ne ferait plus partie d'une séquence complète et c'est la seconde qui serait alors prise en compte).
Cette règle permet d'éliminer une grosse lourdeur dans le code pour les balises
[pre] et
[code] : jusqu'ici j'utilisais une notion de contexte pour définir quand une balise est valide ou non. En l'occurrence,
[pre] définit un contexte dans lequel aucune autre balise que
[/pre] n'est reconnue. Mais cette gestion de contextes complexifie pas mal le code pour gérer seulement deux cas particuliers, et elle peut être remplacée par une solution bien plus simple : plutôt que deux balises distinctes (une ouvrante et une fermante),
[pre] devient une seule balise dont l'expression régulière est
[pre].*[/pre] (avec un "*" non glouton). Une fois reconnue cette balise superpose toutes les éventuelles balises prises dans le
.*, et comme elle les précède elle a la priorité, ce qui les empêche d'être reconnues.
En bonus, c'est une règle qui permet de tout traiter en une passe et s'implémente facilement. Jusqu'ici tout va bien.
Maintenant, un problème se pose pour les tableaux qui ont un jeu de balises compliqué et assez peu logique. Pour des raisons historiques, un tableau ressemble à ça :
[table] [^] En-tête 1 [^] En-tête 2 [-] [|] Ligne 1 [|] Ligne 2 [/table]. On pourrait croire qu'il commence par deux balises
[table] [^], mais en réalité il s'agit d'une seule balise de la forme
[table]\s*[^] : le
[^] est obligatoire pour indiquer qu'on veut ouvrir une cellule d'en-tête (et non une cellule simple) et il ne peut pas y avoir de texte entre
[table] et
[^] (il n'apparaîtrait pas dans le tableau puisqu'il se trouve avant le premier
[^] qui déclare le début de la toute première cellule). Il en est de même pour
[-]\s*[^] qui termine une ligne et déclare la première cellule de la ligne suivante. C'est comparable à ce qu'on trouve en HTML : bien qu'il faille écrire
<table> <tr> <td> pour débuter un tableau, insérer du contenu entre ces trois balises est invalide. En revanche ici il existe bien des balises
[^] et
[|] qui permettent de terminer une cellule et de passer à la suivante. Si je résume, un tableau est formé par une combinaison de ces balises :
-
[table]\s*[^] : démarrer un tableau en commençant par une cellule d'en-tête
-
[table]\s*[|] : démarrer un tableau en commençant par une cellule normale
-
[-]\s*[^] : terminer la ligne et commencer une cellule d'en-tête
-
[-]\s*[|] : terminer la ligne et commencer une cellule normale
-
[^] : terminer la cellule en cours et commencer une cellule d'en-tête
-
[|] : terminer la cellule en cours et commencer une cellule normale
-
[/table] : terminer le tableau
Avec ce joyeux bazar, supposons que je veuille insérer un tableau à l'intérieur d'un autre tableau. Voilà ce que je vais avoir envie écrire :
[table]
[^] Titi
[-]
[|] [table][^] Sous-tableau [/table]
[-]
[|] Toto
[/table]
Bon, aujourd'hui ça fonctionne plus ou moins, mais vous ne voulez vraiment pas savoir comment. Malheureusement avec les règles définies plus haut, ça ne va plus fonctionner comme je m'y attends. Voilà deux des séquences de balises qui vont être trouvées (je vous épargne toute la combinatoire) :
[table] [^] Titi [-] [|] [table][^] Sous-tableau [/table] [-] [|] Toto[/table]
1: <---------> <-----> <-> <-----> <------>
2: <--------> <------>
En suivant toujours la même règle, la séquence 1 va être prise en priorité et manger le second
[^] qui aurait pu permettre d'ouvrir un second tableau avec la séquence 2. Le problème vient du fait que les balises des tableaux sont ambiguës, et ici j'ai deux balises superposées qui donnent lieu à deux interprétations différentes.
J'aimerais trouver une règle pour corriger ce problème, si possible simple, mais qui n'entre en conflit avec aucun des autres cas cités plus haut. Si je remplace ma règle par "on commence à trouver les séquences par la droite", ou "on commence à trouver les séquences par l'intérieur", non seulement je vais rendre le code sensiblement plus complexe mais surtout la balise
[pre] telle que je la décrivais plus haut ne fonctionnera plus, pas plus que
[url=http://bidule]chose[/url].
Une autre façon de résoudre le problème serait de choisir des balises non ambiguës pour les tableaux, mais ça voudrait dire casser la sacro-sainte rétro-compatibilité et 0² m'en voudrait
.
Avez-vous des idées ?