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'])
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/version.txt	Tue Feb 13 13:37:39 2018 -0800
@@ -0,0 +1,2 @@
+0.1.0
+