Mercurial > moin > 1.9
changeset 2779:c9dd12befda7
wiki parser: match everything looking like a macro and either execute it (macro imports ok) or render the macro markup as text (macro import fails, error msg is in title). This makes scan_rules independent of wiki, so we can move all re.compile time to Parser class (doing it only once on module import time).
author | Thomas Waldmann <tw AT waldmann-edv DOT de> |
---|---|
date | Tue, 28 Aug 2007 13:43:11 +0200 |
parents | c8dd346f146e |
children | 28b851be0844 |
files | MoinMoin/formatter/__init__.py MoinMoin/formatter/dom_xml.py MoinMoin/formatter/text_docbook.py MoinMoin/formatter/text_gedit.py MoinMoin/formatter/text_python.py MoinMoin/parser/text_moin_wiki.py |
diffstat | 6 files changed, 33 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/MoinMoin/formatter/__init__.py Tue Aug 28 03:12:46 2007 +0200 +++ b/MoinMoin/formatter/__init__.py Tue Aug 28 13:43:11 2007 +0200 @@ -304,10 +304,19 @@ # Dynamic stuff / Plugins ############################################ - def macro(self, macro_obj, name, args): + def macro(self, macro_obj, name, args, markup=None): # call the macro - return macro_obj.execute(name, args) - + try: + return macro_obj.execute(name, args) + except ImportError, err: + errmsg = unicode(err) + if markup: + errmsg = wikiutil.escape(errmsg) + return (self.span(1, title=errmsg) + + self.text(markup) + + self.span(0)) + else: + return self.text(errmsg) def _get_bang_args(self, line): if line.startswith('#!'): try:
--- a/MoinMoin/formatter/dom_xml.py Tue Aug 28 03:12:46 2007 +0200 +++ b/MoinMoin/formatter/dom_xml.py Tue Aug 28 13:43:11 2007 +0200 @@ -203,7 +203,7 @@ kw['pagename'] = pagename return self._set_tag('interwiki', on, **kw) - def macro(self, macro_obj, name, args): + def macro(self, macro_obj, name, args, markup=None): # call the macro return self._add_tag('macro', name=name, args=(args or ''))
--- a/MoinMoin/formatter/text_docbook.py Tue Aug 28 03:12:46 2007 +0200 +++ b/MoinMoin/formatter/text_docbook.py Tue Aug 28 13:43:11 2007 +0200 @@ -565,7 +565,7 @@ else: return "" - def macro(self, macro_obj, name, args): + def macro(self, macro_obj, name, args, markup=None): if name == "TableOfContents": # Table of content can be inserted in docbook transformation return u"" @@ -573,7 +573,7 @@ # At the begining text mode contain some string which is later # exchange for real value. There is problem that data inserted # as text mode are encoded to xml, e.g. < is encoded in the output as < - text = FormatterBase.macro(self, macro_obj, name, args) + text = FormatterBase.macro(self, macro_obj, name, args, markup) if len(text) > 0: # prepare identificator sKey = "EXCHANGESTRINGMACRO-" + str(len(self.exchangeKeys)) + "-EXCHANGESTRINGMACRO"
--- a/MoinMoin/formatter/text_gedit.py Tue Aug 28 03:12:46 2007 +0200 +++ b/MoinMoin/formatter/text_gedit.py Tue Aug 28 13:43:11 2007 +0200 @@ -95,7 +95,7 @@ # Dynamic stuff / Plugins ############################################ - def macro(self, macro_obj, name, args): + def macro(self, macro_obj, name, args, markup=None): #use ImageLink for resized images if name == "ImageLink" and args is not None: @@ -127,11 +127,13 @@ kw['src'] = AttachFile.getAttachUrl(pagename, url, self.request, addts=1) return self.image(**kw) + elif markup is not None: + result = markup elif args is not None: result = "<<%s(%s)>>" % (name, args) else: result = "<<%s>>" % name - return '<span style="background-color:#ffff11">%s</span>' % result + return '<span style="background-color:#ffff11">%s</span>' % result # XXX XSS needs escaping! def parser(self, parser_name, lines): """ parser_name MUST be valid!
--- a/MoinMoin/formatter/text_python.py Tue Aug 28 03:12:46 2007 +0200 +++ b/MoinMoin/formatter/text_python.py Tue Aug 28 13:43:11 2007 +0200 @@ -185,16 +185,16 @@ else: return self.formatter.div(on, **kw) - def macro(self, macro_obj, name, args): + def macro(self, macro_obj, name, args, markup=None): if self.__is_static(macro_obj.get_dependencies(name)): # XXX: why is this necessary?? macro_obj.formatter = self return macro_obj.execute(name, args) else: return self.__insert_code( - '%srequest.write(%s.macro(macro_obj, %r, %r))' % + '%srequest.write(%s.macro(macro_obj, %r, %r, %r))' % (self.__adjust_formatter_state(), - self.__formatter, name, args)) + self.__formatter, name, args, markup)) def parser(self, parser_name, lines): """ parser_name MUST be valid!
--- a/MoinMoin/parser/text_moin_wiki.py Tue Aug 28 03:12:46 2007 +0200 +++ b/MoinMoin/parser/text_moin_wiki.py Tue Aug 28 13:43:11 2007 +0200 @@ -143,6 +143,10 @@ """ dl_re = re.compile(dl_rule, re.VERBOSE|re.UNICODE) + # others + indent_re = re.compile(ur"^\s*", re.UNICODE) + eol_re = re.compile(r'\r?\n', re.UNICODE) + # this is used inside <pre> / parser sections (we just want to know when it's over): pre_scan_rule = ur""" (?P<pre> @@ -240,7 +244,7 @@ (?=\s) # we require some space after the smiley )|(?P<macro> << - (?P<macro_name>(%%(macronames)s)) # name of the macro (only existing ones will match) + (?P<macro_name>\w+) # name of the macro (?:\((?P<macro_args>.*?)\))? # optionally macro arguments >> )|(?P<heading> @@ -297,6 +301,7 @@ 'u': config.chars_upper, 'l': config.chars_lower, 'smiley': u'|'.join([re.escape(s) for s in config.smileys])} + scan_re = re.compile(scan_rules, re.UNICODE|re.VERBOSE) # Don't start p before these no_new_p_before = ("heading rule table tableZ tr td " @@ -350,8 +355,6 @@ self.list_indents = [] self.list_types = [] - # XXX TODO if we remove the runtime dependency, we can compile the scan_rules at module load time: - self.scan_rules = self.scan_rules % {'macronames': u'|'.join(macro.getNames(self.cfg))} def _close_item(self, result): #result.append("<!-- close item begin -->\n") @@ -1113,7 +1116,7 @@ # create macro instance if self.macro is None: self.macro = macro.Macro(self) - return self.formatter.macro(self.macro, macro_name, macro_args) + return self.formatter.macro(self.macro, macro_name, macro_args, markup=groups.get('macro')) _macro_name_repl = _macro_repl _macro_args_repl = _macro_repl @@ -1149,8 +1152,7 @@ self.formatter.in_p) and lastpos < len(line): result.append(self.formatter.paragraph(1, css_class="line874")) if '}}}' in line and len(line[lastpos:].strip()) > 0: - scan_re = re.compile(self.scan_rules, re.UNICODE|re.VERBOSE) - result.append(self.scan(scan_re, line[lastpos:].strip(), inhibit_p=inhibit_p)) + result.append(self.scan(self.scan_re, line[lastpos:].strip(), inhibit_p=inhibit_p)) else: result.append(self.formatter.text(line[lastpos:])) return u''.join(result) @@ -1205,19 +1207,12 @@ self.formatter = formatter self.hilite_re = self.formatter.page.hilite_re - # prepare regex patterns - self.request.clock.start('compile_huge_and_pretty') - scan_re = re.compile(self.scan_rules, re.UNICODE|re.VERBOSE) - indent_re = re.compile(ur"^\s*", re.UNICODE) - eol_re = re.compile(r'\r?\n', re.UNICODE) - self.request.clock.stop('compile_huge_and_pretty') - # get text and replace TABs rawtext = self.raw.expandtabs() # go through the lines self.lineno = self.start_line - self.lines = eol_re.split(rawtext) + self.lines = self.eol_re.split(rawtext) self.line_is_empty = 0 self.in_processing_instructions = 1 @@ -1333,7 +1328,7 @@ continue # Check indent level - indent = indent_re.match(line) + indent = self.indent_re.match(line) indlen = len(indent.group(0)) indtype = "ul" numtype = None @@ -1389,7 +1384,7 @@ self.in_table = 0 # Scan line, format and write - scanning_re = self.in_pre and self.pre_scan_re or scan_re + scanning_re = self.in_pre and self.pre_scan_re or self.scan_re if '{{{' in line: self.in_nested_pre += 1 formatted_line = self.scan(scanning_re, line, inhibit_p=inhibit_p)