今日も微速転進

ここではないどこかへ

Pandocで生成したEPUBをRubyで修正してみる


スポンサーリンク

Pandocネタの続き。おそらく正しい対処法はPandocのfilter機能を使う方法。解説というよりは備忘録です。あしからず。

その場しのぎのやっつけとして適当なスクリプト言語で書き換える。

背景

PandocでEPUBを作る際に、--number-sectionsオプションを使うと章番号、セクション番号を自動的に割り振ってくれる。

しかし、「第n章」や「Chapter n」のようにはしてくれない。CSS疑似要素である程度は設定できるが、いずれにしろ標準機能では対応していない。

Pandocのバージョンは2.2.3.2。フォーマットはEPUB3。

EPUBと目次

EPUBの正体はCSSとHTML(正確に言うとXMLベース)の寄せ集めをZipで圧縮したものなので展開して編集して再度圧縮すれば問題ない。

EPUBには目次用のファイルとしてEPUB2用のtoc.ncxとEPUB3系のnav.xhtml、さらに目次ページが存在している。

問題はnav.xhtmlEPUBビューワーで目次ページとして表示する場合はCSSが使える。そのためCSS疑似要素で章番号のフォーマットをいじることができる。

残念ながらこのnav.xhtmlはナビゲーションパネルにも使用され、その場合はCSSは機能しない。故にCSSの疑似要素で章番号のスタイルを変えるという方式は 中途半端になってしまう*1

実際の対応

CSS疑似要素を使う方法+スクリプトによる修正。

hav.xhtmltoc.ncxスクリプトで書き換えて、本文側はCSSで擬似要素として実現する方式。

追加の要件として「付録」という見出しの章はセクションを含めて特別扱いする。

ただ、疑似要素による章見出しはKindle化した際に見栄えが良くないかも。

nav.xhtml<nav>要素で<ol><li><a>...というリストをラップしているだけ。もちろん<ol>要素が入れ子担っている点を考慮する必要がある。

NokogiriのXPath指定で<a>タグを取り出して条件に合うところだけ書き換える。XMLなのでnamespaceを考慮する。

chapter_node = node.xpath('./xmlns:a')

章番号、セクション番号ともに<a>タグの内側に<span>タグで囲まれているので正規表現でマッチしたところを書き換える。

toc.ncxの修正

章の見出しだけ書き換える。<navLabel>というタグの要素を取り出す。

ncx_xml.xpath('//xmlns:navLabel/xmlns:text') 

<navLabel>というタグの下に<navLabel>というタグがあるので親のタグだけ書き換える。

本文側の修正

./EPUB/text/ch00X.xhtmlの各ファイルを修正する。以下のような形式なので対して難しくない。

<h1><span class="header-section-number">5</span>

付録扱いしたいChapterだけ<span>タグのクラスを置き換えて対処。それ以外はCSSで対応。

h1 > span.header-section-number::before {
  content: "第" ;
}

h1 > span.header-section-number::after {
  content: "章" ;
}

スクリプトによる修正

EPUB_tempというフォルダに展開しているという前提。

  • 付録のChapter は「付録A」「付録B」でセクション番号がA.1、A.2となるように
  • 章見出しは「第1章」という形式に(目次はテキストをスクリプトで編集、本文側はCSS

EPUBビューワーの目次ページではCSSが効くが、目次パネル(?)ではCSSが効かないのでこういう微妙な対処方法に。

書き換えの対象

Nokogiriのインストール

$ gem install nokogiri

コード

Pandocで生成したepubファイルの目次情報と章番号を修正するRubyスクリプト

ザ・やっつけ仕事ですが似たようなことをやる人の参考になりますようにということで。

展開と再圧縮

これも備忘録。実際はRakeで一気にやっています。

展開

$ unzip -q temp.epub -d _temp

temp.epubというEPUB3形式のファイルを_tempに展開。

再圧縮

必要な箇所を修正したら再度圧縮する。mimetypeというファイルだけ圧縮率0にする。

展開先のディレクトリ(この例では_temp)に移動してから再圧縮。

$ cd _temp

まずmimetypeというファイルだけ入ったファイルを作り、その後で残りのファイルを圧縮してくっつけるイメージ。

$ zip -0Xq output.epub mimetype
$ zip -Xr9Dq outoput.epub *

これでOK。

参考

EPUB生成のpandocのコマンドは下記のとおり。

$ pandoc -f markdown -t epub3 --epub-metadata=metadata.xml -o temp.epub title.txt *.md --epub-cover-image=image.png --css=github.css --toc --toc-depth=2 --epub-chapter-leve=1 --number-sections --no-highlight

title.txtはタイトルと著者、元データはMarkdown

参考にしたサイトは次のとおり。

まとめ

EPUBがWeb技術ベースなのでこれまでの知識がかなり活用できている。EPUBの仕様策定に関わった方々の好判断の賜物。

ちゃんとPandocのfilter機能を勉強するのが一番だけど。

EPUB 3 電子書籍制作の教科書

EPUB 3 電子書籍制作の教科書

*1:もちろんナビゲーションパネルと目次ページ、本文で章番号の形式が変わってもいいなら問題ない

広告