img_re = re.compile(r"^.*\.(png|gif|jpg|jpeg|bmp|ico|ogm|ogg|mkv|mpg|mpeg|mp4|avi|asf|flv|wmv|qt)$", re.IGNORECASE)
video_re = re.compile(r"^.*\.(ogm|ogg|mkv|mpg|mpeg|mp4|avi|asf|flv|wmv|qt)$", re.IGNORECASE)
url_re = re.compile(r"^[a-z]{3,8}://[^\s'\"]+\S$")
-link_re = re.compile(r"(?:\[\[|{{)([^\s\|]+)(?:\s*\|\s*([^\]]+)|)(?:\]\]|}})")
ext_re = re.compile(r"\.([^\./]+)$")
title_done = False
def permalink(s):
return re.sub(' ', '-', re.sub('[^a-z0-9_ ]', '', s.lower()).strip())
+# Split arg lists like "blah| blah blah| width=100 | align = center",
+# return a list containing anonymous arguments and a map containing the named arguments
+def parse_args(s):
+ args = []
+ kwargs = {}
+ for arg in s.strip('<[{}]>').split('|'):
+ try:
+ key, val = arg.split('=', 1)
+ kwargs[key.strip()] = val.strip()
+ except ValueError:
+ args.append(arg.strip())
+ return (args, kwargs)
+
+def url_args(kvargs):
+ argv = []
+ for k, v in kvargs.items():
+ argv.append(k + '=' + v)
+ if argv:
+ return '?' + '&'.join(argv)
+ return ''
+
# Formatting stuff --------------------------------------------------
def emit_header(mime_type="text/html"):
print("Content-type: " + mime_type + "; charset=utf-8\n")
send_title(None, msg_text=("%s: on query '%s'" % (status, query)))
send_footer()
-def link_tag(params, text=None, link_class=None, privileged=False):
+def link_tag(params, text=None, link_class=None, privileged=False, **kvargs):
if text is None:
text = params # default
elif img_re.match(text):
return '<a %shref="%s">%s</a>' % (classattr, relative_url(params, privileged=privileged), text)
-def link_inline(name, descr=None, args=''):
+def link_inline(name, descr=None, kvargs={}):
if not descr: descr = name
url = relative_url(name)
if video_re.match(name):
return '<video src="%s">Your browser does not support the HTML5 video tag</video>' % url
elif img_re.match(name):
- return '<a href="%s"><img border="0" src="%s" alt="%s" /></a>' % (url, url + args, descr)
+ return '<a href="%s"><img border="0" src="%s" alt="%s" /></a>' % (url, url + url_args(kvargs), descr)
elif file_re.match(name) and not ext_re.search(name): # FIXME: this guesses a wiki page
return Page(name).send_naked()
else:
return self._undent() + '\n<hr size="%d" noshade="noshade" />\n' % (len(word) - 2)
def _macro_repl(self, word):
- m = re.compile("\<\<([^\s\|\>]+)(?:\s*\|\s*([^\>]+)|)\>\>").match(word)
- name = m.group(1)
- argv = [name]
- if m.group(2):
- argv.extend(m.group(2).split('|'))
- argv = list(map(str.strip, argv))
-
- macro = globals().get('_macro_' + name)
- if not macro:
- try:
+ try:
+ args, kwargs = parse_args(word)
+ macro = globals().get('_macro_' + args[0])
+ if not macro:
exec(open("macros/" + name + ".py").read(), globals())
- except IOError as err:
- if err.errno == errno.ENOENT: pass
- macro = globals().get('_macro_' + name)
- if macro:
- return macro(argv)
- else:
- msg = '<<' + '|'.join(argv) + '>>'
+ macro = globals().get('_macro_' + name)
+ return macro(*args, **kwargs)
+ except Exception:
+ msg = cgi.escape(word)
if not self.in_html:
msg = '<strong class="error">' + msg + '</strong>'
return msg
def _hurl_repl(self, word):
- m = link_re.match(word)
- return link_tag(m.group(1), m.group(2))
+ args, kvargs = parse_args(word)
+ return link_tag(*args, **kvargs)
def _inl_repl(self, word):
- (name, descr) = link_re.match(word).groups()
-
- if descr:
- argv = descr.split('|')
- descr = argv.pop(0)
- args = ''
- if argv:
- args = '?' + '&'.join(argv)
-
+ args, kvargs = parse_args(word)
+ name = args.pop(0)
+ if len(args):
+ descr = args.pop(0)
# The "extthumb" nonsense works around a limitation of the HTML block model
return '<div class="extthumb"><div class="thumb">' \
- + link_inline(name, descr, args) \
+ + link_inline(name, descr, kvargs) \
+ '<div class="caption">' + descr + '</div></div></div>'
else:
- return link_inline(name, name)
+ return link_inline(name, None, kvargs)
def _html_repl(self, word):
if not self.in_html and word.startswith('<div'): word = '</p>' + word
except IOError as err:
if err.errno == errno.ENOENT:
if default is None:
- default = '//[[?edit=%s|Describe %s]]//' % (self.page_name, self.page_name)
+ default = '//[[%s|Describe %s|action=edit]]//' % (self.page_name, self.page_name)
return default
if err.errno == errno.EISDIR:
return self.format_dir()