Ticket #38656: 38656.3.diff
File 38656.3.diff, 6.8 KB (added by , 8 years ago) |
---|
-
src/wp-includes/formatting.php
466 466 // Change multiple <br>s into two line breaks, which will turn into paragraphs. 467 467 $pee = preg_replace('|<br\s*/?>\s*<br\s*/?>|', "\n\n", $pee); 468 468 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 $allblocks = "(?:$peeblocks|$peefreeblocks)"; 476 $peeblocks = "(?:$peeblocks)"; 477 $peefreeblocks = "(?:$peefreeblocks)"; 478 479 // Empty elements that cannot contain anything. 480 $emptyblocks = "(?:hr|br)"; 481 482 // Media elements that will be processed later. 483 $mediablocks = "(?:object|param|embed|audio|video|source|track)"; 484 485 // Split the HTML into a stream of elements and text nodes. 486 $stream = wp_html_split( $pee ); 487 488 // Assume that the top level is pee-able. 489 $peeable = array( true ); 490 491 foreach ( $stream as $id => $droplet ) { 492 if ( '<' === substr( $droplet, 0, 1 ) ) { 493 if ( preg_match( '!<' . $emptyblocks . '(?: [^>]*)?>!s', $droplet ) ) { 494 // If we encounter an empty element, ignore it. 495 continue; 496 } elseif ( preg_match( '!^<.+/>$!s', $droplet ) ) { 497 // Ignore self-closing elements, too. 498 continue; 499 } elseif ( preg_match( '%^<!--.+-->$%s', $droplet ) ) { 500 // Comments can be ignored. 501 continue; 502 } elseif ( preg_match( '%^<!\[CDATA\[.+\]\]>$%s', $droplet ) ) { 503 // CDATA can totally be ignored. 504 continue; 505 } elseif ( preg_match( '!^</.+>$!s', $droplet ) ) { 506 // Here's closing element, let's move back up a level. 507 array_pop( $peeable ); 508 } elseif ( preg_match( '!^<' . $peeblocks . '(?: [^>]*)?>$!s', $droplet ) ) { 509 // We've just entered a pee-able block, mark it so. 510 $peeable[] = true; 511 } elseif ( preg_match( '!^<' . $mediablocks . '(?: [^>]*)?>$!s', $droplet ) ) { 512 // Media blocks can't really be pee'd, but they're handle later on. 513 $peeable[] = true; 514 } else { 515 $peeable[] = false; 516 } 517 518 // We can't pee an element, so move to the next droplet. 519 continue; 520 } 521 522 // If the current level can't be pee'd, protect it from being pee'd later. 523 if( ! end( $peeable ) ) { 524 $stream[ $id ] = str_replace( "\n", '<!-- wpnl -->', $droplet ); 525 } 526 } 527 528 // If we accidentally marked the final newline as being unpee-able (for example, if there's 529 // some malformed HTML that didn't close properly), fix it. 530 if ( '<!-- wpnl -->' === $stream[ $id ] ) { 531 $stream[ $id ] = "\n"; 532 } 533 534 // Reform the HTML stream. 535 $pee = implode( $stream ); 470 536 471 537 // Add a double line break above block-level opening tags. 472 538 $pee = preg_replace('!(<' . $allblocks . '[\s/>])!', "\n\n$1", $pee); … … 474 540 // Add a double line break below block-level closing tags. 475 541 $pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee); 476 542 543 // Add a double line break below block-level opening tags that are allowed to contain a <p>. 544 $pee = preg_replace('%(<' . $peeblocks . '(?: [^>]*)?>)%', "$1\n\n", $pee); 545 546 // Add a double line break above block-level closing tags that are allowed to contain a <p>. 547 $pee = preg_replace('%(</' . $peeblocks . '>)%', "\n\n$1", $pee); 548 477 549 // Standardize newline characters to "\n". 478 550 $pee = str_replace(array("\r\n", "\r"), "\n", $pee); 479 551 … … 506 578 $pee = preg_replace( '%\s*(<(?:source|track)[^>]*>)\s*%', '$1', $pee ); 507 579 } 508 580 581 // If there's only one paragraph inside a pee block, remove the newlines. 582 $pee = preg_replace( '%(<(' . $peeblocks . ")(?: [^>]*)?>)\n\n((?(?!\n\n).)*)\n\n(</\\2>)%s", '$1$3$4', $pee ); 583 509 584 // Remove more than two contiguous line breaks. 510 585 $pee = preg_replace("/\n\n+/", "\n\n", $pee); 511 586 … … 537 612 $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee); 538 613 539 614 // 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);615 $pee = preg_replace('%<p>(?:\s|<!-- wpnl -->)*(</?' . $allblocks . '[^>]*>)%', "$1", $pee); 541 616 542 617 // 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);618 $pee = preg_replace('%(</?' . $allblocks . '[^>]*>)(?:\s|<!-- wpnl -->)*</p>%', "$1", $pee); 544 619 545 620 // Optionally insert line breaks. 546 621 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 … … 534 540 535 541 $this->assertEquals( $expected, trim( wpautop( $content ) ) ); 536 542 } 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 array( 570 "<div>a\n\n<hr>\n\nb</div>", 571 "<div>\n<p>a</p>\n<hr>\n<p>b</p>\n</div>", 572 ), 573 array( 574 "<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>", 575 "<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>", 576 ) 577 ); 578 579 return $data; 580 } 581 582 /** 583 * @ticket 38656 584 * @dataProvider data_paragraphs_inside_blocks 585 */ 586 function test_paragraphs_inside_blocks( $content, $expected ) { 587 $this->assertEquals( $expected, trim( wpautop( $content ) ) ); 588 } 537 589 }