Reveal.jsのスライドをdecktapeできれいにPDFにするための工夫

自分の作った、Reveal.jsのスライドをきれいなPDFにするまでにあれこれやった記録です。

HTMLスライドから遅れること2ヶ月、ようやくPyCon JPのPDF版スライドをSpeakerDeckにアップロードしました。

他の色々な要因もあったのですが、つまるところ「ちゃんと本来のHTMLスライドどおりの表現をしてるPDF」を作るのにえらく苦労したのが理由の一つだったりします。

ちょっとメモを兼ねて、「じゃあキレイなPDFを作るのにどうしないかいけないか」を整理しておきます。

前提・免責

  • ここでの「キレイなPDF」は、次の状態になっていることを指します

    • アスペクト比が、元のスライドとちゃんと同一になっていること

    • 文字(フォント)が、元のスライドと同等の構造であること(最低限、豆腐になっていないこと)

    • 貼り付けた画像類が、全て元のスライドどおりに表示されていること

  • 「自分の環境における解決」を主眼に置いているので、客観的に正しいことを保証しません

やったこと3点

サイズ概念の違いを意識してdecktapeを実行する

今回のスライドは Reveal.initialize 実行時に width: 1024, height: 768 で作成しています。

この状態で「decktape でPDF化」を考えれば、 当たり前のように decktape -s 1024x768 というオプションで実行しようとするわけなのですが、 これがキレイな表示にならないどころか、アスペクト比すら正しくならない状態で出力されてしまいます。

実際の挙動レベルでの確認なのですが、 で作成しても、そもそもこのアスペクト比でPDFが出力されない状況になりました。

SpeakerDeckにアップロード出来たものと比較すると、どうにも余白がかなり詰められてしまうようで、 若干のバッファを持たせないとキレイにならないみたいです。

とりあえずレイアウトを崩れない程度にアス比を維持できるサイズを適当に見繕っておくと良いでしょう。 (「同じ4:3だし、ちょっと広めで1280x960」ぐらいな感じで問題なさそうです)

Webフォントを指定する+そのフォントをローカルでも設定する

現在の decktape は、 puppeteer 経由でSS化・PDF化を行います。 Puppetter は内部的に Chromium を使っているので、普通にWebフォントをレンダリングしてくれます。

ので、全面的にWebフォントを使うようにしておけば、とりあえずちゃんと表示できるようになるみたいです。

body {
  font-family: 'Noto Sans JP', sans-serif;
}

何度か試行錯誤をした時点で、見えている挙動として、

  • オリジナルのDockerイメージでは現状だと確定で失敗する

  • Webフォント自体の取得は出来ないのか、ローカルに同じフォントファイルがないと失敗する

といった感じになるため、事前にGoogleフォントから使用しているフォントを取得して登録しておくと良いでしょう。

スライドの時点で画像がセクションをはみ出さないようにする

別件で同じタイプのスライドを正しいアス比・フォントでPDF化したのですが、 画像が欠落することがあります。

どういうケースで起きるかを見る限り、どうも「貼り付けた画像が本来のセクションの領域をはみ出す」時に、 PDF化の際に画像が欠落するみたいです。(多分ですが、表示しきれない=表示しないくていいと判断されてる?)

これについては、元画像とサイズに気をつけて貼るようにするしか、現状は対抗手段がありません。 とはいえ、もともと画像自体は「スライド内に全部を表示すること」を前提に作成しているため、 「プレビューちゃんとしましょうね」ということなんでしょう。

総括

おかげで、

  1. SphinxでReveal.jsのスライドを作る

  2. Reveal.jsのスライドをPDF化する

がキレイにできるようになったので、自分のやってみたいスタイルでの発表はこれからも続けられそうです。

派生な話ではありますが、 sphinx-revealjs は上記のことを自分がやりたいというモチベーションで作ってるので、 これからもちょくちょく使いやすくしていきたいかなと思ってます。