review 0.9.0 → 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.
Files changed (49) hide show
  1. data/.travis.yml +9 -0
  2. data/ChangeLog +326 -0
  3. data/Rakefile +3 -5
  4. data/VERSION +1 -1
  5. data/bin/review-compile +50 -50
  6. data/bin/review-epubmaker +62 -75
  7. data/bin/review-epubmaker-ng +185 -0
  8. data/bin/review-index +2 -1
  9. data/bin/review-pdfmaker +158 -101
  10. data/bin/review-vol +6 -2
  11. data/doc/format.rdoc +111 -46
  12. data/doc/libepubmaker/sample.yaml +90 -0
  13. data/doc/quickstart.rdoc +188 -0
  14. data/doc/sample.yaml +8 -0
  15. data/lib/epubmaker.rb +28 -0
  16. data/lib/epubmaker/content.rb +82 -0
  17. data/lib/epubmaker/epubv2.rb +419 -0
  18. data/lib/epubmaker/epubv3.rb +249 -0
  19. data/lib/epubmaker/producer.rb +204 -0
  20. data/lib/epubmaker/resource.rb +66 -0
  21. data/lib/review.rb +1 -1
  22. data/lib/review/book.rb +27 -4
  23. data/lib/review/builder.rb +153 -20
  24. data/lib/review/compiler.rb +61 -10
  25. data/lib/review/ewbbuilder.rb +3 -2
  26. data/lib/review/htmlbuilder.rb +174 -67
  27. data/lib/review/i18n.rb +30 -0
  28. data/lib/review/i18n.yaml +23 -0
  29. data/lib/review/idgxmlbuilder.rb +110 -63
  30. data/lib/review/index.rb +34 -12
  31. data/lib/review/latexbuilder.rb +128 -33
  32. data/lib/review/latexutils.rb +18 -1
  33. data/lib/review/textbuilder.rb +17 -0
  34. data/lib/review/tocparser.rb +3 -1
  35. data/lib/review/tocprinter.rb +1 -0
  36. data/lib/review/topbuilder.rb +397 -198
  37. data/review.gemspec +101 -100
  38. data/test/test_book.rb +27 -0
  39. data/test/test_epubmaker.rb +507 -0
  40. data/test/test_helper.rb +8 -0
  41. data/test/test_htmlbuilder.rb +295 -10
  42. data/test/test_i18n.rb +64 -0
  43. data/test/test_idgxmlbuilder.rb +268 -10
  44. data/test/test_latexbuilder.rb +316 -20
  45. data/test/test_preprocessor.rb +23 -0
  46. data/test/test_topbuilder.rb +246 -0
  47. metadata +46 -53
  48. data/doc/format.re +0 -505
  49. data/test/test_index.rb +0 -15
data/bin/review-epubmaker CHANGED
@@ -26,7 +26,7 @@ def main
26
26
  values = { # These parameters can be overridden by YAML file.
27
27
  "bookname"=> nil, # it defines epub file name also
28
28
  "booktitle" => "ReVIEW EPUBサンプル",
29
- "aut" => "吟遊詩人", # author
29
+ "aut" => nil, # author
30
30
  "prt" => nil, # printer(publisher)
31
31
  "asn" => nil, # associated name
32
32
  "ant" => nil, # bibliographic antecedent
@@ -70,82 +70,37 @@ def main
70
70
  identifier = values["urnid"].nil? ? "urn:uuid:#{UUID.create}" : values["urnid"]
71
71
 
72
72
  tmp = values["debug"].nil? ? Dir.mktmpdir : "."
73
- Dir.mkdir("#{tmp}/#{bookname}")
73
+ @bookdir = "#{tmp}/#{bookname}"
74
+ Dir.mkdir(@bookdir)
74
75
 
75
76
  # MIME type
76
- File.open("#{tmp}/#{bookname}/mimetype", "w") {|f|
77
+ File.open("#{@bookdir}/mimetype", "w") {|f|
77
78
  f.puts "application/epub+zip"
78
79
  }
79
80
 
80
- Dir.mkdir("#{tmp}/#{bookname}/OEBPS")
81
+ Dir.mkdir("#{@bookdir}/OEBPS")
81
82
  # XHTML
82
- pre = 0
83
- body = 0
84
- post = 0
85
83
  @manifeststr = ""
86
84
  @ncxstr = ""
87
85
  @tocdesc = Array.new
88
- toccount = 2
89
86
 
90
87
  if File.exists?("PREDEF")
91
- File.open("PREDEF") {|chaps|
92
- chaps.each_line {|l|
93
- next if l =~ /^#/
94
- pre = pre + 1
95
- toccount = toccount + 1
96
- fork {
97
- STDOUT.reopen("#{tmp}/#{bookname}/OEBPS/pre#{pre}.html")
98
- exec("review-compile --target=html --level=#{values["secnolevel"]} #{values["params"]} #{l}")
99
- }
100
- Process.waitall
101
- getanchors("#{tmp}/#{bookname}/OEBPS/pre#{pre}.html")
102
- @manifeststr << %Q(<item id="pre#{pre}" href="pre#{pre}.html" media-type="application/xhtml+xml" />\n)
103
- @ncxstr << %Q(<itemref idref="pre#{pre}" />\n)
104
- }
105
- }
88
+ output_chaps("PREDEF", values)
106
89
  end
107
90
  if File.exists?("CHAPS")
108
- File.open("CHAPS") {|chaps|
109
- chaps.each_line {|l|
110
- body = body + 1
111
- toccount = toccount + 1
112
- next if l =~ /^#/
113
- fork {
114
- STDOUT.reopen("#{tmp}/#{bookname}/OEBPS/chap#{body}.html")
115
- exec("review-compile --target=html --level=#{values["secnolevel"]} #{values["params"]} #{l}")
116
- }
117
- Process.waitall
118
- getanchors("#{tmp}/#{bookname}/OEBPS/chap#{body}.html")
119
- @manifeststr << %Q(<item id="chap#{body}" href="chap#{body}.html" media-type="application/xhtml+xml" />\n)
120
- @ncxstr << %Q(<itemref idref="chap#{body}" />\n)
121
- }
122
- }
91
+ output_chaps("CHAPS", values)
123
92
  end
124
93
  if File.exists?("POSTDEF")
125
- File.open("POSTDEF") {|chaps|
126
- chaps.each_line {|l|
127
- next if l =~ /^#/
128
- post = post + 1
129
- toccount = toccount + 1
130
- fork {
131
- STDOUT.reopen("#{tmp}/#{bookname}/OEBPS/post#{post}.html")
132
- exec("review-compile --target=html --level=#{values["secnolevel"]} #{values["params"]} #{l}")
133
- }
134
- Process.waitall
135
- getanchors("#{tmp}/#{bookname}/OEBPS/post#{post}.html")
136
- @manifeststr << %Q(<item id="post#{post}" href="post#{post}.html" media-type="application/xhtml+xml" />\n)
137
- @ncxstr << %Q(<itemref idref="post#{post}" />\n)
138
- }
139
- }
94
+ output_chaps("POSTDEF", values)
140
95
  end
141
96
  if File.exist?("images")
142
- Dir.mkdir("#{tmp}/#{bookname}/OEBPS/images")
143
- copyImagesToDir("images", "#{tmp}/#{bookname}/OEBPS/images")
97
+ Dir.mkdir("#{@bookdir}/OEBPS/images")
98
+ copyImagesToDir("images", "#{@bookdir}/OEBPS/images")
144
99
  end
145
100
 
146
101
  # container
147
- Dir.mkdir("#{tmp}/#{bookname}/META-INF")
148
- File.open("#{tmp}/#{bookname}/META-INF/container.xml", "w") {|f|
102
+ Dir.mkdir("#{@bookdir}/META-INF")
103
+ File.open("#{@bookdir}/META-INF/container.xml", "w") {|f|
149
104
  f.puts <<EOT
150
105
  <?xml version="1.0" encoding="UTF-8"?>
151
106
  <container xmlns="urn:oasis:names:tc:opendocument:xmlns:container" version="1.0">
@@ -157,7 +112,7 @@ EOT
157
112
  }
158
113
 
159
114
  # opf (meta info)
160
- File.open("#{tmp}/#{bookname}/OEBPS/#{bookname}.opf", "w") {|f|
115
+ File.open("#{@bookdir}/OEBPS/#{bookname}.opf", "w") {|f|
161
116
  f.puts <<EOT
162
117
  <?xml version="1.0" encoding="UTF-8"?>
163
118
  <package version="2.0" xmlns="http://www.idpf.org/2007/opf" unique-identifier="BookId">
@@ -209,10 +164,11 @@ EOT
209
164
  <item id="colophon" href="colophon.html" media-type="application/xhtml+xml" />
210
165
  EOT
211
166
  end
167
+ cover_linear = values["cover_linear"] || "no"
212
168
  f.puts <<EOT
213
169
  </manifest>
214
170
  <spine toc="ncx">
215
- <itemref idref="#{bookname}" linear="no" />
171
+ <itemref idref="#{bookname}" linear="#{cover_linear}" />
216
172
  <itemref idref="top" />
217
173
  EOT
218
174
  unless values["mytoc"].nil?
@@ -245,7 +201,7 @@ EOT
245
201
  }
246
202
 
247
203
  # ncx (toc)
248
- File.open("#{tmp}/#{bookname}/OEBPS/#{bookname}.ncx", "w") {|f|
204
+ File.open("#{@bookdir}/OEBPS/#{bookname}.ncx", "w") {|f|
249
205
  f.puts <<EOT
250
206
  <?xml version="1.0" encoding="UTF-8"?>
251
207
  <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
@@ -309,7 +265,7 @@ EOT
309
265
  }
310
266
 
311
267
  # Cover page
312
- File.open("#{tmp}/#{bookname}/OEBPS/#{bookname}.html", "w") {|f|
268
+ File.open("#{@bookdir}/OEBPS/#{bookname}.html", "w") {|f|
313
269
  f.puts <<EOT
314
270
  <?xml version="1.0" encoding="UTF-8"?>
315
271
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
@@ -343,7 +299,7 @@ EOT
343
299
 
344
300
 
345
301
  # Title page
346
- File.open("#{tmp}/#{bookname}/OEBPS/top.html", "w") {|f|
302
+ File.open("#{@bookdir}/OEBPS/top.html", "w") {|f|
347
303
  f.puts <<EOT
348
304
  <?xml version="1.0" encoding="UTF-8"?>
349
305
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
@@ -397,7 +353,7 @@ EOT
397
353
 
398
354
  # Additional toc page
399
355
  unless values["mytoc"].nil?
400
- File.open("#{tmp}/#{bookname}/OEBPS/toc.html", "w") {|f|
356
+ File.open("#{@bookdir}/OEBPS/toc.html", "w") {|f|
401
357
  f.puts <<EOT
402
358
  <?xml version="1.0" encoding="UTF-8"?>
403
359
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
@@ -421,14 +377,24 @@ EOT
421
377
  # values["level"]
422
378
  next if level > values["toclevel"].to_i
423
379
  if level > current
380
+ current += 1
424
381
  f.puts ""
425
- f.puts "<ul class=\"toc-h#{level}\">"
426
- current = level
382
+ f.puts "<ul class=\"toc-h#{current}\">"
383
+ while current < level
384
+ current += 1
385
+ f.puts "<li>"
386
+ f.puts "<ul class=\"toc-h#{current}\">"
387
+ end
427
388
  elsif level < current
389
+ current -= 1
428
390
  f.puts "</li>"
429
391
  f.puts "</ul>"
430
392
  f.puts "</li>"
431
- current = level
393
+ while current > level
394
+ current -= 1
395
+ f.puts "</ul>"
396
+ f.puts "</li>"
397
+ end
432
398
  elsif init_item
433
399
  # noop
434
400
  else
@@ -455,17 +421,18 @@ EOT
455
421
  end
456
422
 
457
423
  # stylesheet
458
- File.open("#{tmp}/#{bookname}/OEBPS/stylesheet.css", "w") {|f|
459
- f.puts <<EOT
424
+ if File.exist?(values["stylesheet"])
425
+ FileUtils.cp values["stylesheet"], "#{@bookdir}/OEBPS/#{values["stylesheet"]}"
426
+ else
427
+ File.open("#{@bookdir}/OEBPS/#{values["stylesheet"]}", "w") {|f|
428
+ f.puts <<EOT
460
429
  /* sample style sheet for epub */
461
430
  @charset "utf-8";
462
431
 
463
432
  body {
464
433
  }
465
434
  EOT
466
- }
467
- if File.exist?(values["stylesheet"])
468
- FileUtils.cp values["stylesheet"], "#{tmp}/#{bookname}/OEBPS/#{values["stylesheet"]}"
435
+ }
469
436
  end
470
437
 
471
438
  # Colophon page
@@ -476,7 +443,7 @@ EOT
476
443
  # hook
477
444
  if !values["posthook"].nil? && !values["posthook"].empty? && FileTest.executable?(values["posthook"])
478
445
  fork {
479
- exec(values["posthook"], "#{tmp}/#{bookname}", Dir.pwd, yamlfile)
446
+ exec(values["posthook"], @bookdir, Dir.pwd, yamlfile)
480
447
  }
481
448
  Process.waitall
482
449
  end
@@ -484,14 +451,14 @@ EOT
484
451
  # Zip epubファイルの作成。mimetypeは圧縮しないようにする
485
452
  fork {
486
453
  basedir = Dir.pwd
487
- Dir.chdir("#{tmp}/#{bookname}") {|d|
454
+ Dir.chdir(@bookdir) {|d|
488
455
  exec("zip -0X #{basedir}/#{bookname}.epub mimetype")
489
456
  }
490
457
  }
491
458
  Process.waitall
492
459
  fork {
493
460
  basedir = Dir.pwd
494
- Dir.chdir("#{tmp}/#{bookname}") {|d|
461
+ Dir.chdir(@bookdir) {|d|
495
462
  exec("zip -Xr9D #{basedir}/#{bookname}.epub META-INF OEBPS")
496
463
  }
497
464
  }
@@ -500,6 +467,25 @@ EOT
500
467
  FileUtils.rm_r(tmp) if values["debug"].nil?
501
468
  end
502
469
 
470
+ def output_chaps(chapsfile, values)
471
+ File.open(chapsfile) {|chaps|
472
+ chaps.each_line {|l|
473
+ next if l =~ /^#/
474
+ file_id = File.basename(l.chomp.strip,".*")
475
+ filename = "#{file_id}.html"
476
+ fork {
477
+ STDOUT.reopen("#{@bookdir}/OEBPS/#{filename}")
478
+ exec("review-compile --target=html --level=#{values["secnolevel"]} #{values["params"]} #{l}")
479
+ }
480
+ Process.waitall
481
+ getanchors("#{@bookdir}/OEBPS/#{filename}")
482
+ @manifeststr << %Q(<item id="#{file_id}" href="#{filename}" media-type="application/xhtml+xml" />\n)
483
+ @ncxstr << %Q(<itemref idref="#{file_id}" />\n)
484
+ }
485
+ }
486
+ end
487
+
488
+
503
489
  def copyImagesToDir(dirname, copybase)
504
490
  Dir.open(dirname) {|dir|
505
491
  dir.each {|fname|
@@ -575,7 +561,7 @@ EOT
575
561
  </html>
576
562
  EOT
577
563
 
578
- colophon_path = "#{tmp}/#{bookname}/OEBPS/colophon.html"
564
+ colophon_path = "#{@bookdir}/OEBPS/colophon.html"
579
565
  colophon = values["colophon"]
580
566
  if colophon.kind_of?(String) && File.exist?(colophon)
581
567
  File.open(colophon_path, "w") {|f|
@@ -602,6 +588,7 @@ EOT
602
588
  <table>
603
589
  EOT
604
590
  f.puts %Q[<tr>\n <th>著 者</th><td>#{values["aut"]}</td>\n</tr>] if values["aut"]
591
+ f.puts %Q[<tr>\n <th>翻 訳</th><td>#{values["trl"]}</td>\n</tr>] if values["trl"]
605
592
  f.puts %Q[<tr>\n <th>デザイン</th><td>#{values["dsr"]}</td>\n</tr>] if values["dsr"]
606
593
  f.puts %Q[<tr>\n <th>イラスト</th><td>#{values["ill"]}</td>\n</tr>] if values["ill"]
607
594
  f.puts %Q[<tr>\n <th>編 集</th><td>#{values["edt"]}</td>\n</tr>] if values["edt"]
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ #
4
+ # Copyright (c) 2010 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 'pathname'
13
+ bindir = Pathname.new(__FILE__).realpath.dirname
14
+ $LOAD_PATH.unshift((bindir + '../lib').realpath)
15
+ require 'epubmaker'
16
+ include EPUBMaker
17
+
18
+ def main
19
+ if ARGV.size != 1
20
+ puts "Usage: #{$0} configfile"
21
+ exit 0
22
+ end
23
+
24
+ @params = { # These parameters can be overridden by YAML file.
25
+ "bookname" => "example", # Book file
26
+ "title" => "example", # Book title
27
+ "params" => "", # specify review2html parameters
28
+ "epubversion" => 2,# EPUB version
29
+ "toclevel" => 3, # level of toc
30
+ "secnolevel" => 2, # level of section #
31
+ "posthook" => nil, # command path of post hook
32
+ "debug" => nil, # debug flag
33
+ }
34
+
35
+ yamlfile = ARGV[0]
36
+ @epub = Producer.new(@params)
37
+ @epub.load(yamlfile)
38
+ @params = @epub.params
39
+
40
+ bookname = @params["bookname"]
41
+
42
+ if File.exist?("#{bookname}.epub")
43
+ STDERR.puts "#{bookname}.epub exists. Please remove or rename it first."
44
+ exit 1
45
+ end
46
+ if @params["debug"] && File.exist?("#{bookname}")
47
+ STDERR.puts "#{bookname} debug directory exists. Please remove or rename it first."
48
+ exit 1
49
+ end
50
+
51
+ basetmp = Dir.mktmpdir
52
+
53
+ FileUtils.cp(@params["cover"], "#{basetmp}/#{@params["cover"]}") if !@params["cover"].nil? && File.exist?(@params["cover"])
54
+
55
+ unless @params["titlepage"].nil? # FIXME
56
+ FileUtils.cp(@params["titlepage"], "#{basetmp}/#{@params["titlepage"]}")
57
+ @epub.contents.push(Content.new("id" => "title", "file" => @params["titlepage"], "title" => @epub.res.v("titlepagetitle")))
58
+ end
59
+
60
+ makeBody(basetmp, yamlfile)
61
+
62
+ unless @params["colophon"].nil?
63
+ if @params["colophon"].instance_of?(String)
64
+ FileUtils.cp(@params["colophon"], "#{basetmp}/colophon.#{@params["htmlext"]}")
65
+ else
66
+ File.open("#{basetmp}/colophon.#{@params["htmlext"]}", "w") {|f| @epub.colophon(f) }
67
+ end
68
+ @epub.contents.push(Content.new("id" => "colophon", "file" => "colophon.#{@params["htmlext"]}", "title" => @epub.res.v("colophontitle")))
69
+ end
70
+
71
+ epubtmpdir = @params["debug"].nil? ? nil : "#{Dir.pwd}/#{bookname}"
72
+ unless @params["debug"].nil?
73
+ Dir.mkdir(bookname)
74
+ end
75
+ @epub.produce("#{bookname}.epub", basetmp, epubtmpdir)
76
+
77
+ FileUtils.rm_r(basetmp)
78
+ end
79
+
80
+ def makeBody(basetmp, yamlfile)
81
+ pre = 0
82
+ body = 0
83
+ post = 0
84
+ @manifeststr = ""
85
+ @ncxstr = ""
86
+ @tocdesc = Array.new
87
+ toccount = 2
88
+
89
+ if File.exists?("PREDEF")
90
+ File.open("PREDEF") do |chaps|
91
+ chaps.each_line do |l|
92
+ pre += 1
93
+ next if l =~ /\A#/
94
+ fork {
95
+ STDOUT.reopen("#{basetmp}/pre#{pre}.#{@params["htmlext"]}")
96
+ exec("review-compile --target=html --yaml=#{yamlfile} #{l}")
97
+ }
98
+ Process.waitall
99
+ getanchors(basetmp, "pre#{pre}.#{@params["htmlext"]}")
100
+ end
101
+ end
102
+ end
103
+
104
+ if File.exists?("CHAPS")
105
+ File.open("CHAPS") do |chaps|
106
+ chaps.each_line do |l|
107
+ body += 1
108
+ next if l =~ /\A#/
109
+ fork {
110
+ STDOUT.reopen("#{basetmp}/chap#{body}.#{@params["htmlext"]}")
111
+ exec("review-compile --target=html --yaml=#{yamlfile} #{l}")
112
+ }
113
+ Process.waitall
114
+ getanchors(basetmp, "chap#{body}.#{@params["htmlext"]}")
115
+ end
116
+ end
117
+ end
118
+
119
+ if File.exists?("POSTDEF")
120
+ File.open("POSTDEF") do |chaps|
121
+ chaps.each_line do |l|
122
+ post += 1
123
+ next if l =~ /^#/
124
+ fork {
125
+ STDOUT.reopen("#{basetmp}/post#{post}.#{@params["htmlext"]}")
126
+ exec("review-compile --target=html --yaml=#{yamlfile} #{l}")
127
+ }
128
+ Process.waitall
129
+ getanchors(basetmp, "post#{post}.#{@params["htmlext"]}")
130
+ end
131
+ end
132
+ end
133
+ if File.exist?("images")
134
+ Dir.mkdir("#{basetmp}/images")
135
+ copyImagesToDir("images", "#{basetmp}/images")
136
+ end
137
+ end
138
+
139
+ def getanchors(basetmp, filename)
140
+ File.open("#{basetmp}/#{filename}") do |f|
141
+ firsttime = true
142
+ f.each_line do |l|
143
+ if l =~ /\A<h(\d)><a id=\"(.+?)\" \/>(.+?)<\/h/
144
+ # level, ID, content
145
+ level = $1.to_i
146
+ id = $2
147
+ title = $3
148
+ if level == 1 && !firsttime.nil?
149
+ @epub.contents.push(Content.new({
150
+ "id" => "#{filename.sub(".#{@params["htmlext"]}", '')}",
151
+ "file" => "#{filename}",
152
+ "level" => level,
153
+ "title" => title
154
+ }))
155
+ firsttime = nil
156
+ else
157
+ @epub.contents.push(Content.new({
158
+ "id" => "#{filename.sub(".#{@params["htmlext"]}", '')}-#{id}",
159
+ "file" => "#{filename}##{id}",
160
+ "level" => level,
161
+ "title" => title
162
+ }))
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ def copyImagesToDir(dirname, copybase)
170
+ Dir.open(dirname) do |dir|
171
+ dir.each do |fname|
172
+ next if fname =~ /\A\./
173
+ if FileTest.directory?("#{dirname}/#{fname}")
174
+ copyImagesToDir("#{dirname}/#{fname}", "#{copybase}/#{fname}")
175
+ else
176
+ if fname =~ /\.(png|gif|jpg|jpeg|svg)\Z/i
177
+ Dir.mkdir(copybase) unless File.exist?(copybase)
178
+ FileUtils.cp "#{dirname}/#{fname}", copybase
179
+ end
180
+ end
181
+ end
182
+ end
183
+ end
184
+
185
+ main