Calepin.co 的简易替代

黄杰, 2012-04-25
root[a]linuxsand.info

UPDATE:见 http://blog.linuxsand.info/using-pelican-to-staticize-blog.html

结构

服务端

- blog.py           # 主程序
- templates/        # 模板目录
    - base.html     # 父模板
    - index.html    # 列表页面模板
    - view.html     # 文章详情页模板
- web/              # web.py
- markdown/         # markdown

贴一下 blog.py。

# coding: utf-8
import web
import urllib2
from markdown import markdown

urls = (
'/', 'Index',
'/(.+)', 'View',
)

render = web.template.render('templates/', base='base')
app = web.application(urls, globals())

d_prefix = 'http://dl.dropbox.com/u/60841531/blog/'

### uncomment it if testing at localhost
# d_prefix = 'C:\\Users\\Administrator\\Dropbox\\Public\\blog\\'
index_txt = d_prefix + 'index.txt'

def open_(txt):
    return open(txt)

### comment it if testing at localhost
open_ = urllib2.urlopen

def get_and_render_content(lines):
    title = lines[0].replace('title:', '').strip()
    date = lines[1].replace('date:', '').strip()
    text = markdown(''.join(lines[4:]).decode('utf8')).encode('utf8')
    return render.view(title, date, text)

# ugly function to avoid processing in template
def process_list(alist):
    all_ = [line.split('|') for line in alist]
    months = [i[0].strip()[:-3] for i in all_] # '2012-04'

    sset = sorted(set(months))
    sset.reverse()
    counts = [months.count(i) for i in sset]

    container = []
    for i, j in zip(sset, counts):
        x = months.index(i) # 0
        y = range(x, x+j) # range(0, 4)
        container.append([i, y])
    return container

class Index:
    def GET(self):
        index_list = open_(index_txt).readlines()
        # don't have to pass `index_list`, lazy...
        return render.index("linuxsand's blog", process_list(index_list), index_list)

class View:
    url_dict = {}
    for i in open_(index_txt):
        key = i.split('|')[1].strip()[1:]
        value = i.split('|')[3].strip()

        # uncomment it if testing at localhost
        # value = i.split('|')[2].strip().decode('utf8') 
        url_dict[key] = value

    def GET(self, slug):
        try:
            content = open_(d_prefix + self.url_dict[slug]).readlines()
            return get_and_render_content(content)
        except KeyError:
            web.notfound()

if __name__ == '__main__':
    app.cgirun()
    # app.run()

定义外观样式花的时间倒不比实现功能少。我直接把 CSS 写在其中了,可读性差。所以模板文件不贴了。

本地

只一个 __update__.py 文件,反正是在本地运行,怎么方便怎么写。

import os, sys
from fnmatch import fnmatch
import urllib

def generate_index(dir):
    lines = []
    for i in os.listdir(dir):
        if fnmatch(i, '*.md'):
            f = open(dir + i)
            filename = f.readline().replace('title:', '').strip() + '.md'
            date = f.readline().replace('date:', '').strip()
            slug = '/%s.html' % (f.readline().replace('slug:', '').strip())
            url = urllib.quote(filename)
            lines.append('%s | %s | %s | %s \n' % (date, slug, filename, url))
    lines.sort()
    lines.reverse()
    return lines

dir_ = 'C:/Users/Administrator/Dropbox/Public/blog/'
lines = generate_index(dir_)
with open('index.txt', 'w') as f:
    f.writelines(lines)

sitemap = ['http://blog.linuxsand.info' + i.split('|')[1].strip() + '\n' for i in lines]
with open('sitemap.txt', 'w') as s:
    s.writelines(sitemap)

# os.system('python __atom__.py')

可以增添代码使其有「分类」「标签」等功能,但是我不需要。

P.S. 迁移过来的一个小小的好处是不需在写完后到 Calepin.co 首页去点击 Publish 了。保持简单。