markup.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import os
  2. import re
  3. from flask import url_for
  4. import mistune
  5. from pygments import highlight
  6. from pygments.lexers import get_lexer_by_name
  7. from pygments.formatters import HtmlFormatter
  8. _re_emoji = re.compile(r':([a-z0-9\+\-_]+):', re.I)
  9. _re_user = re.compile(r'@(\w+)', re.I)
  10. # base directory of flaskbb - used to collect the emojis
  11. _basedir = os.path.join(os.path.abspath(os.path.dirname(
  12. os.path.dirname(__file__))))
  13. def collect_emojis():
  14. """Returns a dictionary containing all emojis with their
  15. name and filename. If the folder doesn't exist it returns a empty
  16. dictionary.
  17. """
  18. emojis = dict()
  19. full_path = os.path.join(_basedir, "static", "emoji")
  20. # return an empty dictionary if the path doesn't exist
  21. if not os.path.exists(full_path):
  22. return emojis
  23. for emoji in os.listdir(full_path):
  24. name, ending = emoji.split(".")
  25. if ending in ["png", "gif", "jpg", "jpeg"]:
  26. emojis[name] = emoji
  27. return emojis
  28. EMOJIS = collect_emojis()
  29. class FlaskBBRenderer(mistune.Renderer):
  30. """Markdown with some syntetic sugar such as @user gets linked to the
  31. user's profile and emoji support.
  32. """
  33. def __init__(self, **kwargs):
  34. super(FlaskBBRenderer, self).__init__(**kwargs)
  35. def paragraph(self, text):
  36. """Rendering paragraph tags. Like ``<p>`` with emoji support."""
  37. def emojify(match):
  38. value = match.group(1)
  39. if value in EMOJIS:
  40. filename = url_for(
  41. "static",
  42. filename="emoji/{}".format(EMOJIS[value])
  43. )
  44. emoji = "<img class='{css}' alt='{alt}' src='{src}' />".format(
  45. css="emoji", alt=value,
  46. src=filename
  47. )
  48. return emoji
  49. return match.group(0)
  50. def userify(match):
  51. value = match.group(1)
  52. user = "<a href='{url}'>@{user}</a>".format(
  53. url=url_for("user.profile", username=value, _external=False),
  54. user=value
  55. )
  56. return user
  57. text = _re_emoji.sub(emojify, text)
  58. text = _re_user.sub(userify, text)
  59. return '<p>%s</p>\n' % text.strip(' ')
  60. def block_code(self, code, lang):
  61. if not lang:
  62. return '\n<pre><code>%s</code></pre>\n' % \
  63. mistune.escape(code)
  64. lexer = get_lexer_by_name(lang, stripall=True)
  65. formatter = HtmlFormatter()
  66. return highlight(code, lexer, formatter)
  67. renderer = FlaskBBRenderer(escape=True, hard_wrap=True)
  68. markdown = mistune.Markdown(renderer=renderer)