用编程的方法制作电子书- CSS实现PDF和EPUB

1,635 阅读6分钟

当我写 "书"《最伟大的CSS技巧》第一卷时,我把 "书 "放在引号里,因为它并没有什么可怕的书的样子。你可以阅读它的_唯一_途径是在线,登录这个网站,拥有一个MVP支持者会员资格。没有印刷版本,甚至没有你所期望的数字书的数字副本。

现在我已经改变了这一点,提供PDF和EPUB版本的书。它们对会员来说是免费下载的--只要把它们加入你的购物车并结账。

所有这些写书的东西过去和现在都是一种实验。我喜欢在这个网站上以类似博客文章的形式写作,所有的内容都在URL上,可以有互动内容。由于是数字化的,我可以控制访问等。这意味着我可以用一种对我来说很舒服的方式来写作,也许--只是--也许,我可以更多产。也许我可以完成我已经有一大堆想法的第二卷。也许我可以写一些我一直在想的其他书。现在我有了一个系统!一个可以写作的地方,多个可以出版的地方,以及一个可以销售的方法。

制作数字版本

当我最初选择在网上写这本书时,我想PDF将是非常简单的。我将在一个 "原始 "模板上输出内容(只是作为一个干净的起点,它将持续下去,并易于预览),应用漂亮的类似于打印的CSS,然后,从字面上看,只是 ⌘P(打印)和 "保存为PDF "就可以了。

Print dialog bog in Google Chrome, with the Save as PDF option chosen.

这其实还挺管用的。你可以摆弄一下设置(例如,"✔打印背景图",以便在代码块等深色背景上显示白色文字),这样就可以得到相当好的效果。但也有一些问题--比如你不能很好地控制每页的页眉或页脚。更不用说它不是程序化的,而是一个非常手动的过程。

以编程方式做事情是我的目标。然后我偶然看到Baldur Bjarnason的这篇博文,他在其中寻找工作。

- 你是否需要制作一个或多个网站,像书一样行走,像书一样说话,像书一样阅读,但你制作的所有东西看起来都像一个博客?

- 你是否在使用网络技术处理PDF、DOCX或EPUB等文件格式时遇到困难?

- 你是否试图从你的网站或你的CMS制作PDF或电子书?

以编程方式创建电子书

我联系了Baldur,他能够帮助我解决这一切。他为我创建了一个自动化系统,接受一个本地.html 文件,并从该单一文件中自动生成PDF、EPUB和MOBI格式。基本上,我可以从命令行中运行make ,它将利用开源工具完成所有工作。

VS Code showing there terminal open running a Makefile script producing the eBooks.

不过,我仍然需要为机器准备好接近完美的HTML,这需要一些工作。幸运的是,我已经在某种程度上准备好了,因为我有一个特殊的URL,可以输出原始内容(如果你不是会员,你仍然可以看到这个,只是截断了内容)和我想要的浅色印刷风格。

工具

有了原始的HTML和程序化的方法,下面是组成这个堆栈的工具。

  • **对于PDF创建,**我们尝试了Paged.jsWeasyPrint。它们都有各自的怪癖,做的事情比对方差/更好。我们最终选择了Paged.js。
  • **对于EPUB的创建,**我们使用pandoc
  • 对于MOBI创建(我们根本没有关注),我们使用Calibre。这是一个原生的Mac应用程序,但它有一个埋在里面的ebook-convert ,可以从命令行调用。

为了达到我们可以通过命令行使用这些工具的程度,各种其他软件都必须安装并准备使用,如Pythonpangolibffi等等。Baldur的脚本使管理这些很容易,这很了不起。

看起来有一个叫Percollate)的新玩家在做这些事情,但我们没有去探索。

一个结合了所有这些工具的HTML-to-eBook创作的公共Repo

在我们一起完成这个过程之后,Baldur慷慨地创建了一个开源的、经过精简的公共版本(book-tricks),供大家参考。这个Makefile里有很多有用的魔法,如果它对和我有同样处境的人没有用处,我会感到震惊:需要从简单的HTML创建电子书。

预览构建

当然,PDF很容易查看(你甚至可以只使用网络浏览器),但我一般都是在Preview.app中弹开。

EPUB在Mac上也同样容易,因为你可以直接把它弹到Books.app中查看。

Mac app Books.app with the EPUB version of the book open.

对于MOBI,Calibre的主要功能是查看这些,所以这就是其中的诀窍。

最痛苦的部分是反馈循环。有一个更新代码(主要是CSS)的整个过程,然后运行整个构建,看看这一切看起来如何。我肯定我做了100次或更多的事情,以使事情正确。这真的应该有一个更好的故事,有实时预览。

纯网络与纯电子书的内容

在写书的早期,我已经放弃了纸质和数字版本。我不再像以前那样倚重文本中的图片,而是开始使用嵌入式CodePen演示来展示输出和代码。无论如何,这是在网络上的理想体验。但我不能在电子书中使用嵌入式笔。电子书可以做一些互动的事情(例如,EPUB支持GIF动画和链接,当然),但运行JavaScript和使用<iframe>s是我不想指望的事情。如果我为所有的东西都准备了适当的图像,那么无论如何,_只是也许_它更能为纸上谈兵做准备。

display: none ,从电子书输出中隐藏东西是很容易的,所以我对所有嵌入的Pens都是这样做的。(它们在转化为iframe之前是一点HTML。)然后为了有只用于电子书版本的 "备用 "内容,我基本上只是把这些东西用<div class="print-only"> ,在网上隐藏起来,在印刷的CSS中显示出来。我在WordPress的块编辑器中制作了自定义的块,以使编写这些块更容易。这样,我可以真正看到我在做什么。

一个有趣的地方是,因为我在这里只做电子书,所以我不需要做我习惯的那种CSS技巧,比如打印样式表,因为那里的输出可能是一些电脑纸。例如,在打印样式表中,我可能通常会这样做。

main a[href]::after {
  content: " (" attr(href) ") ";
}

这样,人们可以看到内容中的链接的URL。但对于这些数字电子书,我只是确保链接是蓝色的,它们在任何数字格式中都可以点击。


这是一个有趣的旅程!我很高兴在这些方面的理解上有了一些进展,特别是因为在数字画布上渲染东西是我的工作内容。不过,我只爬了几级,因为这东西的学习曲线相当陡峭啊!"。