Je suis de retour pour poser quelques questions sur les expressions régulières.
Ayant remarqué qu'il n'existe aucun script PHP implémentant la syntaxe Wiki définit par le groupe Creole (à part PEAR qui l'implémente mais en php4, et avec divers packages liés entre eux), je me suis décidé de réaliser une classe PHP5.
Les recommandations sont disponibles ici :
http://www.wikicreole.org/wiki/Creole1.0
J'ai donc commencé à écrire ceci :
<?php
class CreoleParser
{
/**
* The rules in order to respect the Creole recommendations.
*/
private $rules = array(
'Emphasis' => array(
'regex' => '#\/\/(.*?)\/\/#',
'xhtml' => '<em>$1</em>',
'type' => 'default'),
'Headings' => array(
'regex' => '#^(={1,6})(.*?)(=+)#m',
'type' => 'callback'),
'HorizontalLine' => array(
'regex' => '#-{4}#m',
'xhtml' => '<hr />',
'type' => 'default'),
'Image' => array(
'regex' => '#{{(.*)(\|(.*))?}}#U',
'type' => 'callback'),
'Links' => array(
'regex' => '#(^|\s)(\*\*|\/\/)(http(s)?|ftp):\/\/(.*)(\.[a-z]{2,4})(\*\*|\/\/)#m',
'type' => 'callback'),
'Strong' => array(
'regex' => '#\*\*(.*?)\*\*#',
'xhtml' => '<strong>$1</strong>',
'type' => 'default'),
'Underline' => array(
'regex' => '#__(.*?)__#',
'xhtml' => '<ins>$1</ins>',
'type' => 'default'),
'Url' => array(
'regex' => '#\[\[(.*)(\|(.*))?\]\]#U',
'type' => 'callback'),
);
/**
* @type String
* Content the last parsed text.
*/
private $text = '';
private function processHeadings($matches) {
$count = strlen($matches[1]);
return '<h' . $count . '>' . $matches[2] . '</h' . $count . '>';
}
private function processImage($matches) {
$alt = $matches[3];
$src = $matches[1];
if (!$alt) {
return '<img src=' . $src . ' />';
} else {
return '<img src="' . $src . '" alt="' . $alt . '" />';
}
}
private function processLinks($matches) {
$start_tag = $matches[2];
$href = $matches[3] . '://' . $matches[5] . $matches[6];
$end_tag = $matches[7];
if (($start_tag == '**' && $end_tag == '**') ||
($start_tag == '//' && $end_tag == '//')) {
return $start_tag . '<a href="' . $href . '">' . $href . '</a>' . $end_tag;
} else {
return '<a href="' . $href . '">' . $href . '</a>';
}
}
private function processUrl($matches)
{
$href = $matches[1];
$title = $matches[3];
$url = '<a href="' . $href . '"';
if ($title) {
$url .= ' title="' . $title . '"';
$url .= '>' . $title . '</a>';
} else {
$url .= '>' . $href . '</a>';
}
return $url;
}
public function parse($txt)
{
$this->text = $txt;
foreach ($this->rules as $rule=>$values) {
if ($values['type'] == 'default') {
$this->text = preg_replace($values['regex'], $values['xhtml'], $this->text);
}
else {
$this->text = preg_replace_callback($values['regex'], array($this, 'process'.$rule), $this->text);
}
}
return $this->text;
}
}
?>
Pour l'instant les règles implémentées (les plus simples) fonctionnent sauf pour une : "Links"En effet celle-ci rentre en conflit avec l'emphase. J'ai utilisé une fonction de callback pour corriger le problème avec la mise en gras "Strong". Mais pour l'emphase je vois pas d'ou vient le problème.
Petit morceau de code pour tester :
<?php
require_once 'Creole.class.php';
$creoleParser = new CreoleParser();
$txt = "=What's a Plouk=";
$txt .= "{{http://www.ecoledesmax.com/espace_regroupeurs/pages_activites/documents/plouk.jpg|Un plouk}}\n\n";
$txt .= "//Un plouk, un vrai//\n";
$txt .= "==Un plouk en details==";
$txt .= "Visitez : http://www.plouktv.com\n";
$txt .= "**//http://www.google.fr//**\n";
$txt .= "[[http://www.google.fr|Plouk library]]";
echo $creoleParser->parse(nl2br($txt));
?>
Ma question étant comment éviter ces conflits ? Car si je modifie une règle, une autre rentre en conflit etc... Ca devient vite très compliqué. Es-ce qu'il faut modifier la règle entrant en conflit (ce que je n'arrive pas à vraiment faire), ou bien adapter les autres règles en conséquence ?Es-ce que un parseur correctement fait peut tenir compte de l'ordre des règles parsées ou cela ne devrait pas avoir d'importance ?
Merci.
Cordialement,
Laurent