import re
from markdown.util import etree, AtomicString
from markdown.inlinepatterns import Pattern
from markdown.preprocessors import Preprocessor
from markdown.extensions import Extension
Markdown preprocessor that matches all TODO and FIXME strings occurring at the beginning of the line or after the inline comment delimiter and highlights them in the documentation.
class Prep(Preprocessor):
matched_strings = ["TODO", "FIXME", "WARNING", "CAUTION"]
regex = re.compile("^\s*(" + "|".join(matched_strings) + ":?)(.*)", flags=re.I)
Intended markup for TODO strings. The type of the string is used as a class.
def template(self, match):
return "<span class={0:s}><strong>{1:s}</strong>{2:s}</span>"\
.format(match.group(1).lower(), match.group(1), match.group(2))
String matching is case insensitive
def run(self, lines):
return [self.regex.sub(self.template, line) for line in lines]
class LinesConnector(Extension):
def __init__(self, regex=r"(\S)\s*\\\s*\n\s*(\S)", sub=r"\1 \2", *args, **kwargs):
regex = re.compile(regex, flags=re.M)
Method ensures that there is exactly one space between 2 joined strings.
def run(self, lines):
return regex.sub(sub, "\n".join(lines)).split("\n")
def extendMarkdown(self, md, md_globals):
md.preprocessors.add('lines-connector', self.Prep, '_end')
Markdown preprocessor that prepares natural-style definition lists for native Markdown extension def_list
. It allows to write more compact and readable class field definitions.
class Prep(Preprocessor):
Searches for a line starting with a literal followed by a colon and multiple spaces:
some arbitrary parameter name : and its definition separated by `:\s\s+` `parameter name` might contain everything except a [colon](//en.wikipedia.org/wiki/Colon_(punctuation)) and be multiline : it still works
And turns it into:
:\s\s+
parameter name
might contain everything except a colon and be multiline def run(self, lines):
new_lines = []
for line in lines:
match = re.match(r'^(\s*)([^:]+):\s{2,}(.+)', line)
if match:
new_lines.append(match.group(1) + match.group(2))
new_lines.append(match.group(1) + ': ' + match.group(3))
new_lines.append('')
else:
new_lines.append(line)
return new_lines
def extendMarkdown(self, md, md_globals):
md.preprocessors.add('sane-def-list', SaneDefList.Prep(md), '_end')
Preprocessor used to parse PyDoc-style comments like :param name:
and format them.
class Prep(Preprocessor):
param lines
Documentation lines
return Lines of text with parsed PyDoc comments
def run(self, lines):
new_lines = []
for text in lines:
Regex that matches @param name
text = re.compile(
r'^(\s?)@(\w+)\s+(["\'\`].+["\'\`]|\S+)\s*', re.M
).sub(
r'\1<span class="pydoc pydoc-\2"><span>\2</span> <code>\3</code></span> ',
text)
Regex that matches @var
text = re.compile(
r'^(\s?)@(\w+)', re.M
).sub(
r'\1<span class="pydoc pydoc-\2"><span>\2</span></span>',
text)
Regex that matches :param name:
text = re.compile(
r'^(\s?):([^: ]+) +([^:]+):', re.M
).sub(
r'\1<span class="pydoc pydoc-\2"><span>\2</span> <code>\3</code></span>',
text)
Regex that matches single-word comments: :return:
text = re.compile(
r'^(\s?):([^: ]+):', re.M
).sub(
r'\1<span class="pydoc pydoc-\2"><span>\2</span></span>',
text)
new_lines.append(text)
There's already an inline pattern called autolink which handles http://www.google.com type links.
class AutoLinkExtension(Extension):
EXTRA_AUTOLINK_RE = r'(?<!"|>)((https?://|www)[-\w./#?%=&]+)'
class pattern(Pattern):
def handleMatch(self, m):
el = etree.Element('a')
if m.group(2).startswith('http'):
href = m.group(2)
else:
href = 'http://%s' % m.group(2)
el.set('href', href)
el.text = m.group(2)
return el
def extendMarkdown(self, md, md_globals):
md.inlinePatterns.add(
'extra_autolink',
AutoLinkExtension.pattern(self.EXTRA_AUTOLINK_RE, self),
'>autolink'
)
Adds support for displaying math formulas using MathJax.
Author: 2015, Dmitry Shachnev mitya57@gmail.com. Slightly customized by cryptonomicon314
class MathExtension(Extension):
def __init__(self, *args, **kwargs):
super(MathExtension, self).__init__(*args, **kwargs)
def extendMarkdown(self, md, md_globals):
def handle_match_inline(m):
node = etree.Element('script')
node.set('type', 'math/tex')
node.text = AtomicString(m.group(3))
return node
def handle_match(m):
node = etree.Element('script')
node.set('type', 'math/tex; mode=display')
if '\\begin' in m.group(2):
node.text = AtomicString(m.group(2) + m.group(4) + m.group(5))
else:
node.text = AtomicString(m.group(3))
return node
inlinemathpatterns = (
Display style math with \[...\]
Pattern(r'(?<!\\)(\\\[)(.+?)(\\\])'),
Pattern(r'(?<!\\)(\\begin{([a-z]+?\*?)})(.+?)(\\end{\3})')