在org-mode中,如果在文件头部写上`#OPTIONS: num:t’,导出的各种格式的文件就会有章节
编号。但用org2blog(punchagan commit 387217f792)生成博客,做同样的设置,却没有效
果。
在github上开了个issue,但等了很久也不见作者或者其他人尝试解决(开源项目中,这种事
儿很常见),于是我自己写了段很丑的Emacs Lisp来解决这个问题。
我想要的效果是,org文件里这样的“代码”:
#+BEGIN_SRC Language
1 Hello
1.1 World
1.2 Emacs
#+END_SRC
导出之后,变成:
1 Hello
1.1 World
1.2 Emacs
2 定位bug
以前除了修改配置文件之外,基本没有接触过Emacs Lisp,所以定位bug花了很长时间。
定位的过程就是跟着代码一步步看,找到出错的位置,最后发现跟org2blog没啥关系。
`org2blog/wp-post-buffer’(把博客发到WordPress)会调用
`org2blog/wp-parse-entry’把org文件转换成HTML,以便发布。
而在`org2blog/wp-parse-entry’中,会调用`org-export-as-html’。
我发现在`org-export-as-html’之前,一切都没问题,但等到`org-export-as-html’把内
容返回来之后,里边却没有章节编号。
于是我按”C-h f RET org-export-as-html”,调出`org-export-as-html’的文档:
org-export-as-html is an interactive autoloaded compiled Lisp function in `org-html.el'. (org-export-as-html ARG &optional EXT-PLIST TO-BUFFER BODY-ONLY PUB-DIR) Export the outline as a pretty HTML file. ... ... ... When BODY-ONLY is set, don't produce the file header and footer, simply return the content of <body>...</body>, without even the body tags themselves. When PUB-DIR is set, use this as the publishing directory.
`org2blog’调用`org-export-as-html’的时候,传入的`BODY-ONLY’参数值为`t’,所以只会
返回 <body>
和 </body>
之间的内容,而不是整个页面。
我自己试了试,发现传入的`BODY-ONLY’为`nil’的时候,章节编号没问题;但
`BODY-ONLY’为`t’的时候,章节编号就不显示了。
所以整了半天,这其实是org-mode的bug。
经过这一趟,对 edebug 用的比较熟了。
3 修改
org-mode比较巨大,代码写得很丑很复杂,注释又特别稀少,我实在不想碰,于是投机取
巧,直接在org2blog里改。
我想,既然`org-export-as-html’生成完整的HTML的时候没有问题,那就先生成完整的
HTML,然后再从里面截取需要的部分。
写个函数抓取 <body>
和 </body>
之间的内容。
(defun org2blog/wp-retrieve-html-body (html-text) "Retrieve the content between <body> and </body> from the HTML string generated by org-export-as-html" (substring html-text (string-match "<body>" html-text) (string-match "</body>" html-text)))
然后修改`org2blog/wp-parse-entry’,让它调用这个函数
(setq html-text ;;Starting with org-mode 7.9.3, org-export-as-html ;;takes 4 optional args instead of 5. (condition-case nil (org2blog/wp-retrieve-html-body (org-export-as-html nil nil nil 'string nil nil)) (wrong-number-of-arguments (org2blog/wp-retrieve-html-body (org-export-as-html nil nil 'string nil nil)))))
这样”num:t”的`org-mode’文件转成的博客,就是带有章节编号的了,同时也带着
postamble(这个可以很容易地去掉,不过我挺喜欢现在这样的)。
4 (心中的)更好的解决方案
这个解决方法其实有很多问题:
- 这是`org-mode’的bug,应该去`org-mode’里边解决。
- `string-match’是有隐患的,如果文章正文里有
</body>
,可能导出的博客就会变短。
最安全的方式是对HTML进行解析之后再进行处理。
最好的办法,是把这个bug提交给`org-mode’的开发团队,或者直接改好了给他们发补丁,
不过暂时能用,就懒得做了。
5 获取代码
可以clone我的fork:
$ git clone git@github.com:RenWenshan/org2blog.git
或者加一个upstream,然后pull(请自行查阅git手册)。
或者直接把下载我的`org2blog.el’,把现有的替换掉:
https://raw.github.com/RenWenshan/org2blog/master/org2blog.el
Happy Hacking!