Ticket #38656: 38656.4.diff
File 38656.4.diff, 7.1 KB (added by , 5 years ago) |
---|
-
src/wp-includes/formatting.php
492 492 // Change multiple <br>s into two line breaks, which will turn into paragraphs. 493 493 $pee = preg_replace( '|<br\s*/?>\s*<br\s*/?>|', "\n\n", $pee ); 494 494 495 $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)'; 495 // Block level elements that can contain a <p>. 496 $peeblocks = 'caption|td|th|div|dd|dt|li|form|map|blockquote|address|fieldset|section|article|aside|header|footer|nav|figure|figcaption|details|menu'; 497 498 // Block level elements that cannot contain a <p>. 499 $peefreeblocks = 'table|thead|tfoot|col|colgroup|tbody|tr|dl|ul|ol|pre|area|math|style|p|h[1-6]|hr|legend|hgroup|summary'; 500 501 $allblocks = "(?:$peeblocks|$peefreeblocks)"; 502 $peeblocks = "(?:$peeblocks)"; 503 $peefreeblocks = "(?:$peefreeblocks)"; 504 505 // Empty elements that cannot contain anything. 506 $emptyblocks = '(?:hr|br)'; 507 508 // Media elements that will be processed later. 509 $mediablocks = '(?:object|param|embed|audio|video|source|track)'; 510 511 // Split the HTML into a stream of elements and text nodes. 512 $stream = wp_html_split( $pee ); 513 514 // Assume that the top level is pee-able. 515 $peeable = array( true ); 516 517 foreach ( $stream as $id => $droplet ) { 518 if ( '<' === substr( $droplet, 0, 1 ) ) { 519 if ( preg_match( '!<' . $emptyblocks . '(?: [^>]*)?>!s', $droplet ) ) { 520 // If we encounter an empty element, ignore it. 521 continue; 522 } elseif ( preg_match( '!^<.+/>$!s', $droplet ) ) { 523 // Ignore self-closing elements, too. 524 continue; 525 } elseif ( preg_match( '%^<!--.+-->$%s', $droplet ) ) { 526 // Comments can be ignored. 527 continue; 528 } elseif ( preg_match( '%^<!\[CDATA\[.+\]\]>$%s', $droplet ) ) { 529 // CDATA can totally be ignored. 530 continue; 531 } elseif ( preg_match( '!^</.+>$!s', $droplet ) ) { 532 // Here's closing element, let's move back up a level. 533 array_pop( $peeable ); 534 } elseif ( preg_match( '!^<' . $peeblocks . '(?: [^>]*)?>$!s', $droplet ) ) { 535 // We've just entered a pee-able block, mark it so. 536 $peeable[] = true; 537 } elseif ( preg_match( '!^<' . $mediablocks . '(?: [^>]*)?>$!s', $droplet ) ) { 538 // Media blocks can't really be pee'd, but they're handle later on. 539 $peeable[] = true; 540 } else { 541 $peeable[] = false; 542 } 543 544 // We can't pee an element, so move to the next droplet. 545 continue; 546 } 547 548 // If the current level can't be pee'd, protect it from being pee'd later. 549 if ( ! end( $peeable ) ) { 550 $stream[ $id ] = str_replace( "\n", '<!-- wpnl -->', $droplet ); 551 } 552 } 553 554 // If we accidentally marked the final newline as being unpee-able (for example, if there's 555 // some malformed HTML that didn't close properly), fix it. 556 if ( '<!-- wpnl -->' === $stream[ $id ] ) { 557 $stream[ $id ] = "\n"; 558 } 559 560 // Reform the HTML stream. 561 $pee = implode( $stream ); 496 562 497 563 // Add a double line break above block-level opening tags. 498 564 $pee = preg_replace( '!(<' . $allblocks . '[\s/>])!', "\n\n$1", $pee ); … … 500 566 // Add a double line break below block-level closing tags. 501 567 $pee = preg_replace( '!(</' . $allblocks . '>)!', "$1\n\n", $pee ); 502 568 569 // Add a double line break below block-level opening tags that are allowed to contain a <p>. 570 $pee = preg_replace( '%(<' . $peeblocks . '(?: [^>]*)?>)%', "$1\n\n", $pee ); 571 572 // Add a double line break above block-level closing tags that are allowed to contain a <p>. 573 $pee = preg_replace( '%(</' . $peeblocks . '>)%', "\n\n$1", $pee ); 574 503 575 // Standardize newline characters to "\n". 504 576 $pee = str_replace( array( "\r\n", "\r" ), "\n", $pee ); 505 577 … … 538 610 $pee = preg_replace( '|</figcaption>\s*|', '</figcaption>', $pee ); 539 611 } 540 612 613 // If there's only one paragraph inside a pee block, remove the newlines. 614 $pee = preg_replace( '%(<(' . $peeblocks . ")(?: [^>]*)?>)\n\n((?(?!\n\n).)*)\n\n(</\\2>)%s", '$1$3$4', $pee ); 615 541 616 // Remove more than two contiguous line breaks. 542 617 $pee = preg_replace( "/\n\n+/", "\n\n", $pee ); 543 618 … … 569 644 $pee = str_replace( '</blockquote></p>', '</p></blockquote>', $pee ); 570 645 571 646 // If an opening or closing block element tag is preceded by an opening <p> tag, remove it. 572 $pee = preg_replace( ' !<p>\s*(</?' . $allblocks . '[^>]*>)!', '$1', $pee );647 $pee = preg_replace( '%<p>(?:\s|<!-- wpnl -->)*(</?' . $allblocks . '[^>]*>)%', '$1', $pee ); 573 648 574 649 // If an opening or closing block element tag is followed by a closing <p> tag, remove it. 575 $pee = preg_replace( ' !(</?' . $allblocks . '[^>]*>)\s*</p>!', '$1', $pee );650 $pee = preg_replace( '%(</?' . $allblocks . '[^>]*>)(?:\s|<!-- wpnl -->)*</p>%', '$1', $pee ); 576 651 577 652 // Optionally insert line breaks. 578 653 if ( $br ) { -
tests/phpunit/tests/formatting/Autop.php
332 332 $content = array(); 333 333 334 334 foreach ( $blocks as $block ) { 335 if ( 'hr' === $block ) { 336 continue; 337 } 335 338 $content[] = "<$block>foo</$block>"; 336 339 } 337 340 … … 360 363 $content = array(); 361 364 362 365 foreach ( $blocks as $block ) { 366 if ( 'hr' === $block ) { 367 continue; 368 } 363 369 $content[] = "<$block attr='value'>foo</$block>"; 364 370 } 365 371 … … 506 512 } 507 513 508 514 /** 509 * wpautop() should convert multiple line breaks into a paragraph regar less of <br /> format515 * wpautop() should convert multiple line breaks into a paragraph regardless of <br /> format 510 516 * 511 517 * @ticket 33377 512 518 */ … … 558 564 $this->assertEquals( $expected2, trim( wpautop( $content2 ) ) ); 559 565 } 560 566 567 /** 568 * @ticket 38656 569 */ 570 function data_paragraphs_inside_blocks() { 571 $data = array( 572 array( 573 "<div>a\n\nb</div>", 574 "<div>\n<p>a</p>\n<p>b</p>\n</div>", 575 ), 576 array( 577 "<h1>a\n\nb</h1>", 578 "<h1>a\n\nb</h1>", 579 ), 580 array( 581 "<h1>a\nb</h1>", 582 "<h1>a\nb</h1>", 583 ), 584 array( 585 "<ul><li>a\n\nb</li></ul>", 586 "<ul>\n<li>\n<p>a</p>\n<p>b</p>\n</li>\n</ul>", 587 ), 588 array( 589 "<ul><li>a\n\n<ul><li>b\n\nc</li></ul></li></ul>", 590 "<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>", 591 ), 592 array( 593 "<div>a\n\n<hr>\n\nb</div>", 594 "<div>\n<p>a</p>\n<hr>\n<p>b</p>\n</div>", 595 ), 596 array( 597 "<table>\n\n<tr>\n\n<td>a\n\nb</td><td>\n\n<ul><li>c\n\n<ul><li>d\n\ne</li></ul>f\n\ng</li></ul>h</td>\n\n</tr>\n\n</table>", 598 "<table>\n<tr>\n<td>\n<p>a</p>\n<p>b</p>\n</td>\n<td>\n<ul>\n<li>\n<p>c</p>\n<ul>\n<li>\n<p>d</p>\n<p>e</p>\n</li>\n</ul>\n<p>f</p>\n<p>g</p>\n</li>\n</ul>\n<p>h</p>\n</td>\n</tr>\n</table>", 599 ), 600 ); 601 602 return $data; 603 } 604 605 /** 606 * @ticket 38656 607 * @dataProvider data_paragraphs_inside_blocks 608 */ 609 function test_paragraphs_inside_blocks( $content, $expected ) { 610 $this->assertEquals( $expected, trim( wpautop( $content ) ) ); 611 } 561 612 }