<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[45585] trunk: Clean up stray `<p>` tags added by `wpautop()` inside block level tags.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/45585">45585</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/45585","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>pento</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2019-07-02 01:30:15 +0000 (Tue, 02 Jul 2019)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Clean up stray `<p>` tags added by `wpautop()` inside block level tags.

`autop()` can sometimes get confused and not clean up stray `<p>` or `</p>` tags inside block level elements, which produces sub-optimal HTML. While browsers can generally handle it, there's no need to make things harder for them if we don't have to.

Props pento, ayubi, pbearne, jond, azaozz, 1994rstefan, dionysous, MikeHansenMe, jorbin, miqrogroove, niallkennedy.
Fixes <a href="https://core.trac.wordpress.org/ticket/27350">#27350</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesformattingphp">trunk/src/wp-includes/formatting.php</a></li>
<li><a href="#trunktestsphpunittestsformattingAutopphp">trunk/tests/phpunit/tests/formatting/Autop.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesformattingphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/formatting.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/formatting.php      2019-07-01 20:47:21 UTC (rev 45584)
+++ trunk/src/wp-includes/formatting.php        2019-07-02 01:30:15 UTC (rev 45585)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -492,7 +492,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">        // Change multiple <br>s into two line breaks, which will turn into paragraphs.
</span><span class="cx" style="display: block; padding: 0 10px">        $pee = preg_replace( '|<br\s*/?>\s*<br\s*/?>|', "\n\n", $pee );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $allblocks        = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)\b';
+       $allblocksexceptp = str_replace( '|p|', '|', $allblocks );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        // Add a double line break above block-level opening tags.
</span><span class="cx" style="display: block; padding: 0 10px">        $pee = preg_replace( '!(<' . $allblocks . '[\s/>])!', "\n\n$1", $pee );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -558,12 +559,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">        // Under certain strange conditions it could create a P of entirely whitespace.
</span><span class="cx" style="display: block; padding: 0 10px">        $pee = preg_replace( '|<p>\s*</p>|', '', $pee );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        // If an opening or closing block element tag is wrapped in a <p>, unwrap it.
+       $pee = preg_replace( '!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', '$1', $pee );
+
</ins><span class="cx" style="display: block; padding: 0 10px">         // Add a closing <p> inside <div>, <address>, or <form> tag if missing.
</span><span class="cx" style="display: block; padding: 0 10px">        $pee = preg_replace( '!<p>([^<]+)</(div|address|form)>!', '<p>$1</p></$2>', $pee );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // If an opening or closing block element tag is wrapped in a <p>, unwrap it.
-       $pee = preg_replace( '!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', '$1', $pee );
-
</del><span class="cx" style="display: block; padding: 0 10px">         // In some cases <li> may get wrapped in <p>, fix them.
</span><span class="cx" style="display: block; padding: 0 10px">        $pee = preg_replace( '|<p>(<li.+?)</p>|', '$1', $pee );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -577,6 +578,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">        // If an opening or closing block element tag is followed by a closing <p> tag, remove it.
</span><span class="cx" style="display: block; padding: 0 10px">        $pee = preg_replace( '!(</?' . $allblocks . '[^>]*>)\s*</p>!', '$1', $pee );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        // If a closing <p> tag is inside a block element tag, without a preceding opening <p> tag, remove it.
+       $pee = preg_replace( '#(<(' . $allblocksexceptp . ')[^>]*>)(((?!<p>|</\2>).)*)</p>#s', '$1$3', $pee );
+
+       // If an opening <p> tag is inside a block element tag, without a following closing <p> tag, remove it.
+       $pee = preg_replace( '#<p>(((?!</p>).)*</' . $allblocksexceptp . '>)#s', '$1', $pee );
+
</ins><span class="cx" style="display: block; padding: 0 10px">         // Optionally insert line breaks.
</span><span class="cx" style="display: block; padding: 0 10px">        if ( $br ) {
</span><span class="cx" style="display: block; padding: 0 10px">                // Replace newlines that shouldn't be touched with a placeholder.
</span></span></pre></div>
<a id="trunktestsphpunittestsformattingAutopphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/formatting/Autop.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/formatting/Autop.php    2019-07-01 20:47:21 UTC (rev 45584)
+++ trunk/tests/phpunit/tests/formatting/Autop.php      2019-07-02 01:30:15 UTC (rev 45585)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -600,4 +600,63 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertEquals( $expected, trim( wpautop( $content ) ) );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * wpautop() should remove stray <p> and </p> tags inside blocks
+        *
+        * @ticket 27350
+        * @dataProvider data_wpautop_removes_stray_p_tags_in_blocks
+        */
+       function test_wpautop_removes_stray_p_tags_in_blocks( $data, $expected ) {
+               $this->assertEquals( $expected, wpautop( $data ) );
+       }
+
+       function data_wpautop_removes_stray_p_tags_in_blocks() {
+               return array(
+                       array(
+                               '<div><p>123</p> </div>',
+                               "<div>\n<p>123</p>\n</div>\n",
+                       ),
+                       array(
+                               '<div><p>123</p></div>',
+                               "<div>\n<p>123</p>\n</div>\n",
+                       ),
+                       array(
+                               'hello<div>test</div>',
+                               "<p>hello</p>\n<div>test</div>\n",
+                       ),
+                       array(
+                               '<div><p>Hello world</p><span>WordPress</span></div>',
+                               "<div>\n<p>Hello world</p>\n<span>WordPress</span></div>\n",
+                       ),
+                       array(
+                               "<div>hello\n<pre>test</pre>\nworld</div>",
+                               "<div>hello\n<pre>test</pre>\n<p>world</p></div>\n",
+                       ),
+                       array(
+                               'hello<div>test</div>',
+                               "<p>hello</p>\n<div>test</div>\n",
+                       ),
+                       array(
+                               '<div><img src="/wp-content/uploads/example.jpg" alt="something" /><div>Something</div></div>',
+                               "<div><img src=\"/wp-content/uploads/example.jpg\" alt=\"something\" />\n<div>Something</div>\n</div>\n",
+                       ),
+                       array(
+                               '<div><span></span><div></div></div>',
+                               "<div><span></span>\n<div></div>\n</div>\n",
+                       ),
+                       array(
+                               '<div>X<div></div></div>',
+                               "<div>X\n<div></div>\n</div>\n",
+                       ),
+                       array(
+                               "<div><div></div>\n </div>",
+                               "<div>\n<div></div>\n</div>\n",
+                       ),
+                       array(
+                               "[banner]\n<h1>Test</h1>",
+                               "<p>[banner]</p>\n<h1>Test</h1>\n",
+                       ),
+               );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>

</body>
</html>