Search code examples
phpregexwordpresspreg-replacewysiwyg

Replacing Heading (<h1>, <h2> ...) Tags with <p> Tags and Classes


I wish to replace tags from a WYSIWYG editor to .

At the moment I am using the following code to achieve this.

$content = preg_replace('/<h1(.*?)<\/h1>/si', '<p class="heading-1"$1</p>', $content);
$content = preg_replace('/<h2(.*?)<\/h2>/si', '<p class="heading-2"$1</p>', $content);
$content = preg_replace('/<h3(.*?)<\/h3>/si', '<p class="heading-3"$1</p>', $content);
$content = preg_replace('/<h4(.*?)<\/h4>/si', '<p class="heading-4"$1</p>', $content);
$content = preg_replace('/<h5(.*?)<\/h5>/si', '<p class="heading-5"$1</p>', $content);
$content = preg_replace('/<h6(.*?)<\/h6>/si', '<p class="heading-6"$1</p>', $content);

As you can see this code is quite messy, it would be great if I could condense this into a single regular expression but I simply lack the ability to do so.

I had considered this line of code as an alternative.

$content = preg_replace('/<h(.*?)<\/h(.*?)>/si', '<p class="heading-$2"$1</p>', $content);

I'm not sure about using the above, clients have a tendency to copy content from other sites, paste it straight into their new WYSIWYG and i've seen anything from hr tags to heading tags popping in there.

What I require is simply the above single line, except the tag itself can only be 2 specific characters (So ensure the tag starts with a H and is followed by [1-6]).

I also require that the class it adds to the p tag is specific to the number use, eg: heading-1, heading-2.

Any help would be greatly appreciated, thank you for your time.


Solution

  • $content = <<<HTML
    <h1 class="heading-title">test1</h1>
    <H2 class="green">test2</H2>
    <h5 class="red">test</h5>
    <h5 class="">test test</h5>
    HTML;
    
    $content = preg_replace('#<h([1-6]).*?class="(.*?)".*?>(.*?)<\/h[1-6]>#si', '<p class="heading-${1} ${2}">${3}</p>', $content);
    
    echo htmlentities($content);
    

    Result:

    <p class="heading-1 heading-title">test1</p> 
    <p class="heading-2 green">test2</p> 
    <p class="heading-5 red">test</p> 
    <p class="heading-5 ">test test</p>
    

    Note for existing classes: Even if your element doesn't have an existing class you have to add empty class attribute class="". Instead this will not work as expected. :( Better solution is to use preg_replace_callback. Then you can check if a match exists and create your p tags more accurately.