Comment découper le corps du texte (field_body)?

10

J'ai créé une vue pour un nœud qui montre le contenu comme entité rendue. Entre autres, je produis le champ corporel dans le modèle de brindille:

{{ content.field_body }}

Maintenant, je voudrais limiter le texte à 200 caractères et mettre trois points. J'ai testé trois façons différentes de le faire, mais rien n'a fonctionné. Le problème est que chaque manière compte et coupe également les caractères HTML.

1: J'ai ajouté le format "Trimmed" dans "Manage display" => Le texte est limité mais pas correct. Et je n'ai pas les trois points.

2: J'ai coupé le texte dans le modèle de brindille. Mais pour compter le texte, je dois d'abord le rendre. Ainsi, twig affiche le texte au format HTML (je vois des balises HTML sur ma page!)

{% set text = content.field_body|render %}
{{ text|length > 200 ? text|slice(0, 200) ~ '...' : text }}

3: J'ai essayé de résoudre le problème dans template_preprocess_node (). Ici, j'ai le même problème avec le comptage du balisage HTML aussi.

$body_text = $node->get('field_body')->getValue()[0]['value'];
$trimmed_text = substr($body_text, 0, 200) . '...';

Comment puis-je couper mon texte correctement?

Merci beaucoup pour votre aide!

marco-s
la source

Réponses:

18

Il y a quelques solutions que vous pouvez essayer, mais prenez note que tronquer des chaînes avec du html est généralement une mauvaise idée en raison de la présence potentielle de balises non fermées ou mal formées.

1. Utilisez | raw pour sortir le html en html, peut produire des balises malformées:

{% set text = content.field_body|render %}
{{ text|length > 200 ? text|slice(0, 200)|raw ~ '...' : text|raw }}

2. Dénudez d'abord le code HTML, nettoyez:

{% set text = content.field_body|render|striptags %}
{{ text|length > 200 ? text|slice(0, 200) ~ '...' : text }}

3. Enregistrez une extension de brindille (non testée):

https://gist.github.com/leon/2857883

Une autre extension utile que vous pouvez consulter est l'extension de texte, qui vous aide à éviter de couper des mots:

http://twig.sensiolabs.org/doc/extensions/text.html

squall3d
la source
2
les premières balises malformées de la solution et la deuxième solution suppriment toutes les balises html.
Yusef
1
@zhilevan yep, comme décrit dans la réponse.
squall3d
1
@ squall3d quelle est votre solution pour le slice sans strip htmls?
Yusef
1
@zhilevan généralement quand je veux afficher du texte tronqué, c'est dans le but d'un teaser, où je veux rarement html. Mais si vous avez besoin de conserver le HTML, vous pouvez essayer cette extension: gist.github.com/leon/2857883
squall3d
1
Si j'utilise l'image dans le champ corporel. Non 2, ne fonctionne pas pour les images. Y a-t-il un autre code, imprimera également l'image
logeshvaran
5

Vous pouvez maintenant le faire avec le module twig_extender et l'utiliser |truncate.

Voici un exemple de la façon de l'utiliser dans le modèle .twig, notez que j'utilise également twig_field_value :

{{ content.field_name|field_value|first['#text']|truncate(15, true, '....') }}

Remarque: je conserve généralement mes paramètres de développement (./admin/config/development/devel) définis pour utiliser le var-dumper Symfony et je peux comprendre la chaîne avec

c'est à dire: {{ devel_dump(content.field_name|field_value) }}

bdanin
la source
4

Améliorations:

  1. si vous vous devriez balises dépouillez |trimpour se débarrasser des espaces blancs
  2. rogner sur la limite des mots - voir ci-dessous slice()etsplit()
  3. Utilisez des points de suspension ( …) plutôt que "..."
  4. |raw le résultat

{% set text = content.field_header_intro|render|striptags|trim %}

{{ (text|length > 200 ? text|slice(0, 201)|split(' ')|slice(0, -1)|join(' ') ~ '&hellip;' : text)|raw }}</code>

Duncanmoo
la source
3

C'est ainsi que j'ai géré cela.

Exemple:
champ - nœud - corps - article.html.twig

{% set mode = element['#view_mode'] %}
...
{% for item in items %}
  {% if mode == 'full' %}
    <div{{ attributes.addClass('texto') }}>{{ item.content }}</div>
  {% elseif mode == 'teaser' %}
    {# if there is something about trim_length in field formatter #}
    {% if item.content['#text_summary_trim_length'] %}
      {# first remove html tags then you slice with trim_length #}
      {% set texto = item.content['#text']|striptags|slice(0, item.content['#text_summary_trim_length']) %}
      <p {{ attributes }}>{{ texto }}...</p>
    {% else %}
      <p {{ attributes }}>{{ item.content }}</p>
    {% endif %}
  {% endif %}
{% endfor %}
...
Vagner
la source