15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# markdown is released under the BSD license
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later)
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright 2004 Manfred Stienstra (the original version)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# All rights reserved.
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Redistribution and use in source and binary forms, with or without
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# modification, are permitted provided that the following conditions are met:
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# *   Redistributions of source code must retain the above copyright
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#     notice, this list of conditions and the following disclaimer.
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# *   Redistributions in binary form must reproduce the above copyright
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#     notice, this list of conditions and the following disclaimer in the
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#     documentation and/or other materials provided with the distribution.
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# *   Neither the name of the <organization> nor the
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#     names of its contributors may be used to endorse or promote products
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#     derived from this software without specific prior written permission.
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY THE PYTHON MARKDOWN PROJECT ''AS IS'' AND ANY
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# DISCLAIMED. IN NO EVENT SHALL ANY CONTRIBUTORS TO THE PYTHON MARKDOWN PROJECT
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# POSSIBILITY OF SUCH DAMAGE.
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from __future__ import unicode_literals
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from __future__ import absolute_import
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from . import util
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from . import odict
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class State(list):
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    """ Track the current and nested state of the parser.
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    This utility class is used to track the state of the BlockParser and
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    support multiple levels if nesting. It's just a simple API wrapped around
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    a list. Each time a state is set, that state is appended to the end of the
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    list. Each time a state is reset, that state is removed from the end of
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    the list.
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Therefore, each time a state is set for a nested block, that state must be
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    reset when we back out of that level of nesting or the state could be
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    corrupted.
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    While all the methods of a list object are available, only the three
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    defined below need be used.
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    """
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def set(self, state):
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """ Set a new state. """
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.append(state)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def reset(self):
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """ Step back one step in nested state. """
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.pop()
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def isstate(self, state):
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """ Test that top (current) level is of given state. """
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if len(self):
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            return self[-1] == state
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            return False
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class BlockParser:
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    """ Parse Markdown blocks into an ElementTree object.
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    A wrapper class that stitches the various BlockProcessors together,
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    looping through them and creating an ElementTree object.
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    """
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def __init__(self, markdown):
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.blockprocessors = odict.OrderedDict()
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.state = State()
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.markdown = markdown
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def parseDocument(self, lines):
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """ Parse a markdown document into an ElementTree.
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        Given a list of lines, an ElementTree object (not just a parent Element)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        is created and the root element is passed to the parser as the parent.
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        The ElementTree object is returned.
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        This should only be called on an entire document, not pieces.
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # Create a ElementTree from the lines
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.root = util.etree.Element(self.markdown.doc_tag)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.parseChunk(self.root, '\n'.join(lines))
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return util.etree.ElementTree(self.root)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def parseChunk(self, parent, text):
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """ Parse a chunk of markdown text and attach to given etree node.
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        While the ``text`` argument is generally assumed to contain multiple
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        blocks which will be split on blank lines, it could contain only one
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        block. Generally, this method would be called by extensions when
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        block parsing is required.
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        The ``parent`` etree Element passed in is altered in place.
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        Nothing is returned.
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.parseBlocks(parent, text.split('\n\n'))
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def parseBlocks(self, parent, blocks):
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """ Process blocks of markdown text and attach to given etree node.
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        Given a list of ``blocks``, each blockprocessor is stepped through
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        until there are no blocks left. While an extension could potentially
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        call this method directly, it's generally expected to be used internally.
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        This is a public method as an extension may need to add/alter additional
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BlockProcessors which call this method to recursively parse a nested
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        block.
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        """
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        while blocks:
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            for processor in self.blockprocessors.values():
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if processor.test(parent, blocks[0]):
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if processor.run(parent, blocks) is not False:
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        # run returns True or None
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        break
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
132