| OLD | NEW |
| (Empty) |
| 1 """ | |
| 2 Definition List Extension for Python-Markdown | |
| 3 ============================================= | |
| 4 | |
| 5 Adds parsing of Definition Lists to Python-Markdown. | |
| 6 | |
| 7 See <https://pythonhosted.org/Markdown/extensions/definition_lists.html> | |
| 8 for documentation. | |
| 9 | |
| 10 Original code Copyright 2008 [Waylan Limberg](http://achinghead.com) | |
| 11 | |
| 12 All changes Copyright 2008-2014 The Python Markdown Project | |
| 13 | |
| 14 License: [BSD](http://www.opensource.org/licenses/bsd-license.php) | |
| 15 | |
| 16 """ | |
| 17 | |
| 18 from __future__ import absolute_import | |
| 19 from __future__ import unicode_literals | |
| 20 from . import Extension | |
| 21 from ..blockprocessors import BlockProcessor, ListIndentProcessor | |
| 22 from ..util import etree | |
| 23 import re | |
| 24 | |
| 25 | |
| 26 class DefListProcessor(BlockProcessor): | |
| 27 """ Process Definition Lists. """ | |
| 28 | |
| 29 RE = re.compile(r'(^|\n)[ ]{0,3}:[ ]{1,3}(.*?)(\n|$)') | |
| 30 NO_INDENT_RE = re.compile(r'^[ ]{0,3}[^ :]') | |
| 31 | |
| 32 def test(self, parent, block): | |
| 33 return bool(self.RE.search(block)) | |
| 34 | |
| 35 def run(self, parent, blocks): | |
| 36 | |
| 37 raw_block = blocks.pop(0) | |
| 38 m = self.RE.search(raw_block) | |
| 39 terms = [l.strip() for l in | |
| 40 raw_block[:m.start()].split('\n') if l.strip()] | |
| 41 block = raw_block[m.end():] | |
| 42 no_indent = self.NO_INDENT_RE.match(block) | |
| 43 if no_indent: | |
| 44 d, theRest = (block, None) | |
| 45 else: | |
| 46 d, theRest = self.detab(block) | |
| 47 if d: | |
| 48 d = '%s\n%s' % (m.group(2), d) | |
| 49 else: | |
| 50 d = m.group(2) | |
| 51 sibling = self.lastChild(parent) | |
| 52 if not terms and sibling is None: | |
| 53 # This is not a definition item. Most likely a paragraph that | |
| 54 # starts with a colon at the begining of a document or list. | |
| 55 blocks.insert(0, raw_block) | |
| 56 return False | |
| 57 if not terms and sibling.tag == 'p': | |
| 58 # The previous paragraph contains the terms | |
| 59 state = 'looselist' | |
| 60 terms = sibling.text.split('\n') | |
| 61 parent.remove(sibling) | |
| 62 # Aquire new sibling | |
| 63 sibling = self.lastChild(parent) | |
| 64 else: | |
| 65 state = 'list' | |
| 66 | |
| 67 if sibling is not None and sibling.tag == 'dl': | |
| 68 # This is another item on an existing list | |
| 69 dl = sibling | |
| 70 if not terms and len(dl) and dl[-1].tag == 'dd' and len(dl[-1]): | |
| 71 state = 'looselist' | |
| 72 else: | |
| 73 # This is a new list | |
| 74 dl = etree.SubElement(parent, 'dl') | |
| 75 # Add terms | |
| 76 for term in terms: | |
| 77 dt = etree.SubElement(dl, 'dt') | |
| 78 dt.text = term | |
| 79 # Add definition | |
| 80 self.parser.state.set(state) | |
| 81 dd = etree.SubElement(dl, 'dd') | |
| 82 self.parser.parseBlocks(dd, [d]) | |
| 83 self.parser.state.reset() | |
| 84 | |
| 85 if theRest: | |
| 86 blocks.insert(0, theRest) | |
| 87 | |
| 88 | |
| 89 class DefListIndentProcessor(ListIndentProcessor): | |
| 90 """ Process indented children of definition list items. """ | |
| 91 | |
| 92 ITEM_TYPES = ['dd'] | |
| 93 LIST_TYPES = ['dl'] | |
| 94 | |
| 95 def create_item(self, parent, block): | |
| 96 """ Create a new dd and parse the block with it as the parent. """ | |
| 97 dd = etree.SubElement(parent, 'dd') | |
| 98 self.parser.parseBlocks(dd, [block]) | |
| 99 | |
| 100 | |
| 101 class DefListExtension(Extension): | |
| 102 """ Add definition lists to Markdown. """ | |
| 103 | |
| 104 def extendMarkdown(self, md, md_globals): | |
| 105 """ Add an instance of DefListProcessor to BlockParser. """ | |
| 106 md.parser.blockprocessors.add('defindent', | |
| 107 DefListIndentProcessor(md.parser), | |
| 108 '>indent') | |
| 109 md.parser.blockprocessors.add('deflist', | |
| 110 DefListProcessor(md.parser), | |
| 111 '>ulist') | |
| 112 | |
| 113 | |
| 114 def makeExtension(*args, **kwargs): | |
| 115 return DefListExtension(*args, **kwargs) | |
| OLD | NEW |