review 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +36 -0
  3. data/.rubocop.yml +1 -0
  4. data/ChangeLog +102 -0
  5. data/README.rdoc +2 -2
  6. data/bin/review-check +18 -16
  7. data/bin/review-compile +49 -42
  8. data/bin/review-epubmaker +23 -993
  9. data/bin/review-epubmaker-legacy +1024 -0
  10. data/bin/review-index +17 -15
  11. data/bin/review-init +39 -9
  12. data/bin/review-pdfmaker +124 -89
  13. data/bin/review-preproc +16 -14
  14. data/bin/review-vol +17 -15
  15. data/debian/docs +1 -1
  16. data/doc/catalog.rdoc +34 -0
  17. data/doc/format.rdoc +16 -2
  18. data/doc/libepubmaker/{config.yaml → config.yml} +63 -19
  19. data/doc/quickstart.rdoc +1 -1
  20. data/doc/{sample.yaml → sample.yml} +0 -0
  21. data/lib/epubmaker.rb +1 -1
  22. data/lib/epubmaker/content.rb +9 -1
  23. data/lib/epubmaker/epubv2.rb +59 -7
  24. data/lib/epubmaker/epubv3.rb +14 -9
  25. data/lib/epubmaker/producer.rb +68 -27
  26. data/lib/epubmaker/resource.rb +3 -1
  27. data/lib/lineinput.rb +2 -2
  28. data/lib/review/book/base.rb +125 -24
  29. data/lib/review/book/chapter.rb +42 -0
  30. data/lib/review/book/compilable.rb +23 -4
  31. data/lib/review/book/image_finder.rb +64 -0
  32. data/lib/review/book/index.rb +64 -50
  33. data/lib/review/book/page_metric.rb +1 -1
  34. data/lib/review/builder.rb +19 -12
  35. data/lib/review/catalog.rb +47 -0
  36. data/lib/review/compiler.rb +3 -2
  37. data/lib/review/configure.rb +5 -3
  38. data/lib/review/epubmaker.rb +130 -46
  39. data/lib/review/ewbbuilder.rb +27 -31
  40. data/lib/review/extentions/string.rb +4 -4
  41. data/lib/review/htmlbuilder.rb +140 -79
  42. data/lib/review/htmllayout.rb +26 -4
  43. data/lib/review/htmlutils.rb +20 -1
  44. data/lib/review/i18n.rb +5 -2
  45. data/lib/review/{i18n.yaml → i18n.yml} +4 -2
  46. data/lib/review/idgxmlbuilder.rb +65 -39
  47. data/lib/review/latexbuilder.rb +72 -24
  48. data/lib/review/latexutils.rb +3 -1
  49. data/lib/review/makerhelper.rb +8 -2
  50. data/lib/review/preprocessor.rb +20 -20
  51. data/lib/review/review.tex.erb +4 -0
  52. data/lib/review/sec_counter.rb +9 -11
  53. data/lib/review/tocparser.rb +2 -2
  54. data/lib/review/tocprinter.rb +12 -12
  55. data/lib/review/topbuilder.rb +15 -15
  56. data/lib/review/version.rb +1 -1
  57. data/lib/uuid.rb +7 -7
  58. data/review.gemspec +2 -2
  59. data/rubocop-todo.yml +443 -0
  60. data/test/sample-book/src/config.yml +2 -2
  61. data/test/sample-book/src/{main.css → style.css} +0 -0
  62. data/test/test_book.rb +46 -48
  63. data/test/test_book_chapter.rb +25 -13
  64. data/test/test_builder.rb +3 -3
  65. data/test/test_catalog.rb +107 -0
  66. data/test/test_epubmaker.rb +6 -6
  67. data/test/test_htmlbuilder.rb +160 -39
  68. data/test/test_htmlutils.rb +22 -0
  69. data/test/test_i18n.rb +2 -2
  70. data/test/test_idgxmlbuilder.rb +33 -47
  71. data/test/test_image_finder.rb +82 -0
  72. data/test/test_inaobuilder.rb +1 -1
  73. data/test/test_latexbuilder.rb +35 -39
  74. data/test/test_lineinput.rb +2 -2
  75. data/test/test_markdownbuilder.rb +2 -2
  76. data/test/test_topbuilder.rb +39 -23
  77. metadata +23 -14
  78. data/bin/review-epubmaker-ng +0 -23
@@ -0,0 +1,1024 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ #
4
+ # Copyright (c) 2010-2014 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 'tmpdir'
13
+ require 'fileutils'
14
+ require 'yaml'
15
+ require 'optparse'
16
+ require 'rexml/document'
17
+ require 'time'
18
+
19
+ require 'pathname'
20
+
21
+ bindir = Pathname.new(__FILE__).realpath.dirname
22
+ $LOAD_PATH.unshift((bindir + '../lib').realpath)
23
+
24
+ require 'uuid'
25
+ require 'review'
26
+ require 'review/i18n'
27
+
28
+ require 'review/htmlutils'
29
+ include ReVIEW::HTMLUtils
30
+
31
+ $essential_files = ['top', 'toc', 'colophon']
32
+ def main
33
+ opts = OptionParser.new
34
+ opts.version = ReVIEW::VERSION
35
+ opts.banner = "Usage: #{File.basename($0)} [options] configfile"
36
+ opts.on('-h', '--help', 'print this message and quit.') {
37
+ puts opts.help
38
+ exit 0
39
+ }
40
+ opts.on('--[no-]debug', 'Keep temporary files.') do |debug|
41
+ config["debug"] = debug
42
+ end
43
+
44
+ begin
45
+ opts.parse!
46
+ rescue OptionParser::ParseError => err
47
+ $stderr.puts err.message
48
+ $stderr.puts opts.help
49
+ exit 1
50
+ end
51
+
52
+ if ARGV.empty?
53
+ $stderr.puts opts.help
54
+ exit 1
55
+ end
56
+
57
+ yamlfile = ARGV[0]
58
+ values = ReVIEW::Configure.values.merge(YAML.load_file(yamlfile))
59
+ bookname = values["bookname"]
60
+ $essential_files <<= bookname
61
+ tmp = values["debug"].nil? ? Dir.mktmpdir : "."
62
+ @bookdir = "#{tmp}/#{bookname}-epub"
63
+ @epubversion = values["epubversion"] || 2
64
+ @htmlversion = values["htmlversion"] || 4
65
+ if @epubversion == 3
66
+ ## if epubversion is 3, htmlversion should be 5
67
+ @htmlversion = 5
68
+ end
69
+
70
+ if File.exist?("#{bookname}.epub")
71
+ STDERR.puts "#{bookname}.epub exists. Please remove or rename first."
72
+ exit 1
73
+ end
74
+ if File.exist?(@bookdir)
75
+ STDERR.puts "#{@bookdir} directory exists. Please remove or rename first."
76
+ exit 1
77
+ end
78
+
79
+ @identifier = values["urnid"].nil? ? "urn:uuid:#{UUID.create}" : values["urnid"]
80
+
81
+ Dir.mkdir(@bookdir)
82
+
83
+ # MIME type
84
+ File.open("#{@bookdir}/mimetype", "w") {|f|
85
+ f.write "application/epub+zip"
86
+ }
87
+
88
+ Dir.mkdir("#{@bookdir}/OEBPS")
89
+ # XHTML
90
+ @manifeststr = ""
91
+ @ncxstr = ""
92
+ @tocdesc = Array.new
93
+
94
+ basedir = Dir.pwd
95
+ base_path = Pathname.new(basedir)
96
+ ReVIEW::Book.load(basedir).parts.each do |part|
97
+ if part.name.present?
98
+ if part.file?
99
+ filename = (base_path + part.path).to_s
100
+ output_chaps_by_file(filename, values)
101
+ htmlfile = File.basename(filename.chomp.strip,".*")+".html"
102
+ else
103
+ htmlfile = "part_#{part.number}.html"
104
+ make_part_page(part, htmlfile, values)
105
+ file_id = "part_#{part.number}"
106
+ part_name = "#{ReVIEW::I18n.t("part", part.number)} #{part.name.strip}"
107
+ @tocdesc << [1, htmlfile, nil, part_name]
108
+ @manifeststr << %Q(<item id="rv-#{file_id}" href="#{htmlfile}" media-type="application/xhtml+xml" />\n)
109
+ @ncxstr << %Q(<itemref idref="rv-#{file_id}" />\n)
110
+ end
111
+ end
112
+
113
+ part.chapters.each do |chap|
114
+ filename = Pathname.new(chap.path).relative_path_from(base_path).to_s
115
+ output_chaps_by_file(filename, values)
116
+ end
117
+ end
118
+
119
+ # images
120
+ if File.exist?("images")
121
+ allow_exts = values["image_ext"] || %w(png gif jpg jpeg svg ttf woff otf)
122
+ Dir.mkdir("#{@bookdir}/OEBPS/images")
123
+ image_files = ReVIEW::MakerHelper.copy_images_to_dir("images", "#{@bookdir}/OEBPS/images", :exts=>allow_exts)
124
+ image_files.each do |image_file|
125
+ dirname = File.dirname(image_file)
126
+ fname = File.basename(image_file)
127
+ figid = getFigId(dirname.gsub(%r|/|,'-')+"-"+fname)
128
+ mime = nil
129
+ fname_pattern = /\.(#{allow_exts.join("|")})$/i
130
+ next unless fname =~ fname_pattern
131
+ case fname.downcase.match(fname_pattern)[1]
132
+ when "png"
133
+ mime = "image/png"
134
+ when "gif"
135
+ mime = "image/gif"
136
+ when "jpg", "jpeg"
137
+ mime = "image/jpeg"
138
+ when "svg"
139
+ mime = "image/svg+xml"
140
+ when "ttf", "otf"
141
+ mime = "application/vnd.ms-opentype"
142
+ when "woff"
143
+ mime = "application/font-woff"
144
+ else
145
+ raise "unsupported type #{fname}"
146
+ end
147
+ if @epubversion == 3 && File.join("images",values["coverimage"]) == image_file
148
+ properties = ' properties="cover-image"'
149
+ end
150
+ @manifeststr << %Q(<item id="#{figid}" href="#{image_file}"#{properties} media-type="#{mime}" />\n)
151
+ end
152
+ end
153
+
154
+ # fonts
155
+ fontdir = values["fontdir"] || "fonts"
156
+ if File.exist?(fontdir)
157
+ font_ext = values["font_ext"]
158
+ Dir.mkdir("#{@bookdir}/OEBPS/#{fontdir}")
159
+ font_files = ReVIEW::MakerHelper.copy_images_to_dir(fontdir, "#{@bookdir}/OEBPS/#{fontdir}", :exts=>font_ext)
160
+ font_files.each do |font_file|
161
+ dirname = File.dirname(font_file)
162
+ fname = File.basename(font_file)
163
+ font_id = "font-"+fname
164
+ mime = nil
165
+ fname_pattern = /\.(#{font_ext.join("|")})$/i
166
+ next unless fname =~ fname_pattern
167
+ case fname.downcase.match(fname_pattern)[1]
168
+ when "svg"
169
+ mime = "image/svg+xml"
170
+ when "ttf", "otf"
171
+ mime = "application/vnd.ms-opentype"
172
+ when "woff"
173
+ mime = "application/font-woff"
174
+ else
175
+ raise "unsupported type #{fname}"
176
+ end
177
+ @manifeststr << %Q(<item id="#{font_id}" href="#{font_file}" media-type="#{mime}" />\n)
178
+ end
179
+ end
180
+
181
+ # container
182
+ Dir.mkdir("#{@bookdir}/META-INF")
183
+ File.open("#{@bookdir}/META-INF/container.xml", "w") {|f|
184
+ f.puts <<EOT
185
+ <?xml version="1.0" encoding="UTF-8"?>
186
+ <container xmlns="urn:oasis:names:tc:opendocument:xmlns:container" version="1.0">
187
+ <rootfiles>
188
+ <rootfile full-path="OEBPS/#{bookname}.opf" media-type="application/oebps-package+xml" />
189
+ </rootfiles>
190
+ </container>
191
+ EOT
192
+ }
193
+
194
+ # opf (meta info)
195
+ if @epubversion == 3
196
+ make_opf_filev3(values, bookname)
197
+ else
198
+ make_opf_file(values, bookname)
199
+ end
200
+
201
+ # ncx (toc)
202
+ if values["toc"]
203
+ File.open("#{@bookdir}/OEBPS/#{bookname}.ncx", "w") {|f|
204
+ f.puts <<EOT
205
+ <?xml version="1.0" encoding="UTF-8"?>
206
+ <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
207
+ <head>
208
+ <meta name="dtb:uid" content="#{@identifier}"/>
209
+ <meta name="dtb:depth" content="1"/>
210
+ <meta name="dtb:totalPageCount" content="0"/>
211
+ <meta name="dtb:maxPageNumber" content="0"/>
212
+ </head>
213
+ <docTitle>
214
+ <text>#{values["booktitle"]}</text>
215
+ </docTitle>
216
+ <docAuthor>
217
+ <text>#{values["aut"].nil? ? "" : values["aut"]}</text>
218
+ </docAuthor>
219
+ <navMap>
220
+ <navPoint id="top" playOrder="1">
221
+ <navLabel>
222
+ <text>#{values["booktitle"]}</text>
223
+ </navLabel>
224
+ <content src="#{bookname}.html"/>
225
+ </navPoint>
226
+ EOT
227
+
228
+ nav_count = 2
229
+
230
+ if values["mytoc"]
231
+ f.puts <<EOT
232
+ <navPoint id="toc" playOrder="2">
233
+ <navLabel>
234
+ <text>目次</text>
235
+ </navLabel>
236
+ <content src="toc.html"/>
237
+ </navPoint>
238
+ EOT
239
+ nav_count = 3
240
+ end
241
+
242
+ @tocdesc.each {|item|
243
+ level, file, id, content = item
244
+ # values["level"]
245
+ next if level > values["toclevel"].to_i
246
+ indent = ""
247
+ if level > values["secnolevel"].to_i
248
+ indent = "- "
249
+ end
250
+ fragment_id = (id ? '#'+id : '')
251
+ f.puts <<EOT
252
+ <navPoint id="navPoint-#{nav_count}" playOrder="#{nav_count}">
253
+ <navLabel>
254
+ <text>#{indent}#{strip_html(content)}</text>
255
+ </navLabel>
256
+ <content src="#{file}#{fragment_id}"/>
257
+ </navPoint>
258
+ EOT
259
+ nav_count += 1
260
+ }
261
+ f.puts <<EOT
262
+ </navMap>
263
+ </ncx>
264
+ EOT
265
+ }
266
+ end
267
+
268
+ # Cover page
269
+ File.open("#{@bookdir}/OEBPS/#{bookname}.html", "w") {|f|
270
+ f.puts <<EOT
271
+ <?xml version="1.0" encoding="UTF-8"?>
272
+ EOT
273
+ doctype = make_doctype()
274
+ f.puts doctype
275
+ f.puts <<EOT
276
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ops="http://www.idpf.org/2007/ops" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="ja">
277
+ <head>
278
+ EOT
279
+ if @htmlversion == 4
280
+ f.puts <<EOT
281
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
282
+ <meta http-equiv="Content-Style-Type" content="text/css"/>
283
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
284
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
285
+ EOT
286
+ else
287
+ f.puts <<EOT
288
+ <meta charset="UTF-8" />
289
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
290
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
291
+ EOT
292
+ end
293
+ f.puts <<EOT
294
+ <title>#{values["booktitle"]}</title>
295
+ </head>
296
+ <body>
297
+ EOT
298
+ if !values["coverfile"].nil? && File.exist?(values["coverfile"])
299
+ File.open(values["coverfile"]) {|f2|
300
+ f2.each_line {|l|
301
+ f.puts l
302
+ }
303
+ }
304
+ else
305
+ f.puts <<EOT
306
+ <h1>#{values["booktitle"]}</h1>
307
+ EOT
308
+ end
309
+
310
+ f.puts <<EOT
311
+ </body>
312
+ </html>
313
+ EOT
314
+ }
315
+
316
+ if values["backcoverfile"]
317
+ make_backcover_image(bookname, values)
318
+ end
319
+
320
+ # Title page
321
+ File.open("#{@bookdir}/OEBPS/top.html", "w") {|f|
322
+ f.puts <<EOT
323
+ <?xml version="1.0" encoding="UTF-8"?>
324
+ EOT
325
+ doctype = make_doctype()
326
+ f.puts doctype
327
+ f.puts <<EOT
328
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ops="http://www.idpf.org/2007/ops" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="ja">
329
+ <head>
330
+ EOT
331
+ if @htmlversion == 4
332
+ f.puts <<EOT
333
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
334
+ <meta http-equiv="Content-Style-Type" content="text/css"/>
335
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
336
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
337
+ EOT
338
+ else
339
+ f.puts <<EOT
340
+ <meta charset="UTF-8" />
341
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
342
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
343
+ EOT
344
+ end
345
+ f.puts <<EOT
346
+ <title>#{values["booktitle"]}</title>
347
+ </head>
348
+ <body>
349
+ EOT
350
+ if !values["titlepagefile"].nil? && File.exist?(values["titlepagefile"])
351
+ File.open(values["titlepagefile"]) {|f2|
352
+ f2.each_line {|l|
353
+ f.puts l
354
+ }
355
+ }
356
+ else
357
+ f.puts <<EOT
358
+ <h1 class="tp-title">#{values["booktitle"]}</h1>
359
+ EOT
360
+ if values["aut"]
361
+ f.puts <<EOT
362
+ <p>
363
+ <br />
364
+ <br />
365
+ </p>
366
+ <h2 class="tp-author">#{join_names(values["aut"])}</h2>
367
+ EOT
368
+ end
369
+ if values["prt"]
370
+ f.puts <<EOT
371
+ <p>
372
+ <br />
373
+ <br />
374
+ <br />
375
+ <br />
376
+ </p>
377
+ <h3 class="tp-publisher">#{values["prt"]}</h3>
378
+ EOT
379
+ end
380
+ end
381
+
382
+ f.puts <<EOT
383
+ </body>
384
+ </html>
385
+ EOT
386
+ }
387
+
388
+ # Additional toc page
389
+ if values["toc"] && values["mytoc"]
390
+ File.open("#{@bookdir}/OEBPS/toc.html", "w") {|f|
391
+ if @epubversion == 3
392
+ listelm = "ol"
393
+ else
394
+ listelm = "ul"
395
+ end
396
+ f.puts <<EOT
397
+ <?xml version="1.0" encoding="UTF-8"?>
398
+ EOT
399
+ doctype = make_doctype()
400
+ f.puts doctype
401
+ f.puts <<EOT
402
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ops="http://www.idpf.org/2007/ops" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="ja">
403
+ <head>
404
+ EOT
405
+ if @htmlversion == 4
406
+ f.puts <<EOT
407
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
408
+ <meta http-equiv="Content-Style-Type" content="text/css"/>
409
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
410
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
411
+ EOT
412
+ else
413
+ f.puts <<EOT
414
+ <meta charset="UTF-8" />
415
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
416
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
417
+ EOT
418
+ end
419
+ f.puts <<EOT
420
+ <title>目次</title>
421
+ </head>
422
+ <body>
423
+ EOT
424
+ f.puts %q(<nav epub:type="toc" id="toc">) if @epubversion == 3
425
+ f.puts <<EOT
426
+ <h1>目次</h1>
427
+ <#{listelm} class=\"toc-h1\">
428
+ EOT
429
+ current = 1
430
+ init_item = true
431
+ @tocdesc.each {|item|
432
+ level, file, id, content = item
433
+ # values["level"]
434
+ next if level > values["toclevel"].to_i
435
+ if level > current
436
+ current += 1
437
+ f.puts ""
438
+ f.puts "<#{listelm} class=\"toc-h#{current}\">"
439
+ while current < level
440
+ current += 1
441
+ f.puts "<li>"
442
+ f.puts "<#{listelm} class=\"toc-h#{current}\">"
443
+ end
444
+ elsif level < current
445
+ current -= 1
446
+ f.puts "</li>"
447
+ f.puts "</#{listelm}>"
448
+ f.puts "</li>"
449
+ while current > level
450
+ current -= 1
451
+ f.puts "</#{listelm}>"
452
+ f.puts "</li>"
453
+ end
454
+ elsif init_item
455
+ # noop
456
+ else
457
+ f.puts "</li>"
458
+ end
459
+ fragment_id = (id ? '#'+id : '')
460
+ f.write "<li><a href=\"#{file}#{fragment_id}\">#{strip_html(content)}</a>"
461
+ init_item = false
462
+ }
463
+
464
+ (current - 1).downto(1) {|n|
465
+ f.puts "</li>"
466
+ f.puts "</#{listelm}>"
467
+ }
468
+ if !init_item
469
+ f.puts "</li>"
470
+ end
471
+
472
+ f.puts "</#{listelm}>"
473
+ f.puts %q(</nav>) if @epubversion == 3
474
+ f.puts <<EOT
475
+ </body>
476
+ </html>
477
+ EOT
478
+ }
479
+ end
480
+
481
+ # stylesheet
482
+ if File.exist?(values["stylesheet"])
483
+ FileUtils.cp values["stylesheet"], "#{@bookdir}/OEBPS/#{values["stylesheet"]}"
484
+ else
485
+ File.open("#{@bookdir}/OEBPS/#{values["stylesheet"]}", "w") {|f|
486
+ f.puts <<EOT
487
+ /* sample style sheet for epub */
488
+ @charset "utf-8";
489
+
490
+ body {
491
+ }
492
+ EOT
493
+ }
494
+ end
495
+
496
+ # Colophon page
497
+ if values["colophon"]
498
+ make_colophon_page(tmp, bookname, values)
499
+ end
500
+
501
+ # hook
502
+ if !values["posthook"].nil? && !values["posthook"].empty? && FileTest.executable?(values["posthook"])
503
+ system(values["posthook"], @bookdir, Dir.pwd, yamlfile)
504
+ end
505
+
506
+ # Zip epubファイルの作成。mimetypeは圧縮しないようにする
507
+ basedir = Dir.pwd
508
+ Dir.chdir(@bookdir) {|d|
509
+ system("zip", "-0X", "#{basedir}/#{bookname}.epub", "mimetype")
510
+ system("zip", "-Xr9D", "#{basedir}/#{bookname}.epub", "META-INF", "OEBPS")
511
+ }
512
+ FileUtils.rm_r(tmp) if values["debug"].nil?
513
+ end
514
+
515
+ def make_doctype
516
+ if @htmlversion == 5
517
+ %q(<!DOCTYPE html>)
518
+ else
519
+ %q(<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">)
520
+ end
521
+ end
522
+
523
+
524
+ def make_opf_file(values, bookname)
525
+ File.open("#{@bookdir}/OEBPS/#{bookname}.opf", "w") {|f|
526
+ f.puts <<EOT
527
+ <?xml version="1.0" encoding="UTF-8"?>
528
+ <package version="2.0" xmlns="http://www.idpf.org/2007/opf" unique-identifier="BookId">
529
+ <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
530
+ <dc:title>#{values["booktitle"]}</dc:title>
531
+ EOT
532
+
533
+ f.puts %Q(<dc:creator opf:role="aut">#{values["aut"]}</dc:creator>) unless values["aut"].nil? # FIXME: support multiple members
534
+
535
+ f.puts %Q(<dc:publisher>#{values["prt"]}</dc:publisher>) unless values["prt"].nil?
536
+
537
+ f.puts %Q(<dc:date>#{values["date"]}</dc:date>) unless values["date"].nil?
538
+ f.puts %Q(<dc:rights>#{values["rights"]}</dc:rights>) unless values["rights"].nil?
539
+
540
+ f.puts %Q(<dc:contributor opf:role="asn">#{values["asn"]}</dc:contributor>) unless values["asn"].nil?
541
+ f.puts %Q(<dc:contributor opf:role="ant">#{values["ant"]}</dc:contributor>) unless values["ant"].nil?
542
+ f.puts %Q(<dc:contributor opf:role="clb">#{values["clb"]}</dc:contributor>) unless values["clb"].nil?
543
+ f.puts %Q(<dc:contributor opf:role="edt">#{values["edt"]}</dc:contributor>) unless values["edt"].nil?
544
+ f.puts %Q(<dc:contributor opf:role="dsr">#{values["dsr"]}</dc:contributor>) unless values["dsr"].nil?
545
+ f.puts %Q(<dc:contributor opf:role="ill">#{values["ill"]}</dc:contributor>) unless values["ill"].nil?
546
+ f.puts %Q(<dc:contributor opf:role="pht">#{values["pht"]}</dc:contributor>) unless values["pht"].nil?
547
+ f.puts %Q(<dc:contributor opf:role="trl">#{values["trl"]}</dc:contributor>) unless values["trl"].nil?
548
+
549
+ f.puts %Q(<dc:description>#{values["description"]}</dc:description>) unless values["description"].nil?
550
+
551
+ if values["coverimage"]
552
+ f.puts %Q(<meta name="cover" content="#{getFigId("images-"+values["coverimage"])}"/>)
553
+ end
554
+ f.puts <<EOT
555
+ <dc:language>ja</dc:language>
556
+ <dc:identifier id="BookId">#{@identifier}</dc:identifier>
557
+ </metadata>
558
+ <manifest>
559
+ EOT
560
+
561
+ if values["toc"]
562
+ f.puts <<EOT
563
+ <item id="ncx" href="#{bookname}.ncx" media-type="application/x-dtbncx+xml" />
564
+ EOT
565
+ end
566
+
567
+ f.puts <<EOT
568
+ <item id="style" href="#{values["stylesheet"]}" media-type="text/css" />
569
+ <item id="#{bookname}" href="#{bookname}.html" media-type="application/xhtml+xml" />
570
+ <item id="top" href="top.html" media-type="application/xhtml+xml" />
571
+ EOT
572
+
573
+ if values["toc"] && values["mytoc"]
574
+ f.puts <<EOT
575
+ <item id="toc" href="toc.html" media-type="application/xhtml+xml" />
576
+ EOT
577
+ end
578
+
579
+ f.puts @manifeststr
580
+ if values["colophon"]
581
+ f.puts <<EOT
582
+ <item id="colophon" href="colophon.html" media-type="application/xhtml+xml" />
583
+ EOT
584
+ end
585
+ if values["backcoverfile"]
586
+ f.puts <<EOT
587
+ <item id="backcover" href="#{values["backcoverfile"]}" media-type="application/xhtml+xml" />
588
+ EOT
589
+ end
590
+
591
+ if values["cover_linear"] && values["cover_linear"] != "no"
592
+ cover_linear = "yes"
593
+ else
594
+ cover_linear = "no"
595
+ end
596
+
597
+ f.puts <<EOT
598
+ </manifest>
599
+ <spine toc="ncx">
600
+ <itemref idref="#{bookname}" linear="#{cover_linear}" />
601
+ <itemref idref="top" />
602
+ EOT
603
+
604
+ if values["toc"] && values["mytoc"]
605
+ f.puts <<EOT
606
+ <itemref idref="toc" />
607
+ EOT
608
+ end
609
+
610
+ f.puts @ncxstr
611
+ if values["colophon"]
612
+ f.puts <<EOT
613
+ <itemref idref="colophon" />
614
+ EOT
615
+ end
616
+ if values["backcoverfile"]
617
+ f.puts <<EOT
618
+ <itemref idref="backcover" />
619
+ EOT
620
+ end
621
+ f.puts <<EOT
622
+ </spine>
623
+ <guide>
624
+ EOT
625
+
626
+ if values["titlepage"]
627
+ f.puts <<EOT
628
+ <reference type="cover" title="表紙" href="#{bookname}.html"/>
629
+ <reference type="title-page" title="Title Page" href="top.html"/>
630
+ EOT
631
+ end
632
+
633
+ if values["toc"] && values["mytoc"]
634
+ f.puts <<EOT
635
+ <reference type="toc" title="目次" href="toc.html"/>
636
+ EOT
637
+ end
638
+ f.puts <<EOT
639
+ </guide>
640
+ </package>
641
+ EOT
642
+ }
643
+ end
644
+
645
+ def make_opf_filev3(values, bookname)
646
+ File.open("#{@bookdir}/OEBPS/#{bookname}.opf", "w") {|f|
647
+ f.puts <<EOT
648
+ <?xml version="1.0" encoding="UTF-8"?>
649
+ <package version="3.0" xmlns="http://www.idpf.org/2007/opf" unique-identifier="BookId">
650
+ <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
651
+ <dc:title>#{values["booktitle"]}</dc:title>
652
+ EOT
653
+ unless values["aut"].nil? # FIXME: support multiple members
654
+ f.puts %Q(<dc:creator id="author">#{values["aut"]}</dc:creator>)
655
+ f.puts %Q(<meta refines="#author" property="role" scheme="marc:relators" id="role">aut</meta>)
656
+ end
657
+ f.puts %Q(<dc:publisher id="publisher">#{values["prt"]}</dc:publisher>) unless values["prt"].nil?
658
+
659
+ f.puts %Q(<dc:date>#{values["date"]}</dc:date>) unless values["date"].nil?
660
+ f.puts %Q(<dc:rights>#{values["rights"]}</dc:rights>) unless values["rights"].nil?
661
+
662
+ %w(asn ant clb edt dsr ill pht trl).each do |attr|
663
+ unless values[attr].nil?
664
+ f.puts %Q(<dc:contributor id="#{attr}">#{values[attr]}</dc:contributor>)
665
+ f.puts %Q(<meta refines='##{attr}' property='role' scheme='marc:relators'>#{attr}</meta>)
666
+ end
667
+ end
668
+ f.puts %Q(<dc:description>#{values["description"]}</dc:description>) unless values["description"].nil?
669
+ f.puts %Q(<meta property="dcterms:modified">#{Time.now.utc.iso8601(0)}</meta>)
670
+ if values["coverimage"]
671
+ f.puts %Q(<meta name="cover" content="#{getFigId("images-"+values["coverimage"])}"/>)
672
+ end
673
+ f.puts <<EOT
674
+ <dc:language>ja</dc:language>
675
+ <dc:identifier id="BookId">#{@identifier}</dc:identifier>
676
+ </metadata>
677
+ <manifest>
678
+ EOT
679
+
680
+ if values["toc"]
681
+ f.puts <<EOT
682
+ <item id="ncx" href="#{bookname}.ncx" media-type="application/x-dtbncx+xml" />
683
+ EOT
684
+ end
685
+
686
+ f.puts <<EOT
687
+ <item id="style" href="#{values["stylesheet"]}" media-type="text/css" />
688
+ <item id="#{bookname}" href="#{bookname}.html" media-type="application/xhtml+xml" />
689
+ <item id="top" href="top.html" media-type="application/xhtml+xml" />
690
+ EOT
691
+
692
+ if values["toc"] && values["mytoc"]
693
+ f.puts <<EOT
694
+ <item id="toc" href="toc.html" properties="nav" media-type="application/xhtml+xml" />
695
+ EOT
696
+ end
697
+
698
+ f.puts @manifeststr
699
+ if values["colophon"]
700
+ f.puts <<EOT
701
+ <item id="colophon" href="colophon.html" media-type="application/xhtml+xml" />
702
+ EOT
703
+ end
704
+
705
+ if values["backcoverfile"]
706
+ f.puts <<EOT
707
+ <item id="backcover" href="#{values["backcoverfile"]}" media-type="application/xhtml+xml" />
708
+ EOT
709
+ end
710
+
711
+ if values["cover_linear"] && values["cover_linear"] != "no"
712
+ cover_linear = "yes"
713
+ else
714
+ cover_linear = "no"
715
+ end
716
+
717
+ f.puts <<EOT
718
+ </manifest>
719
+ <spine toc="ncx">
720
+ <itemref idref="#{bookname}" linear="#{cover_linear}" />
721
+ <itemref idref="top" />
722
+ EOT
723
+
724
+ if values["toc"] && values["mytoc"]
725
+ f.puts <<EOT
726
+ <itemref idref="toc" />
727
+ EOT
728
+ end
729
+
730
+ f.puts @ncxstr
731
+ if values["colophon"]
732
+ f.puts <<EOT
733
+ <itemref idref="colophon" />
734
+ EOT
735
+ end
736
+ if values["backcoverfile"]
737
+ f.puts <<EOT
738
+ <itemref idref="backcover" />
739
+ EOT
740
+ end
741
+ f.puts <<EOT
742
+ </spine>
743
+ <guide>
744
+ EOT
745
+
746
+ if values["titlepage"]
747
+ f.puts <<EOT
748
+ <reference type="cover" title="表紙" href="#{bookname}.html"/>
749
+ <reference type="title-page" title="Title Page" href="top.html"/>
750
+ EOT
751
+ end
752
+
753
+ if values["toc"] && values["mytoc"]
754
+ f.puts <<EOT
755
+ <reference type="toc" title="目次" href="toc.html"/>
756
+ EOT
757
+ end
758
+ f.puts <<EOT
759
+ </guide>
760
+ </package>
761
+ EOT
762
+ }
763
+ end
764
+
765
+
766
+ def output_chaps(chapsfile, values)
767
+ File.open(chapsfile) {|chaps|
768
+ chaps.each_line {|l|
769
+ next if l =~ /^#/
770
+ output_chaps_by_file(l, values)
771
+ }
772
+ }
773
+ end
774
+
775
+ def output_chaps_by_file(l, values)
776
+ file_id = File.basename(l.chomp.strip,".*")
777
+ if (idx = $essential_files.index(file_id))
778
+ if idx == $essential_files.size - 1
779
+ STDERR.puts "#{file_id} is book name. Please rename #{l.chomp.strip}."
780
+ else
781
+ STDERR.puts "#{file_id} is special name. Please rename #{l.chomp.strip}."
782
+ end
783
+ exit 1
784
+ end
785
+ filename = "#{file_id}.html"
786
+ system("#{ReVIEW::MakerHelper.bindir}/review-compile --target=html --level=#{values["secnolevel"]} --htmlversion=#{values["htmlversion"]} --epubversion=#{values["epubversion"]} #{values["params"]} #{l} > #{@bookdir}/OEBPS/#{filename}")
787
+ getanchors("#{@bookdir}/OEBPS/#{filename}")
788
+ if @epubversion == 3 && include_mathml?("#{@bookdir}/OEBPS/#{filename}")
789
+ @manifeststr << %Q(<item id="rv-#{file_id}" href="#{filename}" properties="mathml" media-type="application/xhtml+xml" />\n)
790
+ else
791
+ @manifeststr << %Q(<item id="rv-#{file_id}" href="#{filename}" media-type="application/xhtml+xml" />\n)
792
+ end
793
+ @ncxstr << %Q(<itemref idref="rv-#{file_id}" />\n)
794
+ end
795
+
796
+ def include_mathml?(filename)
797
+ File.open(filename) {|f|
798
+ REXML::Document.new(f).each_element("//math"){
799
+ return true
800
+ }
801
+ return false
802
+ }
803
+ rescue
804
+ false
805
+ end
806
+
807
+ def getFigId(filename)
808
+ figid = filename.sub(/\.(png|gif|jpg|jpeg|svg)$/, '')
809
+ "fig-#{figid}"
810
+ end
811
+
812
+ def getTitle(filename)
813
+ File.open(filename) {|f|
814
+ return REXML::Document.new(f).elements["//html/head/title"].text
815
+ }
816
+ end
817
+
818
+ def getanchors(filename)
819
+ File.open(filename) {|f|
820
+ file = filename.sub(/.+\//, '')
821
+ f.each_line {|l|
822
+ if l =~ /\A<h(\d)[^>]*><a id=\"(.+?)\"><\/a>(.+?)<\/h/
823
+ # level, ID, content
824
+ @tocdesc << [$1.to_i, file, $2, $3]
825
+ end
826
+ }
827
+ }
828
+ end
829
+
830
+ def join_names(param)
831
+ if param.respond_to?(:join)
832
+ param.join(ReVIEW::I18n.t("names_splitter"))
833
+ else
834
+ param
835
+ end
836
+ end
837
+
838
+ def make_colophon_page(tmp,bookname,values)
839
+
840
+ header = <<EOT
841
+ <?xml version="1.0" encoding="UTF-8"?>
842
+ EOT
843
+ header += make_doctype()
844
+ header += <<EOT
845
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ops="http://www.idpf.org/2007/ops" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="ja">
846
+ <head>
847
+ EOT
848
+ if @htmlversion == 4
849
+ header += <<EOT
850
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
851
+ <meta http-equiv="Content-Style-Type" content="text/css"/>
852
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
853
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
854
+ EOT
855
+ else
856
+ header += <<EOT
857
+ <meta charset="UTF-8" />
858
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
859
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
860
+ EOT
861
+ end
862
+ header += <<EOT
863
+ <title>#{values["booktitle"]}</title>
864
+ </head>
865
+ <body>
866
+ EOT
867
+
868
+ footer = <<EOT
869
+ </body>
870
+ </html>
871
+ EOT
872
+
873
+ colophon_path = "#{@bookdir}/OEBPS/colophon.html"
874
+ colophon = values["colophon"]
875
+ if colophon.kind_of?(String) && File.exist?(colophon)
876
+ File.open(colophon_path, "w") {|f|
877
+ f.puts header
878
+ File.open(values["colophon"]) {|f2|
879
+ f2.each_line {|l|
880
+ f.puts l
881
+ }
882
+ }
883
+ f.puts footer
884
+ }
885
+ else
886
+ File.open(colophon_path, "w") {|f|
887
+ f.puts header
888
+ f.puts <<EOT
889
+ <div class="colophon">
890
+ <p class="title">#{values["booktitle"]}</p>
891
+ EOT
892
+ if values["pubhistory"]
893
+ f.puts %Q[<div class="pubhistory">\n<p>#{values["pubhistory"].gsub(/\n/,"<br />")}</p>\n</div>]
894
+ end
895
+
896
+ f.puts <<EOT
897
+ <table>
898
+ EOT
899
+ f.puts %Q[<tr>\n <th>著 者</th><td>#{join_names(values["aut"]) + ReVIEW::I18n.t("author_postfix")}</td>\n</tr>] if values["aut"]
900
+ f.puts %Q[<tr>\n <th>監 修</th><td>#{join_names(values["csl"]) + ReVIEW::I18n.t("supervisor_postfix")}</td>\n</tr>] if values["csl"]
901
+ f.puts %Q[<tr>\n <th>翻 訳</th><td>#{join_names(values["trl"]) + ReVIEW::I18n.t("translator_postfix")}</td>\n</tr>] if values["trl"]
902
+ f.puts %Q[<tr>\n <th>デザイン</th><td>#{join_names(values["dsr"])}</td>\n</tr>] if values["dsr"]
903
+ f.puts %Q[<tr>\n <th>イラスト</th><td>#{join_names(values["ill"])}</td>\n</tr>] if values["ill"]
904
+ f.puts %Q[<tr>\n <th>表 紙</th><td>#{join_names(values["cov"])}</td>\n</tr>] if values["cov"]
905
+ f.puts %Q[<tr>\n <th>編 集</th><td>#{join_names(values["edt"])}</td>\n</tr>] if values["edt"]
906
+ f.puts %Q[<tr>\n <th>発行所</th><td>#{values["prt"]}</td>\n</tr>] if values["prt"]
907
+ f.puts <<EOT
908
+ </table>
909
+ EOT
910
+ if values["rights"]
911
+ f.puts %Q[<p class="copyright">#{values["rights"]}</p>]
912
+ end
913
+
914
+ f.puts "</div>"
915
+ f.puts footer
916
+ }
917
+ end
918
+ end
919
+
920
+ def make_part_page(part, filename, values)
921
+ File.open("#{@bookdir}/OEBPS/#{filename}", "w") {|f|
922
+ f.puts <<-EOT
923
+ <?xml version="1.0" encoding="UTF-8"?>
924
+ EOT
925
+ doctype = make_doctype()
926
+ f.puts doctype
927
+ if @htmlversion == 4
928
+ header = <<-EOT
929
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ops="http://www.idpf.org/2007/ops" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="ja">
930
+ <head>
931
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
932
+ <meta http-equiv="Content-Style-Type" content="text/css"/>
933
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
934
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
935
+ <title>#{values["booktitle"]}</title>
936
+ </head>
937
+ EOT
938
+ else
939
+ header = <<-EOT
940
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ops="http://www.idpf.org/2007/ops" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="ja">
941
+ <head>
942
+ <meta charset="UTF-8" />
943
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
944
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
945
+ <title>#{values["booktitle"]}</title>
946
+ </head>
947
+ EOT
948
+ end
949
+ f.puts header
950
+
951
+ f.puts <<-EOT
952
+ <body>
953
+ <h1 class="part-number">#{ReVIEW::I18n.t("part", part.number)}</h1>
954
+ EOT
955
+
956
+ if part.name.strip.present?
957
+ f.puts <<-EOT
958
+ <h2 class="part-title">#{part.name.strip}</h2>
959
+ EOT
960
+ end
961
+
962
+ f.puts <<-EOT
963
+ </body>
964
+ </html>
965
+ EOT
966
+ }
967
+ end
968
+
969
+ def make_backcover_image(bookname, values)
970
+ backcoverfile = values["backcoverfile"]
971
+ File.open("#{@bookdir}/OEBPS/#{backcoverfile}", "w") {|f|
972
+ f.puts <<EOT
973
+ <?xml version="1.0" encoding="UTF-8"?>
974
+ EOT
975
+ doctype = make_doctype()
976
+ f.puts doctype
977
+ f.puts <<EOT
978
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ops="http://www.idpf.org/2007/ops" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="ja">
979
+ <head>
980
+ EOT
981
+ if @htmlversion == 4
982
+ f.puts <<EOT
983
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
984
+ <meta http-equiv="Content-Style-Type" content="text/css"/>
985
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
986
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
987
+ EOT
988
+ else
989
+ f.puts <<EOT
990
+ <meta charset="UTF-8" />
991
+ <link rel="stylesheet" type="text/css" href="#{values["stylesheet"]}"/>
992
+ <meta name="generator" content="Re:VIEW EPUB Maker"/>
993
+ EOT
994
+ end
995
+ f.puts <<EOT
996
+ <title>#{values["booktitle"]}</title>
997
+ </head>
998
+ <body>
999
+ EOT
1000
+ if File.exist?(backcoverfile)
1001
+ File.open(backcoverfile) {|f2|
1002
+ f2.each_line {|l|
1003
+ f.puts l
1004
+ }
1005
+ }
1006
+ else
1007
+ f.puts <<EOT
1008
+ <div id="back-cover-image" class="full">
1009
+ <img src="images/#{backcoverfile}" alt="back-cover"/>
1010
+ </div>
1011
+ EOT
1012
+ end
1013
+
1014
+ f.puts <<EOT
1015
+ </body>
1016
+ </html>
1017
+ EOT
1018
+ }
1019
+ end
1020
+
1021
+
1022
+
1023
+
1024
+ main