Как отключить самозакрывающиеся теги в WordPress (для HTML5 или HTML4)?
Я хочу использовать HTML5 в своей теме WordPress, как отключить wptexturize?
Меня не беспокоит, что WP добавляет переносы строк, но я хочу, чтобы они были в виде <br>
, а не <br />
. Как получить контроль над тем, как эти переносы отображаются в моем коде?
РЕДАКТИРОВАНИЕ: Меня волнует только проблема с тегом <br>
, типографские изменения меня не беспокоят.
РЕДАКТИРОВАНИЕ 2: На самом деле, теги <img>
тоже важны. Любые самозакрывающиеся одиночные теги будут иметь значение. Так что <hr>
тоже может быть проблемой. Не говоря уже о таких элементах wp_head()
, как <link>
и различные <meta>
теги.
Переносы строк добавляются функцией wpautop()
, а не wptexturize()
. wpautop()
также автоматически добавляет теги абзацев.
Лучше исправить теги <br />
, чем заменять фильтр. Поскольку wpautop()
выполняется с приоритетом 10, вы можете просто добавить свой хук после него и исправить это.
add_filter( 'the_content', 'html5_line_breaks', 25 );
function html5_line_breaks( $content ) {
return str_replace( '<br />', '<br>', $content );
}
Обновление после уточнения автора:
Функции WordPress предназначены для вывода XHTML. Чтобы избавиться от завершающих слэшей на всем сайте, вам придется использовать буферизацию вывода. Можно использовать фильтр, аналогичный приведенному выше, для замены слэшей в содержимом записей, но это не затронет заголовок, боковую панель и другие элементы.
Решение не самое элегантное и может немного повлиять на производительность, но вот оно (добавьте этот код в плагин или файл functions.php
вашей темы):
if ( !is_admin() && ( ! defined('DOING_AJAX') || ( defined('DOING_AJAX') && ! DOING_AJAX ) ) {
ob_start( 'html5_slash_fixer' );
add_action( 'shutdown', 'html5_slash_fixer_flush' );
}
function html5_slash_fixer( $buffer ) {
return str_replace( ' />', '>', $buffer );
}
function html5_slash_fixer_flush() {
ob_end_flush();
}
Этот код означает, что если вы не в админ-панели и не обрабатываете AJAX-запрос, то начинается буферизация вывода через фильтр, а затем, используя хук WordPress shutdown, выводится этот буфер.

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

@Thomas: Файл functions.php
вашей темы работает так же, как файл плагина. Любой код в нем будет выполняться автоматически. Не имеет значения, куда его вставлять, главное чтобы это был валидный PHP-код.

Вот решение:
function my_awesome_tag_fixer( $input ){
// Заменяем самозакрывающиеся теги вида <tag /> на обычные <tag>
return preg_replace( '/(<.+)\s\/>/', '$1>', $input );
}
// Применяем фильтр к основному контенту, цитатам и тексту комментариев
foreach( array('the_content', 'the_excerpt', 'comment_text') as $filter )
add_filter( $filter, 'my_awesome_tag_fixer', 12 );
Это не самое элегантное решение, но оно работает значительно быстрее, чем переписывание функций wpautop и wptexturize.

Только что узнал, что самозакрывающиеся теги для пустых элементов допустимы в HTML.
В HTML5 мы разрешили использование / для пустых элементов (таких как <meta>, <img>, <br>, <input> и т.д.), чтобы упростить миграцию в XML и обратно.
http://lists.whatwg.org/pipermail/help-whatwg.org/2008-August/000137.html
Дополнительная информация:
http://wiki.whatwg.org/wiki/FAQ#Should_I_close_empty_elements_with_.2F.3E_or_.3E.3F

"Однако, из-за широко распространённых попыток использования XHTML1, существует значительное количество страниц, использующих завершающий слэш. По этой причине синтаксис с завершающим слэшем был разрешён для пустых элементов в HTML, чтобы облегчить миграцию с XHTML1 на HTML5."
Разрешено как наследие. Я считаю, что путь вперёд — это отказ от лишнего "/", отсюда и мой вопрос. Думаю, WordPress должен предоставить возможность создавать код в xhtml, html4.01 или html5.

В этом и заключается проблема — вы вкладываете в сказанное свой смысл. Завершающие слэши разрешены, что означает их валидный синтаксис. Вы предполагаете, что они будут удалены? Зачем гадать, куда движутся стандарты, и создавать работу для решения несуществующей проблемы?

Я ничего не предполагаю. Я ни во что не вкладываю догадок. Символ "/" не требуется спецификацией, и я хочу иметь возможность убрать его в WordPress.

Мне нравится XHTML, но неужели нам нужно возвращаться к неупорядоченному виду старого HTML.

Арлен, мне нравится упорядоченный html, мне нравится xhtml. Я большой поклонник валидаторов. Я написал свой собственный doctype для валидации моего кода. Я использовал html 3.2, html 4, 4.01, и даже html 2.0! http://lab.artlung.com/html-2.0/ -- но мне бы хотелось иметь возможность убирать самозакрывающиеся теги в WordPress. Это не кажется чем-то сложным. Мне кажется, что спорить с предпосылкой моего вопроса совсем не помогает.

@artlung: Я думаю, проблема в том, что некоторые люди предположили, что ты не знаешь, что "<br />", "<br>" и даже "<br><br />" являются полностью валидными в HTML5. Однако, я считаю, что твой вопрос абсолютно валиден, независимо от того, куда движется HTML5 в будущем, если его переформулировать; в конце концов, wordpress должен уметь генерировать валидный HTML4.

Могу ли я получить более детальный контроль над этим? Разве я не потеряю типографские знаки, если сделаю это таким образом?

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

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

У меня есть стартовая тема для HTML5 и WordPress, а также функция, не для wptexturize, а для wpautop(). Включены также другие элементы HTML, такие как thead, tfoot, aside, и используется синтаксис HTML5, например <br> и <script>.
/**
* wpautop для HTML5, разрешены: table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|map|area|blockquote|address|math|style|input|p|h[1-6]|hr|fieldset|legend|section|article|aside|header|footer|hgroup|figure|details|figcaption|summary)
* @link http://nicolasgallagher.com/using-html5-elements-in-wordpress-post-content/
* @author nicolas@nicolasgallagher.com
*/
function html5wpautop($pee, $br = 1) {
if ( trim($pee) === '' )
return '';
$pee = $pee . "\n"; // просто для удобства, добавляем перенос в конце
$pee = preg_replace('|<br />\s*<br />|', "\n\n", $pee);
// Разделяем содержимое немного
// *добавлены* section|article|aside|header|footer|hgroup|figure|details|figcaption|summary
$allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|map|area|blockquote|address|math|style|input|p|h[1-6]|hr|fieldset|legend|section|article|aside|header|footer|hgroup|figure|details|figcaption|summary)';
$pee = preg_replace('!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee);
$pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee);
$pee = str_replace(array("\r\n", "\r"), "\n", $pee); // кросс-платформенные переносы строк
if ( strpos($pee, '<object') !== false ) {
$pee = preg_replace('|\s*<param([^>]*)>\s*|', "<param$1>", $pee); // не вставляем параграфы внутри object/embed
$pee = preg_replace('|\s*</embed>\s*|', '</embed>', $pee);
}
$pee = preg_replace("/\n\n+/", "\n\n", $pee); // убираем дублирующиеся переносы
// создаем параграфы, включая один в конце
$pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY);
$pee = '';
foreach ( $pees as $tinkle )
$pee .= '<p>' . trim($tinkle, "\n") . "</p>\n";
$pee = preg_replace('|<p>\s*</p>|', '', $pee); // в некоторых странных условиях может создать пустой параграф
// *добавлены* section|article|aside
$pee = preg_replace('!<p>([^<]+)</(div|address|form|section|article|aside)>!', "<p>$1</p></$2>", $pee);
$pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); // не добавляем параграфы вокруг тегов
$pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // проблема с вложенными списками
$pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee);
$pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee);
$pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee);
$pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee);
if ($br) {
$pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', create_function('$matches', 'return str_replace("\n", "<WPPreserveNewline />", $matches[0]);'), $pee);
$pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee); // опционально добавляем переносы строк
$pee = str_replace('<WPPreserveNewline />', "\n", $pee);
}
$pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee);
// *добавлены* img|figcaption|summary
$pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol|img|figcaption|summary)[^>]*>)!', '$1', $pee);
if (strpos($pee, '<pre') !== false)
$pee = preg_replace_callback('!(<pre[^>]*>)(.*?)</pre>!is', 'clean_pre', $pee );
$pee = preg_replace( "|\n</p>$|", '</p>', $pee );
return $pee;
}
// удаляем оригинальную функцию wpautop
remove_filter('the_excerpt', 'wpautop');
remove_filter('the_content', 'wpautop');
// добавляем нашу новую функцию html5autop
add_filter('the_excerpt', 'html5wpautop');
add_filter('the_content', 'html5wpautop');
Подробнее в SVN стартовой темы HTML5, не фреймворка!

Плагин Disable WPtexturize сработал для меня: Отключить WPtexturize
Это довольно просто:
remove_filter('the_content', 'wptexturize');
remove_filter('the_excerpt', 'wptexturize');
remove_filter('comment_text', 'wptexturize');
