通过Org做公众号排版
我的博客基本上都会同步到微信公众号,但是我从来不用公众号后台提供的编辑器,一个原因是它不好用,另一个原因是我已经写好了markdown文本格式,不想再在富文本编辑器里做一次排版工作了。过去我一直在使用 https://github.com/doocs/md ,但因为一些问题,我想从Markdown格式迁移到Org格式,找了一下没发现有可以将Org转换到公众号格式的工具,于是打算自己写一个工具用于转换。
界面预览
目前的UI和功能都还比较简单,只是将Org文本贴进去,预览一下样式,再复制粘贴到公众号后台。
原理
微信公众号编辑器支持直接粘贴富文本内容。所谓富文本,顾名思义就是除了文字以外,还包含字体、大小、颜色、对齐方式等样式信息。如果可以从Org文本生成一个富文本内容,那么就可以做到编辑Org格式文本,再一键复制到公众号发布了。
DSL转换
首先需要做的,是两种不同DSL之间的转换。什么是DSL?
DSL(Domain-specific language,领域专用语言),是一种专门为了某个特定领域或应用场景而定制的计算机语言。相比通用编程语言,DSL更加小巧、简单、高度专注于特定问题域。它旨在提高开发效率,让程序员或最终用户能够用更自然的方式表达意图。标记语言是DSL的一种典型形式,主要用于对文本内容进行注释和赋予含义。标记语言使用一组预先定义好的结构化标记,将文档划分为不同的逻辑区块,并对每个区块的类型和语义做出约定,最经典的一种标记语言就是HTML(HyperText Markup Language 超文本标记语言)。
Org也是一种标记语言,举个例子,Org格式规定将一段文本用星号包起来,例如 *bold*
,就表示这段文本应当加粗,支持Org格式的应用,如Emacs就可以通过解析Org文档,获取这个信息,从而在界面上将这段文本加粗显示。
那为什么要从Org格式转换到HTML格式呢?因为微信支持HTML格式的富文本,并且HTML可以和另一个DSL——CSS结合,描述更丰富的样式信息。
具体的做法是通过一种叫做Parser的程序,将Org转换成一种树形结构,称为AST(Abstract syntax tree,抽象语法树)。例如一段Org文本:
可以解析成这样一种结构:
通过遍历这棵树的节点,可以递归地将其转换成HTML。
CSS内联
只是用HTML表示一个节点是标题还是无序列表,所携带的样式信息还是太少了。要想描述文本的字体、大小、颜色、间距等细节,还需要借助CSS(Cascading Style Sheets,层叠样式表)进行渲染控制。但是注意,我们不能单独写一个CSS文件上传到公众号后台,要想直接将使用CSS定义了样式的HTML复制到公众号后台,需要使用HTML的内联CSS语法:
在从Org转换到HTML的过程中,可以直接为要生成的元素写死内联样式,但是为了扩展性(也许用户需要自定义CSS样式),在实际的代码中是在转换过程完成后,再将一个单独的CSS文本解析注入到已有的HTML文本中去的。
拷贝富文本
生成了内联样式的HTML后,怎么把它复制到公众号编辑器里呢?如果你直接打开一个网页,右键查看源代码,把这个源代码复制到公众号,会发现只是复制了HTML的源码文本,而不是最终呈现的富文本样式。怎么把富文本复制到系统的剪切板?其实只需要很短的代码就可以实现:
Roadmap
目前这个工具的功能还是非常简单的,后续打算把之前用过的markdown转换的工具的功能都移植过来:
- 链接转换:订阅号不支持外链,只允许内部其他图文链接,要分开处理,外链转成脚注,内部链接不变
- 自定义样式
- 图片上传OSS,可以和picgo之类的工具结合一下