pandoc:用 docs 生成 epub
最近网上找了一本 epub 电子书,但目录结构紊乱,决定处理一下。
epub 本身很难处理。可以用 Calibre 来编辑 epub 文件,但这个不会。所以找了个网站 https://rare2pdf.com/epub-to-docx/ 转换成 docx 文件然后处理。
docx 编辑的注意事项
- 需要使用 Word/WPS 内置的标题
Headings功能来处理书签和层级。 - 需要使用脚注来处理引用
使用 pandoc 转换文档
安装说明: https://zhuanlan.zhihu.com/p/682455380
转换命令
pandoc input.docx -o output.epub --epub-cover-image=cover.jpg --metadata title="书名"
通过上述命令设置封面图片和书名。默认情况下,pandoc 只会处理第一级 heading 并为其设置书签链接。
我们可以通过添加 --epub-chapter-level=5 参数的方式,来指定 heading 深度。
但请注意,不论标题层级大小,在 pandoc 转换的时候,都会被解析成一个 epub 章节,对应一个 xhtml 文件,然后这些 xhtml 文件顺序拼接,最后显示为 epub 电子书。
弹出式脚注
在 pandoc 的自动转化下,脚注会以超链接的形式跳转到文档章节尾部。然后再借助脚注最后的超链接返回原位。这样非常干扰阅读体验。
epub3 支持弹出式脚注。即可以生成一个小弹窗,显示脚注内容,而不需要跳转到章节尾部。
要想支持这个功能,需要添加额外的 lua 脚本,来识别转换原脚注文本。并添加 --lua-filter=epub_footnote.lua 参数。
完整的命令行脚本可以是:
pandoc input.docx -o output.epub --epub-cover-image=cover.jpg --metadata title="书名" --epub-chapter-level=5 --lua-filter=epub_footnote.lua
微信读书支持弹出式脚注。特别是通过微信读书APP内加载的书能够正常支持弹出式脚注,但通过 epub 格式导入的,以 aside 标签作为标注的脚注,似乎并不支持。也可能是我脚本写的不对。留待后续探索。
-- epub_footnote.lua
counter = 1
function Para(el)
local blocks = {}
local inlines = {}
for _, inline in ipairs(el.content) do
if inline.t == 'Note' then
local id = "fn" .. counter
local ref = pandoc.RawInline('html', '<a href="#' .. id .. '" epub:type="noteref">[' .. counter .. ']</a>')
table.insert(inlines, ref)
local footnote_content = pandoc.utils.stringify(inline.content)
local aside_html = '<aside id="' .. id .. '" epub:type="footnote"><p>[' .. counter .. ']' .. footnote_content .. '</p></aside>'
table.insert(blocks, pandoc.RawBlock('html', aside_html))
counter = counter + 1
else
table.insert(inlines, inline)
end
end
-- 返回一个段落 + 若干个脚注块
local result = { pandoc.Para(inlines) }
for _, b in ipairs(blocks) do
table.insert(result, b)
end
return result
end
function Header(el)
local blocks = {}
local inlines = {}
for _, inline in ipairs(el.content) do
if inline.t == 'Note' then
local id = "fn" .. counter
local ref = pandoc.RawInline('html', '<a href="#' .. id .. '" epub:type="noteref">[' .. counter .. ']</a>')
table.insert(inlines, ref)
local footnote_content = pandoc.utils.stringify(inline.content)
local aside_html = '<aside id="' .. id .. '" epub:type="footnote"><p>[' .. counter .. ']' .. footnote_content .. '</p></aside>'
table.insert(blocks, pandoc.RawBlock('html', aside_html))
counter = counter + 1
else
table.insert(inlines, inline)
end
end
-- 新的标题块
local new_heading = pandoc.Header(el.level, inlines, el.identifier, el.classes, el.attributes)
local result = { new_heading }
for _, b in ipairs(blocks) do
table.insert(result, b)
end
return result
end

浙公网安备 33010602011771号