Pour un projet sur lequel je travaille actuellement, j'ai dût avoir recours à la syntaxe utilisée par les moteurs wiki : pour sa simplicité d'utilisation (plus accessible que l'html).
Seulement en regardant les expliquations faites de la syntaxe notament sur wikipedia, J'y ai vu beaucoups d'abérations sémantiques ...
J'ai donc décidé de la retravailler, en respectant la sémantique, et en essayant d'améliorer quelques points.
Elle est cependant actuellement beaucoups moin complète que celle des moteurs wiki, car pour le moment, je l'ai programmé seul, et je suis allé à l'essentiel requis par le projet en cours.
Je soumet ce code aujourd'hui pour partager mon travaille et pour que toute une communauté puisse travailler à son enrichissement.
Voici la page d'interprétation, incluant l'interpréteur et un formulaire pour le tester :
<?
//estimation du nombre de lignes pour l'affichage dans les textareas ....
function nblignes ($chaine) {
$i=1;
preg_match_all('#^#m', $chaine, $out);
for($j=0;isset($out[0][$j]);$j++) $i++;
return $i;
}
//############################################################################
//############################################################################
//############################ DEBUT INTERPRETEUR ############################
//############################################################################
//############################################################################
//#### LES PARAGRAPHES
// Les paragraphe se font (comme vous pourrez le voir dans l'exemple) juste en écrivant sur une nouvelle ligne ...
function wiki2html_p ($return) {
// Citation de touts les cas où le code ne doit pas mettre de balise p.
if(preg_match('#^(?:=|\*|\#|//|\n|\(:|:|;;|:\)|-{4,}|<!--|(?-s).*"""(?s)|(?U)\{.*\}(?-U)\s*$)#ms',trim($return[2]))) return $return[0];
else return $return[1].'<p>'.trim($return[2]).'</p>';
}
//#### LES TITRES
/*
[x*]=[!] titre [:: id ][x*]=
([x*] correspond à x fois le caractère qui le suit (signe égal))
(les autres [] correspondent à des champs facultatifs)
Le nombre de signes égals correspond au rang du titre dans la hierarchie. Pour une adaptation, il est possible de décaler les rangs des titres du document afin que ce dernier s'adapte à la page, avec la variable $wiki2html_decalage déclarée ci-dessous. Ainsi avec la valeur de 2 =titre= donnerra une balise h(1+2) : h3 plutot qu'une h1, et ==sous-titre== donnerra une balise h4.
L'éventuel point d'exclamation après le/les premiers signes égals rend le titre invisible à l'affichage final.
Il est possible d'atribuer un id aux titres (pour des liens de positions notament), il suffit pour cela de le mettre après l'intitulé du titre, et de séparer ces deux éléments de deux "deux points".
Une ligne dont le nombre de signes égals ne serra pas égal en début et fin ne serra pas considéré comme un titre.
*/
$wiki2html_decalage=2;
function wiki2html_titre ($return) {
global $wiki2html_decalage;
$return[4] = split("::",$return[4]);
$espace = $return[1];
$titre = trim($return[4][0]);
$niveau = strlen($return[2])+$wiki2html_decalage;
if($return[3] == '!') $class = ' class="hidden"';
else $class = '';
if(isset($return[4][1])) {
$id = trim($return[4][1]);
if($id != "") $id = ' id="'.$id.'"';
}
else $id = '';
return $espace.'<h'.$niveau.$id.$class.'>'.$titre.'</h'.$niveau.'>';
}
//#### LES BARRES HORIZONTAL
// (4 ou plus) tirés sur une ligne apart donne une barre horizontal hr.
function wiki2html_hr ($return) {
return $return[1].'<hr />';
}
//#### LES IMAGES
/*
{ url [:: alt ][:: alignement]}
(les [] correspondent à des champs facultatifs)
Voir les exemples.
*/
function wiki2html_image ($return) {
$return = split("::",$return[1]);
$url = trim($return[0]);
if(isset($return[1])) {
$alt = trim($return[1]);
if($alt != "") $alt = ' alt="'.$alt.'"';
}
else $alt = '';
if(isset($return[2])) {
$float = trim($return[2]);
if($float == "<") $float = ' class="left"';
elseif($float == ">") $float = ' class="right"';
else $float = '';
}
else $float = '';
return '<img src="'.$url.'"'.$alt.$float.' />';
}
//#### LES LIENS
/*
[ url {:: title }{:: hreflang }]intitulé[/]
(les {} correspondent à des champs facultatifs)
Voir les exemples.
*/
function wiki2html_lien ($return) {
$return[1] = split("::",$return[1]);
$url = trim($return[1][0]);
$intitule = trim($return[2]);
if(isset($return[1][1])) {
$title = trim($return[1][1]);
if($title != "") $title = ' title="'.$title.'"';
}
else $title = '';
if(isset($return[1][2])) {
$hreflang = trim($return[1][2]);
if($hreflang != "") $hreflang = ' hreflang="'.$hreflang.'"';
}
else $hreflang = '';
return '<a href="'.$url.'"'.$title.$hreflang.'>'.$intitule.'</a>';
}
//#### LES FORTES EMPHASES
function wiki2html_strong ($return) {
$intitule = $return[1];
//Vérification qu'il ne sagit pas d'une emphrase simple...
preg_match_all('#\'\'#', $return[1], $ems);
if((sizeof($ems[0])%2) == 0) return '<strong>'.$intitule.'</strong>';
else return $return[0];
}
//#### LES EMPHASES
function wiki2html_em ($return) {
//Je fais la démarche de traiter la chaine dans une fonction, pour prévoir d'éventuels ajouts plus complexes...
$intitule = $return[1];
return '<em>'.$intitule.'</em>';
}
//#### LES LISTES DE DEFINITIONS
/*
(:
: terme [:: id]
définition block
;;
: terme2 [:: id2]
définition2 block
;;
: terme3 [:: id3]
définition3 block
;;
:)
(les [] correspondent à des champs facultatifs)
Voir les exemples...
*/
// DT et DD
function wiki2html_ddt ($return) {
$return[1] = split("::",$return[1]);
$terme = trim($return[1][0]);
$definition = trim($return[2]);
//Ajout d'une tabulation à chaque ligne pour marquer l'appartenance à la balise dd
$definition = preg_replace('#^#m',"\t",$definition);
if(isset($return[1][1])) {
$id = trim($return[1][1]);
if($id != '') $id = ' id="'.$id.'"';
}
else $id = '';
return "\n\t".'<dt'.$id.'>'.$terme.'</dt>'."\n\t".'<dd>'."\n\t".$definition."\n\t".'</dd>';
}
// DL
function wiki2html_dlist ($return) {
$espace = $return[1];
$ddt = $return[2];
//traitements des termes à définir et de leur définition
$ddt = preg_replace_callback('#^\s*:(.*)\n(?sU)(.*)(?-Us)\n\s*;;\s*\n#m','wiki2html_ddt',"\n".$ddt."\n");
//Rajout de l'espace initial à chaque ligne...
$ddt = preg_replace('#^(\s*)#m','\1'.$espace,$ddt);
return $espace.'<dl>'.$ddt."\n".$espace.'</dl>';
}
//#### LES CITATIONS : BLOCK
/*
[ auteur ][:: titre ] """
citation en block
"""
(les [] correspondent à des champs facultatifs)
Voir les exemples...
*/
function wiki2html_blockquote ($return) {
$origine = $return[1];
$espace = $return[1];
$return[2] = split("::",$return[2]);
if(isset($return[2][0]) && trim($return[2][0]) != "") $auteur = trim($return[2][0]);
if(isset($return[2][1]) && trim($return[2][1]) != "") $source = trim($return[2][1]);
if(isset($auteur) || isset($source)) $origine.= '<p>Citation de <cite>';
if(isset($auteur)) $origine.= $auteur.'</cite>';
if(isset($auteur) && isset($source)) $origine.= ', <cite>'.$source.'</cite>';
if(!isset($auteur) && isset($source)) $origine.= $source.'</cite>';
if(isset($auteur) || isset($source)) $origine.= ' :</p>';
//Rajout de l'espace
$citation = preg_replace('#^#m',"\t".$espace,$return[3]);
return $origine."\n".$espace.'<blockquote>'."\n".$citation."\n".$espace.'</blockquote>';
}
//#### LES CITATIONS : INLINE
function wiki2html_q ($return) {
$intitule = $return[1];
return '<q>'.$intitule.'</q>';
}
//#### LES LISTES
//eum ici l'interprétation a été complexe, même si l'utilisation est simple ... voir l'exemple ...
// si quelqu'un veut une expliquation du code ... je peux essayer une tentative d'expliquation ...
function wiki2html_tab ($nb) {
$returned = "";
for($i=0;$i<$nb;$i++) $returned.= "\t";
return $returned;
}
$wiki2html_lastniveau = -1;
$wiki2html_type[$wiki2html_lastniveau] = "";
function wiki2html_listes ($return) {
global $wiki2html_lastniveau,$wiki2html_type;
if(preg_match('#^(\s*)([\*\#]*)(.*)#',$return[1],$liste)) {
$puces = strlen($liste[2]);
$niveau = $puces-1;
$lastpuces = $wiki2html_lastniveau+1;
$tab['xl'] = $niveau*2;
$tab['last']['xl'] = $wiki2html_lastniveau*2;
$tab['li'] = $niveau*2+1;
$tab['last']['li'] = $wiki2html_lastniveau*2+1;
if(preg_match('#\*$#', $liste[2])) $type = 'ul';
elseif(preg_match('#\#$#', $liste[2])) $type = 'ol';
else $type = '';
//Eventuel id ou class au ul
$liste[3] = split("::",$liste[3]);
$id_class = '';
if(isset($liste[3][1])) {
if(preg_match('#^(class|id)\s*:(.*)$#i',trim($liste[3][1]),$id_class)) {
$id_class = ' '.$id_class[1].'="'.trim($id_class[2]).'"';
}
else $id_class = ' id="'.trim($liste[3][1]).'"';
}
$changements = $niveau-$wiki2html_lastniveau;
if($changements > 1) echo '<p>Syntaxe Wiki Ereur - Listes : Vous ne devez pas dans la hierarchie des listes monter de deux niveaux d\'un coups.</p>';
if($changements <= 0 && $lastpuces > 0) $close['last']['li'] = true;
else $close['last']['li'] = false;
if($changements > 0) $open['xl'] = true;
else $open['xl'] = false;
if($puces > 0) $open['li'] = true;
else $open['li'] = false;
$close['nb']['all'] = $changements*(-1);
$returned = '';
$returned2 = '';
$closes = '';
if($close['last']['li']) {
$returned.= '</li>';
}
if($open['xl']) {
$returned.= wiki2html_tab($tab['xl']).$liste[1].'<'.$type.$id_class.'>';
}
for($i=0;$i<$close['nb']['all'];$i++) {
$closes.= "\n".wiki2html_tab($tab['last']['xl']-($i*2)).$liste[1].'</'.$wiki2html_type[$wiki2html_lastniveau-$i].'>';
if(!($i==($close['nb']['all']-1) && $puces <= 0)) {
$closes.= "\n".wiki2html_tab($tab['last']['li']-(($i+1)*2)).$liste[1].'</li>';
}
}
if($open['li']) {
$returned2.= "\n".wiki2html_tab($tab['li']).$liste[1].'<li>'.trim($liste[3][0]);
}
$wiki2html_lastniveau = $niveau;
$wiki2html_type[$wiki2html_lastniveau] = $type;
if(!($changements == 0 && $puces < 1)) return $returned.$closes.$returned2;
else return $return[0];
}
else return $return[0];
}
//Fonction finale
function wiki2html ($chaine) {
//#### LES COMMENTAIRES
// Block
$chaine = preg_replace('#^\s*(?Us)/\*.*\*/#m','',$chaine);
// ligne (pour ne pas que les // soient gènants, le commentaire n'est valable qu'en début de ligne).
$chaine = preg_replace('#^\s*//.*$#m','',$chaine);
$chaine = preg_replace_callback('#^(\s*)(.*)$#m','wiki2html_p',$chaine);
$chaine = preg_replace_callback('#^(\s*)(=+)(!?)(.+)\2\s*$#m','wiki2html_titre',$chaine);
$chaine = preg_replace_callback('#^(\s*)-{4,}\s*$#m','wiki2html_hr',$chaine);
$chaine = preg_replace_callback('#\{([^}]+)\}#','wiki2html_image',$chaine);
$chaine = preg_replace_callback('#\[([^]]+)\](.*)\[/\]#U','wiki2html_lien',$chaine);
$chaine = preg_replace_callback('#\'\'\'(.*)\'\'\'#U','wiki2html_strong',$chaine);
$chaine = preg_replace_callback('#\'\'(.*)\'\'#U','wiki2html_em',$chaine);
$chaine = preg_replace_callback('#^(\s*)\(:\s*\n(?sU)(.*)(?-Us)\n\s*:\)\s*$#m','wiki2html_dlist',$chaine);
$chaine = preg_replace_callback('#^(?-U)(\s*)(?U)(.*)"""\s*\n(?s)(.*)(?-s)\n\s*"""\s*$#Um','wiki2html_blockquote',$chaine);
$chaine = preg_replace_callback('#""(.*)""#U','wiki2html_q',$chaine);
$chaine = preg_replace_callback('#^(.*)$#m','wiki2html_listes',$chaine);
$chaine = preg_replace('#\n</li>#','</li>',$chaine);
$chaine = trim($chaine);
return $chaine;
}
//############################# fin interpréteur #############################
//############################################################################
//############################################################################
//############################################################################
$wiki = "
= Titre du document :: haut =
== Titre 1 ==
Paragraphe du chapitre 1 avec un mot en ''emphrase''. Bblabla blabal blabla blaabl bla. Blablate bl ba badeba la bla bblabla bl. Blabla bla bla bla bblabla ba.
=== Sous-titre 1 ===
Voici une arborescence de titres... Histoire de ne pas écrire pour rien, je vais illustrer la forte emphrase, voici donc '''un bout de texte en forte emphrase'''.
=== Sous-titre 2 ===
Bon ... Voilà quoi.
== Titre 2 ==
===! Sous-titre caché ===
{http://lesfilsdegaia.free.fr/galerie/Bertrand/mini/250.jpg :: Le tabac, c'est mal. :: <}
Voilà à quoi ressemblerra l'intégration d'une image dans un document. Blabla bla bla bla bblabla blabal blabla bla bla bla blabla blabl bla. Blablate bl ba badeba.
Il peut y avoir plusieurs paragraphes qui la contournent, bla bblabla blabal blabla blaabl bla. Blablate bl ba badeba la bla bblabla bl. Blabla bla bla bla bblabla ba.
=== Sous-titre ===
Tout comme il peut y avoir des titres, des listes, ou n'importe quel élément. Une fois la hauteur de l'image dépassée, le texte reprend toute la largeur possible.
Un petit hr pour la démo (mais très mal placé...) :
---------
// Commentaire invisible
/*
Commentaire
en block
invisible
*/
<!-- Commentaire visible (dans le code source) -->
== Titre 3 ==
=== Citation ===
[ http://openweb.eu.org/ :: Openweb Group, pour les Standards du Web. ] Openweb [/] :: [ http://openweb.eu.org/articles/xhtml_une_heure/ ] Apprendre l'Xhtml en une heure [/] \"\"\"
Il arrive que certains mots aient besoin d'être mis en évidence. On appelle cela l'emphase. Pour mettre un ou plusieurs mots en emphase, on utilise l'élément <code>em</code>. Généralement, cela aura pour effet de mettre le texte en question en italique. Sur un navigateur textuel comme Lynx, cela soulignera le mot.
Pour mettre un texte en forte emphase, on utilisera l'élément <code>strong</code>. Cela aura pour effet de mettre le texte en gras.
\"\"\"
=== Listes ===
Voici 2 listes comprenants des éléments numérotés ou non :
* élément1
* élément2
** sous-élément1
** sous-élément2
** sous-élément3
*** sous-sous-élément1 :: class:sousousul
*** sous-sous-élément2
** sous-élément4
**# sous-sous-élément numéroté1
**# sous-sous-élément numéroté2
**# sous-sous-élément numéroté3
* élément3
# élément numéroté1 :: ul2
# élément néméroté2
#* sous-élément5
#* sous-élément6
# élément néméroté3
## sous-élément numéroté1
## sous-élément numéroté2
==== Listes de définitions ====
(:
: Noria
Machine à élever l'eau, constituée principalement d'une roue ou d'une chaine sans fin à laquel est fixés des godets.
;;
: Dimère
Composé résultat de la combinaison (dimérisation) de deux molécules semblables.
N<sub>2</sub>O<sub>4</sub> est le dimère de NO<sub>2</sub>.
;;
:)
[ #haut ] Retour en début de document [/].
";
//##### RECUPERATION DU FORMULAIRE #####
if(isset($_POST['texte'])) {
$wiki = "\n".$_POST['texte'];
$wiki = stripslashes($wiki);
}
//######################################
$html = wiki2html($wiki);
$nblignes['wiki'] = nblignes($wiki);
$nblignes['html'] = nblignes($html);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
Analyseur syntaxique de WIKI
</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" xml:lang="fr" />
<style type="text/css">
/*<![CDATA[*/
/*Propiétés sur la page même*/
body {
background-color: #fbfcfb;
font-size: 1.3em;
text-align: justify;
}
.html, .html2, .wiki {
width: 95%;
background-color: white;
border: 1px #aaa solid;
}
.html {
height: <?echo $nblignes['html']+1?>em;
}
.wiki {
height: <?echo $nblignes['wiki']?>em;
}
/*Propiétés sur le code généré*/
.left {
float: left;
}
.right {
float: right;
}
.hidden {
display: none;
}
fieldset {
border: none;
padding: 0;
}
/*]]>*/
</style>
</head>
<body>
<?php
//##### FORMULAIRE DE MODIFICATION #####
?>
<h1>Syntaxe wiki : page de test et d'entrainement.</h1>
<h2>Syntaxe wiki : Modification</h2>
<form method="post" action="<?php echo($_SERVER['PHP_SELF']); ?>">
<fieldset>
<textarea name="texte" id="texte" class="wiki" rows="50" cols=""><?php echo(htmlentities($wiki)); ?></textarea>
<input type="submit" value="Tester" />
</fieldset>
</form>
<?php
//#####################################
//############ AFFICHAGE ##############
?>
<h2>Syntaxe html : Code</h2>
<form action="<?php echo($_SERVER['PHP_SELF']); ?>" method="post">
<fieldset>
<textarea class="html" rows="50" cols=""><?php echo(htmlentities($html)); ?></textarea>
</fieldset>
</form>
<h2>Syntaxe html : Rendu final</h2>
<div class="html2"><?php echo($html); ?><br /></div>
<?php
//#####################################
?>
</body>
</html>
J'ai essayé de commenter un maximum mon code, mais si vous ne comprennez pas quelque chose, n'hésitez pas à demander.Voilà, j'attends vos commentaires et suggestions.
Merci de votre attention.
ps : Il est installé à cette adresse : http://lesfilsdegaia.free.fr/hx5/wikitest.php
EDIT 29/04/05 : Amélioration de la page d'interprétation par Cyrano.
EDIT 05/09/05 : http://www.phpfrance.com/forums/voir_re ... .php#57698