用markdown + pandoc + makefile + git(github)搭建免费个人wiki

date: 2013.06.28; modification:2015.09.18

目录:

以前用过各种工具, 记笔记写文章, 但都不是特别理想. 所以自己用markdown + pandoc + makefile + git(github)倒腾出一套符合自己需求的工具(其实叫做方法更合适, 因为工具都现成的, 只是组合而已). 先拿出来与大家分享, 并尽量详细解释.

1 前言

以前用过的各种工具, 它们各自的优缺点如下:

工具 优点 缺点
现成的博客(网易,新浪等) 简单 过于依赖于服务器, 文章的系统性不强, 无版本管理
wordpress 可以自主定制 过于依赖于服务器, 文章的系统性不强, 无版本管理
evernote 简单方便, 非常适合于做笔记. 用户粘性大, 无版本管理.
mediawiki 文章系统性强 过于依赖服务器
vimwiki 使用起来近乎完美 用户粘性大, 语法与工具不通用
github+jekyll 方便的版本管理. 模版是借助第三方的, 所以个人不太喜欢. 且需要服务器提供jekyll服务来渲染. 如果和我的需求类似, 但是用不习惯makefile, 那么这个应该是最好的选择了.

曾经以为vimwiki是一个比较适合我的工具, 因为我一直在用vim, 所以vimwiki用起来比较顺手. 但是后来发现了一个问题, vimwiki用的语法不是通用的标准, 而且他的转化工具是vim内部脚本. 所以如果以后写的文章多了, 再行改其他的工具, 这个转化过程会是非常痛苦的.

所以总结了一下我个人对于笔记/wiki工具的需求:

基于以上需求, 我自己用markdown + pandoc + makefile + git(github)倒腾出一套符合自己需求的工具(其实叫平台或者方法更合适, 因为工具都现成的, 只是组合而已). 不过这种用很多小工具组合成平台的方法, 也正体现了unix的哲学之一: 个体很渺小, 联合很强大.

我的这套平台具有以下特点:

优点:

缺点:

2 基本原理

  1. 将用markdown写的文章或者笔记保存为.mkd文件, 并在本地按照知识体系安排好文件夹层次. mtd语法请参照: markdown语法
  2. 用makefile调用pandoc, 并套用pandoc模版, 生成html. 请参考: pandoc模板 以及下文的makefile分析部分.
  3. 用git上传到github进行在线发表. 如果你有兴趣的话github还能绑定自己的域名. 请参考: github发布个人wiki

这样, 本地笔记和在线wiki就都有了.

3 使用方法

  1. 使用前提: 先安装make, pandoc, git. windows下可以使用cygwin模拟.
  2. 下载: 示例包
  3. 将示例包中的makefile与index.mkd放在同级目录, 并置于将要发布的网站的顶级目录(因为其他页面都是从此向子目录搜索编译的).
  4. 键入make, 回车. 生成html.
  5. 假如这些文章已经被git管理, 则可以用git push到github进行发表.

4 相关知识:

5 makefile解析

通过分析makefile, 便可了解本方法的核心原理. 从而定制出符合您自己需求的工具版本.

请查看上面的示例包中的makefile的源文件, 对照里面的注释即可看懂. 如果看不懂, 就参考上面的makefile入门的链接.

至此全部和wiki本身相关的内容已经介绍完毕. 接下来会介绍一些vim中使用的扩展技巧, 如果对vim没有兴趣, 可以到此结束

6 在Vim中使用

本节包含:

首先, 我安装了叫做markdown的vim语法高亮插件: vim-markdown

然后, 将下面的这几段脚本保存为mkd.vim放到vim runtime路径下的ftplugin下, 这样, 会自动匹配扩展名为mkd的文件, 其他文件不受影响.

我尽量加了详细的注释, 大家可以根据需要修改. 修改可以参考: 编写Vim脚本. 以该链接作为参考字典, 只要稍微有点编程知识就能自行修改了.

这几句使其不会因为重复加载该脚本而报错:

if exists("loaded_MikeWiki")
    finish
endif
let loaded_MikeWiki = 1

这是自动跳转到站内链接的:

" ------------------------------------------------------------------------------
" 按回车键自动跳到光标所在的站内wiki链接(光标需要放在链接xxx/xxxx.html上)
func! MikewikiEnterWikiPage()
    let l:lineBuffer = expand("<cWORD>")                                                " 获取光标所在处的链接字符串
    let l:localLink = substitute(l:lineBuffer, '.*\](\(.*\).html).*', '\1.mkd', "g")    " 将链接中的.html改为.mkd.
    let l:hasLink = match(l:lineBuffer, '.\+.html')                                     " 匹配是否存在.html...
    if l:hasLink == 0                                                                   " ...如果存在才跳转
        " 检测目标文件所在文件夹是否存在, 如果不存在则创建
        let l:localLinkDir = substitute(system("dirname ".l:localLink), '\n', '', "g")
        let l:localLinkDirExist = isdirectory(l:localLinkDir)
        if !l:localLinkDirExist
            exec "!mkdir -p ".l:localLinkDir           " 这里的mkdir如果使用的不是linux可以自行修改为别的命令.
                " ^ 此处我故意没加silent, 所以创建时会停在提示栏, 按任意键才继续, 因为个人认为创建目录是一件谨慎的事.
                " 如果觉得麻烦, 可以改为exec "silent !mkdir -p ".l:localLinkDir, 就自动继续了.
        endif

        exec "vi ".l:localLink                         " 打开(跳转到)目标文件xxx/xxxx.mkd
    endif
endfunc
nmap <buffer> <cr> :call MikewikiEnterWikiPage()<CR>   " 映射为回车, 可以自行修改

这是在文件保存时候自动更新时间:

" ------------------------------------------------------------------------------
" 更新日期: 会将.mkd文件中的<!---date-->或者<!---date:yyyy.mm.dd-->替换为当前日期
" 有了这个就很容易实现在make时候向html中更新日期.
func! MikewikiUpdateDatetime()
    exec "norm mz"
    exec '%s/^<!---date\(.*\)-->.*/<!---date:'.strftime("%Y.%m.%d")."-->"."/e"
                                                                " ^ 如果需要时间可以加上 %H:%M:%S
    exec "norm `z"
endfunc
au BufWritePre *.mkd call MikewikiUpdateDatetime()

这是在文件保存时候自动make的:

" make, 判断如果当前目录下存在makefile(注意大小写)则执行外部命令make.
func! MikewikiMake()
    if filereadable("makefile")
        exec "silent !make"
    endif
endfunc

" 设置为在*.mkd后缀的文件, 当保存时候起效果:
au BufWritePost *.mkd call MikewikiMake()

7 Firefox中自动刷新

如果用vim编辑的话, 虽然按照上述方法可以自动make, 但是还有一个问题就是无法所见及所得, 我会在写作的过程中不断的切换到firefox来手动刷新看效果. 感觉很麻烦.

后来发现了一个firefox自动刷新的插件: reload every. 可以自动刷新页面.

使用方法就是安装之后, 在页面右键->reload every, 然后选启用, 就可以不断刷新了, 也可以自定义刷新间隔(建议>=3s). 现在我在vim中一保存, firefox那边基本就能看到效果. 这样类似半所见即所得, 写作时感觉响当相当的行云流水.

注: 这个插件好像有点问题, 我设置成2秒的时间间隔, 就刷不出效果来了. 所以我最小就设为3秒. 而且有时css修改后也刷不出效果, 手动刷一下就好了.