From 176592955580263b6613ed329fd3b9af9eabbbb4 Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Wed, 2 Oct 2013 21:49:55 +0200 Subject: [PATCH] Added Code Chunks support Currently with inline style sheets. That will definitely change soon. --- blog/models.py | 16 ++++ blog/static/css/code.css | 46 ++++++++++ blog/templates/blog/code-chunk.html | 15 ++++ blog/templatetags/__init__.py | 0 blog/templatetags/code_chunks.py | 36 ++++++++ blog/urls.py | 1 + blog/views.py | 6 +- gergelypolonkaiweb/solarized_dark.py | 91 ++++++++++++++++++++ gergelypolonkaiweb/templates/front_base.html | 1 + 9 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 blog/static/css/code.css create mode 100644 blog/templates/blog/code-chunk.html create mode 100644 blog/templatetags/__init__.py create mode 100644 blog/templatetags/code_chunks.py create mode 100644 gergelypolonkaiweb/solarized_dark.py diff --git a/blog/models.py b/blog/models.py index 5ff1692..346fa7e 100644 --- a/blog/models.py +++ b/blog/models.py @@ -1,5 +1,6 @@ from django.db import models from django.contrib.auth.models import User +from django.template.defaultfilters import slugify from taggit.managers import TaggableManager class Post(models.Model): @@ -19,3 +20,18 @@ class Post(models.Model): self.slug = slugify(self.title) super(Post, self).save(*args, **kwargs) + +class CodeChunk(models.Model): + language = models.CharField(max_length = 20) + created_at = models.DateTimeField(auto_now_add=True) + title = models.CharField(max_length = 100) + slug = models.SlugField(editable = False, max_length = 100) + description = models.TextField(blank=True) + content = models.TextField() + + def save(self, *args, **kwargs): + if not self.id: + self.slug = slugify(self.title) + + super(CodeChunk, self).save(*args, **kwargs) + diff --git a/blog/static/css/code.css b/blog/static/css/code.css new file mode 100644 index 0000000..1418da0 --- /dev/null +++ b/blog/static/css/code.css @@ -0,0 +1,46 @@ +/* + Document : code + Created on : 2012.09.04., 10:05:47 + Author : polonkai.gergely + Description: + Purpose of the stylesheet follows. +*/ + +.code-chunk { + background-color: #b5b5b5; + padding: 10px; +} + +.code-chunk .code-title { + text-indent: 0 !important; + font-size: 120%; + font-weight: bold; +} + +.code-chunk .code-description { + border: 1px solid #333; + background-color: #d9d9d9; + padding: 3px; + text-indent: 0 !important; + margin: .5em 0 0 0 !important; + font-size: 75%; + color: #444; +} + +.code-chunk .code { + font-family: monospace; + background-color: #002b36; + padding: 5px; + height: 300px; + overflow: auto; +} + +.code-chunk .code * { + font-family: monospace; +} + +.code-chunk .code ol { + background-color: #002b36; + color: #586e75; +} + diff --git a/blog/templates/blog/code-chunk.html b/blog/templates/blog/code-chunk.html new file mode 100644 index 0000000..acae004 --- /dev/null +++ b/blog/templates/blog/code-chunk.html @@ -0,0 +1,15 @@ +{% extends 'front_base.html' %} + +{% load code_chunks %} + +{% block content %} +
+

{{ codechunk.title }}

+ {{ codechunk.content|syhilite:codechunk.language }} + {% if codechunk.description %} +
+ {{ codechunk.description|safe }} +
+ {% endif %} +
+{% endblock %} diff --git a/blog/templatetags/__init__.py b/blog/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blog/templatetags/code_chunks.py b/blog/templatetags/code_chunks.py new file mode 100644 index 0000000..aa47460 --- /dev/null +++ b/blog/templatetags/code_chunks.py @@ -0,0 +1,36 @@ +from django import template +from django.template.defaultfilters import stringfilter +from django.utils.safestring import mark_safe +import logging +from pygments import highlight +from pygments.lexers import get_lexer_by_name +from pygments.formatters import HtmlFormatter +from gergelypolonkaiweb.solarized_dark import SolarizedDarkStyle + +register = template.Library() + +class CodeFormatter(HtmlFormatter): + def wrap(self, source, outfile): + return self._wrap_code(source) + + def _wrap_code(self, source): + yield 0, "
    " + for i, t in source: + if i == 1: + t = "
  1. " + t + "
  2. " + + yield i, t + yield 0, "
" + +@register.filter(needs_autoescape=True) +@stringfilter +def syhilite(value, language, autoescape=None): + if language == "php": + value = "[^/]+)$', views.taglist, name='taglist'), url(r'^tag/(?P[^/]+)/page/(?P\d+)$', views.tagpage, name='tagpage'), url(r'^(?P\d+)/(?P\d+)/(?P\d+)/(?P[^/]+)$', views.read, name='read'), + url(r'^code-chunk/(?P[^/]+)/(?P[^/]+)$', views.codechunk, name='codechunk'), url(r'^feed$', views.feed, name='feed'), ) diff --git a/blog/views.py b/blog/views.py index e57401d..67860f4 100644 --- a/blog/views.py +++ b/blog/views.py @@ -1,7 +1,7 @@ import datetime from django.shortcuts import render, get_object_or_404 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger -from blog.models import Post +from blog.models import Post, CodeChunk def mainpage(request): last_posts = Post.objects.filter(draft = False).order_by('-created_at')[:5] @@ -42,6 +42,10 @@ def read(request, year, month, day, slug): post = get_object_or_404(Post, created_at__year=int(year), created_at__month=int(month), created_at__day=int(day), slug=slug, draft=False); return render(request, 'blog/view.html', {'post': post}) +def codechunk(request, language, slug): + chunk = get_object_or_404(CodeChunk, language=language, slug=slug) + return render(request, 'blog/code-chunk.html', {'codechunk': chunk}) + def feed(request): return render(request, 'blog/feed.xml', {}) diff --git a/gergelypolonkaiweb/solarized_dark.py b/gergelypolonkaiweb/solarized_dark.py new file mode 100644 index 0000000..74e044f --- /dev/null +++ b/gergelypolonkaiweb/solarized_dark.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +""" + pygments.styles.solarized_dark + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Solarized style. See http://ethanschoonover.com/solarized for details. + Solarized is created by Ethan Schoonover. +""" + +from pygments.style import Style +from pygments.token import Comment, Error, Generic, Keyword, Literal, Name, Number, Operator, Other, Punctuation, String, Text, Token, Whitespace + +class SolarizedDarkStyle(Style): + """ + Solarized style. + """ + + default_style = '' + + styles = { + Comment: '#586e75', + Comment.Multiline: '#586e75', + Comment.Preproc: '#586e75', + Comment.Single: '#586e75', + Comment.Special: '#586e75', + Error: '', + Generic: '', + Generic.Deleted: '', + Generic.Emph: '', + Generic.Error: '', + Generic.Heading: '', + Generic.Inserted: '', + Generic.Output: '', + Generic.Prompt: '', + Generic.Strong: '', + Generic.Subheading: '', + Generic.Traceback: '', + Keyword: '#b58900', + Keyword.Constant: '', + Keyword.Declaration: '', + Keyword.Namespace: '', + Keyword.Pseudo: '', + Keyword.Reserved: '', + Keyword.Type: '', + Literal: '', + Literal.Date: '', + Name: '', + Name.Attribute: '', + Name.Builtin: '#2aa198', + Name.Builtin.Pseudo: '', + Name.Class: '', + Name.Constant: '', + Name.Decorator: '', + Name.Entity: '', + Name.Exception: '', + Name.Function: '#93a1a1', + Name.Label: '', + Name.Namespace: '', + Name.Other: '', + Name.Property: '', + Name.Tag: '', + Name.Variable: '#268Bd2', + Name.Variable.Class: '', + Name.Variable.Global: '', + Name.Variable.Instance: '', + Number: '#2aa198', + Number.Float: '#2aa198', + Number.Hex: '#2aa198', + Number.Integer: '#2aa198', + Number.Integer.Long: '#2aa198', + Number.Oct: '#2aa198', + Operator: '#859900', + Operator.Word: '#859900', + Other: '', + Punctuation: '', + String: '#2aa198', + String.Backtick: '#2aa198', + String.Char: '#2aa198', + String.Doc: '#2aa198', + String.Double: '#2aa198', + String.Escape: '#2aa198', + String.Heredoc: '#2aa198', + String.Interpol: '#2aa198', + String.Other: '#2aa198', + String.Regex: '#2aa198', + String.Single: '#2aa198', + String.Symbol: '#2aa198', + Text: '', + Token: '#93a1a1', + Whitespace: '' + } diff --git a/gergelypolonkaiweb/templates/front_base.html b/gergelypolonkaiweb/templates/front_base.html index d926e6c..8e721b3 100644 --- a/gergelypolonkaiweb/templates/front_base.html +++ b/gergelypolonkaiweb/templates/front_base.html @@ -12,6 +12,7 @@ + {% endblock %} {% endcompress %}