最近,高考互助组成立并进入试运营阶段,产生了一定量的工作成果。
HackMD 在很多方面令人满意,从手感良好的 markdown 编辑器到与 Github 手动同步,这个极客风格的多人文档协同工具给我留下了不错的印象。
然而,它有两个不足之处:
- 国内无法访问。由于天朝特殊的网络环境,服务器在国外的 HackMD 在中国完全无法访问。虽然编辑者可以科学上网,但读者未必有这个条件。
- 无法全文搜索。查重等工作需要通过全文搜索来开展,尽管可以借用本地编辑器来完成,但终究不够方便。
于是我花费一个下午的时间,搭建了高考文档,以解决以上两个问题。
框架选取
最终选择了 Docsify,有如下优点:
- 方便快捷。单文件部署,直接渲染 markdown 文件,无需额外工作。
- 支持全文搜索。
- 静态化部署,无需服务器。
- PWA 支持,一定程度上缓解海外服务器访问缓慢的问题。
最大的痛点是没有开箱即用的 MathJax,只找到了一个 KaTeX 的插件,然而试了一下发现 mhchem 宏包需要额外配置。我发现我不会配置,于是作罢,干脆不渲染数学公式了。
相信各位读者一定能裸眼渲染 LaTeX 公式的。
部署
部署 Docsify 相对简单,尽管折腾各种问题消耗了一定的时间,但最后发现折腾不出什么来就直接轻装上阵了。
部署方法:在根目录下新建 index.html
,将官方文档中的示例代码拷贝进去。
做了一些基础的配置:
- 更换主题,支持黑夜模式。
- 添加全文搜索插件。
- 添加折叠目录插件。
- 开启 PWA
最终大概长这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>高考文档</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-darklight-theme@latest/dist/style.min.css" title="docsify-darklight-theme" type="text/css"/>
</head>
<body>
<div id="app"></div>
<script>
window.$docsify = {
name: '高考',
repo: 'gaokao-team/GaokaoNote',
loadSidebar: true,
subMaxLevel: 2,
search: 'auto',
}
</script>
<!-- Docsify v4 -->
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-darklight-theme@latest/dist/index.min.js" type="text/javascript"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-sidebar-collapse/dist/docsify-sidebar-collapse.min.js"></script>
<script>
if (typeof navigator.serviceWorker !== 'undefined') {
navigator.serviceWorker.register('sw.js')
}
</script>
</body>
</html>
|
侧边栏目录
Docsify 不能自动获取子文件夹下的文件来生成目录。
因此必须使用某些工具来手动生成 _sidebar.md
文件,才能得到可用的目录。
然而现有的工具都是由文件名生成目录,而我希望以文章中的一级标题作为名称来生成。
迫不得已,现学现卖,拿我破烂的 C++ 技术栈来做这个事情。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#include <iostream>
#include <fstream>
#include <string>
#include <filesystem>
using std::endl;
using std::ofstream;
using std::ifstream;
using std::string;
using std::filesystem::directory_iterator;
int main()
{
string path = std::filesystem::current_path();
ofstream output;
output.open(path + "/_sidebar.md");
for (const auto & sub : directory_iterator(path))
{
if (!sub.is_directory()) continue;
if (sub.path().filename() == ".git" || sub.path().filename() == ".vscode") continue;
output << " - " << sub.path().filename().generic_string() << endl;
for (const auto &file : directory_iterator(sub.path()))
{
if(file.path().extension() == ".md")
{
ifstream reader;
reader.open(file.path());
string now;
do { reader >> now; }while(now != "#");
getline(reader,now);
while(now.back() == ' ') now.pop_back();
while(now.front() == ' ') now.erase(now.begin());
//now is the title of the file
output << " - [" << now << "](/" << sub.path().filename().generic_string()
<< '/' << file.path().filename().generic_string() << ')' << endl;
reader.close();
}
}
}
return 0;
}
|
本来想集成到 Github Actions 里,后来发现我又不会操作,于是作罢。
完工
如果不算途中各种无效尝试的话,整体的耗时大概在一小时左右。
目前来说,这依然只是一个非常简陋的项目,有如下的改进空间:
大体上感觉这是个吃灰项目,以后再说吧。