Разрешить HTML в отрывке (excerpt)

13 апр. 2014 г., 00:11:46
Просмотры: 136K
Голосов: 66

Вот мой код для отрывка.

// Генерация пользовательской длины отрывка
function wpbx_excerpt_length($length) {
    return 300;
}
add_filter('excerpt_length', 'wpbx_excerpt_length');

Как разрешить HTML-теги такие как <a> <b> <i> <br>

0
Все ответы на вопрос 3
23
144

ПОЛНОЕ РУКОВОДСТВО ПО ЭКСЦЕРПТАМ

Недавно я отвечал на несколько вопросов, касающихся эксцерптов, поэтому решил дать развернутое объяснение, охватывающее как можно больше аспектов.

ПРЕДИСЛОВИЕ

В связи с этим ответом возникло несколько вопросов о том, куда следует помещать код. Ответ заключается в том, что это действительно зависит от вас и вашего удобства. Есть несколько вариантов размещения кода (если явно не указано иное):

  • В файле functions.php вашей темы или любом другом файле, используемом как файл функций. Просто помните, что если тема не ваша, все изменения будут потеряны при обновлении темы.

  • Лучшим вариантом будет использование кода в дочерней теме. Как и выше, в файле functions.php или связанном с функциями файле.

  • Использование кода в плагине. Это предпочтительный способ, так как он делает код доступным для всех тем. Если вы смените тему, вам не придется переписывать тот же код заново.

Надеюсь, это немного проясняет ситуацию :-)

HTML-ТЕГИ/ФОРМАТИРОВАНИЕ

the_excerpt() прежде всего не принимает никаких параметров, поэтому ничего нельзя передать в него. Факт в том, что the_excerpt() обрезает контент до 55 слов, и все HTML-теги удаляются перед возвратом текста. the_excerpt() находится в wp-includes/post-template.php. Чтобы разрешить определенные или все HTML-теги в эксцерпте, необходимо создать новый эксцерпт.

Прежде всего, нужно сначала удалить оригинальную функцию, а затем подключить новую функцию к get_the_excerpt. Обратите внимание, этот новый эксцерпт по-прежнему будет вызываться как the_excerpt() в файлах шаблонов, не нужно это менять. get_the_excerpt() находится в wp-includes/post-template.php.

Эксцерпт использует wp_trim_excerpt для возврата обрезанного текста, поэтому сначала нужно удалить wp_trim_excerpt из фильтра эксцерпта. wp_trim_excerpt() находится в wp-includes/formatting.php, строка 2355. Вот как это делается:

remove_filter('get_the_excerpt', 'wp_trim_excerpt');

Теперь вы можете добавить ваш новый эксцерпт к get_the_excerpt

add_filter('get_the_excerpt', 'wpse_custom_wp_trim_excerpt');

Чтобы разрешить HTML-теги/форматирование, нужно указать, какие теги вы хотите разрешить. Можно использовать следующий оператор strip_tags для этого:

$wpse_excerpt = strip_tags($wpse_excerpt, wpse_allowedtags());

Второй аргумент wpse_allowedtags() — это небольшая функция, которая используется для добавления тегов, которые the_excerpt() будет разрешать. Для полного списка допустимых HTML 5 тегов, посмотрите здесь. Вот функция, добавьте любые HTML-теги, которые вам нужно разрешить/оставить:

function wpse_allowedtags() {
// Добавьте пользовательские теги в эту строку
    return '<script>,<style>,<br>,<em>,<i>,<ul>,<ol>,<li>,<a>,<p>,<img>,<video>,<audio>'; 
}

Если вам нужно разрешить все HTML-теги, то есть не удалять никакие теги, функцию strips_tags() можно полностью опустить/удалить.

Однако стоит отметить, что при разрешении HTML-тегов эти теги учитываются как слова, поэтому количество слов в эксцерптах с тегами и без них не будет совпадать. Чтобы исправить это, нужно сначала удалить эти теги из фактического подсчета слов, чтобы учитывались только слова.

Я написал эксцерпт, который разрешает все теги, считает только слова как слова, завершает предложение после установленного количества слов (чтобы текст не обрезался посередине предложения) и добавляет текст "Читать далее" после последнего слова.

Вот полный код:

function wpse_allowedtags()
{
  // Добавьте пользовательские теги в эту строку
  return '<script>,<style>,<br>,<em>,<i>,<ul>,<ol>,<li>,<a>,<p>,<img>,<video>,<audio>';
}

if (!function_exists('wpse_custom_wp_trim_excerpt')) :

  function wpse_custom_wp_trim_excerpt($wpse_excerpt)
  {
    $raw_excerpt = $wpse_excerpt;
    if ('' == $wpse_excerpt) {

      $wpse_excerpt = get_the_content('');
      $wpse_excerpt = strip_shortcodes($wpse_excerpt);
      $wpse_excerpt = apply_filters('the_content', $wpse_excerpt);
      $wpse_excerpt = str_replace(']]>', ']]&gt;', $wpse_excerpt);
      $wpse_excerpt = strip_tags($wpse_excerpt, wpse_allowedtags()); /*Если нужно разрешить только определенные теги. Удалите, если разрешены все теги */

      //Установите количество слов в эксцерпте и обрезайте только после завершения предложения.
      $excerpt_word_count = 75;
      $excerpt_length = apply_filters('excerpt_length', $excerpt_word_count);
      $tokens = array();
      $excerptOutput = '';
      $count = 0;

      // Разделите строку на токены; HTML-теги или слова, за которыми следует пробел
      preg_match_all('/(<[^>]+>|[^<>\s]+)\s*/u', $wpse_excerpt, $tokens);

      foreach ($tokens[0] as $token) {

        if ($count >= $excerpt_length && preg_match('/[\,\;\?\.\!]\s*$/uS', $token)) {
          // Достигнут лимит, продолжаем до , ; ? . или ! в конце
          $excerptOutput .= trim($token);
          break;
        }

        // Добавляем слова для завершения предложения
        $count++;

        // Добавляем оставшуюся часть токена
        $excerptOutput .= $token;
      }

      $wpse_excerpt = trim(force_balance_tags($excerptOutput));

      $excerpt_end = ' <a href="' . esc_url(get_permalink()) . '">' . '&nbsp;&raquo;&nbsp;' . sprintf(__('Читать далее: %s &nbsp;&raquo;', 'wpse'), get_the_title()) . '</a>';
      $excerpt_more = apply_filters('excerpt_more', ' ' . $excerpt_end);

      //$pos = strrpos($wpse_excerpt, '</');
      //if ($pos !== false)
      // Внутри последнего HTML-тега
      //$wpse_excerpt = substr_replace($wpse_excerpt, $excerpt_end, $pos, 0); /* Добавить "Читать далее" рядом с последним словом */
      //else
      // После контента
      $wpse_excerpt .= $excerpt_more; /*Добавить "Читать далее" в новом абзаце */

      return $wpse_excerpt;

    }
    return apply_filters('wpse_custom_wp_trim_excerpt', $wpse_excerpt, $raw_excerpt);
  }

endif;

remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'wpse_custom_wp_trim_excerpt');

Вы можете просто убрать '//' из функций, которые вам нужны дополнительно.

ПОЛЬЗОВАТЕЛЬСКАЯ ДЛИНА ЭКСЦЕРПТА

Иногда нужно отображать простые эксцерпты разной длины, и создавать отдельный эксцерпт для каждой записи/функции/страницы нецелесообразно. Вот небольшая удобная функция с использованием wp_trim_words:

function wpse_custom_excerpts($limit) {
    return wp_trim_words(get_the_excerpt(), $limit, '<a href="'. esc_url( get_permalink() ) . '">' . '&nbsp;&hellip;' . __( 'Читать далее &nbsp;&raquo;', 'wpse' ) . '</a>');
}

Что делает эта небольшая функция: берет get_the_excerpt, обрезает до $limit, установленного пользователем, и возвращает текст со ссылкой "Читать далее" в конце.

Вы можете вызвать этот эксцерпт в вашем шаблоне следующим образом:

echo wpse_custom_excerpts($limit);

где $limit будет вашим количеством слов, так что эксцерпт из 30 слов будет:

echo wpse_custom_excerpts(30);

Одна вещь, которую нужно помнить: если вы установите лимит больше 55 слов, вернется только 55 слов, так как эксцерпт имеет длину только в 55 слов. Если нужны более длинные эксцерпты, используйте get_the_content.

НАСТРОЙКА ДЛИНЫ ЭКСЦЕРПТА

Если вам нужно просто изменить длину the_excerpt(), можно использовать следующую функцию:

function wpse_excerpt_length( $length ) {
    return 20;
}
add_filter( 'excerpt_length', 'wpse_excerpt_length', 999 );

Помните, нужно установить приоритет больше 10, чтобы ваша пользовательская функция выполнялась после стандартной.

ДОБАВЛЕНИЕ ССЫЛКИ "ЧИТАТЬ ДАЛЕЕ"

Весь текст, возвращаемый эксцерптом, имеет ненавистные [...] в конце, которые не кликабельны. Чтобы добавить текст "Читать далее" вместо многоточия, используйте эту функцию:

 function wpse_excerpt_more( $more ) {
    return ' <a class="read-more" href="'. get_permalink( get_the_ID() ) . '">' . __('Читать далее', 'your-text-domain') . '</a>';
}
add_filter( 'excerpt_more', 'wpse_excerpt_more' );

РЕДАКТИРОВАНИЕ

Эксцерпт первого абзаца

Я хочу, чтобы это руководство было полным, поэтому вот эксцерпт, который обрезает после первого абзаца.

Вот функция, которая сохраняет HTML-теги, добавляет ссылку "Читать далее" в конце эксцерпта и обрезает эксцерпт после первого абзаца.

if ( ! function_exists( 'wpse0001_custom_wp_trim_excerpt' ) ) : 
    
    function wpse0001_custom_wp_trim_excerpt($wpse0001_excerpt) {
        global $post;
        $raw_excerpt = $wpse0001_excerpt;
        if ( '' == $wpse0001_excerpt ) {
    
            $wpse0001_excerpt = get_the_content('');
            $wpse0001_excerpt = strip_shortcodes( $wpse0001_excerpt );
            $wpse0001_excerpt = apply_filters('the_content', $wpse0001_excerpt);
            $wpse0001_excerpt = substr( $wpse0001_excerpt, 0, strpos( $wpse0001_excerpt, '</p>' ) + 4 );
            $wpse0001_excerpt = str_replace(']]>', ']]&gt;', $wpse0001_excerpt);
    
            $excerpt_end = ' <a href="'. esc_url( get_permalink() ) . '">' . '&nbsp;&raquo;&nbsp;' . sprintf(__( 'Читать далее: %s &nbsp;&raquo;', 'pietergoosen' ), get_the_title()) . '</a>'; 
            $excerpt_more = apply_filters('excerpt_more', ' ' . $excerpt_end); 
    
            //$pos = strrpos($wpse0001_excerpt, '</');
            //if ($pos !== false)
            // Внутри последнего HTML-тега
            //$wpse0001_excerpt = substr_replace($wpse0001_excerpt, $excerpt_end, $pos, 0);
            //else
            // После контента
            $wpse0001_excerpt .= $excerpt_more;
    
            return $wpse0001_excerpt;
    
        }
        return apply_filters('wpse0001_custom_wp_trim_excerpt', $wpse0001_excerpt, $raw_excerpt);
    }
    
endif; 
    
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'wpse0001_custom_wp_trim_excerpt');

РЕДАКТИРОВАНИЕ 29-10-2015

Для тех, кому нужно решение, чтобы не отображать ссылку "Читать далее" после эксцерпта, когда эксцерпт короче установленного количества слов, см. следующий вопрос и ответ:

13 апр. 2014 г. 08:30:46
Комментарии

куда именно нужно вставить эту часть function wpse_allowedtags() { // Добавьте пользовательские теги в эту строку return '<script>,<style>,<br>,<em>,<i>,<ul>,<ol>,<li>,<a>,<p>,<img>,<video>,<audio>'; } я запутался

user32447 user32447
13 апр. 2014 г. 12:13:38

Весь этот код добавляется в functions.php. Вы можете вставить его прямо перед if ( ! function_exists( 'wpse_custom_wp_trim_excerpt' ) ) : в вашем functions.php

Pieter Goosen Pieter Goosen
13 апр. 2014 г. 12:16:16

@user32447 смотрите правки

Pieter Goosen Pieter Goosen
13 апр. 2014 г. 12:19:14

я знаю это, но я хочу разрешить определённые теги и не знаю, как этого добиться, я поместил код в functions.php, но что мне изменить, чтобы разрешить определённые теги @pieter goosen

user32447 user32447
13 апр. 2014 г. 12:21:02

мне нужно удалить эту строку и заменить её $wpse_excerpt = strip_tags($wpse_excerpt, wpse_allowedtags());

user32447 user32447
13 апр. 2014 г. 12:21:58

неважно, я пропустил начало кода

user32447 user32447
13 апр. 2014 г. 12:25:12

Нет, оставьте $wpse_excerpt = strip_tags($wpse_excerpt, wpse_allowedtags());. Вы должны добавить свои теги в return '<script>,<style>,<br>,<em>,<i>,<ul>,<ol>,<li>,<a>,<p>,<img>,<video>,<audio>'; Также вы можете удалить все эти теги и просто добавить свои

Pieter Goosen Pieter Goosen
13 апр. 2014 г. 12:25:27

если добавить это в файл functions.php, не будет ли это перезаписано при обновлении?

mcgrailm mcgrailm
24 июл. 2014 г. 04:51:56

@mcgrailm да, будет. Именно поэтому важно добавлять это в functions.php дочерней темы. Вы также можете добавить это в must-use плагин

Pieter Goosen Pieter Goosen
24 июл. 2014 г. 06:55:16

Возможно, также добавить ":" в качестве токена?

timocouckuyt timocouckuyt
28 мар. 2015 г. 15:49:13

@PieterGoosen Вау, это отличное объяснение! Есть только один момент: функция будет добавлять слова до следующей . или ! (например), но что если после последней . или ! больше нет слов? Ссылка "Читать далее" все равно будет отображаться... Я знаю, что функция цитаты не должна показывать полное содержимое, но это может быть сложно контролировать, если редактор пишет небольшую статью. Что вы думаете по поводу этой ситуации?

Pipo Pipo
12 июн. 2015 г. 18:34:15

@Pipo Вы правы. Я рассмотрю этот вопрос после выходных, я буду немного занят. Буду держать вас в курсе. Спасибо за ваш ответ

Pieter Goosen Pieter Goosen
13 июн. 2015 г. 06:12:00

@PieterGoosen Не переживайте, нет никакой спешки, я просто пытаюсь учиться на вашем коде. Хорошего воскресенья

Pipo Pipo
14 июн. 2015 г. 21:13:09

Это гарантирует, что никакие теги не останутся открытыми? Я спрашиваю из-за этого вопроса.

Nicolai Grossherr Nicolai Grossherr
30 июл. 2015 г. 14:47:32

Есть проблема с тегами ul и li, о которой я знаю, но в целом это должно просто удаляться из отрывка. @ialocin

Pieter Goosen Pieter Goosen
30 июл. 2015 г. 14:51:08

Отлично! То есть, если у меня, скажем, 100 слов и есть открывающий тег без закрывающего, он будет удален.

Nicolai Grossherr Nicolai Grossherr
30 июл. 2015 г. 14:53:32

@ialocin нет, не будет. Можно реализовать что-то подобное, чтобы удалять оставшиеся открытыми теги. Я имел в виду, что на самом деле следует удалять теги, такие как ul и li, из анонса. В одной из функций выше можно это сделать.

Pieter Goosen Pieter Goosen
30 июл. 2015 г. 14:58:22

Жаль, я вас тогда неправильно понял - очевидно. Речь шла скорее о тегах, например, <b>.

Nicolai Grossherr Nicolai Grossherr
30 июл. 2015 г. 15:05:16

Думаю, это нужно протестировать :-). Когда я это создавал, это больше предназначалось для тегов a, которые на тот момент были моей основной проблемой. Только позже я заметил, что теги ul и li обрезались посередине, поэтому оставался открывающий тег без закрывающего. Честно говоря, у этого кода есть свои недостатки :-)

Pieter Goosen Pieter Goosen
30 июл. 2015 г. 15:16:00

@PieterGoosen Просто упоминаю, что подключение функции excerpt_more не сработает, если не задать ей более низкий приоритет, поскольку template-tags.php загружается после functions.php текущей темы.

Cu7l4ss Cu7l4ss
16 дек. 2015 г. 03:05:11

@PieterGoosen спасибо за очень информативный пост - быстрый вопрос: можно ли таким образом изменить отрывок только для определенного типа записи?

nickpish nickpish
8 сент. 2017 г. 01:52:04

Можешь просто написать быстрое решение, которое я могу скопировать и вставить в свой код? Сейчас лето, и мне не хочется читать целую книгу.

Daniel Muñoz Parsapoormoghadam Daniel Muñoz Parsapoormoghadam
9 июн. 2018 г. 17:54:59

Для тех, кто не знает, что копировать — в ответе есть раздел "Here is the complete code" (Вот полный код).

m4n0 m4n0
31 дек. 2020 г. 10:36:51
Показать остальные 18 комментариев
0

Добавьте больше тегов, если необходимо, в $allowed_tags = ...

function _20170529_excerpt($text) {
$raw_excerpt = $text;
if ( '' == $text ) {
    // Получаем содержимое записи.
    $text = get_the_content('');

    // Удаляем все шорткоды из содержимого.
    $text = strip_shortcodes( $text );

    $text = apply_filters('the_content', $text);
    $text = str_replace(']]>', ']]&gt;', $text);

    $allowed_tags = '<a>,<b>,<br><i>'; 
    $text = strip_tags($text, $allowed_tags);

    $excerpt_word_count = 55; /*** ИЗМЕНИТЕ ЭТО. Укажите желаемое количество слов в анонсе.***/
    $excerpt_length = apply_filters('excerpt_length', $excerpt_word_count); 

    $excerpt_end = '[...]'; /*** ИЗМЕНИТЕ ЭТО. Укажите желаемое окончание анонса.***/
    $excerpt_more = apply_filters('excerpt_more', ' ' . $excerpt_end);

    $words = preg_split("/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
    if ( count($words) > $excerpt_length ) {
        array_pop($words);
        $text = implode(' ', $words);
        $text = $text . $excerpt_more;
    } else {
        $text = implode(' ', $words);
    }
}
return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
}

Источник: http://bacsoftwareconsulting.com/blog/index.php/wordpress-cat/how-to-preserve-html-tags-in-wordpress-excerpt-without-a-plugin/

29 мая 2017 г. 11:21:49
1

Вы можете добавить визуальный редактор для кратких описаний (экспертов), добавив приведённый ниже код в файл плагина или functions.php вашей темы. Это позволит вам использовать HTML-редактор для создания экспертов, а также корректно отображать HTML-разметку в самих экспертах. #ура

Я скопировал этот код откуда-то, но не помню источник. Использую его во всех своих проектах, и он отлично работает.

Примечание: Этот код был взят из ответа "Adding a rich text editor to Excerpt" пользователя fuxia за 2012 год

Пример работы редактора для экспертов

/**
  * Заменяет стандартный редактор экспертов на TinyMCE.
*/
add_action( 'add_meta_boxes', array ( 'T5_Richtext_Excerpt', 'switch_boxes' ) );
class T5_Richtext_Excerpt
{
    /**
     * Заменяет метабоксы.
     *
     * @return void
     */
    public static function switch_boxes()
    {
        if ( ! post_type_supports( $GLOBALS['post']->post_type, 'excerpt' ) )
        {
            return;
        }

        remove_meta_box(
            'postexcerpt', // ID
            '',            // Экран, пусто для поддержки всех типов записей
            'normal'      // Контекст
        );

        add_meta_box(
            'postexcerpt2',     // Повторное использование 'postexcerpt' не работает.
            __( 'Краткое описание' ),    // Заголовок
            array ( __CLASS__, 'show' ), // Функция отображения
            null,              // Экран, используем все экраны с метабоксами.
            'normal',          // Контекст
            'core',            // Приоритет
        );
    }

    /**
     * Вывод метабокса.
     *
     * @param  object $post
     * @return void
     */
    public static function show( $post )
    {
        ?>
        <label class="screen-reader-text" for="excerpt"><?php
        _e( 'Краткое описание' )
        ?></label>
        <?php
            // Используем стандартное имя 'excerpt', чтобы не заботиться о
            // сохранении, фильтрах и прочем.
            wp_editor(
                self::unescape( $post->post_excerpt ),
                'excerpt',
                array (
                    'textarea_rows' => 15,
                    'media_buttons' => FALSE,
                    'teeny'         => TRUE,
                    'tinymce'       => TRUE
                )
            );
    }

    /**
     * Краткое описание обычно экранируется. Это ломает HTML-редактор.
     *
     * @param  string $str
     * @return string
     */
    public static function unescape( $str )
    {
        return str_replace(
            array ( '&lt;', '&gt;', '&quot;', '&amp;', '&nbsp;', '&amp;nbsp;' ),
                array ( '<',    '>',    '"',      '&',     ' ', ' ' ),
                $str
        );
    }
}
7 апр. 2019 г. 03:18:36
Комментарии

Спасибо, @peter-wooster за правку.

Mayur Chauhan Mayur Chauhan
22 нояб. 2021 г. 02:07:52