5

For one of my current projects, I had to transfer blogposts from an old Wordpress site to my project.

Things went smoothly until I've seen that all the posts were copy pasted from Word, leaving this before pretty much every paragraph:

<span style="font-size: medium; font-family: georgia,palatino;">

And at some places things like these:

<p style="text-align: justify;">
<p style="text-align: justify;"><span style="font-size: medium; font-family: georgia,palatino;"><strong><span style="color: #000000;">

So because I don't have the 40 hours (even less the patience) to just go into every post (there's about 100) and remove those unwanted tags, I'm looking for a filter that would just remove all style (except maybe if it contains text-decoration:underline) elements before outputting the_content()

Is there such a thing?

  • Can't you override styles in CSS files using !important ? – Shanavas M Nov 24 '15 at 13:51
  • That may be possible but isn't optimal. It requires knowing every style that needs to be overridden and can play havoc with css priorities. !important is a last resort when all else has failed. – Slam Jan 16 '18 at 23:42
10

If we want to remove all inline styles, then just simply need to add the following code in functions.php.

add_filter('the_content', function( $content ){
    //--Remove all inline styles--
    $content = preg_replace('/ style=("|\')(.*?)("|\')/','',$content);
    return $content;
}, 20);
  • 1
    IMO this is the correct answer. It removes only styles and nothing else leaving classes intact. It also doesn't mess with the database so it's not destructive. It only alters the output. – Slam Jan 16 '18 at 23:00
5

Just add this to your functions.php.

Note: This filter works at the time of saving/updating the post.

add_filter( 'wp_insert_post_data' , 'filter_post_data' , '99', 2 );

function filter_post_data( $data , $postarr ) {

    $content = $data['post_content'];

    $content = preg_replace('#<p.*?>(.*?)</p>#i', '<p>\1</p>', $content);
    $content = preg_replace('#<span.*?>(.*?)</span>#i', '<span>\1</span>', $content);
    $content = preg_replace('#<ol.*?>(.*?)</ol>#i', '<ol>\1</ol>', $content);
    $content = preg_replace('#<ul.*?>(.*?)</ul>#i', '<ul>\1</ul>', $content);
    $content = preg_replace('#<li.*?>(.*?)</li>#i', '<li>\1</li>', $content);

    $data['post_content'] = $content;

    return $data;
}

Note: This filter works at the time when function the_content() is executed.

add_filter( 'the_content', 'the_content_filter', 20 );

function the_content_filter( $content ) {
    $content = preg_replace('#<p.*?>(.*?)</p>#i', '<p>\1</p>', $content);
    $content = preg_replace('#<span.*?>(.*?)</span>#i', '<span>\1</span>', $content);
    $content = preg_replace('#<ol.*?>(.*?)</ol>#i', '<ol>\1</ol>', $content);
    $content = preg_replace('#<ul.*?>(.*?)</ul>#i', '<ul>\1</ul>', $content);
    $content = preg_replace('#<li.*?>(.*?)</li>#i', '<li>\1</li>', $content);
    return $content;
}
  • Note: this function is overkill for this question — it removes all styles, yes. but also all classes, types, and everything else inside the the <p> tag and leaves only a plain <p>. Reza's solution is the correct one for the OP. – Slam Jan 16 '18 at 22:59
  • Note that the first part of this alters the content in the database and as such it's dangerous. If you make a mistake then your content is permanently altered. Say later on your discover you need some class info. Too bad, it's all erased now. The second approach is better because it's non-destructive. If it's wrong you can rewrite the filter and alter the output without destroying the source material. – Slam Jan 16 '18 at 23:46
  • 1
    Would say that in the way I program my sites, I try to make it so you dont have to work with classes added in the_content() for the pages to work. I think working that way makes the client unable to modify the site after it has been delivered. – Fredy31 Jan 17 '18 at 15:09
  • Although some would say this is overkill, in some cases you want to remove all tag attributes, leaving only the tag. Example: exporting all posts to a 'plain' HTML file that will be imported into Word - as in creating an ebook from posts on a site. So the technique here is helpful; just modify the statements to 'clean' the tags you want to clean. It is also useful for posts created with copy/paste from Word document; it will remove the Word formatting tags so that the theme can style the content. So, the claim of 'dangerous' could actually be the desired outcome. – Rick Hellewell Sep 14 '18 at 19:56
3

I tried the method above with the saving/updating but didn't worked for me so I went from another approach. I exported the whole wp_posts table, opened it in Sublime and did a regex replace. I used style="*.*?" to find all cases and replaced them with emptyness. Then droped the old table's content and imported the new one.

If any one try this method - please make sure you have a clear back up in case there are some other post types in the wp_post table and the things got bit messy.

0

I would check out the content_save_pre filter, and probably apply some fancy regex at that point.

  • 3
    "This answer was automatically flagged as low-quality because of its length and content", which I am sure you don't want. @vancoder, your suggestion is one of a couple of plausible answers but without more description and possibly some sample code it is not a very useful answer except to an already knowledgeable programmer, a qualification we can't assume. And a programmer would have likely thought of this already. Can you please add some detail? – s_ha_dum Mar 22 '13 at 17:54
  • I'd have a read of this (as well as the SO question linked from the article) with respect to using regex for (X)HTML parsing. – montrealist Mar 22 '13 at 18:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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