From 9d843a61036d392b46fd496ad9007a17644c702f Mon Sep 17 00:00:00 2001 From: "Pierre Habouzit (MadCoder" Date: Thu, 27 Jan 2005 17:40:04 +0000 Subject: [PATCH] wiki2xhtml added git-archimport-id: opensource@polytechnique.org--2005/platal--mainline--0.9--patch-398 --- AUTHORS | 15 +- include/acronyms.txt | 46 ++ include/xorg.wiki2xhtml.php | 1085 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1143 insertions(+), 3 deletions(-) create mode 100644 include/acronyms.txt create mode 100644 include/xorg.wiki2xhtml.php diff --git a/AUTHORS b/AUTHORS index a7c5077..f36eabc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,12 +13,21 @@ Polytechnique.org TEAM : Vincent Palatin -XML-RPC stuff : + +XML-RPC stuff (public domain/GPL) : Dan Libby http://xmlrpc-epi.sourceforge.net/ Marc Boeren http://fr2.php.net/xml-rpc -Smarty Trimwhitespace prefilter : +Smarty Trimwhitespace prefilter (public domain) : Monte Ohrt http://smarty.incutio.com/?page=SmartyTips -Some of the icons : +Some of the icons (under LGPL) : David Vignoni http://www.icon-king.com/ + +Wiki2xhtml (under MPL) : + Olivier Meunier. http://www.neokraft.net/ + Stephanie Booth + Mathieu Pillard + Christophe Bonijol + Jean-Charles Bagneris + diff --git a/include/acronyms.txt b/include/acronyms.txt new file mode 100644 index 0000000..35b225d --- /dev/null +++ b/include/acronyms.txt @@ -0,0 +1,46 @@ +(X)HTML : (eXtensible) HyperText Markup Language +AFNOR : Association Française de NORmalisation +ANSI : American National Standard Institute +ASCII : American Standard Code for Information Interchange +ASP : Active Server Pages +CSS : Cascading Style Sheets +DHTML : Dynamic HyperText Markup Language +DOM : Document Object Model +DTD : Document Type Definition +ECMA : European Computer Manufacturer Association +FAI : Fournisseur d'Acces à Internet +FAQ : Foire Aux Questions +FTP : File Transfer Protocol +FIDEV : Formation et Insertion pour DEficients Visuels +HTML : HyperText Markup Language +HTTP : HyperText Transfer Protocol +IP : Internet Protocol +IRC : Internet Relay Chat +ISO : International Standard Organization +JS : JavaScript +MIME : Multipurpose Internet Mail Extension +P3P : Platform for Privacy Preferences Project +PC : Personnal Computer +PHP : PHP: Hypertext Preprocessor +PICS : Platform for Internet Content Selection +PNG : Portable Network Graphics +RDF : Resource Description Framework +RFC : Request For Comment +RSS : RDF Site Summary +SGML : Standard Generalized Markup Language +SMIL : Synchronized Multimedia Integration Language +SSII : Société de Service et d'Ingénierie Informatique +SVG : Scalable Vector Graphics +TAG : Technical Architecture Group +TCP : Transmission Control Protocol +URI : Universal Resource Identifier +URL : Uniform Resource Locator +URN : Universal Resource Name +W3C : World Wide Web Consortium +WAI : Web Accessibility Initiative +WYSIWYG : What You See Is What You Get +WWW : World Wide Web +XHTML : eXtensible HyperText Markup Language +XML : eXtensible Markup Language +XSL : eXtensible Stylesheet Language +XSLT : eXtensible Stylesheet Language Transformation diff --git a/include/xorg.wiki2xhtml.php b/include/xorg.wiki2xhtml.php new file mode 100644 index 0000000..b577ac2 --- /dev/null +++ b/include/xorg.wiki2xhtml.php @@ -0,0 +1,1085 @@ + Bug du Call-time pass-by-reference +# +# 3.1 +# Olivier +# => Ajout des macros «««..»»» +# => Ajout des blocs vides øøø +# => Ajout du niveau de titre paramétrable +# => Option de blocage du parseur dans les
+#			=> Titres au format setext (experimental, désactivé)
+#
+# 3.0
+# Olivier		=> Récriture du parseur inline, plus d'erreur XHTML
+#			=> Ajout d'une vérification d'intégrité pour les listes
+#			=> Les acronymes sont maintenant dans un fichier texte
+#			=> Ajout d'un tag images ((..)), del --..-- et ins ++..++
+#			=> Plus possible de faire des liens JS [lien|javascript:...]
+#			=> Ajout des notes de bas de page §§...§§
+#			=> Ajout des mots wiki
+#
+# 2.5
+# Olivier		=> Récriture du code, plus besoin du saut de ligne entre blocs !=
+#
+# 2.0
+# Stephanie	=> correction des PCRE et ajout de fonctionnalités
+# Mathieu 	=> ajout du strip-tags, implementation des options, reconnaissance automatique d'url, etc.
+# Olivier		=> chagement de active_link en active_urls
+#			=> ajout des options pour les blocs
+#			=> intégration de l'aide dans le code, avec les options
+#			=> début de quelque chose pour la reconnaissance auto d'url (avec Mat)
+
+# TODO :
+# Mathieu	=> active_wiki_urls (modifier wikiParseUrl ?)
+# 		=> active_auto_urls
+#
+# *		=> ajouter des options.
+# 		=> trouver un meilleur nom pour active_link ? (pour le jour ou ca sera tellement une usine
+#		   a gaz que on generera des tags  :)
+#
+
+# Wiki2xhtml
+
+class wiki2xhtml
+{
+	var $__version__ = '3.1a';
+	
+	var $T;
+	var $opt;
+	var $line;
+	var $foot_notes;
+	
+	var $tags;
+	var $open_tags;
+	var $close_tags;
+	var $all_tags;
+	var $tag_pattern;
+	var $escape_table;
+	var $allowed_inline = array();
+	
+	function wiki2xhtml()
+	{
+		# Mise en place des options
+		$this->setOpt('active_title',1);		# Activation des titres !!!
+		$this->setOpt('active_setext_title',0);	# Activation des titres setext (EXPERIMENTAL)
+		$this->setOpt('active_hr',1);			# Activation des 
+ $this->setOpt('active_lists',1); # Activation des listes + $this->setOpt('active_quote',1); # Activation du
+ $this->setOpt('active_pre',1); # Activation du
+		$this->setOpt('active_empty',0);		# Activation du bloc vide øøø
+		$this->setOpt('active_auto_urls',0);	# Activation de la reconnaissance d'url
+		$this->setOpt('active_urls',1);		# Activation des liens []
+		$this->setOpt('active_auto_img',1);	# Activation des images automatiques dans les liens []
+		$this->setOpt('active_img',1);		# Activation des images (())
+		$this->setOpt('active_anchor',1);		# Activation des ancres ~...~
+		$this->setOpt('active_em',1);			# Activation du  ''...''
+		$this->setOpt('active_strong',1);		# Activation du  __...__
+		$this->setOpt('active_br',1);			# Activation du 
%%% + $this->setOpt('active_q',1); # Activation du {{...}} + $this->setOpt('active_code',1); # Activation du @@...@@ + $this->setOpt('active_acronym',1); # Activation des acronymes + $this->setOpt('active_ins',1); # Activation des ins ++..++ + $this->setOpt('active_del',1); # Activation des del --..-- + $this->setOpt('active_footnotes',1); # Activation des notes de bas de page + $this->setOpt('active_wikiwords',0); # Activation des mots wiki + $this->setOpt('active_macros',0); # Activation des macros «««..»»» + + $this->setOpt('parse_pre',1); # Parser l'intérieur de blocs
 ?
+		
+		$this->setOpt('active_fix_word_entities',1); # Fixe les caractères MS
+		$this->setOpt('active_fr_syntax',1);	# Corrections syntaxe FR
+		
+		$this->setOpt('first_title_level',3);	# Premier niveau de titre 
+		
+		$this->setOpt('note_prefix','wiki-footnote');
+		$this->setOpt('note_str','

Notes

%s
'); + $this->setOpt('words_pattern','((?acro_table = $this->__getAcronyms(); + $this->foot_notes = array(); + } + + function setOpt($option, $value) + { + $this->opt[$option] = $value; + } + + function getOpt($option) + { + return (!empty($this->opt[$option])) ? $this->opt[$option] : false; + } + + function transform($in) + { + # Initialisation des tags + $this->__initTags(); + $this->foot_notes = array(); + + # Vérification du niveau de titre + if ($this->getOpt('first_title_level') > 4) { + $this->setOpt('first_title_level',4); + } + + $res = str_replace("\r", '', $in); + + $escape_pattern = array(); + + # traitement des titres à la setext + if ($this->getOpt('active_setext_title') && $this->getOpt('active_title')) { + $res = preg_replace('/^(.*)\n[=]{5,}$/m','!!!$1',$res); + $res = preg_replace('/^(.*)\n[-]{5,}$/m','!!$1',$res); + } + + # Transformation des mots Wiki + if ($this->getOpt('active_wikiwords') && $this->getOpt('words_pattern')) { + $res = preg_replace('/'.$this->getOpt('words_pattern').'/ms','¶¶¶$1¶¶¶',$res); + } + + $this->T = explode("\n",$res); + $this->T[] = ''; + + # Parse les blocs + $res = $this->__parseBlocks(); + + # Line break + if ($this->getOpt('active_br')) { + $res = preg_replace('/(?', $res); + $escape_pattern[] = '%%%'; + } + + # Correction des caractères faits par certains traitement + # de texte comme Word + if ($this->getOpt('active_fix_word_entities')) { + $wR = array( + '‚' => '‚', + 'ƒ' => 'ƒ', + '„' => '„', + '…' => '…', + '†' => '†', + '‡' => '‡', + 'ˆ' => 'ˆ', + '‰' => '‰', + 'Š' => 'Š', + '‹' => '‹', + 'Œ' => 'Œ', + '‘' => '‘', + '’' => '’', + '“' => '“', + '”' => '”', + '•' => '•', + '–' => '–', + '—' => '—', + '˜' => '˜', + '™' => '™', + 'š' => 'š', + '›' => '›', + 'œ' => 'œ', + 'Ÿ' => 'Ÿ', + '€' => '€'); + + $res = str_replace(array_keys($wR),array_values($wR),$res); + } + + # Nettoyage des \s en trop + $res = preg_replace('/([\s]+)(<\/p>|<\/li>|<\/pre>)/', '$2', $res); + $res = preg_replace('/(
  • )([\s]+)/', '$1', $res); + + # On vire les escapes + $res = preg_replace('/\\\('.implode('|',$escape_pattern).')/','$1',$res); + + # On vire les ¶¶¶MotWiki¶¶¶ qui sont resté (dans les url...) + if ($this->getOpt('active_wikiwords') && $this->getOpt('words_pattern')) { + $res = preg_replace('/¶¶¶'.$this->getOpt('words_pattern').'¶¶¶/msU','$1',$res); + } + + # On ajoute les notes + if (count($this->foot_notes) > 0) + { + $res_notes = ''; + $i = 1; + foreach ($this->foot_notes as $k => $v) { + $res_notes .= "\n".'

    ['.$i.'] '.$v.'

    '; + $i++; + } + $res .= sprintf("\n".$this->getOpt('note_str')."\n",$res_notes); + } + + return $res; + } + + /* PRIVATE + --------------------------------------------------- */ + + function __initTags() + { + $this->tags = array( + 'em' => array("''","''"), + 'strong' => array('__','__'), + 'acronym' => array('??','??'), + 'a' => array('[',']'), + 'img' => array('((','))'), + 'q' => array('{{','}}'), + 'code' => array('@@','@@'), + 'anchor' => array('~','~'), + 'del' => array('--','--'), + 'ins' => array('++','++'), + 'note' => array('$$','$$'), + 'word' => array('¶¶¶','¶¶¶'), + 'macro' => array('«««','»»»') + ); + + # Suppression des tags selon les options + if (!$this->getOpt('active_urls')) { + unset($this->tags['a']); + } + if (!$this->getOpt('active_img')) { + unset($this->tags['img']); + } + if (!$this->getOpt('active_anchor')) { + unset($this->tags['anchor']); + } + if (!$this->getOpt('active_em')) { + unset($this->tags['em']); + } + if (!$this->getOpt('active_strong')) { + unset($this->tags['strong']); + } + if (!$this->getOpt('active_q')) { + unset($this->tags['q']); + } + if (!$this->getOpt('active_code')) { + unset($this->tags['code']); + } + if (!$this->getOpt('active_acronym')) { + unset($this->tags['acronym']); + } + if (!$this->getOpt('active_ins')) { + unset($this->tags['ins']); + } + if (!$this->getOpt('active_del')) { + unset($this->tags['del']); + } + if (!$this->getOpt('active_footnotes')) { + unset($this->tags['note']); + } + if (!$this->getOpt('active_wikiwords')) { + unset($this->tags['word']); + } + if (!$this->getOpt('active_macros')) { + unset($this->tags['macro']); + } + + $this->open_tags = $this->__getTags(); + $this->close_tags = $this->__getTags(false); + $this->all_tags = $this->__getAllTags(); + $this->tag_pattern = $this->__getTagsPattern(); + + $this->escape_table = $this->all_tags; + array_walk($this->escape_table,create_function('&$a','$a = \'\\\\\'.$a;')); + } + + function __getTags($open=true) + { + $res = array(); + foreach ($this->tags as $k => $v) { + $res[$k] = ($open) ? $v[0] : $v[1]; + } + return $res; + } + + function __getAllTags() + { + $res = array(); + foreach ($this->tags as $v) { + $res[] = $v[0]; + $res[] = $v[1]; + } + return array_values(array_unique($res)); + } + + function __getTagsPattern($escape=false) + { + $res = $this->all_tags; + array_walk($res,create_function('&$a','$a = preg_quote($a,"/");')); + + if (!$escape) { + return '/(?T); + + for ($i=0; $i<$max; $i++) + { + $pre_mode = $mode; + $pre_type = $type; + $end = ($i+1 == $max); + + $line = $this->__getLine($i,$type,$mode); + + if ($type != 'pre' || $this->getOpt('parse_pre')) { + $line = $this->__inlineWalk($line); + } + + $res .= $this->__closeLine($type,$mode,$pre_type,$pre_mode); + $res .= $this->__openLine($type,$mode,$pre_type,$pre_mode); + + # P dans les blockquotes + if ($type == 'blockquote' && trim($line) == '' && $pre_type == $type) { + $res .= "

    \n

    "; + } + + # Correction de la syntaxe FR dans tous sauf pre et hr + # Sur idée de Christophe Bonijol + if ($this->getOpt('active_fr_syntax') && $type != NULL && $type != 'pre' && $type != 'hr') { + $line = preg_replace('/ ([:?!;](\s|$))/',' $1',$line); + } + + $res .= $line; + } + + return trim($res); + } + + function __getLine($i,&$type,&$mode) + { + $pre_type = $type; + $pre_mode = $mode; + $type = $mode = NULL; + + if (empty($this->T[$i])) { + return false; + } + + $line = htmlspecialchars($this->T[$i],ENT_NOQUOTES); + + # Ligne vide + if (empty($line)) + { + $type = NULL; + } + elseif ($this->getOpt('active_empty') && preg_match('/^øøø(.*)$/',$line,$cap)) + { + $type = NULL; + $line = trim($cap[1]); + } + # Titre + elseif ($this->getOpt('active_title') && preg_match('/^([!]{1,4})(.*)$/',$line,$cap)) + { + $type = 'title'; + $mode = strlen($cap[1]); + $line = trim($cap[2]); + } + # Ligne HR + elseif ($this->getOpt('active_hr') && preg_match('/^[-]{4}[- ]*$/',$line)) + { + $type = 'hr'; + $line = NULL; + } + # Blockquote + elseif ($this->getOpt('active_quote') && preg_match('/^(>|;:)(.*)$/',$line,$cap)) + { + $type = 'blockquote'; + $line = trim($cap[2]); + } + # Liste + elseif ($this->getOpt('active_lists') && preg_match('/^([*#]+)(.*)$/',$line,$cap)) + { + $type = 'list'; + $mode = $cap[1]; + $valid = true; + + # Vérification d'intégrité + $dl = ($type != $pre_type) ? 0 : strlen($pre_mode); + $d = strlen($mode); + $delta = $d-$dl; + + if ($delta < 0 && strpos($pre_mode,$mode) !== 0) { + $valid = false; + } + if ($delta > 0 && $type == $pre_type && strpos($mode,$pre_mode) !== 0) { + $valid = false; + } + if ($delta == 0 && $mode != $pre_mode) { + $valid = false; + } + if ($delta > 1) { + $valid = false; + } + + if (!$valid) { + $type = 'p'; + $mode = NULL; + $line = '
    '.$line; + } else { + $line = trim($cap[2]); + } + } + # Préformaté + elseif ($this->getOpt('active_pre') && preg_match('/^[ ]{1}(.*)$/',$line,$cap)) + { + $type = 'pre'; + $line = $cap[1]; + } + # Paragraphe + else { + $type = 'p'; + $line = trim($line); + } + + return $line; + } + + function __openLine($type,$mode,$pre_type,$pre_mode) + { + $open = ($type != $pre_type); + + if ($open && $type == 'p') + { + return "\n

    "; + } + elseif ($open && $type == 'blockquote') + { + return "\n

    "; + } + elseif (($open || $mode != $pre_mode) && $type == 'title') + { + $fl = $this->getOpt('first_title_level'); + $fl = $fl+3; + $l = $fl-$mode; + return "\n'; + } + elseif ($open && $type == 'pre') + { + return "\n

    ";
    +		}
    +		elseif ($open && $type == 'hr')
    +		{
    +			return "\n
    "; + } + elseif ($type == 'list') + { + $dl = ($open) ? 0 : strlen($pre_mode); + $d = strlen($mode); + $delta = $d-$dl; + $res = ''; + + if($delta > 0) { + if(substr($mode, -1, 1) == '*') { + $res .= "
      \n"; + } else { + $res .= "
        \n"; + } + } elseif ($delta < 0) { + $res .= "\n"; + for($j = 0; $j < abs($delta); $j++) { + if (substr($pre_mode,(0 - $j - 1), 1) == '*') { + $res .= "
    \n
  • \n"; + } else { + $res .= "\n\n"; + } + } + } else { + $res .= "\n"; + } + + return $res."
  • "; + } + else + { + return NULL; + } + } + + function __closeLine($type,$mode,$pre_type,$pre_mode) + { + $close = ($type != $pre_type); + + if ($close && $pre_type == 'p') + { + return "

    \n"; + } + elseif ($close && $pre_type == 'blockquote') + { + return "

  • \n"; + } + elseif (($close || $mode != $pre_mode) && $pre_type == 'title') + { + $fl = $this->getOpt('first_title_level'); + $fl = $fl+3; + $l = $fl-$pre_mode; + return '\n"; + } + elseif ($close && $pre_type == 'pre') + { + return "
    \n"; + } + elseif ($close && $pre_type == 'list') + { + $res = ''; + for($j = 0; $j < strlen($pre_mode); $j++) { + if(substr($pre_mode,(0 - $j - 1), 1) == '*') { + $res .= "\n"; + } else { + $res .= "\n"; + } + } + return $res; + } + else + { + return "\n"; + } + } + + + /* Inline + --------------------------------------------------- */ + function __inlineWalk($str,$allow_only=NULL) + { + $tree = preg_split($this->tag_pattern,$str,-1,PREG_SPLIT_DELIM_CAPTURE); + + $res = ''; + for ($i=0; $iopen_tags)) && + ($allow_only == NULL || in_array(array_search($tree[$i],$this->open_tags),$allow_only))) + { + $tag = array_search($tree[$i],$this->open_tags); + $tag_type = 'open'; + + if (($tidy = $this->__makeTag($tree,$tag,$i,$i,$attr,$tag_type)) !== false) + { + if ($tag != '') { + $res .= '<'.$tag.$attr; + $res .= ($tag_type == 'open') ? '>' : ' />'; + } + $res .= $tidy; + } + else + { + $res .= $tree[$i]; + } + } + else + { + $res .= $tree[$i]; + } + } + + # Suppression des echappements + $res = str_replace($this->escape_table,$this->all_tags,$res); + + return $res; + } + + function __makeTag(&$tree,&$tag,$position,&$j,&$attr,&$type) + { + $res = ''; + $closed = false; + + $itag = $this->close_tags[$tag]; + + # Recherche fermeture + for ($i=$position+1;$i__parseLink($res,$tag,$attr,$type); + break; + case 'img': + $type = 'close'; + $res = $this->__parseImg($res,$attr); + break; + case 'acronym': + $res = $this->__parseAcronym($res,$attr); + break; + case 'q': + $res = $this->__parseQ($res,$attr); + break; + case 'anchor': + $tag = 'a'; + $res = $this->__parseAnchor($res,$attr); + break; + case 'note': + $tag = ''; + $res = $this->__parseNote($res); + break; + case 'word': + $res = $this->parseWikiWord($res,$tag,$attr,$type); + break; + case 'macro': + $res = $this->parseMacro($res,$tag,$attr,$type); + break; + default : + $res = $this->__inlineWalk($res); + break; + } + + if ($type == 'open' && $tag != '') { + $res .= ''; + } + $j = $i; + break; + } + } + + return $res; + } + else + { + return false; + } + } + + function __parseLink($str,&$tag,&$attr,&$type) + { + $n_str = $this->__inlineWalk($str,array('acronym','img')); + $data = explode('|',$n_str); + $no_image = false; + + if (count($data) == 1) + { + $url = trim($str); + $content = $str; + $lang = ''; + $title = ''; + } + elseif (count($data) > 1) + { + $url = trim($data[1]); + $content = $data[0]; + $lang = (!empty($data[2])) ? $this->protectAttr($data[2],true) : ''; + $title = (!empty($data[3])) ? $data[3] : ''; + $no_image = (!empty($data[4])) ? (boolean) $data[4] : false; + } + + $array_url = $this->__specialUrls(); + $url = preg_replace(array_flip($array_url),$array_url,$url); + + # On vire les   dans l'url + $url = str_replace(' ',' ',$url); + + if (ereg('^(.+)[.](gif|jpg|jpeg|png)$', $url) && !$no_image && $this->getOpt('active_auto_img')) + { + # On ajoute les dimensions de l'image si locale + # Idée de Stephanie + $img_size = NULL; + if (!ereg('[a-zA-Z]+://', $url)) { + if (ereg('^/',$url)) { + $path_img = $_SERVER['DOCUMENT_ROOT'] . $url; + } else { + $path_img = $url; + } + + $img_size = @getimagesize($path_img); + } + + $attr = ' src="'.$this->protectAttr($this->protectUrls($url)).'"'. + $attr .= (count($data) > 1) ? ' alt="'.$this->protectAttr($content).'"' : ' alt=""'; + $attr .= ($lang) ? ' lang="'.$lang.'"' : ''; + $attr .= ($title) ? ' title="'.$this->protectAttr($title).'"' : ''; + $attr .= (is_array($img_size)) ? ' '.$img_size[3] : ''; + + $tag = 'img'; + $type = 'close'; + return NULL; + } + else + { + $attr = ' href="'.$this->protectAttr($this->protectUrls($url)).'"'; + $attr .= ($lang) ? ' hreflang="'.$lang.'"' : ''; + $attr .= ($title) ? ' title="'.$this->protectAttr($title).'"' : ''; + + return $content; + } + } + + function __specialUrls() + { + $res['#^google://(.*)$#'] = 'http://www.google.com/search?q=$1&start=0&start=0'; + $res['#^wikipedia://(.*)$#'] = 'http://en.wikipedia.org/wiki/$1'; + + return $res; + } + + function __parseImg($str,&$attr) + { + $data = explode('|',$str); + + $alt = ''; + $url = $data[0]; + if (!empty($data[1])) { + $alt = $data[1]; + } + + $attr = ' src="'.$this->protectAttr($this->protectUrls($url)).'"'; + $attr .= ' alt="'.$this->protectAttr($alt).'"'; + + if (!empty($data[2])) { + if ($data[2] == 'G' || $data[2] == 'L') { + $attr .= ' style="float:left; margin: 0 1em 1em 0;"'; + } elseif ($data[2] == 'D' || $data[2] == 'R') { + $attr .= ' style="float:right; margin: 0 0 1em 1em;"'; + } + } + + if (!empty($data[3])) { + $attr .= ' longdesc="'.$this->protectAttr($data[3]).'"'; + } + + return NULL; + } + + function __parseQ($str,&$attr) + { + $str = $this->__inlineWalk($str); + $data = explode('|',$str); + + $content = $data[0]; + $lang = (!empty($data[1])) ? $this->protectAttr($data[1],true) : ''; + + $attr .= (!empty($lang)) ? ' lang="'.$lang.'"' : ''; + $attr .= (!empty($data[2])) ? ' cite="'.$this->protectAttr($data[2]).'"' : ''; + + return $content; + } + + function __parseAnchor($str,&$attr) + { + $name = $this->protectAttr($str,true); + + if ($name != '') { + $attr = ' name="'.$name.'"'; + } + return null; + } + + function __parseNote($str) + { + $i = count($this->foot_notes)+1; + $id = $this->getOpt('note_prefix').'-'.$i; + $this->foot_notes[$id] = $this->__inlineWalk($str); + return '\['.$i.'\]'; + } + + # Obtenir un acronyme + function __parseAcronym($str,&$attr) + { + $data = explode('|',$str); + + $acronym = $data[0]; + $title = $lang = ''; + + if (count($data) > 1) + { + $title = $data[1]; + $lang = (!empty($data[2])) ? $this->protectAttr($data[2],true) : ''; + } + + if ($title == '' && !empty($this->acro_table[$acronym])) { + $title = $this->acro_table[$acronym]; + } + + $attr = ($title) ? ' title="'.$this->protectAttr($title).'"' : ''; + $attr .= ($lang) ? ' lang="'.$lang.'"' : ''; + + return $acronym; + } + + # Définition des acronymes, dans le fichier acronyms.txt + function __getAcronyms() + { + $file = dirname(__FILE__).'/acronyms.txt'; + $res = array(); + + if (file_exists($file)) + { + if (($fc = @file($file)) !== false) + { + foreach ($fc as $v) + { + $v = trim($v); + if ($v != '') + { + $p = strpos($v,':'); + $K = (string) trim(substr($v,0,$p)); + $V = (string) trim(substr($v,($p+1))); + + if ($K) { + $res[$K] = $V; + } + } + } + } + } + + return $res; + } + + # Mots wiki (pour héritage) + function parseWikiWord($str,&$tag,&$attr,&$type) + { + $tag = $attr = ''; + return $str; + } + + # Macros (pour héritage) + function parseMacro($str,&$tag,&$attr,&$type) + { + $tag = $attr = ''; + return $str; + } + + /* Protection des attributs */ + function protectAttr($str,$name=false) + { + if ($name && !preg_match('/^[A-Za-z][A-Za-z0-9_:.-]*$/',$str)) { + return ''; + } + + return str_replace(array("'",'"'),array(''','"'),$str); + } + + /* Protection des urls */ + function protectUrls($str) + { + if (preg_match('/^javascript:/',$str)) { + $str = '#'; + } + + return $str; + } + + /* Aide et debug + --------------------------------------------------- */ + function help() + { + $help['b'] = array(); + $help['i'] = array(); + + $help['b'][] = 'Laisser une ligne vide entre chaque bloc de même nature.'; + $help['b'][] = 'Paragraphe : du texte et une ligne vide'; + + if ($this->getOpt('active_title')) { + $help['b'][] = 'Titre : !!!, !!, '. + '! pour des titres plus ou moins importants'; + } + + if ($this->getOpt('active_hr')) { + $help['b'][] = 'Trait horizontal : ----'; + } + + if ($this->getOpt('active_lists')) { + $help['b'][] = 'Liste : ligne débutant par * ou '. + '#. Il est possible de mélanger les listes '. + '(*#*) pour faire des listes de plusieurs niveaux. '. + 'Respecter le style de chaque niveau'; + } + + if ($this->getOpt('active_pre')) { + $help['b'][] = 'Texte préformaté : espace devant chaque ligne de texte'; + } + + if ($this->getOpt('active_quote')) { + $help['b'][] = 'Bloc de citation : > ou '. + ';: devant chaque ligne de texte'; + } + + if ($this->getOpt('active_fr_syntax')) { + $help['i'][] = 'La correction de ponctuation est active. Un espace '. + 'insécable remplacera automatiquement tout espace '. + 'précédant les marque ";","?",":" et "!".'; + } + + if ($this->getOpt('active_em')) { + $help['i'][] = 'Emphase : deux apostrophes \'\'texte\'\''; + } + + if ($this->getOpt('active_strong')) { + $help['i'][] = 'Forte emphase : deux soulignés __texte__'; + } + + if ($this->getOpt('active_br')) { + $help['i'][] = 'Retour forcé à la ligne : %%%'; + } + + if ($this->getOpt('active_ins')) { + $help['i'][] = 'Insertion : deux plus ++texte++'; + } + + if ($this->getOpt('active_del')) { + $help['i'][] = 'Suppression : deux moins --texte--'; + } + + if ($this->getOpt('active_urls')) { + $help['i'][] = 'Lien : [url], [nom|url], '. + '[nom|url|langue] ou [nom|url|langue|titre].'; + + $help['i'][] = 'Image : comme un lien mais avec une extension d\'image.'. + '
    Pour désactiver la reconnaissance d\'image mettez 0 dans un dernier '. + 'argument. Par exemple [image|image.gif||0] fera un lien vers l\'image au '. + 'lieu de l\'afficher.'. + '
    Il est conseillé d\'utiliser la nouvelle syntaxe.'; + } + + if ($this->getOpt('active_img')) { + $help['i'][] = 'Image (nouvelle syntaxe) : '. + '((url|texte alternatif)), '. + '((url|texte alternatif|position)) ou '. + '((url|texte alternatif|position|description longue)). '. + '
    La position peut prendre les valeur L ou G (gauche) ou R ou D (droite).'; + } + + if ($this->getOpt('active_anchor')) { + $help['i'][] = 'Ancre : ~ancre~'; + } + + if ($this->getOpt('active_acronym')) { + $help['i'][] = 'Acronyme : ??acronyme?? ou '. + '??acronyme|titre??'; + } + + if ($this->getOpt('active_q')) { + $help['i'][] = 'Citation : {{citation}}, '. + '{{citation|langue}} ou {{citation|langue|url}}'; + } + + if ($this->getOpt('active_code')) { + $help['i'][] = 'Code : @@code ici@@'; + } + + if ($this->getOpt('active_footnotes')) { + $help['i'][] = 'Note de bas de page : $$Corps de la note$$'; + } + + $res = '
    '; + + $res .= '
    Blocs
    '; + if (count($help['b']) > 0) + { + $res .= '
    • '; + $res .= implode(' ;
    • ', $help['b']); + $res .= '.
    '; + } + $res .= '
    '; + + $res .= '
    Éléments en ligne
    '; + if (count($help['i']) > 0) + { + $res .= '
    • '; + $res .= implode(' ;
    • ', $help['i']); + $res .= '.
    '; + } + $res .= '
    '; + + $res .= '
    '; + + return $res; + } + + /* + function debug() + { + $mode = $type = NULL; + $max = count($this->T); + + $res = + ''. + ''; + + for ($i=0; $i<$max; $i++) + { + $pre_mode = $mode; + $pre_type = $type; + + $line = $this->__getLine($i,$type,$mode); + + $res .= + ''. + ''; + + } + $res .= '
    p-modep-typemodetypechaine
    '.$pre_mode.''.$pre_type.''.$mode.''.$type.''.$line.'
    '; + + return $res; + } + //*/ +} + +?> \ No newline at end of file -- 2.1.4