RubyによるMarkdownをベースにしたEPUB電子書籍の作り方と出版のお知らせ ブログが電子書籍に変わる日
「情報革命」とは何でしょうか。それはネットを介した大量情報の流入による社会生活の変化の連続のことです。情報革命の初期に始まる一つの変化は「見る変化」です。情報を最も効率的に処理できる人間の入力デバイスは「目」であり、そのための環境作りがまず構築されるでしょう。
スマートフォンが携帯電話を駆逐したのは、iPhoneのデザインが素晴らしかったからではありません。人々が大量の情報を処理するためには、非効率な「耳」デバイスを置いて、より効率的な「目」デバイスを活用する必要があったからです。
7インチタブレットの新製品投入が相次いでいます。これは何を意味し、何を駆逐するのでしょうか。そのフォルムを見れば答えは明らかでしょう。それはまさに「書籍」なのです。7インチタブレットは「アトムの読書」を「ビットの読書」にすべて置き換えようとしています。
スマートフォンは、話し言葉を文字化して見るためのデバイスとして登場しました。そして7インチタブレットは、文章を読むのに最適化されたデバイスとして今ここに登場したのです。
「見る変化」第二幕の始まりです…
スマホもタブレットも持ってない僕が、偉そうに言うことじゃありませんでしたね!(えっ?)
ブログを電子書籍化する
さて、そうなると僕はこのブログの行く末が心配です。ブログというメディアはもっぱら大型モニタ用に作られたメディアですから、7インチタブレットにおける快適な読書体験に適しているかというと疑問が残ります。苦労して書いた記事を誰も読まない日が来るとしたら悲しいです。承認欲求が満たされません。ブコメやツイートでの「面白い」「へぇ〜」とかの言葉を食べて今日まで生きてきたのに。
そんなわけで…
Jekyllを使ったこのブログ記事を電子書籍化するツール「Maliq
」をRubyで作りました!
rubygems: Maliq github: melborne/maliq
つまりMaliq
は、Liquid拡張されたMarkdown形式のコンテンツからEPUBパッケージを作るツールです。Liquidにより実現されているコードのsyntax highlightingやAmazonリンク付きのコンテンツを、そのまま電子書籍化できます。「Markdown」と「Liquid」の頭を取って「Maliq」です。Mr. マリック(Maric)とは何の関係もありません。
Maliqは、maliq
とmaliq_gepub
という2つのコマンドを持っていて、これらのコマンドで簡単にEPUBパッケージが作れるようになっています。maliq はMarkdownをXHTMLに変換し、maliq_gepubはXHTMLファイルからEPUBパッケージを生成します。
maliq_gepubは、小嶋智さんによる「Gepub」というEPUB3に対応した、Ruby製EPUBジェネレータの単なるラッパーです。Maliqにおける変換の仕事の大半はこのGepubで実現されています。素晴らしい!
Maliqの使い方
以下ではMaliqの使い方を説明しています。MaliqはGem化されているので、gem install maliq
で入手できます。gepubも同時にインストールされます。
コマンドの使い方
以下の手順に従います。
1. Markdownで書かれたコンテンツファイルを準備する(ex. chapter01.md)。
2. EPUB生成に必要とされるメタ情報をYAMLフォーマットでファイル(複数ある場合は最初のファイル)先頭に記述する(Yaml Front Matter)。
3. ファイル内にチャプター区切りを示す特別のマーカーを書くことで、1つのMarkdownファイルを分割して複数のXHTMLファイルを生成できる。デフォルトでのマーカーの書式は`<<<--- <filename> --->>>`(ex. `<<<--- chapter02 --->>>`)。
4. CSSおよび画像ファイルがあるなら、カレントディレクトリまたはそのサブディレクトリに配置する。
5. コンテンツに特別なLiquid Tagが含まれている場合、対応Pluginを`plugins`サブディレクトリに置く。
6. `maliq`コマンドにMarkdownファイル名を渡して実行する(maliq chapter01.md)。これにより、1または複数のXHTMLファイルがカレントディレクトリに生成される。
7. `maliq_gepub`を実行する。これにより、EPUBファイルがカレントディレクトリ生成される。
Yaml Front Matterのサンプル
YFMのサンプルを示します。
---
language: 'en'
unique_identifier:
- 'http:/example.jp/bookid_in_url'
- 'BookID'
- 'URL'
title: 'Book of Charlie'
subtitle: 'Where Charlie goes to'
creator: 'melborne'
date: '2012-01-01'
---
トリプルダッシュの行の間に、EPUB生成で必要とされるメタ情報をYAMLフォーマットで記述します。メタ項目については以下が参考になります。
Epub Format Construction Guide - HXA7241 - 2007
Liquid plugins
ネット上には各種Liquid pluginがありますが、Maliqでそれらを利用するためには少し修正が要ります。例えば、ネット上のデータにアクセスする必要のあるpluginではそれをローカル保存するような修正が必要になるでしょう。gistにJekyll向けliquid pluginを修正した僕のpluginが少し置いてあるので利用して下さい。
コードでの使い方
上記コマンドでは定型的なことしかできません。より柔軟に変換を行いたい場合にはRubyでコードを書く必要があります。
Maliq::Converter.new
にMarkdownテキストを渡して#run
メソッドを実行します。
puts Maliq::Converter.new("#header1\nline1\n\nline2").run
これにより以下が得られます。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="ja">
<head>
<title></title>
</head>
<body>
<h1>header1</h1>
<p>line1</p>
<p>line2</p>
</body>
</html>
pluginでliquid tagをパースするためには、pluginのフォルダを指定する必要があります。これはYaml Front Matterまたは#set_meta
メソッドで行います。フォルダのデフォルトはplugins
になっているので、その場合は指定は不要です。
Maliq::Converter.new(<<-EOS).run(false)
---
liquid: 'filters'
---
# header1
{% calc 2 + 3 %}
EOS
これによりfilters
というフォルダ名にあるcalc pluginが使えるようになります。出力です。
<h1>header1</h1>
<p>2 + 3 = 5</p>
#run
にfalseを渡すとbody要素のみを返します。
簡単なチュートリアル
次に、順を追って電子書籍を実際に作ってみます。
コンテンツを準備する
まずはMarkdownによるコンテンツを用意します。作業ディレクトリをmy_first_ebook
、ファイル名をchapter01.md
とします。
このコンテンツにおけるポイントは次の3点です。
1. コンテンツは"Syntax Highlighting", "Gist", "Amazon Link"用のLiquid Tagを含んでいる。
2. ファイル先頭のYaml Front Matterにおいてメタ情報を定義している。
3. 各章の前にチャプター区切りマーカーを配置している。
Syntax HighlightingにはPygmentsとそのRubyラッパーpygments.rb
を使うので、事前にそのインストールが必要になります。以下を参考にしてください。
pygments.rbはgem install pygments.rb
です。
またAmazon Linkを使うには、AWSのアカウントとruby-aawsのインストールが必要になります。以下を参考にしてください。
Amazon Plugin for Octopress - Zanshin.net
YFMにおいてunique_identifier
、title
属性は必須です。language
属性も本来必須の属性ですが、Maliqではデフォルトを’ja’としているので、その場合は省略できます。
チュートリアル用に小説を用意しました。上記ポイントに注意しながら目を通してください。中身は気にせずに…
chapter01.md
---
unique_identifier:
- 'http:/example.jp/bookid_in_url'
- 'BookID'
- 'URL'
title: 'Rubyと鶏卵'
subtitle: 'Egg in the Ruby'
creator: 'melborne'
date: '2012-12-01'
---
# 1章 私を煮るなら殻にして
今にして思えばあの時にちゃんとRubyの中に鶏卵を納めておくべきだった。そうすれば、彼女がこんなに変わってしまうことはなかった。そのときの光景はおぞましくも僕の脳裏に焼き付いて離れないけど、それをコードで表現するなら差し詰め次のようになるだろう。
{% highlight ruby %}
if egg.nil?
egg = Egg.new
elsif egg.empty?
egg << Egg.new
end
{% endhighlight %}
僕はここで重大なミスを犯す。彼女は`egg`がnilのときにカラにして欲しいと望んだのに、どういう訳か僕は誤って`Egg.new`してしまった。
それからだった。彼女のすべてが変わってしまったのは。
<<<--- chapter02 --->>>
# 2章 怠惰な日々とはにわとGeorge
ルート101を北に向かってもう3時間も休みなしに走ってる。隣には「デカバチンはにわ」が100個ほど置いてある。全くやってられない。彼女は「デカバチンはにわ100個をGeorgeに必ず渡して」って言ったけど、僕はGeorgeがどこで何を生業として生きている人間であるかの情報を、これっぽっちも持ち合わせていない。あるのは彼がRubyと鶏卵に深い造詣があるという彼女からの情報だけだ。それとてフタシカなものだけれども。僕の今の陰鬱な気分をせめてコードで表現させてほしい。
{% gist 4174909 ruby_egg.rb %}
あぁ、どうやら頭が混乱しているようだ。これは昨日Stefanieが僕にpushしたコード片じゃないか。全く、どうかしているよ。
<<<--- chapter03 --->>>
# 3章 僕とタップを踊ろうよ、どんな意味においても
要約するならば、まあ僕がどうしようもなく世間知らずな若造だった、ってことだ。「デカバチンはにわ」を待ってるGeorgeなんて男は元々この世には存在しなかったし、`egg`がemptyのときは`Egg.new`をappendするってのも悪い方策とも言えない。問題の根本解決にはならないかもしれないけれども。それでも僕はルート101とはにわ100個の不整合性には、もっと早くに気づくべきだった。この一件に関しては完全に僕の負けを認めざるを得ない。ゴメンよRuby。許してくれるなら、僕とタップを踊ろうよ。どんな意味においても。
完
{{ 4806906557 | amazon_medium_image }}
{{ 4806906557 | amazon_link }}
小説中のgist tagはgistサーバー上のコードを指し示しています。内容は次のとおりです。
melborne’s gist: 4174909 — Gist
ruby_egg.rb
# encoding: UTF-8
∞= 1.0/0
(1..∞).lazy.map {|i| Statue.new(i) }
.select {|statue| statue.of_liberty? }
.take(100).send(:george)
# ~> YouLazzyError: undefined method ‘lazy’ for 1..Infinity:Range
Liquid Pluginの配置
次に、plugins
サブディレクトリを作って、ここにpluginを配置します。ここでは僕のgist上のものをcloneします。
Liquid filters for maliq gem to generate xhtml — Gist
my_first_ebook% mkdir plugins
my_first_ebook% git clone git://gist.github.com/4134497.git plugins
結果、ファイル構成は次のようになります。
my_first_ebook% tree
.
├── chapter01.md
└── plugins
├── amazon_liquid_tags.rb
├── gist_tag.rb
├── highlight.rb
└── syntax.css
1 directory, 5 files
CSSおよび画像ファイルの配置
CSSや画像がある場合は、それぞれcss, imagesなどのサブディレクトリを作って配置します。ここではcss
ディレクトリを作って、簡単なスタイルシートstyle.css
とsyntax highliting用のsyntax.css
を配置します。syntax.cssは先程gistからcloneした中に含まれるものを使います。style.cssは以下のとおりです。
h1, h2, h3 {
color: #8B1A1A;
}
ol {
list-style-type: none;
}
ここでは実践しませんが、表紙画像がある場合はファイル名にcover
を使って(ex. cover.jpg)、imagesディレクトリに配置します。
XHTMLファイルの生成
さて下準備ができたので、maliq
コマンドを使ってEPUB用XHTMLファイルを生成します。
my_first_ebook% maliq chapter01.md
/Users/keyes/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': iconv will be deprecated in the future, use String#encode instead.
'chapter01.xhtml' created.
'chapter02.xhtml' created.
Image downloading...
'chapter03.xhtml' created.
警告が出ますが、気にせずに生成されたファイル群を見てみます。
my_first_ebook% tree
.
├── chapter01.md
├── chapter01.xhtml
├── chapter02.xhtml
├── chapter03.xhtml
├── css
│ ├── style.css
│ └── syntax.css
├── images
│ └── 51C9X825VXL._SL160_.jpg
└── plugins
├── amazon_liquid_tags.rb
├── gist_tag.rb
└── highlight.rb
2 directories, 8 files
chapter01〜03のXHTMLファイルが生成され、Amazonリンクに係る画像データがDLされているのが分かります。
chapter01.xhtmlの中身をちょっと覗いてみます。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="ja">
<head>
<title>Rubyと鶏卵</title>
<link href='css/style.css' rel='stylesheet' type='text/css'/>
<link href='css/syntax.css' rel='stylesheet' type='text/css'/>
</head>
<body>
<h1>1章 私を煮るなら殻にして</h1>
<p>今にして思えばあの時にちゃんとRubyの中に鶏卵を納めておくべきだった。そうすれば、彼女がこんなに変わってしまうことはなかった。そのときの光景はおぞましくも僕の脳裏に焼き付いて離れないけど、それをコードで表現するなら差し詰め次のようになるだろう。</p>
<div class="highlight"><pre><code class="ruby"><span class="k">if</span> <span class="n">egg</span><span class="o">.</span><span class="n">nil?</span>
<span class="n">egg</span> <span class="o">=</span> <span class="no">Egg</span><span class="o">.</span><span class="n">new</span>
<span class="k">elsif</span> <span class="n">egg</span><span class="o">.</span><span class="n">empty?</span>
<span class="n">egg</span> <span class="o"><<</span> <span class="no">Egg</span><span class="o">.</span><span class="n">new</span>
<span class="k">end</span>
</code></pre></div>
<p>僕はここで重大なミスを犯す。彼女は<code>egg</code>がnilのときにカラにして欲しいって望んだのに、どういう訳か僕は誤って<code>Egg.new</code>してしまった。</p>
<p>それからだった。彼女のすべてが変わってしまったのは。</p>
</body>
</html>
うまく行ったようです。
EPUBパッケージの生成
さて、最後にmaliq_gepub
コマンドを使って、EPUBファイルを生成します。
my_first_ebook% maliq_gepub -o ruby_egg.epub
my_first_ebook% ls -l
total 56
-rw-r--r-- 1 keyes staff 2733 11 30 19:07 chapter01.md
-rw-r--r-- 1 keyes staff 1541 11 30 21:21 chapter01.xhtml
-rw-r--r-- 1 keyes staff 1190 11 30 21:21 chapter02.xhtml
-rw-r--r-- 1 keyes staff 2065 11 30 21:21 chapter03.xhtml
drwxr-xr-x 3 keyes staff 102 11 30 21:21 images
drwxr-xr-x 6 keyes staff 204 11 30 19:27 plugins
-rw-r--r-- 1 keyes staff 11716 11 30 21:43 ruby_egg.epub
生成されたruby_egg.epub
の中身を見てみます。
my_first_ebook% unzip -v ruby_egg.epub
Archive: ruby_egg.epub
Length Method Size Ratio Date Time CRC-32 Name
-------- ------ ------- ----- ---- ---- ------ ----
20 Stored 20 0% 11-30-12 21:43 2cab616f mimetype
252 Defl:N 172 32% 11-30-12 21:43 e0f26a53 META-INF/container.xml
1541 Defl:N 740 52% 11-30-12 21:43 a0b369fe OEBPS/chapter01.xhtml
1190 Defl:N 748 37% 11-30-12 21:43 6b7298be OEBPS/chapter02.xhtml
2065 Defl:N 1062 49% 11-30-12 21:43 7dd26128 OEBPS/chapter03.xhtml
6034 Defl:N 6003 1% 11-30-12 21:43 988e6d97 OEBPS/images/51C9X825VXL._SL160_.jpg
710 Defl:N 377 47% 11-30-12 21:43 0b041246 OEBPS/nav.html
542 Defl:N 370 32% 11-30-12 21:43 05e77aca OEBPS/nav.xhtml
1504 Defl:N 552 63% 11-30-12 21:43 30d6f9d0 OEBPS/package.opf
1227 Defl:N 514 58% 11-30-12 21:43 0a6ee4da OEBPS/toc.ncx
-------- ------- --- -------
15085 10558 30% 10 files
よさそうです。
では、EPUBリーダーでファイルを開いてみます。
いいですね!
EPUB電子書籍の完成です。
電子書籍「これからRubyを始める人たちへ」の販売について
このEPUB生成ツールを使って、早々このブログにおけるRubyの入門記事を1つ電子書籍化しました。
そしてこれに表紙を付けて、「Gumroad」を通して販売させて戴くことにしました。
価格は100円です。
コンテンツについては、ブログ記事「これからRubyを始める人たちへ」における、誤記の修正およびメディア向けの調整を行っていますが、実質的な内容についての追加・変更はありません。したがってテキストに関し、有料購入する価値は無いと思います。しかしながら、次の何れかの理由で興味を持たれる方が居られるかもしれません。
コンテンツに関心があるので、それが電子書籍の形態で読めるのはやはり便利だ。
コードのSyntax HighlightingをEPUBで実現したものをあまり見たことがない。どんなものかちょっと見てみたい。
このEPUB生成ツール
Maliq
に関心がある。つまり自分もブログを電子書籍化したいので、その出力サンプルとして参考にしたい。ブログの記事を読んだが参考になった。これが無料なんて申し訳なく思うから買ってあげたい。
ブログの記事は読んでないが、興味はあるのでどうせなら電子書籍で読んでみよう。
なんか表紙が気に入ったからそれを眺めるために買ってみよう。
このブログのネタは全体としてなかなか面白い。これからも継続して欲しいので寄付の気持ちで購入してもいいかな。
タブレットを買ったばかりなので、いろいろな電子書籍を衝動買いしたい。
今日はいい気分だ。だれでもいいから俺の100円受け取って。
次のリンクはGumroadにおける商品購入リンクになっています。クリックすると、オーバーレイ・ウインドウが立ち上がって、この場でクレジットカード決済による購入が可能です。購入にはクレジット情報およびメールアドレスの入力が必要になります。購入すると、入力したメールアドレスにコンテンツのDLリンクが送られてきます。
ご検討のほど、よろしくお願いしますm(__)m
なお、EPUBはAmazon Kindleでは読めないので、mobiなどへの変換が必要です。変換には「calibre」が便利です。
以上、EPUB生成ツールMaliq
の紹介と 電子書籍「これからRubyを始める人たちへ」の宣伝でした。
関連記事:エラーメッセージから学ぶ電子書籍EPUB - 最初の一歩
(追記:2012−12−04) pygments.rbのインストールについて追記しました。
Kindle Paperwhite 3G (2012年モデル)
blog comments powered by Disqus