constance

Scripts for generating (an earlier obsolete version of) my personal web site
git clone https://code.djc.id.au/git/constance/

blog.py (3063B) - raw

      1 
      2 # vim:fileencoding=utf-8
      3 
      4 import os
      5 import re
      6 import email
      7 from datetime import datetime
      8 import genshi.template
      9 import lxml.etree
     10 
     11 import constance
     12 import viewutils
     13 
     14 template_loader = genshi.template.TemplateLoader(
     15         os.path.join(os.path.realpath(os.path.dirname(__file__)), 'templates', 'blog'), 
     16         variable_lookup='strict')
     17 
     18 def cleanup_metadata(header_items):
     19     cleaned = {}
     20     for k, v in header_items:
     21         k = k.lower()
     22         if k.endswith('date'):
     23             v = datetime.strptime(v, '%Y-%m-%d %H:%M:%S')
     24         else:
     25             v = v.decode('utf8') # XXX encoding
     26         cleaned[k] = v
     27     return cleaned
     28 
     29 class BlogEntry(object):
     30 
     31     def __init__(self, dir, name):
     32         content_filename = os.path.join(dir, name + '.txt')
     33         self.id = name.decode('utf8')
     34 
     35         # not really a MIME document, but parse it like one
     36         msg = email.message_from_file(open(content_filename, 'r'))
     37         self.metadata = cleanup_metadata(msg.items())
     38         self.body = viewutils.markdown(msg.get_payload().decode('utf8'))
     39         self.title = viewutils.mini_markdown(self.metadata['title'])
     40 
     41         raw_tags = self.metadata.get('tags', '').strip()
     42         if raw_tags:
     43             self.tags = frozenset(tag.strip() for tag in raw_tags.split(','))
     44         else:
     45             self.tags = frozenset()
     46 
     47         self.modified_date = datetime.fromtimestamp(os.path.getmtime(content_filename))
     48         self.publication_date = self.metadata.get('publication-date', None) or self.modified_date
     49         self.guid = self.metadata['guid']
     50         self.language = self.metadata.get('language', None)
     51 
     52     def generate_atom(self, config):
     53         return template_loader.load('entry.atom').generate(item=self,
     54                 config=config)
     55 
     56 class BlogEntrySet(object):
     57 
     58     def __init__(self, dir):
     59         self.dir = dir
     60         self.entries = []
     61         for filename in os.listdir(dir):
     62             m = re.match(r'([^.].*)\.txt$', filename)
     63             if m:
     64                 self.entries.append(BlogEntry(dir, m.group(1)))
     65     
     66     def __iter__(self):
     67         return iter(self.entries)
     68 
     69     def __len__(self):
     70         return len(self.entries)
     71 
     72 def generate(dir, xslt, config):
     73     entries = BlogEntrySet(dir)
     74     
     75     for entry in entries:
     76         rendered = template_loader.load('entry.html').generate(item=entry,
     77                 config=config).render('xhtml', encoding='utf8')
     78         transformed = str(xslt(lxml.etree.fromstring(rendered)))
     79         constance.output(os.path.join(dir, entry.id.encode('utf8') + '.html'), transformed)
     80     
     81     # index
     82     rendered = template_loader.load('index.html').generate(items=entries,
     83             config=config).render('xhtml', encoding='utf8')
     84     transformed = str(xslt(lxml.etree.fromstring(rendered)))
     85     constance.output(os.path.join(dir, 'index.html'), transformed)
     86 
     87     # feed
     88     rendered = template_loader.load('index.atom').generate(items=entries,
     89             config=config).render('xml', encoding='utf8')
     90     constance.output(os.path.join(dir, 'index.atom'), rendered)
     91 
     92     return entries