2012-10-15 22:03:50 +02:00
|
|
|
import re
|
|
|
|
import markdown
|
|
|
|
|
2012-10-20 05:34:14 +02:00
|
|
|
from zephyr.lib.avatar import gravatar_hash
|
|
|
|
from zephyr.lib.bugdown import codehilite
|
2012-10-17 04:42:19 +02:00
|
|
|
|
|
|
|
class Gravatar(markdown.inlinepatterns.Pattern):
|
|
|
|
def handleMatch(self, match):
|
|
|
|
# NB: the first match of our regex is match.group(2) due to
|
|
|
|
# markdown internal matches
|
|
|
|
img = markdown.util.etree.Element('img')
|
|
|
|
img.set('class', 'message_body_gravatar img-rounded')
|
|
|
|
img.set('src', 'https://secure.gravatar.com/avatar/%s?d=identicon&s=30'
|
|
|
|
% (gravatar_hash(match.group(2)),))
|
|
|
|
return img
|
|
|
|
|
2012-10-16 17:35:58 +02:00
|
|
|
class Bugdown(markdown.Extension):
|
|
|
|
def extendMarkdown(self, md, md_globals):
|
|
|
|
del md.inlinePatterns['image_link']
|
|
|
|
del md.inlinePatterns['image_reference']
|
2012-10-16 17:39:00 +02:00
|
|
|
del md.parser.blockprocessors['hashheader']
|
|
|
|
del md.parser.blockprocessors['setextheader']
|
2012-10-16 17:35:58 +02:00
|
|
|
|
2012-10-17 04:42:19 +02:00
|
|
|
md.inlinePatterns.add('gravatar', Gravatar(r'!gravatar\(([^)]*)\)'), '_begin')
|
|
|
|
|
2012-10-15 22:03:50 +02:00
|
|
|
# We need to re-initialize the markdown engine every 30 messages
|
|
|
|
# due to some sort of performance leak in the markdown library.
|
|
|
|
MAX_MD_ENGINE_USES = 30
|
|
|
|
|
|
|
|
_md_engine = None
|
|
|
|
_use_count = 0
|
|
|
|
|
|
|
|
# A link starts after whitespace, and cannot contain spaces,
|
|
|
|
# end parentheses, or end brackets (which would confuse Markdown).
|
|
|
|
# FIXME: Use one of the actual linkification extensions.
|
|
|
|
_link_regex = re.compile(r'(\s|\A)(?P<url>https?://[^\s\])]+)')
|
|
|
|
|
|
|
|
def _linkify(match):
|
|
|
|
url = match.group('url')
|
|
|
|
return ' [%s](%s) ' % (url, url)
|
|
|
|
|
|
|
|
def convert(md):
|
|
|
|
"""Convert Markdown to HTML, with Humbug-specific settings and hacks."""
|
|
|
|
global _md_engine, _use_count
|
|
|
|
|
|
|
|
if _md_engine is None:
|
|
|
|
_md_engine = markdown.Markdown(
|
|
|
|
safe_mode = 'escape',
|
2012-10-20 05:34:14 +02:00
|
|
|
output_format = 'xhtml',
|
|
|
|
extensions = ['fenced_code', 'nl2br',
|
2012-10-20 05:44:39 +02:00
|
|
|
codehilite.makeExtension(configs=[('force_linenos', False)]),
|
2012-10-20 05:34:14 +02:00
|
|
|
Bugdown()])
|
2012-10-15 22:03:50 +02:00
|
|
|
|
|
|
|
md = _link_regex.sub(_linkify, md)
|
|
|
|
|
|
|
|
try:
|
|
|
|
html = _md_engine.convert(md)
|
|
|
|
except:
|
|
|
|
# FIXME: Do something more reasonable here!
|
|
|
|
html = '<p>[Humbug note: Sorry, we could not understand the formatting of your message]</p>'
|
|
|
|
|
|
|
|
_use_count += 1
|
|
|
|
if _use_count >= MAX_MD_ENGINE_USES:
|
|
|
|
_md_engine = None
|
|
|
|
_use_count = 0
|
|
|
|
|
|
|
|
return html
|