Ticket #2048: ticket2048-patches.diff
| File ticket2048-patches.diff, 11.8 KB (added by cboos, 4 years ago) |
|---|
-
trac/htdocs/css/trac.css
diff -r 6d3496d9bdcd -r 75dc2a742e6a trac/htdocs/css/trac.css
a b span.closed { text-decoration: line-thro 310 310 span.closed { text-decoration: line-through } 311 311 span.forbidden, a.forbidden { background: #fafaf0; color: #998; } 312 312 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 313 322 dl.wiki dt { font-weight: bold } 314 323 dl.compact dt { float: left; padding-right: .5em } 315 324 dl.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): 146 146 else: 147 147 m = re.match(r'\s*[^=]+=', arg) 148 148 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():] 150 153 else: 151 154 largs.append(arg) 152 155 return largs, kwargs -
trac/wiki/formatter.py
diff -r 6d3496d9bdcd -r 75dc2a742e6a trac/wiki/formatter.py
a b import urllib 24 24 25 25 from StringIO import StringIO 26 26 27 from genshi.builder import tag 28 from genshi.core import Stream 27 from genshi.builder import tag, Element 28 from genshi.core import Stream, Markup, escape 29 from genshi.filters import HTMLSanitizer 30 from genshi.input import HTMLParser, ParseError 31 from genshi.util import plaintext 29 32 30 33 from trac.core import * 31 34 from trac.mimeview import * 32 35 from trac.resource import get_relative_url 33 36 from trac.util.compat import set 34 from trac.wiki.api import WikiSystem 37 from trac.wiki.api import WikiSystem, parse_args 35 38 from trac.wiki.parser import WikiParser 36 from trac.util.html import escape, plaintext, Markup, Element, html37 39 from trac.util.text import shorten_line, to_unicode, \ 38 40 unicode_quote, unicode_quote_plus 41 from trac.util.translation import _ 39 42 40 43 __all__ = ['wiki_to_html', 'wiki_to_oneliner', 'wiki_to_outline', 41 44 'Formatter', 'format_to', 'format_to_html', 'format_to_oneliner', 42 45 'extract_link'] 43 46 44 47 def 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") 47 50 48 51 def _markup_to_unicode(markup): 49 52 stream = None … … class WikiProcessor(object): 60 63 61 64 _code_block_re = re.compile('^<div(?:\s+class="([^"]+)")?>(.*)</div>$') 62 65 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) 65 74 """ 66 75 self.formatter = formatter 67 76 self.env = formatter.env 68 77 self.name = name 78 self.args = args 69 79 self.error = None 70 80 self.macro_provider = None 71 81 72 82 builtin_processors = {'html': self._html_processor, 73 83 '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'])) 75 91 76 92 self.processor = builtin_processors.get(name) 77 93 if not self.processor: … … class WikiProcessor(object): 107 123 def _html_processor(self, text): 108 124 if WikiSystem(self.env).render_unsafe_content: 109 125 return Markup(text) 110 from genshi.input import HTMLParser, ParseError111 from genshi.filters import HTMLSanitizer112 126 try: 113 127 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) 118 129 except ParseError, e: 119 130 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) 122 153 123 154 # generic processors 124 155 … … class WikiProcessor(object): 172 203 elif text.startswith('<table'): 173 204 interrupt_paragraph = True 174 205 if content_for_span: 175 text = html.SPAN(class_='code-block')(*content_for_span)206 text = tag.span(class_='code-block')(*content_for_span) 176 207 elif interrupt_paragraph: 177 208 text = "</p>%s<p>" % to_unicode(text) 178 209 return text … … class Formatter(object): 277 308 return self.simple_tag_handler(match, '<sup>', '</sup>') 278 309 279 310 def _inlinecode_formatter(self, match, fullmatch): 280 return html.TT(fullmatch.group('inline'))311 return tag.tt(fullmatch.group('inline')) 281 312 282 313 def _inlinecode2_formatter(self, match, fullmatch): 283 return html.TT(fullmatch.group('inline2'))314 return tag.tt(fullmatch.group('inline2')) 284 315 285 316 # -- Post- IWikiSyntaxProvider rules 286 317 … … class Formatter(object): 328 359 path) 329 360 if '?' in path: 330 361 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) 332 363 else: 333 364 return self._make_link(ns, target, match, label) 334 365 … … class Formatter(object): 391 422 local_url = self.env.config.get('project', 'url') or \ 392 423 (self.req or self.env).abs_href.base 393 424 if not url.startswith(local_url): 394 return html.A(html.SPAN(text, class_="icon"),425 return tag.a(tag.span(text, class_="icon"), 395 426 class_="ext-link", href=url, title=title or None) 396 427 else: 397 return html.A(text, href=url, title=title or None)428 return tag.a(text, href=url, title=title or None) 398 429 399 430 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"), 401 432 class_="mail-link", href=url, title=title or None) 402 433 403 434 # WikiMacros … … class Formatter(object): 708 739 else: 709 740 self.code_text += line + os.linesep 710 741 elif not self.code_processor: 711 match = WikiParser._processor_re. search(line)742 match = WikiParser._processor_re.match(line) 712 743 if match: 713 744 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) 715 752 else: 716 753 self.code_text += line + os.linesep 717 754 self.code_processor = WikiProcessor(self, 'default') -
trac/wiki/parser.py
diff -r 6d3496d9bdcd -r 75dc2a742e6a trac/wiki/parser.py
a b class WikiParser(Component): 105 105 r"(?P<table_cell>\|\|)"] 106 106 107 107 _processor_re = re.compile('#\!([\w+-][\w+-/]*)') 108 _processor_param_re = re.compile(r'''[\s;]*(\w+)=(".*?"|'.*?'|\w+)''') 108 109 _anchor_re = re.compile('[^\w:.-]+', re.UNICODE) 109 110 110 111 def __init__(self): -
trac/wiki/tests/formatter.py
diff -r 6d3496d9bdcd -r 75dc2a742e6a trac/wiki/tests/formatter.py
a b class WikiTestCase(unittest.TestCase): 141 141 g2 = ["%s\n" % x for x in match.group(2).split(r'\n')] 142 142 diff = ''.join(list(difflib.unified_diff(g1, g2))) 143 143 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' \ 145 145 % (sep, ''.join(g1), sep, ''.join(g2), sep, 146 146 # Tip: sometimes, 'expected' and 'actual' differ only by whitespace. 147 147 # 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 498 498 <div>Click me</div> 499 499 ------------------------------ 500 500 […] 501 ============================== div and span wiki processors 502 And now it's [[span('''TIME FOR BED!,class=important)]]. Really. 503 {{{ 504 #!div ; class=important 505 Go ahead, edit it freely. 506 507 {{{ 508 #!div; style="border: 2pt solid blue; margin: 1em; padding: .5em"; class=demo 509 And now it's [[span('''TIME FOR BED! ''',class=important)]]. Really. 510 }}} 511 etc. 512 }}} 513 Done. 514 ------------------------------ 515 <p> 516 And now it's <span class="important"><strong>TIME FOR BED!</strong></span>. Really. 517 </p> 518 <div class="important"><p> 519 Go ahead, edit it freely. 520 </p> 521 <div style="border: 2pt solid blue; margin: 1em; padding: .5em" class="demo"><p> 522 And now it's <span class="important"><strong>TIME FOR BED! </strong></span>. Really. 523 </p> 524 </div><p> 525 etc. 526 </p> 527 </div><p> 528 Done. 529 </p> 530 ------------------------------ 531 And now it's [[span(...)]]. Really. 532 […] 533 Done. 534 ============================== div and Span wiki processors 535 {{{ 536 #!div ; class="important" 537 Go ahead, [[Span(''edit it freely'',class=important)]]. 538 }}} 539 Done. 540 ------------------------------ 541 <div class="important"><p> 542 Go ahead, <span class="important"><i>edit it freely</i></span>. 543 </p> 544 </div><p> 545 Done. 546 </p> 547 ------------------------------ 548 […] 549 Done. 501 550 ============================================================ 502 551 503 552 Wiki Macros
