Mercurial > piecrust2
changeset 694:b917ae071994
formatting: Add a `hoedown` formatter.
The `hoedown` library is not yet in the dependency list however since I have
to figure out its availability on most platforms.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Wed, 23 Mar 2016 08:35:51 -0700 |
parents | d2a87365b85b |
children | 0c688063890f |
files | piecrust/formatting/hoedownformatter.py piecrust/plugins/builtin.py |
diffstat | 2 files changed, 118 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piecrust/formatting/hoedownformatter.py Wed Mar 23 08:35:51 2016 -0700 @@ -0,0 +1,116 @@ +import logging +import hoedown +from piecrust.formatting.base import Formatter + + +logger = logging.getLogger(__name__) + + +class HoedownFormatter(Formatter): + FORMAT_NAMES = ['hoedown'] + OUTPUT_FORMAT = 'html' + + def __init__(self): + super(HoedownFormatter, self).__init__() + self._formatter = None + + def render(self, format_name, txt): + assert format_name in self.FORMAT_NAMES + self._ensureInitialized() + return self._formatter.render(txt) + + def _ensureInitialized(self): + if self._formatter is not None: + return + + # Don't show warnings once for each worker when baking, so only + # show them for the first. If the variable is not set, we're not + # baking so do show them either way. + show_warnings = (self.app.config.get('baker/worker_id', 0) == 0) + + config = self.app.config.get('hoedown') + if config is None: + config = {} + elif not isinstance(config, dict): + raise Exception("The `hoedown` configuration setting must be " + "a dictionary.") + + extensions = config.get('extensions', []) + if isinstance(extensions, str): + extensions = [e.strip() for e in extensions.split(',')] + # Compatibility with PieCrust 1.x + if config.get('use_markdown_extra'): + extensions.append('extra') + + render_flags = config.get('render_flags') + if render_flags is None: + render_flags = [] + + # Translate standard Markdown formatter extensions to Hoedown + # extension/render flags to make it easier to use Hoedown as a drop-in + # replacement. + exts = 0 + rdrf = 0 + other = 0 + for n in extensions: + # Try an extension? + e = getattr(hoedown, 'EXT_' + n.upper(), None) + if e is not None: + exts |= e + continue + + # Try a render flag? + f = getattr(hoedown, 'HTML_' + n.upper(), None) + if f is not None: + rdrf |= f + + # Other flag? + f = getattr(hoedown, 'TABLE_' + n.upper(), None) + if f is not None: + other |= f + + # Try translating from a Markdown extension name. + t = ext_translate.get(n) + if t is None: + if show_warnings: + logger.warning("Unknown Hoedown Markdown extension or flag: " + "%s" % n) + continue + if not isinstance(t, list): + t = [t] + for i in t: + if i.startswith('EXT_'): + exts |= getattr(hoedown, i) + elif i.startswith('HTML_'): + rdrf |= getattr(hoedown, i) + elif show_warnings: + logger.warning("Unknown Hoedown Markdown extension or flag:" + "%s" % n) + if n == 'extra' and show_warnings: + # Special warning for the 'extra' extension. + logger.warning( + "The 'extra' extension doesn't have a full equivalent " + "in Hoedown Markdown. Only 'fenced_code', 'footnotes' and " + "'tables' extensions will be active. " + "To remove this warning, replace 'extra' with those 3 " + "specific extensions.") + + # Enable a few things by default. + exts |= hoedown.EXT_NO_INTRA_EMPHASIS + + renderer = hoedown.HtmlRenderer(flags=rdrf) + self._formatter = hoedown.Markdown( + renderer, extensions=(exts | other)) + + +ext_translate = { + 'fenced_code': 'EXT_FENCED_CODE', + 'footnotes': 'EXT_FOOTNOTES', + 'tables': 'EXT_TABLES', + 'nl2br': 'HTML_HARD_WRAP', + 'smarty': 'HTML_SMARTYPANTS', + 'smartypants': 'HTML_SMARTYPANTS', + 'toc': 'HTML_TOC', + 'extra': ['EXT_FENCED_CODE', 'EXT_FOOTNOTES', 'EXT_TABLES'] + } +
--- a/piecrust/plugins/builtin.py Wed Mar 23 01:53:57 2016 -0700 +++ b/piecrust/plugins/builtin.py Wed Mar 23 08:35:51 2016 -0700 @@ -17,6 +17,7 @@ from piecrust.commands.builtin.util import ( InitCommand, PurgeCommand, ImportCommand) from piecrust.data.provider import (IteratorDataProvider, BlogDataProvider) +from piecrust.formatting.hoedownformatter import HoedownFormatter from piecrust.formatting.markdownformatter import MarkdownFormatter from piecrust.formatting.textileformatter import TextileFormatter from piecrust.formatting.smartypantsformatter import SmartyPantsFormatter @@ -98,6 +99,7 @@ def getFormatters(self): return [ + HoedownFormatter(), MarkdownFormatter(), SmartyPantsFormatter(), TextileFormatter()]