终于搞定了使用 MathJax 渲染 LaTex 数学公式的问题,分享给大家。
辛辛苦苦用 markdown 写就了一系列文章,怎么样导出制作成一本高颜值的电子书呢?本文介绍一种在 Mac 下使用 kitabu + princexml 导出高颜值电子书的方法。
本文还介绍了字体定制,排版定制,代码高亮,使用 MathJax 渲染 LaTex 数学公式等方法。
安装软件
首先安装 kitabu
gem install kitabu
这是个开源的 Ruby 包,主要提供电子书模板和制作过程自动化的功能。如果你没使用过 ruby ,可能在使用 gem install kitabu
时报错 Errno::ECONNRESET: Connection reset by peer
,可以试试切换 taobao 的 RubyGems 镜像:
$ gem sources --add https://ruby.taobao.org/ --remove https://rubygems.org/
$ gem sources -l
*** CURRENT SOURCES ***
https://ruby.taobao.org
接着安装 princexml,可以从官网 princexml.com 下载免费的安装包。princexml 会完成从 html 转为为 pdf 功能。安装完这两个工具后,可以用 kitabu check
命令检查一下是否安装成功:
bogon:~ kamidox$ kitabu check
Prince XML: Converts HTML files into PDF files.
Installed.
KindleGen: Converts ePub e-books into .mobi files.
Installed.
html2text: Converts HTML documents into plain text.
Not installed.
我的环境里多安装了 KindleGen ,如果你需要制作 .mobi 格式的电子书,可以使用 brew install kindlegen
来安装。不过这一步不是必须的。
制作电子书
接着在工作目录执行 kitabu new mybook
即可创建 kitabu 电子书的模板:
mybook/
├── Gemfile
├── Guardfile
├── config
│ ├── helper.rb
│ └── kitabu.yml
├── fonts
├── images
│ ├── kitabu-icon.png
│ ├── kitabu-icon.svg
│ ├── kitabu-word.png
│ ├── kitabu-word.svg
│ ├── kitabu.png
│ └── kitabu.svg
├── output
├── templates
│ ├── epub
│ │ ├── cover.erb
│ │ ├── cover.png
│ │ └── page.erb
│ ├── html
│ │ └── layout.erb
│ └── styles
│ ├── epub.scss
│ ├── files
│ │ └── _normalize.scss
│ ├── html.scss
│ ├── pdf.scss
│ └── print.scss
└── text
├── 01_Getting_Started.md
├── 02_Creating_Chapters.md
├── 03_Syntax_Highlighting.erb
├── 04_Dynamic_Content.erb
└── 05_Exporting_Files.md
然后在 mybook
目录运行 kitabu export
即可在 output
目录下生成电子书了。默认情况下,会生成 kitabu 使用说明文档。
基础配置
要制作自己的电子书,需要做些简单的配置。先把 kitabu 模板的 text
目录清空,然后把自己的 markdown 文件拷贝到这个目录下,需要注意的是 kitabu 是使用文件名排序生成电子书,并且会自动把 2-6 级标题自动生成书籍的目录。如果你的 markdown 文件是以 1 级标题开始,则需要把所有的标题降一个等级。
接着修改 config/kitabu.yml
把书箱的作者,版权声明,出版商的信息补充完整。然后修改 templates
目录下的 css 文件,让生成的电子书更漂亮。
我自己主要修改两处。一是修改 templates/styles/pdf.scss
,在所有的 font-family
字段里添加 PingFang SC
,以便使用 Mac 的苹方字体来显示中文,默认字体中文效果比较差。比如:
body {
font-family: Caslon, serif;
font-size: 14px;
line-height: 1.5;
}
改成
body {
font-family: PingFang SC, Caslon, serif;
font-size: 14px;
line-height: 1.5;
}
二是修改图片的宽度,以便电子书里的图片能自动缩放,避免大图片显示不全的问题。这个主要是修改 templates/styles/files/_normalize.scss
:
img {
border: 0;
}
改成:
img {
border: 0;
width: 100%;
}
这样生成的电子书颜值就很高了。如果你是前端工程师,折腾一下 css 可以做出更精美的电子书。
在电子书中插入图片
另外,我自己写作过程中,直接把图片放在本地目录,然后使用相对路径在 markdown 里生成图片,比如:
![](images/ch02.01.png)
否则就得找图床,生成电子书时还会从图床下载图片。所以直接放在本地,用相对路径引用是个相对经济的方案。默认情况下,kitabu 是不认本地相对路径的图片的。这时需要 hack 一下 kitabu,因为默认情况下,kitabu 启用了安全链接的功能,我们可以把这个功能关闭掉。
首先找到 kitabu 包的安装目录,可以使用 gem help install
命令,然后在输出中找 --install-dir
字段,比如我的机器上有这样的输出:
$ gem help install
... ...
Defaults:
--both --version '>= 0' --document --no-force
--install-dir /usr/local/lib/ruby/gems/2.3.0 --lock
然后进入 /usr/local/lib/ruby/gems/2.3.0/gems/kitabu-2.0.4/
目录,打开 lib/kitabu/markdown.rb
文件,把
renderer = Renderer.new(hard_wrap: true, safe_links_only: true)
修改为
renderer = Renderer.new(hard_wrap: true, safe_links_only: false)
支持 LaTex 公式
MathJax 是一个 JavaScript 库,用来渲染 LaTex 格式的数学公式。如果你想了解怎么样在 Markdown 里书写数学公式,可以参考我之前的一篇博客 《使用 Markdown + MathJax 在博客里插入数学公式》。
默认情况下,kitabu 无法在渲染使用 MathJax 在 markdown 里书写的数学公式。其原因是 princexml 不支持 Window 等对象,所以 MathJax 的 JavaScript 脚本无法执行。
解决这个问题的思路是,使用 Phantomjs 来渲染包含 LaTex 数学公式的 html 页面,由于 Phantomjs 可以正确地执行 MathJax 的 JavaScript 脚本,所以能正确地渲染出数学公式。接着再使用 princexml 来生成 PDF 格式的电子书就可以正确地渲染出数学公式了。思路很简单,操作起来还是有点麻烦。
首先,安装 Phantomjs 工具,可以在官网下载安装适合你的操作系统的版本。在 macOS 上,下载下来的是一个绿色安装包,我把它放在硬盘的合适位置后,把 /bin/phantomjs
加入到 PATH 变量里,以便在命令行中能直接执行这个命令。
$ tree ~/tools/phantomjs/
~/tools/phantomjs/
├── ChangeLog
├── LICENSE.BSD
├── README.md
├── bin
│ └── phantomjs
├── examples
接着,安装 MathJax ,方法是把 MathJax 下载到电子书的目录。比如,你使用 kitabu new mybook
时,则把 MathJax 下载后解压到 mybook
目录下,我使用的是 MathJax 2.7.0 版本。
接着,再把 MathJaxRender.js 和 MathJaxConfig.js 也下载到 mybook
目录下。这两个分别是 phantomjs 渲染脚本和 MathJax 配置文件。需要特别注意,MathJaxConfig.js 不要修改文件名,如果修改了文件名,很多引用的地方也要跟着同步修改。
接着,还要 hack 一下 kitabu,其目的是配置 Redcarpet (这是把 markdown 转成 html 的 ruby 库),关闭智能脚本渲染,即把 superscript
改为 false
,否则会和 MathJax 冲突。
方法是进入 /usr/local/lib/ruby/gems/2.3.0/gems/kitabu-2.0.4/
目录,打开 lib/kitabu/markdown.rb
文件,把
self.processor = Redcarpet::Markdown.new(renderer, {
tables: true,
footnotes: true,
space_after_headers: true,
superscript: true,
highlight: true,
strikethrough: true,
autolink: true,
fenced_code_blocks: true,
no_intra_emphasis: true
})
修改为
self.processor = Redcarpet::Markdown.new(renderer, {
tables: true,
footnotes: true,
space_after_headers: true,
superscript: false,
highlight: true,
strikethrough: true,
autolink: true,
fenced_code_blocks: true,
no_intra_emphasis: true
})
最后,修改 mybook/templates/html/layout.erb
文件,以便在模板里引入 MathJax 及其配置文件,方法是在其 head
标签下插入如下内容,
即,把
<%= title %>
<%= highlight_theme %>
改成
<%= title %>
<%= highlight_theme %>
完成这些步骤后,我的电子书目录看起来像这样:
mybook/
├── Gemfile
├── Guardfile
├── MathJax
│ └── MathJax.js
├── MathJaxConfig.js
├── MathJaxRender.js
├── build-ebook.sh
├── config
├── fonts
├── images
├── output
├── templates
└── text
build-ebook.sh
的内容是这样的:
kitabu export --only=pdf
cd output
phantomjs ../MathJaxRender.js kitabu-ebook.pdf.html | prince --javascript -o ml-scikit-learn.pdf -
cd ..
其中调用 phantomjs
的那行命令就是用来生成带数学公式的电子书的。不要忘记了这个命令最后还有一个 -
字符,意思是从 stdin 里读取输入来转换为 PDF。
参考文档: Using MathJax with PrinceXML
结语
差不多就这些。奋力写作吧,只为自己成为自己的出版商。