tmtms-review 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.travis.yml +9 -0
- data/COPYING +515 -0
- data/ChangeLog +2083 -0
- data/README.rdoc +50 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/bin/review-check +178 -0
- data/bin/review-checkdep +63 -0
- data/bin/review-compile +205 -0
- data/bin/review-epubmaker +661 -0
- data/bin/review-epubmaker-ng +176 -0
- data/bin/review-index +118 -0
- data/bin/review-pdfmaker +208 -0
- data/bin/review-preproc +142 -0
- data/bin/review-validate +51 -0
- data/bin/review-vol +102 -0
- data/debian/README.Debian +12 -0
- data/debian/README.source +5 -0
- data/debian/changelog +5 -0
- data/debian/compat +1 -0
- data/debian/control +22 -0
- data/debian/copyright +62 -0
- data/debian/docs +6 -0
- data/debian/manpage.1.ex +59 -0
- data/debian/patches/path.diff +91 -0
- data/debian/patches/series +1 -0
- data/debian/review.install +13 -0
- data/debian/review.links +4 -0
- data/debian/rules +13 -0
- data/debian/source/format +1 -0
- data/doc/format.rdoc +582 -0
- data/doc/format_idg.rdoc +180 -0
- data/doc/libepubmaker/sample.yaml +90 -0
- data/doc/quickstart.rdoc +188 -0
- data/doc/ruby-uuid/README +11 -0
- data/doc/ruby-uuid/README.ja +34 -0
- data/doc/sample.css +108 -0
- data/doc/sample.yaml +62 -0
- data/lib/epubmaker.rb +28 -0
- data/lib/epubmaker/content.rb +82 -0
- data/lib/epubmaker/epubv2.rb +418 -0
- data/lib/epubmaker/epubv3.rb +249 -0
- data/lib/epubmaker/producer.rb +204 -0
- data/lib/epubmaker/resource.rb +66 -0
- data/lib/lineinput.rb +155 -0
- data/lib/review.rb +3 -0
- data/lib/review/book.rb +46 -0
- data/lib/review/book/base.rb +235 -0
- data/lib/review/book/chapter.rb +81 -0
- data/lib/review/book/compilable.rb +159 -0
- data/lib/review/book/index.rb +339 -0
- data/lib/review/book/page_metric.rb +38 -0
- data/lib/review/book/parameters.rb +97 -0
- data/lib/review/book/part.rb +44 -0
- data/lib/review/book/volume.rb +65 -0
- data/lib/review/builder.rb +444 -0
- data/lib/review/compiler.rb +550 -0
- data/lib/review/configure.rb +38 -0
- data/lib/review/epubbuilder.rb +18 -0
- data/lib/review/exception.rb +21 -0
- data/lib/review/extentions.rb +3 -0
- data/lib/review/extentions/object.rb +9 -0
- data/lib/review/extentions/string.rb +33 -0
- data/lib/review/htmlbuilder.rb +1097 -0
- data/lib/review/htmllayout.rb +19 -0
- data/lib/review/htmlutils.rb +36 -0
- data/lib/review/i18n.rb +30 -0
- data/lib/review/i18n.yaml +34 -0
- data/lib/review/idgxmlbuilder.rb +1145 -0
- data/lib/review/latexbuilder.rb +815 -0
- data/lib/review/latexindex.rb +35 -0
- data/lib/review/latexutils.rb +79 -0
- data/lib/review/preprocessor.rb +563 -0
- data/lib/review/review.tex.erb +232 -0
- data/lib/review/textbuilder.rb +17 -0
- data/lib/review/textutils.rb +66 -0
- data/lib/review/tocparser.rb +342 -0
- data/lib/review/tocprinter.rb +221 -0
- data/lib/review/topbuilder.rb +785 -0
- data/lib/review/unfold.rb +138 -0
- data/lib/uuid.rb +312 -0
- data/review.gemspec +141 -0
- data/test/CHAPS +2 -0
- data/test/bib.re +13 -0
- data/test/book_test_helper.rb +35 -0
- data/test/test.re +43 -0
- data/test/test_book.rb +598 -0
- data/test/test_book_chapter.rb +418 -0
- data/test/test_book_parameter.rb +42 -0
- data/test/test_book_part.rb +50 -0
- data/test/test_builder.rb +144 -0
- data/test/test_compiler.rb +44 -0
- data/test/test_epubmaker.rb +507 -0
- data/test/test_helper.rb +27 -0
- data/test/test_htmlbuilder.rb +554 -0
- data/test/test_htmlutils.rb +28 -0
- data/test/test_i18n.rb +64 -0
- data/test/test_idgxmlbuilder.rb +589 -0
- data/test/test_index.rb +31 -0
- data/test/test_latexbuilder.rb +656 -0
- data/test/test_lineinput.rb +198 -0
- data/test/test_preprocessor.rb +23 -0
- data/test/test_textutils.rb +68 -0
- data/test/test_topbuilder.rb +244 -0
- data/test/test_uuid.rb +156 -0
- metadata +161 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
For GitHub users;
|
|
2
|
+
|
|
3
|
+
This is a pure-ruby implementation of RFC4122 that I wrote back in
|
|
4
|
+
2005. I have touched its internals a few times (mainly bugfixes). I
|
|
5
|
+
know someone has already uploaded an old copy of it to GitHub, and
|
|
6
|
+
thats' 100% legal he has the right to do so, but I believe what I have
|
|
7
|
+
now is better than the older ones. So I upload this.
|
|
8
|
+
|
|
9
|
+
It's very tiny (<300 lines ruby code) and you can simply copy
|
|
10
|
+
lib/uuid.rb to your project. The gemspec file can help you maintain
|
|
11
|
+
your dependency though.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
UUID: Pure-ruby RFC4122 Implementation
|
|
2
|
+
|
|
3
|
+
RFC4122をフルサポート(はず)のライブラリ。使いかたは
|
|
4
|
+
|
|
5
|
+
require 'uuid'
|
|
6
|
+
UUID.create # => instance
|
|
7
|
+
|
|
8
|
+
とか。
|
|
9
|
+
|
|
10
|
+
基本的にUUIDってのは存在していることに意味があるオブジェクトなため、それ自身には
|
|
11
|
+
ほとんどインスタンスメソッドを持たない。以下はその数少ないメソッドたち
|
|
12
|
+
|
|
13
|
+
* UUID#==, UUID#<=>
|
|
14
|
+
比較。RFC4122によるとなぜかUUIDは順序つきなんだそうだ。何に使うのか不明。RFCに準
|
|
15
|
+
拠するためだけのメソッド。
|
|
16
|
+
|
|
17
|
+
* UUID#to_i, UUID#to_int
|
|
18
|
+
128bit unsigned intとみなして整数化。
|
|
19
|
+
|
|
20
|
+
* UUID#to_s, UUID#to_uri, UUID#guid
|
|
21
|
+
人間が読める文字列にする。to_uriはRFC4122が定めるURIとして変換。guidはよく
|
|
22
|
+
Windowsとかで見るあれ。
|
|
23
|
+
|
|
24
|
+
* UUID#raw_bytes
|
|
25
|
+
これも文字列を返すんだけど、基本的には読めない。128bit長のUUID値そのもの。
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Local Variables:
|
|
29
|
+
# mode: text
|
|
30
|
+
# indent-tabs-mode: t
|
|
31
|
+
# tab-width: 8
|
|
32
|
+
# fill-column: 79
|
|
33
|
+
# default-justification: full
|
|
34
|
+
# End:
|
data/doc/sample.css
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
@charset "utf-8";
|
|
2
|
+
|
|
3
|
+
h1 {
|
|
4
|
+
color: #000080;
|
|
5
|
+
font-weight: bold;
|
|
6
|
+
text-align: center;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
h2 {
|
|
10
|
+
color: #000080;
|
|
11
|
+
font-weight: bold;
|
|
12
|
+
border-bottom: dotted 1px #000080;
|
|
13
|
+
margin-top: 1em;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
h3 {
|
|
17
|
+
color: #000080;
|
|
18
|
+
border-bottom: dotted 1px #000080;
|
|
19
|
+
margin-top: 1em;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
p.lead {
|
|
23
|
+
padding: 1em;
|
|
24
|
+
background: #c0c0ff;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
p.footnote {
|
|
28
|
+
font-size: xx-small;
|
|
29
|
+
padding: 1em;
|
|
30
|
+
background: #d0d0d0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
p.sourcecaption {
|
|
34
|
+
font-weight: bold;
|
|
35
|
+
text-align: center;
|
|
36
|
+
}
|
|
37
|
+
p.imagecaption {
|
|
38
|
+
font-weight: bold;
|
|
39
|
+
text-align: center;
|
|
40
|
+
}
|
|
41
|
+
p.listcaption {
|
|
42
|
+
font-weight: bold;
|
|
43
|
+
text-align: center;
|
|
44
|
+
}
|
|
45
|
+
p.emlistcaption {
|
|
46
|
+
font-weight: bold;
|
|
47
|
+
text-align: center;
|
|
48
|
+
}
|
|
49
|
+
p.tablecaption {
|
|
50
|
+
font-weight: bold;
|
|
51
|
+
text-align: center;
|
|
52
|
+
}
|
|
53
|
+
p.notecaption {
|
|
54
|
+
font-weight: bold;
|
|
55
|
+
text-align: center;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
img {
|
|
59
|
+
text-align: center;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
table {
|
|
63
|
+
border: solid 1px #000000;
|
|
64
|
+
width: 90%;
|
|
65
|
+
margin-bottom: 1em;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
th {
|
|
69
|
+
border-bottom: solid 1px #000000;
|
|
70
|
+
background: #800000;
|
|
71
|
+
color: #ffffff;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
span.kw {
|
|
75
|
+
font-weight: bold;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
div.column {
|
|
79
|
+
padding: 0.5em;
|
|
80
|
+
background: #ffd0d0;
|
|
81
|
+
border: dotted 2px #808080;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
div.image {
|
|
85
|
+
text-align: center;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
div h5 {
|
|
89
|
+
font-size: larger;
|
|
90
|
+
border-bottom: solid 1px #000000;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
p {
|
|
94
|
+
text-indent: 1em;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
p.caption {
|
|
98
|
+
font-weight: bold;
|
|
99
|
+
text-indent: 0em;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
p.noindent {
|
|
103
|
+
text-indent: 0em;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
p.flushright {
|
|
107
|
+
text-align: right;
|
|
108
|
+
}
|
data/doc/sample.yaml
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# review-epubmaker向けの設定ファイルの例。
|
|
2
|
+
# yamlファイルをReVIEWファイルのある場所に置き、
|
|
3
|
+
# 「review-epubmaker yamlファイル」を実行すると、<bookname>.epubファイルが
|
|
4
|
+
# 生成されます。
|
|
5
|
+
# このファイルはUTF-8エンコーディングで記述してください。
|
|
6
|
+
|
|
7
|
+
# ブック名(ファイル名になるもの。ASCII範囲の文字を使用)
|
|
8
|
+
bookname: review-sample
|
|
9
|
+
# 書名
|
|
10
|
+
booktitle: ReVIEW EPUBサンプル
|
|
11
|
+
# 著者
|
|
12
|
+
aut: 吟遊詩人
|
|
13
|
+
# 以下はオプション
|
|
14
|
+
# prt: 出版社
|
|
15
|
+
# asn: Associated name
|
|
16
|
+
# ant: Bibliographic antecedent
|
|
17
|
+
# clb: 貢献者
|
|
18
|
+
# edt: 編集者
|
|
19
|
+
# dsr: デザイナ
|
|
20
|
+
# ill: イラストレータ
|
|
21
|
+
# pht: 撮影者
|
|
22
|
+
# trl: 翻訳者
|
|
23
|
+
# date: 刊行日
|
|
24
|
+
# rights: 権利表記
|
|
25
|
+
# description: ブックの説明
|
|
26
|
+
#
|
|
27
|
+
# coverfile: カバーページのbody要素内に挿入する内容を記述したファイル名
|
|
28
|
+
#
|
|
29
|
+
# coverimage: カバー用画像。画像ディレクトリ内に置いてもディレクトリ名は不要(例: cover.jpg)
|
|
30
|
+
#
|
|
31
|
+
# 固有IDに使用するドメイン。指定しない場合には、時刻に基づくランダムUUIDが入る
|
|
32
|
+
# urnid: urn:uid:http://example.com/some-book-title/1.0.2/
|
|
33
|
+
# CSSファイル (yamlファイルおよびReVIEWファイルを置いたディレクトリにあること)
|
|
34
|
+
stylesheet: stylesheet.css
|
|
35
|
+
# LaTeX用のスタイルファイル(styディレクトリ以下に置くこと)
|
|
36
|
+
# texstyle: samplemacro
|
|
37
|
+
# LaTeX用のdocumentclassを指定する
|
|
38
|
+
# texdocumentclass: ["jsarticle", "b5paper,oneside"]
|
|
39
|
+
# 目次として抽出するレベル
|
|
40
|
+
toclevel: 3
|
|
41
|
+
# セクション番号を表示するレベル
|
|
42
|
+
secnolevel: 2
|
|
43
|
+
# EPUBのバージョン(現時点では2または3。デフォルトは2)
|
|
44
|
+
epubversion: 2
|
|
45
|
+
# HTMLのバージョン(現時点では4または5。デフォルトは4。epubversionを3にした場合は自動で5に設定される)
|
|
46
|
+
htmlversion: 4
|
|
47
|
+
# 表紙を出力するか
|
|
48
|
+
titlepage: true
|
|
49
|
+
# 目次を出力するか
|
|
50
|
+
toc: true
|
|
51
|
+
# EPUB標準の目次以外に目次を作成するか
|
|
52
|
+
mytoc: null
|
|
53
|
+
# 奥付を作成するか。デフォルトでは作成されない。trueを指定するとデフォルトの奥付、ファイル名を指定するとそれがcolophon.htmlとしてコピーされる
|
|
54
|
+
colophon: null
|
|
55
|
+
# XHTML生成後に実行するプログラム。$1:HTMLの生成されたディレクトリ $2:ReVIEWファイルのあるディレクトリ $3:起動時指定のyamlファイル名
|
|
56
|
+
# posthook: hook.sh
|
|
57
|
+
# EPUBで表紙をコンテンツに含めるか。デフォルトでは作成されない。yesにするとiBooks等でも最初に表紙が表示されるようになる
|
|
58
|
+
cover_linear: null
|
|
59
|
+
# review-compileに渡すパラメータ
|
|
60
|
+
params: --stylesheet=sample.css
|
|
61
|
+
# デバッグフラグ。nullでないときには一時ファイルをカレントディレクトリに作成し、削除もしない
|
|
62
|
+
debug: null
|
data/lib/epubmaker.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# = epubmaker.rb -- EPUB production set.
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2010-2012 Kenshi Muto
|
|
5
|
+
#
|
|
6
|
+
# This program is free software.
|
|
7
|
+
# You can distribute or modify this program under the terms of
|
|
8
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
|
9
|
+
# For details of the GNU LGPL, see the file "COPYING".
|
|
10
|
+
#
|
|
11
|
+
# == Quick usage
|
|
12
|
+
# (If you put xhtml files on current directory and put figures in
|
|
13
|
+
# images subdirectory)
|
|
14
|
+
#
|
|
15
|
+
# require 'epubmaker'
|
|
16
|
+
# epub = EPUBMaker::Producer.new
|
|
17
|
+
# params = epub.load("config.yaml")
|
|
18
|
+
# epub.contents.push(EPUBMaker::Content.new({"file" => "ch01.xhtml"}))
|
|
19
|
+
# epub.contents.push(EPUBMaker::Content.new({"file" => "ch02.xhtml"}))
|
|
20
|
+
# ...
|
|
21
|
+
# epub.importImageInfo("images")
|
|
22
|
+
# epub.produce
|
|
23
|
+
|
|
24
|
+
require 'epubmaker/producer'
|
|
25
|
+
require 'epubmaker/resource'
|
|
26
|
+
require 'epubmaker/content'
|
|
27
|
+
require 'epubmaker/epubv2'
|
|
28
|
+
require 'epubmaker/epubv3'
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# = content.rb -- Content object for EPUBMaker.
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2010 Kenshi Muto
|
|
5
|
+
#
|
|
6
|
+
# This program is free software.
|
|
7
|
+
# You can distribute or modify this program under the terms of
|
|
8
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
|
9
|
+
# For details of the GNU LGPL, see the file "COPYING".
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
module EPUBMaker
|
|
13
|
+
|
|
14
|
+
# EPUBMaker::Content describes a content data for EPUBMaker. EPUBMaker#contents takes an array of Content.
|
|
15
|
+
class Content
|
|
16
|
+
# ID
|
|
17
|
+
attr_accessor :id
|
|
18
|
+
# File path (can accept #<anchor> suffix also)
|
|
19
|
+
attr_accessor :file
|
|
20
|
+
# MIME type
|
|
21
|
+
attr_accessor :media
|
|
22
|
+
# Title
|
|
23
|
+
attr_accessor :title
|
|
24
|
+
# Header level (from 1)
|
|
25
|
+
attr_accessor :level
|
|
26
|
+
# Show in TOC? nil:No.
|
|
27
|
+
attr_accessor :notoc
|
|
28
|
+
|
|
29
|
+
# :call-seq:
|
|
30
|
+
# initialize(file, id, media, title, level, notoc)
|
|
31
|
+
# initialize(hash)
|
|
32
|
+
# Construct Content object by passing a sequence of parameters or hash.
|
|
33
|
+
# Keys of +hash+ relate with each parameters.
|
|
34
|
+
# +file+ (or +hash+["file"]) is required. Others are optional.
|
|
35
|
+
def initialize(fileorhash, id=nil, media=nil, title=nil, level=nil, notoc=nil)
|
|
36
|
+
if fileorhash.instance_of?(Hash)
|
|
37
|
+
@id = fileorhash["id"]
|
|
38
|
+
@file = fileorhash["file"]
|
|
39
|
+
@media = fileorhash["media"]
|
|
40
|
+
@title = fileorhash["title"]
|
|
41
|
+
@level = fileorhash["level"]
|
|
42
|
+
@notoc = fileorhash["notoc"]
|
|
43
|
+
else
|
|
44
|
+
@file = fileorhash
|
|
45
|
+
@id = id
|
|
46
|
+
@media = media
|
|
47
|
+
@title = title
|
|
48
|
+
@level = level
|
|
49
|
+
@notoc = notoc
|
|
50
|
+
end
|
|
51
|
+
complement
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def ==(obj)
|
|
55
|
+
if self.class != obj.class
|
|
56
|
+
return false
|
|
57
|
+
end
|
|
58
|
+
[self.id, self.file, self.media, self.title, self.level, self.notoc] ==
|
|
59
|
+
[obj.id, obj.file, obj.media, obj.title, obj.level, obj.notoc]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
# Complement other parameters from file parameter.
|
|
65
|
+
def complement
|
|
66
|
+
@id = @file.gsub(/[\\\/\.]/, '-') if @id.nil?
|
|
67
|
+
@media = @file.sub(/.+\./, '').downcase if !@file.nil? && @media.nil?
|
|
68
|
+
|
|
69
|
+
@media = "application/xhtml+xml" if @media == "xhtml" || @media == "xml" || @media == "html"
|
|
70
|
+
@media = "text/css" if @media == "css"
|
|
71
|
+
@media = "image/jpeg" if @media == "jpg" || @media == "jpeg" || @media == "image/jpg"
|
|
72
|
+
@media = "image/png" if @media == "png"
|
|
73
|
+
@media = "image/gif" if @media == "gif"
|
|
74
|
+
@media = "image/svg" if @media == "svg"
|
|
75
|
+
@media = "image/svg+xml" if @media == "svg" || @media == "image/svg"
|
|
76
|
+
|
|
77
|
+
if @id.nil? || @file.nil? || @media.nil?
|
|
78
|
+
raise "Type error: #{id}, #{file}, #{media}, #{title}, #{notoc}"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# = epubv2.rb -- EPUB version 2 producer.
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2010-2012 Kenshi Muto and Masayoshi Takahashi
|
|
5
|
+
#
|
|
6
|
+
# This program is free software.
|
|
7
|
+
# You can distribute or modify this program under the terms of
|
|
8
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
|
9
|
+
# For details of the GNU LGPL, see the file "COPYING".
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
require 'epubmaker/producer'
|
|
13
|
+
require 'cgi'
|
|
14
|
+
|
|
15
|
+
module EPUBMaker
|
|
16
|
+
|
|
17
|
+
# EPUBv2 is EPUB version 2 producer.
|
|
18
|
+
class EPUBv2
|
|
19
|
+
# Construct object with parameter hash +params+ and message resource hash +res+.
|
|
20
|
+
def initialize(producer)
|
|
21
|
+
@producer = producer
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Return mimetype content.
|
|
25
|
+
def mimetype
|
|
26
|
+
return "application/epub+zip"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Return opf file content.
|
|
30
|
+
def opf
|
|
31
|
+
s = <<EOT
|
|
32
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
33
|
+
<package version="2.0" xmlns="http://www.idpf.org/2007/opf" unique-identifier="BookId">
|
|
34
|
+
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
|
|
35
|
+
EOT
|
|
36
|
+
%w[title language date type format source description relation coverage subject rights].each do |item|
|
|
37
|
+
next if @producer.params[item].nil?
|
|
38
|
+
if @producer.params[item].instance_of?(Array)
|
|
39
|
+
s << @producer.params[item].map {|i| %Q[ <dc:#{item}>#{CGI.escapeHTML(i.to_s)}</dc:#{item}>\n]}.join
|
|
40
|
+
else
|
|
41
|
+
s << %Q[ <dc:#{item}>#{CGI.escapeHTML(@producer.params[item].to_s)}</dc:#{item}>\n]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# ID
|
|
46
|
+
if @producer.params["isbn"].nil?
|
|
47
|
+
s << %Q[ <dc:identifier id="BookId">#{@producer.params["urnid"]}</dc:identifier>\n]
|
|
48
|
+
else
|
|
49
|
+
s << %Q[ <dc:identifier id="BookId" opf:scheme="ISBN">#{@producer.params["isbn"]}</dc:identifier>\n]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# creator
|
|
53
|
+
%w[aut a-adp a-ann a-arr a-art a-asn a-aqt a-aft a-aui a-ant a-bkp a-clb a-cmm a-dsr a-edt a-ill a-lyr a-mdc a-mus a-nrt a-oth a-pht a-prt a-red a-rev a-spn a-ths a-trc a-trl].each do |role|
|
|
54
|
+
next if @producer.params[role].nil?
|
|
55
|
+
@producer.params[role].each do |v|
|
|
56
|
+
s << %Q[ <dc:creator opf:role="#{role.sub('a-', '')}">#{CGI.escapeHTML(v)}</dc:creator>\n]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
# contributor
|
|
60
|
+
%w[adp ann arr art asn aqt aft aui ant bkp clb cmm dsr edt ill lyr mdc mus nrt oth pht prt red rev spn ths trc trl].each do |role|
|
|
61
|
+
next if @producer.params[role].nil?
|
|
62
|
+
@producer.params[role].each do |v|
|
|
63
|
+
s << %Q[ <dc:contributor opf:role="#{role}">#{CGI.escapeHTML(v)}</dc:contributor>\n]
|
|
64
|
+
if role == "prt"
|
|
65
|
+
s << %Q[ <dc:publisher>#{v}</dc:publisher>\n]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
if @producer.params["coverimage"]
|
|
71
|
+
@producer.contents.each do |item|
|
|
72
|
+
if item.media =~ /\Aimage/ && item.file =~ /#{@producer.params["coverimage"]}\Z/
|
|
73
|
+
s << %Q[ <meta name="cover" content="#{item.id}"/>\n]
|
|
74
|
+
break
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
s << %Q[ </metadata>\n]
|
|
80
|
+
|
|
81
|
+
# manifest
|
|
82
|
+
s << <<EOT
|
|
83
|
+
<manifest>
|
|
84
|
+
<item id="ncx" href="#{@producer.params["bookname"]}.ncx" media-type="application/x-dtbncx+xml"/>
|
|
85
|
+
<item id="#{@producer.params["bookname"]}" href="#{@producer.params["cover"]}" media-type="application/xhtml+xml"/>
|
|
86
|
+
EOT
|
|
87
|
+
|
|
88
|
+
s << %Q[ <item id="toc" href="#{@producer.params["tocfile"]}" media-type="application/xhtml+xml"/>\n] unless @producer.params["mytoc"].nil?
|
|
89
|
+
|
|
90
|
+
@producer.contents.each do |item|
|
|
91
|
+
next if item.file =~ /#/ # skip subgroup
|
|
92
|
+
s << %Q[ <item id="#{item.id}" href="#{item.file}" media-type="#{item.media}"/>\n]
|
|
93
|
+
end
|
|
94
|
+
s << %Q[ </manifest>\n]
|
|
95
|
+
|
|
96
|
+
# tocx
|
|
97
|
+
s << %Q[ <spine toc="ncx">\n]
|
|
98
|
+
s << %Q[ <itemref idref="#{@producer.params["bookname"]}" linear="no"/>\n]
|
|
99
|
+
s << %Q[ <itemref idref="toc" />\n] unless @producer.params["mytoc"].nil?
|
|
100
|
+
|
|
101
|
+
@producer.contents.each do |item|
|
|
102
|
+
next if item.media !~ /xhtml\+xml/ # skip non XHTML
|
|
103
|
+
s << %Q[ <itemref idref="#{item.id}"/>\n] if item.notoc.nil?
|
|
104
|
+
end
|
|
105
|
+
s << %Q[ </spine>\n]
|
|
106
|
+
|
|
107
|
+
# guide
|
|
108
|
+
s << %Q[ <guide>\n]
|
|
109
|
+
s << %Q[ <reference type="cover" title="#{@producer.res.v("covertitle")}" href="#{@producer.params["cover"]}"/>\n]
|
|
110
|
+
s << %Q[ <reference type="title-page" title="#{@producer.res.v("titlepagetitle")}" href="#{@producer.params["titlepage"]}"/>\n] unless @producer.params["titlepage"].nil?
|
|
111
|
+
s << %Q[ <reference type="toc" title="#{@producer.res.v("toctitle")}" href="#{@producer.params["tocfile"]}"/>\n] unless @producer.params["mytoc"].nil?
|
|
112
|
+
s << %Q[ <reference type="colophon" title="#{@producer.res.v("colophontitle")}" href="colophon.#{@producer.params["htmlext"]}"/>\n] unless @producer.params["colophon"].nil? # FIXME: path
|
|
113
|
+
s << %Q[ </guide>\n]
|
|
114
|
+
s << %Q[</package>\n]
|
|
115
|
+
return s
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Return ncx content. +indentarray+ defines prefix string for each level.
|
|
119
|
+
def ncx(indentarray)
|
|
120
|
+
s = <<EOT
|
|
121
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
122
|
+
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
|
|
123
|
+
<head>
|
|
124
|
+
<meta name="dtb:depth" content="1"/>
|
|
125
|
+
<meta name="dtb:totalPageCount" content="0"/>
|
|
126
|
+
<meta name="dtb:maxPageNumber" content="0"/>
|
|
127
|
+
EOT
|
|
128
|
+
if @producer.params["isbn"].nil?
|
|
129
|
+
s << %Q[ <meta name="dtb:uid" content="#{@producer.params["urnid"]}"/>\n]
|
|
130
|
+
else
|
|
131
|
+
s << %Q[ <meta name="dtb:uid" content="#{@producer.params["isbn"]}"/>\n]
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
s << <<EOT
|
|
135
|
+
</head>
|
|
136
|
+
<docTitle>
|
|
137
|
+
<text>#{CGI.escapeHTML(@producer.params["title"])}</text>
|
|
138
|
+
</docTitle>
|
|
139
|
+
<docAuthor>
|
|
140
|
+
<text>#{@producer.params["aut"].nil? ? "" : CGI.escapeHTML(@producer.params["aut"].join(", "))}</text>
|
|
141
|
+
</docAuthor>
|
|
142
|
+
<navMap>
|
|
143
|
+
<navPoint id="top" playOrder="1">
|
|
144
|
+
<navLabel>
|
|
145
|
+
<text>#{CGI.escapeHTML(@producer.params["title"])}</text>
|
|
146
|
+
</navLabel>
|
|
147
|
+
<content src="#{@producer.params["cover"]}"/>
|
|
148
|
+
</navPoint>
|
|
149
|
+
EOT
|
|
150
|
+
|
|
151
|
+
nav_count = 2
|
|
152
|
+
|
|
153
|
+
unless @producer.params["mytoc"].nil?
|
|
154
|
+
s << <<EOT
|
|
155
|
+
<navPoint id="toc" playOrder="#{nav_count}">
|
|
156
|
+
<navLabel>
|
|
157
|
+
<text>#{@producer.res.v("toctitle")}</text>
|
|
158
|
+
</navLabel>
|
|
159
|
+
<content src="#{@producer.params["tocfile"]}"/>
|
|
160
|
+
</navPoint>
|
|
161
|
+
EOT
|
|
162
|
+
nav_count += 1
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
@producer.contents.each do |item|
|
|
166
|
+
next if item.title.nil?
|
|
167
|
+
indent = indentarray.nil? ? [""] : indentarray
|
|
168
|
+
level = item.level.nil? ? 0 : (item.level - 1)
|
|
169
|
+
level = indent.size - 1 if level >= indent.size
|
|
170
|
+
s << <<EOT
|
|
171
|
+
<navPoint id="nav-#{nav_count}" playOrder="#{nav_count}">
|
|
172
|
+
<navLabel>
|
|
173
|
+
<text>#{indent[level]}#{item.title}</text>
|
|
174
|
+
</navLabel>
|
|
175
|
+
<content src="#{item.file}"/>
|
|
176
|
+
</navPoint>
|
|
177
|
+
EOT
|
|
178
|
+
nav_count += 1
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
s << <<EOT
|
|
182
|
+
</navMap>
|
|
183
|
+
</ncx>
|
|
184
|
+
EOT
|
|
185
|
+
return s
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Return container content.
|
|
189
|
+
def container
|
|
190
|
+
s = <<EOT
|
|
191
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
192
|
+
<container xmlns="urn:oasis:names:tc:opendocument:xmlns:container" version="1.0">
|
|
193
|
+
<rootfiles>
|
|
194
|
+
<rootfile full-path="OEBPS/#{@producer.params["bookname"]}.opf" media-type="application/oebps-package+xml" />
|
|
195
|
+
</rootfiles>
|
|
196
|
+
</container>
|
|
197
|
+
EOT
|
|
198
|
+
return s
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Return cover content.
|
|
202
|
+
def cover
|
|
203
|
+
s = common_header
|
|
204
|
+
s << <<EOT
|
|
205
|
+
<title>#{CGI.escapeHTML(@producer.params["title"])}</title>
|
|
206
|
+
</head>
|
|
207
|
+
<body>
|
|
208
|
+
EOT
|
|
209
|
+
if @producer.params["coverimage"].nil?
|
|
210
|
+
s << <<EOT
|
|
211
|
+
<h1 class="cover-title">#{CGI.escapeHTML(@producer.params["title"])}</h1>
|
|
212
|
+
EOT
|
|
213
|
+
else
|
|
214
|
+
file = nil
|
|
215
|
+
@producer.contents.each do |item|
|
|
216
|
+
if item.media =~ /\Aimage/ && item.file =~ /#{@producer.params["coverimage"]}\Z/ # /
|
|
217
|
+
file = item.file
|
|
218
|
+
break
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
raise "coverimage #{@producer.params["coverimage"]} not found. Abort." if file.nil?
|
|
222
|
+
s << <<EOT
|
|
223
|
+
<div id="cover-image" class="cover-image">
|
|
224
|
+
<img src="#{file}" alt="#{CGI.escapeHTML(@producer.params["title"])}" class="max"/>
|
|
225
|
+
</div>
|
|
226
|
+
EOT
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
s << <<EOT
|
|
230
|
+
</body>
|
|
231
|
+
</html>
|
|
232
|
+
EOT
|
|
233
|
+
return s
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Return title (copying) content.
|
|
237
|
+
def titlepage
|
|
238
|
+
s = common_header
|
|
239
|
+
s << <<EOT
|
|
240
|
+
<title>#{CGI.escapeHTML(@producer.params["title"])}</title>
|
|
241
|
+
</head>
|
|
242
|
+
<body>
|
|
243
|
+
<h1 class="tp-title">#{CGI.escapeHTML(@producer.params["title"])}</h1>
|
|
244
|
+
EOT
|
|
245
|
+
|
|
246
|
+
if @producer.params["aut"]
|
|
247
|
+
s << <<EOT
|
|
248
|
+
<p>
|
|
249
|
+
<br />
|
|
250
|
+
<br />
|
|
251
|
+
</p>
|
|
252
|
+
<h2 class="tp-author">#{CGI.escapeHTML(@producer.params["aut"])}</h2>
|
|
253
|
+
EOT
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
if @producer.params["prt"]
|
|
257
|
+
s << <<EOT
|
|
258
|
+
<p>
|
|
259
|
+
<br />
|
|
260
|
+
<br />
|
|
261
|
+
<br />
|
|
262
|
+
<br />
|
|
263
|
+
</p>
|
|
264
|
+
<h3 class="tp-publisher">#{CGI.escapeHTML(@producer.params["prt"])}</h3>
|
|
265
|
+
EOT
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
s << <<EOT
|
|
269
|
+
</body>
|
|
270
|
+
</html>
|
|
271
|
+
EOT
|
|
272
|
+
return s
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Return colophon content.
|
|
276
|
+
def colophon
|
|
277
|
+
s = common_header
|
|
278
|
+
s << <<EOT
|
|
279
|
+
<title>#{@producer.res.v("colophontitle")}</title>
|
|
280
|
+
</head>
|
|
281
|
+
<body>
|
|
282
|
+
<div class="colophon">
|
|
283
|
+
<p class="title">#{CGI.escapeHTML(@producer.params["title"])}</p>
|
|
284
|
+
EOT
|
|
285
|
+
|
|
286
|
+
if @producer.params["pubhistory"]
|
|
287
|
+
s << %Q[ <div class="pubhistory">\n <p>#{@producer.params["pubhistory"].gsub(/\n/, "<br />")}</p>\n </div>\n] # FIXME: should be array?
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
s << %Q[ <table class="colophon">\n]
|
|
291
|
+
s << %Q[ <tr><th>#{@producer.res.v("c-aut")}</th><td>#{CGI.escapeHTML(@producer.params["aut"])}</td></tr>\n] if @producer.params["aut"]
|
|
292
|
+
s << %Q[ <tr><th>#{@producer.res.v("c-dsr")}</th><td>#{CGI.escapeHTML(@producer.params["dsr"])}</td></tr>\n] if @producer.params["dsr"]
|
|
293
|
+
s << %Q[ <tr><th>#{@producer.res.v("c-ill")}</th><td>#{CGI.escapeHTML(@producer.params["ill"])}</td></tr>\n] if @producer.params["ill"]
|
|
294
|
+
s << %Q[ <tr><th>#{@producer.res.v("c-edt")}</th><td>#{CGI.escapeHTML(@producer.params["edt"])}</td></tr>\n] if @producer.params["edt"]
|
|
295
|
+
s << %Q[ <tr><th>#{@producer.res.v("c-prt")}</th><td>#{CGI.escapeHTML(@producer.params["prt"])}</td></tr>\n] if @producer.params["prt"]
|
|
296
|
+
s << <<EOT
|
|
297
|
+
</table>
|
|
298
|
+
</div>
|
|
299
|
+
</body>
|
|
300
|
+
</html>
|
|
301
|
+
EOT
|
|
302
|
+
return s
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# Return own toc content.
|
|
306
|
+
def mytoc
|
|
307
|
+
s = common_header
|
|
308
|
+
s << <<EOT
|
|
309
|
+
<title>#{@producer.res.v("toctitle")}</title>
|
|
310
|
+
</head>
|
|
311
|
+
<body>
|
|
312
|
+
<h1 class="toc-title">#{@producer.res.v("toctitle")}</h1>
|
|
313
|
+
<ul class="toc-h1">
|
|
314
|
+
EOT
|
|
315
|
+
|
|
316
|
+
# FIXME: indent
|
|
317
|
+
current = 1
|
|
318
|
+
init_item = true
|
|
319
|
+
@producer.contents.each do |item|
|
|
320
|
+
next if !item.notoc.nil? || item.level.nil? || item.file.nil? || item.title.nil? || item.level > @producer.params["toclevel"].to_i
|
|
321
|
+
if item.level > current
|
|
322
|
+
s << %Q[\n<ul class="toc-h#{item.level}">\n]
|
|
323
|
+
current = item.level
|
|
324
|
+
elsif item.level < current
|
|
325
|
+
(current - 1).downto(item.level) do |n|
|
|
326
|
+
s << %Q[</li>\n</ul>\n]
|
|
327
|
+
end
|
|
328
|
+
s << %Q[</li>\n]
|
|
329
|
+
current = item.level
|
|
330
|
+
elsif init_item
|
|
331
|
+
# noop
|
|
332
|
+
else
|
|
333
|
+
s << %Q[</li>\n]
|
|
334
|
+
end
|
|
335
|
+
s << %Q[<li><a href="#{item.file}">#{item.title}</a>]
|
|
336
|
+
init_item = false
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
(current - 1).downto(1) do |n|
|
|
340
|
+
s << %Q[</li>\n</ul>\n]
|
|
341
|
+
end
|
|
342
|
+
if !init_item
|
|
343
|
+
s << %Q[</li>\n]
|
|
344
|
+
end
|
|
345
|
+
s << <<EOT
|
|
346
|
+
</ul>
|
|
347
|
+
</body>
|
|
348
|
+
</html>
|
|
349
|
+
EOT
|
|
350
|
+
return s
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
# Produce EPUB file +epubfile+.
|
|
354
|
+
# +basedir+ points the directory has contents.
|
|
355
|
+
# +tmpdir+ defines temporary directory.
|
|
356
|
+
def produce(epubfile, basedir, tmpdir)
|
|
357
|
+
File.open("#{tmpdir}/mimetype", "w") {|f| @producer.mimetype(f) }
|
|
358
|
+
|
|
359
|
+
Dir.mkdir("#{tmpdir}/META-INF") unless File.exist?("#{tmpdir}/META-INF")
|
|
360
|
+
File.open("#{tmpdir}/META-INF/container.xml", "w") {|f| @producer.container(f) }
|
|
361
|
+
|
|
362
|
+
Dir.mkdir("#{tmpdir}/OEBPS") unless File.exist?("#{tmpdir}/OEBPS")
|
|
363
|
+
File.open("#{tmpdir}/OEBPS/#{@producer.params["bookname"]}.opf", "w") {|f| @producer.opf(f) }
|
|
364
|
+
File.open("#{tmpdir}/OEBPS/#{@producer.params["bookname"]}.ncx", "w") {|f| @producer.ncx(f, @producer.params["ncxindent"]) }
|
|
365
|
+
File.open("#{tmpdir}/OEBPS/#{@producer.params["tocfile"]}", "w") {|f| @producer.mytoc(f) } unless @producer.params["mytoc"].nil?
|
|
366
|
+
|
|
367
|
+
if File.exist?("#{basedir}/#{@producer.params["cover"]}")
|
|
368
|
+
FileUtils.cp("#{basedir}/#{@producer.params["cover"]}", "#{tmpdir}/OEBPS")
|
|
369
|
+
else
|
|
370
|
+
File.open("#{tmpdir}/OEBPS/#{@producer.params["cover"]}", "w") {|f| @producer.cover(f) }
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# FIXME:colophon and titlepage should be included in @producer.contents.
|
|
374
|
+
|
|
375
|
+
@producer.contents.each do |item|
|
|
376
|
+
next if item.file =~ /#/ # skip subgroup
|
|
377
|
+
fname = "#{basedir}/#{item.file}"
|
|
378
|
+
raise "#{fname} doesn't exist. Abort." unless File.exist?(fname)
|
|
379
|
+
FileUtils.mkdir_p(File.dirname("#{tmpdir}/OEBPS/#{item.file}")) unless File.exist?(File.dirname("#{tmpdir}/OEBPS/#{item.file}"))
|
|
380
|
+
FileUtils.cp(fname, "#{tmpdir}/OEBPS/#{item.file}")
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
fork {
|
|
384
|
+
Dir.chdir(tmpdir) {|d|
|
|
385
|
+
exec("zip", "-0X", "#{epubfile}", "mimetype")
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
Process.waitall
|
|
389
|
+
fork {
|
|
390
|
+
Dir.chdir(tmpdir) {|d|
|
|
391
|
+
exec("zip", "-Xr9D", "#{epubfile}", "META-INF", "OEBPS")
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
Process.waitall
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
private
|
|
398
|
+
|
|
399
|
+
# Return common XHTML headder
|
|
400
|
+
def common_header
|
|
401
|
+
s =<<EOT
|
|
402
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
403
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
404
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ops="http://www.idpf.org/2007/ops" xml:lang="#{@producer.params["language"]}">
|
|
405
|
+
<head>
|
|
406
|
+
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
|
|
407
|
+
<meta http-equiv="Content-Style-Type" content="text/css"/>
|
|
408
|
+
<meta name="generator" content="EPUBMaker::Producer"/>
|
|
409
|
+
EOT
|
|
410
|
+
|
|
411
|
+
@producer.params["stylesheet"].each do |file|
|
|
412
|
+
s << %Q[ <link rel="stylesheet" type="text/css" href="#{file}"/>\n]
|
|
413
|
+
end
|
|
414
|
+
return s
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
end
|