Permalink
Browse files

initial commit

  • Loading branch information...
1 parent ffc1d3e commit e527b8ffcb7575c7edee3091d530d5faaaf3ce25 @stefantalpalaru stefantalpalaru committed Sep 14, 2010
View
@@ -0,0 +1,7 @@
+*.pyc
+*.pyo
+*.swp
+*.swo
+*.*~
+*.bak
+.DS_Store
View
@@ -0,0 +1,2 @@
+Stefan Talpalaru <stefan.talpalaru@od-eon.com>
+
View
674 LICENSE

Large diffs are not rendered by default.

Oops, something went wrong.
View
22 README
@@ -0,0 +1,22 @@
+django-pygments is a Django app that provides a template tag and 2 filters for doing syntax highlighting with Pygments ( http://pygments.org/ ).
+
+Dependencies:
+- pygments
+- lxml
+
+Installation:
+- add django_pygments to your project directory
+- if you want to see the integrated demo page, add a urls.py entry and copy/link the media files in the proper dir
+
+Usage:
+- enclose your code snippet in a pre tag with the non-standard "lang" attribute set to a supported language like this:
+ <pre lang="python">....</pre>
+- see the view and demo template for examples on how to use the "pygmentify" and "pygmentify_inline" filters (the later is rather useful for RSS feeds) or the "pygment" tag
+
+Notes:
+- the custom HTML formatter class displays each line as an ordered list element, thus implementing line numbering without interfering with copy/pasting
+- to see a list of supported languages, look at the "lexer_names" variable in utils.py
+
+
+For technical support use the github bugtracker or contact us at developers@od-eon.com
+
No changes.
@@ -0,0 +1,20 @@
+#content {
+ width: 960px;
+ margin-left: auto;
+ margin-right: auto;
+ background-color: #EEE;
+ padding: 10px;
+}
+
+div.highlight {
+ margin: 0px 20px;
+}
+div.highlight ol{
+ margin-left: 40px;
+}
+div.highlight li{
+ color: #831D0A;
+}
+div.highlight li div.line{
+ color: #333;
+}
@@ -0,0 +1,64 @@
+.highlight .hll { background-color: #ffffcc }
+.highlight { background: #f8f8f8; overflow: auto; }
+.highlight .c { color: #408080; font-style: italic } /* Comment */
+.highlight .err { border: 1px solid #FF0000 } /* Error */
+.highlight .k { color: #008000; font-weight: bold } /* Keyword */
+.highlight .o { color: #666666 } /* Operator */
+.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
+.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
+.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
+.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
+.highlight .gd { color: #A00000 } /* Generic.Deleted */
+.highlight .ge { font-style: italic } /* Generic.Emph */
+.highlight .gr { color: #FF0000 } /* Generic.Error */
+.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.highlight .gi { color: #00A000 } /* Generic.Inserted */
+.highlight .go { color: #808080 } /* Generic.Output */
+.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+.highlight .gs { font-weight: bold } /* Generic.Strong */
+.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.highlight .gt { color: #0040D0 } /* Generic.Traceback */
+.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
+.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
+.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
+.highlight .kp { color: #008000 } /* Keyword.Pseudo */
+.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
+.highlight .kt { color: #B00040 } /* Keyword.Type */
+.highlight .m { color: #666666 } /* Literal.Number */
+.highlight .s { color: #BA2121 } /* Literal.String */
+.highlight .na { color: #7D9029 } /* Name.Attribute */
+.highlight .nb { color: #008000 } /* Name.Builtin */
+.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
+.highlight .no { color: #880000 } /* Name.Constant */
+.highlight .nd { color: #AA22FF } /* Name.Decorator */
+.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
+.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
+.highlight .nf { color: #0000FF } /* Name.Function */
+.highlight .nl { color: #A0A000 } /* Name.Label */
+.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
+.highlight .nv { color: #19177C } /* Name.Variable */
+.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+.highlight .mf { color: #666666 } /* Literal.Number.Float */
+.highlight .mh { color: #666666 } /* Literal.Number.Hex */
+.highlight .mi { color: #666666 } /* Literal.Number.Integer */
+.highlight .mo { color: #666666 } /* Literal.Number.Oct */
+.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
+.highlight .sc { color: #BA2121 } /* Literal.String.Char */
+.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
+.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
+.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
+.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
+.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
+.highlight .sx { color: #008000 } /* Literal.String.Other */
+.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
+.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
+.highlight .ss { color: #19177C } /* Literal.String.Symbol */
+.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
+.highlight .vc { color: #19177C } /* Name.Variable.Class */
+.highlight .vg { color: #19177C } /* Name.Variable.Global */
+.highlight .vi { color: #19177C } /* Name.Variable.Instance */
+.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
+.highlight .lineno { color: #000000; background-color: #dddddd; }
+
@@ -0,0 +1,2 @@
+#from django.db import models
+
@@ -0,0 +1,54 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+{% load pygmentify %}
+
+<html xmlns="http://www.w3.org/1999/xhtml" dir="{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}" xml:lang="{{ LANGUAGE_CODE }}" lang="{{ LANGUAGE_CODE }}" xmlns:fb="http://www.facebook.com/2008/fbml">
+ <head>
+ <title>django-pygments demo</title>
+ <link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}app/django_pygments/css/pygments_default.css" />
+ <link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}app/django_pygments/css/demo.css" />
+ </head>
+
+ <body>
+ <div id="content">
+ <h1>django-pygments demo</h1>
+ <br />
+ <h3>the "pygmentify" filter</h3>
+ {{ snippet|pygmentify }}
+ <br />
+ <h3>the "pygmentify_inline" filter</h3>
+ {{ snippet|pygmentify_inline }}
+ <br />
+ <h3>the "pygment" tag</h3>
+ {% pygment %}
+ <pre lang="bash">
+stefan$ ./manage.py runserver_cp
+Validating models...
+0 errors found
+starting server with options {'ssl_certificate': None, 'workdir': None, 'verbose': 1, 'server_name': 'localhost', 'host': 'localhost', 'daemonize': 0, 'threads': 10, 'pidfile': None, 'shutdown_timeout': 60, 'ssl_private_key': None, 'server_group': 'www-data', 'port': 8000, 'server_user': 'www-data', 'request_queue_size': 5}
+
+Django version 1.2.1 SVN-13353, using settings 'proj.settings'
+Development server is running at http://localhost:8000/
+Quit the server with &lt;CTRL&gt;+C.
+[01/Aug/2010 17:34:39] "GET /labs/ HTTP/1.1" 200
+[01/Aug/2010 17:34:39] "GET /media/css/style.css HTTP/1.1" 304
+[01/Aug/2010 17:34:39] "GET /media/css/pretty.photo.css HTTP/1.1" 304
+[01/Aug/2010 17:34:39] "GET /media/js/jquery.js HTTP/1.1" 304
+[01/Aug/2010 17:34:39] "GET /media/app/labs/css/labs.css HTTP/1.1" 200
+[01/Aug/2010 17:34:39] "GET /media/css/main.css HTTP/1.1" 304
+[01/Aug/2010 17:34:39] "GET /media/js/main.js HTTP/1.1" 304
+[01/Aug/2010 17:34:39] "GET /media/js/custom.js HTTP/1.1" 304
+ </pre>
+ <br />
+ {{ snippet|safe }}
+ {% endpygment %}
+ </div>
+ </body>
+
+</html>
+
+{% comment %}
+vim:filetype=htmldjango
+{% endcomment %}
+
No changes.
@@ -0,0 +1,49 @@
+from django import template
+from django.template.defaultfilters import stringfilter
+from django_pygments.utils import pygmentify_text
+from django.utils.safestring import mark_safe
+
+register = template.Library()
+
+# truncate after a certain number of characters
+@register.filter
+@stringfilter
+def pygmentify(value):
+ try:
+ res = pygmentify_text(value)
+ except Exception, e:
+ print e
+ print 'value="%s"' % value
+ res = value
+ return mark_safe(res)
+
+@register.filter
+@stringfilter
+def pygmentify_inline(value):
+ try:
+ res = pygmentify_text(value, noclasses=True)
+ except Exception, e:
+ print e
+ print 'value="%s"' % value
+ res = value
+ return mark_safe(res)
+
+class PygmentifyNode(template.Node):
+ def __init__(self, nodelist):
+ self.nodelist = nodelist
+ def render(self, context):
+ output = self.nodelist.render(context)
+ try:
+ res = pygmentify_text(output)
+ except Exception, e:
+ print e
+ print 'value="%s"' % value
+ res = output
+ return mark_safe(res)
+
+@register.tag
+def pygment(parser, token):
+ nodelist = parser.parse(('endpygment',))
+ parser.delete_first_token()
+ return PygmentifyNode(nodelist)
+
View
@@ -0,0 +1,6 @@
+from django.conf.urls.defaults import patterns, url
+
+urlpatterns = patterns(
+ 'django_pygments.views',
+ (r'^demo/$', 'demo'),
+)
View
@@ -0,0 +1,44 @@
+import warnings
+warnings.simplefilter('ignore')
+from pygments.lexers import LEXERS, get_lexer_by_name
+warnings.resetwarnings()
+from pygments import highlight
+from pygments.formatters import HtmlFormatter
+from lxml import html
+
+class ListHtmlFormatter(HtmlFormatter):
+ def wrap(self, source, outfile):
+ return self._wrap_div(self._wrap_pre(self._wrap_list(source)))
+
+ def _wrap_list(self, source):
+ yield 0, '<ol>'
+ for i, t in source:
+ if i == 1:
+ # it's a line of formatted code
+ t = '<li><div class="line">%s</div></li>' % t
+ yield i, t
+ yield 0, '</ol>'
+
+def pygmentify_text(text, **kwargs):
+ default_lang = 'text'
+
+ # a tuple of known lexer names
+ lexer_names = reduce(lambda a,b: a + b[2], LEXERS.itervalues(), ())
+
+ # custom formatter
+ formatter = ListHtmlFormatter(encoding='utf-8', **kwargs)
+
+ html_node = html.fragment_fromstring(text, create_parent='div')
+ new_html_node = html_node
+ for code_node in html_node.findall('pre'):
+ if not code_node.text:
+ continue
+ lang = code_node.attrib.get('lang', default_lang)
+ if lang not in lexer_names:
+ lang = default_lang
+ lexer = get_lexer_by_name(lang, stripall=True)
+ new_code_node = html.fragment_fromstring(highlight(code_node.text, lexer, formatter))
+ new_html_node.replace(code_node, new_code_node)
+
+ return html.tostring(new_html_node, encoding=unicode, method='xml')[5:-6] # need to strip the enclosing div
+
View
@@ -0,0 +1,24 @@
+from django.shortcuts import render_to_response, get_object_or_404
+from django.template import RequestContext
+from django.utils.html import escape
+
+
+def demo(request):
+ raw_snippet="""
+class ListHtmlFormatter(HtmlFormatter):
+ def wrap(self, source, outfile):
+ return self._wrap_div(self._wrap_pre(self._wrap_list(source)))
+
+ def _wrap_list(self, source):
+ yield 0, '<ol>'
+ for i, t in source:
+ if i == 1:
+ # it's a line of formatted code
+ t = '<li><div class="line">%s</div></li>' % t
+ yield i, t
+ yield 0, '</ol>'
+ # a very long comment that keeps on going and going and going and going and going and going and going and going and going and going and going and going
+ """
+ snippet = '<pre lang="python">' + escape(raw_snippet) + '</pre>'
+ return render_to_response('django_pygments/demo.html', locals(), context_instance = RequestContext(request))
+

0 comments on commit e527b8f

Please sign in to comment.