Home | History | Annotate | Download | only in extensions
      1 #!/usr/bin/env Python
      2 """
      3 Definition List Extension for Python-Markdown
      4 =============================================
      5 
      6 Added parsing of Definition Lists to Python-Markdown.
      7 
      8 A simple example:
      9 
     10     Apple
     11     :   Pomaceous fruit of plants of the genus Malus in 
     12         the family Rosaceae.
     13     :   An american computer company.
     14 
     15     Orange
     16     :   The fruit of an evergreen tree of the genus Citrus.
     17 
     18 Copyright 2008 - [Waylan Limberg](http://achinghead.com)
     19 
     20 """
     21 
     22 import markdown, re
     23 from markdown import etree
     24 
     25 
     26 class DefListProcessor(markdown.blockprocessors.BlockProcessor):
     27     """ Process Definition Lists. """
     28 
     29     RE = re.compile(r'(^|\n)[ ]{0,3}:[ ]{1,3}(.*?)(\n|$)')
     30 
     31     def test(self, parent, block):
     32         return bool(self.RE.search(block))
     33 
     34     def run(self, parent, blocks):
     35         block = blocks.pop(0)
     36         m = self.RE.search(block)
     37         terms = [l.strip() for l in block[:m.start()].split('\n') if l.strip()]
     38         d, theRest = self.detab(block[m.end():])
     39         if d:
     40             d = '%s\n%s' % (m.group(2), d)
     41         else:
     42             d = m.group(2)
     43         #import ipdb; ipdb.set_trace()
     44         sibling = self.lastChild(parent)
     45         if not terms and sibling.tag == 'p':
     46             # The previous paragraph contains the terms
     47             state = 'looselist'
     48             terms = sibling.text.split('\n')
     49             parent.remove(sibling)
     50             # Aquire new sibling
     51             sibling = self.lastChild(parent)
     52         else:
     53             state = 'list'
     54 
     55         if sibling and sibling.tag == 'dl':
     56             # This is another item on an existing list
     57             dl = sibling
     58             if len(dl) and dl[-1].tag == 'dd' and len(dl[-1]):
     59                 state = 'looselist'
     60         else:
     61             # This is a new list
     62             dl = etree.SubElement(parent, 'dl')
     63         # Add terms
     64         for term in terms:
     65             dt = etree.SubElement(dl, 'dt')
     66             dt.text = term
     67         # Add definition
     68         self.parser.state.set(state)
     69         dd = etree.SubElement(dl, 'dd')
     70         self.parser.parseBlocks(dd, [d])
     71         self.parser.state.reset()
     72 
     73         if theRest:
     74             blocks.insert(0, theRest)
     75 
     76 class DefListIndentProcessor(markdown.blockprocessors.ListIndentProcessor):
     77     """ Process indented children of definition list items. """
     78 
     79     ITEM_TYPES = ['dd']
     80     LIST_TYPES = ['dl']
     81 
     82     def create_item(parent, block):
     83         """ Create a new dd and parse the block with it as the parent. """
     84         dd = markdown.etree.SubElement(parent, 'dd')
     85         self.parser.parseBlocks(dd, [block])
     86  
     87 
     88 
     89 class DefListExtension(markdown.Extension):
     90     """ Add definition lists to Markdown. """
     91 
     92     def extendMarkdown(self, md, md_globals):
     93         """ Add an instance of DefListProcessor to BlockParser. """
     94         md.parser.blockprocessors.add('defindent',
     95                                       DefListIndentProcessor(md.parser),
     96                                       '>indent')
     97         md.parser.blockprocessors.add('deflist', 
     98                                       DefListProcessor(md.parser),
     99                                       '>ulist')
    100 
    101 
    102 def makeExtension(configs={}):
    103     return DefListExtension(configs=configs)
    104 
    105