119 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """
 | |
| Admonition extension for Python-Markdown
 | |
| ========================================
 | |
| 
 | |
| Adds rST-style admonitions. Inspired by [rST][] feature with the same name.
 | |
| 
 | |
| The syntax is (followed by an indented block with the contents):
 | |
|     !!! [type] [optional explicit title]
 | |
| 
 | |
| Where `type` is used as a CSS class name of the div. If not present, `title`
 | |
| defaults to the capitalized `type`, so "note" -> "Note".
 | |
| 
 | |
| rST suggests the following `types`, but you're free to use whatever you want:
 | |
|     attention, caution, danger, error, hint, important, note, tip, warning
 | |
| 
 | |
| 
 | |
| A simple example:
 | |
|     !!! note
 | |
|         This is the first line inside the box.
 | |
| 
 | |
| Outputs:
 | |
|     <div class="admonition note">
 | |
|     <p class="admonition-title">Note</p>
 | |
|     <p>This is the first line inside the box</p>
 | |
|     </div>
 | |
| 
 | |
| You can also specify the title and CSS class of the admonition:
 | |
|     !!! custom "Did you know?"
 | |
|         Another line here.
 | |
| 
 | |
| Outputs:
 | |
|     <div class="admonition custom">
 | |
|     <p class="admonition-title">Did you know?</p>
 | |
|     <p>Another line here.</p>
 | |
|     </div>
 | |
| 
 | |
| [rST]: http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific-admonitions
 | |
| 
 | |
| By [Tiago Serafim](http://www.tiagoserafim.com/).
 | |
| 
 | |
| """
 | |
| 
 | |
| 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 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(configs={}):
 | |
|     return AdmonitionExtension(configs=configs)
 |