我的知识库管理现状

一段时间以来我都算是 PocketEvernote 的忠实用户,Pocket 用于采集网上看到的想要稍后预读的文章,遇到比较好的内容觉得该记录下来的就记录在 Evernote 里,这样 Evernote 基本被我用来做个人知识库了,平常比较零散的个人信息之类的则记录到 Google Keep 中。

最近在 Android 手机上碰到几次比较奇怪的 Evernote 数据库错误之后还是觉得 Evernote 虽然有相对还算好用的离线、同步、搜索等功能,但也有一些问题:

  • 众所周知的编辑功能确实比较烂,不支持 Markdown,对于表格等稍微复杂点的内容那编辑效果简直惨不忍睹;
  • 只有笔记本组和笔记本这两层结构对于我来说始终还是觉得不够;
  • 客户端里所有笔记数据都放在 SQLite 数据库文件感觉稳定性一般。 再加上最近 Evernote 这头大象给人的前景似乎一直不太好,所以我就想找到一个相对比较简单优雅的个人知识库系统,最好是能直接支持 Markdown 格式,不需要复杂的搭建步骤,能方便的在我的 VPS 和本地跑起来,当然 Evernote 我暂时还是不会弃用的。

MDwiki 和 Wikitten 对比

我找了几个比较流行的 Wiki 系统,开始就跳过了 MediaWiki 这种看起来略复杂的系统,也简单看了看很多网友推荐的 DokuWiki,甚至还有 TiddlyWiki 这种直接单文件的 Wiki 方式,初步考虑后想用 MDwiki 这个基于 Markdown 而且超级简单的纯静态 Wiki 系统。

MDwiki 相对于其它 Wiki 系统的最大好处是其单纯使用浏览器就可以解析 Markdown 文档,部署可算是超级简单了,VPS 上只要有 Web 服务器就可以访问(纯静态不需要 PHP 支持),甚至在 PC 本地也可以直接打开(虽然 IE11 和 Chrome 浏览器上已经不支持请求本地文件了)。

按照 MDwiki 官网的介绍生成一个 Wiki 主页还是非常简单的,网上的说明也比较多这里就不介绍了,如果知识库内容比较少用 MDwiki 还是很方便的,但我想稍微增加一些内容时就发现了 MDwiki 一些明显的不足:

  • 导航菜单只支持两层,这个是 MDwiki 使用的 Bootstrap 的限制,而且如果有很多层目录,每个目录下又有不少 Markdown 文档,直接全部放在导航菜单里那体验也是比较糟糕的;
  • 由于纯静态的限制,如果在某个目录下增加了 Markdown 文档,那就需要同步修改导航菜单,或者在其它页面里加上指向新文档的链接,这样如果需要动态修改更新实在有点麻烦;
  • 同样由于纯静态的限制,基本没有办法实现搜索功能,如果后续知识库文章较多那还需要同步下来对文件夹进行搜索;
  • MDwiki 只有一个主 html 文件,切换文章是用 AJAX 异步加载 Markdown 文档然后解析显示的,这样就意味着 MDwiki 对于搜索引擎来说是非常不友好的,基本没有实际可用内容。

因此我还是想实现既能兼顾 MDwiki 直接使用 Markdown 的方便之处又能解决上面列出的问题,最后还是找到了 Wikitten 这个用 PHP 实现的 Wiki 系统。

Wikitten 与 MDwiki 不同之处在于 Markdown 文档是由 PHP 程序解析并直接转换为 HTML 返回给浏览器的,而且配置好知识库目录之后访问就可以显示完整的目录树(有修改更新时也不用手工修改其它 Markdown 文件了),也有比较简单的搜索功能,可以直接把源代码文件以比较漂亮的形式显示出来。

我部署的 Wikitten 系统运行效果图如下:

wikitten-example
wikitten-example

综合考虑之后我准备对 Wikitten 和 MDwiki 做出少量修改,以实现在我的 VPS 服务器上主要还是用 Wikitten 来动态展示,需要在本地直接查看修改时也可以用上 MDwiki,这样就能兼顾两者的优点了。

MDwiki 的修改

对 MDwiki 的修改主要考虑到要能方便的找到目录树的 Markdown 文档,修改如下:

  1. 把 Markdown 文档放到单独的目录中,我是直接改成放到和mdwiki.html主文件相同路径的library目录,这与 Wikitten 的默认知识库目录是一致的,这样 Wikitten 和 MDwiki 就可以共用 Markdown 文档了;
  2. 支持识别 Markdown 文件开头添加的 YAML front matter 数据,front matter 可以用来表示 Markdown 文档的标题、作者、标签等信息;

提示

MDwiki 新增加的 font matter 支持需要修改config.json配置文件增加”parseHeader”: true进行开启。

Wikitten 是直接支持 YAML front matter 的并能动态生成到 HTML 数据中的,常见的 front matter 数据格式是这样的:

1---
2"title": "Wiki site",
3"tags": ["tag1", "tag2", "tag3"],
4"author": "xxx"
5---

注意

上面的格式中开头和结束是 3 个横线,而且开头以及结束的横线和中间的实际 front matter(也就是 meta data)内容之间只有一个回车哦;下面修改后的格式也是类似的。

不过上面这种格式很多 Markdown 编辑器却是不支持的显示有问题,这里我改成了和 MDwiki 暂未发布的开发版本中一致的形式:

---
"title": "Wiki site",
"tags": ["tag1", "tag2", "tag3"],
"author": "xxx"
---

我写了一个自动生成 Markdown 知识库目录下面所有子目录索引文件index.md的 shell 脚本 generate-index.sh 给 MDwiki 使用,使用起来也很简单:

 1(trusty)zzm@localhost:~/wiki$ ./generate-index.sh library
 2Generate index file: library/生活/index.md
 3Generate index file: library/阅读/index.md
 4Generate index file: library/技术/网络/index.md
 5Generate index file: library/技术/硬件/USB/index.md
 6Generate index file: library/技术/硬件/PCI-E/index.md
 7Generate index file: library/技术/硬件/index.md
 8Generate index file: library/技术/存储/index.md
 9Generate index file: library/技术/index.md
10Generate index file: library/技术/音视频/index.md
11Generate index file: library/技术/Linux/内存管理/index.md
12Generate index file: library/技术/Linux/文件系统/index.md
13Generate index file: library/技术/Linux/开发工具/index.md
14Generate index file: library/技术/Linux/index.md
15Generate index file: library/技术/Android/index.md
16Generate index file: library/技术/Docker/index.md

generate-index.sh脚本会查找输入的 Markdown 知识库目录并判断是否需要生成子目录下的索引文件(如果用户自己单独写了index.md文档就不会直接覆盖);

编写者在创建新的 Markdown 文档或者删除更新时,只需要再运行 generate-index.sh 脚本就可以自动更新知识库中所有目录的索引。

我修改的 generate-index.sh 自动生成脚本下载地址在这里(也可以从文章最后的版本库里检出):

generate-index.sh

这样修改之后 MDwiki 里就可以通过指向目录的索引文件以间接实现目录树功能(只是需要像 Windows 资源管理器那样一层层往下),同时这种方式生成的每个子目录的index.md索引文件也可以给 Wikitten 使用(Wikitten 自带目录树功能基本很少会用到索引文件)。

MDwiki 下访问目录的效果(使用脚本自动生成的索引文件):

mdwiki
mdwiki

Wikitten 的修改

由于 Wikitten 的基本功能都算可以用了,故我对 Wikitten 只有一些小改动:

  1. 同时兼容上面说明的 Markdown 文件开头的两种 YAML front matter 形式,可以实现和 MDwiki 下面基本相同的效果;
  2. 浏览具体目录页时 Wikitten 原有处理是直接提示用户从左边目录树中选择,这里我稍微修改为自动判断该目录下是否有index.md文件,存在则直接解释显示 Markdown 文档;
  3. 修正上面的 generate-index.sh 脚本生成的目录索引 Markdown 表格的显示效果。

同时部署 Wikitten 和 MDwiki

部署 Wikitten

Wikitten 部署参照其官网的说明一般没什么问题,只是 Wikitten 需要至少 PHP 5.3 版本,为此我还专门对 VPS 上 LNMP 套件里的 PHP 进行了升级,同时 Wikitten 也需要开启 PHP 的 fileinfo 模块。

Wikitten 需要 Web 服务器支持 rewrite,其版本库中自带了 Apache 适用的.htaccess文件,这里贴下适用于 nginx 的我的 Wiki 主域名wiki.zohead.com的 vhost 配置给大家一个参考:

 1server
 2{
 3    listen 80;
 4    server_name wiki.zohead.com;
 5    index index.html index.htm index.php default.html default.htm default.php;
 6    root /home/wwwroot/wiki.zohead.com;
 7    location ~* ^/static/(css|js|img|fonts)/.+.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt|swf|pdf|txt|bmp|eot|svg|ttf|woff|woff2)$ {
 8        access_log off;
 9        expires max;
10    }
11    location / {
12        rewrite ^(.*)$ /index.php last;
13    }
14    location ~ /index.php$ {
15        try_files $uri =404;
16        fastcgi_pass  unix:/tmp/php-cgi.sock;
17        include fastcgi.conf;
18    }
19}

其实也是比较简单的,参考 Wikitten 自带的.htaccess就可以修改过来,主要是下面的 rewrite 规则配置正确就可以了。

部署 MDwiki

这里为了和上面的 Wiki 主域名wiki.zohead.com区分,我为 MDwiki 站点单独搞了个 Wiki 备用域名mdwiki.zohead.com,这个的配置就非常简单了,只要最基本的 vhost 配置就可以了:

1server
2{
3    listen 80;
4    server_name mdwiki.zohead.com;
5    index index.html index.htm default.html default.htm;
6    root /home/wwwroot/wiki.zohead.com;
7}

可以看到这个 MDwiki 备用域名的主目录和上面的 Wikitten 是一样的,只是刚好把index.html给 MDwiki 使用,index.php给 Wikitten 使用。

综述

说了这么多,下面是我的初步 Wiki 知识库演示效果了。这样修改之后对于我来说最大的好处是当发现哪个用的不爽时可以无缝切换,毕竟现在这两个系统的目录结构和数据是完全共用的,哈哈。

Wikitten 动态主站请访问:http://wiki.zohead.com/
备用 MDwiki 纯静态站点请访问:http://mdwiki.zohead.com/

整个 Markdown 知识库目录我是使用 BitTorrent Sync 进行本机和 VPS 之间的同步,另外我把整合和修改过的 Wikitten 和 MDwiki 基础代码放到了一起,并在 GitHub 上建立了一个版本库:https://github.com/zohead/wikitten-and-mdwiki

大家有兴趣的话可以检出这个版本库自行修改部署哦,项目主页上也有一些介绍说明,如果你不需要同时支持 Wikitten 和 MDwiki 的话也可以自己取舍的,毕竟这个版本库里 MDwiki 的代码只有根目录下的index.html这一个文件。

Wikitten 的配置文件为根目录下的config.php,MDwiki 的配置文件为根目录下的config.json,还是比较一致的哈。

如果你只想要 Wikitten 系统的话那删除index.html、config.json文件即可,如果你只需要 MDwiki 那也只用保留index.html、config.json和generate-index.sh这几个文件。

注:原文来自zohead.com ,由于近期该网站打开有问题,通过浏览器收录的快照重新整理了一份备存。