Avoid converting “>” to >

I’m using a Markdown plugin and trying to write a blockquote

Like this

Read More

But WordPress converts “>” to an html entity, so the result looks

> like this

Is there a way to avoid this?

Related posts

Leave a Reply

4 comments

  1. Filtering the_content

    function wpse72941_content_filter( $content ) {
        $new_content = '';
        foreach( preg_split( '/((r?n)|(rn?))/', $content ) as $line ) {
            $new_content .= preg_replace( '/^>/', '>', $line ) . 'rn';
        }
        return $new_content;
    }
    add_filter( 'the_content', 'wpse72941_content_filter', 1 );
    

    I don’t know your markdown plugin – for the above approach, I have assumed that the markdown is interpreted after the post is retrieved from the database and not before it is saved to the same. I.e. that the markdown plugin also filters the_content.

    The regex ^> matches > iff those are the first four characters of a string. In the above, the content is iterated over line by line, hence all > entities at the beginning of a line are converted back to > characters.

    When the filter is added, we set the priority high (1), such that our entity conversion will run before the markdown interpretation.

    The above will work when added to your theme’s functions.php, but probably would be a better fit in a plugin. Actually the markdown plugin should take care of it itself.

    Preventing TinyMCE from converting entities

    If you need to stop the entity conversion right where it happens, before it is written to the databse, you will have to alter TinyMCE’s (the editor’s) configuration, the entities and/or entity_encoding options look promising.
    There is the tiny_mce_before_init filter that can pass custom config values to the WP editor.

    I would have provided a working example as well, were it not for this:

    Encoding Type: raw | All characters will be stored in non-entity form except these XML default entities: & < > "
    from the TinyMCE documentation on entity_encoding

    So for the specific entity in question, this appears to be more involved.
    This might also be the reason for why disabling the visual editor might not suffice.
    Possibly a combo of 'named' as a value for entity_encoding and a list without gt for entities might do it.
    Otherwise the onPostProcess event would be a last way to go.

    Life would be simpler though, if the above assumption was true and filtering the post on database retrieval would suffice.

  2. I solve it using:

    function my_content_filter( $content ) {
        $new_content = str_replace('>','>',$content);
        return $new_content;
    }
    add_filter( 'the_content', 'my_content_filter', 1 );
    

    I think it’s not glamorous, but, it work..

  3. I had a basically identical issue under WordPress 4.9.4, but in my case, the culprit was the wp_filter_post_kses() filter added to the content_save_pre filters by wp-includes/kses.php. This filter has a variety of effects, including translating <, &, > to entities and removing various HTML tags. A diagnostic indication that KSES was involved is that the conversion of these characters to entities was not happening for the super admin user of a multi-site install, as KSES does not install its filters for the super admin.

    Judging by the acronym “KSES” which stands for “KSES Strips Evil Scripts!” the KSES module is apparently a security measure. If potentially malicious agents do not have access to posting content to your site, you’ll want to disable KSES in some way to allow raw “>” characters and so on in the content of your posts.

    From the code, it appears that KSES is supposed to be disabled for users that have the unfiltered_html capability. I could not get that to work; no matter how I tried to grant a user this capability, KSES was still enabled except for the network super admin. Perhaps someone with a more thorough knowledge of user capabilities could get this mechanism to work. For me in the end, in order to allow “<” and such in my posts, I was forced to add a filter to pre_post_content (which runs before content_save_pre) that returned the input value unmodified, but which as a side effect checked that the current user was an administrator and if so, executed kses_remove_filters() which disables KSES.