Как заставить WordPress и TinyMCE принимать теги, оборачивающие блочные элементы, как допустимые в HTML5?

Вопрос или проблема

Начиная с версии 5, стандарт HTML позволяет тегам <a> обертывать блочные элементы. На определенной странице мне нужно обернуть заголовок и изображение в тег <a>:

Некоторый вводный текст.

<div>
  <a href="http://somewhere/">
    <h4>Некоторый заголовок</h4>
    <img src="http://somewhere/some-img.jpg" alt="Некоторое изображение" />
  </a>
</div>

Хотя я могу ввести это в текстовом редакторе, это вызывает странное поведение:

Код выше будет преобразован в следующий HTML код:

<p>Некоторый вводный текст.</p>
<div>
<a href="http://somewhere/"></p>
<h4>Некоторый заголовок</h4>
<p><img src="http://somewhere/some-img.jpg" alt="Некоторое изображение" /><br />
</a>
</div>

Очевидно, что открывающий <a> идет перед закрывающим </p> для никогда не открытого <p>, что абсолютно неверно. Также перед тегом <img> имеется незакрытый тег <p>.


Поскольку это похоже на проблему, связанную с переносами строк, я попытался удалить переносы строк из моего кода WordPress:

Некоторый вводный текст.

<div><a href="http://somewhere/"><h4>Некоторый заголовок</h4><img src="http://somewhere/some-img.jpg" alt="Некоторое изображение" /></a></div>

Интересно, что это приводит к следующему HTML коду:

<p>Некоторый вводный текст.</p>
<div><a href="http://somewhere/"><br />
<h4>Некоторый заголовок</h4>
<p><img src="http://somewhere/some-img.jpg" alt="Некоторое изображение" /></a></div>

Теперь все еще отсутствует закрывающий </p> тег после <img>. (Хорошо, HTML5 принимает незакрытые <p> теги… но я не думаю, что такое поведение используется здесь умышленно.) Кроме того, WordPress вводит <br />, который появляется как будто из ниоткуда.

Пока что это проблемы, связанные с WordPress…


Теперь к проблемам, связанным с TinyMCE:

При переключении обратно из текстового режима редактирования в WordPress в визуальный режим редактирования, <a> все еще присутствуют. Однако, когда я снова переключаюсь в текстовый режим (или сохраняю страницу из визуального режима редактирования), <a> полностью удаляются.


Понятно, теперь переходим к моему основному вопросу: Как мне заставить WordPress и TinyMCE принять теги <a>, обертывающие блочные элементы?


Вот что я уже попробовал:

Я также нашел тикет “Блок <a> теги удаляются из редактора“, но не совсем понимаю, считается ли удаление <a> тегов намеренным поведением.

Несколько лет спустя, но, надеюсь, кто-то другой найдет это решение полезным…

Хотя мои проблемы с попыткой заставить это работать в WordPress были немного другими, надеюсь, это решение будет полезно и вам.

Во-первых, проблема с тем, что теги не могут содержать несколько блочных элементов была решена добавлением следующего кода из этой статьи в мой файл functions.php…

function allow_all_tinymce_elements_attributes( $init ) {

    // Разрешить все элементы и все атрибуты
    $ext="*[*]";

    // Добавить к extended_valid_elements, если он уже существует
    if ( isset( $init['extended_valid_elements'] ) ) {
        $init['extended_valid_elements'] .= ',' . $ext;
    } else {
        $init['extended_valid_elements'] = $ext;
    }

    // вернуть значение
    return $init;
}

add_filter('tiny_mce_before_init', 'allow_all_tinymce_elements_attributes');

… а затем убедившись, что моему тегу <a> дано имя. Это позволило мне ввести и успешно сохранить следующее во вкладке Текст…

Некоторый текст.
<div>
<a href="https://somewhere.com/product/this_prod/" name="link">
<h2>УЮТНЫЙ ПРОДУКТ</h2>
Экономически эффективный Бла-бла-бла</a>
</div>

Для второй проблемы, когда код удаляется при переключении с “текстовой” на “визуальную” вкладку, я просто отключил визуальную вкладку для определенного типа записи. Я адаптировал начальный код, найденный в этой статье, которая изначально была нацелена на ID записи, а не на тип записи. Я добавил этот код в файл functions.php…

add_filter('user_can_richedit', 'disable_wyswyg_to_preserve_my_markup');
function disable_wyswyg_to_preserve_my_markup( $default ){
  if( get_post_type() == 'product') return false;
  return $default;
}

Если это не работает для пользовательского типа записи, вы можете попробовать добавить следующую строку над предыдущим кодом…

add_theme_support( 'post-formats', 'my_custom_post_type' );

Или, чтобы решить эту вторую проблему, вы можете попробовать плагин, такой как этот.

Я всегда делал это через короткий код. Например…

[b_link url="http://example.com"]<h4>Вещи</h4><p>Ядда ядда</p>[/b_link]

(Нет кода под рукой, и я на мобильном, но могу предоставить завтра, если потребуется.)

Ответ или решение

Чтобы сделать так, чтобы WordPress и TinyMCE принимали теги <a>, обертывающие блочные элементы в соответствии со стандартом HTML5, необходимо учесть несколько технических аспектов и внести соответствующие изменения в код. Ниже приведены шаги, которые помогут вам решить эту проблему.

1. Понимание проблемы

В стандартном WordPress редакторе при попытке обернуть блочные элементы (такие как заголовки и изображения) тегом <a>, вы сталкиваетесь с проблемой, когда HTML-код неправильно обрабатывается. Это связано с тем, что в редакторе по умолчанию применяются определённые правила, ограничивающие возможность использования блочных элементов внутри тегов <a>.

2. Модификация TinyMCE

Чтобы TinyMCE правильно обрабатывал блочные элементы внутри тегов <a>, вам нужно изменить настройки редактора. Для этого вы можете добавить следующий код в файл functions.php вашей темы:

function allow_all_tinymce_elements_attributes( $init ) {
    // Разрешите все элементы и атрибуты
    $ext="*[*]";

    // Добавить к extended_valid_elements, если он уже существует
    if ( isset( $init['extended_valid_elements'] ) ) {
        $init['extended_valid_elements'] .= ',' . $ext;
    } else {
        $init['extended_valid_elements'] = $ext;
    }

    return $init;
}

add_filter('tiny_mce_before_init', 'allow_all_tinymce_elements_attributes');

Этот код разрешает использование всех элементов и атрибутов, что, в свою очередь, позволит вам оборачивать блочные элементы в ссылки.

3. Установка схемы HTML5

Кроме того, важно убедиться, что схема TinyMCE установлена на HTML5. Добавьте следующий код также в файл functions.php:

function set_html5_schema( $init ) {
    $init['schema'] = 'html5';
    return $init;
}
add_filter( 'tiny_mce_before_init', 'set_html5_schema' );

4. Отключение визуального редактора для определённых типах записей

Одним из способов решения проблемы с обрезанием кода является отключение визуального редактора для определённых постов или типов записей. Например:

add_filter('user_can_richedit', 'disable_wyswyg_to_preserve_my_markup');
function disable_wyswyg_to_preserve_my_markup( $default ) {
    if( get_post_type() == 'product' ) return false;
    return $default;
}

Этот код отключает визуальный редактор для типа записи ‘product’, позволяя сохранять ваш HTML-код без изменений.

5. Использование шорткодов как альтернативы

Если решение с визуальным редактором не подходит, рассмотрите возможность использования шорткодов для реализации вашей задачи. Например:

function b_link_shortcode( $atts, $content = null ) {
    $attributes = shortcode_atts( array(
        'url' => '#',
    ), $atts );

    return '<a href="' . esc_url($attributes['url']) . '">' . do_shortcode($content) . '</a>';
}

add_shortcode( 'b_link', 'b_link_shortcode' );

Используя шорткод [b_link url="http://example.com"]<h4>Текст</h4>[/b_link], вы можете оборачивать блочные элементы в ссылки без потери форматирования.

Заключение

Следуя описанным выше шагам, вы сможете настроить WordPress и TinyMCE для поддержки обертывания блочных элементов в теги <a>, что соответствует современным стандартам HTML5. Эти изменения, помимо устранения технических проблем, значительно упростят процесс редактирования ваших постов и страниц, обеспечив больше гибкости и возможности для кастомизации контента.

Оцените материал
Добавить комментарий

Капча загружается...