From 2e866d0a3770a94992564c624e1d4f718991bb10 Mon Sep 17 00:00:00 2001 From: Lakshmi Vyasarajan Date: Wed, 9 Nov 2011 23:36:45 +0530 Subject: [PATCH] Issue #82: Added sourcecode directive to restructured text --- CHANGELOG.rst | 7 ++- LICENSE | 2 +- README.rst | 2 +- hyde/ext/templates/jinja.py | 14 +++-- hyde/lib/__init__.py | 0 hyde/lib/pygments/__init__.py | 0 hyde/lib/pygments/rst_directive.py | 82 ++++++++++++++++++++++++++++++ hyde/tests/test_jinja2template.py | 35 +++++++++++++ hyde/version.py | 2 +- 9 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 hyde/lib/__init__.py create mode 100644 hyde/lib/pygments/__init__.py create mode 100644 hyde/lib/pygments/rst_directive.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e7d69ad..59d90ea 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,9 @@ +Version 0.8.4c20 +============================================================ + +* Added test for codehilite markdown extension (Issue #82) +* Added rst_directive.py from the pygments repository (Issue #82) + Version 0.8.4c19 ============================================================ @@ -9,7 +15,6 @@ Version 0.8.4c18 * Added support for default publisher (Issue #83) - Version 0.8.4c17 ============================================================ diff --git a/LICENSE b/LICENSE index 1cad62e..c142337 100644 --- a/LICENSE +++ b/LICENSE @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file +THE SOFTWARE. diff --git a/README.rst b/README.rst index 89045a5..12623e3 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -Version 0.8.4c19 +Version 0.8.4c20 A brand new **hyde** ==================== diff --git a/hyde/ext/templates/jinja.py b/hyde/ext/templates/jinja.py index 149317e..2c8f23c 100644 --- a/hyde/ext/templates/jinja.py +++ b/hyde/ext/templates/jinja.py @@ -125,7 +125,7 @@ def markdown(env, value): import markdown as md except ImportError: logger.error(u"Cannot load the markdown library.") - raise TemplateError("Cannot load the markdown library") + raise TemplateError(u"Cannot load the markdown library") output = value d = {} if hasattr(env.config, 'markdown'): @@ -147,8 +147,16 @@ def restructuredtext(env, value): try: from docutils.core import publish_parts except ImportError: - print u"Requires docutils library to use restructuredtext tag." - raise + logger.error(u"Cannot load the docutils library.") + raise TemplateError(u"Cannot load the docutils library.") + + highlight_source = False + if hasattr(env.config, 'restructuredtext'): + highlight_source = getattr(env.config.restructuredtext, 'highlight_source', False) + + if highlight_source: + import hyde.lib.pygments.rst_directive + parts = publish_parts(source=value, writer_name="html") return parts['html_body'] diff --git a/hyde/lib/__init__.py b/hyde/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hyde/lib/pygments/__init__.py b/hyde/lib/pygments/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hyde/lib/pygments/rst_directive.py b/hyde/lib/pygments/rst_directive.py new file mode 100644 index 0000000..973398a --- /dev/null +++ b/hyde/lib/pygments/rst_directive.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +""" + The Pygments reStructuredText directive + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + This fragment is a Docutils_ 0.5 directive that renders source code + (to HTML only, currently) via Pygments. + + To use it, adjust the options below and copy the code into a module + that you import on initialization. The code then automatically + registers a ``sourcecode`` directive that you can use instead of + normal code blocks like this:: + + .. sourcecode:: python + + My code goes here. + + If you want to have different code styles, e.g. one with line numbers + and one without, add formatters with their names in the VARIANTS dict + below. You can invoke them instead of the DEFAULT one by using a + directive option:: + + .. sourcecode:: python + :linenos: + + My code goes here. + + Look at the `directive documentation`_ to get all the gory details. + + .. _Docutils: http://docutils.sf.net/ + .. _directive documentation: + http://docutils.sourceforge.net/docs/howto/rst-directives.html + + :copyright: Copyright 2006-2011 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +# Options +# ~~~~~~~ + +# Set to True if you want inline CSS styles instead of classes +INLINESTYLES = False + +from pygments.formatters import HtmlFormatter + +# The default formatter +DEFAULT = HtmlFormatter(noclasses=INLINESTYLES) + +# Add name -> formatter pairs for every variant you want to use +VARIANTS = { + 'linenos': HtmlFormatter(noclasses=INLINESTYLES, linenos=True), +} + + +from docutils import nodes +from docutils.parsers.rst import directives, Directive + +from pygments import highlight +from pygments.lexers import get_lexer_by_name, TextLexer + +class Pygments(Directive): + """ Source code syntax hightlighting. + """ + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = True + option_spec = dict([(key, directives.flag) for key in VARIANTS]) + has_content = True + + def run(self): + self.assert_has_content() + try: + lexer = get_lexer_by_name(self.arguments[0]) + except ValueError: + # no lexer found - use the text one instead of an exception + lexer = TextLexer() + # take an arbitrary option if more than one is given + formatter = self.options and VARIANTS[self.options.keys()[0]] or DEFAULT + parsed = highlight(u'\n'.join(self.content), lexer, formatter) + return [nodes.raw('', parsed, format='html')] + +directives.register_directive('sourcecode', Pygments) diff --git a/hyde/tests/test_jinja2template.py b/hyde/tests/test_jinja2template.py index efdb0bb..7a4a49e 100644 --- a/hyde/tests/test_jinja2template.py +++ b/hyde/tests/test_jinja2template.py @@ -193,6 +193,41 @@ Hello

Hello

""", html +def test_restructuredtext_with_sourcecode(): + source = """ +{% restructuredtext %} +Code +==== +.. sourcecode:: python + + def add(a, b): + return a + b + +See `Example`_ + +.. _Example: example.html + +{% endrestructuredtext %} +""" + + expected = """ +
+

Code

+
def add(a, b):
+    return a + b
+
+

See Example

+
+""" + t = Jinja2Template(JINJA2.path) + s = Site(JINJA2.path) + c = Config(JINJA2.path, config_dict=dict( + restructuredtext=dict(highlight_source=True))) + s.config = c + t.configure(s) + html = t.render(source, {}).strip() + assert html.strip() == expected.strip() + def test_markdown_with_extensions(): source = """ {%markdown%} diff --git a/hyde/version.py b/hyde/version.py index e592468..242dfd7 100644 --- a/hyde/version.py +++ b/hyde/version.py @@ -3,4 +3,4 @@ Handles hyde version TODO: Use fabric like versioning scheme """ -__version__ = '0.8.4c19' +__version__ = '0.8.4c20'