WordPress.org

Make WordPress Core

Ticket #38656: 38656.2.diff

File 38656.2.diff, 5.6 KB (added by pento, 5 years ago)
  • src/wp-includes/formatting.php

     
    466466        // Change multiple <br>s into two line breaks, which will turn into paragraphs.
    467467        $pee = preg_replace('|<br\s*/?>\s*<br\s*/?>|', "\n\n", $pee);
    468468
    469         $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)';
     469        // Block level elements that can contain a <p>.
     470        $peeblocks = 'caption|td|th|div|dd|dt|li|form|map|blockquote|address|fieldset|section|article|aside|header|footer|nav|figure|figcaption|details|menu';
     471
     472        // Block level elements that cannot contain a <p>.
     473        $peefreeblocks = 'table|thead|tfoot|col|colgroup|tbody|tr|dl|ul|ol|pre|area|math|style|p|h[1-6]|hr|legend|hgroup|summary';
     474
     475
     476        $allblocks     = "(?:$peeblocks|$peefreeblocks)";
     477        $peeblocks     = "(?:$peeblocks)";
     478        $peefreeblocks = "(?:$peefreeblocks)";
     479        $emptyblocks   = "(?:hr|br)";
     480        $mediablocks   = "(?:object|param|embed|audio|video|source|track)";
     481
     482        $stream = wp_html_split( $pee );
     483        $peeable = array( true );
     484        foreach ( $stream as $id => $droplet ) {
     485                if ( '<' === substr( $droplet, 0, 1 ) ) {
     486                        $matches = array();
     487                        if ( preg_match( '!<' . $emptyblocks . '(?: [^>]*)?>!s', $droplet ) ) {
     488                                continue;
     489                        } elseif ( preg_match( '!^<.+/>$!s', $droplet ) ) {
     490                                continue;
     491                        } elseif ( preg_match( '%^<!--.+-->$%s', $droplet ) ) {
     492                                continue;
     493                        } elseif ( preg_match( '%^<!\[CDATA\[.+\]\]>$%s', $droplet ) ) {
     494                                continue;
     495                        } elseif ( preg_match( '!^</.+>$!s', $droplet ) ) {
     496                                array_pop( $peeable );
     497                        } elseif ( preg_match( '!^<' . $peeblocks . '(?: [^>]*)?>$!s', $droplet ) ) {
     498                                $peeable[] = true;
     499                        } elseif ( preg_match( '!^<' . $mediablocks . '(?: [^>]*)?>$!s', $droplet ) ) {
     500                                // Media blocks can't really be pee'd, but they're handle later on.
     501                                $peeable[] = true;
     502                        } else {
     503                                $peeable[] = false;
     504                        }
     505
     506                        continue;
     507                }
     508
     509                if( ! end( $peeable ) ) {
     510                        $stream[ $id ] = str_replace( "\n", '<!-- wpnl -->', $droplet );
     511                }
     512        }
     513
     514        if ( '<!-- wpnl -->' === $stream[ $id ] ) {
     515                $stream[ $id ] = "\n";
     516        }
     517
     518        $pee = implode( $stream );
    470519
    471520        // Add a double line break above block-level opening tags.
    472521        $pee = preg_replace('!(<' . $allblocks . '[\s/>])!', "\n\n$1", $pee);
     
    474523        // Add a double line break below block-level closing tags.
    475524        $pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee);
    476525
     526        // Add a double line break below block-level opening tags that are allowed to contain a <p>.
     527        $pee = preg_replace('%(<' . $peeblocks . '(?: [^>]*)?>)%', "$1\n\n", $pee);
     528
     529        // Add a double line break above block-level closing tags that are allowed to contain a <p>.
     530        $pee = preg_replace('%(</' . $peeblocks . '>)%', "\n\n$1", $pee);
     531
    477532        // Standardize newline characters to "\n".
    478533        $pee = str_replace(array("\r\n", "\r"), "\n", $pee);
    479534
     
    506561                $pee = preg_replace( '%\s*(<(?:source|track)[^>]*>)\s*%', '$1', $pee );
    507562        }
    508563
     564        // If there's only one paragraph inside a pee block, remove the newlines.
     565        $pee = preg_replace( '%(<(' . $peeblocks . ")(?: [^>]*)?>)\n\n((?(?!\n\n).)*)\n\n(</\\2>)%s", '$1$3$4', $pee );
     566
    509567        // Remove more than two contiguous line breaks.
    510568        $pee = preg_replace("/\n\n+/", "\n\n", $pee);
    511569
     
    537595        $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee);
    538596
    539597        // If an opening or closing block element tag is preceded by an opening <p> tag, remove it.
    540         $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee);
     598        $pee = preg_replace('%<p>(?:\s|<!-- wpnl -->)*(</?' . $allblocks . '[^>]*>)%', "$1", $pee);
    541599
    542600        // If an opening or closing block element tag is followed by a closing <p> tag, remove it.
    543         $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee);
     601        $pee = preg_replace('%(</?' . $allblocks . '[^>]*>)(?:\s|<!-- wpnl -->)*</p>%', "$1", $pee);
    544602
    545603        // Optionally insert line breaks.
    546604        if ( $br ) {
  • tests/phpunit/tests/formatting/Autop.php

     
    332332                $content = array();
    333333
    334334                foreach ( $blocks as $block ) {
     335                        if ( 'hr' === $block ) {
     336                                continue;
     337                        }
    335338                        $content[] = "<$block>foo</$block>";
    336339                }
    337340
     
    360363                $content = array();
    361364
    362365                foreach ( $blocks as $block ) {
     366                        if ( 'hr' === $block ) {
     367                                continue;
     368                        }
    363369                        $content[] = "<$block attr='value'>foo</$block>";
    364370                }
    365371
     
    534540
    535541                $this->assertEquals( $expected, trim( wpautop( $content ) ) );
    536542        }
     543
     544        /**
     545         * @ticket 38656
     546         */
     547        function data_paragraphs_inside_blocks() {
     548                $data = array(
     549                        array(
     550                                "<div>a\n\nb</div>",
     551                                "<div>\n<p>a</p>\n<p>b</p>\n</div>",
     552                        ),
     553                        array(
     554                                "<h1>a\n\nb</h1>",
     555                                "<h1>a\n\nb</h1>",
     556                        ),
     557                        array(
     558                                "<h1>a\nb</h1>",
     559                                "<h1>a\nb</h1>",
     560                        ),
     561                        array(
     562                                "<ul><li>a\n\nb</li></ul>",
     563                                "<ul>\n<li>\n<p>a</p>\n<p>b</p>\n</li>\n</ul>",
     564                        ),
     565                        array(
     566                                "<ul><li>a\n\n<ul><li>b\n\nc</li></ul></li></ul>",
     567                                "<ul>\n<li>\n<p>a</p>\n<ul>\n<li>\n<p>b</p>\n<p>c</p>\n</li>\n</ul>\n</li>\n</ul>",
     568                        ),
     569                );
     570
     571                return $data;
     572        }
     573
     574        /**
     575         * @ticket 38656
     576         * @dataProvider data_paragraphs_inside_blocks
     577         */
     578        function test_paragraphs_inside_blocks( $content, $expected ) {
     579                $this->assertEquals( $expected, trim( wpautop( $content ) ) );
     580        }
    537581}