commit 3fdad57c33d0cb2f4ced0b933f50451b03908974 Author: ben.spip@gmail.com <> Date: Sat May 30 14:38:35 2009 +0000 _plugins_/_core_ vers _core_/plugins diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9587a51 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,38 @@ +* text=auto !eol +barre_outils/edition.php -text +barre_outils/forum.php -text +/barre_outils_icones.css.html -text +css/barre_outils.css -text +css/images/handle.png -text +css/images/menu.png -text +css/images/submenu.png -text +icones_barre/clean.png -text +icones_barre/eye.png -text +icones_barre/keyboard.png -text +icones_barre/text_bold.png -text +icones_barre/text_indent.png -text +icones_barre/text_indent_remove.png -text +icones_barre/text_italic.png -text +icones_barre/text_list_bullets.png -text +icones_barre/text_list_numbers.png -text +icones_barre/text_strikethrough.png -text +inc/barre.php -text +inc/barre_outils.php -text +javascript/jquery.markitup.js -text +javascript/jquery.markitup_pour_spip.js -text +javascript/jquery.previsu_spip.js -text +lang/barre_outils_ar.php -text +lang/barre_outils_en.php -text +lang/barre_outils_fr.php -text +markitup/readme.txt -text +markitup/templates/preview.css -text +markitup/templates/preview.html -text +/plugin.xml -text +/porte_plume.js.html -text +/porte_plume.js_fonctions.php -text +/porte_plume_options.php -text +/porte_plume_pipelines.php -text +/preview.html -text +tests/all_tests.php -text +tests/barre_outil_markitup.php -text +tests/lanceur_spip.php -text diff --git a/barre_outils/edition.php b/barre_outils/edition.php new file mode 100644 index 0000000..89c3c2e --- /dev/null +++ b/barre_outils/edition.php @@ -0,0 +1,408 @@ + 'edition', + #'previewAutoRefresh'=> true, + #'previewParserPath' => url_absolue(generer_url_public('preview')), + 'onShiftEnter' => array('keepDefault'=>false, 'replaceWith'=>"\n_ "), + 'onCtrlEnter' => array('keepDefault'=>false, 'replaceWith'=>"\n\n"), + // garder les listes si on appuie sur entree + 'onEnter' => array('keepDefault'=>false, 'selectionType'=>'return', 'replaceWith'=>"\n"), + 'onTab' => array('keepDefault'=>false, 'replaceWith'=>"\t"), + 'markupSet' => array( + // H1 - {{{ + array( + "id" => 'header1', + "name" => _T('barre_outils:barre_intertitre'), + "key" => "H", + "className" => "outil_header1", + "openWith" => "\n{{{", + "closeWith" => "}}}\n", + "display" => true, + "selectionType" => "line", + ), + // Bold - {{ + array( + "id" => 'bold', + "name" => _T('barre_outils:barre_gras'), + "key" => "B", + "className" => "outil_bold", + "openWith" => "{{", + "closeWith" => "}}", + "display" => true, + "selectionType" => "word", + ), + // Italic - { + array( + "id" => 'italic', + "name" => _T('barre_outils:barre_italic'), + "key" => "I", + "className" => "outil_italic", + "openWith" => "{", + "closeWith" => "}", + "display" => true, + "selectionType" => "word", + ), + + // montrer une suppression + array( + "id" => 'stroke_through', + "name" => _T('barre_outils:barre_barre'), // :-) + "className" => "outil_stroke_through", + "openWith" => "", + "closeWith" => "", + "display" => true, + "selectionType" => "word", + ), + + // listes -* + array( + "id" => 'liste_ul', + "name" => _T('barre_outils:barre_liste_ul'), + "className" => "outil_liste_ul", + "replaceWith" => "function(h){ return outil_liste(h, '*');}", + "display" => true, + "selectionType" => "line", + "forceMultiline" => true, + "dropMenu" => array( + // liste -# + array( + "id" => 'liste_ol', + "name" => _T('barre_outils:barre_liste_ol'), + "className" => "outil_liste_ol", + "replaceWith" => "function(h){ return outil_liste(h, '#');}", + "display" => true, + "selectionType" => "line", + "forceMultiline" => true, + ), + // indenter + array( + "id" => 'indenter', + "name" => _T('barre_outils:barre_indenter'), + "className" => "outil_indenter", + "replaceWith" => "function(h){return outil_indenter(h);}", + "display" => true, + "selectionType" => "line", + "forceMultiline" => true, + ), + // desindenter + array( + "id" => 'desindenter', + "name" => _T('barre_outils:barre_desindenter'), + "className" => "outil_desindenter", + "replaceWith" => "function(h){return outil_desindenter(h);}", + "display" => true, + "selectionType" => "line", + "forceMultiline" => true, + ), + ), + ), + + + + // separation + array( + "id" => "sepLink", // trouver un nom correct ! + "separator" => "---------------", + "display" => true, + ), + // lien spip + array( + "id" => 'link', + "name" => _T('barre_outils:barre_lien'), + "key" => "L", + "className" => "outil_link", + "openWith" => "[", + "closeWith" => "->[!["._T('barre_outils:barre_lien_input')."]!]]", + "display" => true, + ), + // note en bas de page spip + array( + "id" => 'notes', + "name" => _T('barre_outils:barre_note'), + "className" => "outil_notes", + "openWith" => "[[", + "closeWith" => "]]", + "display" => true, + "selectionType" => "word", + ), + + // separation + // (affichee dans forum) + array( + "id" => "sepCitations", // trouver un nom correct ! + "separator" => "---------------", + "display" => false, + ), + // quote spip + // (affichee dans forum) + array( + "id" => 'quote', + "name" => _T('barre_outils:barre_quote'), + "key" => "Q", + "className" => "outil_quote", + "openWith" => "\n", + "closeWith" => "\n", + "display" => false, + "selectionType" => "word", + ), + + // separation + array( + "id" => "sepGuillemets", + "separator" => "---------------", + "display" => true, + ), + // guillemets + array( + "id" => 'guillemets', + "name" => _T('barre_outils:barre_guillemets'), + "className" => "outil_guillemets", + "openWith" => "«", + "closeWith" => "»", + "display" => true, + "lang" => array('fr','eo','cpf','ar','es'), + "selectionType" => "word", + ), + // guillemets internes + array( + "id" => 'guillemets_simples', + "name" => _T('barre_outils:barre_guillemets_simples'), + "className" => "outil_guillemets_simples", + "openWith" => "“", + "closeWith" => "”", + "display" => true, + "lang" => array('fr','eo','cpf','ar','es'), + "selectionType" => "word", + ), + // guillemets de + array( + "id" => 'guillemets_de', + "name" => _T('barre_outils:barre_guillemets'), + "className" => "outil_guillemets_de", + "openWith" => "„", + "closeWith" => "“", + "display" => true, + "lang" => array('bg','de','pl','hr','src'), + "selectionType" => "word", + ), + // guillemets de, simples + array( + "id" => 'guillemets_de_simples', + "name" => _T('barre_outils:barre_guillemets_simples'), + "className" => "outil_guillemets_de_simples", + "openWith" => "‚", + "closeWith" => "‘", + "display" => true, + "lang" => array('bg','de','pl','hr','src'), + "selectionType" => "word", + ), + // guillemets autres langues + array( + "id" => 'guillemets_autres', + "name" => _T('barre_outils:barre_guillemets'), + "className" => "outil_guillemets_simples", + "openWith" => "“", + "closeWith" => "”", + "display" => true, + "lang_not" => array('fr','eo','cpf','ar','es','bg','de','pl','hr','src'), + "selectionType" => "word", + ), + // guillemets simples, autres langues + array( + "id" => 'guillemets_autres_simples', + "name" => _T('barre_outils:barre_guillemets_simples'), + "className" => "outil_guillemets_uniques", + "openWith" => "‘", + "closeWith" => "’", + "display" => true, + "lang_not" => array('fr','eo','cpf','ar','es','bg','de','pl','hr','src'), + "selectionType" => "word", + ), + + // separation + array( + "id" => "sepCaracteres", + "separator" => "---------------", + "display" => true, + ), + // icones clavier + array( + "id" => 'grpCaracteres', + "name" => _T('barre_outils:barre_inserer_caracteres'), + "className" => 'outil_caracteres', + "display" => true, + + "dropMenu" => array( + // A majuscule accent grave + array( + "id" => 'A_grave', + "name" => _T('barre_outils:barre_a_accent_grave'), + "className" => "outil_a_maj_grave", + "replaceWith" => "À", + "display" => true, + "lang" => array('fr','eo','cpf'), + ), + // E majuscule accent aigu + array( + "id" => 'E_aigu', + "name" => _T('barre_outils:barre_e_accent_aigu'), + "className" => "outil_e_maj_aigu", + "replaceWith" => "É", + "display" => true, + "lang" => array('fr','eo','cpf'), + ), + // oe + array( + "id" => 'oe', + "name" => _T('barre_outils:barre_eo'), + "className" => "outil_oe", + "replaceWith" => "œ", + "display" => true, + "lang" => array('fr'), + ), + // OE + array( + "id" => 'OE', + "name" => _T('barre_outils:barre_eo_maj'), + "className" => "outil_oe_maj", + "replaceWith" => "Œ", + "display" => true, + "lang" => array('fr'), + ), + ), + ), + + + // separation + array( + "id" => "sepPreview", // trouver un nom correct ! + "separator" => "---------------", + "display" => true, + ), + // clean + array( + "id" => 'clean', + "name" => _T('barre_outils:barre_clean'), + "className" => "outil_clean", + "replaceWith" => 'function(markitup) { return markitup.selection.replace(/<(.*?)>/g, "") }', + "display" => true, + ), + // preview + array( + "id" => 'preview', + "name" => _T('barre_outils:barre_preview'), + "className" => "outil_preview", + "call" => "preview", + "display" => true, + ), + + + ), + + 'functions' => " + // remplace ou cree -* ou -** ou -# ou -## + function outil_liste(h, c) { + if ((s = h.selection) && (r = s.match(/^-([*#]+) (.*)\$/))) { + r[1] = r[1].replace(/[#*]/g, c); + s = '-'+r[1]+' '+r[2]; + } else { + s = '-' + c + ' '+s; + } + return s; + } + + // indente des -* ou -# + function outil_indenter(h) { + if (s = h.selection) { + if (s.substr(0,2)=='-*') { + s = '-**' + s.substr(2); + } else if (s.substr(0,2)=='-#') { + s = '-##' + s.substr(2); + } else { + s = '-* ' + s; + } + } + return s; + } + + // desindente des -* ou -** ou -# ou -## + function outil_desindenter(h){ + if (s = h.selection) { + if (s.substr(0,3)=='-**') { + s = '-*' + s.substr(3); + } else if (s.substr(0,3)=='-* ') { + s = s.substr(3); + } else if (s.substr(0,3)=='-##') { + s = '-#' + s.substr(3); + } else if (s.substr(0,3)=='-# ') { + s = s.substr(3); + } + } + return s; + } + ", + )); + + $set->cacher(array( + 'stroke_through', + 'clean', 'preview', + )); + + return $set; +} + + + +/** + * Definitions des liens entre css et icones + */ +function barre_outils_edition_icones(){ + return array( + //'outil_header1' => 'text_heading_1.png', + 'outil_header1' => 'intertitre.png', + 'outil_bold' => 'text_bold.png', + 'outil_italic' => 'text_italic.png', + + 'outil_stroke_through' => 'text_strikethrough.png', + + 'outil_liste_ul' => 'text_list_bullets.png', + 'outil_liste_ol' => 'text_list_numbers.png', + 'outil_indenter' => 'text_indent.png', + 'outil_desindenter' => 'text_indent_remove.png', + + //'outil_quote' => 'text_indent.png', + 'outil_quote' => 'quote.png', + + //'outil_link' => 'world_link.png', + 'outil_link' => 'lien.png', + 'outil_notes' => 'notes.png', + + 'outil_guillemets' => 'guillemets.png', + 'outil_guillemets_simples' => 'guillemets-simples.png', + 'outil_guillemets_de' => 'guillemets-de.png', + 'outil_guillemets_de_simples' => 'guillemets-uniques-de.png', + 'outil_guillemets_uniques' => 'guillemets-uniques.png', + + 'outil_caracteres' => 'keyboard.png', + 'outil_a_maj_grave' => 'agrave-maj.png', + 'outil_e_maj_aigu' => 'eacute-maj.png', + 'outil_oe' => 'oelig.png', + 'outil_oe_maj' => 'oelig-maj.png', + + 'outil_clean' => 'clean.png', + 'outil_preview' => 'eye.png', + ); +} +?> diff --git a/barre_outils/forum.php b/barre_outils/forum.php new file mode 100644 index 0000000..4168dc0 --- /dev/null +++ b/barre_outils/forum.php @@ -0,0 +1,33 @@ +nameSpace = 'forum'; + $barre->cacherTout(); + $barre->afficher(array( + 'bold','italic', + 'sepLink','link', + 'sepCitations', 'quote', + 'sepCaracteres','guillemets', 'guillemets_simples', + 'guillemets_de', 'guillemets_de_simples', + 'guillemets_autres', 'guillemets_autres_simples', + 'A_grave', 'E_aigu', 'oe', 'OE', + )); + return $barre; +} + + +?> diff --git a/barre_outils_icones.css.html b/barre_outils_icones.css.html new file mode 100644 index 0000000..122a67c --- /dev/null +++ b/barre_outils_icones.css.html @@ -0,0 +1,7 @@ +#CACHE{7*24*3600} +#HTTP_HEADER{Content-Type: text/css; charset=utf-8} +#HTTP_HEADER{Vary: Accept-Encoding} +[(#VAL|barre_outils_css_icones)] + +/* roue ajax */ +.ajaxLoad{background:white url('[(#CHEMIN{images/searching.gif}|url_absolue)]') top left no-repeat;} diff --git a/css/barre_outils.css b/css/barre_outils.css new file mode 100644 index 0000000..a7aa1e0 --- /dev/null +++ b/css/barre_outils.css @@ -0,0 +1,141 @@ +.formulaire_spip textarea.markItUpEditor { +width:96%; /* reduire la taille par defaut des formulaires spip */ +} + + +/* ------------------------------------------------------------------- +// markItUp! Universal MarkUp Engine, JQuery plugin +// By Jay Salvat - http://markitup.jaysalvat.com/ +// ------------------------------------------------------------------*/ + +.markItUp .markItUpHeader a, +.markItUp .markItUpTabs a, +.markItUp .markItUpFooter a { + color:#000; + text-decoration:none; +} +.markItUp { + margin:5px 0 5px 0; + clear:both; +} +.markItUp .markItUpContainer { + margin:0px; padding:0px; +} +.markItUp .markItUpEditor { + padding:5px; + height:320px; /* la hauteur est calculee par SPIP */ + clear:both; display:block; + overflow:auto; +} +.markItUp .markItUpPreviewFrame {} +.markItUp .markItUpFooter { + margin:0px; padding:0px; + width:100%; +} +.markItUp .markItUpResizeHandle { + overflow:hidden; + width:22px; height:5px; + margin-left:auto; + margin-right:auto; + background-image:url(images/handle.png); + cursor:ns-resize; +} + +/***************************/ +/* tabs */ +.markItUp .markItUpTabs { + text-align:right; margin-bottom:3px; padding:1px 1px 0; + border-bottom:1px solid #888; overflow:hidden; + width:auto; float:right; clear:both;} +.markItUp .markItUpTabs a { + display:block; float:right; border:1px solid #888; margin:0px 1px; border-bottom:none; + padding:3px 4px 2px 4px; background:#f0f0f0; + -moz-border-radius:5px 5px 0 0;-webkit-border-top-left-radius:5px;-webkit-border-top-right-radius:5px;} +.markItUp .markItUpTabs a.on {background:#fff; } +.markItUp .markItUpTabs a:hover {background:#fff;} + +/***************************/ +/* previsu */ +.markItUp .markItUpPreview { + clear:both; + border:1px solid #888; + background:#fff; + overflow:auto; + padding:1em; +} + +/* correction des styles spip_formulaires appliques par defaut (grr) */ +.markItUp .preview p {margin-bottom:1em;} +.markItUp .preview ul {margin-bottom:1em; margin-top:0.5em;} +.markItUp .preview li {border:none; padding:1px;} +/* coloration code */ +.markItUp .preview .cadre ol, +.markItUp .preview .cadre ul {padding:0.5em;} + + +/***************************************************************************************/ +/* first row of buttons */ +.markItUp .markItUpHeader { margin:0px; padding:0px;} +.markItUp .markItUpHeader ul li { + list-style:none; + float:left; + position:relative; + clear:none; + border:0; + margin:0; + padding:0; + overflow:visible; +} +.markItUp .markItUpHeader ul li:first-child { /* annuler un reglage des forms prive */ + padding-top:0; +} + +.markItUp .markItUpHeader ul .markItUpDropMenu { + /*background:inherit url(images/menu.png) no-repeat 100% 80%; + padding-right:10px;*/ +} +.markItUp .markItUpHeader ul .markItUpDropMenu li { + margin-right:0px; + background-color: #eee; + padding:2px 1px 2px 0; +} +.markItUp .markItUpHeader ul .markItUpDropMenu li:first-child{padding-left:2px;} + +/* next rows of buttons */ +.markItUp .markItUpHeader ul ul { + display:none; + position:absolute; + top:24px; left:-2px; + width:150px; +} +.markItUp .markItUpHeader ul ul li { + float:left; +} +.markItUp .markItUpHeader ul ul .markItUpDropMenu { + background:#F5F5F5 url(images/submenu.png) no-repeat 50% 50%; +} +.markItUp .markItUpHeader ul .markItUpSeparator { + margin:0 6px; + width:0px; + height:16px; + overflow:hidden; +} +.markItUp .markItUpHeader ul ul .markItUpSeparator { + width:auto; height:1px; + margin:0px; +} + +.markItUp .markItUpHeader ul a { + display:block; + width:16px; height:16px; + text-indent:-10000px; + background-repeat:no-repeat; + background-position:50% 50%; + background-color:#f5f5f5; + border:1px solid #ccc; + padding:3px; + margin-right:1px; +} +.markItUp .markItUpHeader ul a:hover{border:1px solid #888; background-color:#fff;} + + diff --git a/css/images/handle.png b/css/images/handle.png new file mode 100644 index 0000000..3993b20 Binary files /dev/null and b/css/images/handle.png differ diff --git a/css/images/menu.png b/css/images/menu.png new file mode 100644 index 0000000..44a07af Binary files /dev/null and b/css/images/menu.png differ diff --git a/css/images/submenu.png b/css/images/submenu.png new file mode 100644 index 0000000..03d1977 Binary files /dev/null and b/css/images/submenu.png differ diff --git a/icones_barre/clean.png b/icones_barre/clean.png new file mode 100644 index 0000000..7e7cefb Binary files /dev/null and b/icones_barre/clean.png differ diff --git a/icones_barre/eye.png b/icones_barre/eye.png new file mode 100644 index 0000000..564a1a9 Binary files /dev/null and b/icones_barre/eye.png differ diff --git a/icones_barre/keyboard.png b/icones_barre/keyboard.png new file mode 100644 index 0000000..898d402 Binary files /dev/null and b/icones_barre/keyboard.png differ diff --git a/icones_barre/text_bold.png b/icones_barre/text_bold.png new file mode 100644 index 0000000..889ae80 Binary files /dev/null and b/icones_barre/text_bold.png differ diff --git a/icones_barre/text_indent.png b/icones_barre/text_indent.png new file mode 100644 index 0000000..9364532 Binary files /dev/null and b/icones_barre/text_indent.png differ diff --git a/icones_barre/text_indent_remove.png b/icones_barre/text_indent_remove.png new file mode 100644 index 0000000..1651b07 Binary files /dev/null and b/icones_barre/text_indent_remove.png differ diff --git a/icones_barre/text_italic.png b/icones_barre/text_italic.png new file mode 100644 index 0000000..8482ac8 Binary files /dev/null and b/icones_barre/text_italic.png differ diff --git a/icones_barre/text_list_bullets.png b/icones_barre/text_list_bullets.png new file mode 100644 index 0000000..4a8672b Binary files /dev/null and b/icones_barre/text_list_bullets.png differ diff --git a/icones_barre/text_list_numbers.png b/icones_barre/text_list_numbers.png new file mode 100644 index 0000000..33b0b8d Binary files /dev/null and b/icones_barre/text_list_numbers.png differ diff --git a/icones_barre/text_strikethrough.png b/icones_barre/text_strikethrough.png new file mode 100644 index 0000000..612058a Binary files /dev/null and b/icones_barre/text_strikethrough.png differ diff --git a/inc/barre.php b/inc/barre.php new file mode 100644 index 0000000..c1b9252 --- /dev/null +++ b/inc/barre.php @@ -0,0 +1,42 @@ +" + . entites_html($texte) + . "\n"; +} + +?> diff --git a/inc/barre_outils.php b/inc/barre_outils.php new file mode 100644 index 0000000..fa43bf5 --- /dev/null +++ b/inc/barre_outils.php @@ -0,0 +1,546 @@ +valeur + */ + function Barre_outils($params=array()){ + foreach ($params as $p=>$v) { + if (isset($this->$p)) { + // si tableau, on verifie les entrees + if (is_array($v)) { + $v = $this->verif_params($p,$v); + } + $this->$p = $v; + } + } + } + + /** + * Verifie que les parametres transmis existent + * et retourne un tableau des parametres valides + * + * @param string $nom : cle du parametre (eventuel) + * @param array $params : parametres du parametre (param->valeur) + */ + function verif_params($nom, $params=array()) { + // si markupset, on boucle sur les items + if (stripos($nom, 'markupSet')!==false) { + foreach ($params as $i=>$v) { + $params[$i] = $this->verif_params($i, $v); + } + } + // sinon on teste la validite + else { + foreach ($params as $p=>$v) { + if (!in_array($p, $this->_liste_params_autorises)) { + unset($params[$p]); + } + } + } + return $params; + } + + /** + * Permet d'affecter des parametres a un element de la barre + * La fonction retourne les parametres, de sorte qu'on peut s'en servir pour simplement recuperer ceux-ci. + * + * Il est possible d'affecter des parametres avant/apres l'element trouve + * en definisant une valeur differente pour le $lieu : 'dedans','avant','apres' + * par defaut 'dedans' (modifie l'element trouve). + * + * Lorsqu'on demande d'inserer avant ou apres, la fonction retourne les parametres inseres + * + * @param string $identifiant : identifiant du bouton a afficher + * @param array $params : parametres a affecter a la trouvaille + * @param string $lieu : lieu d'affectation des parametres (dedans, avant, apres) + * @param false/array $tableau : tableau ou chercher les elements (sert pour la recursion) + */ + function affecter(&$tableau, $identifiant, $params=array(), $lieu='dedans'){ + static $cle_de_recherche = 'id'; // ou className ? + + if ($tableau === null) + $tableau = &$this->markupSet; + + if (!in_array($lieu, array('dedans','avant','apres'))) + $lieu = 'dedans'; + + // present en premiere ligne ? + $trouve = false; + foreach ($tableau as $i=>$v){ + if (isset($v[$cle_de_recherche]) and ($v[$cle_de_recherche] == $identifiant)) { + $trouve = $i; + break; + } + } + // si trouve, affectations + if (($trouve !== false)) { + if ($params) { + $params = $this->verif_params($identifiant, $params); + // dedans on merge + if ($lieu == 'dedans') { + return $tableau[$trouve] = array_merge($tableau[$trouve], $params); + } + // avant ou apres, on insere + elseif ($lieu == 'avant') { + array_splice($tableau, $trouve, 0, array($params)); + return $params; + } + elseif ($lieu == 'apres') { + array_splice($tableau, $trouve+1, 0, array($params)); + return $params; + } + } + return $tableau[$trouve]; + } + + // recursivons sinon ! + foreach ($tableau as $i=>$v){ + if (is_array($v)) { + foreach ($v as $m=>$n) { + if (is_array($n) AND ($r = $this->affecter($tableau[$i][$m], $identifiant, $params, $lieu))) + return $r; + } + } + } + return false; + } + + + /** + * Permet d'affecter des parametres toutes les elements de la barre + * + * @param array $params : parametres a affecter a la trouvaille + * @param array $ids : tableau identifiants particuliers a qui on affecte les parametres + * si vide, tous les identifiants seront modifies + * @param false/array $tableau : tableau ou chercher les elements (sert pour la recursion) + */ + function affecter_a_tous(&$tableau, $params=array(), $ids=array()){ + if (!$params) + return false; + + if ($tableau === null) + $tableau = &$this->markupSet; + + $params = $this->verif_params('divers', $params); + + // merge de premiere ligne + foreach ($tableau as $i=>$v){ + if (!$ids OR in_array($v['id'], $ids)) { + $tableau[$i] = array_merge($tableau[$i], $params); + } + // recursion si sous-menu + if (isset($tableau[$i]['dropMenu'])) { + $this->affecter_a_tous($tableau[$i]['dropMenu'], $params, $ids); + } + } + return true; + } + + + /** + * Affecte les valeurs des parametres indiques au bouton demande + * et retourne l'ensemble des parametres du bouton (sinon false) + * + * @param string/array $identifiant : id du ou des boutons a afficher + * @param array $params : param->valeur + * @return mixed + */ + function set($identifiant, $params=array()) { + // prudence tout de meme a pas tout modifier involontairement (si array) + if (!$identifiant) return false; + + if (is_string($identifiant)) { + return $this->affecter($this->markupSet, $identifiant, $params); + } + elseif (is_array($identifiant)) { + return $this->affecter_a_tous($this->markupSet, $params, $identifiant); + } + return false; + } + + /** + * Retourne les parametres du bouton demande + * + * @param string $identifiant : nom (de la classe du) bouton + * @return mixed + */ + function get($identifiant) { + if ($a = $this->affecter($this->markupSet, $identifiant)) { + return $a; + } + return false; + } + + + /** + * Affiche le bouton demande + * + * @param string $identifiant : nom (de la classe du) bouton a afficher + * @return true/false + */ + function afficher($identifiant){ + return $this->set($identifiant,array('display'=>true)); + } + + + /** + * Cache le bouton demande + * + * @param string $identifiant : nom (de la classe du) bouton a afficher + * @return true/false + */ + function cacher($identifiant){ + return $this->set($identifiant,array('display'=>false)); + } + + + /** + * Affiche tous les boutons + * + * @param string $identifiant : nom (de la classe du) bouton a afficher + * @return true/false + */ + function afficherTout(){ + return $this->affecter_a_tous($this->markupSet, array('display'=>true)); + } + + /** + * Cache tous les boutons + * + * @param string $identifiant : nom (de la classe du) bouton a afficher + * @return true/false + */ + function cacherTout(){ + return $this->affecter_a_tous($this->markupSet, array('display'=>false)); + } + + + /** + * ajouter un bouton ou quelque chose, avant un autre deja present + * + * @param string $identifiant : identifiant du bouton ou l'on doit se situer + * @param array $params : parametres de l'ajout + */ + function ajouterAvant($identifiant, $params){ + return $this->affecter($this->markupSet, $identifiant, $params, 'avant'); + } + + /** + * ajouter un bouton ou quelque chose, apres un autre deja present + * + * @param string $identifiant : identifiant du bouton ou l'on doit se situer + * @param array $params : parametres de l'ajout + */ + function ajouterApres($identifiant, $params){ + return $this->affecter($this->markupSet, $identifiant, $params, 'apres'); + + } + + /** + * ajouter une fonction js pour etre utilises dans les boutons + * + * @param string $fonction : code de la fonction js + * @return null + */ + function ajouterFonction($fonction){ + if (false === strpos($this->functions, $fonction)){ + $this->functions .= "\n" . $fonction . "\n"; + } + } + + /** + * Supprimer les elements non affiches (display:false) + * + * @param false/array $tableau : tableau a analyser (sert pour la recursion) + */ + function enlever_elements_non_affiches(&$tableau){ + if ($tableau === null) + $tableau = &$this->markupSet; + + foreach ($tableau as $p=>$v){ + + if (isset($v['display']) AND !$v['display']) { + unset($tableau[$p]); + $tableau = array_values($tableau); // remettre les cles automatiques sinon json les affiche et ça plante. + } + // sinon, on lance une recursion sur les sous-menus + else { + if (isset($v['dropMenu']) and is_array($v['dropMenu'])) { + $this->enlever_elements_non_affiches($tableau[$p]['dropMenu']); + // si le sous-menu est vide, on enleve l'icone + if (!$tableau[$p]['dropMenu']) { + unset($tableau[$p]); + $tableau = array_values($tableau); + } + } + } + } + } + + /** + * Supprime les elements vides (uniquement a la racine de l'objet) + * et uniquement si chaine ou tableau. + * + * Supprime les parametres prives + * Supprime les parametres inutiles a markitup/json dans les parametres markupSet + * (id, display, icone) + */ + function enlever_parametres_inutiles() { + foreach($this as $p=>$v){ + if (!$v) { + if (is_array($v) or is_string($v)) { + unset($this->$p); + } + } elseif ($p == 'functions') { + unset($this->$p); + } + } + foreach($this->markupSet as $p=>$v) { + foreach ($v as $n=>$m) { + if (in_array($n, array('id', 'display', 'icon'))) { + unset($this->markupSet[$p][$n]); + } + } + } + unset ($this->_liste_params_autorises); + } + + + /** + * Cree la sortie json pour le javascript des parametres de la barre + * et la retourne + * + * @return string : declaration json de la barre + */ + function creer_json(){ + $barre = $this; + $type = $barre->nameSpace; + $fonctions = $barre->functions; + + $barre->enlever_elements_non_affiches($this->markupSet); + $barre->enlever_parametres_inutiles(); + + $json = Barre_outils::json_export($barre); + + // on lance la transformation des &chose; en veritables caracteres + // sinon markitup restitue « au lieu de « directement + // lorsqu'on clique sur l'icone + include_spip('inc/charsets'); + $json = unicode2charset(html2unicode($json)); + return "\n\nbarre_outils_$type = ".$json . "\n\n $fonctions"; + } + + /** + * Transform a variable into its javascript equivalent (recursive) + * (depuis ecrire/inc/json, mais modifie pour que les fonctions + * js ne soient pas mises dans un string + * + * @access private + * @param mixed the variable + * @return string js script | boolean false if error + */ + function json_export($var) { + $asso = false; + switch (true) { + case is_null($var) : + return 'null'; + case is_string($var) : + if (strtolower(substr(ltrim($var),0,8))=='function') + return $var; + return '"' . addcslashes($var, "\"\\\n\r") . '"'; + case is_bool($var) : + return $var ? 'true' : 'false'; + case is_scalar($var) : + return $var; + case is_object( $var) : + $var = get_object_vars($var); + $asso = true; + case is_array($var) : + $keys = array_keys($var); + $ikey = count($keys); + while (!$asso && $ikey--) { + $asso = $ikey !== $keys[$ikey]; + } + $sep = ''; + if ($asso) { + $ret = '{'; + foreach ($var as $key => $elt) { + $ret .= $sep . '"' . $key . '":' . Barre_outils::json_export($elt); + $sep = ','; + } + return $ret ."}\n"; + } else { + $ret = '['; + foreach ($var as $elt) { + $ret .= $sep . Barre_outils::json_export($elt); + $sep = ','; + } + return $ret ."]\n"; + } + } + return false; + } + +} + + + +/** + * Cette fonction cree la css pour les images + * des icones des barres d'outils + * en s'appuyant sur la description des jeux de barres disponibles. + * + * elle cherche une fonction barre_outils_($barre)_icones pour chaque + * barre et l'appelle si existe. + * + * @return string : declaration css des icones + */ +function barre_outils_css_icones(){ + // recuperer la liste, extraire les icones + $css = ""; + + // liste des barres + if (!$barres = barre_outils_liste()) + return null; + + // liste des classes css et leur correspondance avec une icone + $classe2icone = array(); + foreach ($barres as $barre) { + include_spip('barre_outils/' . $barre); + if ($f = charger_fonction($barre . '_icones', 'barre_outils', true)) { + if (is_array($icones = $f())) { + $classe2icone = array_merge($classe2icone, $icones); + } + } + } + + // passer le tout dans un pipeline pour ceux qui ajoute de simples icones a des barres existantes + $classe2icone = pipeline('porte_plume_lien_classe_vers_icone',$classe2icone); + + // passage en css + foreach ($classe2icone as $n=>$i) { + $css .= "\n.markItUp .$n a {\n\tbackground-image:url(".url_absolue(find_in_path("icones_barre/$i")).");\n}"; + } + + return $css; +} + + +/** + * Retourne une instance de Barre_outils + * cree a partir du type de barre demande + * + * @param string $set : type de barre + * @return object/false : objet de type barre_outil + */ +function barre_outils_initialiser($set){ + if ($f = charger_fonction($set, 'barre_outils')) { + // retourne une instance de l'objet Barre_outils + return $f(); + } + return false; +} + +/** + * Retourne la liste des barres d'outils connues + * + * @return array/false : tableau des noms de barres trouvees + */ +function barre_outils_liste(){ + static $sets = -1; + if ($sets !== -1) + return $sets; + + // on recupere l'ensemble des barres d'outils connues + if (!$sets = find_all_in_path('barre_outils/','.*[.]php') + or !is_array($sets)) { + $sets = false; + return $sets; + } + + foreach($sets as $fichier=>$adresse) { + $sets[$fichier] = substr($fichier,0,-4); // juste le nom + } + return $sets; +} + +?> diff --git a/javascript/jquery.markitup.js b/javascript/jquery.markitup.js new file mode 100644 index 0000000..1bdf319 --- /dev/null +++ b/javascript/jquery.markitup.js @@ -0,0 +1,553 @@ +// ---------------------------------------------------------------------------- +// markItUp! Universal MarkUp Engine, JQuery plugin +// v 1.1.5 +// Dual licensed under the MIT and GPL licenses. +// ---------------------------------------------------------------------------- +// Copyright (C) 2007-2008 Jay Salvat +// http://markitup.jaysalvat.com/ +// ---------------------------------------------------------------------------- +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ---------------------------------------------------------------------------- +(function($) { + $.fn.markItUp = function(settings, extraSettings) { + var options, ctrlKey, shiftKey, altKey; + ctrlKey = shiftKey = altKey = false; + + options = { id: '', + nameSpace: '', + root: '', + previewInWindow: '', // 'width=800, height=600, resizable=yes, scrollbars=yes' + previewAutoRefresh: true, + previewPosition: 'after', + previewTemplatePath: '~/templates/preview.html', + previewParserPath: '', + previewParserVar: 'data', + resizeHandle: true, + beforeInsert: '', + afterInsert: '', + onEnter: {}, + onShiftEnter: {}, + onCtrlEnter: {}, + onTab: {}, + markupSet: [ { /* set */ } ] + }; + $.extend(options, settings, extraSettings); + + // compute markItUp! path + if (!options.root) { + $('script').each(function(a, tag) { + miuScript = $(tag).get(0).src.match(/(.*)jquery\.markitup(\.pack)?\.js$/); + if (miuScript !== null) { + options.root = miuScript[1]; + } + }); + } + + return this.each(function() { + var $$, textarea, levels, scrollPosition, caretPosition, caretOffset, + clicked, hash, header, footer, previewWindow, template, iFrame, abort; + $$ = $(this); + textarea = this; + levels = []; + abort = false; + scrollPosition = caretPosition = 0; + caretOffset = -1; + + options.previewParserPath = localize(options.previewParserPath); + options.previewTemplatePath = localize(options.previewTemplatePath); + + // apply the computed path to ~/ + function localize(data, inText) { + if (inText) { + return data.replace(/("|')~\//g, "$1"+options.root); + } + return data.replace(/^~\//, options.root); + } + + // init and build editor + function init() { + id = ''; nameSpace = ''; + if (options.id) { + id = 'id="'+options.id+'"'; + } else if ($$.attr("id")) { + id = 'id="markItUp'+($$.attr("id").substr(0, 1).toUpperCase())+($$.attr("id").substr(1))+'"'; + + } + if (options.nameSpace) { + nameSpace = 'class="'+options.nameSpace+'"'; + } + $$.wrap('
'); + $$.wrap('
'); + $$.wrap('
'); + $$.addClass("markItUpEditor"); + + // add the header before the textarea + header = $('
').insertBefore($$); + $(dropMenus(options.markupSet)).appendTo(header); + + // add the footer after the textarea + footer = $('
').insertAfter($$); + + // add the resize handle after textarea + if (options.resizeHandle === true && $.browser.safari !== true) { + resizeHandle = $('
') + .insertAfter($$) + .bind("mousedown", function(e) { + var h = $$.height(), y = e.clientY, mouseMove, mouseUp; + mouseMove = function(e) { + $$.css("height", Math.max(20, e.clientY+h-y)+"px"); + return false; + }; + mouseUp = function(e) { + $("html").unbind("mousemove", mouseMove).unbind("mouseup", mouseUp); + return false; + }; + $("html").bind("mousemove", mouseMove).bind("mouseup", mouseUp); + }); + footer.append(resizeHandle); + } + + // listen key events + $$.keydown(keyPressed).keyup(keyPressed); + + // bind an event to catch external calls + $$.bind("insertion", function(e, settings) { + if (settings.target !== false) { + get(); + } + if (textarea === $.markItUp.focused) { + markup(settings); + } + }); + + // remember the last focus + $$.focus(function() { + $.markItUp.focused = this; + }); + } + + // recursively build header with dropMenus from markupset + function dropMenus(markupSet) { + var ul = $(''), i = 0; + $('li:hover > ul', ul).css('display', 'block'); + $.each(markupSet, function() { + var button = this, t = '', title, li, j; + title = (button.key) ? (button.name||'')+' [Ctrl+'+button.key+']' : (button.name||''); + key = (button.key) ? 'accesskey="'+button.key+'"' : ''; + if (button.separator) { + li = $('
  • '+(button.separator||'')+'
  • ').appendTo(ul); + } else { + i++; + for (j = levels.length -1; j >= 0; j--) { + t += levels[j]+"-"; + } + li = $('
  • '+(button.name||'')+'
  • ') + .bind("contextmenu", function() { // prevent contextmenu on mac and allow ctrl+click + return false; + }).click(function() { + return false; + }).mouseup(function() { + if (button.call) { + eval(button.call)(); + } + markup(button); + return false; + }).hover(function() { + $('> ul', this).show(); + $(document).one('click', function() { // close dropmenu if click outside + $('ul ul', header).hide(); + } + ); + }, function() { + $('> ul', this).hide(); + } + ).appendTo(ul); + if (button.dropMenu) { + levels.push(i); + $(li).addClass('markItUpDropMenu').append(dropMenus(button.dropMenu)); + } + } + }); + levels.pop(); + return ul; + } + + // markItUp! markups + function magicMarkups(string) { + if (string) { + string = string.toString(); + string = string.replace(/\(\!\(([\s\S]*?)\)\!\)/g, + function(x, a) { + var b = a.split('|!|'); + if (altKey === true) { + return (b[1] !== undefined) ? b[1] : b[0]; + } else { + return (b[1] === undefined) ? "" : b[0]; + } + } + ); + // [![prompt]!], [![prompt:!:value]!] + string = string.replace(/\[\!\[([\s\S]*?)\]\!\]/g, + function(x, a) { + var b = a.split(':!:'); + if (abort === true) { + return false; + } + value = prompt(b[0], (b[1]) ? b[1] : ''); + if (value === null) { + abort = true; + } + return value; + } + ); + return string; + } + return ""; + } + + // prepare action + function prepare(action) { + if ($.isFunction(action)) { + action = action(hash); + } + return magicMarkups(action); + } + + // build block to insert + function build(string) { + openWith = prepare(clicked.openWith); + placeHolder = prepare(clicked.placeHolder); + replaceWith = prepare(clicked.replaceWith); + closeWith = prepare(clicked.closeWith); + if (replaceWith !== "") { + block = openWith + replaceWith + closeWith; + } else if (selection === '' && placeHolder !== '') { + block = openWith + placeHolder + closeWith; + } else { + block = openWith + (string||selection) + closeWith; + } + return { block:block, + openWith:openWith, + replaceWith:replaceWith, + placeHolder:placeHolder, + closeWith:closeWith + }; + } + + // define markup to insert + function markup(button) { + var len, j, n, i; + hash = clicked = button; + get(); + + $.extend(hash, { line:"", + root:options.root, + textarea:textarea, + selection:(selection||''), + caretPosition:caretPosition, + ctrlKey:ctrlKey, + shiftKey:shiftKey, + altKey:altKey + } + ); + // callbacks before insertion + prepare(options.beforeInsert); + prepare(clicked.beforeInsert); + if (ctrlKey === true && shiftKey === true) { + prepare(clicked.beforeMultiInsert); + } + $.extend(hash, { line:1 }); + + if (ctrlKey === true && shiftKey === true) { + lines = selection.split(/\r?\n/); + for (j = 0, n = lines.length, i = 0; i < n; i++) { + if ($.trim(lines[i]) !== '') { + $.extend(hash, { line:++j, selection:lines[i] } ); + lines[i] = build(lines[i]).block; + } else { + lines[i] = ""; + } + } + string = { block:lines.join('\n')}; + start = caretPosition; + len = string.block.length + (($.browser.opera) ? n : 0); + } else if (ctrlKey === true) { + string = build(selection); + start = caretPosition + string.openWith.length; + len = string.block.length - string.openWith.length - string.closeWith.length; + len -= fixIeBug(string.block); + } else if (shiftKey === true) { + string = build(selection); + start = caretPosition; + len = string.block.length; + len -= fixIeBug(string.block); + } else { + string = build(selection); + start = caretPosition + string.block.length ; + len = 0; + start -= fixIeBug(string.block); + } + if ((selection === '' && string.replaceWith === '')) { + caretOffset += fixOperaBug(string.block); + + start = caretPosition + string.openWith.length; + len = string.block.length - string.openWith.length - string.closeWith.length; + + caretOffset = $$.val().substring(caretPosition, $$.val().length).length; + caretOffset -= fixOperaBug($$.val().substring(0, caretPosition)); + } + $.extend(hash, { caretPosition:caretPosition, scrollPosition:scrollPosition } ); + + if (string.block !== selection && abort === false) { + insert(string.block); + set(start, len); + } else { + caretOffset = -1; + } + get(); + + $.extend(hash, { line:'', selection:selection }); + + // callbacks after insertion + if (ctrlKey === true && shiftKey === true) { + prepare(clicked.afterMultiInsert); + } + prepare(clicked.afterInsert); + prepare(options.afterInsert); + + // refresh preview if opened + if (previewWindow && options.previewAutoRefresh) { + refreshPreview(); + } + + // reinit keyevent + shiftKey = altKey = ctrlKey = abort = false; + } + + // Substract linefeed in Opera + function fixOperaBug(string) { + if ($.browser.opera) { + return string.length - string.replace(/\n*/g, '').length; + } + return 0; + } + // Substract linefeed in IE + function fixIeBug(string) { + if ($.browser.msie) { + return string.length - string.replace(/\r*/g, '').length; + } + return 0; + } + + // add markup + function insert(block) { + if (document.selection) { + var newSelection = document.selection.createRange(); + newSelection.text = block; + } else { + $$.val($$.val().substring(0, caretPosition) + block + $$.val().substring(caretPosition + selection.length, $$.val().length)); + } + } + + // set a selection + function set(start, len) { + if (textarea.createTextRange){ + // quick fix to make it work on Opera 9.5 + if ($.browser.opera && $.browser.version >= 9.5 && len == 0) { + return false; + } + range = textarea.createTextRange(); + range.collapse(true); + range.moveStart('character', start); + range.moveEnd('character', len); + range.select(); + } else if (textarea.setSelectionRange ){ + textarea.setSelectionRange(start, start + len); + } + textarea.scrollTop = scrollPosition; + textarea.focus(); + } + + // get the selection + function get() { + textarea.focus(); + + scrollPosition = textarea.scrollTop; + if (document.selection) { + selection = document.selection.createRange().text; + if ($.browser.msie) { // ie + var range = document.selection.createRange(), rangeCopy = range.duplicate(); + rangeCopy.moveToElementText(textarea); + caretPosition = -1; + while(rangeCopy.inRange(range)) { // fix most of the ie bugs with linefeeds... + rangeCopy.moveStart('character'); + caretPosition ++; + } + } else { // opera + caretPosition = textarea.selectionStart; + } + } else { // gecko + caretPosition = textarea.selectionStart; + selection = $$.val().substring(caretPosition, textarea.selectionEnd); + } + return selection; + } + + // open preview window + function preview() { + if (!previewWindow || previewWindow.closed) { + if (options.previewInWindow) { + previewWindow = window.open('', 'preview', options.previewInWindow); + } else { + iFrame = $(''); + if (options.previewPosition == 'after') { + iFrame.insertAfter(footer); + } else { + iFrame.insertBefore(header); + } + previewWindow = iFrame[iFrame.length-1].contentWindow || frame[iFrame.length-1]; + } + } else if (altKey === true) { + if (iFrame) { + iFrame.remove(); + } + previewWindow.close(); + previewWindow = iFrame = false; + } + if (!options.previewAutoRefresh) { + refreshPreview(); + } + } + + // refresh Preview window + function refreshPreview() { + if (previewWindow.document) { + try { + sp = previewWindow.document.documentElement.scrollTop + } catch(e) { + sp = 0; + } + previewWindow.document.open(); + previewWindow.document.write(renderPreview()); + previewWindow.document.close(); + previewWindow.document.documentElement.scrollTop = sp; + } + if (options.previewInWindow) { + previewWindow.focus(); + } + } + + function renderPreview() { + if (options.previewParserPath !== '') { + $.ajax( { + type: 'POST', + async: false, + url: options.previewParserPath, + data: options.previewParserVar+'='+encodeURIComponent($$.val()), + success: function(data) { + phtml = localize(data, 1); + } + } ); + } else { + if (!template) { + $.ajax( { + async: false, + url: options.previewTemplatePath, + success: function(data) { + template = localize(data, 1); + } + } ); + } + phtml = template.replace(//g, $$.val()); + } + return phtml; + } + + // set keys pressed + function keyPressed(e) { + shiftKey = e.shiftKey; + altKey = e.altKey; + ctrlKey = (!(e.altKey && e.ctrlKey)) ? e.ctrlKey : false; + + if (e.type === 'keydown') { + if (ctrlKey === true) { + li = $("a[accesskey="+String.fromCharCode(e.keyCode)+"]", header).parent('li'); + if (li.length !== 0) { + ctrlKey = false; + li.triggerHandler('mouseup'); + return false; + } + } + if (e.keyCode === 13 || e.keyCode === 10) { // Enter key + if (ctrlKey === true) { // Enter + Ctrl + ctrlKey = false; + markup(options.onCtrlEnter); + return options.onCtrlEnter.keepDefault; + } else if (shiftKey === true) { // Enter + Shift + shiftKey = false; + markup(options.onShiftEnter); + return options.onShiftEnter.keepDefault; + } else { // only Enter + markup(options.onEnter); + return options.onEnter.keepDefault; + } + } + if (e.keyCode === 9) { // Tab key + if (shiftKey == true || ctrlKey == true || altKey == true) { // Thx Dr Floob. + return false; + } + if (caretOffset !== -1) { + get(); + caretOffset = $$.val().length - caretOffset; + set(caretOffset, 0); + caretOffset = -1; + return false; + } else { + markup(options.onTab); + return options.onTab.keepDefault; + } + } + } + } + + init(); + }); + }; + + $.fn.markItUpRemove = function() { + return this.each(function() { + $$ = $(this).unbind().removeClass('markItUpEditor'); + $$.parent('div').parent('div.markItUp').parent('div').replaceWith($$); + } + ); + }; + + $.markItUp = function(settings) { + var options = { target:false }; + $.extend(options, settings); + if (options.target) { + return $(options.target).each(function() { + $(this).focus(); + $(this).trigger('insertion', [options]); + }); + } else { + $('textarea').trigger('insertion', [options]); + } + }; +})(jQuery); diff --git a/javascript/jquery.markitup_pour_spip.js b/javascript/jquery.markitup_pour_spip.js new file mode 100644 index 0000000..eba981e --- /dev/null +++ b/javascript/jquery.markitup_pour_spip.js @@ -0,0 +1,776 @@ +// ---------------------------------------------------------------------------- +// markItUp! Universal MarkUp Engine, JQuery plugin +// v 1.1.5 +// Dual licensed under the MIT and GPL licenses. +// ---------------------------------------------------------------------------- +// Copyright (C) 2007-2008 Jay Salvat +// http://markitup.jaysalvat.com/ +// ---------------------------------------------------------------------------- +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ---------------------------------------------------------------------------- + +/* + * Le code original de markitup 1.1.5 + * a ete modifie pour prendre en compte + * + * 1) la langue utilisee dans les textarea : + * - si un textarea possede un attribut lang='xx' alors + * markitup n'affichera que les icones qui correspondent a cette langue + * - on peut passer une valeur de langue par defaut a markitup (le textarea peut ne pas en definir) + * .markitup(set_spip,{lang:'fr'}); + * - une option supplementaire optionnelle 'lang' est introduite dans les parametres + * des boutons (markupset), par exemple : lang:['fr','es','en'] + * - si un bouton n'a pas ce parametre, l'icone s'affiche + * quelque soit la langue designee dans le textarea ou les parametres de markitup ; + * sinon, il faut que la langue soit contenue dedans pour que l'icone s'affiche. + * 2) les control + shift (ou alt) + click bouton qui ne semblaient pas fonctionner + * en tout cas sous FF3/ubintu/jquery 1.2.6 a verifier chez les autres (opera 9.5/ubuntu ok) + * 3) gerer des types de selections differentes : + * - normales comme dans markitup (rien a faire) + * - 'selectionType':'word' : aux mots le plus proche si pas de selection (sinon la selection) + * - 'selectionType':'line' : aux lignes les plus proches + * - and 'return' : ugly hack to generate list (and so on) on key 'return' press + * 4) forcer des actions multilignes sans avoir besoin de faire control+click + * - 'forceMultiline':true : force donc une insertion multiligne + * 5) correction de la recuperation des selections d'Opera et de IE + * en utilisant une autre fonction de split() qui corrige leurs bugs. + * (caretOffset n'est plus necessaire) + * + */ +;(function($) { + $.fn.markItUp = function(settings, extraSettings) { + var options, ctrlKey, shiftKey, altKey, enterKey; + ctrlKey = shiftKey = altKey = enterKey = false; + + options = { id: '', + nameSpace: '', + root: '', + lang: '', + previewInWindow: '', // 'width=800, height=600, resizable=yes, scrollbars=yes' + previewAutoRefresh: true, + previewPosition: 'after', + previewTemplatePath: '~/templates/preview.html', + previewParserPath: '', + previewParserVar: 'data', + resizeHandle: true, + beforeInsert: '', + afterInsert: '', + onEnter: {}, + onShiftEnter: {}, + onCtrlEnter: {}, + onTab: {}, + markupSet: [ { /* set */ } ] + }; + $.extend(options, settings, extraSettings); + + // compute markItUp! path + if (!options.root) { + $('script').each(function(a, tag) { + miuScript = $(tag).get(0).src.match(/(.*)jquery\.markitup(\.pack)?\.js$/); + if (miuScript !== null) { + options.root = miuScript[1]; + } + }); + } + + return this.each(function() { + var $$, textarea, levels, scrollPosition, caretPosition, caretEffectivePosition, + clicked, hash, header, footer, previewWindow, template, iFrame, abort, + before, after; + $$ = $(this); + textarea = this; + levels = []; + abort = false; + scrollPosition = caretPosition = 0; + + options.previewParserPath = localize(options.previewParserPath); + options.previewTemplatePath = localize(options.previewTemplatePath); + + // apply the computed path to ~/ + function localize(data, inText) { + if (inText) { + return data.replace(/("|')~\//g, "$1"+options.root); + } + return data.replace(/^~\//, options.root); + } + + // init and build editor + function init() { + id = ''; nameSpace = ''; + if (options.id) { + id = 'id="'+options.id+'"'; + } else if ($$.attr("id")) { + id = 'id="markItUp'+($$.attr("id").substr(0, 1).toUpperCase())+($$.attr("id").substr(1))+'"'; + + } + if (options.nameSpace) { + nameSpace = 'class="'+options.nameSpace+'"'; + } + $$.wrap('
    '); + $$.wrap('
    '); + $$.wrap('
    '); + $$.addClass("markItUpEditor"); + + // add the header before the textarea + header = $('
    ').insertBefore($$); + $(dropMenus(options.markupSet)).appendTo(header); + // remove empty dropMenu + $(header).find("li.markItUpDropMenu ul:empty").parent().remove(); + + // add the footer after the textarea + footer = $('
    ').insertAfter($$); + + // add the resize handle after textarea + if (options.resizeHandle === true && $.browser.safari !== true) { + resizeHandle = $('
    ') + .insertAfter($$) + .bind("mousedown", function(e) { + var h = $$.height(), y = e.clientY, mouseMove, mouseUp; + mouseMove = function(e) { + $$.css("height", Math.max(20, e.clientY+h-y)+"px"); + return false; + }; + mouseUp = function(e) { + $("html").unbind("mousemove", mouseMove).unbind("mouseup", mouseUp); + return false; + }; + $("html").bind("mousemove", mouseMove).bind("mouseup", mouseUp); + }); + footer.append(resizeHandle); + } + + // listen key events + $$.keydown(keyPressed).keyup(keyPressed); + + // bind an event to catch external calls + $$.bind("insertion", function(e, settings) { + if (settings.target !== false) { + get(); + } + if (textarea === $.markItUp.focused) { + markup(settings); + } + }); + + // remember the last focus + $$.focus(function() { + $.markItUp.focused = this; + }); + } + + // recursively build header with dropMenus from markupset + function dropMenus(markupSet) { + var ul = $(''), i = 0; + var lang = ($$.attr('lang')||options.lang); + + $('li:hover > ul', ul).css('display', 'block'); + $.each(markupSet, function() { + var button = this, t = '', title, li, j; + // pas de langue ou dans la langue ; et uniquement si langue autorisee + if ((!lang || !button.lang || ($.inArray(lang, button.lang) != -1)) + && (!button.lang_not || ($.inArray(lang, button.lang_not) == -1))) { + title = (button.key) ? (button.name||'')+' [Ctrl+'+button.key+']' : (button.name||''); + key = (button.key) ? 'accesskey="'+button.key+'"' : ''; + if (button.separator) { + li = $('
  • '+(button.separator||'')+'
  • ').appendTo(ul); + } else { + i++; + for (j = levels.length -1; j >= 0; j--) { + t += levels[j]+"-"; + } + li = $('
  • '+(button.name||'')+'
  • ') + .bind("contextmenu", function() { // prevent contextmenu on mac and allow ctrl+click + return false; + }).click(function() { + return false; + }).mouseup(function() { + if (button.call) { + eval(button.call)(); + } + markup(button); + return false; + }).hover(function() { + $('> ul', this).show(); + $(document).one('click', function() { // close dropmenu if click outside + $('ul ul', header).hide(); + } + ); + }, function() { + $('> ul', this).hide(); + } + ).appendTo(ul); + if (button.dropMenu) { + levels.push(i); + $(li).addClass('markItUpDropMenu').append(dropMenus(button.dropMenu)); + } + } + } + }); + levels.pop(); + return ul; + } + + // markItUp! markups + function magicMarkups(string) { + if (string) { + string = string.toString(); + string = string.replace(/\(\!\(([\s\S]*?)\)\!\)/g, + function(x, a) { + var b = a.split('|!|'); + if (altKey === true) { + return (b[1] !== undefined) ? b[1] : b[0]; + } else { + return (b[1] === undefined) ? "" : b[0]; + } + } + ); + // [![prompt]!], [![prompt:!:value]!] + string = string.replace(/\[\!\[([\s\S]*?)\]\!\]/g, + function(x, a) { + var b = a.split(':!:'); + if (abort === true) { + return false; + } + value = prompt(b[0], (b[1]) ? b[1] : ''); + if (value === null) { + abort = true; + } + return value; + } + ); + return string; + } + return ""; + } + + // prepare action + function prepare(action) { + if ($.isFunction(action)) { + action = action(hash); + } + return magicMarkups(action); + } + + // build block to insert + function build(string) { + openWith = prepare(clicked.openWith); + placeHolder = prepare(clicked.placeHolder); + replaceWith = prepare(clicked.replaceWith); + closeWith = prepare(clicked.closeWith); + if (replaceWith !== "") { + block = openWith + replaceWith + closeWith; + } else if (selection === '' && placeHolder !== '') { + block = openWith + placeHolder + closeWith; + } else { + block = openWith + (string||selection) + closeWith; + } + return { block:block, + openWith:openWith, + replaceWith:replaceWith, + placeHolder:placeHolder, + closeWith:closeWith + }; + } + + + function selectWord(){ + selectionBeforeAfter(/\s|[.,;:!¡?¿()]/); + selectionSave(); + } + function selectLine(){ + selectionBeforeAfter(/\r?\n/); + selectionSave(); + } + + function selectionRemoveLast(pattern){ + // Remove space by default + if (!pattern) pattern = /\s/; + last = selection[selection.length-1]; + if (last && last.match(pattern)) { + set(caretPosition, selection.length-1); + get(); + $.extend(hash, { caretPosition:caretPosition, scrollPosition:scrollPosition } ); + } + } + + function selectionBeforeAfter(pattern) { + if (!pattern) pattern = /\s/; + before = $$.val().substring(0, caretEffectivePosition); + after = $$.val().substring(caretEffectivePosition + selection.length - fixOperaBug(selection) - fixIeBug(selection)); + + before = before.xSplit(pattern); + after = after.xSplit(pattern); + } + + function selectionSave(){ + nb_before = before ? before[before.length-1].length : 0; + nb_after = after ? after[0].length : 0; + + nb = nb_before + selection.length + nb_after - fixIeBug(selection); + caretPosition = caretPosition - nb_before; + + set(caretPosition, nb); + get(); + $.extend(hash, { caretPosition:caretPosition, scrollPosition:scrollPosition } ); + } + + // define markup to insert + function markup(button) { + var len, j, n, i; + hash = clicked = button; + get(); + + $.extend(hash, { line:"", + root:options.root, + textarea:textarea, + selection:(selection||''), + caretPosition:caretPosition, + ctrlKey:ctrlKey, + shiftKey:shiftKey, + altKey:altKey, + enterKey:enterKey + } + ); + + // corrections des selections pour que + // - soit le curseur ne change pas + // - soit on prend le mot complet (si pas de selection) + // - soit on prend la ligne (avant, apres la selection) + if (button.selectionType) { + + if (button.selectionType == "word") { + if (!selection) { + selectWord(); + } else { + // win/ff add space on double click ? (hum, seems strange) + selectionRemoveLast(/\s/); + } + } + if (button.selectionType == "line") { + selectLine(); + } + // horrible chose, mais tellement plus pratique + // car on ne peut pas de l'exerieur (json) utiliser + // les fonctions internes de markitup + if (button.selectionType == "return"){ + selectionBeforeAfter(/\r?\n/); + before_last = before[before.length-1]; + after = ''; + // gestion des listes -# et -* + if (r = before_last.match(/^-([*#]+) ?(.*)$/)) { + if (r[2]) { + button.replaceWith = "\n-"+r[1]+' '; + before_last = ''; + } else { + // supprime le -* present + // (before le fera) + button.replaceWith = "\n"; + } + } else { + before_last = ''; + button.replaceWith = "\n"; + } + before[before.length-1] = before_last; + selectionSave(); + } + + } + // / fin corrections + + // callbacks before insertion + prepare(options.beforeInsert); + prepare(clicked.beforeInsert); + if (ctrlKey === true && shiftKey === true) { + prepare(clicked.beforeMultiInsert); + } + $.extend(hash, { line:1 }); + + // insertion forcee en multiligne ou ctrl+click + if ((button.forceMultiline === true && selection.length) + || (ctrlKey === true && shiftKey === true)) { + lines = selection.xSplit(/\r?\n/); + for (j = 0, n = lines.length, i = 0; i < n; i++) { + if ($.trim(lines[i]) !== '') { + $.extend(hash, { line:++j, selection:lines[i] } ); + lines[i] = build(lines[i]).block; + } else { + lines[i] = ""; + } + } + string = { block:lines.join('\n')}; + start = caretPosition; + len = string.block.length + (($.browser.opera) ? n : 0); + } else if (ctrlKey === true) { + string = build(selection); + start = caretPosition + string.openWith.length; + len = string.block.length - string.openWith.length - string.closeWith.length; + len -= fixIeBug(string.block); + } else if (shiftKey === true) { + string = build(selection); + start = caretPosition; + len = string.block.length; + len -= fixIeBug(string.block); + } else { + string = build(selection); + start = caretPosition + string.block.length ; + len = 0; + start -= fixIeBug(string.block); + } + + if (selection === ''){ + start += fixOperaBug(string.replaceWith); + } + //$.extend(hash, { caretPosition:caretPosition, scrollPosition:scrollPosition } ); + + if (string.block !== selection && abort === false) { + insert(string.block); + set(start, len); + } + + get(); + + $.extend(hash, { line:'', selection:selection }); + + // callbacks after insertion + if ((button.forceMultiline === true) + || (ctrlKey === true && shiftKey === true)) { + prepare(clicked.afterMultiInsert); + } + + prepare(clicked.afterInsert); + prepare(options.afterInsert); + + // refresh preview if opened + if (previewWindow && options.previewAutoRefresh) { + refreshPreview(); + } + + // reinit keyevent + shiftKey = altKey = ctrlKey = enterKey = abort = false; + + } + + // Substract linefeed in Opera + function fixOperaBug(string) { + if ($.browser.opera) { + return string.length - string.replace(/\n*/g, '').length; + } + return 0; + } + // Substract linefeed in IE + function fixIeBug(string) { + if ($.browser.msie) { + return string.length - string.replace(/\r*/g, '').length; + } + return 0; + } + + // add markup + function insert(block) { + if (document.selection) { + var newSelection = document.selection.createRange(); + newSelection.text = block; + } else { + $$.val($$.val().substring(0, caretEffectivePosition) + block + $$.val().substring(caretEffectivePosition + selection.length)); + } + } + + // set a selection + function set(start, len) { + if (textarea.createTextRange){ + range = textarea.createTextRange(); + range.collapse(true); + range.moveStart('character', start); + range.moveEnd('character', len); + range.select(); + } else if (textarea.setSelectionRange ){ + textarea.setSelectionRange(start, start + len); + } + textarea.scrollTop = scrollPosition; + textarea.focus(); + } + + // get the selection + function get() { + textarea.focus(); + + scrollPosition = textarea.scrollTop; + if (document.selection) { + selection = document.selection.createRange().text; + if ($.browser.msie) { // ie + var range = document.selection.createRange(), rangeCopy = range.duplicate(); + rangeCopy.moveToElementText(textarea); + caretPosition = -1; + while(rangeCopy.inRange(range)) { // fix most of the ie bugs with linefeeds... + rangeCopy.moveStart('character'); + caretPosition ++; + } + caretEffectivePosition = caretPosition; + } else { // opera + caretPosition = textarea.selectionStart; + lenSelection = selection.length; + // calcul du nombre reel de caracteres pour les substr() + set(0,caretPosition); + opBefore = document.selection.createRange().text; + caretEffectivePosition = opBefore.length - fixOperaBug(opBefore); + set(caretPosition, lenSelection); + selection = document.selection.createRange().text; + } + } else { // gecko + caretPosition = textarea.selectionStart; + caretEffectivePosition = caretPosition; + selection = $$.val().substring(caretPosition, textarea.selectionEnd); + } + return selection; + } + + // open preview window + function preview() { + if (!previewWindow || previewWindow.closed) { + if (options.previewInWindow) { + previewWindow = window.open('', 'preview', options.previewInWindow); + } else { + iFrame = $(''); + if (options.previewPosition == 'after') { + iFrame.insertAfter(footer); + } else { + iFrame.insertBefore(header); + } + previewWindow = iFrame[iFrame.length-1].contentWindow || frame[iFrame.length-1]; + } + } else if (altKey === true) { + if (iFrame) { + iFrame.remove(); + } + previewWindow.close(); + previewWindow = iFrame = false; + } + if (!options.previewAutoRefresh) { + refreshPreview(); + } + } + + // refresh Preview window + function refreshPreview() { + if (previewWindow.document) { + try { + sp = previewWindow.document.documentElement.scrollTop + } catch(e) { + sp = 0; + } + previewWindow.document.open(); + previewWindow.document.write(renderPreview()); + previewWindow.document.close(); + previewWindow.document.documentElement.scrollTop = sp; + } + if (options.previewInWindow) { + previewWindow.focus(); + } + } + + function renderPreview() { + if (options.previewParserPath !== '') { + $.ajax( { + type: 'POST', + async: false, + url: options.previewParserPath, + data: options.previewParserVar+'='+encodeURIComponent($$.val()), + success: function(data) { + phtml = localize(data, 1); + } + } ); + } else { + if (!template) { + $.ajax( { + async: false, + url: options.previewTemplatePath, + success: function(data) { + template = localize(data, 1); + } + } ); + } + phtml = template.replace(//g, $$.val()); + } + return phtml; + } + + // set keys pressed + function keyPressed(e) { + if (e.type === 'keydown') { + if (e.keyCode === 18) {e.altKey = true;} // alt + if (e.keyCode === 17) {e.ctrlKey = true;} // control + if (e.keyCode === 16) {e.shiftKey = true;} // shift + } + shiftKey = e.shiftKey; + altKey = e.altKey; + ctrlKey = (!(e.altKey && e.ctrlKey)) ? e.ctrlKey : false; + if (e.type === 'keydown') { + if (ctrlKey === true) { + li = $("a[accesskey="+String.fromCharCode(e.keyCode)+"]", header).parent('li'); + if (li.length !== 0) { + ctrlKey = false; + li.triggerHandler('mouseup'); + return false; + } + } + // si opera, on s'embete pas, il cree plus de problemes qu'autre chose + // car il ne prend pas en compte l'arret de ces evenements + if (!$.browser.opera) { + if (e.keyCode === 13 || e.keyCode === 10) { // Enter key + enterKey = true; + if (ctrlKey === true) { // Enter + Ctrl + ctrlKey = false; + markup(options.onCtrlEnter); + return options.onCtrlEnter.keepDefault; + } else if (shiftKey === true) { // Enter + Shift + shiftKey = false; + markup(options.onShiftEnter); + return options.onShiftEnter.keepDefault; + } else { // only Enter + markup(options.onEnter); + return options.onEnter.keepDefault; + } + } + + if (e.keyCode === 9) { // Tab key + // don't know what that is for... + if (shiftKey == true || ctrlKey == true || altKey == true) { // Thx Dr Floob. + return false; + } + markup(options.onTab); + return options.onTab.keepDefault; + } + } + } + } + + init(); + }); + }; + + $.fn.markItUpRemove = function() { + return this.each(function() { + $$ = $(this).unbind().removeClass('markItUpEditor'); + $$.parent('div').parent('div.markItUp').parent('div').replaceWith($$); + } + ); + }; + + $.markItUp = function(settings) { + var options = { target:false }; + $.extend(options, settings); + if (options.target) { + return $(options.target).each(function() { + $(this).focus(); + $(this).trigger('insertion', [options]); + }); + } else { + $('textarea').trigger('insertion', [options]); + } + }; + +})(jQuery); + + +/* + * Corriger les split qui ne fonctionnent pas pareil + * sous IE particulierement. Provient de : + * http://blog.stevenlevithan.com/archives/cross-browser-split + * (ici, remplace par la fonction xSplit) + */ + +/* + Cross-Browser Split 0.3 + By Steven Levithan + MIT license + Provides a consistent cross-browser, ECMA-262 v3 compliant split method +*/ + +//String.prototype._$$split = String.prototype._$$split || String.prototype.split; + +//String.prototype.split = function (s /* separator */, limit) { +String.prototype.xSplit = function (s /* separator */, limit) { + // if separator is not a regex, use the native split method + if (!(s instanceof RegExp)) + return String.prototype.split.apply(this, arguments); + //return String.prototype._$$split.apply(this, arguments); + + var flags = (s.global ? "g" : "") + (s.ignoreCase ? "i" : "") + (s.multiline ? "m" : ""), + s2 = new RegExp("^" + s.source + "$", flags), + output = [], + origLastIndex = s.lastIndex, + lastLastIndex = 0, + i = 0, match, lastLength; + + /* behavior for limit: if it's... + - undefined: no limit + - NaN or zero: return an empty array + - a positive number: use limit after dropping any decimal + - a negative number: no limit + - other: type-convert, then use the above rules + */ + if (limit === undefined || +limit < 0) { + limit = false; + } else { + limit = Math.floor(+limit); + if (!limit) + return []; + } + + if (s.global) + s.lastIndex = 0; + else + s = new RegExp(s.source, "g" + flags); + + while ((!limit || i++ <= limit) && (match = s.exec(this))) { + var emptyMatch = !match[0].length; + + // Fix IE's infinite-loop-resistant but incorrect lastIndex + if (emptyMatch && s.lastIndex > match.index) + s.lastIndex--; + + if (s.lastIndex > lastLastIndex) { + // Fix browsers whose exec methods don't consistently return undefined for non-participating capturing groups + if (match.length > 1) { + match[0].replace(s2, function () { + for (var j = 1; j < arguments.length - 2; j++) { + if (arguments[j] === undefined) + match[j] = undefined; + } + }); + } + + output = output.concat(this.slice(lastLastIndex, match.index)); + if (1 < match.length && match.index < this.length) + output = output.concat(match.slice(1)); + lastLength = match[0].length; // only needed if s.lastIndex === this.length + lastLastIndex = s.lastIndex; + } + + if (emptyMatch) + s.lastIndex++; // avoid an infinite loop + } + + // since this uses test(), output must be generated before restoring lastIndex + output = lastLastIndex === this.length ? + (s.test("") && !lastLength ? output : output.concat("")) : + (limit ? output : output.concat(this.slice(lastLastIndex))); + s.lastIndex = origLastIndex; // only needed if s.global, else we're working with a copy of the regex + return output; +}; diff --git a/javascript/jquery.previsu_spip.js b/javascript/jquery.previsu_spip.js new file mode 100644 index 0000000..6539ed3 --- /dev/null +++ b/javascript/jquery.previsu_spip.js @@ -0,0 +1,77 @@ +;(function($) { + $.fn.previsu_spip = function(settings) { + var options; + + options = { + previewParserPath: '' , + previewParserVar: 'data', + textEditer: 'Editer', + textVoir: 'Voir' + }; + $.extend(options, settings); + + return this.each(function() { + var $$, textarea, tabs, preview; + $$ = $(this); + textarea = this; + + // init and build previsu buttons + function init() { + tabs = $('
    ').prependTo($$.parent()); + $(tabs).append( + '' + options.textVoir + '' + + '' + options.textEditer + '' + ); + + preview = $('
    ').insertAfter(tabs); + preview.hide(); + + $('.previsuVoir').click(function(){ + mark = $(this).parent().parent(); + $(mark).find('.markItUpPreview').height( + $(mark).find('.markItUpHeader').height() + + $(mark).find('.markItUpEditor').height() + + $(mark).find('.markItUpFooter').height() + ); + $(mark).find('.markItUpHeader').hide(); + $(mark).find('.markItUpEditor').hide(); + $(mark).find('.markItUpFooter').hide(); + $(this).addClass('on').next().removeClass('on'); + $(mark).find('.markItUpPreview').show() + .addClass('ajaxLoad') + .html(renderPreview()) + .removeClass('ajaxLoad'); + return false; + }); + $('.previsuEditer').click(function(){ + mark = $(this).parent().parent(); + $(mark).find('.markItUpPreview').hide(); + $(mark).find('.markItUpHeader').show(); + $(mark).find('.markItUpEditor').show(); + $(mark).find('.markItUpFooter').show(); + $(this).addClass('on').prev().removeClass('on'); + return false; + }); + } + + + function renderPreview() { + var phtml; + if (options.previewParserPath !== '') { + $.ajax( { + type: 'POST', + async: false, + url: options.previewParserPath, + data: options.previewParserVar+'='+encodeURIComponent($$.val()), + success: function(data) { + phtml = data; + } + } ); + } + return phtml; + } + + init(); + }); + }; +})(jQuery); diff --git a/lang/barre_outils_ar.php b/lang/barre_outils_ar.php new file mode 100644 index 0000000..6e5c101 --- /dev/null +++ b/lang/barre_outils_ar.php @@ -0,0 +1,89 @@ + 'تنظيف الرموز البرمجية من كل علامات HTML', +'barre_lorem_ipsum' => 'إدراج فقرة زائفة', +'barre_lorem_ipsum_3' => 'إدراج ثلاث فقرات زائفة', +'barre_liste_ul' => 'تحويل الى لائحة', +'barre_liste_ol' => 'تحويل الى لائحة مرقمة', +'barre_indenter' => 'إزاحة لائحة', +'barre_desindenter' => 'إلغاء إزاحة لائحة', +'barre_inserer_caracteres' => 'إدراج حروف محددة', + +'editer'=>'تحرير', +'voir'=>'معاينة', + + +// B (depuis SPIP) +'barre_a_accent_grave' => 'إدراج A مع نبر الاطالة: À', +'barre_aide' => 'استخدم شريط اختصارات الكتابة لإغناء تصميم صفحتك', +'barre_e_accent_aigu' => 'ادراج E كبير مع نبر حاد - É', +'barre_eo' => 'ادراج e داخل e: œ', +'barre_eo_maj' => 'ادراج E كبير داخل O كبير: Œ', +'barre_euro' => 'ادراج رمز €', +'barre_gras' => '{{اسود}}', +'barre_guillemets' => 'احاطة «بعلامتي اقتباس مزدوجة»', +'barre_guillemets_simples' => 'وضع بين "علامتي إقتباس مزدوجة من المستوى الثاني"', +'barre_intertitre' => 'تحويل الى {{{عنوان فقرة}}}', +'barre_italic' => '{مائل}', +'barre_lien' => 'تحويل الى [وصلة هايبرتكست->http://...]', +'barre_lien_input' => 'الرجاء ادخال عنوان الوصلة (يمكنك ادخال عنوان نسيج على شكل http://www.mysite.com او ادخال رقم مقال من الموقع الحالي فقط).', +'barre_note' => 'تحويل الى [[حاشية]]', +'barre_paragraphe' => 'انشاء فقرة', +'barre_quote' => 'اقتباس رسالة', + +// B (depuis BTv2) +'barre_langue' => 'لغة مختصرة', +'barre_miseenevidence' => '[*إبراز*] النص', +'barre_exposant' => 'تحويل الى <sup>نص فوقي</sup>', +'barre_petitescapitales' => 'تحويل الى <sc>حروف كبيرة مصغرة</sc>', +'barre_centrer' => '[|توسيط|] الفقرة', +'barre_alignerdroite' => 'محاذاة الى [/اليمين/]', +'barre_encadrer' => 'وضع في [(إطار)]', +'barre_e_accent_grave' => 'إدراج E كبير مع نبر الاطالة: È', +'barre_ea' => 'ادراج e داخل a: æ', +'barre_ea_maj' => 'ادراج E كبير داخل A كبير: Æ', +'barre_c_cedille_maj' => 'ادراج C كبير مع علامة لفظية: Ç', + +'barre_chercher' => 'بحث واستبدال', +'barre_tableau' => 'إدراج جدول أو تعديل جدول (تحديده أولاً)', +'barre_glossaire' => 'مدخل في [?المعجم] (ويكيبيديا)', + +'barre_caracteres' => 'حروف خاصة', +'barre_adresse' => 'عنوان', +'barre_lien_externe' => 'رابط خارجي', +'barre_bulle' => 'بالون تعليمات', +'barre_formatages_speciaux' => 'تنسيقات خاصة', +'barre_galerie' => 'فتح صالة العرض', +'barre_gestion_caption' => 'وصف وملخص', +'barre_gestion_colonne' => 'عدد الأعمدة', +'barre_gestion_ligne' => 'عدد السطور', +'barre_gestion_entete' => 'ترويسة', +'barre_gestion_taille' => 'حجم ثابت', +'barre_gestion_cr_changercasse' => 'تغيير حجم الحروف', +'barre_gestion_cr_changercassemajuscules' => 'تحويل الى الحروف كبيرة', +'barre_gestion_cr_changercasseminuscules' => 'تحويل الى الحروف صغيرة', +'barre_gestion_cr_chercher' => 'بحث', +'barre_gestion_cr_remplacer' => 'استبدال', +'barre_gestion_cr_casse' => 'تطابق حجم الحروف', +'barre_gestion_cr_tout' => 'استبدال الكل', +'barre_gestion_cr_entier' => 'كلمة كاملة', +'barre_preview' => 'معاينة', +'barre_stats' => 'عرض احصاءات النص', + +'barre_code' => 'تنسيق <code>مقطع رموز برمجية</code>', +'barre_cadre' => 'وضع في <cadre>مجال إدخال نصوص</cadre>', +'barre_poesie' => 'تنسيق <poesie>شعر</poesie>', + +'barre_ancres' => 'إدارة المراسي', +'barre_gestion_anc_caption' => 'إدارة المراسي', +'barre_gestion_anc_inserer' => 'تحويل الى مرساة', +'barre_gestion_anc_nom' => 'اسم المرساة', +'barre_gestion_anc_pointer' => 'التصويب الى مرساة', +'barre_gestion_anc_cible' => 'المرساة الهدف', +'barre_gestion_anc_bulle' => 'بالون تعليمات المرساة' + + +); +?> diff --git a/lang/barre_outils_en.php b/lang/barre_outils_en.php new file mode 100644 index 0000000..6d12994 --- /dev/null +++ b/lang/barre_outils_en.php @@ -0,0 +1,89 @@ + 'Clean the code of all HTML tags', +'barre_lorem_ipsum' => 'Insert a fake paragraph', +'barre_lorem_ipsum_3' => 'Insert three fake paragraphs', +'barre_liste_ul' => 'Set list', +'barre_liste_ol' => 'Set numbered list', +'barre_indenter' => 'Indent a line', +'barre_desindenter' => 'Unindent a line', +'barre_inserer_caracteres' => 'Insert special characters', + +'editer'=>'Edit', +'voir'=>'Preview', + + +// B (depuis SPIP) +'barre_a_accent_grave' => 'Insert a capital A with grave accent', +'barre_aide' => 'Use the typographic short cuts to refine your layout', +'barre_e_accent_aigu' => 'Insert a capital E with acute accent', +'barre_eo' => 'Insert an oe-ligature', +'barre_eo_maj' => 'Insert a capital EO-ligature', +'barre_euro' => 'Insert the € symbol', +'barre_gras' => 'Put in {{bold type}}', +'barre_guillemets' => 'Place between «double quotes«', +'barre_guillemets_simples' => 'Place between “single quotes“', +'barre_intertitre' => 'Turn into a {{{subheading}}}', +'barre_italic' => 'Put in {italics}', +'barre_lien' => 'Turn into a [hyperlink->http://...]', +'barre_lien_input' => 'Please enter the target of your hyperlink (you may give an internet URL in the form http://www.mysite.com or else simply the number of an article on this site).', +'barre_note' => 'Turn into a [[Footnote]]', +'barre_paragraphe' => 'Create a paragraph', +'barre_quote' => 'Quote a message', + +// B (depuis BTv2) +'barre_langue' => 'Abbreviated lnguage', +'barre_miseenevidence' => 'Mettre le texte en [*évidence*]', +'barre_exposant' => 'Put the text in <sup>superscript</sup>', +'barre_petitescapitales' => 'Put the text in <sc>small capitales</sc>', +'barre_centrer' => '[|Center|] paragraph', +'barre_alignerdroite' => '[/Right align/] paragraph', +'barre_encadrer' => '[(Frame)] paragraph', +'barre_e_accent_grave' => 'Insert capital E grave', +'barre_ea' => 'Insert æ', +'barre_ea_maj' => 'Insert Æ', +'barre_c_cedille_maj' => 'Insert capital C cedilla', + +'barre_chercher' => 'Search & Replace', +'barre_tableau' => 'Insert/modify a table (select it first)', +'barre_glossaire' => '[?Glossary] reference (Wikipedia)', + +'barre_caracteres' => 'Special characters', +'barre_adresse' => 'Address', +'barre_lien_externe' => 'External link', +'barre_bulle' => 'Help bubble', +'barre_formatages_speciaux' => 'Special formating', +'barre_galerie' => 'Open gallery', +'barre_gestion_caption' => 'Caption and Summary', +'barre_gestion_colonne' => 'No. of columns', +'barre_gestion_ligne' => 'No. of lines', +'barre_gestion_entete' => 'Header', +'barre_gestion_taille' => 'Fixed size', +'barre_gestion_cr_changercasse' => 'Change case', +'barre_gestion_cr_changercassemajuscules' => 'Convert to upper case', +'barre_gestion_cr_changercasseminuscules' => 'Convert to lower case', +'barre_gestion_cr_chercher' => 'Search', +'barre_gestion_cr_remplacer' => 'Replace', +'barre_gestion_cr_casse' => 'Match case', +'barre_gestion_cr_tout' => 'Replace all', +'barre_gestion_cr_entier' => 'Only complete words', +'barre_preview' => 'Preview mode', +'barre_stats' => 'Show text statistics', + +'barre_code' => 'Edit a <code>computer code</code>', +'barre_cadre' => 'Put in a <cadre>textarea</cadre>', +'barre_poesie' => 'Edit as a <poesie>poetry</poesie>', + +'barre_ancres' => 'Anchors', +'barre_gestion_anc_caption' => 'Anchors', +'barre_gestion_anc_inserer' => 'Convert to anchor', +'barre_gestion_anc_nom' => 'Anchor name', +'barre_gestion_anc_pointer' => 'Point to an anchor', +'barre_gestion_anc_cible' => 'Anhor target', +'barre_gestion_anc_bulle' => 'Anchor help bubble', + + +); +?> diff --git a/lang/barre_outils_fr.php b/lang/barre_outils_fr.php new file mode 100644 index 0000000..ec6cb64 --- /dev/null +++ b/lang/barre_outils_fr.php @@ -0,0 +1,90 @@ + 'Nettoyer le code de toutes les balises HTML', +'barre_lorem_ipsum' => 'Insérer un paragraphe factice', +'barre_lorem_ipsum_3' => 'Insérer trois paragraphes factices', +'barre_liste_ul' => 'Mettre en liste', +'barre_liste_ol' => 'Mettre en liste numérotée', +'barre_indenter' => 'Indenter une liste', +'barre_desindenter' => 'Désindenter une liste', +'barre_inserer_caracteres' => 'Insérer des caractères spécifiques', +'barre_barre' => 'Barrer le texte', + +'editer'=>'Éditer', +'voir'=>'Voir', + + +// B (depuis SPIP) +'barre_a_accent_grave' => 'Insérer un A accent grave majuscule', +'barre_aide' => 'Utilisez les raccourcis typographiques pour enrichir votre mise en page', +'barre_e_accent_aigu' => 'Insérer un E accent aigu majuscule', +'barre_eo' => 'Insérer un E dans l\'O', +'barre_eo_maj' => 'Insérer un E dans l\'O majuscule', +'barre_euro' => 'Insérer le symbole €', +'barre_gras' => 'Mettre en {{gras}}', +'barre_guillemets' => 'Entourer de « guillemets »', +'barre_guillemets_simples' => 'Entourer de “guillemets de second niveau”', +'barre_intertitre' => 'Transformer en {{{intertitre}}}', +'barre_italic' => 'Mettre en {italique}', +'barre_lien' => 'Transformer en [lien hypertexte->http://...]', +'barre_lien_input' => 'Veuillez indiquer l\'adresse de votre lien (vous pouvez indiquer une adresse Internet sous la forme http://www.monsite.com, une adresse courriel, ou simplement indiquer le numéro d\'un article de ce site.', +'barre_note' => 'Transformer en [[Note de bas de page]]', +'barre_paragraphe' => 'Créer un paragraphe', +'barre_quote' => 'Citer un message', + +// B (depuis BTv2) +'barre_langue' => 'Langue abrégée', +'barre_miseenevidence' => 'Mettre le texte en [*évidence*]', +'barre_exposant' => 'Mettre le texte en <sup>exposant</sup>', +'barre_petitescapitales' => 'Mettre le texte en <sc>petites capitales</sc>', +'barre_centrer' => '[|Centrer|] le paragraphe', +'barre_alignerdroite' => '[/Aligne à droite/] le paragraphe', +'barre_encadrer' => '[(Encadrer)] le paragraphe', +'barre_e_accent_grave' => 'Insérer un E majuscule accent grave', +'barre_ea' => 'Insérer un E dans l\'A', +'barre_ea_maj' => 'Insérer un E dans l\'A majuscule', +'barre_c_cedille_maj' => 'Insérer un C cédille majuscule', + +'barre_chercher' => 'Chercher Remplacer', +'barre_tableau' => 'Insérer/modifier (le sélectionner avant) un tableau', +'barre_glossaire' => 'Entrée du [?glossaire] (Wikipedia)', + +'barre_caracteres' => 'Caractères spéciaux', +'barre_adresse' => 'Adresse', +'barre_lien_externe' => 'Lien externe', +'barre_bulle' => 'Bulle d\'aide', +'barre_formatages_speciaux' => 'Formatage spéciaux', +'barre_galerie' => 'Ouvrir la galerie', +'barre_gestion_caption' => 'Caption et Résumé', +'barre_gestion_colonne' => 'Nb colonnes', +'barre_gestion_ligne' => 'Nb lignes', +'barre_gestion_entete' => 'Entete', +'barre_gestion_taille' => 'Taille fixe', +'barre_gestion_cr_changercasse' => 'Changer la casse', +'barre_gestion_cr_changercassemajuscules' => 'Passer en majuscules', +'barre_gestion_cr_changercasseminuscules' => 'Passer en minuscules', +'barre_gestion_cr_chercher' => 'Chercher', +'barre_gestion_cr_remplacer' => 'Remplacer', +'barre_gestion_cr_casse' => 'Respecter la casse', +'barre_gestion_cr_tout' => 'Tout remplacer', +'barre_gestion_cr_entier' => 'Mot entier', +'barre_preview' => 'Mode prévisualisation', +'barre_stats' => 'Afficher les statistiques du texte', + +'barre_code' => 'Mettre en forme un <code>code informatique</code>', +'barre_cadre' => 'Placer dans une <cadre>zone de saisie de texte</cadre>', +'barre_poesie' => 'Mettre en forme comme une <poesie>poésie</poesie>', + +'barre_ancres' => 'Gestion des ancres', +'barre_gestion_anc_caption' => 'Gestion des ancres', +'barre_gestion_anc_inserer' => 'Transformer en ancre', +'barre_gestion_anc_nom' => 'Nom de l\'ancre', +'barre_gestion_anc_pointer' => 'Pointer vers une ancre', +'barre_gestion_anc_cible' => 'Ancre cible', +'barre_gestion_anc_bulle' => 'Bulle d\'aide ancre' + + +); +?> diff --git a/markitup/readme.txt b/markitup/readme.txt new file mode 100644 index 0000000..dfbb656 --- /dev/null +++ b/markitup/readme.txt @@ -0,0 +1,55 @@ +markItUp! 1.1.3 + +CHANGE LOG +markItUp! 1.1.3 2008-09-12 +- Fixed: IE7 preview problem + +markItUp! 1.1.2 2008-07-17 +- Fixed: Quick fix for Opera 9.5 caret position problem after insertion + +markItUp! 1.1.1 2008-06-02 +- Fixed: Key events status are passed to callbacks properly +- Improved: ScrollPosition is kept in the preview when its refreshed + +markItUp! 1.1.0 2008-05-04 +- Modified: Textarea's id is no more moved to the main container +- Modified: NameSpace Span become a Div to remain strict +- Added: Relative path to the script is computed +- Added: Relative path to the script passed to callbacks +- Added: Global instance ID property +- Added: $(element).markItUpRemove() to remove markItUp! +- Added: Resize handle is now optional with resizeHandle property +- Added: Property previewInWindow is added and accept window parameter +- Added: Property previewPosition is added +- Modified: Resize handle is no more displayed in Safari to avoid repetition with the native handle +- Modified: Property previewIframeRefresh become previewAutorefresh +- Modified: Built-in Html Preview call a template file +- Improved: Autorefreshing is now apply for preview in window too +- Improved: Cancel button in prompt window cancel now the whole insertion process +- Improved: Cleaner markItUp! code added to the DOM +- Removed: Depreciated preview properties as previewBaseUrl, previewCharset, previewCssPath, previewBodyId, previewBodyClassName +- Removed: Property previewIframe not longer exists +- Fixed: "Magic markups" works with line feeds +- Fixed: Key events are initialized after insertion +- Fixed: Internet Explorer line feed offset bug +- Fixed: Shortcut keys on Mac OS +- Fixed: Ctrl+click works and doesn't open Mac context menu anymore +- Fixed: Ctrl+click works and doesn't open the page in a new tab anymore +- Fixed: Minor Css modifications + +markItUp! 1.0.3 2008-04-04 +- Fixed: IE7 Preview empty baseurl problem +- Fixed: IE7 external targeted insertion +- Added: Property scrollPosition is passed to callbacks functions + +markItUp! 1.0.2 2008-03-31 +- Fixed: IE7 Html preview problems +- Fixed: Selection is kept if nothing is inserted +- Improved: Code minified + +markItUp! 1.0.1 2008-03-21 +- Removed: Global PlaceHolder +- Modified: Property previewCharset is setted to "utf-8" by default + +markItUp! 1.0.0 2008-03-01 +- First public release diff --git a/markitup/templates/preview.css b/markitup/templates/preview.css new file mode 100644 index 0000000..ad91a87 --- /dev/null +++ b/markitup/templates/preview.css @@ -0,0 +1,5 @@ +/* preview style examples */ +body { + background-color:#EFEFEF; + font:70% Verdana, Arial, Helvetica, sans-serif; +} \ No newline at end of file diff --git a/markitup/templates/preview.html b/markitup/templates/preview.html new file mode 100644 index 0000000..b8b3702 --- /dev/null +++ b/markitup/templates/preview.html @@ -0,0 +1,11 @@ + + + + +markItUp! preview template + + + + + + diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..b13c863 --- /dev/null +++ b/plugin.xml @@ -0,0 +1,29 @@ + + Porte plume - Une barre d'outil pour bien écrire + Matthieu Marcillaud + GNU/GPL + 1.2.6 + + "Porte plume" est une barre d'outil géniale pour SPIP qui + utilise la librairie javascript [MarkItUp->http://markitup.jaysalvat.com/home/] + + Utilise les icones [FamFamFam->http://www.famfamfam.com/] + + http://documentation.magraine.net/-Porte-Plume- + stable + porte_plume + + porte_plume_options.php + inc/barre_outils.php + + + insert_head + porte_plume_pipelines.php + + + header_prive + insert_head + porte_plume_pipelines.php + + + diff --git a/porte_plume.js.html b/porte_plume.js.html new file mode 100644 index 0000000..f2618f5 --- /dev/null +++ b/porte_plume.js.html @@ -0,0 +1,4 @@ +#CACHE{7*24*3600} +#HTTP_HEADER{Content-Type: text/javascript; charset=#CHARSET} + +[(#VAL|porte_plume_creer_json_markitup)] diff --git a/porte_plume.js_fonctions.php b/porte_plume.js_fonctions.php new file mode 100644 index 0000000..99e90b6 --- /dev/null +++ b/porte_plume.js_fonctions.php @@ -0,0 +1,61 @@ +ajouterApres('bold',array(params)); + // $barre->ajouterAvant('bold',array(params)); + // + // $bold = $barre->get('bold'); + // $bold['id'] = 'bold2'; + // $barre->ajouterApres('italic',$bold); + $barres = pipeline('porte_plume_barre_pre_charger', $barres); + + + // 3 chargement + // permet de cacher ou afficher certains boutons au besoin + // exemples : + // $barre = &$flux['spip']; + // $barre->afficher('bold'); + // $barre->cacher('bold'); + // + // $barre->cacherTout(); + // $barre->afficher(array('bold','italic','header1')); + $barres = pipeline('porte_plume_barre_charger', $barres); + + + // 4 on cree les jsons + $json = ""; + foreach($barres as $set=>$barre) { + $json .= $barre->creer_json(); + } + return $json; +} + + +?> diff --git a/porte_plume_options.php b/porte_plume_options.php new file mode 100644 index 0000000..ed0e246 --- /dev/null +++ b/porte_plume_options.php @@ -0,0 +1,20 @@ + diff --git a/porte_plume_pipelines.php b/porte_plume_pipelines.php new file mode 100644 index 0000000..176f0d7 --- /dev/null +++ b/porte_plume_pipelines.php @@ -0,0 +1,55 @@ +\n" + . "\n" + . "\n" + . "\n" + . "\n"; + + $preview = url_absolue(generer_url_public('preview')); + $tEditer = _T('barre_outils:editer'); + $tVoir = _T('barre_outils:voir'); + $flux .= << + + +EOF; + + return $flux; +} + + +?> diff --git a/preview.html b/preview.html new file mode 100644 index 0000000..621696a --- /dev/null +++ b/preview.html @@ -0,0 +1,6 @@ +#CACHE{0} +#HTTP_HEADER{Content-Type: text/html; charset=#CHARSET} +
    +[(#ENV*{data}|propre|image_reduire{440}|liens_absolus)] +[
    (#NOTES)
    ] +
    diff --git a/tests/all_tests.php b/tests/all_tests.php new file mode 100644 index 0000000..31ce28f --- /dev/null +++ b/tests/all_tests.php @@ -0,0 +1,12 @@ +SpipTestSuite('Barre MarkitUp'); + $this->addDir(__FILE__); + #$this->addFile(find_in_path('tests/barre_outil_markitup.php')); + } +} + +?> diff --git a/tests/barre_outil_markitup.php b/tests/barre_outil_markitup.php new file mode 100644 index 0000000..9dba800 --- /dev/null +++ b/tests/barre_outil_markitup.php @@ -0,0 +1,359 @@ +SpipTest("Test de la classe Barre_outils"); + + // instancier une barre d'outil + include_spip('inc/barre_outils'); + $this->baseParamsBarre = array( + 'nameSpace' => 'spip', + 'markupSet' => array( + // H1 - {{{ + array( + "id" => 'header1', + "name" => _T('barre_outils:barre_intertitre'), + "key" => "H", + "className" => "outil_header1", + "openWith" => "{{{", + "closeWith" => "}}}", + "display" => true, + ))); + $p = $this->baseParamsBarre; + $p['markupSet'][1] = array( + "id" => 'couleurs', + "name" => _T('barre_outils:barre_couleur'), + "key" => "C", + "className" => "outil_couleur", + "openWith" => '[color=[![Color]!]]', + "closeWith" => '[/color]', + "display" => true, + "dropMenu" => array( + array( + "id" => "couleur_jaune", + "name" => 'Yellow', + "openWith" => '[color=yellow]', + "closeWith" => '[/color]', + "className" => "outil_couleur", + "display" => true, + ), + array( + "id" => "couleur_orange", + "name" => 'Orange', + "openWith" => '[color=orange]', + "closeWith" => '[/color]', + "className" => "outil_couleur", + "display" => true, + ), + array( + "id" => "couleur_rouge", + "name" => 'Red', + "openWith" => '[color=red]', + "closeWith" => '[/color]', + "className" => "outil_couleur", + "display" => true, + ), + ), + ); + $this->baseParamsBarreEtendue = $p; + } + + // avant chaque appel de fonction test + function setUp() { + + } + // apres chaque appel de fonction test + function tearDown() { + + } + + + function testInitialisationBarre(){ + // parametres inseres a leur bonne place + $b = new Barre_outils($this->baseParamsBarre); + $this->assertEqual('spip', $b->nameSpace); + $this->assertEqual('header1', $b->markupSet[0]['id']); + $this->assertEqual(7, count($b->markupSet[0])); + } + + function testInitialisationBarreEtendue(){ + // parametres inseres a leur bonne place, + // meme quand il y a des sous-menu d'icones + $b = new Barre_outils($this->baseParamsBarreEtendue); + $this->assertEqual('spip', $b->nameSpace); + $this->assertEqual('header1', $b->markupSet[0]['id']); + $this->assertEqual(7, count($b->markupSet[0])); + $this->assertEqual('couleurs', $b->markupSet[1]['id']); + $this->assertEqual(3, count($b->markupSet[1]['dropMenu'])); + } + + function testOptionsIncorrectesNonIncluses(){ + $p = $this->baseParamsBarre; + $p['fausseVariable'] = "je ne dois pas m'installer"; + $p['markupSet'][0]['fauxParam'] = "je ne dois pas m'installer"; + $b = new Barre_outils($p); + $this->assertEqual('spip',$b->nameSpace); + $this->assertNull($b->fausseVariable); + $this->assertNull($b->markupSet[0]['fauxParam']); + $this->assertEqual(7, count($b->markupSet[0])); + } + + function testRecuperationDeParametreAvecGet(){ + // trouver des id de premier niveau + $p = $this->baseParamsBarre; + $b = new Barre_outils($p); + $this->assertEqual($b->get('header1'), $p['markupSet'][0]); + + // trouver des id de second niveau + $p = $this->baseParamsBarreEtendue; + $b = new Barre_outils($p); + $this->assertEqual($b->get('header1'), $p['markupSet'][0]); + $this->assertEqual($b->get('couleurs'), $p['markupSet'][1]); + $this->assertEqual($b->get('couleur_jaune'), $p['markupSet'][1]['dropMenu'][0]); + $this->assertEqual($b->get('couleur_orange'), $p['markupSet'][1]['dropMenu'][1]); + $this->assertEqual($b->get('couleur_rouge'), $p['markupSet'][1]['dropMenu'][2]); + + // ne pas trouver d'id inconnu + $this->assertFalse($b->get('je_nexiste_pas')); + } + + function testModificationDeParametresAvecSet(){ + $p = $this->baseParamsBarre; + $b = new Barre_outils($p); + $p['markupSet'][0]['name'] = 'New'; + $r = $p['markupSet'][0]; + $x = $b->set('header1', array("name"=>"New")); + + $this->assertEqual($r, $x); // set retourne la chaine modifiee complete + $this->assertEqual($r, $b->get('header1')); + + // on ne peut ajouter de mauvais parametres + $x = $b->set('header1', array("Je Suis Pas Bon"=>"No no no")); + $this->assertEqual($r, $x); // set retourne la chaine modifiee complete + $this->assertEqual($r, $b->get('header1')); + } + + function testAjoutDeParametresApres(){ + $b = new Barre_outils($this->baseParamsBarre); + $p = $this->baseParamsBarreEtendue; + + // ajoutons la couleur apres + $b->ajouterApres('header1',$p['markupSet'][1]); + $this->assertEqual(2, count($b->markupSet)); // 2 boutons de premier niveau maintenant + $this->assertEqual($b->get('couleurs'), $p['markupSet'][1]); // get renvoie bien le bon ajout + $this->assertEqual($b->markupSet[1], $p['markupSet'][1]); // et l'ajout est au bon endroit + + // ajoutons une couleur dans l'ajout + $coul = $p['markupSet'][1]['dropMenu'][0]; + $coul['id'] = 'couleur_violette'; + $b->ajouterApres('couleur_orange',$coul); + $this->assertEqual(4, count($b->markupSet[1]['dropMenu'])); // sous boutons + $this->assertEqual($b->get('couleur_violette'), $coul); + $this->assertEqual($b->markupSet[1]['dropMenu'][2], $coul); // insertion au bon endroit + + // ajoutons un header2 encore apres + $p['markupSet'][0]['id'] = 'header2'; + $b->ajouterApres('couleurs',$p['markupSet'][0]); + $this->assertEqual(3, count($b->markupSet)); + $this->assertEqual($b->get('header2'), $p['markupSet'][0]); + $this->assertEqual($b->markupSet[2], $p['markupSet'][0]); + } + + function testAjoutDeParametresAvant(){ + $b = new Barre_outils($this->baseParamsBarre); + $p = $this->baseParamsBarreEtendue; + + // ajoutons la couleur apres + $b->ajouterAvant('header1',$p['markupSet'][1]); + $this->assertEqual(2, count($b->markupSet)); // 2 boutons de premier niveau maintenant + $this->assertEqual($b->get('couleurs'), $p['markupSet'][1]); // get renvoie bien le bon ajout + $this->assertEqual($b->markupSet[0], $p['markupSet'][1]); // et l'ajout est au bon endroit + + // ajoutons une couleur dans l'ajout + $coul = $p['markupSet'][1]['dropMenu'][0]; + $coul['id'] = 'couleur_violette'; + $b->ajouterAvant('couleur_orange',$coul); + $this->assertEqual(4, count($b->markupSet[0]['dropMenu'])); // sous boutons + $this->assertEqual($b->get('couleur_violette'), $coul); + $this->assertEqual($b->markupSet[0]['dropMenu'][1], $coul); // insertion au bon endroit + + // ajoutons un header2 avant le 1 + $p['markupSet'][0]['id'] = 'header2'; + $b->ajouterAvant('header1',$p['markupSet'][0]); + $this->assertEqual(3, count($b->markupSet)); + $this->assertEqual($b->get('header2'), $p['markupSet'][0]); + $this->assertEqual($b->markupSet[1], $p['markupSet'][0]); + } + + function testAfficherEtCacher(){ + $b = new Barre_outils($this->baseParamsBarre); + $b->cacher('header1'); + $this->assertFalse($b->markupSet[0]['display']); + $b->afficher('header1'); + $this->assertTrue($b->markupSet[0]['display']); + } + + function testAfficherEtCacherTout(){ + $b = new Barre_outils($this->baseParamsBarreEtendue); + $b->cacherTout(); + $this->assertFalse($b->markupSet[0]['display']); + $this->assertFalse($b->markupSet[1]['dropMenu'][0]['display']); + + $b->afficherTout(); + $this->assertTrue($b->markupSet[0]['display']); + $this->assertTrue($b->markupSet[1]['dropMenu'][0]['display']); + } + + function testAfficherEtCacherPlusieursBoutons(){ + $b = new Barre_outils($this->baseParamsBarreEtendue); + $b->cacher(array('header1','couleur_jaune')); + $this->assertFalse($b->markupSet[0]['display']); + $this->assertFalse($b->markupSet[1]['dropMenu'][0]['display']); + $this->assertTrue($b->markupSet[1]['dropMenu'][1]['display']); + + $b->cacherTout(); + $b->afficher(array('header1','couleur_jaune')); + $this->assertTrue($b->markupSet[0]['display']); + $this->assertTrue($b->markupSet[1]['dropMenu'][0]['display']); + $this->assertFalse($b->markupSet[1]['dropMenu'][1]['display']); + } + + function testSetAvecIdVideNeDoitRienModifier(){ + $b = new Barre_outils($this->baseParamsBarreEtendue); + $b->set(array(),array('display'=>false)); + $this->assertTrue($b->markupSet[0]['display']); + $this->assertTrue($b->markupSet[1]['dropMenu'][0]['display']); + } + + function testSetAvecIdArrayDoitModifTousLesIds(){ + $b = new Barre_outils($this->baseParamsBarreEtendue); + $b->set(array('header1','couleur_jaune'),array('display'=>false)); + $this->assertFalse($b->markupSet[0]['display']); + $this->assertFalse($b->markupSet[1]['dropMenu'][0]['display']); + $this->assertTrue($b->markupSet[1]['dropMenu'][1]['display']); + } + + function testCreerJson(){ + $b = new Barre_outils($this->baseParamsBarre); + $b->ajouterApres('header1', array( + "id" => 'Caracteres decodes', + "name" => "étrange", + "className" => "outil_fr", + "openWith" => "[fr]", + "display" => true, + )); + $json = $b->creer_json(); + $this->assertPattern(',barre_outils_spip = {,',$json); + $this->assertPattern(',\[{"name":",',$json); + $this->assertNoPattern(',eacute;,',$json); + } + + function testBoutonsDUneLangue(){ + $b = new Barre_outils($this->baseParamsBarre); + $ico2 = $ico1 = array( + "id" => 'ico_fr1', + "name" => "test apparaissant si langue est le francais", + "className" => "outil_fr", + "openWith" => "[fr]", + "lang" => array("fr"), + "display" => true, + ); + $ico2['id'] = 'ico_fr2'; + $ico2['lang'] = array("fr","en","es"); + + $b->ajouterApres('header1', $ico1); + $b->ajouterApres('ico_fr1', $ico2); + $this->assertEqual($ico1, $b->get('ico_fr1')); + $this->assertEqual($ico2, $b->get('ico_fr2')); + + // verifier que ces nouveaux array() + // ne posent pas de problemes dans les recursions + $b->cacherTout(); + $this->assertFalse($b->markupSet[1]['display']); + $b->afficher('ico_fr1'); + $this->assertTrue($b->markupSet[1]['display']); + $b->cacherTout(); + $b->afficher(array('ico_fr1','ico_fr2')); + $this->assertTrue($b->markupSet[1]['display']); + + // la langue est bien transmise au json + $json = $b->creer_json(); + $this->assertPattern(',"lang":\[,', $json); + } + + + function testFonctionsJavacriptDansParametreNeDoitPasEtreEntreguillemetsDansJson(){ + $b = new Barre_outils($this->baseParamsBarre); + $clean = array( + "id" => 'clean', + "name" => _T('barre_outils:barre_clean'), + "className" => "outil_clean", + // function doit etre echappe + "replaceWith" => 'function(markitup) { return markitup.selection.replace(/<(.*?)>/g, "") }', + "display" => true, + ); + $b->ajouterApres('header1', $clean); + $json = $b->creer_json(); + // pas de :"function(... ..." + $this->assertPattern('/:function\(/',$json); + } + + function testParametreFunctionsDansJson(){ + $b = new Barre_outils($this->baseParamsBarre); + $b->functions = "function dido(){}"; + $json = $b->creer_json(); + // function n'est plus dans la barre + $this->assertFalse($b->functions); + // mais uniquement en fin du fichier json + $this->assertPattern('/function dido\(/', $json); + } + + function testAjouterFonctions(){ + $b = new Barre_outils($this->baseParamsBarre); + $b->Ajouterfonction("function dido(){}"); + $this->assertPattern('/function dido\(/', $b->fonctions); + } + + /* + function squeletteTest(){ + $sq = new SqueletteTest("SimpleTest"); + $sq->addInsertHead(); + $sq->addToBody(" +
    +
    + +
    +
    + "); + return $sq; + } + + function testPresenceBarreOutilPublique(){ + include_spip('simpletest/browser'); + include_spip('simpletest/web_tester'); + + $sq = $this->squeletteTest(); + + $browser = &new SimpleBrowser(); + $browser->get($f=$this->urlTestCode($sq->code())); + $browser->setField('texte', 'me'); + $this->dump($browser->getField('texte')); + $this->dump($browser->getContent()); + #$this->dump($c); + #$this->assertPattern('/jquery\.markitup_pour_spip\.js/', $c); + }*/ +} + + +?> diff --git a/tests/lanceur_spip.php b/tests/lanceur_spip.php new file mode 100644 index 0000000..b14b355 --- /dev/null +++ b/tests/lanceur_spip.php @@ -0,0 +1,36 @@ +Echec : SPIP ne peut pas etre demarre automatiquement pour le test.
    + Vous utilisez certainement un lien symbolique dans votre repertoire plugins."); +} +include_spip('inc/tests'); +if (!class_exists('SpipTestSuite')) { + die("Echec : le plugin pour les tests unitaires avec SimpleTest ne semble pas actif."); +} +?>