Extract and truncate plain text from HTML content using Twig in Winter CMS

112 Views Asked by At

I'm working on a blog template in Winter CMS using Twig as the templating language. Within my template, I have a field called post.summary that contains HTML content, including a video embed code.

For example, the value of post.summary is:

<div class="video-wrapper ratio-16-9">
    <iframe src="https://www.youtube.com/embed/A9zLuEALnPo" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" width="560" height="315" frameborder="0"></iframe>
</div>
Įamžintos įvairios akimirkos: merginų, vestuvių, šeimyninių švenčių ir nuotykių pasirodymai. Pristatome jums įspūdingą 2021 metų video darbų demonstracinį įrašą. Tai yra puiki galimybė pamatyti mūsų fotografijos ir videografinio meno potencialą.

Šis šou reel leis jums įsijungti į skirtingus pasaulius, įkvepiančius akimirkas ir nepakartojamą atmosferą. Nuo vizualiai įspūdingų vaizdų iki kūrybingos redagavimo technikos, šis demonstracinis įrašas atskleidžia mūsų gebėjimą sukurti unikalias istorijas ir įamžinti jūsų ypatingiausias akimirkas.

Leiskite mums parodyti jums, kaip mūsų talentas ir aistra gali paversti jūsų akimirkas į nuostabius kadrus, kurie bus įsimintini visam laikui.

I want to extract the plain text from post.summary, excluding any HTML tags and the video embed code. Additionally, I would like to truncate the resulting plain text to a maximum of 100 characters and append an ellipsis if the text exceeds that limit.

Here's the relevant part of my Twig template code that attempts to achieve this:

{% macro truncateText(text, length) %}
  {% if text|length > length %}
    {% set plainText = text|striptags %}
    {% set truncatedText = plainText|slice(0, length) %}
    {% set lastSpaceIndex = truncatedText|rindex(' ') %}
    {% if lastSpaceIndex > 0 %}
      {% set truncatedText = truncatedText|slice(0, lastSpaceIndex) %}
    {% endif %}
    {{ truncatedText|raw }}...
  {% else %}
    {{ text|raw }}
  {% endif %}
{% endmacro %}

...

{% for category in post.categories %}
  {% if category.name == 'Video' %}
    <p class="excerpt">
      {% set modifiedSummary = post.summary|replace({'<div class="video-wrapper ratio-16-9"><iframe': '', '</iframe></div>': '', '&quot;': '"'}) %}
      {% set modifiedSummary = _self.truncateText(modifiedSummary, 100) %}
      {{ modifiedSummary|raw }}

It's totally working fine on plain text data, but with div and <iframe> tags the output is not what I'm expecting, actual results:

https://www.youtube.com/embed/A9zLuEALnPo

UPDATE: I've added a custom twig filter, but as result I'm still getting the plain string https://www.youtube.com/embed/A9zLuEALnPo while the rest of the text data is ignored

<?php 

namespace Kuzma\Twigextensionyoutube;

use System\Classes\PluginBase;
use Twig\TwigFilter;

class Plugin extends PluginBase
{
    public function registerComponents()
    {
    }

    public function registerSettings()
    {
    }
    
    public function registerMarkupTags()
    {
        return [
            'filters' => [
                'truncateText' => [$this, 'truncateTextFilter'],
            ],
        ];
    }   
    
    public function truncateTextFilter($text)
    {
        // Remove div element with class "video-wrapper" and its contents
        $text = preg_replace('/<div class="video-wrapper[^>]*>.*?<\/div>/is', '', $text);

        // Remove iframe tags
        $text = preg_replace('/<iframe.*?>.*?<\/iframe>/is', '', $text);

        // Extract the remaining text
        $text = strip_tags($text);

        // Trim any extra whitespace
        $text = trim($text);

        return $text;
    }


}

0

There are 0 best solutions below