markup.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. # -*- coding: utf-8 -*-
  2. """
  3. flaskbb.utils.markup
  4. ~~~~~~~~~~~~~~~~~~~~
  5. A module for all markup related stuff.
  6. :copyright: (c) 2016 by the FlaskBB Team.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. import logging
  10. import re
  11. from flask import url_for
  12. import mistune
  13. from pygments import highlight
  14. from pygments.lexers import get_lexer_by_name
  15. from pygments.formatters import HtmlFormatter
  16. from pygments.util import ClassNotFound
  17. logger = logging.getLogger(__name__)
  18. _re_user = re.compile(r'@(\w+)', re.I)
  19. class FlaskBBRenderer(mistune.Renderer):
  20. """Markdown with some syntactic sugar, such as @user gettting linked
  21. to the user's profile.
  22. """
  23. def __init__(self, **kwargs):
  24. super(FlaskBBRenderer, self).__init__(**kwargs)
  25. def paragraph(self, text):
  26. """Render paragraph tags, autolinking user handles."""
  27. def userify(match):
  28. value = match.group(1)
  29. user = "<a href='{url}'>@{user}</a>".format(
  30. url=url_for("user.profile", username=value, _external=False),
  31. user=value
  32. )
  33. return user
  34. text = _re_user.sub(userify, text)
  35. return '<p>%s</p>\n' % text.strip(' ')
  36. def block_code(self, code, lang):
  37. if lang:
  38. try:
  39. lexer = get_lexer_by_name(lang, stripall=True)
  40. except ClassNotFound:
  41. lexer = None
  42. else:
  43. lexer = None
  44. if not lexer:
  45. return '\n<pre><code>%s</code></pre>\n' % \
  46. mistune.escape(code)
  47. formatter = HtmlFormatter()
  48. return highlight(code, lexer, formatter)
  49. renderer = FlaskBBRenderer(escape=True, hard_wrap=True)
  50. markdown = mistune.Markdown(renderer=renderer)