New WIKI

把东西整理好(除去椅子上长出来的衣服),是我喜欢做的一件事情。 为了解决我的笔记,想了各种办法。 由于笔记固有的复杂性,总是很难整理到满意的地步。 这些年用过wiz笔记,evernote,simplenote, onenote, 可是都没法做到非常有序。 这不,我希望试验一下使用 wiki 来管理学习的知识。

在调研了一圈wiki应用后,为这些应用复杂的特性感到shame。 鉴于

  • 整理是件费力的事情,在电脑上比较高效,
  • 文本编辑 vim 相对来说对我更高效

我决定以一个 Git 仓库来管理 markdown 文件。 我设定的规则是:

  • 限制 3 层树结构。
  • 文档ID 是路径+文件名,去掉 .md 的部分,例如 Leetcode/283 对应 ./Leetcode/283.md
  • 直接使用 [文档ID] 的形式,渲染时可以链接到对应文档。不存在的文档ID 当作普通文本,不存在的文档ID链接报错404。

规则就是这三个,没有更多规则了。

想想 Jekyll 博客也进入第十个年头了,能坚持到现在,一个原因是使用简单,有事没事,进来花个10分钟加个文件,立马走人。希望这个简单的 Wiki 程序也能好用,并用上一些年头。

一个快慢糙的实现,我想在1k个文档内,这个程序都不太会有性能问题:

import os
from glob import glob
from flask import Flask, abort, redirect
from markdown import markdown

app = Flask(__name__)

def load_files():
    files = [filename for filename in glob('*.md')]
    files.extend(filename for filename in glob('*/*.md'))
    files.extend(filename for filename in glob('*/*/*.md'))
    files = map(lambda filename: filename.decode('utf8'), files)
    return u'\n'.join(
        u'[%s]: /%s' % (filename.strip('.md'), filename.strip('.md'))
        for filename in files
    )

@app.route('/')
def index():
    return redirect('/Home')

@app.route("/<path:filename>")
def show_wiki(filename):
    filename_ext = '%s.md' % filename
    if not os.path.exists(filename_ext):
        abort(404)
    title = filename
    with open(filename_ext) as f:
        body = f.read()
        body += '\n'
        body = body.decode('utf8')
        body += load_files()
        body = markdown(body)
    return '<html><head><title>%(title)s</title></head><body>%(body)s</body></html>' % dict(
        title=title,
        body=body,
    )

外加一个部署的 ansible 配置:

---

- name: Provision a wiki application.
  hosts: app
  become: yes
  become_user: root
  remote_user: root
  vars:
    wiki_port: 9999
  tasks:
    - name: Update Code
      git:
        repo: git@github.com:soasme/wiki.git
        dest: /var/www/wiki
    - name: Build Environment
      pip:
        requirements: /var/www/wiki/requirements.txt
        virtualenv: /var/www/wiki/venv
    - name: Gunicorn
      pip:
        name: gunicorn
        virtualenv: /var/www/wiki/venv
    - name: Kill
      shell: fuser -k {{ wiki_port }}/tcp
      ignore_errors: yes
    - name: Start
      shell: venv/bin/gunicorn runwiki:app --daemon -b 0.0.0.0:{{ wiki_port }} --access-logfile -  --error-logfile /var/log/wiki-gunicorn.log
      args:
        chdir: /var/www/wiki

可访问 http://wiki.soasme.com/Home 查看。