Ticket #4356: trac_wiki_creole-r9337.patch
| File trac_wiki_creole-r9337.patch, 13.5 KB (added by cboos, 2 years ago) |
|---|
-
trac/wiki/formatter.py
WikiFormatting: add some support for WikiCreole (#4356) - `**` token for bold and `//` token for italic. Note that they should be matched by themselves, i.e. one can't use `'''` to match `**` or `''` to match `//` - `[[target]]` or `[[target|label]]` TracLinks. If `target` has to contain a `|` character, it must be wrapped in a string quote, as usual with TracLinks. The content of `[[]]` can't contain the `]]` substring. Note that support for the [[http://meta.wikimedia.org/wiki/Help:Piped_link#Pipe_trick|pipe trick]] is simply "emulated" (and to some extent only), as the wiki text is not converted before save. It is consistent with the removal of the scheme we do anyway. The reverse pipe trick is not operational yet. diff --git a/trac/wiki/formatter.py b/trac/wiki/formatter.py
a b class Formatter(object): 408 408 409 409 def _bold_formatter(self, match, fullmatch): 410 410 return self.simple_tag_handler(match, '<strong>', '</strong>') 411 # should be <b> 412 413 def _bold_wc_formatter(self, match, fullmatch): 414 return self.simple_tag_handler(match, '<b>', '</b>') 415 # should be <strong> 411 416 412 417 def _italic_formatter(self, match, fullmatch): 413 418 return self.simple_tag_handler(match, '<i>', '</i>') 414 419 420 def _italic_wc_formatter(self, match, fullmatch): 421 return self.simple_tag_handler(match, '<em>', '</em>') 422 415 423 def _underline_formatter(self, match, fullmatch): 416 424 return self.simple_tag_handler(match, '<span class="underline">', 417 425 '</span>') … … class Formatter(object): 473 481 ns = fullmatch.group('lns') 474 482 target = self._unquote(fullmatch.group('ltgt')) 475 483 label = fullmatch.group('label') 484 return self._make_lhref_link(match, fullmatch, rel, ns, target, label) 485 486 def _make_lhref_link(self, match, fullmatch, rel, ns, target, label): 476 487 if not label: # e.g. `[http://target]` or `[wiki:target]` 477 488 if target: 478 489 if target.startswith('//'): # for `[http://target]` … … class Formatter(object): 512 523 query = '&' + query.lstrip('?') 513 524 return tag.a(label, href=path + query + fragment) 514 525 else: 515 return self._make_link(ns, target, match, label, fullmatch) 526 return self._make_link(ns or 'wiki', target or '', match, label, 527 fullmatch) 516 528 517 529 def _make_link(self, ns, target, match, label, fullmatch): 518 530 # first check for an alias defined in trac.ini … … class Formatter(object): 610 622 label = format_to_oneliner(self.env, self.context, label) 611 623 return '<span class="wikianchor" id="%s">%s</span>' % (anchor, label) 612 624 613 # WikiMacros 625 # WikiMacros or WikiCreole links 626 627 def _macrolink_formatter(self, match, fullmatch): 628 # check for a known [[macro]] 629 macro_or_link = match[2:-2] 630 fullmatch = WikiParser._macro_re.match(macro_or_link) 631 if fullmatch: 632 name = fullmatch.group('macroname') 633 args = fullmatch.group('macroargs') 634 macro = False # not a macro 635 macrolist = name[-1] == '?' 636 if name.lower() == 'br' or name == '?': 637 macro = None 638 else: 639 macro = WikiProcessor(self, (name, name[:-1])[macrolist]) 640 if macro.error: 641 macro = False 642 if macro is not False: 643 if macrolist: 644 macro = WikiProcessor(self, 'MacroList') 645 return self._macro_formatter(match, fullmatch, macro) 646 fullmatch = WikiParser._creolelink_re.match(macro_or_link) 647 return self._lhref_formatter(match, fullmatch) 614 648 615 def _macro_formatter(self, match, fullmatch ):649 def _macro_formatter(self, match, fullmatch, macro=None): 616 650 name = fullmatch.group('macroname') 617 651 if name.lower() == 'br': 618 652 return '<br />' 619 653 if name and name[-1] == '?': # Macro?() shortcut for MacroList(Macro) 620 654 args = name[:-1] or '*' 621 name = 'MacroList'622 655 else: 623 656 args = fullmatch.group('macroargs') 624 657 try: 625 macro = WikiProcessor(self, name)626 658 return macro.process(args, in_paragraph=True) 627 659 except Exception, e: 628 660 self.env.log.error('Macro %s(%s) failed: %s' % … … class OneLinerFormatter(Formatter): 1202 1234 def _table_row_sep_formatter(self, match, fullmatch): 1203 1235 return '' 1204 1236 1205 def _macro_formatter(self, match, fullmatch ):1237 def _macro_formatter(self, match, fullmatch, macro=None): 1206 1238 name = fullmatch.group('macroname') 1207 1239 if name.lower() == 'br': 1208 1240 return ' ' … … class OutlineFormatter(Formatter): 1265 1297 1266 1298 # Avoid the possible side-effects of rendering WikiProcessors 1267 1299 1268 def _macro_formatter(self, match, fullmatch ):1300 def _macro_formatter(self, match, fullmatch, macro=None): 1269 1301 return '' 1270 1302 1271 1303 def handle_code_block(self, line, startmatch=None): -
trac/wiki/parser.py
diff --git a/trac/wiki/parser.py b/trac/wiki/parser.py
a b class WikiParser(Component): 30 30 31 31 BOLDITALIC_TOKEN = "'''''" 32 32 BOLD_TOKEN = "'''" 33 BOLD_TOKEN_WIKICREOLE = r"\*\*" 33 34 ITALIC_TOKEN = "''" 35 ITALIC_TOKEN_WIKICREOLE = "//" 34 36 UNDERLINE_TOKEN = "__" 35 37 STRIKE_TOKEN = "~~" 36 38 SUBSCRIPT_TOKEN = ",," … … class WikiParser(Component): 63 65 # Font styles 64 66 r"(?P<bolditalic>!?%s)" % BOLDITALIC_TOKEN, 65 67 r"(?P<bold>!?%s)" % BOLD_TOKEN, 68 r"(?P<bold_wc>!?%s)" % BOLD_TOKEN_WIKICREOLE, 66 69 r"(?P<italic>!?%s)" % ITALIC_TOKEN, 70 r"(?P<italic_wc>!?%s)" % ITALIC_TOKEN_WIKICREOLE, 67 71 r"(?P<underline>!?%s)" % UNDERLINE_TOKEN, 68 72 r"(?P<strike>!?%s)" % STRIKE_TOKEN, 69 73 r"(?P<subscript>!?%s)" % SUBSCRIPT_TOKEN, … … class WikiParser(Component): 71 75 r"(?P<inlinecode>!?%s(?P<inline>.*?)%s)" \ 72 76 % (STARTBLOCK_TOKEN, ENDBLOCK_TOKEN), 73 77 r"(?P<inlinecode2>!?%s(?P<inline2>.*?)%s)" \ 74 % (INLINE_TOKEN, INLINE_TOKEN)] 78 % (INLINE_TOKEN, INLINE_TOKEN), 79 ] 75 80 76 81 # Rules provided by IWikiSyntaxProviders will be inserted here 77 82 … … class WikiParser(Component): 96 101 # [=#anchor] creation 97 102 (r"(?P<anchor>!?\[=#(?P<anchorname>%s)" % XML_NAME + 98 103 "(?P<anchorlabel>\s+[^\]]*)?\])"), 99 # [[macro]] call 100 (r"(?P<macro>!?\[\[(?P<macroname>[\w/+-]+\??|\?)" 101 r"(\]\]|\((?P<macroargs>.*?)\)\]\]))"), 104 # [[macro]] call or [[WikiCreole link]] 105 (r"(?P<macrolink>!?\[\[(?:[^]]|][^]])*\]\])"), 102 106 # == heading == #hanchor 103 107 r"(?P<heading>^\s*(?P<hdepth>={1,6})\s(?P<htext>.*?)" 104 108 r"(?P<hanchor>#%s)?\s*$)" % XML_NAME, … … class WikiParser(Component): 125 129 _startblock_re = re.compile(r"\s*%s(?:%s|\s*$)" % 126 130 (STARTBLOCK, PROCESSOR)) 127 131 _processor_param_re = re.compile(PROCESSOR_PARAM) 128 _anchor_re = re.compile('[^\w:.-]+', re.UNICODE) 132 _anchor_re = re.compile(r'[^\w:.-]+', re.UNICODE) 133 134 _macro_re = re.compile(r''' 135 (?P<macroname> [\w/+-]+ \?? | \? ) # macro, macro? or ? 136 (?: \( (?P<macroargs> .*? ) \) )? $ # optional arguments within () 137 ''', re.VERBOSE) 138 139 _creolelink_re = re.compile(r''' 140 (?: 141 (?P<rel> %(rel)s ) # rel is "./..." or "/..." 142 | (?: (?P<lns> %(scheme)s ) : )? # lns is the optional "scheme:" 143 (?P<ltgt> # ltgt is the optional target 144 %(scheme)s : (?:%(quoted)s) # - "scheme:'...quoted..'" 145 | %(quoted)s # - "'...quoted...'" 146 | [^|]+ # - anything but a '|' 147 )? 148 ) 149 \s* (?: \| (?P<label> .* ) )? # optional label after a '|' 150 151 ''' % {'rel': LHREF_RELATIVE_TARGET, 152 'scheme': LINK_SCHEME, 153 'quoted': QUOTED_STRING}, re.VERBOSE) 129 154 130 155 def __init__(self): 131 156 self._compiled_rules = None -
trac/wiki/tests/wiki-tests.txt
diff --git a/trac/wiki/tests/wiki-tests.txt b/trac/wiki/tests/wiki-tests.txt
a b This should be '''''bold and italic''''' 9 9 This should be <strong><i>bold and italic</i></strong> 10 10 </p> 11 11 ------------------------------ 12 ============================== Multiline bold italic markup (WikiCreole) 13 **//bold 14 italic (//not italic//) 15 multiline//** 16 ------------------------------ 17 <p> 18 <b><em>bold 19 italic (</em>not italic<em>) 20 multiline</em></b> 21 </p> 22 ------------------------------ 12 23 ============================== Problematic markup: comma-separated list with a time + bold markup 13 24 23:59,'''test''',123 14 25 ------------------------------ … … rfc-2396.compatible://link 433 444 <a class="ext-link" href="rfc-2396.compatible://link"><span class="icon"> </span>RFC 2396</a> 434 445 </p> 435 446 ------------------------------ 447 ============================== WikiCreole style for the above examples 448 [[link:WikiStart| Foo]] [[http://www.edgewall.com/|Edgewall]] 449 450 [[link:Foo Bar|Foo Bar]] [[link:Foo Bar#baz|Foo Bar]] 451 452 [[Foo Bar]] [[Foo Bar|Fu Bar]] [[Foo Bar#baz|Foo Bar]] 453 454 [[link:Argv|"*argv[] versus **argv"]] 455 456 [[link:test|"test.txt", line 123]] 457 458 [[link:pl/de|%de]] 459 460 i.e. [[mailto:cboos@neuf.fr|me]] 461 462 [[th:]] 463 [[th:|Trac Hacks]] 464 465 [[svn+ssh://secureserver.org|SVN link]] 466 [[rfc-2396.compatible://link|RFC 2396]] 467 ------------------------------ 468 <p> 469 <a class="text resolver" href="/stuff/WikiStart"> Foo</a> <a class="ext-link" href="http://www.edgewall.com/"><span class="icon"> </span>Edgewall</a> 470 </p> 471 <p> 472 <a class="text resolver" href="/stuff/Foo%20Bar">Foo Bar</a> <a class="text resolver" href="/stuff/Foo%20Bar%23baz">Foo Bar</a> 473 </p> 474 <p> 475 <a class="missing wiki" href="/wiki/Foo%20Bar" rel="nofollow">Foo Bar?</a> <a class="missing wiki" href="/wiki/Foo%20Bar" rel="nofollow">Fu Bar?</a> <a class="missing wiki" href="/wiki/Foo%20Bar#baz" rel="nofollow">Foo Bar?</a> 476 </p> 477 <p> 478 <a class="text resolver" href="/stuff/Argv">*argv[] versus **argv</a> 479 </p> 480 <p> 481 <a class="text resolver" href="/stuff/test">"test.txt", line 123</a> 482 </p> 483 <p> 484 <a class="text resolver" href="/stuff/pl/de">%de</a> 485 </p> 486 <p> 487 i.e. <a class="mail-link" href="mailto:cboos@neuf.fr"><span class="icon"> </span>me</a> 488 </p> 489 <p> 490 <a class="ext-link" href="http://trac-hacks.org/intertrac/" title="Trac Hacks"><span class="icon"> </span>th</a> 491 <a class="ext-link" href="http://trac-hacks.org/intertrac/" title="Trac Hacks"><span class="icon"> </span>Trac Hacks</a> 492 </p> 493 <p> 494 <a class="ext-link" href="svn+ssh://secureserver.org"><span class="icon"> </span>SVN link</a> 495 <a class="ext-link" href="rfc-2396.compatible://link"><span class="icon"> </span>RFC 2396</a> 496 </p> 497 ------------------------------ 498 ============================== More WikiCreole examples 499 [[coffeehouse setup|How to set up a coffee house]] 500 501 [[link:Template]] 502 [[link:Template|]] 503 504 [[trac:wiki:Pipe (computing)|]] 505 [[trac:wiki:Pipe (computing)|]] 506 507 [[|b]] (might change to relative) 508 ------------------------------ 509 <p> 510 <a class="missing wiki" href="/wiki/coffeehouse%20setup" rel="nofollow">How to set up a coffee house?</a> 511 </p> 512 <p> 513 <a class="text resolver" href="/stuff/Template">Template</a> 514 <a class="text resolver" href="/stuff/Template">Template</a> 515 </p> 516 <p> 517 <a class="ext-link" href="http://trac.edgewall.org/intertrac/wiki%3APipe%20%28computing%29" title="wiki:Pipe (computing) in Trac's Trac"><span class="icon"> </span>trac:wiki:Pipe (computing)</a> 518 <a class="ext-link" href="http://trac.edgewall.org/intertrac/wiki%3APipe%20%28computing%29" title="wiki:Pipe (computing) in Trac's Trac"><span class="icon"> </span>trac:wiki:Pipe (computing)</a> 519 </p> 520 <p> 521 <a class="wiki" href="/wiki/WikiStart">b</a> (might change to relative) 522 </p> 523 ------------------------------ 436 524 ============================== Link resolver counter examples 437 525 Test:[[BR]] There should be a 438 526 line break … … Hello, Hello World, args = hej hopp 862 950 </p> 863 951 ------------------------------ 864 952 Hello, [[HelloWorld(...)]] 865 ============================== Bad macro call 953 ============================== Bad macro call, but valid WikiCreole link 866 954 [[HelloWorld(hej hopp) ]] # This shouldnt executed as macro since it contain whitespace between ) and ] 867 955 ------------------------------ 868 956 <p> 869 [[<a class="missing wiki" href="/wiki/HelloWorld" rel="nofollow">HelloWorld?</a>(hej hopp) ]]# This shouldnt executed as macro since it contain whitespace between ) and ]957 <a class="missing wiki" href="/wiki/HelloWorld%28hej%20hopp%29%20" rel="nofollow">HelloWorld(hej hopp) ?</a> # This shouldnt executed as macro since it contain whitespace between ) and ] 870 958 </p> 871 959 ------------------------------ 872 [[<a class="missing wiki" href="/wiki/HelloWorld" rel="nofollow">HelloWorld?</a>(hej hopp) ]]# This shouldnt executed as macro since it contain whitespace between ) and ]960 <a class="missing wiki" href="/wiki/HelloWorld%28hej%20hopp%29%20" rel="nofollow">HelloWorld(hej hopp) ?</a> # This shouldnt executed as macro since it contain whitespace between ) and ] 873 961 ============================== Another bad macro call 874 962 [[HelloWorld(hej hopp))]] # Extra right brace and still executed 875 963 ------------------------------
