[spip-dev] fonction couper()

Salut la liste,

je trouve la fonction couper() affreusement compliquée. Et elle ne rend pas toujours le résultat attendu. C’est surtout l’ellipse qui n’apparait pas toujours, même sur des phrases longues qui sont coupées. Du coup on a un rendu assez aléatoire.

J’ai créé la fonction suivante qui me semble plus simple :

/**

  • Couper le texte a une longueur donnée
  • Si le texte est plus long que N caractères
  • alors on retourne les (N-5) premiers caractères
  • afin de prendre en compte l’ellipse finale
    **/
    function couper_propre($chaine,$len,$end=’ (…)’,$encoding=’’) {
    include_spip(‘inc/filtres’);
    // Utiliser l’encodage par défaut (UTF-8 par exemple)
    if (!$encoding) $encoding = $GLOBALS[‘meta’][‘charset’];
    // Ne considérer que le texte brut, sans espace autour
    $chaine = trim(textebrut($chaine));
    // Faut-il réduire cette chaîne ?
    if (strlen($chaine) <= $len) return $chaine;
    // réduisons
    $souschaine = trim(mb_substr($chaine,0,$len,$encoding));
    // Faut-il rajouter une ellipse en fin de chaîne ?
    $offset = strlen(textebrut($end));
    if (strlen($souschaine) >= $len - $offset) $souschaine = trim(mb_substr($souschaine,0,$len-offset,$encoding)) . $end;
    return $souschaine;
    }

Est-ce qu’on ne pourrait pas simplifier la fonction couper() actuelle ?

.Gilles

Pardon, il y a une erreur de typo :
http://pastebin.com/USYiMUjK

c’est mieux

Hello,

C’est plus simple, certes, mais du coup tu évacues tous les cas particuliers foireux qui ont rendu la fonction compliquée pour qu’elle marche du mieux dans tous les cas.

En particulier :

  • couper sur un très long texte qui sans plomber l’empreinte mémoire
  • la prise en compte des

    ,
    qui sont transformés en retour ligne, ce qui a son utilité dans une sortie au format texte

  • la prise en compte des entités html : il faut compter é comme 1 seul caractère et pas comme 7, et surtout ne pas couper au milieu
  • idem sur les caractères utf8 : ne pas les compter pour 2 caractères et ne pas les couper
  • le nettoyage des raccourcis typographiques : il ne faut pas garder les [ ->], ni les {{ }}, {{{ }}} dans le résultat coupé
  • ne pas couper au milieu d’un mot
  • Renvoyer “Bonj (…)” au lieu de “Bonjour” sur un [(#VAL{Bonjour Monsieur}|couper{10})] est assez peu élégant, c’est la raison pour laquelle les ellipses n’apparaissent en général pas sur les petites coupes

Donc oui, la fonction couper est compliquée, mais c’est parce que couper proprement du texte HTML de diverses sources et formats, dans toutes les longueur de coupe possibles, c’est aussi compliqué.

Il suffit de lire attentivement la fonction couper() pour voir tous les cas particuliers qu’elle traite, et à ce titre il ne me semble pas envisageable de remplacer la fonction couper actuelle par la version simplifiée que tu proposes.

Après on peut toujours proposer une seconde version plus simple, comme celle que tu proposes. Je ne suis pas sur que « propre » soit par contre la meilleure définition de la coupe, pour le coup.

Cédric

couper_propre() n’est pas le meilleur nom c’est certain - et ça reste perso :wink:

Effectivement il y a beaucoup de cas que j’ai évacués.

Mon besoin était que :

  • si j’ai un contenu de plus de 20 caractères, alors le texte apparaisse et qu’on voit qu’il a été coupé (avec les ellipses de fin)

Bref que ça coupe et qu’on sache quand c’est coupé.

La fonction actuelle de couper() ne le permet pas et pire certains mots étaient tronqués sans ellipse

Je pense que c’est lié à http://core.spip.org/projects/spip/repository/entry/spip/ecrire/inc/texte_mini.php#L348

L’effet de bord apparait parce que j’ai une coupe ‘courte’ (25 à 40 caractères) mais il me semble l’avoir observé pour des textes plus longs

Est-ce qu’il y a un endroit sur la zone où on peut faire un ensemble de tests pour les fonctions de l’api de SPIP ?

.Gilles

Exemple concret sur des articles :

“Informaticien, comptable, joueur d’échecs, libraire”

lorsque que j’utilise [(#TITRE|couper{25})] j’obtiens le texte “Informaticien, comptable,”

lorsque j’utilise [(#TITRE|couper_perso{25})]
j’obtiens " Informaticien, comp (…)", ce qui certes est plus moche mais indique mieux qu’il y a eu une coupure

Sinon la fonction couper() actuelle fonctionne super bien pour des textes longs.

Dans ce cas, c'est plutôt au niveau de ton CSS qu'il faut travailler, je
pense, en ajoutant "text-overflow: ellipsis;"

https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow

personnellement j’ajouterais simplement des caractères pour visualiser la coupe
[(#TEXTE|couper{80, '...'})]

Dans ce cas, c'est plutôt au niveau de ton CSS qu'il faut travailler, je
pense, en ajoutant "text-overflow: ellipsis;"

Effectivement dans certains cas j'utilise
.nowrap {white-space: nowrap;text-overflow: ellipsis;overflow: hidden;}

Maintenant ça ne résout pas mon problème qui demande que le texte soit
coupé, sur de l'export pdf par exemple

personnellement j'ajouterais simplement des caractères pour visualiser
la coupe
[(#TEXTE|couper{80, '...'})]

justement ces caractères n'apparaissent pas dans certains cas (par exemple
si la coupe s'est faite juste après la fin d'un mot - et pour des coupes à
peu de caractères). Dans certains cas le mot est tronqué sans qu'il n'y ait
d'ellipse (observé vers les 20 caractères).

a oui pardon… alors je comprends la proposition du css

En illustration, voici une capture qui montre les inconvénients (à mon avis) du filtre |couper
http://www.evernote.com/shard/s5/sh/c0d32893-4034-418c-aed1-91ef6d822446/e85b8f3144b0994c7a970f72a05746ad

Une solution que je n’ai pas évoquée serait de rajouter un paramètre à ce filtre pour forcer l’ajout d’une ellipse.

Qu’en dites-vous ?