Вопрос или проблема
Начиная с версии 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>
, обертывающие блочные элементы?
Вот что я уже попробовал:
- Добавление фильтра к
tiny_mce_before_init
, который устанавливает настройкуvalid_children
для<a>
в TinyMCE, чтобы включить<h4>
(как предложено в вопросе “Проблема HTML5, WordPress и Tiny MCE – обертывание тега- якоря вокруг div приводит к странному выводу“) - Добавление фильтра к
tiny_mce_before_init
, который устанавливает настройкуschema
в TinyMCE наhtml5
.
Я также нашел тикет “Блок <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. Эти изменения, помимо устранения технических проблем, значительно упростят процесс редактирования ваших постов и страниц, обеспечив больше гибкости и возможности для кастомизации контента.