]> git.sur5r.net Git - i3/i3.github.io/blob - _controllers/org.py
repositories: create separate files instead of using /etc/apt/{preferences,sources...
[i3/i3.github.io] / _controllers / org.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 """
5 org.py convert org source file into html file 
6 """
7
8 __author__ = "Jaemok Jeong(jmjeong@gmail.com)"
9 __date__   = "Tue Aug 11 12:50:17 2009"
10
11
12 import os
13 import tempfile
14 import logging
15 import re
16 import sys
17 import commands
18 import codecs
19 import datetime
20 import pytz
21 from BeautifulSoup import BeautifulSoup
22
23 import blogofile_bf as bf
24
25 logger = logging.getLogger("blogofile.org")
26
27
28 class EmacsNotFoundException(Exception):
29     pass
30
31
32 post = bf.config.controllers.blog.post.mod
33
34
35 class org(object):
36     """
37         Class to Convert org file into html file
38
39         It composes org-content with source, preamble, and postample.
40         Launches emacs and convert the org-content into html file.
41
42         Generated html file is processed with BeautifulSoup module to
43         extract body section and title and categories.
44
45         self.content  = body
46         self.title    = title (which is first '*' in org-file)
47         self.category = categories (which is tags in first '*' in org-file)
48         self.date     = date (which is scheduled file?)
49
50         """
51     def __init__(self, source):
52         self.source = source
53         return self.__convert()
54         
55     def __convert(self):
56         temp_file = tempfile.NamedTemporaryFile(suffix='.org')
57         try:
58             temp_file.write(bf.config.blog.emacs_orgmode_preamble)
59             temp_file.write("\n")
60         except AttributeError:
61             pass
62         temp_file.write(self.source.encode(bf.config.blog_post_encoding))
63         temp_file.flush()
64
65         pname = ""
66         try:
67             pname = bf.config.blog.emacs_binary
68         except AttributeError:
69             raise EmacsNotFoundException("Emacs binary is not defined")
70
71         pname += " --batch"
72         try:
73             if bf.config.blog.emacs_preload_elisp:
74                 pname += " --load={0}".format(
75                         bf.config.blog.emacs_preload_elisp)
76         except AttributeError:
77             pass
78
79         pname += " --visit={0} --funcall org-export-as-html-batch".format(
80                 temp_file.name)
81         logger.debug("Exec name::: %s" % pname)
82
83         status, output = commands.getstatusoutput(pname)
84         logger.debug("Convert output:::\n\t%s"%output)
85         if status:
86             raise EmacsNotFoundException("orgfile filter failed")
87         
88         html = temp_file.name[:-4] + '.html'
89         temp_file.close()
90
91         #IMO codecs.open is broken on Win32.
92         #It refuses to open files without replacing newlines with CR+LF
93         #reverting to regular open and decode:
94         content = open(html, "rb").read().decode(bf.config.blog_post_encoding)
95
96         # remote the temporary file
97         os.remove(html)
98
99         soup = BeautifulSoup(content)
100
101         # the first h2 section will be used for title, category, and date
102         metaline = soup.find('div', {'id': 'outline-container-1'}).h2
103
104         # extract title
105         try:
106             self.title = re.sub(' ', '', metaline.contents[0]).strip()
107         except AttributeError:
108             self.title = None
109
110         # extract category
111         try:
112             categories = metaline('span', {'class':'tag'})[0].string
113             self.categories = set([post.Category(x)
114                     for x in categories.split(' ')])
115         except:
116             self.categories = None
117
118         # extract date
119         try:
120             date = metaline('span', {'class':'timestamp'})[0].string # 2009-08-22 Sat 15:22
121             # date_format = "%Y/%m/%d %H:%M:%S"
122             self.date = datetime.datetime.strptime(date, "%Y-%m-%d %a %H:%M")
123             self.date = self.date.replace(
124                     tzinfo=pytz.timezone(bf.config.blog_timezone))
125         except:
126             self.date = None
127
128         # delete first h2 section (which is title and category)
129         try:
130             metaline.extract()
131         except AttributeError:
132             pass
133
134         # print soup.body
135         try:
136             toc = soup.find('div',{'id': 'table-of-contents'})
137             content = soup.find('div', {'id': 'outline-container-1'})
138
139             if toc != None:
140                 content = str(toc) + str(content)
141                 
142             self.content = str(content).decode(bf.config.blog_post_encoding)
143         except:
144             pass
145
146
147 if __name__ == '__main__':
148     import doctest
149     doctest.testmod(verbose=True)
150