¿Cómo recortar el texto del cuerpo (field_body)?

10

He creado una vista para un nodo que muestra el contenido como entidad representada. Entre otros, imprimo el campo del cuerpo en la plantilla de ramita:

{{ content.field_body }}

Ahora, me gustaría limitar el texto a 200 caracteres y poner tres puntos. He probado tres formas diferentes de hacerlo, pero nada ha funcionado. El problema es que cada forma cuenta y recorta los caracteres HTML también.

1: He agregado el formato "Recortado" en "Administrar pantalla" => El texto es limitado pero no correcto. Y no tengo los tres puntos.

2: He recortado el texto en la plantilla de ramita. Pero para contar el texto, primero tengo que representarlo. De este modo, twig genera el texto como HTML (¡veo etiquetas HTML en mi página!)

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

3: He intentado resolver el problema en template_preprocess_node (). Aquí tengo el mismo problema con contar el marcado HTML también.

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

¿Cómo puedo recortar mi texto correctamente?

¡Muchas gracias por su ayuda!

marco-s
fuente

Respuestas:

18

Hay algunas soluciones que puede probar, pero tenga en cuenta que truncar cadenas con html generalmente es una mala idea debido a que tiene posibles etiquetas no formadas o mal formadas.

1. Use | raw para generar el html como html, puede producir etiquetas mal formadas:

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

2. Tira html primero, limpiador:

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

3. Registre una extensión de ramita (sin probar):

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

Otra extensión útil que puede consultar es la extensión de texto, que le ayuda a evitar cortar palabras:

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

squall3d
fuente
2
etiquetas malformadas de primera solución y tira de segunda solución todas las etiquetas html.
Yusef
1
@zhilevan sí, como se describe en la respuesta.
squall3d
1
@ squall3d ¿cuál es su solución para cortarlo sin tirar htmls?
Yusef
1
@zhilevan generalmente cuando quiero mostrar texto truncado es con el propósito de un avance, donde rara vez quiero html. Pero si necesita preservar html, puede probar esta extensión: gist.github.com/leon/2857883
squall3d el
1
Si uso la imagen en el campo del cuerpo. No 2, no funciona para imágenes. ¿Hay algún otro código
También
5

Ahora puede hacer esto con el módulo twig_extender y usar |truncate.

Aquí hay un ejemplo de cómo usarlo en la plantilla .twig, tenga en cuenta que también estoy usando twig_field_value :

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

nota: generalmente mantengo mi configuración de desarrollo (./admin/config/development/devel) configurada para usar Symfony var-dumper y puedo descifrar la cadena con

es decir: {{ devel_dump(content.field_name|field_value) }}

bdanin
fuente
4

Mejoras:

  1. Si se tira de etiquetas que debe |trimde deshacerse de los espacios en blanco
  2. recortar en el límite de la palabra - ver abajo slice()ysplit()
  3. Utilice puntos suspensivos ( …) en lugar de "..."
  4. |raw La salida

{% 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
fuente
3

Así es como manejé esto.

Ejemplo:
campo - nodo - cuerpo - 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
fuente