aboutsummaryrefslogtreecommitdiffstats
path: root/markdown/extensions/extra.py
diff options
context:
space:
mode:
authorWaylan Limberg <waylan@gmail.com>2013-10-14 15:31:49 -0700
committerWaylan Limberg <waylan@gmail.com>2013-10-14 15:31:49 -0700
commitd700d0a243b3e461f2e9ff189137be31c15972f4 (patch)
treec9b329436683582b18e219b5061f9a84ec7f718d /markdown/extensions/extra.py
parent191d88b26c6bcb1cd9f66cb3a115e106366d1a55 (diff)
parentdaa2d46b567e67aa4578a5c26a7d92e4cf5abc81 (diff)
downloadmarkdown-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.py93
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)