基于git和markdown的文档平台

背景

对于一个团队而言,文档的重要性不言而喻,为此我们尝试了很多的文档平台,如wiki, confluence,iwiki,ishare等等。实际使用过程中,总会有各种各样的问题,而且无法定制解决。

对于技术文档,重点关注的是内容,而不是格式,文档中代码比重比较高,平时组内同学写博客大部都是基于 markdown 来写,最终我们决定基于 git + markdown 搭建组内的文档平台。

搭建后的整体框架:

Markdown编辑器

Markdown 的编辑器有很多,最终从可扩展性和轻量级上,最终选择了 VSCode

通过 VSCode 丰富的插件库,补全文档编辑过程中的不足:

  1. Draw.io Integration:画图工具,而支持直接编辑 svg 和 png 图片
  2. Favorites:收藏工具,方便收藏常用的文档
  3. GitLens:Git工具,方便查看每段文档的提交人
  4. Paste Image:方便粘贴图片

但还是存在几个关键问题:

  1. 无法快速分享当前文档的GitLab地址
  2. 对于没有GitLab权限的PM,无法查看
  3. 图片存储方式与位置没有统一的规范

自定义 Plugin 解决快速分享问题

插件实现非常简单,主要思路:

  1. 获取当前 markdown 文档的相对路径
  2. 通过提前配置的 GitLab 和 动态博客的 baseURL,拼接出完整分享地址

源码:vscode-git-markdown-tools

效果如下:

动态博客解决无权限无法查看问题

通过 GitLab 来分享,除了权限问题外,还有对 Markdown 的支持问题,如当前公司的 GitLab 不支持 svg 的渲染。

gitbook、hexo等静态博客的流程:

此类静态博客的最大问题是本地编译时间较长,不适配团队且更新频繁的文档。

动态博客docsify的流程:

Python搭建web服务

docsify的两种访问方式:

  1. 访问首页:https://host:ip/
  2. 访问子页:https://host:ip/xxx,如https://host:ip/README

从其原理可知,这两种访问都应该近回 index.html,而不应该访问具体的 xxx.md 文件。

由 index.html 异步发出的请求:

  1. 请求 *.md、图片等:https://host:ip/xxx.md,https://host:ip/xxx.png
  2. 请求目录文件(_sidebar.md):此目录文件是通过相对路径请求的,所以直接打开子页面时,除了https://host:ip/_sidebar.md 外,还会发出一个请求,如 https://host:ip/README/_sidebar.md

通过 Python 的 Flask Web 框架实现上述需求,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from flask import Flask, send_from_directory, request
import os

app = Flask(__name__)

@app.route('/')
def docsify():
return send_from_directory(app.root_path, 'index.html')

@app.route('/<path:filename>')
def docsify_static(filename):
file_extension = os.path.splitext(filename)[1]
if(file_extension == ''): # 因为routerMode:'history'模式,不能直接打开子页面,需要先加载index.html页面才行
return send_from_directory(app.root_path, 'index.html')
if(filename.endswith('_sidebar.md')):
return send_from_directory(app.root_path, '_sidebar.md')
return send_from_directory(app.root_path + '/..', filename)

if __name__ == '__main__':
# 先更新代码,再启动服务
updateCode()
app.run(debug=True, port=8484, host='0.0.0.0')

通过 Webhooks 实现代码的监听,提供一个接口给 GitLab 来调用,代码如下:

1
2
3
4
5
6
7
8
9
10
11
def updateCode():
working_path = app.root_path + '/..'
# 先更新代码
process = subprocess.run(["git","pull", "origin", "master:master"], cwd=working_path, capture_output=True)
# 重新生成目录文件
docsify_generate_sidebar.gen_sidebar()
return process.stdout

@app.route('/igit_webhook', methods = ['POST','GET'])
def web_hook():
return updateCode()

由于 docsify 不支持通过扫描文件夹,生成目录的功能,使用 Python 写了一个脚本,在代码更新后,自动遍历文件夹,生成目录文件(_sidebar.md)

参考

  1. docsify
  2. flask
感谢您的阅读,本文由 刘阳 版权所有。如若转载,请注明出处:刘阳(https://handsomeliuyang.github.io/2021/05/11/%E7%BB%8F%E9%AA%8C%E6%80%BB%E7%BB%93-%E5%9F%BA%E4%BA%8Egit%E5%92%8Cmarkdown%E7%9A%84%E6%96%87%E6%A1%A3%E5%B9%B3%E5%8F%B0/
Android端的架构设计的演进和思考
暗黑适配方案比较