WP File Manager
Current Path:
/
home
/
argothem
/
www
/
organecyberpresse
/
plugins
/
auto
/
orthotypo
/
v2.2.0
/
Name
Action
..
.gitattributes
Edit
CHANGELOG.md
Edit
README.md
Edit
css
formulaires
install.log
Edit
lang
orthotypo-xx.svg
Edit
orthotypo_fonctions.php
Edit
orthotypo_ieconfig_metas.php
Edit
orthotypo_options.php
Edit
paquet.xml
Edit
prive
Editing: orthotypo_fonctions.php
<?php /** * Plugin Ortho-Typographie * (c) 2013 cedric * Licence GNU/GPL */ if (!defined('_ECRIRE_INC_VERSION')) { return; } include_spip('inc/config'); /** * Ajouter la CSS des guillemets si active * @param $flux * @return string */ function orthotypo_insert_head_css($flux) { $config = lire_config('orthotypo/'); if ($config['guillemets'] ?? 'on') { $flux .= '<link rel="stylesheet" type="text/css" href="' . find_in_path('css/typo_guillemets.css') . '" media="all" />' . "\n"; } return $flux; } /** * Post-typo : corrections selon les fonctions activees * @param $texte * @return mixed|string */ function orthotypo_post_typo($texte) { static $config; if (is_null($config)) { $config = lire_config('orthotypo/'); } if ($config['guillemets'] ?? 'on') { $texte = orthotypo_guillemets_post_typo($texte); } // mois avant les exposants car on y match des "1er mars" if ($config['mois'] ?? 'on') { $texte = orthotypo_mois_post_typo($texte); } // a optimiser : represente +60% du temps de calcul total des 4 fonctions if ($config['exposants'] ?? 'on') { $texte = orthotypo_exposants_post_typo($texte); } if ($config['caps'] ?? 'on') { $texte = orthotypo_caps_post_typo($texte); } if ($config['fines'] ?? 'on') { $texte = orthotypo_espaces_fines_post_typo($texte); } $texte = orthotypo_points_medians_accessibles($texte); return $texte; } // Fonctions de traitement sur #TEXTE function orthotypo_pre_typo($texte) { static $config; if (is_null($config)) { $config = lire_config('orthotypo/'); } if ( isset($config['corrections']) && $config['corrections'] && isset($config['corrections_regles']) && $config['corrections_regles'] ) { $texte = orthotypo_corrections_pre_typo($texte); } return $texte; } /** * evite les transformations typo dans les balises $balises * par exemple pour <html>, <cadre>, <code>, <frame>, <script>, <acronym> et <cite>, $balises = 'html|code|cadre|frame|script|acronym|cite' * * @param $texte * $texte a filtrer * @param $filtre * le filtre a appliquer pour transformer $texte * si $filtre = false, alors le texte est retourne protege, sans filtre * @param $balises * balises concernees par l'echappement * si $balises = '' alors la protection par defaut est sur les balises de _PROTEGE_BLOCS * si $balises = false alors le texte est utilise tel quel * @param null|array $args * arguments supplementaires a passer au filtre * @return string */ function orthotypo_filtre_texte_echappe($texte, $filtre, $balises = '', $args = null) { if ((string) $texte === '') { return ''; } if ($filtre !== false) { $fonction = chercher_filtre($filtre, false); if (!$fonction) { spip_log("orthotypo_filtre_texte_echappe() : $filtre() non definie", _LOG_ERREUR); return $texte; } $filtre = $fonction; } // Échapper aussi les |@...@| https://git.spip.net/spip-contrib-extensions/orthotypo/issues/3 if (strpos($texte, '|@') !== false) { $texte = preg_replace('#@\|[A-Z]+[a-f0-9]{7}\|[A-Za-z0-9+/]+=*\|@#U', '<orthotypo $0>', $texte); } // protection du texte // Perf : Ne pas rentrer dans le coûteux processus d'échappement si rien à échapper if ($balises !== false && strstr($texte, '<') === false) { if ((string) $balises === '') { $balises = _PROTEGE_BLOCS;//'html|pre|code|cadre|frame|script|style'; } else { $balises = ',<(' . $balises . ')(\s[^>]*)?>(.*)</\1>,UimsS'; } if (!function_exists('echappe_html')) { include_spip('inc/texte_mini'); } $texte = echappe_html($texte, 'FILTRETEXTECHAPPE', true, $balises); } // retour du texte simplement protege if ($filtre === false) { return $texte; } // transformation par $fonction : on split le texte pour ne pas filtrer les <balises ...> ou </balises> html elle meme if (strpos($texte, '<') !== false) { if ($parts = preg_split(',(</?\w+>|<\w+\s[^>]*>),Uims', $texte, -1, PREG_SPLIT_DELIM_CAPTURE)) { $partsCount = count($parts); for ($i = 0; $i < $partsCount; $i += 2) { if ($parts[$i] !== '') { if (!$args) { $parts[$i] = $filtre($parts[$i]); } else { array_unshift($args, $parts[$i]); $parts[$i] = $filtre(...$args); array_shift($args); } } } } $texte = implode($parts); } elseif (!$args) { $texte = $filtre($texte); } else { array_unshift($args, $texte); $texte = $filtre(...$args); } // deprotection des balises $texte = echappe_retour($texte, 'FILTRETEXTECHAPPE'); return preg_replace('/<orthotypo (.*)>/mU', '$1', $texte); } function orthotypo_echappe_balises_html($texte) { // prudence : on protege le contenu de toute balise html if (strpos($texte, '<') !== false) { // tout #$texte = preg_replace_callback(',<[^>]*>,UmsS', 'orthotypo_echappe_balise_html', $texte); // dangereux uniquement $texte = preg_replace_callback(',<\w+\b[^>]+>,UmsS', 'orthotypo_echappe_balise_html', $texte); } return $texte; } function orthotypo_echappe_balise_html($m) { if (strpos($m[0], 'class="base64') !== false) { return $m[0]; } return code_echappement($m[0], 'FILTRETEXTECHAPPE', true, 'span'); } /* ********************************************************************************************************************* * Guillemets * merge de * - https://zone.spip.org/trac/spip-zone/browser/_plugins_/typo_guillemets/typo_guillemets_fonctions.php?rev=54676 * - https://zone.spip.org/trac/spip-zone/browser/_plugins_/couteau_suisse/outils/guillemets.php?rev=64721 */ /* Fichier de formatage typographique des guillemets, par Vincent Ramos <www-lansargues AD kailaasa POINT net>, sous licence GNU/GPL. Ne sont touchees que les paires de guillemets. Le formatage des guillemets est tire de <http://en.wikipedia.org/wiki/Quotation_mark%2C_non-English_usage> Certains des usages indiques ne correspondent pas a ceux que la barre d'insertion de caracteres speciaux de SPIP propose. Les variables suivies du commentaire LRTEUIN sont confirmees par le _Lexique des regles typographiques en usage a l'Imprimerie nationale_. Les variables entierement commentees sont celles pour lesquelles aucune information n'a ete trouvee. Par defaut, les guillements sont alors de la forme “mot”, sauf si la barre d'insertion de SPIP proposait deja une autre forme. Version optimisee par Patrice Vanneufville (2007) cf https://contrib.spip.net/?article1592 */ // voir aussi : http://trac.rezo.net/trac/spip/changeset/9429 // definitions des chaines de remplacement define('_GUILLEMETS_defaut', '“$1”'); define('_GUILLEMETS_fr', '« $1 »'); //LRTEUIN //define('_GUILLEMETS_ar', ''); define('_GUILLEMETS_bg', '„$1“'); //define('_GUILLEMETS_br', ''); //define('_GUILLEMETS_bs', ''); define('_GUILLEMETS_ca', '«$1»'); define('_GUILLEMETS_cpf', '« $1 »'); //define('_GUILLEMETS_cpf_hat', ''); define('_GUILLEMETS_cs', '„$1“'); define('_GUILLEMETS_da', '»$1«'); define('_GUILLEMETS_de', '„$1“'); //ou "»$1«" // LRTEUIN define('_GUILLEMETS_en', '“$1”'); //LRTEUIN define('_GUILLEMETS_eo', '«$1»'); define('_GUILLEMETS_es', '«$1»'); //define('_GUILLEMETS_eu', ''); //define('_GUILLEMETS_fa', ''); //define('_GUILLEMETS_fon', ''); //define('_GUILLEMETS_gl', ''); define('_GUILLEMETS_hu', '„$1”'); define('_GUILLEMETS_it', '«$1»'); define('_GUILLEMETS_it_fem', '«$1»'); define('_GUILLEMETS_ja', '「$1」'); //define('_GUILLEMETS_lb', ''); define('_GUILLEMETS_nl', '„$1”'); //define('_GUILLEMETS_oc_auv', ''); //define('_GUILLEMETS_oc_gsc', ''); //define('_GUILLEMETS_oc_lms', ''); //define('_GUILLEMETS_oc_lnc', ''); //define('_GUILLEMETS_oc_ni', ''); //define('_GUILLEMETS_oc_ni_la', ''); //define('_GUILLEMETS_oc_prv', ''); //define('_GUILLEMETS_oc_va', ''); define('_GUILLEMETS_pl', '„$1”'); define('_GUILLEMETS_pt', '«$1»'); define('_GUILLEMETS_pt_br', '«$1»'); define('_GUILLEMETS_ro', '„$1”'); define('_GUILLEMETS_ru', '«$1»'); define('_GUILLEMETS_tr', '«$1»'); //define('_GUILLEMETS_vi', ''); define('_GUILLEMETS_zh', '「$1」'); // ou "“$1”" en chinois simplifie function orthotypo_guillemets_echappe_balises_callback($matches) { if (strpos($matches[1], 'class="base64') === false) { $matches[1] = code_echappement($matches[1], 'GUILL', true, 'span'); } return str_replace('"', "'", $matches[1]); } function orthotypo_guillemets_rempl($texte) { // on s'en va si pas de guillemets... if (strpos($texte, '"') === false) { return $texte; } // prudence : on protege TOUTES les balises contenant des doubles guillemets droits if (strpos($texte, '<') !== false) { $texte = preg_replace_callback('/(<[^>]+"[^>]*>)/Ums', 'orthotypo_guillemets_echappe_balises_callback', $texte); } // si le texte ne contient pas de guillemets droits // ou s'il contient deja des guillemets élaborés // on ne touche pas if ( strpos($texte, '"') !== false && (strpos($texte, '«') === false) && (strpos($texte, '»') === false) && (strpos($texte, '“') === false) && (strpos($texte, '”') === false) ) { // choix de la langue, de la constante et de la chaine de remplacement $lang = $GLOBALS['lang_objet'] ?? $GLOBALS['spip_lang']; $constante = '_GUILLEMETS_' . $lang; $guilles = defined($constante) ? constant($constante) : _GUILLEMETS_defaut; // Remplacement des autres paires de guillemets (et suppression des espaces apres/avant) // Et retour des balises contenant des doubles guillemets droits $texte = preg_replace('/"\s*(.*?)\s*"/', $guilles, $texte); } return echappe_retour($texte, 'GUILL'); } function orthotypo_guillemets_post_typo($texte) { if (strpos($texte, '"') !== false) { $texte = orthotypo_filtre_texte_echappe($texte, 'orthotypo_guillemets_rempl', 'html|code|cadre|frame|script|acronym|cite'); } return $texte; } function orthotypo_espaces_fines_post_typo($texte) { if (strpos($texte, ' ') !== false) { $texte = orthotypo_filtre_texte_echappe($texte, 'orthotypo_espaces_fines_post_rempl'); } return $texte; } function orthotypo_espaces_fines_post_rempl($t = '') { $nbsp = "\xc2\xa0"; $fine = '<small class="fine d-inline">' . $nbsp . '</small>'; $t = str_replace( [ ' »', '« ', ' ?', ' ;', ' !', ' %', ' ', ], [ "$fine\xc2\xbb", "\xc2\xab$fine", "$fine?", "$fine;", "$fine!", "$fine%", $nbsp, ], $t ); // CKEditor double les fines chaque fois que l'on passe en mode source puis retour while (strpos($t, $fine . $fine) !== false) { $t = str_replace($fine . $fine, $fine, $t); } return $t; } /* ********************************************************************************************************************* * Exposants * Merge de * - https://zone.spip.org/trac/spip-zone/browser/_plugins_/typo_exposants/typo_exposants_fonctions.php?rev=61523 * - https://zone.spip.org/trac/spip-zone/browser/_plugins_/couteau_suisse/outils/typo_exposants.php?rev=63425 */ // Filtre typographique exposants pour langue francaise // serieuse refonte 2006 : Patrice Vanneufville // Toutes les infos sur : https://contrib.spip.net/?article1564 // TODO : raccourci pour les exposants et indices (Pouce^2 ou Pouce^2^, H_2O ou H_2_O ou H,,2,,O // exemple : https://zone.spip.org/trac/spip-zone/wiki/WikiFormatting include_spip('inc/charsets'); if (!defined('_TYPO_class')) { define('_TYPO_class', '<sup class="typo_exposants">'); } if (!defined('_TYPO_sup')) { define('_TYPO_sup', _TYPO_class . '\\1</sup>'); } if (!defined('_TYPO_sup2')) { define('_TYPO_sup2', '\\1' . _TYPO_class . '\\2</sup>'); } // cette fonction ne fonctionne que pour l'anglais // elle n'est pas appelee dans les balises html : html|code|cadre|frame|script|acronym|cite function orthotypo_exposants_en($texte) { static $typo; if (!$typo) { $typo = [ [ ',(?<=1)(st)\b,', ',(?<=2)(nd)\b,', ',(?<=3)(rd)\b,', ',(?<=\d)(th)\b,', ',(?<=m)([23])\b,', // m² m³ ], [ _TYPO_sup, _TYPO_sup, _TYPO_sup, _TYPO_sup, _TYPO_sup, ] ]; } return preg_replace($typo[0], $typo[1], $texte); } // cette fonction ne fonctionne que pour le francais // elle n'est pas appelee dans les balises html : html|code|cadre|frame|script|acronym|cite function orthotypo_exposants_fr($texte) { static $typo = null; static $egrave; static $eaigu1; static $eaigu2; static $accents; if (is_null($typo)) { $u = isset($GLOBALS['meta']['charset']) ? ($GLOBALS['meta']['charset'] == 'utf-8' ? 'u' : '') : ''; // en principe, pas besoin de : caractere_utf_8(232) $carre = unicode2charset('²') . '|²|²'; $egrave = unicode2charset('è') . '|è|è'; $eaigu1 = unicode2charset('é') . '|é|é'; $eaigu2 = unicode2charset('É') . '|É|É'; $accents = unicode2charset('àáâäåæèéêëìíîïòóôöùúûü'); $typo = [ // Mlle(s), Mme(s) // Mme(s) et Mgr '/\bM(gr|mes?)\b/u' => 'M' . _TYPO_sup, '/\bM(lles?)\b/u' => 'M' . _TYPO_sup, // Dr, Pr suivis d'un espace d'un point ou d'un tiret '/\b([DP])(r)(?=[\s\.-])/u' => _TYPO_sup2, // m2 "/\bm(?:$carre)\b/" => 'm' . _TYPO_class . '2</sup>', // m2, m3 '/\bm([23])\b/u' => 'm' . _TYPO_sup, // millions, milliards '/\b([\s\d][Mm])([nd]s?)\b/u' => _TYPO_sup2, // Vve '/\bV(ve)\b/' => 'V' . _TYPO_sup, // Cie(s) '/\bC(ies?)\b/u' => 'C' . _TYPO_sup, // Societes(s), Etablissements "/\bS(t(?:$eaigu1)s?)(?=\W)/$u" => 'S' . _TYPO_sup, "/(?<=\W)(?:E|$eaigu2)ts\b/$u" => 'É' . _TYPO_class . 'ts</sup>', // 1er(s), Erreurs 1ier(s), 1ier(s) '/(?<=\b[1I])i?(ers?)\b/u' => _TYPO_sup, "/(?<=\b[1I])i?(?:e|$egrave)(res?)\b/$u" => _TYPO_sup, // Erreurs 1(i)ere(s) + accents '/(?<=\b1)(r?es?)\b/u' => _TYPO_sup, // 1e(s), 1re(s) '/(?<=\b2)n?(de?s?)\b/u' => _TYPO_sup, // 2nd(e)(s) // Erreurs (i)(e)me(s) + accents "/(\b[0-9IVX]+)i?(?:e|$egrave)?me(s?)\b/$u" => '$1' . _TYPO_class . 'e$2</sup>', // 2e(s), IIIe(s)... (les 1(e?r?s?) ont deja ete remplaces) '/\b([0-9IVX]+)(es?)\b/u' => _TYPO_sup2, // recto, verso, primo, secondo, etc. "/(?<![;$accents])\b(\d+|r|v)o\b/$u" => '$1' . _TYPO_class . 'o</sup>', // Maitre (suivi d'un espace et d'une majuscule) '/\bM(e)(?= [A-Z])/u' => 'M' . _TYPO_sup, ]; $typo = [array_keys($typo),array_values($typo)]; } return preg_replace($typo[0], $typo[1], $texte); } function orthotypo_exposants_echappe_balises_callback($matches) { return code_echappement($matches[1], 'EXPO', true, 'span'); } function orthotypo_exposants_post_typo($texte) { $lang = empty($GLOBALS['lang_objet']) ? $GLOBALS['spip_lang'] : $GLOBALS['lang_objet']; if (function_exists($fonction = 'orthotypo_exposants_' . lang_typo($lang))) { $texte = orthotypo_filtre_texte_echappe($texte, $fonction, 'html|code|cadre|frame|script|acronym|cite'); return echappe_retour($texte, 'EXPO'); } return $texte; } /* ********************************************************************************************************************* * Typo des Mois : espace insecable entre le numero du jour et le mois : 12 Mars => 12 Mars * Tire de * - https://zone.spip.org/trac/spip-zone/browser/_plugins_/typo_mois/typo_mois_fonctions.php?rev=43239 * avec ameliorations : * - prise en compte des echappements de balise * - prise en compte de la langue */ function orthotypo_mois_rempl($texte) { static $typo = []; $lang = $GLOBALS['spip_lang']; if (!isset($typo[$lang])) { $typo[$lang] = []; for ($m = 1; $m <= 12; $m++) { $typo[$lang][] = _T('date_mois_' . $m); } $pre1 = _T('date_jnum1'); $pre2 = _T('date_jnum2'); $pre3 = _T('date_jnum3'); // si on est en _AUTOBR desactive, on accepte un retour ligne entre le chiffre et le mois (mais pas 2=paragraphe) // sinon on accepte pas de retours lignes du tout $space = ((defined('_AUTOBR') && !_AUTOBR) ? "(?:[ \t]*(?:\r\n|\r|\n))?[ \t]*" : "[ \t]+"); $typo[$lang] = ",([1-3]?[0-9]|$pre1|$pre2|$pre3)$space+(" . implode('|', $typo[$lang]) . ')\b,UimsS'; include_spip('inc/charsets'); $typo[$lang] = unicode2charset(html2unicode($typo[$lang])); } return preg_replace($typo[$lang], '\1 \2', $texte); } function orthotypo_mois_post_typo($texte) { if (strpbrk($texte, '123456789') !== false) { $texte = orthotypo_filtre_texte_echappe($texte, 'orthotypo_mois_rempl', 'html|code|cadre|frame|script|acronym|cite'); } return $texte; } /* ********************************************************************************************************************* * Typo des Caps : espace insecable entre le numero du jour et le mois : 12 Mars => 12 Mars * Tire de * - https://zone.spip.org/trac/spip-zone/browser/_plugins_/typo_caps/typo_caps_fonctions.php?rev=43238 * avec ameliorations : * - prise en compte des echappements de balise */ /* code tire de typogrify * http://jeffcroft.com/sidenotes/2007/may/29/typogrify-easily-produce-web-typography-doesnt-suc/ */ /** * This is necessary to keep dotted cap strings to pick up extra spaces * used in preg_replace_callback later on */ function orthotypo_caps_replace_callback($matchobj) { if (!empty($matchobj[2])) { return sprintf('<span class="caps">%s</span>', $matchobj[2]); } else { $mthree = $matchobj[3]; if (($mthree[strlen($mthree) - 1]) == ' ') { $caps = substr($mthree, 0, -1); $tail = ' '; } else { $caps = $mthree; $tail = ''; } return sprintf('<span class="caps">%s</span>%s', $caps, $tail); } } function orthotypo_caps_rempl($texte) { static $cap_finder; if (is_null($cap_finder)) { $cap_finder = "/( (\b[A-Z\d]* # Group 2: Any amount of caps and digits [A-Z]\d*[A-Z] # A cap string must at least include two caps (but they can have digits between them) [A-Z\d]*\b) # Any amount of caps and digits | (\b[A-Z]+\.\s? # OR: Group 3: Some caps, followed by a '.' and an optional space (?:[A-Z]+\.\s?)+) # Followed by the same thing at least once more (?:\s|\b|$))/xS"; } $texte = orthotypo_echappe_balises_html($texte); return preg_replace_callback($cap_finder, 'orthotypo_caps_replace_callback', $texte); } function orthotypo_caps_post_typo($texte) { return orthotypo_filtre_texte_echappe($texte, 'orthotypo_caps_rempl', 'html|code|cadre|frame|script|acronym|cite'); } /* ********************************************************************************************************************* * Outil Correction auto tiree de la lame insertion du CS */ // cette fonction appelee automatiquement a chaque affichage de la page privee du Couteau Suisse renvoie un tableau function orthotypo_corrections_regles() { $str = []; $preg = []; $regles = trim(lire_config('orthotypo/corrections_regles')); if (strlen($regles) !== 0) { $liste = preg_split("/[\r\n]+/", $regles); foreach ($liste as $l) { [$a, $b] = explode('=', $l, 2); $a = trim($a); $b = trim($b); if (!strlen($a) || preg_match('/^(#|\/\/)/', $a)) { // remarques ou vide } elseif (preg_match('/^\((.+)\)$/', $a, $reg)) { // les mots seuls $preg[0][] = '/\b' . $reg[1] . '\b/'; $preg[1][] = $b; } elseif (preg_match('/^(\/.+\/[imsxuADSUX]*)$/', $a)) { // expressions regulieres $preg[0][] = $a; $preg[1][] = $b; } elseif (strlen($a) !== 0) { // simples remplacements $str[0][] = $a; $str[1][] = $b; } } } return [$str, $preg]; } // cette fonction n'est pas appelee dans les balises html : html|code|cadre|frame|script function orthotypo_corrections_rempl($texte) { static $str,$preg; if (is_null($str)) { [$str, $preg] = orthotypo_corrections_regles(); } $texte = orthotypo_echappe_balises_html($texte); if ($str !== []) { $texte = str_replace($str[0], $str[1], $texte); } if ($preg !== []) { $texte = preg_replace($preg[0], $preg[1], $texte); } return $texte; } /** * Point médian encapsulé dans span aria-hidden='true' * Voir https://legothequeabf.wordpress.com/2017/11/07/recommandations-pour-une-ecriture-inclusive-et-accessible/ * @param string $texte; * @return string $texte. **/ function orthotypo_points_medians_accessibles_rempl($texte) { return str_replace('·', '<span aria-hidden=\'true\'>·</span>', $texte); } function orthotypo_points_medians_accessibles($texte) { if (strpos($texte, '·') !== false) { $texte = orthotypo_filtre_texte_echappe($texte, 'orthotypo_points_medians_accessibles_rempl'); } return $texte; } // Fonctions de traitement sur #TEXTE function orthotypo_corrections_pre_typo($texte) { return orthotypo_filtre_texte_echappe($texte, 'orthotypo_corrections_rempl'); }