diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index 00782b1f33..15fef0d851 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -492,7 +492,8 @@ function wpautop( $pee, $br = true ) { // Change multiple
s into two line breaks, which will turn into paragraphs. $pee = preg_replace( '|\s*|', "\n\n", $pee ); - $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)'; + $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 ); // Add a double line break above block-level opening tags. $pee = preg_replace( '!(<' . $allblocks . '[\s/>])!', "\n\n$1", $pee ); @@ -558,12 +559,12 @@ function wpautop( $pee, $br = true ) { // Under certain strange conditions it could create a P of entirely whitespace. $pee = preg_replace( '|

\s*

|', '', $pee ); - // Add a closing

inside

,
, or
tag if missing. - $pee = preg_replace( '!

([^<]+)!', '

$1

', $pee ); - // If an opening or closing block element tag is wrapped in a

, unwrap it. $pee = preg_replace( '!

\s*(]*>)\s*

!', '$1', $pee ); + // Add a closing

inside

,
, or tag if missing. + $pee = preg_replace( '!

([^<]+)!', '

$1

', $pee ); + // In some cases
  • may get wrapped in

    , fix them. $pee = preg_replace( '|

    (|', '$1', $pee ); @@ -577,6 +578,12 @@ function wpautop( $pee, $br = true ) { // If an opening or closing block element tag is followed by a closing

    tag, remove it. $pee = preg_replace( '!(]*>)\s*

    !', '$1', $pee ); + // If a closing

    tag is inside a block element tag, without a preceding opening

    tag, remove it. + $pee = preg_replace( '#(<(' . $allblocksexceptp . ')[^>]*>)(((?!

    |).)*)

    #s', '$1$3', $pee ); + + // If an opening

    tag is inside a block element tag, without a following closing

    tag, remove it. + $pee = preg_replace( '#

    (((?!

    ).)*)#s', '$1', $pee ); + // Optionally insert line breaks. if ( $br ) { // Replace newlines that shouldn't be touched with a placeholder. diff --git a/tests/phpunit/tests/formatting/Autop.php b/tests/phpunit/tests/formatting/Autop.php index e93e826695..bf1675f548 100644 --- a/tests/phpunit/tests/formatting/Autop.php +++ b/tests/phpunit/tests/formatting/Autop.php @@ -600,4 +600,63 @@ line 2
    $this->assertEquals( $expected, trim( wpautop( $content ) ) ); } + + /** + * wpautop() should remove stray

    and

    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( + '

    123

    ', + "
    \n

    123

    \n
    \n", + ), + array( + '

    123

    ', + "
    \n

    123

    \n
    \n", + ), + array( + 'hello
    test
    ', + "

    hello

    \n
    test
    \n", + ), + array( + '

    Hello world

    WordPress
    ', + "
    \n

    Hello world

    \nWordPress
    \n", + ), + array( + "
    hello\n
    test
    \nworld
    ", + "
    hello\n
    test
    \n

    world

    \n", + ), + array( + 'hello
    test
    ', + "

    hello

    \n
    test
    \n", + ), + array( + '
    something
    Something
    ', + "
    \"something\"\n
    Something
    \n
    \n", + ), + array( + '
    ', + "
    \n
    \n
    \n", + ), + array( + '
    X
    ', + "
    X\n
    \n
    \n", + ), + array( + "
    \n
    ", + "
    \n
    \n
    \n", + ), + array( + "[banner]\n

    Test

    ", + "

    [banner]

    \n

    Test

    \n", + ), + ); + } }