Issues就是一个Blog

bird or boat

孤雁? 孤舟!

几年前就看到有人用 Github Issues 写 Blog, 尽管这是个很酷也很务实的玩法, 但考虑它无法提供一个沉浸式的阅读体验, 我也就一笑而过了.

Issue 与 Post 二者之间的共同特质是: 归档沟通.

一直以来我都是用 GitHub PagesJekyll 来搭一个 Serverless 的 Blog, 功能虽有限, 但好在对我来说够用且省心. 倒不是说, 我不想要额外的功能(如评论), 只是要投入更多时间研究 Jekyll 插件, 总认为对我这种随机写作的人是不值得的.

“若是将 Issues 作为 Post 存取载体, 借助 API 给换一个沉浸式的阅读体验的外壳呢?” 这是前些天, 我脑子里蹦出的想法. 此外, 知道 Ammonite 很久, 一直没有个合适场景发挥它的优势, 于是我有动力来干这件事了.

// Domain Model
type Transform[Issue, Fragment] = Issue => Fragment
type Render[Layout, Fragment, Doc] = Layout => Fragment => Doc

看似一句话的事情, 我还是断断续续弄了好些天. 遇到几个纠结耗时小坎:

模版

起初, 考虑到未来想把它工具化, 用户只要懂 HTML 就可以很容易上手, 在选择模版选型上, 尽可能避免混合控制逻辑代码.

Scalate 总结了各类风格模版引擎:

  • Mustache which is a Scala dialect of Mustache for logic-less templates which also work inside the browser using mustache.js
  • Scaml which is a Scala dialect of Haml and is very DRY for generating HTML / XHTML
  • Jade which is an even more DRY dialect of Scaml for HTML / XHTML markup generation
  • SSP which is like Velocity, JSP or Erb from Rails

与此同时要想兼顾模版定制的灵活性, 那么实现的复杂度就会增加. 最终, 我选择了Scalatags, 理由是实现复杂度低, 定制灵活性高, 其 API 的设计风格与原生 HTML 也接近. 唯一不足是, 它是 Embedded DSL, 因而需要使用者熟悉一点 Scala 语言.

迁移

之前的 Blog 已经积累了 25 篇 Markdown 写的 Post 需要迁移到 Issues 里. 要处理的问题有:

  1. 文章标题有中英两种:
    1. 中文的需要从 Markdown 文件中提取, 转换为 Issue 的 Title,
    2. 英文的需要保留作为站点生成的页面路径, 比如: https://zhongl.github.io/2019/03/07/how-to-open-a-fancy-source-on-github/
  2. 转为 Issue 后, 原始文章的发布时间 Issue 没有保存(Issue的创建时间没法修改),
  3. 原始文章中的标签, 需要转换为 Issue 的 Label.

本想借用一些在线翻译服务来实现根据中文标题自动生成英文的, 可是一方面从页面挖掘 API 比较耗时, 另一方面随着时间的推荐翻译的结果可能有变, 这导致生成的路径链接不稳定, 于是作罢了.

比较稳妥的方式是, 在 Issue 的 Body 里用不可见元素存储标题和日期等这类信息.

<input type='hidden' name='created' value='2008-04-13' />

好在, Jsoup可以很容易帮我在 Markdown 里 Body 找到它们.

M2H

Github API 提供 Media Type 内容参数, 也就是说, Markdown 写的 Issue, API 可以直接获取渲染成 HTML 的结果. 本以为可以省掉自己解析渲染的工作, 可惜 Github 提供的 Markdown 语法支持有限, 比如我很喜欢的 [TOC] 就不支持, 只好借助 flexmark-java 自己来干了.

Post 中的代码片段语法高亮, 还没有想到轻量级的解决方案, 故而暂时没有支持.

发布

犯了一个想当然的错误, 没有预先验证, 做到最后发现预设的自动发布方案行不通. 即, 通过 Repo 集成 travis-ci, 由 Issue 事件来触发 Blog 生成任务, 进而实现一旦新的 Issue 一提交就自动发布更新 Blog.

不幸的是, 只有 Pull Request 才可以触发任务, 普通的 Issue 是不支持的. 考虑过使用 PR 来写 Post, 但新建 PR 需要有分支去合并做前提, 这就没有必要了.

还好, travis-ci 提供 Cron Jobs 功能, 做不到秒级实时更新, 还是能做到 24h 内自动更新的, 对于更新不怎么频繁的 Blog 场景而言够用了.

对我个人而言, Cron Jobs 按周运行一次也够用了.

如果有兴趣了解更多, 请移步Repo. 也欢迎在评论中与我讨论更有意思的想法.

Enjoy!

ammonitegithubComment(0)