markup.py 2.4 KB

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