blocks.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. from __future__ import unicode_literals
  2. import re
  3. from django.utils.crypto import get_random_string
  4. import markdown
  5. from markdown.blockprocessors import BlockProcessor, HRProcessor
  6. from markdown.preprocessors import Preprocessor
  7. from markdown.util import etree
  8. QUOTE_START = get_random_string(32)
  9. QUOTE_END = get_random_string(32)
  10. class BBCodeHRProcessor(HRProcessor):
  11. RE = r'^\[hr\]*'
  12. # Detect hr on any line of a block.
  13. SEARCH_RE = re.compile(RE, re.MULTILINE | re.IGNORECASE)
  14. class QuoteExtension(markdown.Extension):
  15. def extendMarkdown(self, md):
  16. md.registerExtension(self)
  17. md.preprocessors.add('misago_bbcode_quote', QuotePreprocessor(md), '_end')
  18. md.parser.blockprocessors.add('misago_bbcode_quote', QuoteBlockProcessor(md.parser), '<paragraph')
  19. class QuotePreprocessor(Preprocessor):
  20. QUOTE_BLOCK_RE = re.compile(r'''
  21. \[quote\](?P<text>.*?)\[/quote\]
  22. '''.strip(), re.IGNORECASE | re.MULTILINE | re.DOTALL);
  23. def run(self, lines):
  24. text = '\n'.join(lines)
  25. while '[quote]' in text and '[/quote]' in text:
  26. text = self.QUOTE_BLOCK_RE.sub(self.replace, text)
  27. return text.split('\n')
  28. def replace(self, matchobj):
  29. text = matchobj.group('text')
  30. return '\n\n{}\n\n{}\n\n{}\n\n'.format(QUOTE_START, text, QUOTE_END)
  31. class QuoteBlockProcessor(BlockProcessor):
  32. def __init__(self, *args, **kwargs):
  33. super(QuoteBlockProcessor, self).__init__(*args, **kwargs)
  34. self._quote = 0
  35. self._children = []
  36. def test(self, parent, block):
  37. return block.strip() == QUOTE_START or self._quote
  38. def run(self, parent, blocks):
  39. block = blocks.pop(0)
  40. if block.strip() == QUOTE_START:
  41. self._quote += 1
  42. self._children.append(block)
  43. if block.strip() == QUOTE_END:
  44. self._quote -= 1
  45. if not self._quote:
  46. children, self._children = self._children[1:-1], []
  47. blockquote = etree.SubElement(parent, 'blockquote')
  48. self.parser.parseBlocks(blockquote, children)