1 前言

自大学起,已经写过好几年的东西,写作工具和流程也反复折腾过好多回. 目前的写作流程已经很流程顺手,所以想分享一下。

2 写作工具

我不倾向任何专用格式的写作软件(如Word), 或者笔记云服务(EverNote,xx笔记等)。

因为前者只能使用专门的软件打开,和该软件绑定,会导致文本内容被专用的软件绑架。 可能过个10年,可能该软件不再流行,你甚至无法打开自己的文章。

对于笔记服务,你的文章数据甚至不掌握在你手里,该服务停用,你的数据就会全部丢失。

所以我倾向于「本地化储存」+「文本格式」 + 「易于同步」的写作方案

最后我选择的写作工具是 Emacs + org-mode=,不熟悉 =org-mode 的读者可能不知道 org-mode 是什么,可能理解成类似是 markdown 的标记语言,但是和=Emacs= 结合后,易用性与扩展性比=markdown= 提高了一个数量级。

这篇文章就是使用 Emacs + org-mode 写出来的:

2.1 图片

《写博客的动机》一文我提到,我之前是自建了博客,但是后来又迁移到了ox-hugo + Hugo 的GitHub Page上,其中最大的一个痛点就是插入图片.

插入图片流程一般是分为两步:

  1. 上传图片到云端存储,一般就是各种图床,如国外的Imgur, Cloudflare, 国内的七牛,又拍云,腾讯云对象存储等等
  2. 将上传的图片插入文章,如果使用 Markdown, 就是 ![]() 的格式插入

最初我是手动上传到 Imgur,再把生成的链接插入到Markdown,每次图片操作下来大概耗费1-2分钟,尤其是Imgur还在国外,网络不好,经常失败。

后来用上了PicGo 这个图片上传工具,稍微好些,但是依旧不方便,因为手动拖拉图片上传,图片还不好管理。

后面遇到 ox-hugo 这个插件之后,就完全没有插入文件的困扰了。

得益于Emacs各种强大的文件交互功能,我只需要做:

  1. 打开本地图片, Ctrl-c l 触发 org-store-link 函数, 将文件名保存起来
  2. Ctrl-c Ctrl-l 触发 org-insert-link 函数, 选择刚刚指定的文件, 点击回车即可.

我现在管理图片的方式是将每篇文章相关的文章都放到 文章名/img 的目录下, 所以我只需要打开 img, Ctrl-c l 选择图片, 再回到文章 Ctrl-c Ctrl-l 插入即可.

又得益于Emacs org-mode 无可比拟的export 功能, 我可以通过ox-hugo 将 org-mode 文件导出成 Hugo 兼容的Markdown 文件, 然后再自动将文章中所有的图片复制到 Hugo 博客下的 static/ox-hugo 目录下.

假如我本地路径为 /home/ramsay/blog/2023/我的写作流/img/emacs_org_mode.png 的图片,在按下 Ctrl-c Ctrl-e H h 之后,导出到 Hugo Markdown 之后,图片路径就会变成:

1
{{\< figure src="/ox-hugo/emacs_org_mode.png" link="/ox-hugo/emacs_org_mode.png" >}}

只需要将复制到 ox-hugo 目录的图片和文章的Markdown 文件一起提交到Git, 并上传到GitHub 就相当于把GitHub 当作图床,但是其他操作都由ox-hugo 和 GitHub 代劳了.

3 写作平台

3.1 博客

在大学时期,我使用的是 org-page + org-mode 来自建博客在 Github Pages, 写了大概一年的博客文章。

后来因为 org-page 总是存在各种奇怪的小bug,博客样式也只有那么几种,不能满足折腾欲望很强烈的我 (这种行为和年少时喜欢在QQ空间换皮肤差不多)。

大概是2018年,我当时学习了Rust,打算找个机会来练手,然后就使用Rust搭建了个人的博客,开源在Github上,还有100+的star,就这样,在自己的博客上又写了几年文章。

直到2022年,因为工作太忙碌,没有太多时间来维护博客的代码以及运维博客的服务。 自建博客的初衷只是为了有个地方可以承载我写的内容,只是因为年轻,有精力折腾,就自己写代码,搭建服务。

但总体而言,写作的流程并不顺手: 因为我一直都是使用=org-mode= 来写作,而我自己的博客只支持 Markdown 格式,这就意味着我必须每次写作完成后,需要将=org-mode= 转换成 markdown , 然后再在博客后台发布。

如果涉及到图片就更麻烦,需要将图片逐张上传到图床,然后再插入到 org-mode=中, 而博客使用的=markdown 编辑器过了5年后,开发者已经不维护了,所以免不了又会有各种小问题。

我又尝试了 Emacs + org-mode + hugo 的博客方案,发现使用起来非常舒心,发布文章几乎无成本。正好碰上博客服务器到期,就干脆切换回=Github Pages=.

hugo 是使用 markdown 来构建网站的框架,而我使用的 org-mode=,所以还需要一个工具将 =org-mode 转换为 Hugo markdown=,这个就是 =Emacs 插件 ox-hugo。当然, hugo 原生也支持 org-mode, 只是功能支持不完整, 远不及 ox-hugo.

ox-hugo 只需要将在 org-mode 内容的最开始插入标记:

1
2
3
4
5
6
7
8
9
#+HUGO_BASE_DIR: ~/code/org/ramsayleung.github.io
#+HUGO_SECTION: zh/post/2023
#+HUGO_CUSTOM_FRONT_MATTER: :toc true
#+HUGO_AUTO_SET_LASTMOD: t
#+HUGO_DRAFT: false
#+DATE: [2023-01-25 Wed 14:25]
#+TITLE: 我的写作流
#+HUGO_TAGS: writing
#+HUGO_CATEGORIES: writing

Emacs一个快捷键 C-c C-e H h 就可以将 org-mode 转换成 Hugo 格式的 Markdown:

结合Github Action,就可以自动把导出的markdown 博文部署到Github Pages,称得上是一键部署。

3.2 公众号

在过新年的时候,闲来无事,新开了一个公众号「宫孙说」,用来「一鱼多吃」,将自己文章也转到公众号。

因为Richard Stallman的影响,我一直是倾向于开放,自由的软件与生态,所以对于公众号这样仅限于「微信」封闭生态的平台不感冒。

另外,关于「公众号」的看法,我是与陈皓一致的,详见他的文章《为什么我不在微信公众号上写文章》

但不可否认的是,「公众号」是国内最完善的创作平台,有完整的分享,阅读生态。

毕竟我不只写技术文章,还会写一些历史,人文类的文章,我希望可以分享给朋友,但Github Pages会间歇性被墙,朋友们大多是在微信阅读文章,虽然博客支持移动端,但是体验终究不及「公众号」。

屈服于现实压力,我最终开了这个公众号。

3.3 知乎

知乎也是国内创作氛围相对自由和蓬勃的平台,本着「一鱼多吃」的心态,我也会把文章转载到知乎上。

3.4 KM

这是公司内部的知识交流创作平台,算是私域流量。有点难以置信的是,在这个读者数量远不如外部的平台,我写的文章有最多的阅读与收藏. 或许是因为我写的内容贴近业务,是同事比较感兴趣的。

3.5 格式兼容多个平台

将同一篇文章分发到多个平台,就难免会有不同平台格式不通的问题。

因为Markdown 是通用文档,所以我倾向于把我的文章发布在其他的平台,如上文提到的知乎,公众号。

但是这些平台都是使用专有的编辑器,并不支持直接解析Markdown,所以我会把文章复制到 https://markdown.com.cn/editor/ 的在线编辑,它提供了一键复制格式到公众号,知乎, 掘金的功能.

新的问题又来了, 我使用 ox-hugo 导出的是Hugo Markdown,又不是标准的Markdown, markdown.com.cn的编辑器无法解析部分标签, 如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
+++
title = "我的写作流"
date = 2023-01-25T14:25:00-08:00
lastmod = 2025-01-09T17:40:36-08:00
tags = ["writing"]
categories = ["工作流"]
draft = false
toc = true
+++

# ## <span class="section-num">1</span> 前言 {#前言} => ## <span class="section-num">1</span> 前言

{{\< figure src="/ox-hugo/emacs_org_mode.png" link="/ox-hugo/emacs_org_mode.png" >}}

既然编辑器不支持Hugo语法,那么把Hugo特有的语法去掉就行了嘛,所以我写了一个 shell script 用来把Hugo Markdown 转换回标准 Markdown:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
remove_heading_tag () {
    # ## <span class="section-num">1</span> 前言 {#前言} => ## <span class="section-num">1</span> 前言
    # 删除 {#前言}
    sed 's/{#.*}//' $1
}

remove_meta_info () {
    # 删除下列信息
    # +++
    # title = "为什么梦想买不起,故乡回不去"
    # date = 2023-01-14T23:21:00+08:00
    # lastmod = 2023-01-25T09:00:47+08:00
    # tags = ["book", "history", "economy"]
    # categories = ["book"]
    # draft = false
    # toc = true
    # +++
    sed '/+++/,/+++/d'
}

又因为Emacs 本身就是个Lisp解析器, 我在运行时修改了一下导出成 Hugo Markdown 的函数, 在导出完之后,再调用上面的shell 脚本, 根据Hugo Markdown 再生成一份标准的Markdown.

1
2
3
4
5
6
7
8
(defun ramsay/org-hugo-export-to-std-md (orig-fun &rest args)
  "Generate standard markdown file base on the exported hugo markdown."
  (let ((res (apply orig-fun args)))
    (message "Generate the standard markdown from %S" res)
    (ramsay/hugo2md-base "~/code/shell/hugomd2md-gitea.sh" res "gitea")
    res))

(advice-add 'org-hugo-export-to-md :around #'ramsay/org-hugo-export-to-std-md)

回到图片的问题上, 虽然GitHub 可以作为图床,但是因为墙不间断阻断 GitHub, 导致国内访问 GitHub 并不稳定,图片可能无法下载下来.

既然 GitHub 无法稳定访问, 那么就挑个能在国内稳定访问的 Git 服务呗。

一番调研之后,最后选定了 Gitea

需要做的事情也很简单,只需要在 Gitea 上新建一个仓库,然后再给我的博客增加一个远程仓库即可:

1
2
3
4
5
> git remote -v
gitea   git@gitea.com:myusername/store.git (fetch)
gitea   git@gitea.com:myusername/store.git (push)
origin  git@github.com:ramsayleung/ramsayleung.github.io.git (fetch)
origin  git@github.com:ramsayleung/ramsayleung.github.io.git (push)

最后需要做的就是再更新一下Shell 脚本,在把Hugo Markdown转换成标准Markdown的时候,再把图片链接修改为GitTea 链接:

1
2
3
4
5
6
replace_link () {
    # hugo的图片链接,转换成markdown 标准链接
    # {{\< figure src="/ox-hugo/土地金融-政府债务.png" link="/ox-hugo/土地金融-政府债务.png" >}}
    # => ![](https://gitea.com/myusername/store/raw/branch/master/static/ox-hugo/土地金融-政府债务.png)
    sed 's/{{\< figure src="\(.*\)" link=.*>}}/!\[\](https:\/\/gitea.com\/myusername\/store\/raw\/branch\/master\/static\1)/'
}

最后的效果就是,在我把 Org-mode 文件导出成 Hugo Markdown 后,会自己再生成一份替换了图片链接地址的标准Markdown.

因为我太懒了,所以我再写了个小函数,导出完成之后,自动复制标准 Markdown 的内容到 clipboard, 这样就可以直接粘贴到 markdown.com.cn了(算下来,我每次操作都省了10来秒)

4 写在最后

完整的写作流如图:

因为使用 Emacs + org-mode 写文章非常顺手,所以我写下了很多的文稿,只是思绪杂乱,不方便都发布出来.

现在正逐步将存稿往公众号平台上迁移,只是公众号有诸多限制,其中一条是一天只能群发一篇文章,只能「小刀锯大树」,慢慢来了。

qrcode_gh_e06d750e626f_1.jpg 公号同步更新,欢迎关注👻