OLD | NEW |
(Empty) | |
| 1 # markdown is released under the BSD license |
| 2 # Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later) |
| 3 # Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b) |
| 4 # Copyright 2004 Manfred Stienstra (the original version) |
| 5 # |
| 6 # All rights reserved. |
| 7 # |
| 8 # Redistribution and use in source and binary forms, with or without |
| 9 # modification, are permitted provided that the following conditions are met: |
| 10 # |
| 11 # * Redistributions of source code must retain the above copyright |
| 12 # notice, this list of conditions and the following disclaimer. |
| 13 # * Redistributions in binary form must reproduce the above copyright |
| 14 # notice, this list of conditions and the following disclaimer in the |
| 15 # documentation and/or other materials provided with the distribution. |
| 16 # * Neither the name of the <organization> nor the |
| 17 # names of its contributors may be used to endorse or promote products |
| 18 # derived from this software without specific prior written permission. |
| 19 # |
| 20 # THIS SOFTWARE IS PROVIDED BY THE PYTHON MARKDOWN PROJECT ''AS IS'' AND ANY |
| 21 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 22 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 23 # DISCLAIMED. IN NO EVENT SHALL ANY CONTRIBUTORS TO THE PYTHON MARKDOWN PROJECT |
| 24 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 25 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 26 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 27 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 28 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 29 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 30 # POSSIBILITY OF SUCH DAMAGE. |
| 31 |
| 32 |
| 33 """ |
| 34 Definition List Extension for Python-Markdown |
| 35 ============================================= |
| 36 |
| 37 Added parsing of Definition Lists to Python-Markdown. |
| 38 |
| 39 A simple example: |
| 40 |
| 41 Apple |
| 42 : Pomaceous fruit of plants of the genus Malus in |
| 43 the family Rosaceae. |
| 44 : An american computer company. |
| 45 |
| 46 Orange |
| 47 : The fruit of an evergreen tree of the genus Citrus. |
| 48 |
| 49 Copyright 2008 - [Waylan Limberg](http://achinghead.com) |
| 50 |
| 51 """ |
| 52 |
| 53 from __future__ import absolute_import |
| 54 from __future__ import unicode_literals |
| 55 from . import Extension |
| 56 from ..blockprocessors import BlockProcessor, ListIndentProcessor |
| 57 from ..util import etree |
| 58 import re |
| 59 |
| 60 |
| 61 class DefListProcessor(BlockProcessor): |
| 62 """ Process Definition Lists. """ |
| 63 |
| 64 RE = re.compile(r'(^|\n)[ ]{0,3}:[ ]{1,3}(.*?)(\n|$)') |
| 65 NO_INDENT_RE = re.compile(r'^[ ]{0,3}[^ :]') |
| 66 |
| 67 def test(self, parent, block): |
| 68 return bool(self.RE.search(block)) |
| 69 |
| 70 def run(self, parent, blocks): |
| 71 |
| 72 raw_block = blocks.pop(0) |
| 73 m = self.RE.search(raw_block) |
| 74 terms = [l.strip() for l in raw_block[:m.start()].split('\n') if l.strip
()] |
| 75 block = raw_block[m.end():] |
| 76 no_indent = self.NO_INDENT_RE.match(block) |
| 77 if no_indent: |
| 78 d, theRest = (block, None) |
| 79 else: |
| 80 d, theRest = self.detab(block) |
| 81 if d: |
| 82 d = '%s\n%s' % (m.group(2), d) |
| 83 else: |
| 84 d = m.group(2) |
| 85 sibling = self.lastChild(parent) |
| 86 if not terms and sibling is None: |
| 87 # This is not a definition item. Most likely a paragraph that |
| 88 # starts with a colon at the begining of a document or list. |
| 89 blocks.insert(0, raw_block) |
| 90 return False |
| 91 if not terms and sibling.tag == 'p': |
| 92 # The previous paragraph contains the terms |
| 93 state = 'looselist' |
| 94 terms = sibling.text.split('\n') |
| 95 parent.remove(sibling) |
| 96 # Aquire new sibling |
| 97 sibling = self.lastChild(parent) |
| 98 else: |
| 99 state = 'list' |
| 100 |
| 101 if sibling and sibling.tag == 'dl': |
| 102 # This is another item on an existing list |
| 103 dl = sibling |
| 104 if len(dl) and dl[-1].tag == 'dd' and len(dl[-1]): |
| 105 state = 'looselist' |
| 106 else: |
| 107 # This is a new list |
| 108 dl = etree.SubElement(parent, 'dl') |
| 109 # Add terms |
| 110 for term in terms: |
| 111 dt = etree.SubElement(dl, 'dt') |
| 112 dt.text = term |
| 113 # Add definition |
| 114 self.parser.state.set(state) |
| 115 dd = etree.SubElement(dl, 'dd') |
| 116 self.parser.parseBlocks(dd, [d]) |
| 117 self.parser.state.reset() |
| 118 |
| 119 if theRest: |
| 120 blocks.insert(0, theRest) |
| 121 |
| 122 class DefListIndentProcessor(ListIndentProcessor): |
| 123 """ Process indented children of definition list items. """ |
| 124 |
| 125 ITEM_TYPES = ['dd'] |
| 126 LIST_TYPES = ['dl'] |
| 127 |
| 128 def create_item(self, parent, block): |
| 129 """ Create a new dd and parse the block with it as the parent. """ |
| 130 dd = etree.SubElement(parent, 'dd') |
| 131 self.parser.parseBlocks(dd, [block]) |
| 132 |
| 133 |
| 134 |
| 135 class DefListExtension(Extension): |
| 136 """ Add definition lists to Markdown. """ |
| 137 |
| 138 def extendMarkdown(self, md, md_globals): |
| 139 """ Add an instance of DefListProcessor to BlockParser. """ |
| 140 md.parser.blockprocessors.add('defindent', |
| 141 DefListIndentProcessor(md.parser), |
| 142 '>indent') |
| 143 md.parser.blockprocessors.add('deflist', |
| 144 DefListProcessor(md.parser), |
| 145 '>ulist') |
| 146 |
| 147 |
| 148 def makeExtension(configs={}): |
| 149 return DefListExtension(configs=configs) |
| 150 |
OLD | NEW |