Ticket #801: patch_779_780_and_more.diff
| File patch_779_780_and_more.diff, 18.6 KB (added by tonib, 4 years ago) |
|---|
-
trac/util.py
72 72 .replace('"', '"') 73 73 return text 74 74 75 def unescape(text): 76 """Reverses Escapes &, <, > and \"""" 77 if not text: 78 return '' 79 if type(text) is StringType: 80 text = text.replace('"', '"') \ 81 .replace('>', '>') \ 82 .replace('<', '<') \ 83 .replace('&', '&') 84 return text 85 75 86 def get_first_line(text, maxlen): 76 87 """ 77 88 returns the first line of text. If the line is longer then -
trac/wikimacros/rst.py
43 43 raise EnvironmentError, 'Docutils version >= %s required, %s found' % (docutils_required, __version__) 44 44 45 45 from trac.Href import Href 46 from trac.WikiFormatter import WikiProcessor 46 47 47 48 __docformat__ = 'reStructuredText' 48 49 49 WIKI_LINK = re.compile(r'(?:wiki:)?( ?P<w>[A-Za-z][\w\#\?]*[^\w\#\?]*)') # Links must begin with Letters, \# ? so we can link inside pages.50 #WIKI_LINK = re.compile(r'(?:wiki:)?(?P<w >(^|(?<=[^A-Za-z]))[!]?[A-Z][a-z/]+(?:[A-Z][a-z/]+)+)')50 WIKI_LINK = re.compile(r'(?:wiki:)?(.+)') 51 #WIKI_LINK = re.compile(r'(?:wiki:)?(?P<wikilink>[A-Za-z][\w\-]*[^\w\#\?]*)') 51 52 TICKET_LINK = re.compile(r'(?:#(\d+))|(?:ticket:(\d+))') 52 53 REPORT_LINK = re.compile(r'(?:{(\d+)})|(?:report:(\d+))') 53 54 CHANGESET_LINK = re.compile(r'(?:\[(\d+)\])|(?:changeset:(\d+))') 54 55 FILE_LINK = re.compile(r'(?:browser|repos|source):([^#]+)#?(.*)') 55 56 57 #import trac.Logging 58 #log = trac.Logging.logger_factory(logtype='file', logfile="/tmp/debug_rst.txt", level='ALL') 59 56 60 def _wikipage(href, args): 57 61 return href.wiki(args[0]) 58 62 … … 71 75 return href.browser(path, rev) 72 76 73 77 # TracLink REs and callback functions 74 LINKS = [(WIKI_LINK, _wikipage), 75 (TICKET_LINK, _ticket), 78 LINKS = [(TICKET_LINK, _ticket), 76 79 (REPORT_LINK, _report), 77 80 (CHANGESET_LINK, _changeset), 78 (FILE_LINK, _browser)] 81 (FILE_LINK, _browser), 82 (WIKI_LINK, _wikipage)] 79 83 80 84 81 def trac_get_reference(env, rawtext, text): 85 def trac_get_reference(env, rawtext, link, text): 86 82 87 for (pattern, function) in LINKS: 83 m = pattern.match( text)88 m = pattern.match(link) 84 89 if m: 85 90 g = filter(None, m.groups()) 86 91 missing = False 92 if not text: 93 text = g[0] 87 94 if pattern == WIKI_LINK: 88 if not (env._wiki_pages.has_key(g[0])): 95 pagename = re.search(r'^[^\#]+',g[0]) 96 if not (env._wiki_pages.has_key(pagename.group())): 89 97 missing = True 90 text = text + "?" 98 text = text + "?" 91 99 uri = function(env.href, g) 92 100 reference = nodes.reference(rawtext, text) 93 101 reference['refuri']= uri 94 102 if missing: 95 103 reference.set_class('missing') 96 104 return reference 105 97 106 return None 98 107 99 108 def trac(env, name, arguments, options, content, lineno, … … 119 128 120 129 .. _TracLink: http://projects.edgewall.com/trac/wiki/TracLinks 121 130 """ 122 text = arguments[int(len(arguments) == 2)] 123 reference = trac_get_reference(env, block_text, text) 131 link = arguments[0] 132 if len(arguments) == 2: 133 text = arguments[1] 134 else: 135 text = None 136 reference = trac_get_reference(env, block_text, link, text) 124 137 if reference: 125 138 return reference 126 139 # didn't find a match (invalid TracLink), … … 133 146 134 147 135 148 def trac_role(env, name, rawtext, text, lineno, inliner, options={}, content=[]): 136 reference = trac_get_reference(env, rawtext, text) 149 args = text.split(" ",1) 150 link = args[0] 151 if len(args)==2: 152 text = args[1] 153 else: 154 text = None 155 reference = trac_get_reference(env, rawtext, link, text) 137 156 if reference: 138 157 return [reference], [] 139 158 warning = nodes.warning(None, … … 159 178 rst.roles.register_local_role('trac', do_trac_role) 160 179 161 180 # The code_block could is taken from the leo plugin rst2 181 def code_formatter(language, text): 182 #log.debug("language '%s' args '%s'", % (language, arguments)) 183 Format = WikiProcessor(env, language) 184 html = Format.process(hdf, text) 185 #log.debug("language '%s' htmltext '%s'" % (language, html)) 186 raw = nodes.raw('',html, format='html') #(self, rawsource='', text='', *children, **attributes): 187 return raw 188 189 def code_role(name, rawtext, text, lineno, inliner, options={}, content=[]): 190 args = text.split(":",1) 191 language = args[0] 192 if len(args)==2: 193 text = args[1] 194 else: 195 text = "" 196 #log.debug("coderole '%s' text '%s'" % (language, text)) 197 reference = code_formatter(language, text) 198 return [reference], [] 199 200 201 162 202 def code_block(name,arguments,options,content,lineno,content_offset,block_text,state,state_machine): 163 203 164 204 """Create a code-block directive for docutils. … … 166 206 Usage: .. code-block:: language 167 207 168 208 If the language can be syntax highlighted it will be.""" 169 170 171 172 from trac.WikiFormatter import Formatter173 174 209 language = arguments[0] 210 text = '\n'.join(content) 211 reference = code_formatter(language, text) 212 return [reference] 175 213 176 code_processor = None177 if Formatter.builtin_processors.has_key(language):178 code_processor = Formatter.builtin_processors[language]179 else:180 code_processor = Formatter.builtin_processors['default']181 182 183 html = code_processor(hdf, '\n'.join(content), env)184 raw = nodes.raw('',html, format='html') #(self, rawsource='', text='', *children, **attributes):185 return [raw]186 187 214 # These are documented at http://docutils.sourceforge.net/spec/howto/rst-directives.html. 188 215 code_block.arguments = ( 189 216 1, # Number of required arguments. … … 199 226 code_block.content = 1 # True if content is allowed. 200 227 # Register the directive with docutils. 201 228 rst.directives.register_directive('code-block',code_block) 229 rst.roles.register_local_role('code-block', code_role) 202 230 203 231 204 232 -
trac/Mimeview.py
51 51 'make':'text/x-makefile', 'mk':'text/x-makefile', 'Makefile':'text/x-makefile', 52 52 'mail':'text/x-mail', 53 53 'pas':'text/x-pascal', 54 'pl':'text/x-perl', 'pm':'text/x-perl', 'PL':'text/x-perl', 54 'pl':'text/x-perl', 'pm':'text/x-perl', 'PL':'text/x-perl', 'perl':'text/x-perl', 55 55 'php':'text/x-php', 'php4':'text/x-php', 'php3':'text/x-php', 56 56 'ps':'application/postscript', 57 57 'psp':'text/x-psp', 58 'py':'text/x-python', 58 'py':'text/x-python', 'python':'text/x-python', 59 59 'pyx':'text/x-pyrex', 60 60 'nroff':'application/x-troff', 'roff':'application/x-troff', 'troff':'application/x-troff', 61 61 62 'rb':'text/x-ruby', 62 'rb':'text/x-ruby', 'ruby':'text/x-ruby', 63 63 'rfc':'text/x-rfc', 64 64 'scm':'text/x-scheme', 65 65 'sh':'application/x-sh', … … 68 68 'tex':'text/x-tex', 69 69 'vba':'text/x-vba', 70 70 'bas':'text/x-vba', 71 'v':'text/x-verilog', 71 'v':'text/x-verilog', 'verilog':'text/x-verilog', 72 72 'vhd':'text/x-vhdl', 73 73 'vrml':'model/vrml', 74 74 'wrl':'model/vrml', -
trac/WikiFormatter.py
27 27 import StringIO 28 28 29 29 import util 30 import Mimeview 30 31 31 __all__ = ['Formatter', 'OneLinerFormatter', 'wiki_to_html', 'wiki_to_oneliner' ]32 __all__ = ['Formatter', 'OneLinerFormatter', 'wiki_to_html', 'wiki_to_oneliner', 'WikiProcessor'] 32 33 33 34 35 class WikiProcessor: 36 37 mime_type = "" 38 39 def __init__(self, env, name): 40 self.env = env 41 self.error = self.set_code_processor(name) 42 43 def default_processor(hdf, text, env): 44 return '<pre class="wiki">' + util.escape(text) + '</pre>' 45 46 def html_processor(hdf, text, env): 47 if Formatter._htmlproc_disallow_rule.search(text): 48 err = """\ 49 <div class="system-message">Error: HTML block contains disallowed tags. 50 <pre> 51 %s</pre> 52 </div>""" % util.escape(text) 53 env.log.error(err) 54 return err 55 return text 56 57 def mime_processor(self, hdf, text, env): 58 return env.mimeview.display(text, self.mime_type) 59 60 builtin_processors = { 'html': html_processor, 61 'default': default_processor} 62 63 def process(self, hdf, text, inline=False): 64 text = self.code_processor(hdf, text, self.env) 65 if inline: 66 code_block_start = re.compile('^<div class="code-block">') 67 code_block_end = re.compile('</div>$') 68 text, nr = code_block_start.subn('<span class="code-block">', text, 1 ) 69 if nr: 70 text, nr = code_block_end.subn('</span>', text, 1 ) 71 return text 72 else: 73 return text 74 75 76 def set_code_processor(self, name): 77 if self.builtin_processors.has_key(name): 78 self.code_processor = self.builtin_processors[name] 79 else: 80 try: 81 self.code_processor = self.load_macro(name) 82 except Exception, e: 83 if Mimeview.MIME_MAP.has_key(name): 84 name = Mimeview.MIME_MAP[name] 85 mimeviewer, exists = self.env.mimeview.get_viewer(name) 86 if exists != -1: 87 self.mime_type = name 88 self.code_processor = self.mime_processor 89 else: 90 self.code_processor = self.builtin_processors['default'] 91 return 1 92 return 0 93 94 def load_macro(self, name): 95 # Look in envdir/wiki-macros/ first 96 try: 97 module = imp.load_source(name, os.path.join(self.env.path, 'wiki-macros', name+'.py')) 98 except IOError: 99 # fall back to site-wide macros 100 macros = __import__('wikimacros.' + name, globals(), locals(), []) 101 module = getattr(macros, name) 102 return module.execute 103 104 34 105 class CommonFormatter: 35 106 """This class contains the patterns common to both Formatter and 36 107 OneLinerFormatter""" … … 240 311 """ 241 312 _rules = [r"""(?P<svnimg>(source|repos):([^ ]+)\.(PNG|png|JPG|jpg|JPEG|jpeg|GIF|gif))"""] + \ 242 313 CommonFormatter._rules + \ 243 [r"""(?P<macro>!?\[\[(?P<macroname>[ a-zA-Z]+)(\((?P<macroargs>[^\)]*)\))?\]\])""",314 [r"""(?P<macro>!?\[\[(?P<macroname>[\w/+-]+)(\]\]|\((?P<macroargs>.*?)\)\]\]))""", 244 315 r"""(?P<heading>^\s*(?P<hdepth>=+)\s.*\s(?P=hdepth)\s*$)""", 245 316 r"""(?P<list>^(?P<ldepth>\s+)(?:\*|[0-9]+\.) )""", 246 317 r"""(?P<indent>^(?P<idepth>\s+)(?=\S))""", … … 250 321 r"""(?P<table_cell>\|\|)"""] 251 322 252 323 _compiled_rules = re.compile('(?:' + string.join(_rules, '|') + ')') 253 _processor_re = re.compile('#\!([a-zA-Z0-9/+-]+)') 254 mime_type = "" 324 _processor_re = re.compile('#\!([\w/+-]+)') 255 325 256 326 257 327 # RE patterns used by other patterna … … 261 331 262 332 _htmlproc_disallow_rule = re.compile('(?i)<(script|noscript|embed|object|iframe|frame|frameset|link|style|meta|param|doctype)') 263 333 264 def default_processor(hdf, text, env):265 return '<pre class="wiki">' + util.escape(text) + '</pre>'266 def asp_processor(hdf, text, env):267 return env.mimeview.display(text, 'text/x-asp')268 def c_processor(hdf, text, env):269 return env.mimeview.display(text, 'text/x-csrc')270 def css_processor(hdf, text, env):271 return env.mimeview.display(text, 'text/css')272 def java_processor(hdf, text, env):273 return env.mimeview.display(text, 'text/x-java')274 def cpp_processor(hdf, text, env):275 return env.mimeview.display(text, 'text/x-c++src')276 def perl_processor(hdf, text, env):277 return env.mimeview.display(text, 'text/x-perl')278 def php_processor(hdf, text, env):279 return env.mimeview.display(text, 'text/x-php')280 def python_processor(hdf, text, env):281 return env.mimeview.display(text, 'text/x-python')282 def ruby_processor(hdf, text, env):283 return env.mimeview.display(text, 'text/x-ruby')284 def sql_processor(hdf, text, env):285 return env.mimeview.display(text, 'text/x-sql')286 def xml_processor(hdf, text, env):287 return env.mimeview.display(text, 'text/xml')288 def verilog_processor(hdf, text, env):289 return env.mimeview.display(text, 'text/x-verilog')290 def html_processor(hdf, text, env):291 if Formatter._htmlproc_disallow_rule.search(text):292 err = """\293 <div class="system-message">Error: HTML block contains disallowed tags.294 <pre>295 %s</pre>296 </div>""" % util.escape(text)297 env.log.error(err)298 return err299 return text300 def mime_processor(self, hdf, text, env):301 return env.mimeview.display(text, self.mime_type)302 303 builtin_processors = { 'html': html_processor,304 'asp': asp_processor,305 'c': c_processor,306 'css': css_processor,307 'cpp': cpp_processor,308 'java': java_processor,309 'php': php_processor,310 'perl': perl_processor,311 'python': python_processor,312 'ruby': ruby_processor,313 'sql': sql_processor,314 'xml': xml_processor,315 'verilog': verilog_processor,316 'default': default_processor}317 318 def load_macro(self, name):319 # Look in envdir/wiki-macros/ first320 try:321 module = imp.load_source(name, os.path.join(self.env.path, 'wiki-macros', name+'.py'))322 except IOError:323 # fall back to site-wide macros324 macros = __import__('wikimacros.' + name, globals(), locals(), [])325 module = getattr(macros, name)326 return module.execute327 328 334 def _macro_formatter(self, match, fullmatch): 329 335 name = fullmatch.group('macroname') 330 336 if name in ['br', 'BR']: 331 337 return '<br />' 332 338 args = fullmatch.group('macroargs') 339 args = util.unescape(args) 333 340 try: 334 macro = self.load_macro(name)335 return macro (self.hdf, args, self.env)341 macro = WikiProcessor(self.env, name) 342 return macro.process(self.hdf, args, True) 336 343 except Exception, e: 337 344 return '<div class="system-message">Macro %s(%s) failed: %s</div>' \ 338 345 % (name, args, e) … … 474 481 else: 475 482 self.code_text += line + os.linesep 476 483 if not self.code_processor: 477 self.code_processor = Formatter.builtin_processors['default']484 self.code_processor = WikiProcessor(self.env, 'default') 478 485 elif line.strip() == '}}}': 479 486 self.in_code_block -= 1 480 487 if self.in_code_block == 0 and self.code_processor: 481 488 self.close_paragraph() 482 489 self.close_table() 483 self.out.write(self.code_processor (self.hdf, self.code_text, self.env))490 self.out.write(self.code_processor.process(self.hdf, self.code_text)) 484 491 else: 485 492 self.code_text += line + os.linesep 486 493 elif not self.code_processor: 487 494 match = Formatter._processor_re.search(line) 488 495 if match: 489 496 name = match.group(1) 490 if Formatter.builtin_processors.has_key(name): 491 self.code_processor = Formatter.builtin_processors[name] 492 else: 493 try: 494 self.code_processor = self.load_macro(name) 495 except Exception, e: 496 mimeviewer, exists = self.env.mimeview.get_viewer(name) 497 if exists != -1: 498 self.mime_type = name 499 self.code_processor = self.mime_processor 500 else: 501 self.code_text += line + os.linesep 502 self.code_processor = Formatter.builtin_processors['default'] 503 self.out.write('<div class="system-message">Failed to load processor macro %s: %s t %s</div>' % (name, line, e)) 497 self.code_processor = WikiProcessor(self.env, name) 498 if self.code_processor.error: 499 self.out.write("<div class='system-message'>Failed to load processor macro '%s': '%s' '%s'</div>" % (name, line, e)) 500 self.code_text += line + os.linesep 504 501 else: 505 502 self.code_text += line + os.linesep 506 self.code_processor = Formatter.builtin_processors['default']503 self.code_processor = WikiProcessor(self.env, 'default') 507 504 else: 508 505 self.code_text += line + os.linesep 509 506 507 510 508 def format(self, text, out): 511 509 self.out = out 512 510 self._open_tags = [] -
trac/tests/wiki.py
4 4 5 5 from Wiki import Formatter 6 6 7 7 8 class WikiTestCase(unittest.TestCase): 8 9 def __init__(self, input, correct): 9 10 unittest.TestCase.__init__(self, 'test') … … 13 14 def test(self): 14 15 """Testing WikiFormatter""" 15 16 import Href 17 import Mimeview 16 18 class Environment: 17 19 def __init__(self): 18 20 self.href = Href.Href('/') 19 21 self._wiki_pages = {} 22 self.mimeview = Mimeview.Mimeview(self) 20 23 class Cursor: 21 24 def execute(self, *kwargs): pass 22 25 def fetchone(self): return [] … … 28 31 out = StringIO.StringIO() 29 32 Formatter(None, Environment(), Connection()).format(self.input, out) 30 33 if out.getvalue() != self.correct: 31 print " '%s' !='%s'" % (out.getvalue(), self.correct)34 print "\n'%s' != \n'%s'" % (out.getvalue(), self.correct) 32 35 assert self.correct == out.getvalue() 33 36 34 37 def suite():
