- 本站的镜像网站: GitHub Pages, 个人网站
- 本人的 CSDN 博客: 点这里起飞
1. 问题描述
众所周知, 搭建自己的知识管理系统是十分重要的.
笔者对知识管理系统的需求有以下几点:
- 支持多平台. PC, 移动端都得有. 移动端编辑功能可以弱一点, 但是查找功能不能弱. 毕竟移动端最大的使用场景就是随时随地找找笔记.
- 支持扩展. 除非功能十分强大, 不然就要对扩展有良好的支持. 总不能软件自身 Markdown 渲染的那么丑, 还不让人自定义吧.
- 数据安全性. 这倒不是说笔记有啥机密, 主要都是自己写的东西, 莫名奇妙的丢了也挺心疼的.
- 平台可替代性. 如果这家公司倒闭了呢, 总得让我能很方便的把数据导出去吧, 最好能直接把 Markdown 导出, 这样导入到其他软件也很方便.
以下是对一些软件使用后的吐槽…
- 为知笔记: 笔者是一个购买了多年为知笔记的用户, 其各平台客户端功能完成度都不错. 虽然 Markdown 编辑器烂成渣, 不过可以在笔记中添加使用第三方编辑器. 这一点还是值得给点赞的. 而为知最大的不足就是搜索. Markdown 笔记内容搜索体验很差. 而且近年感觉为知的更新速度放缓了, 论坛也很少有回复了, 有种渐行渐远的感觉…
- 有道云笔记: 搜索渣的连为知都不如, 虽然体量很大, 但体验确实做得不好.
- Leanote: 刚开始接触 Leanote 时, 有种被惊艳到的感觉. 优良的 Markdown 编辑体验, 自带 blog 展示. 还是开源软件, 不仅客户端开源, 服务器端也开源了. 笔者于是很快搭建了自己的 Leanote 服务. 可等到新鲜劲过去之后, 问题也暴露的越来越多. 它的 安卓 和 ios 客户端功能完成度很低. 而且查了下 gitHub, 都有一年以上没更新了… 再加上自建服务器稳定性有待商榷, 所以还是弃坑了.
- VNote: 本地功能很强大, 但是好像目前还没有做同步 和 移动端软件.
- …
2. 方案设计
现有的笔记类软件很难满足要求. 在一个个软件的使用和比较中, 总在做着艰难的取舍. 就没有一个符合自己全部要求的方案吗? 有, 那就是自己搞一个!
历史总是惊人的相似, 轮子总是重复的创造…
如果从 PC 到 移动端 再到 服务器 完整打造一套软件系统, 所花费的时间成本太大了. 而比较现实的方案是: 先应用一些现有的软件, 辅以扩展性良好的通用数据结构, 打造能基本满足需求的系统. 等之后再从短板开始进行逐一替换.
那就先说说这个现有的实现方案吧. 使用体验上虽然还不完美, 但也绝对比之前的体验要好.
- 使用 Markdown 作为笔记格式, 使用单纯的目录结构来管理笔记.
- 使用 git 负责笔记同步, 国内可选择同步到 码云 等平台. 可以设置 git 项目属性为 private.
- 使用 Hexo 生成博客, 托管到 GitHub Pages 上.
- Win, Mac 下, 可使用
VS Code加载笔记文件夹, 且可以通过安装插件, 完成 Markdown 图片粘贴, git 快速同步, Markdown 高级预览. - ios 下, 有很多支持 git 的软件, 试用了一圈发现还是
Working Copy更符合我的使用习惯. 主要是因为其支持 查找文档内容 和 Markdown 预览. 虽然 Markdown 预览有些瑕疵, 但是不影响使用. - 运行在自己服务器中的一些脚本, 用于自动更新 Hexo 生成 blogs.
3. 效果体现
忙活了好几天, 终于完成了. 最后达到的效果是:
- 在任一客户端更改笔记后, 将笔记 push 到码云.
- 这会触发一个预先在码云该项目中设置了的 web hook, 它会发送一个 POST 请求到笔者的服务器.
- 在该服务器上运行着一个 Node.js 服务. 当收到请求时, 会执行:
- pull 笔记到本地, 读取文档中的一个配置文件. 该文件说明了 blogs 的生成规则, 包括哪些笔记要生成 blogs, 用到哪些 tags, 是否接受评论, …
- 将这些待发布为 blog 的笔记做一些特殊处理后, 生成 md 文件到 Hexo source 目录下.
- 复制这些 md 文件中用到的图片到 Hexo source 目录下.
- 调用 Hexo 生成 Html 文件. 再 push 到 GitHub Pages 中.
- 自动发送邮件给笔者, 通知执行结果, 并把日志文件以附件形式包含在邮件中.
4. 实现过程中的问题记录
在整个过程中, 遇到了一些问题, 积累点滴, 以供成长.
4.1. 在Markdown中插入图片和附件
在 Markdown 文档中插入图片, 一直是一个痛点. 而现有软件的解决思路一般有以下几种:
- 插入图片时, 将图片传到自己服务器, 并返回一个 URL. 和使用网络图床的解决方法一致.
- 插入图片时, 将图片复制到一个指定路径, 并返回该路径. 同步时, 将图片和文档一起同步.
方案一中管理图片时, 需要先登录到图床, 再进行修改. 万一哪天图床挂了, 图床之间的迁移成本太高了. 所以笔者采用了方案二. 具体做法是: 在笔记的同级目录, 创建文件夹 res, 将图片拷贝到该文件夹下. 在 note1.md 中使用  的方式来引用该图片. 目录结构示意图如下:
1 | res |
VS Code 可使用 Paste Image 插件将剪切板的图像生成图片文件, 存储到特定目录下, 再将路径插入到文档中. 可使用 Markdown Preview Enhanced 来选择现有的图片插入. 该插件会将图片复制到指定目录, 并在文档中增加内容. 只需要在安装完插件后, 增加配置如下:
1 | //----------------- markdown preview Enhanced ------------------- |
4.2. Hexo生成带有图片的blog
当待生成 blog 的 markdown 中有图片时, 直接使用 hexo 生成的 Html 是无法正常显示图片的. 因为相对于 html文件而言, 类似于 ./res/test.png 的这些路径找不到了. Hexo 是以时间为目录来组织生成的 html 的, 这些 html 分散在很多个以日期标注的文件夹下, 一个个复制到对应文件夹下有点累. 所以笔者的解决方法是, 修改待发布的markdown 中 ./res/test.png 为 /res/test.png, 这样只要将用到的图片复制到 hexo 的 source/res/ 目录下, hexo 在生成时, 会自动把这些文件拷贝到 html 同级目录中. 这样就能正常显示了.
这个修改路径的工作可以直接交给脚本去执行. 顺便还能给文件加个公共的Head 和 Tail.
为了简化 “脚本中查找本文档用到的图片” 逻辑, 笔者在写文档时, 将所有的图片资源引用都放到了文章开头, 格式如下:
1 | // 放于前面 |
4.3. 使用码云的webhooks
可以使用 node.js 快速搭建一个支持 码云 web hooks 请求的服务. 可以直接引用库 gitee-webhook-handler. 在自己的 js 中调用脚本执行即可.
如果使用的是其他的 git 仓库, 比如 GitHub, Coding 等, 可以直接引用对应的库来使用.
— 道理越辩越明, 欢迎留言讨论. —