diff options
author | Waylan Limberg <waylan@gmail.com> | 2013-10-14 15:31:49 -0700 |
---|---|---|
committer | Waylan Limberg <waylan@gmail.com> | 2013-10-14 15:31:49 -0700 |
commit | d700d0a243b3e461f2e9ff189137be31c15972f4 (patch) | |
tree | c9b329436683582b18e219b5061f9a84ec7f718d /markdown/extensions/extra.py | |
parent | 191d88b26c6bcb1cd9f66cb3a115e106366d1a55 (diff) | |
parent | daa2d46b567e67aa4578a5c26a7d92e4cf5abc81 (diff) | |
download | markdown-d700d0a243b3e461f2e9ff189137be31c15972f4.tar.gz markdown-d700d0a243b3e461f2e9ff189137be31c15972f4.tar.bz2 markdown-d700d0a243b3e461f2e9ff189137be31c15972f4.zip |
Merge pull request #260 from ryneeverett/master
Issue #52 Patch -- Markdown Inside HTML Blocks
Diffstat (limited to 'markdown/extensions/extra.py')
-rw-r--r-- | markdown/extensions/extra.py | 93 |
1 files changed, 85 insertions, 8 deletions
diff --git a/markdown/extensions/extra.py b/markdown/extensions/extra.py index e6a1e82..dd70305 100644 --- a/markdown/extensions/extra.py +++ b/markdown/extensions/extra.py @@ -6,22 +6,22 @@ A compilation of various Python-Markdown extensions that imitates [PHP Markdown Extra](http://michelf.com/projects/php-markdown/extra/). Note that each of the individual extensions still need to be available -on your PYTHONPATH. This extension simply wraps them all up as a +on your PYTHONPATH. This extension simply wraps them all up as a convenience so that only one extension needs to be listed when initiating Markdown. See the documentation for each individual extension for specifics about that extension. -In the event that one or more of the supported extensions are not -available for import, Markdown will issue a warning and simply continue -without that extension. +In the event that one or more of the supported extensions are not +available for import, Markdown will issue a warning and simply continue +without that extension. -There may be additional extensions that are distributed with +There may be additional extensions that are distributed with Python-Markdown that are not included here in Extra. Those extensions are not part of PHP Markdown Extra, and therefore, not part of Python-Markdown Extra. If you really would like Extra to include additional extensions, we suggest creating your own clone of Extra -under a differant name. You could also edit the `extensions` global -variable defined below, but be aware that such changes may be lost +under a differant name. You could also edit the `extensions` global +variable defined below, but be aware that such changes may be lost when you upgrade to any future version of Python-Markdown. """ @@ -29,6 +29,9 @@ when you upgrade to any future version of Python-Markdown. from __future__ import absolute_import from __future__ import unicode_literals from . import Extension +from ..blockprocessors import BlockProcessor +from .. import util +import re extensions = ['smart_strong', 'fenced_code', @@ -38,7 +41,7 @@ extensions = ['smart_strong', 'tables', 'abbr', ] - + class ExtraExtension(Extension): """ Add various extensions to Markdown class.""" @@ -49,6 +52,80 @@ class ExtraExtension(Extension): if not md.safeMode: # Turn on processing of markdown text within raw html md.preprocessors['html_block'].markdown_in_raw = True + md.parser.blockprocessors.add('markdown_block', + MarkdownInHtmlProcessor(md.parser), + '_begin') + md.parser.blockprocessors.tag_counter = -1 + md.parser.blockprocessors.contain_span_tags = re.compile( + r'^(p|h[1-6]|li|dd|dt|td|th|legend|address)$', re.IGNORECASE) + def makeExtension(configs={}): return ExtraExtension(configs=dict(configs)) + + +class MarkdownInHtmlProcessor(BlockProcessor): + """Process Markdown Inside HTML Blocks.""" + def test(self, parent, block): + return block == util.TAG_PLACEHOLDER % \ + str(self.parser.blockprocessors.tag_counter + 1) + + def _process_nests(self, element, block): + """Process the element's child elements in self.run.""" + # Build list of indexes of each nest within the parent element. + nest_index = [] # a list of tuples: (left index, right index) + i = self.parser.blockprocessors.tag_counter + 1 + while len(self.parser.markdown.htmlStash.tag_data) > i and self.\ + parser.markdown.htmlStash.tag_data[i]['left_index']: + left_child_index = \ + self.parser.markdown.htmlStash.tag_data[i]['left_index'] + right_child_index = \ + self.parser.markdown.htmlStash.tag_data[i]['right_index'] + nest_index.append((left_child_index - 1, right_child_index)) + i += 1 + + # Create each nest subelement. + i = 0 + for n in nest_index[:-1]: + self.run(element, block[n[0]:n[1]], + block[n[1]:nest_index[i + 1][0]], True) + i += 1 + self.run(element, block[nest_index[-1][0]:nest_index[-1][1]], # last + block[nest_index[-1][1]:], True) # nest + + def run(self, parent, blocks, tail=None, nest=False): + self.parser.blockprocessors.tag_counter += 1 + tag_data = self.parser.markdown.htmlStash.tag_data[ + self.parser.blockprocessors.tag_counter] + + # Create Element + markdown_value = tag_data['attrs'].pop('markdown') + element = util.etree.SubElement(parent, tag_data['tag'], + tag_data['attrs']) + + # Slice Off Block + if nest: + self.parser.parseBlocks(parent, tail) # Process Tail + block = blocks[1:] + else: # includes nests since a third level of nesting isn't supported + block = blocks[tag_data['left_index'] + 1: + tag_data['right_index']] + del blocks[:tag_data['right_index']] + + # Process Text + if (self.parser.blockprocessors.contain_span_tags.match( # Span Mode + tag_data['tag']) and markdown_value != 'block') or \ + markdown_value == 'span': + element.text = '\n'.join(block) + else: # Block Mode + i = self.parser.blockprocessors.tag_counter + 1 + if len(self.parser.markdown.htmlStash.tag_data) > i and self.\ + parser.markdown.htmlStash.tag_data[i]['left_index']: + first_subelement_index = self.parser.markdown.htmlStash.\ + tag_data[i]['left_index'] - 1 + self.parser.parseBlocks( + element, block[:first_subelement_index]) + if not nest: + block = self._process_nests(element, block) + else: + self.parser.parseBlocks(element, block) |