[Mac] Enable MacViews bookmark editor behind --enable-mac-views-dialogs.
[chromium-blink-merge.git] / third_party / markdown / extensions / admonition.py
blob48e3aaac06e0fe2014e273e2a6e845a1cac53b56
1 # markdown is released under the BSD license
2 # Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later)
3 # Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
4 # Copyright 2004 Manfred Stienstra (the original version)
5 #
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are met:
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above copyright
14 # notice, this list of conditions and the following disclaimer in the
15 # documentation and/or other materials provided with the distribution.
16 # * Neither the name of the <organization> nor the
17 # names of its contributors may be used to endorse or promote products
18 # derived from this software without specific prior written permission.
20 # THIS SOFTWARE IS PROVIDED BY THE PYTHON MARKDOWN PROJECT ''AS IS'' AND ANY
21 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 # DISCLAIMED. IN NO EVENT SHALL ANY CONTRIBUTORS TO THE PYTHON MARKDOWN PROJECT
24 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 # POSSIBILITY OF SUCH DAMAGE.
33 """
34 Admonition extension for Python-Markdown
35 ========================================
37 Adds rST-style admonitions. Inspired by [rST][] feature with the same name.
39 The syntax is (followed by an indented block with the contents):
40 !!! [type] [optional explicit title]
42 Where `type` is used as a CSS class name of the div. If not present, `title`
43 defaults to the capitalized `type`, so "note" -> "Note".
45 rST suggests the following `types`, but you're free to use whatever you want:
46 attention, caution, danger, error, hint, important, note, tip, warning
49 A simple example:
50 !!! note
51 This is the first line inside the box.
53 Outputs:
54 <div class="admonition note">
55 <p class="admonition-title">Note</p>
56 <p>This is the first line inside the box</p>
57 </div>
59 You can also specify the title and CSS class of the admonition:
60 !!! custom "Did you know?"
61 Another line here.
63 Outputs:
64 <div class="admonition custom">
65 <p class="admonition-title">Did you know?</p>
66 <p>Another line here.</p>
67 </div>
69 [rST]: http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific-admonitions
71 By [Tiago Serafim](http://www.tiagoserafim.com/).
73 """
75 from __future__ import absolute_import
76 from __future__ import unicode_literals
77 from . import Extension
78 from ..blockprocessors import BlockProcessor
79 from ..util import etree
80 import re
83 class AdmonitionExtension(Extension):
84 """ Admonition extension for Python-Markdown. """
86 def extendMarkdown(self, md, md_globals):
87 """ Add Admonition to Markdown instance. """
88 md.registerExtension(self)
90 md.parser.blockprocessors.add('admonition',
91 AdmonitionProcessor(md.parser),
92 '_begin')
95 class AdmonitionProcessor(BlockProcessor):
97 CLASSNAME = 'admonition'
98 CLASSNAME_TITLE = 'admonition-title'
99 RE = re.compile(r'(?:^|\n)!!!\ ?([\w\-]+)(?:\ "(.*?)")?')
101 def test(self, parent, block):
102 sibling = self.lastChild(parent)
103 return self.RE.search(block) or \
104 (block.startswith(' ' * self.tab_length) and sibling and \
105 sibling.get('class', '').find(self.CLASSNAME) != -1)
107 def run(self, parent, blocks):
108 sibling = self.lastChild(parent)
109 block = blocks.pop(0)
110 m = self.RE.search(block)
112 if m:
113 block = block[m.end() + 1:] # removes the first line
115 block, theRest = self.detab(block)
117 if m:
118 klass, title = self.get_class_and_title(m)
119 div = etree.SubElement(parent, 'div')
120 div.set('class', '%s %s' % (self.CLASSNAME, klass))
121 if title:
122 p = etree.SubElement(div, 'p')
123 p.text = title
124 p.set('class', self.CLASSNAME_TITLE)
125 else:
126 div = sibling
128 self.parser.parseChunk(div, block)
130 if theRest:
131 # This block contained unindented line(s) after the first indented
132 # line. Insert these lines as the first block of the master blocks
133 # list for future processing.
134 blocks.insert(0, theRest)
136 def get_class_and_title(self, match):
137 klass, title = match.group(1).lower(), match.group(2)
138 if title is None:
139 # no title was provided, use the capitalized classname as title
140 # e.g.: `!!! note` will render `<p class="admonition-title">Note</p>`
141 title = klass.capitalize()
142 elif title == '':
143 # an explicit blank title should not be rendered
144 # e.g.: `!!! warning ""` will *not* render `p` with a title
145 title = None
146 return klass, title
149 def makeExtension(configs={}):
150 return AdmonitionExtension(configs=configs)