diff --git a/previewer_code/MANIFEST.in b/previewer_code/MANIFEST.in new file mode 100644 index 0000000..93a0256 --- /dev/null +++ b/previewer_code/MANIFEST.in @@ -0,0 +1 @@ +graft indico_previewer_code/templates diff --git a/previewer_code/indico_previewer_code/__init__.py b/previewer_code/indico_previewer_code/__init__.py new file mode 100644 index 0000000..fa5246d --- /dev/null +++ b/previewer_code/indico_previewer_code/__init__.py @@ -0,0 +1,21 @@ +# This file is part of Indico. +# Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN). +# +# Indico is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# Indico is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Indico; if not, see . + +"""Syntax highlighting for common programming languages and related formats.""" + +from .plugin import CodePreviewerPlugin + +__all__ = ('CodePreviewerPlugin',) diff --git a/previewer_code/indico_previewer_code/plugin.py b/previewer_code/indico_previewer_code/plugin.py new file mode 100644 index 0000000..46e57a7 --- /dev/null +++ b/previewer_code/indico_previewer_code/plugin.py @@ -0,0 +1,84 @@ +# This file is part of Indico. +# Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN). +# +# Indico is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# Indico is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Indico; if not, see . + +from __future__ import unicode_literals + +import mimetypes + +from flask import render_template +from pygments import highlight +from pygments.lexers import get_lexer_for_mimetype, CppLexer, PhpLexer, JavaLexer, RubyLexer +from pygments.formatters import HtmlFormatter + +from indico.core import signals +from indico.core.plugins import IndicoPlugin +from indico.modules.attachments.preview import Previewer + + +def register_custom_mimetypes(): + mimetypes.add_type(b'text/x-csharp', b'.cs') + + +register_custom_mimetypes() + + +class PygmentsPreviewer(Previewer): + # All supported MIME types + MIMETYPES = ('text/css', 'text/x-python', 'text/x-ruby-script', 'text/x-java-source', 'text/x-c', + 'application/javascript', 'text/x-c', 'text/x-fortran', 'text/x-csharp', 'text/php', + 'text/x-php') + + # Python's mimetypes lib and Pygments do not quite agree on some MIME types + CUSTOM_LEXERS = { + 'text/x-c': CppLexer(), + 'text/x-java-source': JavaLexer(), + 'text/x-ruby-script': RubyLexer(), + 'text/php': PhpLexer() + } + + @classmethod + def can_preview(cls, attachment_file): + return attachment_file.content_type in cls.MIMETYPES + + @classmethod + def generate_content(cls, attachment): + mime_type = attachment.file.content_type + + lexer = cls.CUSTOM_LEXERS.get(mime_type) + if lexer is None: + lexer = get_lexer_for_mimetype(mime_type) + + with attachment.file.open() as f: + html_formatter = HtmlFormatter(style='tango', linenos='inline', prestyles='mono') + html_code = highlight(f.read(), lexer, html_formatter) + + css_code = html_formatter.get_style_defs('.highlight') + + return render_template('previewer_code:pygments_preview.html', attachment=attachment, + html_code=html_code, css_code=css_code) + + +class CodePreviewerPlugin(IndicoPlugin): + """Syntax highlighter (Pygments)""" + + configurable = False + + def init(self): + super(CodePreviewerPlugin, self).init() + self.connect(signals.attachments.get_file_previewers, self._get_file_previewers) + + def _get_file_previewers(self, sender, **kwargs): + yield PygmentsPreviewer diff --git a/previewer_code/indico_previewer_code/templates/pygments_preview.html b/previewer_code/indico_previewer_code/templates/pygments_preview.html new file mode 100644 index 0000000..735ba1d --- /dev/null +++ b/previewer_code/indico_previewer_code/templates/pygments_preview.html @@ -0,0 +1,18 @@ + + +
+    {{ html_code | safe }}
+
diff --git a/previewer_code/setup.py b/previewer_code/setup.py new file mode 100644 index 0000000..5226be4 --- /dev/null +++ b/previewer_code/setup.py @@ -0,0 +1,38 @@ +# This file is part of Indico. +# Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN). +# +# Indico is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# Indico is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Indico; if not, see . + +from __future__ import unicode_literals + +from setuptools import setup, find_packages + + +setup( + name='indico_previewer_code', + version='0.1', + url='https://github.com/indico/indico-plugins', + license='https://www.gnu.org/licenses/gpl-3.0.txt', + author='Indico Team', + author_email='indico-team@cern.ch', + packages=find_packages(), + zip_safe=False, + include_package_data=True, + platforms='any', + install_requires=[ + 'indico>=1.9.4', + 'pygments' + ], + entry_points={'indico.plugins': {'previewer_code = indico_previewer_code:CodePreviewerPlugin'}} +)