WordPress.org

Make WordPress Core

Ticket #4539: dev-snapshot-2010-11-21.php.diff

File dev-snapshot-2010-11-21.php.diff, 15.6 KB (added by norbertm, 8 years ago)
  • wordpress/wp-includes/formatting.php

     
    5656                $static_characters = array_merge(array('---', ' -- ', '--', ' - ', 'xn–', '...', '``', '\'\'', ' (tm)'), $cockney);
    5757                $static_replacements = array_merge(array('—', ' — ', '–', ' – ', 'xn--', '…', $opening_quote, $closing_quote, ' ™'), $cockneyreplace);
    5858
    59                 $dynamic_characters = array('/\'(\d\d(?:&#8217;|\')?s)/', '/\'(\d)/', '/(\s|\A|[([{<]|")\'/', '/(\d)"/', '/(\d)\'/', '/(\S)\'([^\'\s])/', '/(\s|\A|[([{<])"(?!\s)/', '/"(\s|\S|\Z)/', '/\'([\s.]|\Z)/', '/\b(\d+)x(\d+)\b/');
    60                 $dynamic_replacements = array('&#8217;$1','&#8217;$1', '$1&#8216;', '$1&#8243;', '$1&#8242;', '$1&#8217;$2', '$1' . $opening_quote . '$2', $closing_quote . '$1', '&#8217;$1', '$1&#215;$2');
     59                $dynamic_map = array(
     60                        '/([\A\s])\'(\d)/' => '$1&#8217;$2', // '99
    6161
     62                        '/([\w\]})])\'([\w])/' => '$1&#8217;$2', // test's
     63
     64                        '/\'([^\']*)\'/' => '&#8216;$1&#8217;', // 'asd'
     65                        '/"([^"]*)"/' => $opening_quote . '$1' . $closing_quote, // "qwe"
     66
     67                        '/(\d)\'/' => '$1&#8242;', // 9'
     68                        '/(\d)"/' => '$1&#8243;', // 9"
     69
     70                        '/\b(\d+)x(\d+)\b/' => '$1&#215;$2' // 97x34
     71                );
     72
     73                $dynamic_characters = array_keys( $dynamic_map );
     74                $dynamic_replacements = array_values( $dynamic_map );
     75
    6276                $static_setup = true;
    6377        }
    6478
     
    7084        $no_texturize_tags_stack = array();
    7185        $no_texturize_shortcodes_stack = array();
    7286
     87        $single_quote_state = '&#8216;';
     88        $double_quote_state = $opening_quote;
     89
     90        $text_node_count = 0;
     91        $whitespace_before_last_tag = false;
     92
    7393        for ( $i = 0; $i < $stop; $i++ ) {
    7494                $curl = $textarr[$i];
    7595
     
    7898                        // This is not a tag, nor is the texturization disabled
    7999                        // static strings
    80100                        $curl = str_replace($static_characters, $static_replacements, $curl);
     101                        // quotes after tags, e.g. <b>somebody</b>'s
     102                        if ( ( $text_node_count > 0 ) && ( ! $whitespace_before_last_tag ) ) {
     103                                $curl = preg_replace( '/^(\')/', '&#8217;', $curl );
     104                        }
    81105                        // regular expressions
    82106                        $curl = preg_replace($dynamic_characters, $dynamic_replacements, $curl);
     107                        // quotes that span multiple tags & shortcodes
     108                        while ( ( $pos = strpos( $curl, '\'' ) ) !== false ) {
     109                                $curl = preg_replace( '/\'/', $single_quote_state, $curl, 1 );
     110                                $single_quote_state = ( ( '&#8216;' == $single_quote_state ) ? '&#8217;' : '&#8216;' );
     111                        }
     112                        while ( ( $pos = strpos($curl, '"' ) ) !== false ) {
     113                                $curl = preg_replace( '/"/', $double_quote_state, $curl, 1 );
     114                                $double_quote_state = ( $opening_quote == $double_quote_state ) ? $closing_quote : $opening_quote;
     115                        }
     116                        // stats for quotes after tags above
     117                        $text_node_count++;
     118                        $whitespace_before_last_tag = ( preg_match('/\s$/', $curl) > 0 );
    83119                } elseif (!empty($curl)) {
    84120                        /*
    85121                         * Only call _wptexturize_pushpop_element if first char is correct
  • wp-testcase/test_includes_formatting.php

     
    385385        function test_bracketed_quotes_3810() {
    386386                $this->assertEquals('A dog (&#8220;Hubertus&#8221;) was sent out.', wptexturize('A dog ("Hubertus") was sent out.'));
    387387        }
    388        
     388
    389389        //WP Ticket #4539
    390390        function test_basic_quotes() {
     391                $this->assertNotEquals('&#8216;&#8217;', wptexturize("''")); // this does not work as expected due to a static replacement
     392                $this->assertEquals('&#8220;&#8221;', wptexturize('""'));
     393                $this->assertEquals('&#8220;&#8221;', wptexturize("``''")); // this is what causes '' to fail
     394                $this->assertEquals('&#8216; &#8217;', wptexturize("' '"));
     395                $this->assertEquals('&#8220; &#8221;', wptexturize('" "'));
     396                $this->assertEquals('&#8216;<img src="">&#8217;', wptexturize('\'<img src="">\''));
     397                $this->assertEquals('&#8220;<img src="">&#8221;', wptexturize('"<img src="">"'));
     398                $this->assertEquals('Peter&#8217;s photo: &#8216;<img src="">&#8217;', wptexturize('Peter\'s photo: \'<img src="">\''));
     399                $this->assertEquals('Peter&#8217;s photo: &#8220;<img src="">&#8221;', wptexturize('Peter\'s photo: "<img src="">"'));
     400
    391401                $this->assertEquals('test&#8217;s', wptexturize('test\'s'));
    392402                $this->assertEquals('test&#8217;s', wptexturize('test\'s'));
    393403
    394404                $this->assertEquals('&#8216;quoted&#8217;', wptexturize('\'quoted\''));
    395405                $this->assertEquals('&#8220;quoted&#8221;', wptexturize('"quoted"'));
     406                $this->assertEquals('&#8216;quoted&#8217;s&#8217;', wptexturize('\'quoted\'s\''));
     407                $this->assertEquals('&#8220;quoted&#8217;s&#8221;', wptexturize('"quoted\'s"'));
    396408
    397409                $this->assertEquals('(&#8216;quoted&#8217;)', wptexturize('(\'quoted\')'));
    398410                $this->assertEquals('{&#8220;quoted&#8221;}', wptexturize('{"quoted"}'));
     411                $this->assertEquals('["quoted"]', wptexturize('["quoted"]')); // shortcode
     412                $this->assertEquals('<"quoted">', wptexturize('<"quoted">')); // tag
     413                $this->assertEquals('(&#8216;quoted&#8217;s&#8217;)', wptexturize('(\'quoted\'s\')'));
     414                $this->assertEquals('{&#8220;quoted&#8217;s&#8221;}', wptexturize('{"quoted\'s"}'));
     415                $this->assertEquals('["quoted\'s"]', wptexturize('["quoted\'s"]')); // shortcode
     416                $this->assertEquals('<"quoted\'s">', wptexturize('<"quoted\'s">')); // tag
    399417
    400418                $this->assertEquals('&#8216;qu(ot)ed&#8217;', wptexturize('\'qu(ot)ed\''));
    401419                $this->assertEquals('&#8220;qu{ot}ed&#8221;', wptexturize('"qu{ot}ed"'));
     420                $this->assertEquals('&#8220;qu[ot]ed&#8221;', wptexturize('"qu[ot]ed"'));
     421                $this->assertEquals('&#8220;qu<ot>ed&#8221;', wptexturize('"qu<ot>ed"'));
     422                $this->assertEquals('&#8216;qu(ot)ed&#8217;s&#8217;', wptexturize('\'qu(ot)ed\'s\''));
     423                $this->assertEquals('&#8220;qu{ot}ed&#8217;s&#8221;', wptexturize('"qu{ot}ed\'s"'));
     424                $this->assertEquals('&#8220;qu[ot]ed&#8217;s&#8221;', wptexturize('"qu[ot]ed\'s"'));
     425                $this->assertEquals('&#8220;qu<ot>ed&#8217;s&#8221;', wptexturize('"qu<ot>ed\'s"'));
     426                $this->assertEquals('&#8216;qu(ot)&#8217;s&#8217;', wptexturize('\'qu(ot)\'s\''));
     427                $this->assertEquals('&#8220;qu{ot}&#8217;s&#8221;', wptexturize('"qu{ot}\'s"'));
     428                $this->assertEquals('&#8220;qu[ot]&#8217;s&#8221;', wptexturize('"qu[ot]\'s"'));
     429                $this->assertEquals('&#8220;qu<ot>&#8217;s&#8221;', wptexturize('"qu<ot>\'s"'));
    402430
    403431                $this->assertEquals('&#8216;test&#8217;s quoted&#8217;', wptexturize('\'test\'s quoted\''));
    404432                $this->assertEquals('&#8220;test&#8217;s quoted&#8221;', wptexturize('"test\'s quoted"'));
    405433        }
    406434
     435        //WP Ticket #4539
     436        function test_nested_quotes() {
     437                $this->assertEquals('&#8220;This is a &#8216;nested quote&#8217;.&#8221;', wptexturize('"This is a \'nested quote\'."'));
     438                $this->assertEquals('&#8216;This is a &#8220;nested quote&#8221;.&#8217;', wptexturize('\'This is a "nested quote".\''));
     439                $this->assertEquals('&#8220;These are some &#8216;nested&#8217; &#8216;quotes&#8217;.&#8221;', wptexturize('"These are some \'nested\' \'quotes\'."'));
     440                $this->assertEquals('&#8216;These are some &#8220;nested&#8221; &#8220;quotes&#8221;.&#8217;', wptexturize('\'These are some "nested" "quotes".\''));
     441        }
     442
    407443        //WP Tickets #4539, #15241
    408444        function test_full_sentences_with_unmatched_single_quotes() {
    409445                $this->assertEquals(
    410446                        'That means every moment you&#8217;re working on something without it being in the public it&#8217;s actually dying.',
    411447                        wptexturize("That means every moment you're working on something without it being in the public it's actually dying.")
    412448                );
     449                $this->assertEquals(
     450                        '&#8216;That means every moment you&#8217;re working on something without it being in the public it&#8217;s actually dying.&#8217;',
     451                        wptexturize("'That means every moment you're working on something without it being in the public it's actually dying.'")
     452                );
     453                $this->assertEquals(
     454                        '&#8220;That means every moment you&#8217;re working on something without it being in the public it&#8217;s actually dying.&#8221;',
     455                        wptexturize("\"That means every moment you're working on something without it being in the public it's actually dying.\"")
     456                );
     457                $this->assertEquals(
     458                        'That means every moment you&#8217;re working on &#8216;something&#8217; without it being in the public it&#8217;s actually dying.',
     459                        wptexturize("That means every moment you're working on 'something' without it being in the public it's actually dying.")
     460                );
     461                $this->assertEquals(
     462                        'That means every moment you&#8217;re working on &#8220;something&#8221; without it being in the public it&#8217;s actually dying.',
     463                        wptexturize("That means every moment you're working on \"something\" without it being in the public it's actually dying.")
     464                );
    413465        }
    414466
    415         //WP Ticket #4539
     467        //WP Tickets #4539, #10606
    416468        function test_quotes() {
    417469                $this->knownWPBug(4539);
    418470                $this->assertEquals('&#8220;Quoted String&#8221;', wptexturize('"Quoted String"'));
    419471                $this->assertEquals('Here is &#8220;<a href="http://example.com">a test with a link</a>&#8221;', wptexturize('Here is "<a href="http://example.com">a test with a link</a>"'));
     472                $this->assertEquals('Here is &#8220; <a href="http://example.com">a test with a link</a> &#8221;', wptexturize('Here is " <a href="http://example.com">a test with a link</a> "'));
     473                $this->assertEquals('Here is &#8220;<a href="http://example.com"> a test with a link </a>&#8221;', wptexturize('Here is "<a href="http://example.com"> a test with a link </a>"'));
    420474                $this->assertEquals('Here is &#8220;<a href="http://example.com">a test with a link and a period</a>&#8221;.', wptexturize('Here is "<a href="http://example.com">a test with a link and a period</a>".'));
    421475                $this->assertEquals('Here is &#8220;<a href="http://example.com">a test with a link</a>&#8221; and a space.', wptexturize('Here is "<a href="http://example.com">a test with a link</a>" and a space.'));
    422476                $this->assertEquals('Here is &#8220;<a href="http://example.com">a test with a link</a> and some text quoted&#8221;', wptexturize('Here is "<a href="http://example.com">a test with a link</a> and some text quoted"'));
     
    424478                $this->assertEquals('Here is &#8220;<a href="http://example.com">a test with a link</a>&#8221;; and a semi-colon.', wptexturize('Here is "<a href="http://example.com">a test with a link</a>"; and a semi-colon.'));
    425479                $this->assertEquals('Here is &#8220;<a href="http://example.com">a test with a link</a>&#8221;- and a dash.', wptexturize('Here is "<a href="http://example.com">a test with a link</a>"- and a dash.'));
    426480                $this->assertEquals('Here is &#8220;<a href="http://example.com">a test with a link</a>&#8221;&#8230; and ellipses.', wptexturize('Here is "<a href="http://example.com">a test with a link</a>"... and ellipses.'));
     481                $this->assertEquals('Here is &#8220;<a href="http://example.com">a test</a> with a link&#8221;.', wptexturize('Here is "<a href="http://example.com">a test</a> with a link".'));
    427482                $this->assertEquals('Here is &#8220;a test <a href="http://example.com">with a link</a>&#8221;.', wptexturize('Here is "a test <a href="http://example.com">with a link</a>".'));
    428                 $this->assertEquals('Here is &#8220;<a href="http://example.com">a test with a link</a>&#8221;and a work stuck to the end.', wptexturize('Here is "<a href="http://example.com">a test with a link</a>"and a work stuck to the end.'));
     483                $this->assertEquals('Here is &#8220;a test <a href="http://example.com">with a link</a>&#8221; .', wptexturize('Here is "a test <a href="http://example.com">with a link</a>" .'));
     484                $this->assertEquals('Here is &#8220;<a href="http://example.com">a test with a link</a>&#8221;and a word stuck to the end.', wptexturize('Here is "<a href="http://example.com">a test with a link</a>"and a word stuck to the end.'));
    429485                $this->assertEquals('A test with a finishing number, &#8220;like 23&#8221;.', wptexturize('A test with a finishing number, "like 23".'));
    430486                $this->assertEquals('A test with a number, &#8220;like 62&#8221;, is nice to have.', wptexturize('A test with a number, "like 62", is nice to have.'));
    431487        }
     
    451507                $this->assertEquals('&#8220;Class of 99&#8221;', wptexturize("\"Class of 99\""));
    452508                $this->assertEquals('&#8220;Class of &#8217;99&#8221;', wptexturize("\"Class of '99\""));
    453509        }
    454        
    455         function test_quotes_after_numbers() {
    456                 $this->assertEquals('Class of &#8217;99', wptexturize("Class of '99"));
    457         }
    458        
     510
    459511        //WP Ticket #15241
    460512        function test_other_html() {
    461513                $this->knownWPBug(15241);
    462514                $this->assertEquals('&#8216;<strong>', wptexturize("'<strong>"));
     515                $this->assertEquals('&#8220;<strong>', wptexturize('"<strong>'));
     516                $this->assertEquals('&#8216;<strong></strong>&#8217;', wptexturize("'<strong></strong>'"));
     517                $this->assertEquals('&#8220;<strong></strong>&#8221;', wptexturize('"<strong></strong>"'));
    463518                $this->assertEquals('&#8216;<strong>Quoted Text</strong>&#8217;,', wptexturize("'<strong>Quoted Text</strong>',"));
    464519                $this->assertEquals('&#8220;<strong>Quoted Text</strong>&#8221;,', wptexturize('"<strong>Quoted Text</strong>",'));
    465520        }
    466        
     521
     522        //WP Ticket #15241
     523        function test_many_single_quotes() {
     524                $this->assertEquals('This isn&#8217;t inherently bad, but I don&#8217;t think it&#8217;s normal.', wptexturize("This isn't inherently bad, but I don't think it's normal."));
     525        }
     526
     527        //WP Ticket #1258
     528        function test_enumeration() {
     529                $this->assertEquals("&#8216;products&#8217;, &#8216;services&#8217;", wptexturize("'products', 'services'"));
     530                $this->assertEquals("&#8216;hello&#8217;, &#8216;world&#8217;, &#8217;tis", wptexturize("'hello', 'world', 'tis"));
     531                $this->assertEquals("&#8216;hello&#8217;, &#8216;world&#8217;, &#8217;tis ", wptexturize("'hello', 'world', 'tis "));
     532        }
     533
     534        //WP Ticket #11275
     535        function test_quoting() {
     536                $this->assertEquals('She said—&#8220;No!&#8221;', wptexturize('She said—"No!"'));
     537                $this->assertEquals('She said — &#8220;No!&#8221;', wptexturize('She said — "No!"'));
     538                $this->assertEquals('She said—&#8220;<a href="#">No!</a>&#8221;', wptexturize('She said—"<a href="#">No!</a>"'));
     539                $this->assertEquals('She said—&#8216;<a href="#">It&#8217;s Peter&#8217;s!</a>&#8217;', wptexturize('She said—\'<a href="#">It\'s Peter\'s!</a>\''));
     540                $this->assertEquals('She said—&#8220;<a href="#">It&#8217;s Peter&#8217;s!</a>&#8221;', wptexturize('She said—"<a href="#">It\'s Peter\'s!</a>"'));
     541        }
     542
     543        //WP Ticket #15444
     544        function test_tag_followed_by_quote() {
     545                $this->knownWPBug(15444);
     546                $this->assertEquals('<a href="#">Jim</a>&#8217;s red bike.', wptexturize('<a href="#">Jim</a>\'s red bike.'));
     547                $this->assertEquals('&#8216;<a href="#">Jim</a>&#8217;s red bike.&#8217;', wptexturize('\'<a href="#">Jim</a>\'s red bike.\''));
     548                $this->assertEquals('&#8220;<a href="#">Jim</a>&#8217;s red bike.&#8221;', wptexturize('"<a href="#">Jim</a>\'s red bike."'));
     549                $this->assertEquals('<a href="#">Jim</a>&#8217;s &#8216;red bike.&#8217;', wptexturize('<a href="#">Jim</a>\'s \'red bike.\''));
     550                $this->assertEquals('<a href="#">Jim</a>&#8217;s &#8220;red bike.&#8221;', wptexturize('<a href="#">Jim</a>\'s "red bike."'));
     551                $this->assertEquals('<a href="#">Jim</a>&#8217;s &#8216;<a href="#">red bike</a>.&#8217;', wptexturize('<a href="#">Jim</a>\'s \'<a href="#">red bike</a>.\''));
     552                $this->assertEquals('<a href="#">Jim</a>&#8217;s &#8220;<a href="#">red bike</a>.&#8221;', wptexturize('<a href="#">Jim</a>\'s "<a href="#">red bike</a>."'));
     553        }
     554
    467555        function test_x() {
    468556                $this->assertEquals('14&#215;24', wptexturize("14x24"));
     557                $this->assertEquals('&#8216;14&#215;24&#8217;', wptexturize("'14x24'"));
     558                $this->assertEquals('&#8220;14&#215;24&#8221;', wptexturize('"14x24"'));
     559                $this->assertEquals('&#8216;<a href="#">14&#215;24</a>&#8217;', wptexturize('\'<a href="#">14x24</a>\''));
     560                $this->assertEquals('&#8220;<a href="#">14&#215;24</a>&#8221;', wptexturize('"<a href="#">14x24</a>"'));
    469561        }
    470562       
    471563        function test_minutes_seconds() {