Kaede Akatsuki

中二病也要开发 Android

基于 Notion 的笔记写作和博客分享自动化方案

Page Cover

个人认为,笔记(Note)、写作(Writing)和分享(Share)是 个人知识管理 重要的组成部分。笔记是知识元素,写作是知识汇总,分享是知识升华。固然每个人具体实践的方式会尽不相同,不过大家应该都或多或少能对体会其中存在的一些割裂感:

其一,笔记存在多端同步编辑的刚需。不过随着云笔记解决方案越来越成熟后,这问题现在已经有许多解决方案。其二,笔记草稿和写作正文之间的同步存在许多机械的地方:同一篇文章经常需要在草稿和正文(终稿)之间来回修订,而大部分情况下这两者的同步是通过复制粘贴和人工比对来完成的,这个过场是写作体验主要的割裂感之一。其三,写作正文完成之后的文章分享(Publish)也是一个麻烦的流程,尽管现在许多静态博客可以通过自动化技术完成部署,不过文章正文内容和部署用的 MarkDown 源文件之间的数据同步也是个非常头疼的事情:如果正文和 MD 文件分开处理,两者之间只能手动同步;如果直接用 MD 文件来写正文,又不得不面临现在多数云笔记糟糕的 MD 文件编辑体验(而且 MD 文件能否导出还是个未知数);如果干脆使用 gitbook 之类的方案来编辑 MD 文件,那基于 git 的笔记云同步方案体验也不会好到哪。

自从改用静态博客代替 WordPress 来发表自己的文章、文档后,我不得已采用”云笔记写草稿,MD 文件保存文章正文,手动在草稿和正文之间同步“这样的 原始 的写作方案,以上说的几种割裂感也是一直以来我感到非常困扰的地方。

几番苦寻更好的云笔记体验方案,未果。直到 ta 的出现:Notion

Notion

Notion 是一款时下比较流行的云笔记服务,虽然上线比较晚,不过 ta 却是众多云笔记里面”最靓的仔“。基于巧妙和独特的文本元素关系设计,Notion 可以将你的 Notes、Project Tasks / Plans、Doc / Wikis 等统统整合起来(还提供许多优秀的 Template 以满足不同的文档需要),在 ta 身上我看到了知识管理和项目管理的“大一统”的希望。

简单来说,Notion 抛弃了传统以段落(paragraph)为原子单位的做法,而是将所有的一切都当做 Block(是 Everything is Block)。一段文本是一个 TextBlock,一张图片也是一个 ImageBlock,Block 之间可以随意移动和嵌套。同时 Notion Block 被巧妙地设计成组合模式:一个 Block 可以是单一的 Block 也可以是 BlockGroup。这使得 Notion 可以满足几乎所有的文本关系,一片文章本身就是一个 PageBlock,PageBlock 即可以包含各种类型 Block 也可以包含 BlockGroup(用来存放 Table、Columns 等文本组),甚至文章本身就是一个 BlockGroup(类似于 Folder,用于存放一组子文章)。此外,Notion 的强大之处还在于 ta 提供了 CollectionBlock(可以认为是一个简化的 Excel),配合相关的 Notion APIs 我们甚至可以把其当做一个数据库来使用。

鉴于 Notion 优秀的多端同步服务和灵活的文本存储功能,我从开始接触到 ta 的时候就产生了“基于 Notion 优化一下自己的知识管理方案”的想法。不过眼下有两个问题还需进一步观察:其一, Notion 一开始是收费的(而且不便宜),我担心收益出现边际效应,成本不可控;其二,Notion 并没有 Official APIs,这会影响基于 Notion 的二次开发的稳定性,而稳定性又是自动化实践里非常重要的考量。

随着 Notion 开放免费的个人账号(Personal Plan)和官方 APIs 计划的展开,这些顾虑都再也不是问题。

Solution & Workflows

如何优化自己现有的知识管理方案呢,我的基本设想是这样的:

  1. 基于 Notion 写作,所有的文本材料和源数据都统一放在 Notion 上面同步,避免“冗余写作”。
  2. 使用自动化手段(DevOps)从 Notion 中导出指定笔记的 MD 文件,解决笔记和写作正文之间的割裂感:源文件依然可以保留各种草稿、标注和评论等内容,导出的 MD 文件则根据配置只生成指定的正文内容。
  3. 同样使用自动化手段导出需要分享的 Notion 文章,自动部署到 Hexo 等静态博客。

如果有需要,作为兜底策略可以定期导出 Notion 全部笔记数据并做好保存和版本控制,从而弥补 Notion 付费才能使用的历史记录功能和为需要从 Notion 迁移数据这种状况做准备(尝试过云笔记数据迁移的朋友应该知道这是什么考量)。

工作流程示意图如下:

NotionDown 工作流程示意图

NotionDown Project

基于 CAP 编程原则,能复制的代码绝不自己写,一开始我抱着侥幸的心态去 GitHub 上面搜索,还真让我找到了类似的工程 notoma。不过项目还处于 WIP 状态,等了快一年作者还没有什么动作,Demo 也是处于无法运行的状态,所以我索性自己动手好了。

自己写一个 3rd-party 的 Notion APIs 不太现实,好在同样的 GitHub 上面已经有先驱做了类似的项目 notion-py,相比之下这个项目的完成度已经非常高了(目前唯一的遗憾就是尚未支持 Notion private 笔记的访问,且项目开发文档有限)。

基于 notion-py 我写了一个用来支撑自己知识管理的 Notion 笔记导出项目 notion-down,主要用来自动从云笔记导出 MD 文件和部署博客(配合 circleci + 静态博客)。

NotionDown 的主要功能如下:

  1. 统一在 Notion 平台上编辑笔记(集大成)。
  2. 基于 Notion 笔记 + 相应的编译配置,解析所需的 MD 文件(必须支持图片配置)。
  3. 根据配置将需要 Publish 的文章自动部署指定的静态博客(Hexo)。
  4. 相关配套的集成功能:图床配置,自定义短代码(如生成的文章内容按渠道配置动态调整),中英混排优化(pangu),拼写检查(双拼用户刚需)。

如此一来,以后岂不是可以专心写作了?🤣(鬼咧,正经 Bloger 谁写文章啊,不都是在折腾博客主题吗。)

Substitute

如果只是需要自动把 Notion 上面的笔记部署到静态博客,我这发现一个更简单的解决方案:Notion + GatsbyJs + Netlify 极致的博客体验

其基本思路是通过 Netlify 作为 Trigger 触发 GatsbyJs 插件服务读取 Notion 笔记数据,并存放到 Gatsby 平台,最终通过 Gatsby 提供的博客服务展示博客内容。有兴趣可以了解一下 Gatsby,这套方案可以节省 circleci 和静态博客 generating 等不少中间流程。