Skip to content

Instantly share code, notes, and snippets.

@uhnomoli
Last active August 29, 2015 14:04
Show Gist options
  • Save uhnomoli/fa6e0acea46ace1d968b to your computer and use it in GitHub Desktop.
Save uhnomoli/fa6e0acea46ace1d968b to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
from copy import deepcopy
from operator import or_
import re
import hoep as h
from mynt.base import Parser as _Parser
from mynt.utils import escape
class _Renderer(h.Hoep):
def __init__(self, extensions = 0, render_flags = 0):
super(_Renderer, self).__init__(extensions, render_flags)
self._mj_tokens = []
self._toc_ids = {}
self._toc_patterns = (
(r'<[^<]+?>', ''),
(r'[^a-z0-9_.\s-]', ''),
(r'\s+', '-'),
(r'^[^a-z]+', ''),
(r'^$', 'section')
)
def block_code(self, text, language):
text = escape(text)
language = ' data-lang="{0}"'.format(language) if language else ''
return '<pre><code{0}>{1}</code></pre>'.format(language, text)
def header(self, text, level):
if self.render_flags & h.HTML_TOC:
identifier = text.lower()
for pattern, replace in self._toc_patterns:
identifier = re.sub(pattern, replace, identifier)
if identifier in self._toc_ids:
self._toc_ids[identifier] += 1
identifier = '{0}-{1}'.format(identifier, self._toc_ids[identifier])
else:
self._toc_ids[identifier] = 1
return '<h{0} id="{1}">{2}</h{0}>'.format(level, identifier, text)
else:
return '<h{0}>{1}</h{0}>'.format(level, text)
def preprocess(self, markdown):
del self._mj_tokens[:]
self._toc_ids.clear()
def mathjax(match):
i = len(self._mj_tokens)
self._mj_tokens.append(match.group(0))
return '{{mj_{0}}}'.format(i)
markdown = re.sub(r'(\${1,2}).+\1', mathjax, markdown)
return markdown
def postprocess(self, html):
for i, token in enumerate(self._mj_tokens):
html = html.replace('{{mj_{0}}}'.format(i), token)
class Parser(_Parser):
accepts = ('.md', '.markdown')
lookup = {
'extensions': {
'autolink': h.EXT_AUTOLINK,
'disable_indented_code': h.EXT_DISABLE_INDENTED_CODE,
'fenced_code': h.EXT_FENCED_CODE,
'footnotes': h.EXT_FOOTNOTES,
'highlight': h.EXT_HIGHLIGHT,
'lax_spacing': h.EXT_LAX_SPACING,
'no_intra_emphasis': h.EXT_NO_INTRA_EMPHASIS,
'quote': h.EXT_QUOTE,
'space_headers': h.EXT_SPACE_HEADERS,
'strikethrough': h.EXT_STRIKETHROUGH,
'superscript': h.EXT_SUPERSCRIPT,
'tables': h.EXT_TABLES,
'underline': h.EXT_UNDERLINE
},
'render_flags': {
'escape': h.HTML_ESCAPE,
'expand_tabs': h.HTML_EXPAND_TABS,
'hard_wrap': h.HTML_HARD_WRAP,
'safelink': h.HTML_SAFELINK,
'skip_html': h.HTML_SKIP_HTML,
'skip_images': h.HTML_SKIP_IMAGES,
'skip_links': h.HTML_SKIP_LINKS,
'skip_style': h.HTML_SKIP_STYLE,
'smartypants': h.HTML_SMARTYPANTS,
'toc': h.HTML_TOC,
'use_xhtml': h.HTML_USE_XHTML
}
}
defaults = {
'extensions': {
'autolink': True,
'fenced_code': True,
'footnotes': True,
'no_intra_emphasis': True,
'strikethrough': True,
'tables': True
},
'render_flags': {
'smartypants': True
}
}
def parse(self, markdown):
return self._md.render(markdown)
def setup(self):
self.flags = {}
self.config = deepcopy(self.defaults)
for k, v in self.options.iteritems():
self.config[k].update(v)
for group, options in self.config.iteritems():
flags = [self.lookup[group][k] for k, v in options.iteritems() if v]
self.flags[group] = reduce(or_, flags, 0)
self._md = _Renderer(**self.flags)
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
import re
import houdini as h
import misaka as m
from mynt.base import Parser as _Parser
class _Renderer(m.HtmlRenderer):
_mj_tokens = []
_toc_ids = {}
_toc_patterns = [
(r'<[^<]+?>', ''),
(r'[^a-z0-9_.\s-]', ''),
(r'\s+', '-'),
(r'^[^a-z]+', ''),
(r'^$', 'section')
]
def block_code(self, text, lang):
text = h.escape_html(text.encode('utf-8'), 1).decode('utf-8')
lang = ' data-lang="{0}"'.format(lang) if lang else ''
return '<pre><code{0}>{1}</code></pre>'.format(lang, text)
def header(self, text, level):
if self.flags & m.HTML_TOC:
identifier = text.lower()
for pattern, replace in self._toc_patterns:
identifier = re.sub(pattern, replace, identifier)
if identifier in self._toc_ids:
self._toc_ids[identifier] += 1
identifier = '{0}-{1}'.format(identifier, self._toc_ids[identifier])
else:
self._toc_ids[identifier] = 1
return '<h{0} id="{1}">{2}</h{0}>'.format(level, identifier, text)
else:
return '<h{0}>{1}</h{0}>'.format(level, text)
def setup(self):
super(_Renderer, self).setup()
self.sp = m.SmartyPants().postprocess
def preprocess(self, markdown):
del self._mj_tokens[:]
self._toc_ids = {}
def mathjax(match):
i = len(self._mj_tokens)
self._mj_tokens.append(match.group(0))
return '{{mj_{0}}}'.format(i)
markdown = re.sub(r'(\${1,2}).+\1', mathjax, markdown)
return markdown
def postprocess(self, html):
if self.flags & m.HTML_SMARTYPANTS:
html = self.sp(html)
for i, token in enumerate(self._mj_tokens):
html = html.replace('{{mj_{0}}}'.format(i), token)
return html
class Parser(_Parser):
lookup = {
'extensions': {
'autolink': m.EXT_AUTOLINK,
'fenced_code': m.EXT_FENCED_CODE,
'lax_html_blocks': m.EXT_LAX_HTML_BLOCKS,
'no_intra_emphasis': m.EXT_NO_INTRA_EMPHASIS,
'space_headers': m.EXT_SPACE_HEADERS,
'strikethrough': m.EXT_STRIKETHROUGH,
'superscript': m.EXT_SUPERSCRIPT,
'tables': m.EXT_TABLES
},
'render_flags': {
'expand_tabs': m.HTML_EXPAND_TABS,
'hard_wrap': m.HTML_HARD_WRAP,
'safelink': m.HTML_SAFELINK,
'skip_html': m.HTML_SKIP_HTML,
'skip_images': m.HTML_SKIP_IMAGES,
'skip_links': m.HTML_SKIP_LINKS,
'skip_style': m.HTML_SKIP_STYLE,
'smartypants': m.HTML_SMARTYPANTS,
'toc': m.HTML_TOC,
'toc_tree': m.HTML_TOC_TREE,
'use_xhtml': m.HTML_USE_XHTML
}
}
config = {
'extensions': {
'autolink': True,
'fenced_code': True,
'no_intra_emphasis': True,
'strikethrough': True
},
'render_flags': {
'hard_wrap': True,
'smartypants': True
}
}
flags = {
'extensions': 0,
'render_flags': 0
}
def parse(self, markdown):
return self._html.render(markdown)
def setup(self):
for k, v in self.options.iteritems():
self.config[k].update(v)
for group, options in self.config.iteritems():
for option, value in options.iteritems():
if value:
self.flags[group] |= self.lookup[group][option]
self._html = m.Markdown(_Renderer(self.flags['render_flags']), self.flags['extensions'])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment