From de9ca906d3d1ebcf2eb8fcb1831a586feffaea83 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Mon, 5 Feb 2018 15:32:57 +1100 Subject: sb: RSB backport changes to support mailing list posting of builds. This requires moving to markdown for HTML and so asciidoc can be removed. Close 3289 --- .../sb/markdown/extensions/fenced_code.py | 113 +++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 source-builder/sb/markdown/extensions/fenced_code.py (limited to 'source-builder/sb/markdown/extensions/fenced_code.py') diff --git a/source-builder/sb/markdown/extensions/fenced_code.py b/source-builder/sb/markdown/extensions/fenced_code.py new file mode 100644 index 0000000..277bac4 --- /dev/null +++ b/source-builder/sb/markdown/extensions/fenced_code.py @@ -0,0 +1,113 @@ +""" +Fenced Code Extension for Python Markdown +========================================= + +This extension adds Fenced Code Blocks to Python-Markdown. + +See +for documentation. + +Original code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/). + + +All changes Copyright 2008-2014 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 ..preprocessors import Preprocessor +from .codehilite import CodeHilite, CodeHiliteExtension, parse_hl_lines +import re + + +class FencedCodeExtension(Extension): + + def extendMarkdown(self, md, md_globals): + """ Add FencedBlockPreprocessor to the Markdown instance. """ + md.registerExtension(self) + + md.preprocessors.add('fenced_code_block', + FencedBlockPreprocessor(md), + ">normalize_whitespace") + + +class FencedBlockPreprocessor(Preprocessor): + FENCED_BLOCK_RE = re.compile(r''' +(?P^(?:~{3,}|`{3,}))[ ]* # Opening ``` or ~~~ +(\{?\.?(?P[\w#.+-]*))?[ ]* # Optional {, and lang +# Optional highlight lines, single- or double-quote-delimited +(hl_lines=(?P"|')(?P.*?)(?P=quot))?[ ]* +}?[ ]*\n # Optional closing } +(?P.*?)(?<=\n) +(?P=fence)[ ]*$''', re.MULTILINE | re.DOTALL | re.VERBOSE) + CODE_WRAP = '
%s
' + LANG_TAG = ' class="%s"' + + def __init__(self, md): + super(FencedBlockPreprocessor, self).__init__(md) + + self.checked_for_codehilite = False + self.codehilite_conf = {} + + def run(self, lines): + """ Match and store Fenced Code Blocks in the HtmlStash. """ + + # Check for code hilite extension + if not self.checked_for_codehilite: + for ext in self.markdown.registeredExtensions: + if isinstance(ext, CodeHiliteExtension): + self.codehilite_conf = ext.config + break + + self.checked_for_codehilite = True + + text = "\n".join(lines) + while 1: + m = self.FENCED_BLOCK_RE.search(text) + if m: + lang = '' + if m.group('lang'): + lang = self.LANG_TAG % m.group('lang') + + # If config is not empty, then the codehighlite extension + # is enabled, so we call it to highlight the code + if self.codehilite_conf: + highliter = CodeHilite( + m.group('code'), + linenums=self.codehilite_conf['linenums'][0], + guess_lang=self.codehilite_conf['guess_lang'][0], + css_class=self.codehilite_conf['css_class'][0], + style=self.codehilite_conf['pygments_style'][0], + use_pygments=self.codehilite_conf['use_pygments'][0], + lang=(m.group('lang') or None), + noclasses=self.codehilite_conf['noclasses'][0], + hl_lines=parse_hl_lines(m.group('hl_lines')) + ) + + code = highliter.hilite() + else: + code = self.CODE_WRAP % (lang, + self._escape(m.group('code'))) + + placeholder = self.markdown.htmlStash.store(code, safe=True) + text = '%s\n%s\n%s' % (text[:m.start()], + placeholder, + text[m.end():]) + else: + break + return text.split("\n") + + def _escape(self, txt): + """ basic html escaping """ + txt = txt.replace('&', '&') + txt = txt.replace('<', '<') + txt = txt.replace('>', '>') + txt = txt.replace('"', '"') + return txt + + +def makeExtension(*args, **kwargs): + return FencedCodeExtension(*args, **kwargs) -- cgit v1.2.3