Edgewall Software

Ticket #2048: ticket2048-patches.diff

File ticket2048-patches.diff, 11.8 KB (added by cboos, 4 years ago)

Updated patch - on top of source:/sandbox/context-refactoring@6135

  • trac/htdocs/css/trac.css

    diff -r 6d3496d9bdcd -r 75dc2a742e6a trac/htdocs/css/trac.css
    a b span.closed { text-decoration: line-thro 
    310310span.closed { text-decoration: line-through } 
    311311span.forbidden, a.forbidden { background: #fafaf0; color: #998; } 
    312312 
     313/* User-selectable styles for blocks */ 
     314.important { 
     315 background: #fcb; 
     316 border: 1px dotted #d00; 
     317 color: #500; 
     318 padding: 0 .5em 0 .5em; 
     319 margin: .5em; 
     320} 
     321 
    313322dl.wiki dt { font-weight: bold } 
    314323dl.compact dt { float: left; padding-right: .5em } 
    315324dl.compact dd { margin: 0; padding: 0 } 
  • trac/wiki/api.py

    diff -r 6d3496d9bdcd -r 75dc2a742e6a trac/wiki/api.py
    a b def parse_args(args, strict=True): 
    146146            else: 
    147147                m = re.match(r'\s*[^=]+=', arg) 
    148148            if m: 
    149                 kwargs[arg[:m.end()-1].strip()] = arg[m.end():] 
     149                kw = arg[:m.end()-1].strip() 
     150                if strict: 
     151                    kw = unicode(kw).encode('utf-8') 
     152                kwargs[kw] = arg[m.end():] 
    150153            else: 
    151154                largs.append(arg) 
    152155    return largs, kwargs 
  • trac/wiki/formatter.py

    diff -r 6d3496d9bdcd -r 75dc2a742e6a trac/wiki/formatter.py
    a b import urllib 
    2424 
    2525from StringIO import StringIO 
    2626 
    27 from genshi.builder import tag 
    28 from genshi.core import Stream 
     27from genshi.builder import tag, Element 
     28from genshi.core import Stream, Markup, escape 
     29from genshi.filters import HTMLSanitizer 
     30from genshi.input import HTMLParser, ParseError 
     31from genshi.util import plaintext 
    2932 
    3033from trac.core import * 
    3134from trac.mimeview import * 
    3235from trac.resource import get_relative_url 
    3336from trac.util.compat import set 
    34 from trac.wiki.api import WikiSystem 
     37from trac.wiki.api import WikiSystem, parse_args 
    3538from trac.wiki.parser import WikiParser 
    36 from trac.util.html import escape, plaintext, Markup, Element, html 
    3739from trac.util.text import shorten_line, to_unicode, \ 
    3840                           unicode_quote, unicode_quote_plus 
     41from trac.util.translation import _ 
    3942 
    4043__all__ = ['wiki_to_html', 'wiki_to_oneliner', 'wiki_to_outline', 
    4144           'Formatter', 'format_to', 'format_to_html', 'format_to_oneliner', 
    4245           'extract_link'] 
    4346 
    4447def system_message(msg, text=None): 
    45     return html.DIV(html.STRONG(msg), text and html.PRE(text), 
    46                     class_="system-message") 
     48    return tag.div(tag.strong(msg), text and tag.pre(text), 
     49                   class_="system-message") 
    4750 
    4851def _markup_to_unicode(markup): 
    4952    stream = None 
    class WikiProcessor(object): 
    6063 
    6164    _code_block_re = re.compile('^<div(?:\s+class="([^"]+)")?>(.*)</div>$') 
    6265 
    63     def __init__(self, formatter, name): 
    64         """Since 0.11: first argument is a Formatter instead of an Environment. 
     66    def __init__(self, formatter, name, args={}): 
     67        """Find the processor by name 
     68         
     69        :param formatter: the formatter embedding a call for this processor  
     70        :param name: the name of the processor  
     71        :param args: extra parameters for the processor 
     72 
     73        (since 0.11) 
    6574        """ 
    6675        self.formatter = formatter 
    6776        self.env = formatter.env 
    6877        self.name = name 
     78        self.args = args 
    6979        self.error = None 
    7080        self.macro_provider = None 
    7181 
    7282        builtin_processors = {'html': self._html_processor, 
    7383                              'default': self._default_processor, 
    74                               'comment': self._comment_processor} 
     84                              'comment': self._comment_processor, 
     85                              'div': self._div_processor, 
     86                              'span': self._span_processor, 
     87                              'Span': self._span_processor} 
     88 
     89        self._sanitizer = HTMLSanitizer(safe_attrs=HTMLSanitizer.SAFE_ATTRS | 
     90                                        set(['style'])) 
    7591         
    7692        self.processor = builtin_processors.get(name) 
    7793        if not self.processor: 
    class WikiProcessor(object): 
    107123    def _html_processor(self, text): 
    108124        if WikiSystem(self.env).render_unsafe_content: 
    109125            return Markup(text) 
    110         from genshi.input import HTMLParser, ParseError 
    111         from genshi.filters import HTMLSanitizer 
    112126        try: 
    113127            stream = Stream(HTMLParser(StringIO(text))) 
    114             sanitizer = HTMLSanitizer( 
    115                 safe_attrs=HTMLSanitizer.SAFE_ATTRS | set(['style']) 
    116             ) 
    117             return (stream | sanitizer).render('xhtml', encoding=None) 
     128            return (stream | self._sanitizer).render('xhtml', encoding=None) 
    118129        except ParseError, e: 
    119130            self.env.log.warn(e) 
    120             return system_message('HTML parsing error: %s' % escape(e.msg), 
    121                                   text.splitlines()[e.lineno - 1].strip()) 
     131            line = unicode(text).splitlines()[e.lineno - 1].strip() 
     132            return system_message(_('HTML parsing error: %(message)s', 
     133                                    message=escape(e.msg)), line) 
     134         
     135    def _elt_processor(self, eltname, format_to, text, args): 
     136        elt = getattr(tag, eltname)(**args) 
     137        if not WikiSystem(self.env).render_unsafe_content: 
     138            sanitized_elt = getattr(tag, eltname) 
     139            for (k,data,pos) in (Stream(elt) | self._sanitizer): 
     140                sanitized_elt.attrib = data[1] 
     141                break # only look at START (elt,attrs) 
     142            elt = sanitized_elt 
     143        elt.append(format_to(self.env, self.formatter.context, text)) 
     144        return elt 
     145 
     146    def _div_processor(self, text): 
     147        return self._elt_processor('div', format_to_html, text, self.args) 
     148     
     149    def _span_processor(self, text): 
     150        args, kwargs = parse_args(text, strict=True) 
     151        return self._elt_processor('span', format_to_oneliner, ', '.join(args), 
     152                                   kwargs) 
    122153 
    123154    # generic processors 
    124155 
    class WikiProcessor(object): 
    172203                elif text.startswith('<table'): 
    173204                    interrupt_paragraph = True 
    174205            if content_for_span: 
    175                 text = html.SPAN(class_='code-block')(*content_for_span) 
     206                text = tag.span(class_='code-block')(*content_for_span) 
    176207            elif interrupt_paragraph: 
    177208                text = "</p>%s<p>" % to_unicode(text) 
    178209        return text 
    class Formatter(object): 
    277308        return self.simple_tag_handler(match, '<sup>', '</sup>') 
    278309 
    279310    def _inlinecode_formatter(self, match, fullmatch): 
    280         return html.TT(fullmatch.group('inline')) 
     311        return tag.tt(fullmatch.group('inline')) 
    281312 
    282313    def _inlinecode2_formatter(self, match, fullmatch): 
    283         return html.TT(fullmatch.group('inline2')) 
     314        return tag.tt(fullmatch.group('inline2')) 
    284315 
    285316    # -- Post- IWikiSyntaxProvider rules 
    286317 
    class Formatter(object): 
    328359                                        path) 
    329360                if '?' in path: 
    330361                    query = '&' + query.lstrip('?') 
    331             return html.A(label or rel, href=path + query + fragment) 
     362            return tag.a(label or rel, href=path + query + fragment) 
    332363        else: 
    333364            return self._make_link(ns, target, match, label) 
    334365 
    class Formatter(object): 
    391422        local_url = self.env.config.get('project', 'url') or \ 
    392423                    (self.req or self.env).abs_href.base 
    393424        if not url.startswith(local_url): 
    394             return html.A(html.SPAN(text, class_="icon"), 
     425            return tag.a(tag.span(text, class_="icon"), 
    395426                          class_="ext-link", href=url, title=title or None) 
    396427        else: 
    397             return html.A(text, href=url, title=title or None) 
     428            return tag.a(text, href=url, title=title or None) 
    398429 
    399430    def _make_mail_link(self, url, text, title=''): 
    400         return html.A(html.SPAN(text, class_="icon"), 
     431        return tag.a(tag.span(text, class_="icon"), 
    401432                      class_="mail-link", href=url, title=title or None) 
    402433 
    403434    # WikiMacros 
    class Formatter(object): 
    708739            else: 
    709740                self.code_text += line + os.linesep 
    710741        elif not self.code_processor: 
    711             match = WikiParser._processor_re.search(line) 
     742            match = WikiParser._processor_re.match(line) 
    712743            if match: 
    713744                name = match.group(1) 
    714                 self.code_processor = WikiProcessor(self, name) 
     745                args = WikiParser._processor_param_re.split(line[len(name):]) 
     746                del args[::3] 
     747                keys = [str(k) for k in args[::2]] # used as keyword parameters 
     748                values = [v and v[0] in '"\'' and v[1:-1] or v 
     749                          for v in args[1::2]] 
     750                args = dict(zip(keys, values)) 
     751                self.code_processor = WikiProcessor(self, name, args) 
    715752            else: 
    716753                self.code_text += line + os.linesep  
    717754                self.code_processor = WikiProcessor(self, 'default') 
  • trac/wiki/parser.py

    diff -r 6d3496d9bdcd -r 75dc2a742e6a trac/wiki/parser.py
    a b class WikiParser(Component): 
    105105        r"(?P<table_cell>\|\|)"] 
    106106 
    107107    _processor_re = re.compile('#\!([\w+-][\w+-/]*)') 
     108    _processor_param_re = re.compile(r'''[\s;]*(\w+)=(".*?"|'.*?'|\w+)''') 
    108109    _anchor_re = re.compile('[^\w:.-]+', re.UNICODE) 
    109110 
    110111    def __init__(self): 
  • trac/wiki/tests/formatter.py

    diff -r 6d3496d9bdcd -r 75dc2a742e6a trac/wiki/tests/formatter.py
    a b class WikiTestCase(unittest.TestCase): 
    141141                g2 = ["%s\n" % x for x in match.group(2).split(r'\n')] 
    142142                diff = ''.join(list(difflib.unified_diff(g1, g2))) 
    143143                msg = '\n%s expected:\n%s\n%s actual:\n%s\n%s' \ 
    144                       '\nwiki text:\n%s\ndiff:\n%s' \ 
     144                      ' wiki text:\n%s\ndiff:\n%s' \ 
    145145                      % (sep, ''.join(g1), sep, ''.join(g2), sep, 
    146146# Tip: sometimes, 'expected' and 'actual' differ only by whitespace. 
    147147#      If so, replace the above lines by those two: 
  • trac/wiki/tests/wiki-tests.txt

    diff -r 6d3496d9bdcd -r 75dc2a742e6a trac/wiki/tests/wiki-tests.txt
    a b Paragraph 
    498498<div>Click me</div> 
    499499------------------------------ 
    500500 […] 
     501============================== div and span wiki processors 
     502And now it's [[span('''TIME FOR BED!,class=important)]]. Really. 
     503{{{ 
     504#!div ; class=important 
     505Go ahead, edit it freely. 
     506 
     507{{{ 
     508#!div; style="border: 2pt solid blue; margin: 1em; padding: .5em"; class=demo 
     509And now it's [[span('''TIME FOR BED! ''',class=important)]]. Really. 
     510}}} 
     511etc. 
     512}}} 
     513Done. 
     514------------------------------ 
     515<p> 
     516And now it's <span class="important"><strong>TIME FOR BED!</strong></span>. Really. 
     517</p> 
     518<div class="important"><p> 
     519Go ahead, edit it freely. 
     520</p> 
     521<div style="border: 2pt solid blue; margin: 1em; padding: .5em" class="demo"><p> 
     522And now it's <span class="important"><strong>TIME FOR BED! </strong></span>. Really. 
     523</p> 
     524</div><p> 
     525etc. 
     526</p> 
     527</div><p> 
     528Done. 
     529</p> 
     530------------------------------ 
     531And now it's [[span(...)]]. Really. 
     532 […] 
     533Done. 
     534============================== div and Span wiki processors 
     535{{{ 
     536#!div ; class="important" 
     537Go ahead, [[Span(''edit it freely'',class=important)]]. 
     538}}} 
     539Done. 
     540------------------------------ 
     541<div class="important"><p> 
     542Go ahead, <span class="important"><i>edit it freely</i></span>. 
     543</p> 
     544</div><p> 
     545Done. 
     546</p> 
     547------------------------------ 
     548 […] 
     549Done. 
    501550============================================================ 
    502551 
    503552        Wiki Macros