17 from functools
import partial
18 from itertools
import cycle
25 _image_exts = (
'.jpg',
'.jpeg',
'.png',
'.gif',
'.bmp',
'.svg')
29 _link = re.compile(
r'\[(.+?\|.*?)\]')
33 _url = re.compile(
r'''
34 ((^|\ ) ["'(\[{]*) # begin of line or space and opt. any char "'([{
35 ([a-z][\w+-.]*://[^\s|]+?) # url
36 (?=[)\]}"'.,!?:;|]* ($|\ )) # opt. any char )]}"'.,!?:;| and eol or space
37 ''', re.VERBOSE|re.MULTILINE|re.IGNORECASE)
40 return self.
_format_url_format_url(text, format_as_image=
False)
45 return self.
_url_url.sub(partial(self.
_replace_url_replace_url, format_as_image), text)
50 if format_as_image
and self.
_is_image_is_image(url):
55 return '<img src="%s" title="%s">' \
56 % (self.
_quot_quot(src), self.
_quot_quot(title
or src))
59 return '<a href="%s">%s</a>' % (self.
_quot_quot(href), content
or href)
62 return attr
if '"' not in attr
else attr.replace(
'"',
'"')
66 tokens = self.
_link_link.split(text)
68 return ''.join(f(t)
for f, t
in zip(formatters, tokens))
71 link, content = [t.strip()
for t
in text.split(
'|', 1)]
73 content = self.
_get_image_get_image(content, link)
75 return self.
_get_image_get_image(link, content)
76 return self.
_get_link_get_link(link, content)
80 return (text.startswith(
'data:image/')
81 or text.lower().endswith(self.
_image_exts_image_exts))
85 handles =
lambda self, line:
True
90 _bold = re.compile(
r'''
92 (^|\ ) # begin of line or space
93 ["'(]* _? # optionally any char "'( and optional begin of italic
96 ([^\ ].*?) # no space and then anything (group 3)
98 (?= # start of postfix (non-capturing group)
99 _? ["').,!?:;]* # optional end of italic and any char "').,!?:;
100 ($|\ ) # end of line or space
106 _italic = re.compile(
r'''
107 ( (^|\ ) ["'(]* ) # begin of line or space and opt. any char "'(
109 ([^\ _].*?) # no space or underline and then anything
111 (?= ["').,!?:;]* ($|\ ) ) # opt. any char "').,!?:; and end of line or space
116 _code = re.compile(
r'''
117 ( (^|\ ) ["'(]* ) # same as above with _ changed to ``
121 (?= ["').,!?:;]* ($|\ ) )
131 for marker, formatter
in self.
_formatters_formatters:
133 line = formatter(line)
137 return self.
_bold_bold.sub(
'\\1<b>\\3</b>', line)
140 return self.
_italic_italic.sub(
'\\1<i>\\3</i>', line)
143 return self.
_code_code.sub(
'\\1<code>\\3</code>', line)
159 for line
in text.splitlines():
162 return '\n'.join(results)
176 results.append(self.
_current_current.end())
181 if formatter.handles(line):
198 raise NotImplementedError
209 raise NotImplementedError
215 return not self.
_lines_lines
and self.
matchmatch(line)
218 raise NotImplementedError
224 raise NotImplementedError
228 match = re.compile(
'^-{3,}$').match
235 match = re.compile(
r'^(={1,3})\s+(\S.*?)\s+\1$').match
238 level, text = self.
matchmatchmatch(line).groups()
239 level = len(level) + 1
240 return '<h%d>%s</h%d>' % (level, text, level)
250 _Formatter.__init__(self)
254 return not any(other.handles(line)
258 return '<p>%s</p>' % self.
_format_line_format_line(
' '.join(lines))
265 _table_line = re.compile(
r'^\| (.* |)\|$')
269 _line_splitter = re.compile(
r' \|(?= )')
276 return self.
_table_line_table_line.match(line)
is not None
282 return [cell.strip()
for cell
in self.
_line_splitter_line_splitter.split(line[1:-1])]
285 maxlen = max(len(row)
for row
in rows)
286 table = [
'<table border="1">']
288 row += [
''] * (maxlen - len(row))
290 table.extend(self.
_format_cell_format_cell(cell)
for cell
in row)
291 table.append(
'</tr>')
292 table.append(
'</table>')
293 return '\n'.join(table)
296 if content.startswith(
'=')
and content.endswith(
'='):
298 content = content[1:-1].strip()
311 return line.startswith(
'| ')
or line ==
'|'
314 lines = [self.
_format_line_format_line(line[2:])
for line
in lines]
315 return '\n'.join([
'<pre>'] + lines + [
'</pre>'])
329 return line.strip().startswith(
'- ')
or line.startswith(
' ')
and self.
_lines_lines
332 items = [
'<li>%s</li>' % self.
_format_item_format_item(line)
334 return '\n'.join([
'<ul>'] + items + [
'</ul>'])
340 if not line.startswith(
'- '):
344 yield ' '.join(current)
345 current = [line[2:].strip()]
346 yield ' '.join(current)