整合Wikitten和MDwiki搭建个人知识库

我的知识库管理现状

一段时间以来我都算是 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 界面

综合考虑之后我准备对 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 数据格式是这样的:

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

    注意

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

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

    ```
    "title": "Wiki site",
    "tags": ["tag1", "tag2", "tag3"],
    "author": "xxx"
    ```
    
  3. 我写了一个自动生成 Markdown 知识库目录下面所有子目录索引文件 index.md 的 shell 脚本 generate-index.sh 给 MDwiki 使用,使用起来也很简单:

    (trusty)zzm@localhost:~/wiki$ ./generate-index.sh library
    Generate index file: library/生活/index.md
    Generate index file: library/阅读/index.md
    Generate index file: library/技术/网络/index.md
    Generate index file: library/技术/硬件/USB/index.md
    Generate index file: library/技术/硬件/PCI-E/index.md
    Generate index file: library/技术/硬件/index.md
    Generate index file: library/技术/存储/index.md
    Generate index file: library/技术/index.md
    Generate index file: library/技术/音视频/index.md
    Generate index file: library/技术/Linux/内存管理/index.md
    Generate index file: library/技术/Linux/文件系统/index.md
    Generate index file: library/技术/Linux/开发工具/index.md
    Generate index file: library/技术/Linux/index.md
    Generate index file: library/技术/Android/index.md
    Generate index file: library/技术/Docker/index.md
    

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

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

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

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

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 配置给大家一个参考:

server
{
	listen 80;

	server_name wiki.zohead.com;
	index index.html index.htm index.php default.html default.htm default.php;
	root /home/wwwroot/wiki.zohead.com;

	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)$ {
		access_log off;
		expires max;
	}
	location / {
		rewrite ^(.*)$ /index.php last;
	}
	location ~ /index.php$ {
		try_files $uri =404;
		fastcgi_pass  unix:/tmp/php-cgi.sock;
		include fastcgi.conf;
	}
}

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

部署 MDwiki

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

server
{
	listen 80;

	server_name mdwiki.zohead.com;
	index index.html index.htm default.html default.htm;
	root /home/wwwroot/wiki.zohead.com;
}

可以看到这个 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.htmlconfig.json 文件即可,如果你只需要 MDwiki 那也只用保留 index.htmlconfig.jsongenerate-index.sh 这几个文件。

最后本文及对应版本库中有任何问题欢迎提出指正哦,祝大家玩的开心 ^_^。

  1. Unee Wang:

    哥tiddlywiki有桌面端,https://github.com/Jermolene/TiddlyDesktop 不过tiddly已弃,没有mdwiki灵活

  2. Uranus Zhou:

    这竟然是个专门给TiddlyWiki搞的浏览器~~~

  3. Unee Wang:

    没有转载,感觉不合适^~^

  4. Uranus Zhou:

    Wiki文档内容是直接转载别人的文章?这个估计得找一些网页转markdown的工具,或者偷懒点里面html内嵌别人网址,哈哈

  5. Leyar:

    开始关注这个东西才发现还是有蛮多个人在用耶 ?
    看来我是真的要找时间研究研究。

  6. Uranus Zhou:

    现在嫌Evernote有点慢准备把笔记用Markdown导到这个Wiki系统里,
    私人点的信息现在就临时记录到Google Keep咯

  7. Unee Wang:

    哈哈,我还是手动更新index,可以在首页里随便加点简介。你这脚本用来发布博客很合适啊。
    我手机里也有一套,通过ksweb就能用浏览器打开了

  8. Uranus Zhou:

    写这个脚本主要还是因为懒 ^_^,我建了好多子目录,实在不想哪天加了一篇Markdown文章就去修改index.md~~~

  9. flydream:

    请问,wikitten如何能显示中文目录名呢?我的library目录中如果添加一个中文目录,左侧tree区域显示的就是乱码,不知道你的演示程序是怎么做到显示正确的中文目录名?
    第二个就是,config.php中library如何自定义为其他目录呢?我换成别的,都报错。

  10. Uranus Zhou:

    估计是要UTF-8编码的,我都用的Linux环境,你那中文目录不行是不是在Windows下测试的?
    config.php中的LIBRARY用绝对路径就可以了

  11. flydream:

    嗯。我的是windows环境。windows环境下新建目录名,如何用utf-8编码呢?
    config.php的library我用绝对路径也不行,如:E:\www\wiki\wikitten\doc,\www\wiki\wikitten\doc,/www/wiki/wikitten/doc,这些都不行。愁人~~

  12. Uranus Zhou:

    Windows上可以用一些工具建UTF-8的目录名,但这样在资源管理器里又是乱码了,倒也可以改wikitten代码转换编码,估计原作者就没考虑Windows需求 ::>_<::
    LIBRARY那做了转义吧?如果在wikitten当前目录下也可以直接改php代码把library改成你要用的doc目录

  13. 依云:

    我就用的 MediaWiki =w=
    多年的使用经历表明它安装简便、好用,稳定可靠。当然装扩展得手动一个个地装比较烦(Arch 源/AUR 里没有包)。另外就是用一些测试性的特性时容易出问题(比如 PostgreSQL)。

  14. Uranus Zhou:

    MediaWiki 毕竟还算是久经考验的 Wiki 系统哈,我搞 MDwiki 这种主要还是想直接用目录树形式管理内容不想搞数据库咯

  15. 依云:

    嗯。有兴趣你也可以试试 gitit,纯文本 + git,支持多种标记语言的。

  16. Uranus Zhou:

    gitit还真是开始就看过呢,嫌配置稍微复杂了点,其实主要还是因为不熟悉Haskell ╮(╯_╰)╭

  17. chinos:

    请问下你是用的哪款支持markdown的软件来更新wiki呢?既是如何线下更新wikitten。
    每新建一个page都要手动上传到ftp吗?
    望指教 谢谢!~

  18. chinos:

    我想到一个办法就是用 dropbox或者btsync同步本地和vps的libarary文件夹,不知道博主是不是这种方法?

  19. Uranus Zhou:

    我是用btsync同步到VPS的,
    另外也用 Zed 编辑器,这个在VPS上运行一个程序之后就可以直接远程编辑

  20. Frederic:

    请问如何使用bittorrent sync与VPS同步?

  21. Uranus Zhou:

    VPS和客户端上都安装BTSync,在VPS上共享一个目录后就可以用了,还是比较简单的

  22. owen:

    为啥不保留 mdwiki 的 Toc 啊,内容长的时候不是更方便吗

  23. Uranus Zhou:

    这边倒没改现在就支持的呢,左边菜单会自动显示Markdown目录,不过好像默认只支持到 h2,再下层就不显示了

  24. netawater:

    请问手机方便访问编辑这个wiki系统吗?谢谢!

  25. Uranus Zhou:

    手机可以访问,编辑只能用Markdown编辑器之后通过BTSync之类的工具进行同步了。

  26. dxbtech:

    正在部署mdwiki,navigation.md怎么写,在doc上面没有找到说明,想请教下

  27. dxbtech:

    https://github.com/Dynalon/mdwiki/issues/250
    找到啦,自答一下

  28. netawater:

    请问你怎么讲evernote的笔记转过来的。evernote只能导出成html格式,谢谢!

  29. Uranus Zhou:

    是这个,我修改的 mdwiki 就是在 navigation.md 里加了个搜索功能。

  30. Uranus Zhou:

    这个还真没研究过,网上一些通过 Pandoc 这种工具将 html 转为 markdown 的方法。

  31. Knlvz:

    你好,我想请教个问题,页面能显示出来了,标题和页面内容的中文能正确显示,只有左侧栏的中文目录名是乱码,这是什么原因导致的?网上查了好久没找到.

  32. Uranus Zhou:

    你是用的 MDwiki 还是 Wikitten?
    MDwiki 的话左侧显示的是页面里的 Markdown h2 二级标题;
    如果是 Wikitten,那估计是中文目录名不是 UTF-8 编码的,你的服务器是用 Windows 的?

  33. Knlvz:

    是的,windows 2008r2的,今天早上我测试下不同的环境,用wnmp3.0.1来运行居然显示正常,如果使用wnmp3.1.0和wamp3.0.6是不正常的,会出现乱码,这个会和环境配置有关嘛?不知有没有解决方法?谢谢

  34. Knlvz:

    还有个问题就是,看了下你这篇全文搜索文章,有点疑惑,如果我在windows环境下该如何实现?也是需要安装node.js吗?那个搜索索引文件search_index.json是自动生成的还是得手动用命令执行一次的?

  35. Knlvz:

    对了,我是用wikitten,我似乎找到原因了,我把php替换成高于7.1以上的版本就显示正常。但还不清楚到底是因为那个参数或者函数的原因。之前我测试wnmp3.1.0版本时可能没有配置好,今晚测试的时候是正常的。

    目前就差全文搜索了,还是上面疑问,windows下是否需要安装node.js?基本步骤是否为安装node.js,配置nginx参数,命令生成search_index.json?请指点下,谢谢。

  36. Uranus Zhou:

    Windows 环境也需要 node.js 支持的,可惜 Windows 2008 不支持 WSL Linux 子系统,不然安装 node.js 倒挺简单的。
    search_index.json 文件是手工生成的,如果要支持自动生成,有的编辑器可以设置文档目录修改之后自动执行相应的命令。

  37. Uranus Zhou:

    Wikitten 在 Windows 上是会有问题的,主要文件名默认都是用的 UTF-8 编码,PHP 7.1 开始支持在 Windows 上使用 UTF-8 的文件和路径名了:
    PHP 7.1 更新说明

  38. Wanicca:

    正在配置,有一个很愁的疑问不知道怎么解决。我是用nginx配置的,不知道怎么修改能让wikitten的library设置到网页根目录以外。现在只能设置到根目录以内,否则无法访问。

  39. Uranus Zhou:

    这个不行哦,是 nginx web 服务器的安全限制,不然能直接访问外面目录就太不安全咯。

  40. wanicca:

    谢谢你,我已经解决了,我没让它直接访问外部目录而是通过一个符号链接访问过去的,但是这样还是需要改nginx关于cgi的配置。不知道这样会不会带来安全问题……不过我目前只是个人使用,暂时全站都需要http验证。
    感觉wikitten的代码结构确实挺简单的,还有很多可以魔改得更顺心的地方,可惜作者多年不开发了。目前我正在研究怎么让文件树里不显示特定文件夹,把图片藏进去^_^。

  41. Uranus Zhou:

    符号链接一般服务器默认应该也不允许;
    wikitten 不复杂,改起来还是比较简单的。

  42. gentao:

    我的需求和你很像耶。^_^

    我本地通过typora写.md文件,通过同步工具syncthing直接同步到项目library下,确实很方便。

    但是发现一个问题,wikitten使用的是michelf的php-markdown渲染器,本地typora支持Github的GFM语法,传上去效果不好。现在比较好的PHP markdown渲染器是parsedown,搞了半天没成功。

    不知博主有没兴趣研究一下替换渲染器成parsedown?

  43. Uranus Zhou:

    GitHub 项目主页上好像很早就有人提过更换渲染引擎,最近俺估计也没空改这个咯。

    看 Wikitten 代码结构,你修改 renderers 里的渲染代码有什么问题?可以在 GitHub 里提 issue 描述下问题让作者也协助看看呢。

  44. Uranus Zhou:

    看起来似乎只要把 renderers 里的调用换掉就行,我有空试试看。

  45. pgunf:

    搜索Wiki工具时找到这里,是我想要的简洁干净的个人知识管理工具,感谢!
    大佬,渲染引擎更换成功了么?我这这边也是用typora写同步过去,默认的渲染引擎表格渲染效果不太好!

  46. Uranus Zhou:

    初步尝试替换 Wikitten 渲染引擎为 Parsedown,似乎也比较简单:

    1. 下载发布版本的 Parsedown.php 放到 renderers/Markdown 目录,
    2. 修改 renderers/Markdown.php 文件先注释原来的代码,再增加:
      require_once dirname(__FILE__) . '/Markdown/Parsedown.php';
    3. 修改 wiki.php 文件,将 \Michelf\MarkdownExtra::defaultTransform 替换成 Parsedown::instance()->text 就可以了。

    感觉表格渲染效果也一般,可能还要改一下相关的 CSS。

  47. Uranus Zhou:

    简单替换 Parsedown 的修改步骤我贴在下面了,可以参考一下,显示效果可能还需要改一下。

  48. pgunf:

    感谢,根据你给的方法更换了渲染引擎,修改了一些CSS代码,我制作了docker镜像,部署在我的黑群晖里面,文件用Drive 同步到本地,本地使用Typora编辑!舒服,哈哈,可以抛弃网易云笔记了!
    这个是截图:

    有需要的朋友,docker镜像:https://hub.docker.com/r/leonyff/wikitten

  49. pgunf:

    截图没出来!
    ![image.png](https://i.loli.net/2019/10/19/UFn8CZzDtXqLEk5.png)

  50. Uranus Zhou:

    看起来确实改了 CSS 比 Wikiteen 自带的好看多了 ^_^

  51. pgunf:

    又遇到点问题,来请教下,我对php不熟悉,我在wikitten中添加了中添加了一些代码片段文件,可能是应为编码的问题,在网页显示中代码片段中的中文注释部分都是乱码!请教下,这个要怎么解决呢?
    https://i.loli.net/2019/10/31/vdCoqgUH8P1KGuO.png

  52. Uranus Zhou:

    这个估计是因为 Windows bat 脚本很少使用 UTF-8 编码的原因吧?很多都是 GB2312 的。
    可以用文本编辑器把 bat 另存为 UTF-8 编码看看了。





*