19

I want to use HTML5 in my WordPress theme, how do I turn off wptexturize?

I don't mind WP adding breaks, but I want them to be <br> and not <br />. How do I get control over how those breaks show up in my code?

EDIT: I only really care about the <br> tag issue, I don't mind the typographic changes it makes.

EDIT2: Actually, I guess <img> tags matter too. Any self-closing standalone tags will matter here. So, <hr> might be an issue as well. Not to mention such wp_head() items as <link> and various <meta> tags.

12
  • 1
    what's wrong with <br />?
    – Scott M.
    Aug 11, 2010 at 23:36
  • 2
    It's fine, but if I want to hew to the non-XML version of HTML5, I won't want the XML-style ` />` endings.
    – artlung
    Aug 12, 2010 at 3:10
  • I thought <br /> was valid html and xhtml? When was it not? Aug 13, 2010 at 20:14
  • 5
    I believe this question is extremely misleading. wptexturize doesn't, in any way, prevent a site from being HTML 5 compliant. Aug 13, 2010 at 22:04
  • 2
    Can someone please re-title this along the lines of "How do I remove trailing-slashes from self-closing elements in wordpress-generated markup"?
    – Bobby Jack
    Sep 6, 2010 at 12:16

6 Answers 6

21

Line breaks are added by wpautop(), not wptexturize(). wpautop() is also the function that automatically adds paragraph tags.

You're better off fixing the <br />'s than you are replacing the filter. Since wpautop() runs at priority 10, you can just hook in after that and fix it.

add_filter( 'the_content', 'html5_line_breaks', 25 );

function html5_line_breaks( $content ) {
    return str_replace( '<br />', '<br>', $content );
}

Edit after OP update:

WordPress functions are designed to output XHTML. In order to get rid of those trailing slashes site-wide, you're going to have to use an output buffer. You could use a filter similar to the one above to replace slashes in the post contents, but that wouldn't catch your head, sidebar, etc.

It's a bit ugly and might have a small impact on performance, but here you go (drop this in a plugin or your theme's functions.php file):

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();
}

That code says if you're not in the administration area and not doing an AJAX request handling, then start buffering the output through a filter and then using the WordPress shutdown hook, output that buffer.

3
  • I haven't had time to crack open functions.php yet, but could you elaborate on where that if block goes? It might be evident once I get a chance to open that file up, but I figure I'd get the question out of the way. Aug 20, 2010 at 0:31
  • @Thomas: Your theme's functions.php file is just like a plugin file. Any code in there will automatically be executed. It doesn't matter where it goes as long as it's valid PHP. Aug 20, 2010 at 1:00
  • Ah. Interesting. I'm fairly new to WordPress development, so I'm still learning a lot. Thanks for clearing that up. Aug 20, 2010 at 1:24
8
+75

Here you go:

function my_awesome_tag_fixer( $input ){
  return preg_replace( '/(<.+)\s\/>/', '$1>', $input );
}

foreach( array('the_content', 'the_excerpt', 'comment_text') as $filter )
  add_filter( $filter, 'my_awesome_tag_fixer', 12 );

It's not the most elegant solution, but it gets it done a lot quicker than rewriting wpautop and wptexturize.

1
  • 1
    +1 I did something very similar for HTML 4.01 Strict compliance. Aug 14, 2010 at 21:18
7

Just found it; self-closing tags on void elements are valid html.

In HTML5 we've allowed the / on void elements (like <meta>, <img>, <br>, <input>, etc), to ease migration to and from XML.

http://lists.whatwg.org/pipermail/help-whatwg.org/2008-August/000137.html

More infomation:

http://wiki.whatwg.org/wiki/FAQ#Should_I_close_empty_elements_with_.2F.3E_or_.3E.3F

7
  • 1
    "However, due to the widespread attempts to use XHTML1, there are a significant number of pages using the trailing slash. Because of this, the trailing slash syntax has been permitted on void elements in HTML in order to ease migration from XHTML1 to HTML5." Permitted as a legacy. I think the way forward is ditching the extra "/", thus my question. I think WordPress needs to allow for the option to create code to xhtml, or html4.01 or html5.
    – artlung
    Aug 13, 2010 at 20:29
  • That is the problem you are reading into what is being said. Trailing slashes are permitted, which means it is valid syntax. You are speculating that it is going to be removed? Why guess where the standards are going and create work to solve a problem that doesn't exist? Aug 13, 2010 at 21:02
  • I'm not speculating on anything. I'm not guessing into anything. The / mark is not required by the spec, and I want to have the option to remove it in WordPress.
    – artlung
    Aug 13, 2010 at 21:09
  • I like XHTML, do we have to go back to the disorderly look of old HTML. Aug 14, 2010 at 14:12
  • Arlen, I like orderly html, I like xhtml. I'm a big fan of validators. I have written my own doctype to do validation on my own code. I've used html 3.2, html 4, 4.01, even html 2.0! lab.artlung.com/html-2.0 -- but I would like the option to remove self-closing tags in WordPress. It does not seem like it should be such a big deal. I feel like arguing with the premise of my question is very unhelpful.
    – artlung
    Aug 14, 2010 at 14:47
6

This can be disabled in e.g. the theme's function.php file by taking advantage of the remove_filter() function (http://codex.wordpress.org/Function_Reference/remove_filter)

remove_filter("the_content", "wptexturize");
4
  • 1
    Can I get more granular control over this? Won't I lose the typographic marks if I do it this way?
    – artlung
    Aug 11, 2010 at 19:44
  • I'm not aware of any simple approach off the top of my head, but let me see what I can figure out for you.
    – thomasjo
    Aug 11, 2010 at 19:46
  • Short of reproducing the desired functionality found in wptexturize(), I was unable to find any other viable solutions.
    – thomasjo
    Aug 11, 2010 at 20:13
  • I wonder if there would be a way to simply reverse the <br /> - replace those with <br> maybe?
    – artlung
    Aug 11, 2010 at 20:30
5

I have an starter theme for html5 and WordPress and also a function not for wptexturize, but for wpautop(). Include also other elements of HTML, like thead, tfoot, aside and use the syntax of HTML5 like <br> and <script>

/**
 * wpautop for HTML5, allowed: 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 [email protected]
 */
function html5wpautop($pee, $br = 1) {
    if ( trim($pee) === '' )
            return '';
     
    $pee = $pee . "\n"; // just to make things a little easier, pad the end
    $pee = preg_replace('|<br />\s*<br />|', "\n\n", $pee);
    // Space things out a little
    // *insertion* of 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); // cross-platform newlines
    if ( strpos($pee, '<object') !== false ) {
            $pee = preg_replace('|\s*<param([^>]*)>\s*|', "<param$1>", $pee); // no pee inside object/embed
            $pee = preg_replace('|\s*</embed>\s*|', '</embed>', $pee);
    }
    $pee = preg_replace("/\n\n+/", "\n\n", $pee); // take care of duplicates
    // make paragraphs, including one at the end
    $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); // under certain strange conditions it could create a P of entirely whitespace
    // *insertion* of 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); // don't pee all over a tag
    $pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // problem with nested lists
    $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); // optionally make line breaks
            $pee = str_replace('<WPPreserveNewline />', "\n", $pee);
    }
    $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee);
    // *insertion* of 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;
}

// remove the original wpautop function
remove_filter('the_excerpt', 'wpautop');
remove_filter('the_content', 'wpautop');

// add our new html5autop function
add_filter('the_excerpt', 'html5wpautop');
add_filter('the_content', 'html5wpautop');

See more on the SVN of the HTML5 starter theme, not a framework!

3

Disable WPtexturize plugin worked for me: Disable WPtexturize

It's pretty straigtforward though:

remove_filter('the_content', 'wptexturize');
remove_filter('the_excerpt', 'wptexturize');
remove_filter('comment_text', 'wptexturize');

Not the answer you're looking for? Browse other questions tagged or ask your own question.