factory.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import re
  2. import markdown
  3. from HTMLParser import HTMLParser
  4. from django.conf import settings
  5. from django.utils.importlib import import_module
  6. from django.utils.translation import ugettext_lazy as _
  7. from misago.utils import get_random_string
  8. class ClearHTMLParser(HTMLParser):
  9. def __init__(self):
  10. HTMLParser.__init__(self)
  11. self.clean_text = ''
  12. def handle_starttag(self, tag, attrs):
  13. try:
  14. if tag == 'img':
  15. for attr in attrs:
  16. if attr[0] == 'src':
  17. self.clean_text += attr[1]
  18. if tag == 'a':
  19. for attr in attrs:
  20. if attr[0] == 'href':
  21. self.clean_text += attr[1]
  22. except IndexError, KeyError:
  23. pass
  24. def handle_data(self, data):
  25. if self.clean_text[-len(data):] != data:
  26. self.clean_text += ' %s' % data
  27. def clear_markdown(text):
  28. parser = ClearHTMLParser()
  29. parser.feed(text)
  30. return parser.clean_text
  31. def remove_unsupported(md):
  32. # References are evil, we dont support them
  33. del md.preprocessors['reference']
  34. del md.inlinePatterns['reference']
  35. del md.inlinePatterns['image_reference']
  36. del md.inlinePatterns['short_reference']
  37. def signature_markdown(acl, text):
  38. md = markdown.Markdown(
  39. safe_mode='escape',
  40. output_format=settings.OUTPUT_FORMAT,
  41. extensions=['nl2br'])
  42. remove_unsupported(md)
  43. if not acl.usercp.allow_signature_links():
  44. del md.inlinePatterns['link']
  45. del md.inlinePatterns['autolink']
  46. if not acl.usercp.allow_signature_images():
  47. del md.inlinePatterns['image_link']
  48. del md.parser.blockprocessors['hashheader']
  49. del md.parser.blockprocessors['setextheader']
  50. del md.parser.blockprocessors['code']
  51. del md.parser.blockprocessors['quote']
  52. del md.parser.blockprocessors['hr']
  53. del md.parser.blockprocessors['olist']
  54. del md.parser.blockprocessors['ulist']
  55. return md.convert(text)
  56. def post_markdown(request, text):
  57. md = markdown.Markdown(
  58. safe_mode='escape',
  59. output_format=settings.OUTPUT_FORMAT,
  60. extensions=['nl2br', 'fenced_code'])
  61. remove_unsupported(md)
  62. md.mi_token = get_random_string(16)
  63. for extension in settings.MARKDOWN_EXTENSIONS:
  64. module = '.'.join(extension.split('.')[:-1])
  65. extension = extension.split('.')[-1]
  66. module = import_module(module)
  67. attr = getattr(module, extension)
  68. ext = attr()
  69. ext.extendMarkdown(md)
  70. text = md.convert(text)
  71. # Final cleanups
  72. text = text.replace('<p><h3><quotetitle>', '<h3><quotetitle>')
  73. text = text.replace('</quotetitle></h3></p>', '</quotetitle></h3>')
  74. text = text.replace('</quotetitle></h3><br>\n', '</quotetitle></h3>\n<p>')
  75. text = text.replace('\n<p></p>', '')
  76. def trans_quotetitle(match):
  77. return _("Posted by %(user)s") % {'user': match.group('content')}
  78. text = re.sub(r'<quotetitle>(?P<content>.+)</quotetitle>', trans_quotetitle, text)
  79. return md, text