Edgewall Software

Ticket #4339: t4339.diff

File t4339.diff, 6.4 KB (added by Tim Hatch <trac@…>, 5 years ago)
  • trac/mimeview/

    old new  
    5959import re 
    6060from StringIO import StringIO 
    6161 
    62 from genshi import escape, Markup, Stream 
     62from genshi import escape, Markup, Stream, Attrs 
    6363from genshi.core import TEXT, START, END, START_NS, END_NS 
    6464from genshi.builder import Fragment, tag 
    6565from genshi.input import HTMLParser 
     
    624624        raise RequestDone 
    625625 
    626626 
    627 def _group_lines(stream): 
     627def _group_lines_core(stream): 
    628628    space_re = re.compile('(?P<spaces> (?: +))|^(?P<tag><\w+.*?>)?( )') 
    629629    def pad_spaces(match): 
    630630        m = match.group('spaces') 
     
    671671    buf = [] 
    672672    for kind, data, pos in _generate(): 
    673673        if kind is TEXT and data == '\n': 
    674             yield Stream(buf[:]) 
     674            yield buf 
    675675            del buf[:] 
    676676        else: 
    677677            if kind is TEXT: 
    678678                data = space_re.sub(pad_spaces, data) 
    679679            buf.append((kind, data, pos)) 
    680680    if buf: 
    681         yield Stream(buf[:]) 
     681        yield buf 
     682 
     683 
     684def _group_lines(stream): 
     685    stack = [] 
     686    for buf in _group_lines_core(stream): 
     687        # Remove empty text events 
     688        for i in range(len(buf)-1, -1, -1): 
     689            if buf[i][0] is TEXT and not buf[i][1]: 
     690                del buf[i] 
     691        # Remove silly open-and-immediately-close spans from the 
     692        # end of each line. 
     693        while len(buf) >= 2 and \ 
     694                buf[-2][0] is START and buf[-1][0] is END and \ 
     695                buf[-2][1][0] == buf[-1][1]: 
     696            del buf[-2:] 
     697        # Same for the start of the line. 
     698        while len(buf) >= 2 and \ 
     699                buf[0][0] is START and buf[1][0] is END and \ 
     700                buf[0][1][0] == buf[1][1]: 
     701            del buf[:2] 
     702        # Now go through and get rid of <span class=""> 
     703        # Make sure the stack is empty in case of invalid input 
     704        del stack[:] 
     705        noclass = Attrs([('class', '')]) 
     706         
     707        def stripclass(): 
     708            for e in buf: 
     709                if e[0] is START: 
     710                    if e[1][1] == noclass: 
     711                        stack.append(None) 
     712                    else: 
     713                        stack.append(e) 
     714                        yield e 
     715                elif e[0] is END: 
     716                    o = stack.pop() 
     717                    if o: 
     718                        yield e 
     719                else: 
     720                    yield e 
     721 
     722        nbuf = list(stripclass()) 
    682723 
     724        yield Stream(nbuf) 
    683725 
    684726# -- Default annotators 
    685727 
  • trac/mimeview/tests/

    old new  
    126126        lines = list(_group_lines(input)) 
    127127        self.assertEquals(len(lines), 1) 
    128128        self.assertTrue(isinstance(lines[0], Stream)) 
    129         self.assertEquals(lines[0].events, input) 
     129        self.assertEquals(lines[0].events, []) 
    130130 
    131131    def test_empty_text_in_span(self): 
    132132        """ 
     
    138138                 (END, ns.span, (None, -1, -1)), 
    139139                ] 
    140140        lines = list(_group_lines(input)) 
    141         self.assertEqual(len(lines), 1) 
    142         self.assertEqual(lines[0].render('html'), "<span></span>") 
     141        self.assertEquals(len(lines), 1) 
     142        self.assertEquals(lines[0].render('html'), "") 
    143143                  
    144144    def test_newline(self): 
    145145        """ 
     
    160160        ditto. 
    161161        """ 
    162162        input = HTMLParser(StringIO('<span class="c">\n\n\na</span>')) 
    163         expected = ['<span class="c"></span>', 
    164                     '<span class="c"></span>', 
    165                     '<span class="c"></span>', 
     163        expected = ['', 
     164                    '', 
     165                    '', 
    166166                    '<span class="c">a</span>', 
    167167                   ] 
    168168        lines = list(_group_lines(input)) 
     
    170170        for a, b in zip(lines, expected): 
    171171            self.assertEquals(a.render('xml'), b) 
    172172 
     173    def test_strip_empty_text(self): 
     174        """ 
     175        One part of 
     176        http://trac.edgewall.org/ticket/4339 
     177        """ 
     178        ns = Namespace('http://www.w3.org/1999/xhtml') 
     179        input = [(START, (ns.span, Attrs([('class', 5)])), (None, -1, -1)), 
     180                 (TEXT, "", (None, -1, -1)), 
     181                 (TEXT, "a", (None, -1, -1)), 
     182                 (END, ns.span, (None, -1, -1)), 
     183                ] 
     184        expected = [(START, (ns.span, Attrs([('class', 5)])), (None, -1, -1)), 
     185                    (TEXT, "a", (None, -1, -1)), 
     186                    (END, ns.span, (None, -1, -1)), 
     187                   ] 
     188        lines = list(_group_lines(input)) 
     189        self.assertEquals(len(lines), 1) 
     190        self.assertEquals(lines[0].render('html'), 
     191                          '<span class="5">a</span>') 
     192        for a, b in zip(lines[0], expected): 
     193            self.assertEquals(a, b) 
     194 
     195    def test_strip_noclass_span(self): 
     196        """ 
     197        One part of 
     198        http://trac.edgewall.org/ticket/4339 
     199        """ 
     200        ns = Namespace('http://www.w3.org/1999/xhtml') 
     201        input = [(START, (ns.span, Attrs([('class', '')])), (None, -1, -1)), 
     202                 (TEXT, "abc", (None, -1, -1)), 
     203                 (END, ns.span, (None, -1, -1)), 
     204                ] 
     205        expected = [(TEXT, "abc", (None, -1, -1))] 
     206         
     207        lines = list(_group_lines(input)) 
     208        self.assertEquals(len(lines), 1) 
     209        self.assertEquals(lines[0].render('html'), 'abc') 
     210        for a, b in zip(lines[0], expected): 
     211            self.assertEquals(a, b) 
     212 
     213    def test_strip_nested_noclass_span(self): 
     214        """ 
     215        One part of 
     216        http://trac.edgewall.org/ticket/4339 
     217        """ 
     218        ns = Namespace('http://www.w3.org/1999/xhtml') 
     219        input = [(START, (ns.em, Attrs([])), (None, -1, -1)), 
     220                 (START, (ns.span, Attrs([('class', '')])), (None, -1, -1)), 
     221                 (TEXT, "abc", (None, -1, -1)), 
     222                 (END, ns.span, (None, -1, -1)), 
     223                 (END, ns.em, (None, -1, -1)), 
     224                ] 
     225        expected = [(START, (ns.em, Attrs([])), (None, -1, -1)), 
     226                    (TEXT, "abc", (None, -1, -1)), 
     227                    (END, ns.em, (None, -1, -1)), 
     228                   ] 
     229         
     230        lines = list(_group_lines(input)) 
     231        self.assertEquals(len(lines), 1) 
     232        self.assertEquals(lines[0].render('html'), '<em>abc</em>') 
     233        for a, b in zip(lines[0], expected): 
     234            self.assertEquals(a, b) 
     235         
     236 
    173237 
    174238def suite(): 
    175239    suite = unittest.TestSuite()