Mercurial > piecrust-hoedown
changeset 0:8e0f125ef135 default tip
Initial commit.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 13 Feb 2018 13:37:39 -0800 |
parents | |
children | |
files | LICENSE.rst MANIFEST.in README.rst piecrust_hoedown.py requirements.txt setup.py version.txt |
diffstat | 7 files changed, 248 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LICENSE.rst Tue Feb 13 13:37:39 2018 -0800 @@ -0,0 +1,14 @@ +Copyright 2011 Ludovic Chabant + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MANIFEST.in Tue Feb 13 13:37:39 2018 -0800 @@ -0,0 +1,2 @@ +include README.rst LICENSE.rst +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.rst Tue Feb 13 13:37:39 2018 -0800 @@ -0,0 +1,43 @@ + +This plugin for `PieCrust`_ lets you use `Hoedown Markdown`_ via `Misaka`_ for +faster Markdown processing. It's much faster than the default pure Python (but +more universal) Markdown formatter that comes by default with PieCrust. + +To install the plugin:: + + pip install piecrust-hoedown + +Then enable it in your website configuration:: + + site: + plugins: [hoedown] + +You can specifically use the Hoedown formatter on a per-page basis by adding +``format: hoedown`` in the page's configuration header, but you might want to +just make it the default formatter for the whole website:: + + site: + default_format: hoedown + auto_formats: + md: hoedown + +The Hoedown formatter should be mostly compatible with the default Markdown +formatter, in the sense that making it the default formatter as specified above +should just work, and would make the website bake faster. However, if you were +using Markdown Extensions, there may or may not be any equivalent in Hoedown. +In this case, your best bet is to replace ``markdown`` with ``hoedown`` when +declaring the extensions, and see if there's an error about an extension not +existing. For instance:: + + site: + default_format: hoedown + hoedown: + extensions: [fenced_code, footnotes, smarty] + +The list of `extensions`_ is available on the Misaka documentation. Any +extension with a dash can also be written with an underscore. + +.. _piecrust: http://bolt80.com/piecrust/ +.. _hoedown markdown: https://github.com/hoedown/hoedown +.. _misaka: http://misaka.61924.nl/ +.. _extensions: http://misaka.61924.nl/#extensions
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piecrust_hoedown.py Tue Feb 13 13:37:39 2018 -0800 @@ -0,0 +1,146 @@ +import logging +from piecrust.plugins.base import PieCrustPlugin +from piecrust.formatting.base import Formatter + + +logger = logging.getLogger(__name__) + + +class HoedownPlugin(PieCrustPlugin): + name = 'Hoedown' + + def getFormatters(self): + return [ + HoedownFormatter()] + + +__piecrust_plugin__ = HoedownPlugin + + +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(txt) + + def _ensureInitialized(self): + if self._formatter is not None: + return + + import misaka + + # 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 = self.app.config.get('markdown') + 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 + use_smartypants = False + for n in extensions: + # Special case for Smartypants. + if n.lower() in ['smarty', 'smartypants']: + use_smartypants = True + continue + + # Try an extension? + e = getattr(misaka, 'EXT_' + n.upper(), None) + if e is not None: + exts |= e + continue + + # Try a render flag? + f = getattr(misaka, 'HTML_' + n.upper(), None) + if f is not None: + rdrf |= f + + # Other flag? + f = getattr(misaka, '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(misaka, i) + elif i.startswith('HTML_'): + rdrf |= getattr(misaka, 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 |= misaka.EXT_NO_INTRA_EMPHASIS + + renderer = misaka.HtmlRenderer(flags=rdrf) + self._formatter = misaka.Markdown(renderer, extensions=(exts | other)) + + if use_smartypants: + self._formatter = _SmartypantsFormatter(self._formatter, + misaka.smartypants) + + +ext_translate = { + 'fenced_code': 'EXT_FENCED_CODE', + 'footnotes': 'EXT_FOOTNOTES', + 'tables': 'EXT_TABLES', + 'nl2br': 'HTML_HARD_WRAP', + 'toc': 'HTML_TOC', + 'extra': ['EXT_FENCED_CODE', 'EXT_FOOTNOTES', 'EXT_TABLES'] + } + + +class _SmartypantsFormatter: + def __init__(self, formatter, smartier): + self._fmt = formatter + self._sp = smartier + + def __call__(self, txt): + return self._sp(self._fmt(txt))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/requirements.txt Tue Feb 13 13:37:39 2018 -0800 @@ -0,0 +1,3 @@ +PieCrust>=2.0.0 +misaka>=2.1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup.py Tue Feb 13 13:37:39 2018 -0800 @@ -0,0 +1,38 @@ +import os +from setuptools import setup + + +root_dir = os.path.dirname(__file__) +with open(os.path.join(root_dir, 'version.txt'), 'r') as fp: + version = fp.read().strip() + +with open(os.path.join(root_dir, 'README.rst'), 'r') as fp: + description = fp.read() + + +setup(name='PieCrust-Hoedown', + version=version, + url='http://bolt80.com/piecrust', + license='Apache2', + author='Ludovic Chabant', + author_email='ludovic@chabant.com', + description=('Hoedown Markdown formatter for PieCrust ' + 'via Misaka'), + long_description=description, + py_modules=['piecrust_hoedown'], + zip_safe=False, + install_requires=[ + 'PieCrust>=2.0.0', + 'misaka>=2.1.0'], + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: Apache Software License', + 'Natural Language :: English', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: POSIX :: Linux', + 'Operating System :: Microsoft :: Windows', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3']) +