review 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +42 -0
  3. data/README.rdoc +31 -0
  4. data/bin/review-catalog-converter +129 -0
  5. data/bin/review-check +4 -2
  6. data/bin/review-compile +7 -7
  7. data/bin/review-index +4 -3
  8. data/bin/review-init +3 -1
  9. data/bin/review-pdfmaker +2 -258
  10. data/bin/review-vol +2 -2
  11. data/doc/catalog.rdoc +18 -3
  12. data/doc/format.rdoc +2 -3
  13. data/doc/quickstart.rdoc +1 -1
  14. data/lib/epubmaker/epubv2.rb +16 -8
  15. data/lib/epubmaker/epubv3.rb +44 -12
  16. data/lib/epubmaker/producer.rb +4 -2
  17. data/lib/review/book.rb +0 -1
  18. data/lib/review/book/base.rb +72 -35
  19. data/lib/review/book/chapter.rb +8 -12
  20. data/lib/review/book/compilable.rb +8 -8
  21. data/lib/review/book/image_finder.rb +7 -0
  22. data/lib/review/book/index.rb +23 -5
  23. data/lib/review/book/volume.rb +2 -1
  24. data/lib/review/builder.rb +10 -5
  25. data/lib/review/catalog.rb +5 -0
  26. data/lib/review/compiler.rb +1 -1
  27. data/lib/review/configure.rb +12 -0
  28. data/lib/review/epubmaker.rb +13 -7
  29. data/lib/review/htmlbuilder.rb +26 -12
  30. data/lib/review/i18n.rb +2 -2
  31. data/lib/review/i18n.yml +21 -0
  32. data/lib/review/idgxmlbuilder.rb +11 -9
  33. data/lib/review/latexbuilder.rb +3 -2
  34. data/lib/review/{review.tex.erb → layout.tex.erb} +9 -1
  35. data/lib/review/markdownbuilder.rb +126 -4
  36. data/lib/review/pdfmaker.rb +291 -0
  37. data/lib/review/tocparser.rb +6 -5
  38. data/lib/review/tocprinter.rb +5 -2
  39. data/lib/review/version.rb +1 -1
  40. data/review.gemspec +1 -1
  41. data/rubocop-todo.yml +13 -0
  42. data/test/test_book.rb +95 -133
  43. data/test/test_book_chapter.rb +16 -21
  44. data/test/test_builder.rb +12 -7
  45. data/test/test_catalog.rb +15 -3
  46. data/test/test_catalog_converter_cmd.rb +73 -0
  47. data/test/test_epubmaker.rb +5 -5
  48. data/test/test_helper.rb +32 -21
  49. data/test/test_htmlbuilder.rb +219 -192
  50. data/test/test_i18n.rb +46 -19
  51. data/test/test_idgxmlbuilder.rb +177 -182
  52. data/test/test_inaobuilder.rb +1 -2
  53. data/test/test_index.rb +20 -0
  54. data/test/test_latexbuilder.rb +175 -183
  55. data/test/test_markdownbuilder.rb +41 -5
  56. data/test/test_pdfmaker.rb +130 -0
  57. data/test/test_topbuilder.rb +92 -96
  58. metadata +10 -6
  59. data/lib/review/book/parameters.rb +0 -98
  60. data/test/test_book_parameter.rb +0 -42
@@ -57,8 +57,8 @@ def main
57
57
  exit 1
58
58
  end
59
59
 
60
- book = basedir ? ReVIEW::Book.load(basedir) : ReVIEW.book
61
- ReVIEW.book.config = @config
60
+ book = basedir ? ReVIEW::Book.load(basedir) : ReVIEW::Book::Base.load_default
61
+ book.config = @config
62
62
  if part_sensitive
63
63
  sep = ""
64
64
  book.each_part do |part|
@@ -9,7 +9,7 @@ Re:VIEW フォーマットで記述された各ファイルを特に一冊の本
9
9
 
10
10
  == catalog.ymlを用いた場合の設定方法
11
11
 
12
- catalog.yml内で、PREDEF(前付け)、CHAPS(本編)、POSTDEF(後付け)を記述します。CHAPSのみ必須です。
12
+ catalog.yml内で、PREDEF(前付け)、CHAPS(本編)、APPENDIX(付録)、POSTDEF(後付け)を記述します。CHAPSのみ必須です。
13
13
 
14
14
  PREDEF:
15
15
  - intro.re
@@ -18,13 +18,28 @@ catalog.yml内で、PREDEF(前付け)、CHAPS(本編)、POSTDEF(後付
18
18
  - ch01.re
19
19
  - ch02.re
20
20
 
21
- POSTDEF:
21
+ APPENDIX:
22
22
  - appendix.re
23
+
24
+ POSTDEF:
25
+ - postscript.re
26
+
27
+ 本編に対して、「部」構成を加えたい場合、CHAPSを段階的にして記述します。部の指定については、タイトル名でもファイル名でもどちらでも使えます。
23
28
 
24
- 本編に対して、「部」構成を加えたい場合、CHAPSを段階的にして記述します。
29
+ CHAPS:
30
+ - ch01.re
31
+ - 第1部:
32
+ - ch02.re
33
+ - ch03.re
34
+ - pt02.re:
35
+ - ch04.re
25
36
 
26
37
  (旧バージョンの利用者の方へ: PARTという項目はありません。CHAPSに記述してください)
27
38
 
39
+ == バージョン 1.3以前について
40
+
41
+ APPENDIXは指定できません。POSTDEFを使ってください。
42
+
28
43
  == バージョン 1.2以前について
29
44
 
30
45
  1.2以前のRe:VIEWではカタログファイルとしてPREDEF, CHAPS, POSTDEF, PARTという独立した4つのファイルを使用していました。
@@ -6,8 +6,7 @@ RD や各種 Wiki の文法をとりいれて簡素化しています。
6
6
 
7
7
  == 段落
8
8
 
9
- 段落(本文)の間は英語の段落のように1行空けます。ただし、組版に
10
- まわすときは前処理して1段落を1行に変更してあります。
9
+ 段落(本文)の間は英語の段落のように1行空けます。
11
10
 
12
11
  例:
13
12
 
@@ -511,7 +510,7 @@ Re:VIEW は任意のブロックを追加可能なので、本によって専用
511
510
 
512
511
  == HTMLのレイアウト機能
513
512
 
514
- CHAPSファイルが置かれているディレクトリに layouts/layout.erb
513
+ CHAPSファイルが置かれているディレクトリに layouts/layout.html.erb
515
514
  を置くとその html を ERB で評価します。
516
515
 
517
516
  例:
@@ -85,7 +85,7 @@ review というディレクトリに展開されるので、review/bin にパ
85
85
 
86
86
  ホームページは@<tt>{https://github.com/kmuto/review/wiki/}です。
87
87
 
88
- テキストファイルの文字エンコーディングには、UTF-8 を使うことをお勧めします。Re:VIEW は日本語文字エンコーディングとして UTF-8、EUC-JP、Shift-JIS、JIS を扱うことができ、入力ファイルについては自動判別、出力ファイルについても選択可能 (デフォルトは UTF-8) ですが、入力・出力のいずれにおいても、使用可能な文字についての制限が少ない UTF-8 が最適です。
88
+ テキストファイルの文字エンコーディングには、UTF-8 を使うことをお勧めします。Re:VIEW は日本語文字エンコーディングとして UTF-8、EUC-JP、Shift_JIS、JIS を扱うことができ、入力ファイルについては自動判別、出力ファイルについても選択可能 (デフォルトは UTF-8) ですが、入力・出力のいずれにおいても、使用可能な文字についての制限が少ない UTF-8 が最適です。
89
89
 
90
90
  次に、章構成ファイルの CHAPS ファイルを同じディレクトリに用意します。このファイルには、Re:VIEW フォーマットファイルの名前を格納します。
91
91
 
@@ -123,9 +123,15 @@ EOT
123
123
  end
124
124
 
125
125
  def opf_tocx
126
+ if @producer.params["cover_linear"] && @producer.params["cover_linear"] != "no"
127
+ cover_linear = "yes"
128
+ else
129
+ cover_linear = "no"
130
+ end
131
+
126
132
  s = ""
127
133
  s << %Q[ <spine toc="ncx">\n]
128
- s << %Q[ <itemref idref="#{@producer.params["bookname"]}" linear="no"/>\n]
134
+ s << %Q[ <itemref idref="#{@producer.params["bookname"]}" linear="#{cover_linear}"/>\n]
129
135
  s << %Q[ <itemref idref="toc" />\n] unless @producer.params["mytoc"].nil?
130
136
 
131
137
  @producer.contents.each do |item|
@@ -223,7 +229,7 @@ EOT
223
229
  s << <<EOT
224
230
  <navPoint id="nav-#{nav_count}" playOrder="#{nav_count}">
225
231
  <navLabel>
226
- <text>#{indent[level]}#{item.title}</text>
232
+ <text>#{indent[level]}#{CGI.escapeHTML(item.title)}</text>
227
233
  </navLabel>
228
234
  <content src="#{item.file}"/>
229
235
  </navPoint>
@@ -251,12 +257,14 @@ EOT
251
257
  end
252
258
 
253
259
  # Return cover content.
254
- def cover
260
+ def cover(type=nil)
261
+ bodyext = type.nil? ? "" : " epub:type=\"#{type}\""
262
+
255
263
  s = common_header
256
264
  s << <<EOT
257
265
  <title>#{CGI.escapeHTML(@producer.params["title"])}</title>
258
266
  </head>
259
- <body>
267
+ <body#{bodyext}>
260
268
  EOT
261
269
  if @producer.params["coverimage"].nil?
262
270
  s << <<EOT
@@ -448,7 +456,7 @@ EOT
448
456
  if !has_part.nil?
449
457
  @producer.contents.each do |item|
450
458
  item.level += 1 if item.chaptype == "part" || item.chaptype == "body"
451
- item.notoc = true if (item.chaptype == "pre" || item.chaptype == "post") && !item.level.nil? && (item.level + 1 == toclevel)
459
+ item.notoc = true if (item.chaptype == "pre" || item.chaptype == "post") && !item.level.nil? && (item.level + 1 == toclevel) # FIXME: 部があるときに前後の処理が困難
452
460
  end
453
461
  toclevel += 1
454
462
  end
@@ -500,7 +508,7 @@ EOT
500
508
  @producer.contents.each do |item|
501
509
  next if !item.notoc.nil? || item.level.nil? || item.file.nil? || item.title.nil? || item.level > @producer.params["toclevel"].to_i
502
510
  is = indent == true ? " " * item.level : ""
503
- s << %Q[<li><a href="#{item.file}">#{is}#{item.title}</a></li>\n]
511
+ s << %Q[<li><a href="#{item.file}">#{is}#{CGI.escapeHTML(item.title)}</a></li>\n]
504
512
  end
505
513
  s << %Q[</#{type}>\n]
506
514
 
@@ -545,8 +553,8 @@ EOT
545
553
  end
546
554
 
547
555
  def export_zip(tmpdir, epubfile)
548
- Dir.chdir(tmpdir) {|d| system("#{@producer.params["zip_stage1"]} #{epubfile} mimetype") }
549
- Dir.chdir(tmpdir) {|d| system("#{@producer.params["zip_stage2"]} #{epubfile} META-INF OEBPS #{@producer.params["zip_addpath"]}") }
556
+ Dir.chdir(tmpdir) {|d| `#{@producer.params["zip_stage1"]} #{epubfile} mimetype` }
557
+ Dir.chdir(tmpdir) {|d| `#{@producer.params["zip_stage2"]} #{epubfile} META-INF OEBPS #{@producer.params["zip_addpath"]}` }
550
558
  end
551
559
 
552
560
  def legacy_cover_and_title_file(loadfile, writefile)
@@ -82,24 +82,51 @@ EOT
82
82
  end
83
83
 
84
84
  # creator (should be array)
85
- %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-csl 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|
85
+ %w[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-csl 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 aut].each do |role|
86
86
  next if @producer.params[role].nil?
87
87
  @producer.params[role].each_with_index do |v, i|
88
- s << %Q[ <dc:creator id="#{role}-#{i}">#{CGI.escapeHTML(v)}</dc:creator>\n]
89
- s << %Q[ <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role.sub('a-', '')}</meta>\n]
88
+ if v.instance_of?(Hash)
89
+ s << %Q[ <dc:creator id="#{role}-#{i}">#{CGI.escapeHTML(v["name"])}</dc:creator>\n]
90
+ s << %Q[ <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role.sub('a-', '')}</meta>\n]
91
+ v.each_pair do |name, val|
92
+ next if name == "name"
93
+ s << %Q[ <meta refines="##{role.sub('a-', '')}-#{i}" property="#{name}">#{CGI.escapeHTML(val)}</meta>\n]
94
+ end
95
+ else
96
+ s << %Q[ <dc:creator id="#{role}-#{i}">#{CGI.escapeHTML(v)}</dc:creator>\n]
97
+ s << %Q[ <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role.sub('a-', '')}</meta>\n]
98
+ end
90
99
  end
91
100
  end
92
101
 
93
102
  # contributor (should be array)
94
- %w[adp ann arr art asn aqt aft aui ant bkp clb cmm csl dsr edt ill lyr mdc mus nrt oth pht prt red rev spn ths trc trl].each do |role|
103
+ %w[adp ann arr art asn aqt aft aui ant bkp clb cmm csl dsr edt ill lyr mdc mus nrt oth pbd pbl pht prt red rev spn ths trc trl].each do |role|
95
104
  next if @producer.params[role].nil?
96
105
  @producer.params[role].each_with_index do |v, i|
97
- s << %Q[ <dc:contributor id="#{role}-#{i}">#{CGI.escapeHTML(v)}</dc:contributor>\n]
98
- s << %Q[ <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role}</meta>\n]
106
+ if v.instance_of?(Hash)
107
+ s << %Q[ <dc:contributor id="#{role}-#{i}">#{CGI.escapeHTML(v["name"])}</dc:contributor>\n]
108
+ s << %Q[ <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role}</meta>\n]
109
+ v.each_pair do |name, val|
110
+ next if name == "name"
111
+ s << %Q[ <meta refines="##{role}-#{i}" property="#{name}">#{CGI.escapeHTML(val)}</meta>\n]
112
+ end
113
+ else
114
+ s << %Q[ <dc:contributor id="#{role}-#{i}">#{CGI.escapeHTML(v)}</dc:contributor>\n]
115
+ s << %Q[ <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role}</meta>\n]
116
+ end
99
117
 
100
- if role == "prt"
101
- s << %Q[ <dc:publisher id="prt">#{CGI.escapeHTML(v)}</dc:publisher>\n]
102
- s << %Q[ <meta refines="#prt" property="role" scheme="marc:relators">prt</meta>\n]
118
+ if role == "prt" || role == "pbl"
119
+ if v.instance_of?(Hash)
120
+ s << %Q[ <dc:publisher id="pub-#{role}-#{i}">#{CGI.escapeHTML(v["name"])}</dc:publisher>\n]
121
+ s << %Q[ <meta refines="#pub-#{role}-#{i}" property="role" scheme="marc:relators">#{role}</meta>\n]
122
+ v.each_pair do |name, val|
123
+ next if name == "name"
124
+ s << %Q[ <meta refines="#pub-#{role}-#{i}" property="#{name}">#{CGI.escapeHTML(val)}</meta>\n]
125
+ end
126
+ else
127
+ s << %Q[ <dc:publisher id="pub-#{role}-#{i}">#{CGI.escapeHTML(v)}</dc:publisher>\n]
128
+ s << %Q[ <meta refines="#pub-#{role}-#{i}" property="role" scheme="marc:relators">prt</meta>\n]
129
+ end
103
130
  end
104
131
  end
105
132
  end
@@ -139,9 +166,15 @@ EOT
139
166
  end
140
167
 
141
168
  def opf_tocx
169
+ if @producer.params["cover_linear"] && @producer.params["cover_linear"] != "no"
170
+ cover_linear = "yes"
171
+ else
172
+ cover_linear = "no"
173
+ end
174
+
142
175
  s = ""
143
176
  s << %Q[ <spine>\n]
144
- s << %Q[ <itemref idref="#{@producer.params["bookname"]}" linear="no"/>\n]
177
+ s << %Q[ <itemref idref="#{@producer.params["bookname"]}" linear="#{cover_linear}"/>\n]
145
178
  # s << %Q[ <itemref idref="#{@producer.params["bookname"]}-toc.#{@producer.params["htmlext"]}" />\n]
146
179
 
147
180
  @producer.contents.each do |item|
@@ -202,7 +235,7 @@ EOT
202
235
  s =<<EOT
203
236
  <?xml version="1.0" encoding="UTF-8"?>
204
237
  <!DOCTYPE html>
205
- <html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/epub" xmlns:ops="http://www.idpf.org/2007/ops" xml:lang="#{@producer.params["language"]}">
238
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xmlns:ops="http://www.idpf.org/2007/ops" xml:lang="#{@producer.params["language"]}">
206
239
  <head>
207
240
  <meta charset="UTF-8" />
208
241
  <meta name="generator" content="Re:VIEW" />
@@ -213,6 +246,5 @@ EOT
213
246
  end
214
247
  s
215
248
  end
216
-
217
249
  end
218
250
  end
@@ -101,7 +101,8 @@ module EPUBMaker
101
101
  # If Producer#params["coverimage"] is defined, it will be used for
102
102
  # the cover image.
103
103
  def cover(wobj)
104
- s = @epub.cover
104
+ type = (@params["epubversion"] >= 3) ? "cover" : nil
105
+ s = @epub.cover(type)
105
106
  wobj.puts s if !s.nil? && !wobj.nil?
106
107
  end
107
108
 
@@ -219,6 +220,7 @@ module EPUBMaker
219
220
  "font_ext" => %w(ttf woff otf),
220
221
  "verify_target_images" => nil,
221
222
  "force_include_images" => [],
223
+ "cover_linear" => nil,
222
224
  }
223
225
 
224
226
  defaults.each_pair do |k, v|
@@ -231,7 +233,7 @@ module EPUBMaker
231
233
  raise "Key #{k} must have a value. Abort." if @params[k].nil?
232
234
  end
233
235
  # array
234
- %w[subject 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 adp ann arr art asn aut aqt aft aui ant bkp clb cmm dsr edt ill lyr mdc mus nrt oth pht prt red rev spn ths trc trl stylesheet rights].each do |item|
236
+ %w[subject 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 adp ann arr art asn aut aqt aft aui ant bkp clb cmm dsr edt ill lyr mdc mus nrt oth pht pbl prt red rev spn ths trc trl stylesheet rights].each do |item|
235
237
  @params[item] = [@params[item]] if !@params[item].nil? && @params[item].instance_of?(String)
236
238
  end
237
239
  # optional
@@ -18,7 +18,6 @@ require 'nkf'
18
18
  require 'review/book/base'
19
19
  require 'review/book/chapter'
20
20
  require 'review/book/part'
21
- require 'review/book/parameters'
22
21
  require 'review/book/page_metric'
23
22
  require 'review/book/volume'
24
23
  require 'review/book/index'
@@ -48,26 +48,41 @@ module ReVIEW
48
48
  @basedir_seen[dir] = true
49
49
  end
50
50
 
51
- def initialize(basedir, parameters = Parameters.default)
51
+ def initialize(basedir)
52
52
  @basedir = basedir
53
- @parameters = parameters
54
53
  @parts = nil
55
54
  @chapter_index = nil
55
+ @config = ReVIEW::Configure.values
56
+ @catalog = nil
56
57
  end
57
58
 
58
- extend Forwardable
59
- def_delegators '@parameters',
60
- :chapter_file,
61
- :part_file,
62
- :bib_file,
63
- :reject_file,
64
- :predef_file,
65
- :postdef_file,
66
- :ext,
67
- :image_dir,
68
- :image_types,
69
- :image_types=,
70
- :page_metric
59
+ def bib_file
60
+ config["bib_file"]
61
+ end
62
+
63
+ def reject_file
64
+ config["reject_file"]
65
+ end
66
+
67
+ def ext
68
+ config["ext"]
69
+ end
70
+
71
+ def image_dir
72
+ config["image_dir"]
73
+ end
74
+
75
+ def image_types
76
+ config["image_types"]
77
+ end
78
+
79
+ def image_types=(types)
80
+ config["image_types"] = types
81
+ end
82
+
83
+ def page_metric
84
+ config["page_metric"]
85
+ end
71
86
 
72
87
  def parts
73
88
  @parts ||= read_parts()
@@ -141,12 +156,12 @@ module ReVIEW
141
156
  @config ||= Configure.values
142
157
  end
143
158
 
144
- # backword compatible
159
+ # backward compatible
145
160
  def param=(param)
146
161
  @config = param
147
162
  end
148
163
 
149
- # backword compatible
164
+ # backward compatible
150
165
  def param
151
166
  @config
152
167
  end
@@ -155,7 +170,7 @@ module ReVIEW
155
170
  return @catalog if @catalog.present?
156
171
 
157
172
  catalogfile_path = "#{basedir}/#{config["catalogfile"]}"
158
- if File.exist? catalogfile_path
173
+ if File.file? catalogfile_path
159
174
  @catalog = Catalog.new(File.open catalogfile_path)
160
175
  end
161
176
 
@@ -166,7 +181,7 @@ module ReVIEW
166
181
  if catalog
167
182
  catalog.chaps
168
183
  else
169
- read_FILE(chapter_file)
184
+ read_FILE(config["chapter_file"])
170
185
  end
171
186
  end
172
187
 
@@ -174,7 +189,15 @@ module ReVIEW
174
189
  if catalog
175
190
  catalog.predef
176
191
  else
177
- read_FILE(predef_file)
192
+ read_FILE(config["predef_file"])
193
+ end
194
+ end
195
+
196
+ def read_APPENDIX
197
+ if catalog
198
+ catalog.appendix
199
+ else
200
+ read_FILE(config["postdef_file"]) # for backward compatibility
178
201
  end
179
202
  end
180
203
 
@@ -182,7 +205,7 @@ module ReVIEW
182
205
  if catalog
183
206
  catalog.postdef
184
207
  else
185
- read_FILE(postdef_file)
208
+ ""
186
209
  end
187
210
  end
188
211
 
@@ -192,7 +215,7 @@ module ReVIEW
192
215
  if catalog
193
216
  @read_PART = catalog.parts
194
217
  else
195
- @read_PART = File.read("#{@basedir}/#{part_file}")
218
+ @read_PART = File.read("#{@basedir}/#{config["part_file"]}")
196
219
  end
197
220
  end
198
221
 
@@ -200,7 +223,7 @@ module ReVIEW
200
223
  if catalog
201
224
  catalog.parts.present?
202
225
  else
203
- File.exist?("#{@basedir}/#{part_file}")
226
+ File.exist?("#{@basedir}/#{config["part_file"]}")
204
227
  end
205
228
  end
206
229
 
@@ -217,30 +240,36 @@ module ReVIEW
217
240
  return mkpart_from_namelist(catalog.predef.split("\n"))
218
241
  end
219
242
 
220
- if File.file?("#{@basedir}/#{predef_file}")
243
+ if File.file?("#{@basedir}/#{config["predef_file"]}")
221
244
  begin
222
- return mkpart_from_namelistfile("#{@basedir}/#{predef_file}")
245
+ return mkpart_from_namelistfile("#{@basedir}/#{config["predef_file"]}")
223
246
  rescue FileNotFound => err
224
247
  raise FileNotFound, "preface #{err.message}"
225
248
  end
226
- else
227
- mkpart_from_namelist(%w(preface))
228
249
  end
229
250
  end
230
251
 
231
- def postscripts
252
+ def appendix
232
253
  if catalog
233
- return mkpart_from_namelist(catalog.postdef.split("\n"))
254
+ names = catalog.appendix.split("\n")
255
+ chaps = names.each_with_index.map {|n, idx|
256
+ mkchap_ifexist(n, idx)
257
+ }.compact
258
+ return mkpart(chaps)
234
259
  end
235
260
 
236
- if File.file?("#{@basedir}/#{postdef_file}")
261
+ if File.file?("#{@basedir}/#{config["postdef_file"]}")
237
262
  begin
238
- return mkpart_from_namelistfile("#{@basedir}/#{postdef_file}")
263
+ return mkpart_from_namelistfile("#{@basedir}/#{config["postdef_file"]}")
239
264
  rescue FileNotFound => err
240
265
  raise FileNotFound, "postscript #{err.message}"
241
266
  end
242
- else
243
- mkpart_from_namelist(%w(appendix postscript))
267
+ end
268
+ end
269
+
270
+ def postscripts
271
+ if catalog
272
+ mkpart_from_namelist(catalog.postdef.split("\n"))
244
273
  end
245
274
  end
246
275
 
@@ -255,6 +284,9 @@ module ReVIEW
255
284
  if pre = prefaces
256
285
  list.unshift pre
257
286
  end
287
+ if app = appendix
288
+ list.push app
289
+ end
258
290
  if post = postscripts
259
291
  list.push post
260
292
  end
@@ -322,10 +354,13 @@ module ReVIEW
322
354
  Chapter.new(self, number, name, path)
323
355
  end
324
356
 
325
- def mkchap_ifexist(name)
357
+ def mkchap_ifexist(name, idx = nil)
326
358
  name += ext if File.extname(name) == ""
327
359
  path = "#{@basedir}/#{name}"
328
- File.file?(path) ? Chapter.new(self, nil, name, path) : nil
360
+ if File.file?(path)
361
+ idx += 1 if idx
362
+ Chapter.new(self, idx, name, path)
363
+ end
329
364
  end
330
365
 
331
366
  def read_FILE(filename)
@@ -343,6 +378,8 @@ module ReVIEW
343
378
  res
344
379
  rescue Errno::ENOENT
345
380
  Dir.glob("#{@basedir}/*#{ext()}").sort.join("\n")
381
+ rescue Errno::EISDIR
382
+ ""
346
383
  end
347
384
  end
348
385
  end