Permalink
Browse files

initial commit

  • Loading branch information...
aaronsw committed Sep 20, 2011
0 parents commit 44807fed4fe1fab0f4c26f5e2ffd452a6c0defac
Showing with 144 additions and 0 deletions.
  1. +44 −0 README
  2. +71 −0 generator.py
  3. +29 −0 metamake.py
44 README
@@ -0,0 +1,44 @@
+Welcome to metamake, a weblog system based on make. This probably isn't
+usable by anyone but extreme geeks, but here it is if you're interested.
+
+## Install
+
+cd /path/to/weblog
+mkdir code
+cd code
+# [get Markdown.pl]
+wget http://www.aaronsw.com/weblog/code/markdown.py
+wget http://www.aaronsw.com/weblog/code/generator.py
+wget http://www.aaronsw.com/weblog/code/generator.py
+cd ..
+
+## Configure
+
+* singlepage.tmpl is the template for the entry page
+* conf/indexes lets you list index templates (RSS, index.html, etc.), e.g.:
+ rss.tmpl rss.xml
+ index.tmpl index.html
+
+Templates are standard Cheetah templates with variables file (filename),
+title, body (converted using Markdown), and date (creation date). The
+multi-entry templates have these inside a list named entries.
+
+## Post
+
+$ cat > _postname.txt
+# The Truth About Purple
+
+Through copious research I have discovered that purple is not really a color.
+Call Dan Rather!
+
+^D
+$ echo postname >> list
+$ make
+
+The first time the Makefile won't exist yet, so you'll have to run:
+
+python code/metamake.py > Makefile
+
+--
+Aaron Swartz: http://www.aaronsw.com/
+email: me@aaronsw.com
@@ -0,0 +1,71 @@
+from Cheetah.Template import Template
+from markdown import markdown
+import sanitize
+import sys, os, datetime, re, cPickle as pickle
+
+class Storage:
+ def __init__(self, x=None):
+ if x: self.__dict__ = x
+
+def striphtml(a): return re.sub('<.*?>', '', a)
+def cleandate(d): return datetime.datetime.fromtimestamp(int(d)).date().strftime('%B %e, %Y')
+def isodate(d): return datetime.datetime.fromtimestamp(int(d)).isoformat()
+def file2dict(fn, comments=True, body=True):
+ s = Storage()
+ s.file = fn
+ fh = open('_'+fn+'.txt')
+ s.title = markdown(fh.readline()[2:].strip()).strip().replace('<p>', '').replace('</p>', '')
+ fh.readline()
+ if body:
+ s.body = markdown(fh.read())
+ s.shortbody = striphtml(s.body)[:150]
+ if not os.path.exists('.'+fn+'.ctime'):
+ open('.'+fn+'.ctime', 'w').write(str(os.stat('_'+fn+'.txt')[-1]))
+ s.date = cleandate(open('.'+fn+'.ctime').read())
+ s.isodate = isodate(open('.'+fn+'.ctime').read())
+ if comments:
+ s.comments = []; i = 1
+ while os.path.exists('_'+fn+'.comments.'+str(i)+'.txt'):
+ furl = '_'+fn+'.comments.'+str(i)+'.txt'
+ if not open(furl).read(): i+=1; continue
+ s.comments.append(Storage(pickle.load(open(furl))))
+ if s.comments[-1].__dict__.get('moderate'):
+ s.comments.pop(); i+=1; continue
+ s.comments[-1].date = cleandate(s.comments[-1].date)
+ s.comments[-1].id = i
+ s.comments[-1].content = sanitize.HTML(markdown(s.comments[-1].content), addnofollow=True)
+ i+=1
+ return s
+
+def handle(fn, out=None):
+ if out is None: out = fn
+ t = str(Template(open('singlepage.tmpl').read(), [file2dict(fn)]))
+ open(out+'.html.tmp', 'w').write(t)
+ os.rename(out+'.html.tmp', out+'.html')
+
+if __name__ == "__main__":
+ fn = sys.argv[1]
+ if fn == "all":
+ entries = []
+ ents = open('list').readlines()
+ ents.reverse()
+ ents = ents[:12]
+ for line in ents:
+ entries.append(file2dict(line.strip().split()[-1], comments=False))
+ for line in open('conf/indexes'):
+ template, filename = line.split()
+ open(filename, 'w').write(str(Template(open(template).read(), [{'entries':entries[:12]}])))
+ print filename
+
+ # fullarchive
+ entries = []
+ ents = open('list').readlines()
+ ents.reverse()
+ for line in ents:
+ entries.append(file2dict(line.strip().split()[-1], comments=False, body=False))
+ open('fullarchive.html', 'w').write(str(Template(open('fullarchive.tmpl').read(), [{'entries':entries}])))
+ print "fullarchive.html"
+ else:
+ out = None
+ if len(sys.argv) > 2: out = sys.argv[2]
+ handle(fn, out)
@@ -0,0 +1,29 @@
+import time
+def parse(fn, sep):
+ x = []
+ for line in open(fn):
+ x.append(line.strip().split()[0])
+ return sep.join(x) + sep
+
+print "all: " + parse('conf/indexes', ' ') + parse('list', '.html ') + 'Makefile'
+print '\tpython code/generator.py all'
+print
+donesofar = set()
+for line in open('list'):
+ line = line.strip()
+ assert line not in donesofar
+ donesofar.add(line)
+ if ' ' in line:
+ out, fn = line.split()
+ else:
+ fn = out = line
+ print out+'.html: _'+fn+'.txt singlepage.tmpl'
+ print '\tcp _%s.txt _%s.txt.bak.%s' % (fn, fn, time.time())
+ print '\tpython code/generator.py '+fn + (' '+out if out != fn else '')
+ print '\tsudo chgrp www-data '+out+'.html'
+ print '\tchmod g+w '+out+'.html'
+ print
+print 'Makefile: list code/metamake.py conf/indexes'
+print '\tpython code/metamake.py > Makefile'
+print '\tmake'
+print

0 comments on commit 44807fe

Please sign in to comment.