<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Soul Of Free Loop &#187; Wiki</title>
	<atom:link href="https://zohead.com/archives/tag/wiki/feed" rel="self" type="application/rss+xml" />
	<link>https://zohead.com</link>
	<description>Uranus Zhou&#039;s Blog</description>
	<lastBuildDate>Sat, 19 Jul 2025 15:42:46 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.8</generator>
	<item>
		<title>使用lunr.js为Wiki系统增加全文搜索支持</title>
		<link>https://zohead.com/archives/wiki-lunr-js/</link>
		<comments>https://zohead.com/archives/wiki-lunr-js/#comments</comments>
		<pubDate>Mon, 09 Jan 2017 16:50:39 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[学习感悟]]></category>
		<category><![CDATA[Elasticlunr.js]]></category>
		<category><![CDATA[lunr.js]]></category>
		<category><![CDATA[MDwiki]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[Wiki]]></category>
		<category><![CDATA[Wikitten]]></category>
		<category><![CDATA[全文]]></category>
		<category><![CDATA[索引]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1338</guid>
		<description><![CDATA[搜索 Wiki 知识库的问题 今年早些时候我捣鼓了一个基于 Wikitten 和 MDwiki 的 个人知识库系统，我一般使用基于 PHP Wikitten 的 动态 Wiki 知识库，本地预览或者测试时可以用基于 MDwiki 的 静态 Wiki 知识库，两个配合使用并通过 BitTorrent Sync 与 VPS 进行数据同步，这样需要更新时也是很方便的。 我在实际使用中还是发现 Wikitten 的搜索功能比较薄弱，只支持通过文档或目录名称进行搜索（Wikitten 显示时是直接遍历 Wiki 文档的，出于效率考虑也不好直接进行目录遍历全文搜索）；MDwiki 则由于是纯静态实现，根本 [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="搜索-wiki-知识库的问题">搜索 Wiki 知识库的问题</h2>
<p>今年早些时候我捣鼓了一个基于 Wikitten 和 MDwiki 的 <a href="https://zohead.com/archives/wikitten-mdwiki/">个人知识库系统</a>，我一般使用基于 PHP Wikitten 的 <a href="https://wiki.zohead.com/" target="_blank">动态 Wiki 知识库</a>，本地预览或者测试时可以用基于 MDwiki 的 <a href="https://mdwiki.zohead.com/" target="_blank">静态 Wiki 知识库</a>，两个配合使用并通过 BitTorrent Sync 与 VPS 进行数据同步，这样需要更新时也是很方便的。</p>
<p>我在实际使用中还是发现 Wikitten 的搜索功能比较薄弱，只支持通过文档或目录名称进行搜索（Wikitten 显示时是直接遍历 Wiki 文档的，出于效率考虑也不好直接进行目录遍历全文搜索）；MDwiki 则由于是纯静态实现，根本没有搜索功能，通过我写的生成 Wiki 目录索引的脚本也只能一层层目录定位到 Wiki 文档，要想快速的搜索知识库内容暂时只能通过在本地运行 grep 等命令的方式。</p>
<h2 id="关于-lunrjs">关于 lunr.js</h2>
<p>最近我在看到 <a href="http://lunrjs.com/">lunr.js</a> 这个轻量级 JavaScript 全文搜索引擎之后，搜索 Wiki 知识库的问题也迎来了曙光。目前有一些基于 Hexo 之类静态博客框架的站点就是使用 lunr.js 实现了站内搜索功能。因为我考虑将 lunr.js 加入到 Wikitten 和 MDwiki 系统中以支持直接在线全文搜索。</p>
<p>lunr.js 的官方版本目前仍然不支持中文的分词器，其目前支持的语言列表在 <a href="https://github.com/MihaiValentin/lunr-languages">这里</a>。开始我考虑过使用 <a href="http://blog.csdn.net/watkinsong">wei song</a> 博主写的基于 lunr.js 的改进版 <a href="http://elasticlunr.com/">Elasticlunr.js</a>，作者介绍的 Elasticlunr.js 相比 lunr.js 可以实现更快的搜索速度和更小的索引文件，只是 Elasticlunr.js 同样也不支持中文搜索，还是暂且作罢。</p>
<p>最终我使用的是国内网友 <a href="http://blog.codepiano.com/">codepaino</a> 分享的支持中文的修改版 lunr.js，项目地址为：</p>
<p><a href="https://github.com/codepiano/lunr.js">https://github.com/codepiano/lunr.js</a></p>
<p>在 VPS 上安装修改版的 lunr.js 也还是比较简单的，首先 VPS 上需要有 node.js 环境（这里只介绍 Linux 版本的），下载修改版的 lunr.js：</p>
<pre class="brush: bash; title: ; notranslate">
root@zoserver:~# wget https://github.com/codepiano/lunr.js/raw/master/lunr.min.js
</pre>
<p>然后 npm 安装依赖的 nodejieba 库：</p>
<pre class="brush: bash; title: ; notranslate">
root@zoserver:~# npm install -g nodejieba
|
&gt; nodejieba@2.2.4 install /usr/lib/node_modules/nodejieba
&gt; node-gyp rebuild

gyp WARN EACCES user &quot;root&quot; does not have permission to access the dev dir &quot;/root/.node-gyp/4.6.1&quot;
gyp WARN EACCES attempting to reinstall using temporary dev dir &quot;/usr/lib/node_modules/nodejieba/.node-gyp&quot;
make: Entering directory `/usr/lib/node_modules/nodejieba/build'
  CXX(target) Release/obj.target/nodejieba/lib/index.o
  CXX(target) Release/obj.target/nodejieba/lib/nodejieba.o
  SOLINK_MODULE(target) Release/obj.target/nodejieba.node
  COPY Release/nodejieba.node
make: Leaving directory `/usr/lib/node_modules/nodejieba/build'
nodejieba@2.2.4 /usr/lib/node_modules/nodejieba
└── nan@2.3.5
</pre>
<h2 id="生成-wiki-搜索索引文件">生成 Wiki 搜索索引文件</h2>
<p>在线的 Wiki 系统在实际使用搜索功能时需要在浏览器前端加载 lunr.js 的搜索索引文件，为了方便生成整个 Wiki 知识库目录的所有 Markdown 文档的索引，我写了一个生成 Wiki 搜索索引文件的 node.js 程序。</p>
<p><strong>search.js</strong> 程序的功能非常简单，遍历 Wikitten 和 MDwiki 共用的 Wiki 文档目录（默认为 <code>library</code>），获取遍历到的 Wiki 文档的标题、关键字标签和文档内容（这三者搜索权重依次降低），然后使用 lunr.js 最终生成 JSON 格式的索引文件：</p>
<pre class="brush: jscript; title: search.js; notranslate">
var fs = require('fs'), removeMd = require('remove-markdown'), lunr = require('./static/js/lunr.min.js');

var md_index = lunr(function () {
	this.field('title');
	this.field('tags');
	this.field('body');
	this.ref('url');
});

function walk_dir(wdir, path, callback) {
	var dirList = fs.readdirSync(wdir + path);
	dirList.forEach(function(item) {
		if(fs.statSync(wdir + path + '/' + item).isDirectory())
			walk_dir(wdir, path + '/' + item, callback);
		else
			callback(wdir, path + '/' + item);
	});
}

function process_markdown(wdir, path) {
	var pos = path.lastIndexOf(&quot;.&quot;);
	if (pos &lt; 0) return;
	if (path.substr(pos) != &quot;.md&quot; &amp;&amp; path.substr(pos) != &quot;.markdown&quot;) return;
	var fpos = path.lastIndexOf(&quot;/&quot;);
	var title = (fpos &gt;= 0 ? path.substring(fpos + 1, pos) : path.substr(0, pos));

	// ignore navigation menu document
	if (path == &quot;/navigation.md&quot;) return;

	var has_front = false;
	var md_doc = {
		&quot;url&quot;: path,
		&quot;title&quot;: title,
		&quot;tags&quot;: &quot;&quot;
	};

	var data = fs.readFileSync(wdir + path, &quot;utf-8&quot;);
	// ignore auto generated index.md
	if (title == &quot;index&quot; &amp;&amp; data.indexOf(&quot;Auto-index of&quot;) &gt;= 0) return;

	// process front matter
	if (data.substr(0, 3) == &quot;```&quot;) {
		pos = data.substr(3).indexOf(&quot;```&quot;);
		if (pos &gt;= 0) {
			var front = JSON.parse(&quot;{&quot; + data.substr(3, pos) + &quot;}&quot;);
			has_front = true;
			if (&quot;title&quot; in front) md_doc.title = front.title;
			if (&quot;tags&quot; in front) md_doc.tags = front.tags.join(' ');
			md_doc.body = removeMd(data.substr(pos + 6));
		}
	}
	if (!has_front) md_doc.body = removeMd(data);
	md_index.add(md_doc);
}

if (process.argv.length &lt; 4) {
	console.log(&quot;Usage:\n&quot;);
	console.log(process.argv[0] + &quot; &quot; + process.argv[1] + &quot; Wiki-document-directory Search-index-file&quot;);
	console.log(process.argv[0] + &quot; &quot; + process.argv[1] + &quot; Search-index-file Keyword&quot;);
	process.exit(1);
} else if (!fs.existsSync(process.argv[2])) {
	console.log(&quot;Invalid Wiki-document-directory or Search-index-file: &quot; + process.argv[2]);
	process.exit(1);
}

if (fs.statSync(process.argv[2]).isDirectory()) {
	walk_dir(process.argv[2], &quot;&quot;, process_markdown);
	fs.writeFileSync(process.argv[3], JSON.stringify(md_index.toJSON()));
} else {
	md_index = lunr.Index.load(JSON.parse(fs.readFileSync(process.argv[2])));
	console.log(JSON.stringify(md_index.search(process.argv[3])));
}
</pre>
<blockquote>
<p><strong>提示</strong></p>
<p>为了方便 Wikitten 和 MDwiki 能同时使用 lunr.js，我把 <strong>search.js</strong> 程序引用的修改版 <code>lunr.min.js</code> 文件放到了 Wiki 程序主目录下的 <code>static/js</code> 文件夹，如需要的话可以自行修改。</p>
</blockquote>
<p>上面的程序在遍历 Markdown 文档时忽略了我之前写的自动生成子目录索引文档脚本 <code>generate-index.sh</code> 产生的 <code>index.md</code> 文档，另外也忽略了 MDwiki 专用的 <code>navigation.md</code> Wiki 系统菜单文档。</p>
<p><strong>search.js</strong> 程序使用了 <code>remove-markdown</code> 这个去掉 Markdown 格式的 npm 包，同样用 npm 安装即可：</p>
<pre class="brush: bash; title: ; notranslate">
root@zoserver:~# npm install -g remove-markdown
</pre>
<p>一般情况下直接在 Wiki 程序目录下运行 <strong>search.js</strong> 程序生成索引文件即可：</p>
<pre class="brush: bash; title: ; notranslate">
root@zoserver:/home/wiki# node search.js library search_index.json
</pre>
<p>最后上面的命令生成出来的 <code>search_index.json</code> 就是 lunr.js 格式的索引文件，我们可以直接放到 Wiki 程序主目录下。</p>
<p>经过实际测试目前我的 Wiki 目录一共包含 44 篇有效的 Markdown 文档，文件夹占用不到 500 KB，不过生成出来的 <code>search_index.json</code> 索引文件就已经接近 1.5 MB 了，浏览器访问索引文件时通过 gzip 压缩传输之后差不多 160 KB，还在我能接受的范围内。</p>
<p>另外你也可以使用 <strong>search.js</strong> 程序通过索引文件直接在本地进行关键字搜索：</p>
<pre class="brush: bash; title: ; notranslate">
root@zoserver:/home/wiki# node search.js search_index.json shell
[{&quot;ref&quot;:&quot;/技术/Android/Android Shell控制手机.md&quot;,&quot;score&quot;:0.21389728235059557},{&quot;ref&quot;:&quot;/技术/Linux/Shell/Shell进行TCP和UDP网络编程.md&quot;,&quot;score&quot;:0.2134705596450158},{&quot;ref&quot;:&quot;/技术/Linux/Shell/sed命令相关技巧.md&quot;,&quot;score&quot;:0.13650355812409723},{&quot;ref&quot;:&quot;/技术/Linux/Shell/vim操作技巧.md&quot;,&quot;score&quot;:0.1060635524797807},{&quot;ref&quot;:&quot;/技术/Windows/rundll32运行命令列表.md&quot;,&quot;score&quot;:0.035704080604386734},{&quot;ref&quot;:&quot;/技术/Windows/Windows注册表记录.md&quot;,&quot;score&quot;:0.0019103777768910307}]
</pre>
<h2 id="将-lunrjs-整合到-wiki-系统">将 lunr.js 整合到 Wiki 系统</h2>
<p>有了正确的搜索索引文件之后，我们就可以修改 Wikitten 和 MDwiki 程序将 lunr.js 搜索功能整合进来了。</p>
<p>下面 Wikitten 和 MDwiki 支持全文搜索的修改我已经提交到 <a href="https://github.com/zohead/wikitten-and-mdwiki">wikitten-and-mdwiki</a> 项目，提交记录可以参考 <a href="https://github.com/zohead/wikitten-and-mdwiki/commit/ea6d35aa038e6da064892c9091f767f323b7864b">这里</a>。</p>
<h3 id="wikitten-修改">Wikitten 修改</h3>
<p>由于 Wikitten 自带了按文档和目录名搜索的功能，我们只要给 Wikitten 增加 AJAX 加载 lunr.js 搜索索引文件并按关键字搜索的功能，最后使用 lunr.js 的搜索结果替换原来的即可。</p>
<p>Wikitten 默认只允许直接访问 <code>static</code> 子目录中的文件，我们需要修改对应的 Web 目录转发规则，这里只贴出 Nginx 服务器的配置（Apache 用户请自行修改 <code>.htaccess</code> 文件）：</p>
<pre class="brush: plain; title: ; notranslate">
server
{
	gzip on;
	gzip_min_length 1000;
	gzip_buffers 4 8k;
	gzip_types text/plain application/x-javascript text/css application/json application/xml text/javascript;

	location ~* ^/(robots.txt|search_index.json|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;
	}
}
</pre>
<p>location 规则指定对 Wiki 主目录下的 <code>robots.txt</code> 和 <code>search_index.json</code> 索引文件以及 <code>static</code> 子目录中的文件不经过 Wikitten 处理；另外为了提高索引文件的加载速度上面的配置中还开启了 gzip 压缩，MDwiki 也可以做同样的修改。</p>
<h3 id="mdwiki-修改">MDwiki 修改</h3>
<p>MDwiki 原本没有搜索功能，为了方便页面上使用，我在其专用的 <code>navigation.md</code> Wiki 系统菜单文档里增加了一个搜索菜单，这样所有 Wiki 文档页面就都能使用了：</p>
<hr size="1" />
<p>[&#x1f50d;]()<br />&nbsp;* # Search file name or content.<br />&nbsp;* [&lt;input id="search_input" type="text"/&gt;](#)</p>
<hr size="1" />
<p>搜索菜单显示效果如下：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442839/mdwiki-search-menu.png" alt="MDwiki 搜索菜单" title="MDwiki 搜索菜单"></p>
<p>然后在 MDwiki 对应的 <code>index.html</code> 中增加搜索处理代码：</p>
<pre class="brush: jscript; title: index.html; notranslate">
&lt;script type=&quot;text/javascript&quot; src=&quot;static/js/lunr.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
var search_indexes = null;

function doSearch(query) {
	if (search_indexes == null) return;
	var s_res = search_indexes.search(query);
	var t_html = '&lt;ul&gt;';
	for (var i = 0; i &lt; s_res.length; i++) {
		var t_pos = s_res[i].ref.lastIndexOf('/');
		t_html += '&lt;li&gt;&lt;a href=&quot;#!' + s_res[i].ref + '&quot;&gt;' + (t_pos &gt;= 0 ? s_res[i].ref.substr(t_pos + 1) : s_res[i].ref) + '&lt;/a&gt;&lt;/li&gt;';
	}
	t_html += '&lt;/ul&gt;';
	$('#search-result-body').html(t_html);
	$('#search-result-label').html('Search result for: ' + query);
	$('#search-result').modal('show');
}

function search_content(query) {
	if (search_indexes == null) {
		$.getJSON(&quot;search_index.json&quot;, function(data){
			if (data != null) search_indexes = lunr.Index.load(data);
			doSearch(query);
		});
	} else
		doSearch(query);
}

$(document).bind('DOMNodeInserted', function(e) {
	if ($('#search_input').length &lt;= 0) return;
	$(document).unbind('DOMNodeInserted');

	$('#search_input').bind('click', function(event) {
		event.stopPropagation();
		return false;
	});
	$('#search_input').bind('keypress', function(event){
		if (event.keyCode == '13')
			search_content($(this).val());
	});
});
&lt;/script&gt;

&lt;div class=&quot;modal fade&quot; id=&quot;search-result&quot; tabindex=&quot;-1&quot; role=&quot;dialog&quot; aria-labelledby=&quot;search-result-label&quot; aria-hidden=&quot;true&quot;&gt;
&lt;div class=&quot;modal-dialog&quot;&gt;
&lt;div class=&quot;modal-content&quot;&gt;
&lt;div class=&quot;modal-header&quot;&gt;
&lt;button type=&quot;button&quot; class=&quot;close&quot; data-dismiss=&quot;modal&quot; aria-hidden=&quot;true&quot;&gt;&amp;#x274c;&lt;/button&gt;
&lt;h4 class=&quot;modal-title&quot; id=&quot;search-result-label&quot;&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;div class=&quot;modal-body&quot; id=&quot;search-result-body&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>上面对搜索输入框的点击事件增加了处理，防止点击时 Bootstrap 的搜索菜单项丢失，在输入框中输入关键字回车才加载索引文件并使用 lunr.js 进行搜索。</p>
<p>MDwiki 的搜索效果如下图所示：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442840/mdwiki-search-result.png" alt="MDwiki 搜索结果" title="MDwiki 搜索结果"></p>
<p>点击搜索结果中的文档名称就会跳转显示对应 Wiki 文档内容。</p>
<h2 id="总结">总结</h2>
<p>经过对 Wikitten 和 MDwiki 进行修改，目前 Wiki 知识库的显示和查询效果基本都能满足我的需求了。虽然还存在搜索索引文件体积稍大的隐患，后续也可以考虑使用 Elasticlunr.js 或者其它方式进行改进咯。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/wiki-lunr-js/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>整合Wikitten和MDwiki搭建个人知识库</title>
		<link>https://zohead.com/archives/wikitten-mdwiki/</link>
		<comments>https://zohead.com/archives/wikitten-mdwiki/#comments</comments>
		<pubDate>Wed, 16 Mar 2016 08:43:49 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[学习感悟]]></category>
		<category><![CDATA[Evernote]]></category>
		<category><![CDATA[Front Matter]]></category>
		<category><![CDATA[Markdown]]></category>
		<category><![CDATA[MDwiki]]></category>
		<category><![CDATA[Wiki]]></category>
		<category><![CDATA[Wikitten]]></category>
		<category><![CDATA[知识管理]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1193</guid>
		<description><![CDATA[我的知识库管理现状 一段时间以来我都算是 Pocket 和 Evernote 的忠实用户，Pocket 用于采集网上看到的想要稍后预读的文章，遇到比较好的内容觉得该记录下来的就记录在 Evernote 里，这样 Evernote 基本被我用来做个人知识库了，平常比较零散的个人信息之类的则记录到 Google Keep 中。 最近在 Android 手机上碰到几次比较奇怪的 Evernote 数据库错误之后还是觉得 Evernote 虽然有相对还算好用的离线、同步、搜索等功能，但也有一些问题： 众所周知的编辑功能确实比较烂，不支持 Markdown，对于表格等稍微复杂点的内容那编辑效果简直惨不忍 [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="我的知识库管理现状">我的知识库管理现状</h2>
<p>一段时间以来我都算是 <a href="https://getpocket.com/">Pocket</a> 和 <a href="https://www.evernote.com/">Evernote</a> 的忠实用户，Pocket 用于采集网上看到的想要稍后预读的文章，遇到比较好的内容觉得该记录下来的就记录在 Evernote 里，这样 Evernote 基本被我用来做个人知识库了，平常比较零散的个人信息之类的则记录到 <a href="https://keep.google.com/">Google Keep</a> 中。</p>
<p>最近在 Android 手机上碰到几次比较奇怪的 Evernote 数据库错误之后还是觉得 Evernote 虽然有相对还算好用的离线、同步、搜索等功能，但也有一些问题：</p>
<ul>
<li>众所周知的编辑功能确实比较烂，不支持 Markdown，对于表格等稍微复杂点的内容那编辑效果简直惨不忍睹；</li>
<li>只有笔记本组和笔记本这两层结构对于我来说始终还是觉得不够；</li>
<li>客户端里所有笔记数据都放在 SQLite 数据库文件感觉稳定性一般。</li>
</ul>
<p>再加上最近 Evernote 这头大象给人的前景似乎一直不太好，所以我就想找到一个相对比较简单优雅的个人知识库系统，最好是能直接支持 Markdown 格式，不需要复杂的搭建步骤，能方便的在我的 VPS 和本地跑起来，当然 Evernote 我暂时还是不会弃用的。</p>
<h2 id="mdwiki-和-wikitten-对比">MDwiki 和 Wikitten 对比</h2>
<p>我找了几个比较流行的 Wiki 系统，开始就跳过了 MediaWiki 这种看起来略复杂的系统，也简单看了看很多网友推荐的 DokuWiki，甚至还有 TiddlyWiki 这种直接单文件的 Wiki 方式，初步考虑后想用 MDwiki 这个基于 Markdown 而且超级简单的纯静态 Wiki 系统。</p>
<p>MDwiki 相对于其它 Wiki 系统的最大好处是其单纯使用浏览器就可以解析 Markdown 文档，部署可算是超级简单了，VPS 上只要有 Web 服务器就可以访问（纯静态不需要 PHP 支持），甚至在 PC 本地也可以直接打开（虽然 IE11 和 Chrome 浏览器上已经不支持请求本地文件了）。</p>
<p>按照 <a href="http://www.mdwiki.info/">MDwiki</a> 官网的介绍生成一个 Wiki 主页还是非常简单的，网上的说明也比较多这里就不介绍了，如果知识库内容比较少用 MDwiki 还是很方便的，但我想稍微增加一些内容时就发现了 MDwiki 一些明显的不足：</p>
<ul>
<li>导航菜单只支持两层，这个是 MDwiki 使用的 Bootstrap 的限制，而且如果有很多层目录，每个目录下又有不少 Markdown 文档，直接全部放在导航菜单里那体验也是比较糟糕的；</li>
<li>由于纯静态的限制，如果在某个目录下增加了 Markdown 文档，那就需要同步修改导航菜单，或者在其它页面里加上指向新文档的链接，这样如果需要动态修改更新实在有点麻烦；</li>
<li>同样由于纯静态的限制，基本没有办法实现搜索功能，如果后续知识库文章较多那还需要同步下来对文件夹进行搜索；</li>
<li>MDwiki 只有一个主 html 文件，切换文章是用 AJAX 异步加载 Markdown 文档然后解析显示的，这样就意味着 MDwiki 对于搜索引擎来说是非常不友好的，基本没有实际可用内容。</li>
</ul>
<p>因此我还是想实现既能兼顾 MDwiki 直接使用 Markdown 的方便之处又能解决上面列出的问题，最后还是找到了 <a href="http://wikitten.vizuina.com/">Wikitten</a> 这个用 PHP 实现的 Wiki 系统。</p>
<p>Wikitten 与 MDwiki 不同之处在于 Markdown 文档是由 PHP 程序解析并直接转换为 HTML 返回给浏览器的，而且配置好知识库目录之后访问就可以显示完整的目录树（有修改更新时也不用手工修改其它 Markdown 文件了），也有比较简单的搜索功能，可以直接把源代码文件以比较漂亮的形式显示出来。</p>
<p>我部署的 Wikitten 系统运行效果图如下：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442965/wikitten-ui.png" alt="Wikitten 界面" title="Wikitten 界面"></p>
<p>综合考虑之后我准备对 Wikitten 和 MDwiki 做出少量修改，以实现在我的 VPS 服务器上主要还是用 Wikitten 来动态展示，需要在本地直接查看修改时也可以用上 MDwiki，这样就能兼顾两者的优点了。</p>
<h2 id="mdwiki-的修改">MDwiki 的修改</h2>
<p>对 MDwiki 的修改主要考虑到要能方便的找到目录树的 Markdown 文档，修改如下：</p>
<ol>
<li>把 Markdown 文档放到单独的目录中，我是直接改成放到和 <code>mdwiki.html</code> 主文件相同路径的 <code>library</code> 目录，这与 Wikitten 的默认知识库目录是一致的，这样 Wikitten 和 MDwiki 就可以共用 Markdown 文档了；</li>
<li>
<p>支持识别 Markdown 文件开头添加的 <a href="http://jekyllrb.com/docs/frontmatter/">YAML front matter</a> 数据，front matter 可以用来表示 Markdown 文档的标题、作者、标签等信息；</p>
<blockquote>
<p><strong>提示</strong></p>
<p>MDwiki 新增加的 font matter 支持需要修改 <code>config.json</code> 配置文件增加 <code>"parseHeader": true</code> 进行开启。</p>
</blockquote>
<p>Wikitten 是直接支持 YAML front matter 的并能动态生成到 HTML 数据中的，常见的 front matter 数据格式是这样的：</p>
<pre class="brush: plain; title: ; notranslate">
---
&quot;title&quot;: &quot;Wiki site&quot;,
&quot;tags&quot;: [&quot;tag1&quot;, &quot;tag2&quot;, &quot;tag3&quot;],
&quot;author&quot;: &quot;xxx&quot;
---
</pre>
<blockquote>
<p><strong>注意</strong></p>
<p>上面的格式中开头和结束是 3 个横线，而且开头以及结束的横线和中间的实际 front matter（也就是 meta data）内容之间只有一个回车哦；下面修改后的格式也是类似的。</p>
</blockquote>
<p>不过上面这种格式很多 Markdown 编辑器却是不支持的显示有问题，这里我改成了和 MDwiki 暂未发布的开发版本中一致的形式：</p>
<pre class="brush: plain; title: ; notranslate">
```
&quot;title&quot;: &quot;Wiki site&quot;,
&quot;tags&quot;: [&quot;tag1&quot;, &quot;tag2&quot;, &quot;tag3&quot;],
&quot;author&quot;: &quot;xxx&quot;
```
</pre>
</li>
<li>
<p>我写了一个自动生成 Markdown 知识库目录下面所有子目录索引文件 <code>index.md</code> 的 shell 脚本 <strong><code>generate-index.sh</code></strong> 给 MDwiki 使用，使用起来也很简单：</p>
<pre class="brush: bash; title: ; notranslate">
(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
</pre>
<p><strong><code>generate-index.sh</code></strong> 脚本会查找输入的 Markdown 知识库目录并判断是否需要生成子目录下的索引文件（如果用户自己单独写了 <code>index.md</code> 文档就不会直接覆盖）；</p>
<p>编写者在创建新的 Markdown 文档或者删除更新时，只需要再运行 <strong><code>generate-index.sh</code></strong> 脚本就可以自动更新知识库中所有目录的索引。</p>
<p>我修改的 <strong><code>generate-index.sh</code></strong> 自动生成脚本下载地址在这里（也可以从文章最后的版本库里检出）： <br />
<a href="http://mdwiki.zohead.com/generate-index.sh">http://mdwiki.zohead.com/generate-index.sh</a></p>
</li>
</ol>
<p>这样修改之后 MDwiki 里就可以通过指向目录的索引文件以间接实现目录树功能（只是需要像 Windows 资源管理器那样一层层往下），同时这种方式生成的每个子目录的 <code>index.md</code> 索引文件也可以给 Wikitten 使用（Wikitten 自带目录树功能基本很少会用到索引文件）。</p>
<p>MDwiki 下访问目录的效果（使用脚本自动生成的索引文件）：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442839/mdwiki-dirindex.png" alt="MDwiki 目录索引" title="MDwiki 目录索引"></p>
<h2 id="wikitten-的修改">Wikitten 的修改</h2>
<p>由于 Wikitten 的基本功能都算可以用了，故我对 Wikitten 只有一些小改动：</p>
<ol>
<li>同时兼容上面说明的 Markdown 文件开头的两种 YAML front matter 形式，可以实现和 MDwiki 下面基本相同的效果；</li>
<li>浏览具体目录页时 Wikitten 原有处理是直接提示用户从左边目录树中选择，这里我稍微修改为自动判断该目录下是否有 <code>index.md</code> 文件，存在则直接解释显示 Markdown 文档；</li>
<li>修正上面的 <strong><code>generate-index.sh</code></strong> 脚本生成的目录索引 Markdown 表格的显示效果。</li>
</ol>
<h2 id="同时部署-wikitten-和-mdwiki">同时部署 Wikitten 和 MDwiki</h2>
<h3 id="部署-wikitten">部署 Wikitten</h3>
<p>Wikitten 部署参照其官网的说明一般没什么问题，只是 Wikitten 需要至少 PHP 5.3 版本，为此我还专门对 VPS 上 LNMP 套件里的 PHP 进行了升级，同时 Wikitten 也需要开启 PHP 的 fileinfo 模块。</p>
<p>Wikitten 需要 Web 服务器支持 rewrite，其版本库中自带了 Apache 适用的 <code>.htaccess</code> 文件，这里贴下适用于 nginx 的我的 Wiki 主域名 <code>wiki.zohead.com</code> 的 vhost 配置给大家一个参考：</p>
<pre class="brush: plain; title: ; notranslate">
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;
	}
}
</pre>
<p>其实也是比较简单的，参考 Wikitten 自带的 <code>.htaccess</code> 就可以修改过来，主要是下面的 rewrite 规则配置正确就可以了。</p>
<h3 id="部署-mdwiki">部署 MDwiki</h3>
<p>这里为了和上面的 Wiki 主域名 <code>wiki.zohead.com</code> 区分，我为 MDwiki 站点单独搞了个 Wiki 备用域名 <code>mdwiki.zohead.com</code>，这个的配置就非常简单了，只要最基本的 vhost 配置就可以了：</p>
<pre class="brush: plain; title: ; notranslate">
server
{
	listen 80;

	server_name mdwiki.zohead.com;
	index index.html index.htm default.html default.htm;
	root /home/wwwroot/wiki.zohead.com;
}
</pre>
<p>可以看到这个 MDwiki 备用域名的主目录和上面的 Wikitten 是一样的，只是刚好把 <code>index.html</code> 给 MDwiki 使用，<code>index.php</code> 给 Wikitten 使用。</p>
<h2 id="综述">综述</h2>
<p>说了这么多，下面是我的初步 Wiki 知识库演示效果了。这样修改之后对于我来说最大的好处是当发现哪个用的不爽时可以无缝切换，毕竟现在这两个系统的目录结构和数据是完全共用的，哈哈。</p>
<p>Wikitten 动态主站请访问：</p>
<p><a href="http://wiki.zohead.com/">http://wiki.zohead.com/</a></p>
<p>备用 MDwiki 纯静态站点请访问：</p>
<p><a href="http://mdwiki.zohead.com/">http://mdwiki.zohead.com/</a></p>
<p>整个 Markdown 知识库目录我是使用 BitTorrent Sync 进行本机和 VPS 之间的同步，另外我把整合和修改过的 Wikitten 和 MDwiki 基础代码放到了一起，并在 GitHub 上建立了一个版本库：</p>
<p><a href="https://github.com/zohead/wikitten-and-mdwiki">https://github.com/zohead/wikitten-and-mdwiki</a></p>
<p>大家有兴趣的话可以检出这个版本库自行修改部署哦，项目主页上也有一些介绍说明，如果你不需要同时支持 Wikitten 和 MDwiki 的话也可以自己取舍的，毕竟这个版本库里 MDwiki 的代码只有根目录下的 <code>index.html</code> 这一个文件。</p>
<p>Wikitten 的配置文件为根目录下的 <code>config.php</code>，MDwiki 的配置文件为根目录下的 <code>config.json</code>，还是比较一致的哈。</p>
<p>如果你只想要 Wikitten 系统的话那删除 <code>index.html</code>、<code>config.json</code> 文件即可，如果你只需要 MDwiki 那也只用保留 <code>index.html</code>、<code>config.json</code> 和 <code>generate-index.sh</code> 这几个文件。</p>
<p>最后本文及对应版本库中有任何问题欢迎提出指正哦，祝大家玩的开心 ^_^。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/wikitten-mdwiki/feed/</wfw:commentRss>
		<slash:comments>52</slash:comments>
		</item>
	</channel>
</rss>
