Browse Source

Retour d'un plugin de Sommaire automatique, heritier de feu http://zone.spip.org/trac/spip-zone/browser/_grenier_/ancres_intertitres tire de http://contrib.spip.net/Sommaire-de-l-article

ainsi que de la lame sommaire du couteau suisse

Fonctionnement :
Par configuration on peut choisir de : ne jamais inserer automatiquement le sommaire dans le texte de l'article, l'inserer à la demande uniquement, en presence du reccourci <sommaire>, l'inserer toujours
Le plugin fournit egalement les outils pour afficher le sommaire depuis les squelettes :
#SOMMAIRE{#TEXTE} affiche le sommaire correspondant aux intertitres de #TEXTE, en prenant soin d'eviter toute duplication des notes
[(#TEXTE|ancres_sommaire)] ajoute les ancres sur les intertitres complementaires du sommaire
[(#TEXTE|retire_sommaire)] retire le sommaire eventuellement ajoute automatiquement a un #TEXTE
[(#TEXTE|retire_ancres_sommaire)] retire les ancres sur les intertitres ajoutees automatiquement a un #TEXTE

Le plugin ajoute automatiquement la css css/sommaire.css surchargeable dans le squelette
Le sommaire est construit a partir de modeles/sommaire.html qui reçoit la hierarchie complète des titres, charge a lui de n'afficher qu'un niveau ou de tronquer les titres si besoin dans le sommaire.
svn/root/tags/v1.2.5
cedric@yterium.com 10 years ago
commit
058a3bd491
  1. 15
      .gitattributes
  2. BIN
      css/img/sommaire-up-16.png
  3. 5
      css/sommaire.css
  4. 45
      formulaires/configurer_sommaire.html
  5. 14
      lang/paquet-sommaire_fr.php
  6. 31
      lang/sommaire_fr.php
  7. 8
      modeles/sommaire.html
  8. 24
      paquet.xml
  9. 7
      prive/squelettes/contenu/configurer_sommaire.html
  10. 18
      prive/style_prive_plugin_sommaire.html
  11. BIN
      prive/themes/spip/images/sommaire-128.png
  12. BIN
      prive/themes/spip/images/sommaire-32.png
  13. BIN
      prive/themes/spip/images/sommaire-64.png
  14. BIN
      prive/themes/spip/images/sommaire-up-16.png
  15. 271
      sommaire_fonctions.php

15
.gitattributes vendored

@ -0,0 +1,15 @@
* text=auto !eol
css/img/sommaire-up-16.png -text
css/sommaire.css -text
formulaires/configurer_sommaire.html -text
lang/paquet-sommaire_fr.php -text
lang/sommaire_fr.php -text
modeles/sommaire.html -text
/paquet.xml -text
prive/squelettes/contenu/configurer_sommaire.html -text
prive/style_prive_plugin_sommaire.html -text
prive/themes/spip/images/sommaire-128.png -text
prive/themes/spip/images/sommaire-32.png -text
prive/themes/spip/images/sommaire-64.png -text
prive/themes/spip/images/sommaire-up-16.png -text
/sommaire_fonctions.php -text

BIN
css/img/sommaire-up-16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

5
css/sommaire.css

@ -0,0 +1,5 @@
.nav-sommaire {border: 1px solid #eee;margin-left: 30%;margin-bottom: 1.5em;}
.nav-sommaire h2 {font-size: inherit;text-transform: uppercase;}
.nav-sommaire ul {}
a.sommaire-back {color:#DDD;display:block;width:16px;height:16px;background:url(img/sommaire-up-16.png) no-repeat center;float: right;opacity:0.5;}

45
formulaires/configurer_sommaire.html

@ -0,0 +1,45 @@
<div class="formulaire_spip formulaire_configurer formulaire_#FORM">
<h3 class="titrem"><:sommaire:cfg_titre_parametrages:></h3>
[<p class="reponse_formulaire reponse_formulaire_ok">(#ENV*{message_ok})</p>]
[<p class="reponse_formulaire reponse_formulaire_erreur">(#ENV*{message_erreur})</p>]
<form method="post" action="#ENV{action}">
<div>
#ACTION_FORMULAIRE{#ENV{action}}
<input type="hidden" name="_meta_table" value="meta" />
#SET{fl,sommaire}
<ul>
#SET{name,sommaire_automatique}#SET{obli,''}#SET{defaut,'on'}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}}
<li class="editer editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]">
<label>[(#GET{fl}|concat{':label_',#GET{name}}|_T)]</label>[
<span class='erreur_message'>(#GET{erreurs})</span>
]
#SET{val,off}
<div class="choix">
<input type="radio" name="#GET{name}" class="radio" id="#GET{name}_#GET{val}" value="#GET{val}"[(#ENV{#GET{name},#GET{defaut}}|=={#GET{val}}|oui)checked="checked"] />
<label for="#GET{name}_#GET{val}">[(#GET{fl}|concat{':label_',#GET{name},'_',#GET{val}}|_T)]</label>
<p class="explication"><:sommaire:explication_sommaire_automatique_off:></p>
<br/>
</div>
#SET{val,ondemand}
<div class="choix">
<input type="radio" name="#GET{name}" class="radio" id="#GET{name}_#GET{val}" value="#GET{val}"[(#ENV{#GET{name},#GET{defaut}}|=={#GET{val}}|oui)checked="checked"] />
<label for="#GET{name}_#GET{val}">[(#GET{fl}|concat{':label_',#GET{name},'_',#GET{val}}|_T)]</label>
<p class="explication"><:sommaire:explication_sommaire_automatique_ondemand:></p>
<br/>
</div>
#SET{val,on}
<div class="choix">
<input type="radio" name="#GET{name}" class="radio" id="#GET{name}_#GET{val}" value="#GET{val}"[(#ENV{#GET{name},#GET{defaut}}|=={#GET{val}}|oui)checked="checked"] />
<label for="#GET{name}_#GET{val}">[(#GET{fl}|concat{':label_',#GET{name},'_',#GET{val}}|_T)]</label>
</div>
</li>
</ul>
<p class="boutons"><span class="image_loading">&nbsp;</span><input type="submit" class="submit" value="<:bouton_enregistrer:>" /></p>
</div>
</form>
</div>

14
lang/paquet-sommaire_fr.php

@ -0,0 +1,14 @@
<?php
// This is a SPIP language file -- Ceci est un fichier langue de SPIP
if (!defined('_ECRIRE_INC_VERSION')) return;
$GLOBALS[$GLOBALS['idx_lang']] = array(
// S
'sommaire_description' => 'Générer un sommaire automatique pour les articles.',
'sommaire_nom' => 'Sommaire automatique',
'sommaire_slogan' => 'Un sommaire pour vos articles',
);
?>

31
lang/sommaire_fr.php

@ -0,0 +1,31 @@
<?php
// This is a SPIP language file -- Ceci est un fichier langue de SPIP
if (!defined('_ECRIRE_INC_VERSION')) return;
$GLOBALS[$GLOBALS['idx_lang']] = array(
// S
'sommaire_titre' => 'Sommaire automatique',
// C
'cfg_exemple' => 'Exemple',
'cfg_exemple_explication' => 'Explication de cet exemple',
'cfg_titre_parametrages' => 'Paramétrages',
// L
'label_sommaire_automatique' => 'Insertion du sommaire d\'article',
'label_sommaire_automatique_off' => 'Aucune insertion dans le texte des articles',
'explication_sommaire_automatique_off' => 'Le sommaire est inséré dans le squelette par le webmestre.',
'label_sommaire_automatique_ondemand' => 'Insertion dans le texte des articles à la demande',
'explication_sommaire_automatique_ondemand' => 'Le sommaire est inséré uniquement en présence du raccourci <tt>&lt;sommaire&gt;</tt> dans le texte des articles.',
'label_sommaire_automatique_on' => 'Insertion automatique sur tous les articles',
// T
'titre_page_configurer_sommaire' => 'Sommaire automatique',
'titre_retour_sommaire' => 'Retour au sommaire',
'titre_cadre_sommaire' => 'Sommaire',
);
?>

8
modeles/sommaire.html

@ -0,0 +1,8 @@
<div class="well nav-sommaire">
<h2><:sommaire:titre_cadre_sommaire:></h2>
<B_somm>
<BOUCLE_somm(POUR){tableau #ENV{sommaire}}>
-[(#VAL{*}|str_pad{#VALEUR{niveau},'*'})] [#VALEUR{id}<-][#VALEUR{titre}->#VALEUR{href}]</BOUCLE_somm>
</B_somm>
</div>
#FILTRE{propre}

24
paquet.xml

@ -0,0 +1,24 @@
<paquet
prefix="sommaire"
categorie="edition"
version="1.0.3"
etat="test"
compatibilite="[3.0.0;3.0.*]"
logo="prive/themes/spip/images/sommaire-64.png"
documentation=""
>
<nom>Sommaire automatique</nom>
<!-- cette balise peut être présente plusieurs fois s'il y a plusieurs auteurs -->
<auteur lien="http://contrib.spip.net/auteur5384">Cédric</auteur>
<credit lien="http://contrib.spip.net/auteur6809">James</credit>
<credit lien="http://contrib.spip.net/auteur5714">Patrice Vanneufville</credit>
<credit lien="http://contrib.spip.net/auteur83">NoPlay</credit>
<licence>GNU/GPL</licence>
<pipeline nom="declarer_tables_interfaces" inclure="sommaire_fonctions.php" />
<pipeline nom="insert_head_css" inclure="sommaire_fonctions.php" />
</paquet>

7
prive/squelettes/contenu/configurer_sommaire.html

@ -0,0 +1,7 @@
[(#AUTORISER{configurer,_sommaire}|sinon_interdire_acces)]
<h1 class="grostitre"><:sommaire:titre_page_configurer_sommaire:></h1>
<div class="ajax">
#FORMULAIRE_CONFIGURER_SOMMAIRE
</div>

18
prive/style_prive_plugin_sommaire.html

@ -0,0 +1,18 @@
[(#REM)
Ce squelette definit les styles de l'espace prive
Note: l'entete "Vary:" sert a repousser l'entete par
defaut "Vary: Cookie,Accept-Encoding", qui est (un peu)
genant en cas de "rotation du cookie de session" apres
un changement d'IP (effet de clignotement).
ATTENTION: il faut absolument le charset sinon Firefox croit que
c'est du text/html !
<style>
]
#wysiwyg .nav-sommaire {border: 1px solid #eee;margin-left: 30%;margin-bottom: 1.5em;}
#wysiwyg .nav-sommaire h2 {background: #eee;font-size: inherit;text-transform: uppercase;padding:0.5em;}
#wysiwyg .nav-sommaire ul {}
a.sommaire-back {color:#DDD;display:block;width:16px;height:16px;background:url(#CHEMIN_IMAGE{sommaire-up-16.png}) no-repeat center;float: #ENV{right};opacity:0.5;}

BIN
prive/themes/spip/images/sommaire-128.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
prive/themes/spip/images/sommaire-32.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
prive/themes/spip/images/sommaire-64.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
prive/themes/spip/images/sommaire-up-16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

271
sommaire_fonctions.php

@ -0,0 +1,271 @@
<?php
/**
* Plugin Sommaire automatique
* (c) 2013 Cédric
* Licence GNU/GPL
*/
if (!defined('_ECRIRE_INC_VERSION')) return;
/**
* Filtre |retire_sommaire
* pour retirer le sommaire automatique et les ancres d'un texte
* @param string $texte
* @return string
*/
function retire_sommaire($texte){
// retirer le sommaire
if (strpos($texte,"<!--sommaire-->")!==false)
$texte = preg_replace(",<!--sommaire-->.*<!--/sommaire-->,Uims","",$texte);
return $texte;
}
/**
* Filtre |retire_ancres_sommaire
* pour retirer les ancres vers le sommaire qui aont ete ajoutee automatiquement sur un texte
* @param $texte
* @return mixed
*/
function retire_ancres_sommaire($texte){
// retirer les liens de retour au sommaire
if (strpos($texte,"sommaire-back")!==false)
$texte = preg_replace(",<a class='sommaire-back'[^>]*></a>,Uims","",$texte);
return $texte;
}
/**
* Filtre |ancres_sommaire
* pour ajouter les ancres de sommaire du les intertitres d'un texte
* @param string $texte
* @return string
*/
function ancres_sommaire($texte){
$texte = sommaire_post_propre($texte, false);
return $texte;
}
/**
* Balise #SOMMAIRE pour afficher le sommaire d'un contenu
* #SOMMAIRE{#TEXTE}
* gere les notes pour eviter leur doublement
*
* @param $p
* @return mixed
*/
function balise_SOMMAIRE_dist($p){
$_texte = interprete_argument_balise(1,$p);
$p->code = "sommaire_empile_note().affiche_sommaire($_texte).sommaire_depile_note()";
$p->interdire_scripts = false; // le contenu vient d'un modele
return $p;
}
/*
* Protected
*/
function sommaire_insert_head_css($flux){
$flux .= '<link rel="stylesheet" type="text/css" href="'.find_in_path('css/sommaire.css').'"/>'."\n";
return $flux;
}
/**
* Affiche le sommaire d'un texte
* @param string $texte
* @return string
*/
function affiche_sommaire($texte){
// retirer le(s) sommaire(s) eventuel(s) deja la avant de re-calculer le sommaire
return sommaire_post_propre(retire_sommaire($texte), $ajoute=true, $sommaire_seul=true);
}
/**
* Empile les notes avant evaluation du texte sur lequel est calcule #SOMMAIRE
* @return string
*/
function sommaire_empile_note(){$notes = charger_fonction('notes','inc');$notes('','empiler');return '';}
/**
* Depile les notes apres calcul de #SOMMAIRE
* @return string
*/
function sommaire_depile_note(){$notes = charger_fonction('notes','inc');$notes('','depiler');return '';}
/**
* Ajouter le calcul du sommaire automatique sur les textes d'article
* @param $interfaces
* @return mixed
*/
function sommaire_declarer_tables_interfaces($interfaces){
$traitement = $interfaces['table_des_traitements']['TEXTE'][0];
if (isset($interfaces['table_des_traitements']['TEXTE']['articles']))
$traitement = $interfaces['table_des_traitements']['TEXTE']['articles'];
$traitement = str_replace("propre(","sommaire_propre(",$traitement);
$interfaces['table_des_traitements']['TEXTE']['articles']= $traitement;
return $interfaces;
}
function sommaire_propre($texte, $connect, $env){
$texte = propre($texte,$connect,$env);
if (
!isset($GLOBALS['meta']['sommaire_automatique'])
OR $GLOBALS['meta']['sommaire_automatique']=="on"
OR ($GLOBALS['meta']['sommaire_automatique']=="ondemand" AND strpos($texte,"<sommaire>")!==false)
){
$texte = sommaire_post_propre($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 sommaire_filtre_texte_echappe($texte, $filtre, $balises='', $args=NULL){
if(!strlen($texte)) return '';
if ($filtre!==false){
$fonction = chercher_filtre($filtre,false);
if (!$fonction) {
spip_log("sommaire_filtre_texte_echappe() : $filtre() non definie",_LOG_ERREUR);
return $texte;
}
$filtre = $fonction;
}
// protection du texte
if($balises!==false) {
if(!strlen($balises)) $balises = _PROTEGE_BLOCS;//'html|code|cadre|frame|script';
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
if (!$args)
$texte = $filtre($texte);
else {
array_unshift($args,$texte);
$texte = call_user_func_array($filtre, $args);
}
// deprotection des balises
return echappe_retour($texte, 'FILTRETEXTECHAPPE');
}
function sommaire_filtre($texte, $ajoute=true, $sommaire_seul=false){
$sommaire = sommaire_recenser($texte);
if ($ajoute OR $sommaire_seul){
$sommaire = recuperer_fond("modeles/sommaire",array('sommaire'=>$sommaire));
$sommaire = "<!--sommaire-->$sommaire<!--/sommaire-->";
if ($sommaire_seul)
return $sommaire;
if ($p = strpos($texte,"<sommaire>")){
$texte = substr_replace($texte,$sommaire,$p,strlen("<sommaire>"));
}
else
$texte = $sommaire . $texte;
}
return $texte;
}
function sommaire_post_propre($texte, $ajoute=true, $sommaire_seul=false){
if (strpos($texte, '<h')!==false)
$texte = sommaire_filtre_texte_echappe($texte,'sommaire_filtre','html|code|cadre|frame|script|acronym|cite',array($ajoute,$sommaire_seul));
return $texte;
}
// renvoie le sommaire d'une page d'article
// $page=false reinitialise le compteur interne des ancres
function sommaire_recenser(&$texte) {
$sommaire = array();
$ancres_vues = array();
// traitement des intertitres <hx>
preg_match_all(",(<h([123456])[^>]*>)(.*)(</h\\2>),Uims", $texte, $matches,PREG_SET_ORDER);
if (!count($matches))
return $texte;
$debutsommairedejala = strpos($texte,'<!--sommaire-->');
$finsommairedejala = strpos($texte,'<!--/sommaire-->');
// trouver le niveau mini des hn qui consitue le niveau 1 du sommaire
$toplevel = 6;
foreach($matches as $m){
$toplevel = min($toplevel,$m[2]);
if ($toplevel==1) break;
}
#var_dump($toplevel);
$currentpos = 0;
$titleretour = attribut_html(_T('sommaire:titre_retour_sommaire'));
foreach($matches as $m){
if (($pos = strpos($texte, $m[0], $currentpos))!==false
AND ($pos<$debutsommairedejala OR $pos>=$finsommairedejala)) {
$titre = $m[3];
$titre = preg_replace(",</?a\b[^>]*>,Uims","",$titre);
$ancre = sommaire_intertitre_ancre($titre,$m,$ancres_vues);
$ancres_vues[] = $ancre;
$sommaire[] = array('niveau'=>$m[2]-$toplevel+1,'titre'=>$titre,'href'=>"#$ancre",'id'=>"s-$ancre");
$lien_back = "<a class='sommaire-back' href='#s-$ancre' title='$titleretour'></a>";
$h = inserer_attribut($m[1],"id",$ancre).retire_ancres_sommaire($m[3]).$lien_back.$m[4];
$texte = substr_replace($texte,$h,$pos,strlen($m[0]));
$currentpos = $pos + strlen($h);
}
}
#var_dump($sommaire);
return $sommaire;
}
function sommaire_intertitre_ancre($titre, $h, $ancres_vues=array()){
// un id sur le hn deja ?
if ($id = extraire_attribut($h[1],"id"))
return $id;
// generer une ancre a partir du titre
$ancre = trim(textebrut($titre));
$ancre = translitteration($ancre);
$ancre = couper($ancre,80);
$ancre = preg_replace(",\W+,","-",$ancre);
$ancre = trim($ancre,"-");
if (!preg_match(",^[a-z],i",$ancre))
$ancre = "t$ancre";
if (!in_array($ancre,$ancres_vues))
return $ancre;
$md5 = substr(md5($titre),0,4);
if (!in_array("$ancre-$md5",$ancres_vues))
return "$ancre-$md5";
$i = 2;
while (in_array("$ancre-$i",$ancres_vues)){
$i++;
}
return "$ancre-$i";
}
?>
Loading…
Cancel
Save