summaryrefslogtreecommitdiffstats
path: root/source-builder/sb/markdown/extensions/admonition.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--source-builder/sb/markdown/extensions/admonition.py96
1 files changed, 96 insertions, 0 deletions
diff --git a/source-builder/sb/markdown/extensions/admonition.py b/source-builder/sb/markdown/extensions/admonition.py
new file mode 100644
index 0000000..76e0fb5
--- /dev/null
+++ b/source-builder/sb/markdown/extensions/admonition.py
@@ -0,0 +1,96 @@
+"""
+Admonition extension for Python-Markdown
+========================================
+
+Adds rST-style admonitions. Inspired by [rST][] feature with the same name.
+
+[rST]: http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific-admonitions # noqa
+
+See <https://pythonhosted.org/Markdown/extensions/admonition.html>
+for documentation.
+
+Original code Copyright [Tiago Serafim](http://www.tiagoserafim.com/).
+
+All changes Copyright The Python Markdown Project
+
+License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
+
+"""
+
+from __future__ import absolute_import
+from __future__ import unicode_literals
+from . import Extension
+from ..blockprocessors import BlockProcessor
+from ..util import etree
+import re
+
+
+class AdmonitionExtension(Extension):
+ """ Admonition extension for Python-Markdown. """
+
+ def extendMarkdown(self, md, md_globals):
+ """ Add Admonition to Markdown instance. """
+ md.registerExtension(self)
+
+ md.parser.blockprocessors.add('admonition',
+ AdmonitionProcessor(md.parser),
+ '_begin')
+
+
+class AdmonitionProcessor(BlockProcessor):
+
+ CLASSNAME = 'admonition'
+ CLASSNAME_TITLE = 'admonition-title'
+ RE = re.compile(r'(?:^|\n)!!!\ ?([\w\-]+)(?:\ "(.*?)")?')
+
+ def test(self, parent, block):
+ sibling = self.lastChild(parent)
+ return self.RE.search(block) or \
+ (block.startswith(' ' * self.tab_length) and sibling is not None and
+ sibling.get('class', '').find(self.CLASSNAME) != -1)
+
+ def run(self, parent, blocks):
+ sibling = self.lastChild(parent)
+ block = blocks.pop(0)
+ m = self.RE.search(block)
+
+ if m:
+ block = block[m.end() + 1:] # removes the first line
+
+ block, theRest = self.detab(block)
+
+ if m:
+ klass, title = self.get_class_and_title(m)
+ div = etree.SubElement(parent, 'div')
+ div.set('class', '%s %s' % (self.CLASSNAME, klass))
+ if title:
+ p = etree.SubElement(div, 'p')
+ p.text = title
+ p.set('class', self.CLASSNAME_TITLE)
+ else:
+ div = sibling
+
+ self.parser.parseChunk(div, block)
+
+ if theRest:
+ # This block contained unindented line(s) after the first indented
+ # line. Insert these lines as the first block of the master blocks
+ # list for future processing.
+ blocks.insert(0, theRest)
+
+ def get_class_and_title(self, match):
+ klass, title = match.group(1).lower(), match.group(2)
+ if title is None:
+ # no title was provided, use the capitalized classname as title
+ # e.g.: `!!! note` will render
+ # `<p class="admonition-title">Note</p>`
+ title = klass.capitalize()
+ elif title == '':
+ # an explicit blank title should not be rendered
+ # e.g.: `!!! warning ""` will *not* render `p` with a title
+ title = None
+ return klass, title
+
+
+def makeExtension(*args, **kwargs):
+ return AdmonitionExtension(*args, **kwargs)