OLD | NEW |
(Empty) | |
| 1 """ |
| 2 Admonition extension for Python-Markdown |
| 3 ======================================== |
| 4 |
| 5 Adds rST-style admonitions. Inspired by [rST][] feature with the same name. |
| 6 |
| 7 [rST]: http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific-adm
onitions # noqa |
| 8 |
| 9 See <https://pythonhosted.org/Markdown/extensions/admonition.html> |
| 10 for documentation. |
| 11 |
| 12 Original code Copyright [Tiago Serafim](http://www.tiagoserafim.com/). |
| 13 |
| 14 All changes Copyright The Python Markdown Project |
| 15 |
| 16 License: [BSD](http://www.opensource.org/licenses/bsd-license.php) |
| 17 |
| 18 """ |
| 19 |
| 20 from __future__ import absolute_import |
| 21 from __future__ import unicode_literals |
| 22 from . import Extension |
| 23 from ..blockprocessors import BlockProcessor |
| 24 from ..util import etree |
| 25 import re |
| 26 |
| 27 |
| 28 class AdmonitionExtension(Extension): |
| 29 """ Admonition extension for Python-Markdown. """ |
| 30 |
| 31 def extendMarkdown(self, md, md_globals): |
| 32 """ Add Admonition to Markdown instance. """ |
| 33 md.registerExtension(self) |
| 34 |
| 35 md.parser.blockprocessors.add('admonition', |
| 36 AdmonitionProcessor(md.parser), |
| 37 '_begin') |
| 38 |
| 39 |
| 40 class AdmonitionProcessor(BlockProcessor): |
| 41 |
| 42 CLASSNAME = 'admonition' |
| 43 CLASSNAME_TITLE = 'admonition-title' |
| 44 RE = re.compile(r'(?:^|\n)!!!\ ?([\w\-]+)(?:\ "(.*?)")?') |
| 45 |
| 46 def test(self, parent, block): |
| 47 sibling = self.lastChild(parent) |
| 48 return self.RE.search(block) or \ |
| 49 (block.startswith(' ' * self.tab_length) and sibling is not None and |
| 50 sibling.get('class', '').find(self.CLASSNAME) != -1) |
| 51 |
| 52 def run(self, parent, blocks): |
| 53 sibling = self.lastChild(parent) |
| 54 block = blocks.pop(0) |
| 55 m = self.RE.search(block) |
| 56 |
| 57 if m: |
| 58 block = block[m.end() + 1:] # removes the first line |
| 59 |
| 60 block, theRest = self.detab(block) |
| 61 |
| 62 if m: |
| 63 klass, title = self.get_class_and_title(m) |
| 64 div = etree.SubElement(parent, 'div') |
| 65 div.set('class', '%s %s' % (self.CLASSNAME, klass)) |
| 66 if title: |
| 67 p = etree.SubElement(div, 'p') |
| 68 p.text = title |
| 69 p.set('class', self.CLASSNAME_TITLE) |
| 70 else: |
| 71 div = sibling |
| 72 |
| 73 self.parser.parseChunk(div, block) |
| 74 |
| 75 if theRest: |
| 76 # This block contained unindented line(s) after the first indented |
| 77 # line. Insert these lines as the first block of the master blocks |
| 78 # list for future processing. |
| 79 blocks.insert(0, theRest) |
| 80 |
| 81 def get_class_and_title(self, match): |
| 82 klass, title = match.group(1).lower(), match.group(2) |
| 83 if title is None: |
| 84 # no title was provided, use the capitalized classname as title |
| 85 # e.g.: `!!! note` will render |
| 86 # `<p class="admonition-title">Note</p>` |
| 87 title = klass.capitalize() |
| 88 elif title == '': |
| 89 # an explicit blank title should not be rendered |
| 90 # e.g.: `!!! warning ""` will *not* render `p` with a title |
| 91 title = None |
| 92 return klass, title |
| 93 |
| 94 |
| 95 def makeExtension(*args, **kwargs): |
| 96 return AdmonitionExtension(*args, **kwargs) |
OLD | NEW |