Ticket #47014: 47014-1.diff
| File 47014-1.diff, 5.9 KB (added by , 7 years ago) |
|---|
-
src/wp-includes/formatting.php
diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index 51a1388dfd..ea091d0b00 100644
a b function force_balance_tags( $text ) { 2465 2465 // WP bug fix for LOVE <3 (and other situations with '<' before a number) 2466 2466 $text = preg_replace( '#<([0-9]{1})#', '<$1', $text ); 2467 2467 2468 while ( preg_match( '/<(\/?[\w:]*)\s*([^>]*)>/', $text, $regex ) ) { 2468 $tag_pattern = ( 2469 '#<' . // start with an opening bracket 2470 '(/?)' . // Group 1 - if it's a closing tag it'll have a leading slash 2471 '(' . // Group 2 - tag name 2472 // custom element tags have more lenient rules than HTML tag names 2473 '(?:[a-z0-9]+(?:-[a-z0-9-]+)*)' . 2474 '|' . 2475 // traditional tag rules approximate HTML tag names 2476 '(?:[\w:]+)' . 2477 ')' . 2478 '(?:' . 2479 // we _either_ immediately close the tag with its '>' and have nothing here 2480 '\s*' . 2481 '(/?)' . // Group 3 - "attributes" for empty tag 2482 '|' . 2483 // _or_ we must start with space characters to separate the tag name from the attributes (or whitespace) 2484 '(\s+)' . // Group 4 - pre-attribute whitespace 2485 '([^>]*)' . // Group 5 - attributes 2486 ')' . 2487 '>#' // end with a closing bracket 2488 ); 2489 2490 while ( preg_match( $tag_pattern, $text, $regex ) ) { 2491 $full_match = $regex[0]; 2492 $has_leading_slash = ! empty( $regex[1] ); 2493 $tag_name = $regex[2]; 2494 $tag = strtolower( $tag_name ); 2495 $is_single_tag = in_array( $tag, $single_tags ); 2496 $pre_attribute_ws = isset( $regex[4] ) ? $regex[4] : ''; 2497 $attributes = trim( isset( $regex[5] ) ? $regex[5] : $regex[3] ); 2498 $has_self_closer = '/' === substr( $attributes, -1 ); 2499 2469 2500 $newtext .= $tagqueue; 2470 2501 2471 $i = strpos( $text, $ regex[0]);2472 $l = strlen( $ regex[0]);2502 $i = strpos( $text, $full_match ); 2503 $l = strlen( $full_match ); 2473 2504 2474 2505 // clear the shifter 2475 2506 $tagqueue = ''; 2476 2507 // Pop or Push 2477 if ( isset( $regex[1][0] ) && '/' == $regex[1][0] ) { // End Tag 2478 $tag = strtolower( substr( $regex[1], 1 ) ); 2508 if ( $has_leading_slash ) { // End Tag 2479 2509 // if too many closing tags 2480 2510 if ( $stacksize <= 0 ) { 2481 2511 $tag = ''; … … function force_balance_tags( $text ) { 2501 2531 $tag = ''; 2502 2532 } 2503 2533 } else { // Begin Tag 2504 $tag = strtolower( $regex[1] );2505 2506 2534 // Tag Cleaning 2507 2508 // If it's an empty tag "< >", do nothing 2509 if ( '' == $tag ) { 2510 // do nothing 2511 } elseif ( substr( $regex[2], -1 ) == '/' ) { // ElseIf it presents itself as a self-closing tag... 2535 if ( $has_self_closer ) { // If it presents itself as a self-closing tag... 2512 2536 // ...but it isn't a known single-entity self-closing tag, then don't let it be treated as such and 2513 2537 // immediately close it with a closing tag (the tag will encapsulate no text as a result) 2514 if ( ! in_array( $tag, $single_tags )) {2515 $ regex[2] = trim( substr( $regex[2], 0, -1 ) ) . "></$tag";2538 if ( ! $is_single_tag ) { 2539 $attributes = trim( substr( $attributes, 0, -1 ) ) . "></$tag"; 2516 2540 } 2517 } elseif ( in_array( $tag, $single_tags ) ) { // ElseIf it's a known single-entity tag but it doesn't close itself, do so 2518 $regex[2] .= '/'; 2541 } elseif ( $is_single_tag ) { // ElseIf it's a known single-entity tag but it doesn't close itself, do so 2542 $pre_attribute_ws = ' '; 2543 $attributes .= '/'; 2519 2544 } else { // Else it's not a single-entity tag 2520 2545 // If the top of the stack is the same as the tag we want to push, close previous tag 2521 2546 if ( $stacksize > 0 && ! in_array( $tag, $nestable_tags ) && $tagstack[ $stacksize - 1 ] == $tag ) { … … function force_balance_tags( $text ) { 2526 2551 } 2527 2552 2528 2553 // Attributes 2529 $attributes = $regex[2];2530 if ( ! empty( $attributes ) && $attributes[0] != '>' ) {2531 $ attributes = ' ' . $attributes;2554 if ( $has_self_closer && $is_single_tag ) { 2555 // we need some space - avoid <br/> and prefer <br /> 2556 $pre_attribute_ws = ' '; 2532 2557 } 2533 2558 2534 $tag = '<' . $tag . $ attributes . '>';2559 $tag = '<' . $tag . $pre_attribute_ws . $attributes . '>'; 2535 2560 //If already queuing a close tag, then put this tag on, too 2536 2561 if ( ! empty( $tagqueue ) ) { 2537 2562 $tagqueue .= $tag; -
tests/phpunit/tests/formatting/balanceTags.php
diff --git a/tests/phpunit/tests/formatting/balanceTags.php b/tests/phpunit/tests/formatting/balanceTags.php index 783c320780..aeb02d15ff 100644
a b class Tests_Formatting_BalanceTags extends WP_UnitTestCase { 68 68 '<em />', 69 69 '<p class="main1"/>', 70 70 '<p class="main2" />', 71 '<STRONG/>', 71 72 ); 72 73 $expected = array( 73 74 '<strong></strong>', 74 75 '<em></em>', 75 76 '<p class="main1"></p>', 76 77 '<p class="main2"></p>', 78 // Valid tags are transformed to lowercase. 79 '<strong></strong>', 77 80 ); 78 81 79 82 foreach ( $inputs as $key => $input ) { … … class Tests_Formatting_BalanceTags extends WP_UnitTestCase { 221 224 } 222 225 } 223 226 227 /** 228 * Get custom element data. 229 * 230 * @return array Data. 231 */ 232 public function data_custom_elements() { 233 return array( 234 // Valid custom element tags. 235 array( 236 '<my-custom-element>Test</my-custom-element>', 237 '<my-custom-element>Test</my-custom-element>', 238 ), 239 array( 240 '<my-custom-element>Test', 241 '<my-custom-element>Test</my-custom-element>', 242 ), 243 array( 244 'Test</my-custom-element>', 245 'Test', 246 ), 247 array( 248 '</my-custom-element>Test', 249 'Test', 250 ), 251 // Invalid (or at least temporarily unsupported) custom element tags. 252 array( 253 '<MY-CUSTOM-ELEMENT>Test', 254 '<MY-CUSTOM-ELEMENT>Test', 255 ), 256 array( 257 '<my->Test', 258 '<my->Test', 259 ), 260 array( 261 '<--->Test', 262 '<--->Test', 263 ), 264 ); 265 } 266 267 /** 268 * Test custom elements. 269 * 270 * @ticket 47014 271 * @dataProvider data_custom_elements 272 * 273 * @param string $source Source. 274 * @param string $expected Expected. 275 */ 276 public function test_custom_elements( $source, $expected ) { 277 $this->assertEquals( $expected, balanceTags( $source, true ) ); 278 } 224 279 }