review 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +90 -66
  3. data/.travis.yml +1 -1
  4. data/Gemfile +0 -1
  5. data/NEWS.ja.md +82 -0
  6. data/NEWS.md +83 -0
  7. data/README.md +5 -3
  8. data/Rakefile +8 -8
  9. data/bin/review +1 -5
  10. data/bin/review-catalog-converter +22 -27
  11. data/bin/review-check +36 -43
  12. data/bin/review-checkdep +10 -15
  13. data/bin/review-compile +37 -55
  14. data/bin/review-epubmaker +4 -5
  15. data/bin/review-index +21 -29
  16. data/bin/review-init +26 -37
  17. data/bin/review-pdfmaker +0 -2
  18. data/bin/review-preproc +25 -45
  19. data/bin/review-validate +19 -18
  20. data/bin/review-vol +15 -27
  21. data/doc/config.yml.sample +5 -2
  22. data/doc/format.ja.md +20 -1
  23. data/doc/format.md +21 -5
  24. data/doc/images/review-generate.png +0 -0
  25. data/lib/epubmaker.rb +1 -3
  26. data/lib/epubmaker/content.rb +24 -27
  27. data/lib/epubmaker/epubcommon.rb +135 -148
  28. data/lib/epubmaker/epubv2.rb +39 -46
  29. data/lib/epubmaker/epubv3.rb +93 -103
  30. data/lib/epubmaker/producer.rb +138 -151
  31. data/lib/epubmaker/zip_exporter.rb +21 -26
  32. data/lib/review/book.rb +3 -6
  33. data/lib/review/book/base.rb +78 -103
  34. data/lib/review/book/chapter.rb +36 -40
  35. data/lib/review/book/compilable.rb +28 -31
  36. data/lib/review/book/image_finder.rb +6 -13
  37. data/lib/review/book/index.rb +100 -121
  38. data/lib/review/book/page_metric.rb +2 -7
  39. data/lib/review/book/part.rb +18 -20
  40. data/lib/review/book/volume.rb +9 -13
  41. data/lib/review/builder.rb +81 -116
  42. data/lib/review/catalog.rb +15 -19
  43. data/lib/review/compiler.rb +64 -83
  44. data/lib/review/configure.rb +87 -97
  45. data/lib/review/converter.rb +2 -7
  46. data/lib/review/epubbuilder.rb +1 -3
  47. data/lib/review/epubmaker.rb +213 -205
  48. data/lib/review/exception.rb +2 -4
  49. data/lib/review/extentions.rb +0 -1
  50. data/lib/review/extentions/hash.rb +2 -2
  51. data/lib/review/extentions/string.rb +5 -30
  52. data/lib/review/htmlbuilder.rb +320 -375
  53. data/lib/review/htmltoc.rb +4 -7
  54. data/lib/review/htmlutils.rb +29 -32
  55. data/lib/review/i18n.rb +33 -44
  56. data/lib/review/i18n.yml +3 -3
  57. data/lib/review/idgxmlbuilder.rb +309 -345
  58. data/lib/review/latexbuilder.rb +175 -212
  59. data/lib/review/latexindex.rb +2 -8
  60. data/lib/review/latexutils.rb +33 -43
  61. data/lib/review/lineinput.rb +1 -1
  62. data/lib/review/logger.rb +21 -0
  63. data/lib/review/makerhelper.rb +1 -4
  64. data/lib/review/markdownbuilder.rb +44 -53
  65. data/lib/review/md2inaobuilder.rb +6 -12
  66. data/lib/review/pdfmaker.rb +143 -173
  67. data/lib/review/preprocessor.rb +64 -101
  68. data/lib/review/rstbuilder.rb +126 -158
  69. data/lib/review/sec_counter.rb +18 -34
  70. data/lib/review/template.rb +4 -5
  71. data/lib/review/textbuilder.rb +2 -3
  72. data/lib/review/textutils.rb +7 -13
  73. data/lib/review/tocparser.rb +31 -56
  74. data/lib/review/tocprinter.rb +26 -52
  75. data/lib/review/topbuilder.rb +219 -247
  76. data/lib/review/unfold.rb +15 -24
  77. data/lib/review/version.rb +1 -1
  78. data/lib/review/webmaker.rb +75 -99
  79. data/lib/review/webtocprinter.rb +15 -20
  80. data/lib/review/yamlloader.rb +13 -15
  81. data/review.gemspec +20 -22
  82. data/templates/latex/layout.tex.erb +2 -2
  83. data/templates/opf/epubv2.opf.erb +7 -7
  84. data/templates/opf/epubv3.opf.erb +7 -7
  85. data/templates/web/html/layout-html5.html.erb +2 -2
  86. data/test/assets/black.eps +280 -0
  87. data/test/assets/fit.png +0 -0
  88. data/test/assets/large.gif +0 -0
  89. data/test/assets/large.jpg +0 -0
  90. data/test/assets/large.png +0 -0
  91. data/test/assets/large.svg +65 -0
  92. data/test/assets/test_template.tex +1 -1
  93. data/test/book_test_helper.rb +2 -2
  94. data/test/run_test.rb +4 -4
  95. data/test/sample-book/src/Rakefile +21 -22
  96. data/test/syntax-book/Gemfile +4 -0
  97. data/test/syntax-book/Rakefile +72 -0
  98. data/test/syntax-book/appA.re +22 -0
  99. data/test/syntax-book/bib.re +6 -0
  100. data/test/syntax-book/catalog.yml +15 -0
  101. data/test/syntax-book/ch01.re +136 -0
  102. data/test/syntax-book/ch02.re +351 -0
  103. data/test/syntax-book/ch03.re +82 -0
  104. data/test/syntax-book/config.yml +35 -0
  105. data/test/syntax-book/images/ball.png +0 -0
  106. data/test/syntax-book/images/cover.jpg +0 -0
  107. data/test/syntax-book/images/fractal.png +0 -0
  108. data/test/syntax-book/images/img3-1.png +0 -0
  109. data/test/syntax-book/images/inlineicon.jpg +0 -0
  110. data/test/syntax-book/images/logic.png +0 -0
  111. data/test/syntax-book/images/logic2.png +0 -0
  112. data/test/syntax-book/images/puzzle.jpg +0 -0
  113. data/test/syntax-book/images/table.jpg +0 -0
  114. data/test/syntax-book/part2.re +6 -0
  115. data/test/syntax-book/pre01.re +26 -0
  116. data/test/syntax-book/review-ext.rb +14 -0
  117. data/test/syntax-book/sty/jumoline.sty +310 -0
  118. data/test/syntax-book/sty/reviewmacro.sty +39 -0
  119. data/test/syntax-book/style.css +494 -0
  120. data/test/syntax-book/syntax.dic +2 -0
  121. data/test/test_book.rb +106 -111
  122. data/test/test_book_chapter.rb +21 -22
  123. data/test/test_book_part.rb +3 -5
  124. data/test/test_builder.rb +11 -22
  125. data/test/test_catalog.rb +17 -18
  126. data/test/test_catalog_converter_cmd.rb +5 -5
  127. data/test/test_compiler.rb +18 -16
  128. data/test/test_configure.rb +35 -38
  129. data/test/test_converter.rb +3 -4
  130. data/test/test_epub3maker.rb +136 -117
  131. data/test/test_epubmaker.rb +107 -114
  132. data/test/test_epubmaker_cmd.rb +2 -4
  133. data/test/test_extentions_hash.rb +32 -33
  134. data/test/test_helper.rb +9 -11
  135. data/test/test_htmlbuilder.rb +454 -420
  136. data/test/test_htmltoc.rb +8 -12
  137. data/test/test_htmlutils.rb +0 -2
  138. data/test/test_i18n.rb +159 -150
  139. data/test/test_idgxmlbuilder.rb +190 -197
  140. data/test/test_image_finder.rb +21 -22
  141. data/test/test_index.rb +24 -29
  142. data/test/test_latexbuilder.rb +274 -264
  143. data/test/test_lineinput.rb +7 -10
  144. data/test/test_location.rb +7 -7
  145. data/test/test_makerhelper.rb +13 -25
  146. data/test/test_markdownbuilder.rb +23 -26
  147. data/test/test_md2inaobuilder.rb +8 -11
  148. data/test/test_pdfmaker.rb +114 -123
  149. data/test/test_pdfmaker_cmd.rb +1 -3
  150. data/test/test_review_ext.rb +3 -5
  151. data/test/test_rstbuilder.rb +92 -97
  152. data/test/test_template.rb +3 -7
  153. data/test/test_textutils.rb +27 -27
  154. data/test/test_tocparser.rb +2 -2
  155. data/test/test_topbuilder.rb +98 -103
  156. data/test/test_webtocprinter.rb +5 -6
  157. data/test/test_yamlloader.rb +42 -42
  158. data/test/test_zip_exporter.rb +12 -18
  159. metadata +86 -9
  160. data/lib/review/ewbbuilder.rb +0 -382
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  # This program is free software.
4
2
  # You can distribute or modify this program under the terms of
5
3
  # the GNU LGPL, Lesser General Public License version 2.1.
@@ -11,7 +9,7 @@ module ReVIEW
11
9
 
12
10
  def initialize(book, builder)
13
11
  @book = book
14
- @book.config["builder"] = builder.target_name
12
+ @book.config['builder'] = builder.target_name
15
13
  @compiler = ReVIEW::Compiler.new(builder)
16
14
  end
17
15
 
@@ -19,10 +17,7 @@ module ReVIEW
19
17
  chap_name = File.basename(file, '.*')
20
18
  chap = @book.chapter(chap_name)
21
19
  result = @compiler.compile(chap)
22
- File.open(output_path, 'w') do |f|
23
- f.puts result
24
- end
20
+ File.open(output_path, 'w') { |f| f.puts result }
25
21
  end
26
22
  end
27
23
  end
28
-
@@ -1,7 +1,7 @@
1
1
  # epubbuilder.rb
2
2
  # just for compatibility
3
3
  #
4
- # Copyright (c) 2010 Kenshi Muto
4
+ # Copyright (c) 2010-2017 Kenshi Muto
5
5
  #
6
6
  # This program is free software.
7
7
  # You can distribute or modify this program under the terms of
@@ -11,8 +11,6 @@
11
11
  require 'review/htmlbuilder'
12
12
 
13
13
  module ReVIEW
14
-
15
14
  class EPUBBuilder < HTMLBuilder
16
15
  end
17
-
18
16
  end # module ReVIEW
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  # Copyright (c) 2010-2017 Kenshi Muto and Masayoshi Takahashi
4
2
  #
5
3
  # This program is free software.
@@ -33,110 +31,120 @@ module ReVIEW
33
31
  def initialize
34
32
  @producer = nil
35
33
  @htmltoc = nil
36
- @buildlogtxt = "build-log.txt"
34
+ @buildlogtxt = 'build-log.txt'
35
+ @logger = ReVIEW.logger
36
+ end
37
+
38
+ def error(msg)
39
+ @logger.error "#{File.basename($PROGRAM_NAME, '.*')}: #{msg}"
40
+ exit 1
41
+ end
42
+
43
+ def warn(msg)
44
+ @logger.warn "#{File.basename($PROGRAM_NAME, '.*')}: #{msg}"
37
45
  end
38
46
 
39
47
  def log(s)
40
- puts s if @params["debug"].present?
48
+ puts s if @config['debug'].present?
41
49
  end
42
50
 
43
51
  def load_yaml(yamlfile)
44
52
  loader = ReVIEW::YAMLLoader.new
45
- @params = ReVIEW::Configure.values.deep_merge(loader.load_file(yamlfile))
46
- @producer = Producer.new(@params)
53
+ @config = ReVIEW::Configure.values.deep_merge(loader.load_file(yamlfile))
54
+ @producer = Producer.new(@config)
47
55
  @producer.load(yamlfile)
48
- @params = @producer.params
49
- @params.maker = "epubmaker"
56
+ @config = @producer.config
57
+ @config.maker = 'epubmaker'
50
58
  end
51
59
 
52
60
  def build_path
53
- if @params["debug"]
54
- path = File.expand_path("#{@params["bookname"]}-epub", Dir.pwd)
55
- if File.exist?(path)
56
- FileUtils.rm_rf(path, :secure => true)
57
- end
61
+ if @config['debug']
62
+ path = File.expand_path("#{@config['bookname']}-epub", Dir.pwd)
63
+ FileUtils.rm_rf(path, secure: true) if File.exist?(path)
58
64
  Dir.mkdir(path)
59
- return path
65
+ path
60
66
  else
61
- return Dir.mktmpdir("#{@params["bookname"]}-epub-")
67
+ Dir.mktmpdir("#{@config['bookname']}-epub-")
62
68
  end
63
69
  end
64
70
 
65
- def produce(yamlfile, bookname=nil)
71
+ def produce(yamlfile, bookname = nil)
66
72
  load_yaml(yamlfile)
67
- I18n.setup(@params["language"])
68
- bookname = @params["bookname"] if bookname.nil?
73
+ I18n.setup(@config['language'])
74
+ bookname = @config['bookname'] if bookname.nil?
69
75
  booktmpname = "#{bookname}-epub"
70
76
 
71
77
  begin
72
- @params.check_version(ReVIEW::VERSION)
78
+ @config.check_version(ReVIEW::VERSION)
73
79
  rescue ReVIEW::ConfigError => e
74
80
  warn e.message
75
81
  end
76
82
  log("Loaded yaml file (#{yamlfile}). I will produce #{bookname}.epub.")
77
83
 
78
84
  FileUtils.rm_f("#{bookname}.epub")
79
- FileUtils.rm_rf(booktmpname) if @params["debug"]
85
+ FileUtils.rm_rf(booktmpname) if @config['debug']
86
+ math_dir = "./#{@config['imagedir']}/_review_math"
87
+ FileUtils.rm_rf(math_dir) if @config['imgmath'] && Dir.exist?(math_dir)
80
88
 
81
- basetmpdir = build_path()
89
+ basetmpdir = build_path
82
90
  begin
83
91
  log("Created first temporary directory as #{basetmpdir}.")
84
92
 
85
- call_hook("hook_beforeprocess", basetmpdir)
93
+ call_hook('hook_beforeprocess', basetmpdir)
86
94
 
87
95
  @htmltoc = ReVIEW::HTMLToc.new(basetmpdir)
88
96
  ## copy all files into basetmpdir
89
97
  copy_stylesheet(basetmpdir)
90
98
 
91
99
  copy_frontmatter(basetmpdir)
92
- call_hook("hook_afterfrontmatter", basetmpdir)
100
+ call_hook('hook_afterfrontmatter', basetmpdir)
93
101
 
94
102
  build_body(basetmpdir, yamlfile)
95
- call_hook("hook_afterbody", basetmpdir)
103
+ call_hook('hook_afterbody', basetmpdir)
96
104
 
97
105
  copy_backmatter(basetmpdir)
98
- call_hook("hook_afterbackmatter", basetmpdir)
106
+ call_hook('hook_afterbackmatter', basetmpdir)
99
107
 
100
108
  ## push contents in basetmpdir into @producer
101
109
  push_contents(basetmpdir)
102
110
 
103
- if @params["epubmaker"]["verify_target_images"].present?
111
+ if @config['epubmaker']['verify_target_images'].present?
104
112
  verify_target_images(basetmpdir)
105
- copy_images(@params["imagedir"], basetmpdir)
113
+ copy_images(@config['imagedir'], basetmpdir)
106
114
  else
107
- copy_images(@params["imagedir"], "#{basetmpdir}/#{@params["imagedir"]}")
115
+ copy_images(@config['imagedir'], "#{basetmpdir}/#{@config['imagedir']}")
108
116
  end
109
117
 
110
- copy_resources("covers", "#{basetmpdir}/#{@params["imagedir"]}")
111
- copy_resources("adv", "#{basetmpdir}/#{@params["imagedir"]}")
112
- copy_resources(@params["fontdir"], "#{basetmpdir}/fonts", @params["font_ext"])
118
+ copy_resources('covers', "#{basetmpdir}/#{@config['imagedir']}")
119
+ copy_resources('adv', "#{basetmpdir}/#{@config['imagedir']}")
120
+ copy_resources(@config['fontdir'], "#{basetmpdir}/fonts", @config['font_ext'])
121
+
122
+ call_hook('hook_aftercopyimage', basetmpdir)
113
123
 
114
- call_hook("hook_aftercopyimage", basetmpdir)
124
+ @producer.import_imageinfo("#{basetmpdir}/#{@config['imagedir']}", basetmpdir)
125
+ @producer.import_imageinfo("#{basetmpdir}/fonts", basetmpdir, @config['font_ext'])
115
126
 
116
- @producer.import_imageinfo("#{basetmpdir}/#{@params["imagedir"]}", basetmpdir)
117
- @producer.import_imageinfo("#{basetmpdir}/fonts", basetmpdir, @params["font_ext"])
127
+ check_image_size(basetmpdir, @config['image_maxpixels'], @config['image_ext'])
118
128
 
119
129
  epubtmpdir = nil
120
- if @params["debug"].present?
130
+ if @config['debug'].present?
121
131
  epubtmpdir = "#{basetmpdir}/#{booktmpname}"
122
132
  Dir.mkdir(epubtmpdir)
123
133
  end
124
- log("Call ePUB producer.")
134
+ log('Call ePUB producer.')
125
135
  @producer.produce("#{bookname}.epub", basetmpdir, epubtmpdir)
126
- log("Finished.")
136
+ log('Finished.')
127
137
  ensure
128
- unless @params["debug"]
129
- FileUtils.remove_entry_secure basetmpdir
130
- end
138
+ FileUtils.remove_entry_secure basetmpdir unless @config['debug']
131
139
  end
132
140
  end
133
141
 
134
142
  def call_hook(hook_name, *params)
135
- filename = @params["epubmaker"][hook_name]
143
+ filename = @config['epubmaker'][hook_name]
136
144
  log("Call #{hook_name}. (#{filename})")
137
145
  if filename.present? && File.exist?(filename) && FileTest.executable?(filename)
138
- if ENV["REVIEW_SAFE_MODE"].to_i & 1 > 0
139
- warn "hook is prohibited in safe mode. ignored."
146
+ if ENV['REVIEW_SAFE_MODE'].to_i & 1 > 0
147
+ warn 'hook is prohibited in safe mode. ignored.'
140
148
  else
141
149
  system(filename, *params)
142
150
  end
@@ -145,35 +153,30 @@ module ReVIEW
145
153
 
146
154
  def verify_target_images(basetmpdir)
147
155
  @producer.contents.each do |content|
148
- if content.media == "application/xhtml+xml"
149
-
156
+ if content.media == 'application/xhtml+xml'
150
157
  File.open("#{basetmpdir}/#{content.file}") do |f|
151
- Document.new(File.new(f)).each_element("//img") do |e|
152
- @params["epubmaker"]["force_include_images"].push(e.attributes["src"])
153
- if e.attributes["src"] =~ /svg\Z/i
154
- content.properties.push("svg")
155
- end
158
+ Document.new(File.new(f)).each_element('//img') do |e|
159
+ @config['epubmaker']['force_include_images'].push(e.attributes['src'])
160
+ content.properties.push('svg') if e.attributes['src'] =~ /svg\Z/i
156
161
  end
157
162
  end
158
- elsif content.media == "text/css"
163
+ elsif content.media == 'text/css'
159
164
  File.open("#{basetmpdir}/#{content.file}") do |f|
160
165
  f.each_line do |l|
161
- l.scan(/url\((.+?)\)/) do |m|
162
- @params["epubmaker"]["force_include_images"].push($1.strip)
163
- end
166
+ l.scan(/url\((.+?)\)/) { |_m| @config['epubmaker']['force_include_images'].push($1.strip) }
164
167
  end
165
168
  end
166
169
  end
167
170
  end
168
- @params["epubmaker"]["force_include_images"] = @params["epubmaker"]["force_include_images"].sort.uniq
171
+ @config['epubmaker']['force_include_images'] = @config['epubmaker']['force_include_images'].compact.sort.uniq
169
172
  end
170
173
 
171
- def copy_images(resdir, destdir, allow_exts=nil)
174
+ def copy_images(resdir, destdir, allow_exts = nil)
172
175
  return nil unless File.exist?(resdir)
173
- allow_exts = @params["image_ext"] if allow_exts.nil?
176
+ allow_exts = @config['image_ext'] if allow_exts.nil?
174
177
  FileUtils.mkdir_p(destdir)
175
- if @params["epubmaker"]["verify_target_images"].present?
176
- @params["epubmaker"]["force_include_images"].each do |file|
178
+ if @config['epubmaker']['verify_target_images'].present?
179
+ @config['epubmaker']['force_include_images'].each do |file|
177
180
  unless File.exist?(file)
178
181
  warn "#{file} is not found, skip." if file !~ /\Ahttp[s]?:/
179
182
  next
@@ -188,9 +191,9 @@ module ReVIEW
188
191
  end
189
192
  end
190
193
 
191
- def copy_resources(resdir, destdir, allow_exts=nil)
194
+ def copy_resources(resdir, destdir, allow_exts = nil)
192
195
  return nil unless File.exist?(resdir)
193
- allow_exts = @params["image_ext"] if allow_exts.nil?
196
+ allow_exts = @config['image_ext'] if allow_exts.nil?
194
197
  FileUtils.mkdir_p(destdir)
195
198
  recursive_copy_files(resdir, destdir, allow_exts)
196
199
  end
@@ -201,12 +204,10 @@ module ReVIEW
201
204
  next if fname.start_with?('.')
202
205
  if FileTest.directory?("#{resdir}/#{fname}")
203
206
  recursive_copy_files("#{resdir}/#{fname}", "#{destdir}/#{fname}", allow_exts)
204
- else
205
- if fname =~ /\.(#{allow_exts.join("|")})\Z/i
206
- FileUtils.mkdir_p(destdir)
207
- log("Copy #{resdir}/#{fname} to the temporary directory.")
208
- FileUtils.cp("#{resdir}/#{fname}", destdir)
209
- end
207
+ elsif fname =~ /\.(#{allow_exts.join('|')})\Z/i
208
+ FileUtils.mkdir_p(destdir)
209
+ log("Copy #{resdir}/#{fname} to the temporary directory.")
210
+ FileUtils.cp("#{resdir}/#{fname}", destdir)
210
211
  end
211
212
  end
212
213
  end
@@ -215,7 +216,7 @@ module ReVIEW
215
216
  def check_compile_status
216
217
  return unless @compile_errors
217
218
 
218
- $stderr.puts "compile error, No EPUB file output."
219
+ $stderr.puts 'compile error, No EPUB file output.'
219
220
  exit 1
220
221
  end
221
222
 
@@ -224,28 +225,27 @@ module ReVIEW
224
225
  @bodycount = 0
225
226
  @postcount = 0
226
227
 
227
- @manifeststr = ""
228
- @ncxstr = ""
228
+ @manifeststr = ''
229
+ @ncxstr = ''
229
230
  @tocdesc = []
230
231
 
231
232
  basedir = File.dirname(yamlfile)
232
233
  base_path = Pathname.new(basedir)
233
234
  book = ReVIEW::Book.load(basedir)
234
- book.config = @params
235
+ book.config = @config
235
236
  @converter = ReVIEW::Converter.new(book, ReVIEW::HTMLBuilder.new)
236
237
  @compile_errors = nil
237
238
  book.parts.each do |part|
238
- htmlfile = nil
239
239
  if part.name.present?
240
240
  if part.file?
241
241
  build_chap(part, base_path, basetmpdir, true)
242
242
  else
243
- htmlfile = "part_#{part.number}.#{@params["htmlext"]}"
243
+ htmlfile = "part_#{part.number}.#{@config['htmlext']}"
244
244
  build_part(part, basetmpdir, htmlfile)
245
- title = ReVIEW::I18n.t("part", part.number)
246
- title += ReVIEW::I18n.t("chapter_postfix") + part.name.strip if part.name.strip.present?
247
- @htmltoc.add_item(0, htmlfile, title, {:chaptype => "part"})
248
- write_buildlogtxt(basetmpdir, htmlfile, "")
245
+ title = ReVIEW::I18n.t('part', part.number)
246
+ title += ReVIEW::I18n.t('chapter_postfix') + part.name.strip if part.name.strip.present?
247
+ @htmltoc.add_item(0, htmlfile, title, chaptype: 'part')
248
+ write_buildlogtxt(basetmpdir, htmlfile, '')
249
249
  end
250
250
  end
251
251
 
@@ -253,22 +253,22 @@ module ReVIEW
253
253
  build_chap(chap, base_path, basetmpdir, false)
254
254
  end
255
255
  end
256
- check_compile_status()
256
+ check_compile_status
257
257
  end
258
258
 
259
259
  def build_part(part, basetmpdir, htmlfile)
260
260
  log("Create #{htmlfile} from a template.")
261
- File.open("#{basetmpdir}/#{htmlfile}", "w") do |f|
262
- @body = ""
263
- @body << "<div class=\"part\">\n"
264
- @body << "<h1 class=\"part-number\">#{CGI.escapeHTML(ReVIEW::I18n.t("part", part.number))}</h1>\n"
261
+ File.open("#{basetmpdir}/#{htmlfile}", 'w') do |f|
262
+ @body = ''
263
+ @body << %Q(<div class="part">\n)
264
+ @body << %Q(<h1 class="part-number">#{CGI.escapeHTML(ReVIEW::I18n.t('part', part.number))}</h1>\n)
265
265
  if part.name.strip.present?
266
- @body << "<h2 class=\"part-title\">#{CGI.escapeHTML(part.name.strip)}</h2>\n"
266
+ @body << %Q(<h2 class="part-title">#{CGI.escapeHTML(part.name.strip)}</h2>\n)
267
267
  end
268
- @body << "</div>\n"
268
+ @body << %Q(</div>\n)
269
269
 
270
- @language = @producer.params['language']
271
- @stylesheets = @producer.params["stylesheet"]
270
+ @language = @producer.config['language']
271
+ @stylesheets = @producer.config['stylesheet']
272
272
  tmplfile = File.expand_path(template_name, ReVIEW::Template::TEMPLATE_DIR)
273
273
  tmpl = ReVIEW::Template.load(tmplfile)
274
274
  f.write tmpl.result(binding)
@@ -276,7 +276,7 @@ module ReVIEW
276
276
  end
277
277
 
278
278
  def template_name
279
- if @producer.params["htmlversion"].to_i == 5
279
+ if @producer.config['htmlversion'].to_i == 5
280
280
  './html/layout-html5.html.erb'
281
281
  else
282
282
  './html/layout-xhtml1.html.erb'
@@ -284,45 +284,45 @@ module ReVIEW
284
284
  end
285
285
 
286
286
  def build_chap(chap, base_path, basetmpdir, ispart)
287
- filename = ""
288
-
289
- chaptype = "body"
287
+ chaptype = 'body'
290
288
  if ispart
291
- chaptype = "part"
292
- elsif chap.on_PREDEF?
293
- chaptype = "pre"
294
- elsif chap.on_APPENDIX?
295
- chaptype = "post"
289
+ chaptype = 'part'
290
+ elsif chap.on_predef?
291
+ chaptype = 'pre'
292
+ elsif chap.on_appendix?
293
+ chaptype = 'post'
296
294
  end
297
295
 
298
- if ispart.present?
299
- filename = chap.path
300
- else
301
- filename = Pathname.new(chap.path).relative_path_from(base_path).to_s
302
- end
303
- id = filename.sub(/\.re\Z/, "")
296
+ filename =
297
+ if ispart.present?
298
+ chap.path
299
+ else
300
+ Pathname.new(chap.path).relative_path_from(base_path).to_s
301
+ end
304
302
 
305
- if @params["epubmaker"]["rename_for_legacy"] && ispart.nil?
306
- if chap.on_PREDEF?
303
+ id = filename.sub(/\.re\Z/, '')
304
+
305
+ if @config['epubmaker']['rename_for_legacy'] && ispart.nil?
306
+ if chap.on_predef?
307
307
  @precount += 1
308
- id = sprintf("pre%02d", @precount)
309
- elsif chap.on_APPENDIX?
308
+ id = sprintf('pre%02d', @precount)
309
+ elsif chap.on_appendix?
310
310
  @postcount += 1
311
- id = sprintf("post%02d", @postcount)
311
+ id = sprintf('post%02d', @postcount)
312
312
  else
313
313
  @bodycount += 1
314
- id = sprintf("chap%02d", @bodycount)
314
+ id = sprintf('chap%02d', @bodycount)
315
315
  end
316
316
  end
317
317
 
318
- htmlfile = "#{id}.#{@params["htmlext"]}"
318
+ htmlfile = "#{id}.#{@config['htmlext']}"
319
319
  write_buildlogtxt(basetmpdir, htmlfile, filename)
320
320
  log("Create #{htmlfile} from #{filename}.")
321
321
 
322
- if @params["params"].present?
323
- warn "'params:' in config.yml is obsoleted."
324
- if @params["params"] =~ /stylesheet=/
325
- warn "stylesheets should be defined in 'stylesheet:', not in 'params:'"
322
+ if @config['params'].present?
323
+ warn %Q('params:' in config.yml is obsoleted.)
324
+ if @config['params'] =~ /stylesheet=/
325
+ warn %Q(stylesheets should be defined in 'stylesheet:', not in 'params:')
326
326
  end
327
327
  end
328
328
  begin
@@ -337,10 +337,10 @@ module ReVIEW
337
337
  end
338
338
 
339
339
  def remove_hidden_title(basetmpdir, htmlfile)
340
- File.open("#{basetmpdir}/#{htmlfile}", "r+") do |f|
340
+ File.open("#{basetmpdir}/#{htmlfile}", 'r+') do |f|
341
341
  body = f.read.
342
- gsub(/<h\d .*?hidden=['"]true['"].*?>.*?<\/h\d>\n/, '').
343
- gsub(/(<h\d .*?)\s*notoc=['"]true['"]\s*(.*?>.*?<\/h\d>\n)/, '\1\2')
342
+ gsub(%r{<h\d .*?hidden=['"]true['"].*?>.*?</h\d>\n}, '').
343
+ gsub(%r{(<h\d .*?)\s*notoc=['"]true['"]\s*(.*?>.*?</h\d>\n)}, '\1\2')
344
344
  f.rewind
345
345
  f.print body
346
346
  f.truncate(f.tell)
@@ -351,108 +351,95 @@ module ReVIEW
351
351
  properties = []
352
352
  File.open(path) do |f|
353
353
  doc = REXML::Document.new(f)
354
- if REXML::XPath.first(doc, "//m:math", {'m' => 'http://www.w3.org/1998/Math/MathML'})
355
- properties<< "mathml"
354
+ if REXML::XPath.first(doc, '//m:math', 'm' => 'http://www.w3.org/1998/Math/MathML')
355
+ properties << 'mathml'
356
356
  end
357
- if REXML::XPath.first(doc, "//s:svg", {'s' => 'http://www.w3.org/2000/svg'})
358
- properties<< "svg"
357
+ if REXML::XPath.first(doc, '//s:svg', 's' => 'http://www.w3.org/2000/svg')
358
+ properties << 'svg'
359
359
  end
360
360
  end
361
361
  properties
362
362
  end
363
363
 
364
- def write_info_body(basetmpdir, id, filename, ispart=nil, chaptype=nil)
364
+ def write_info_body(basetmpdir, _id, filename, ispart = nil, chaptype = nil)
365
365
  headlines = []
366
366
  path = File.join(basetmpdir, filename)
367
367
  Document.parse_stream(File.new(path), ReVIEWHeaderListener.new(headlines))
368
368
  properties = detect_properties(path)
369
- prop_str = ""
370
- if properties.present?
371
- prop_str = ",properties="+properties.join(" ")
372
- end
369
+ prop_str = ''
370
+ prop_str = ',properties=' + properties.join(' ') if properties.present?
373
371
  first = true
374
372
  headlines.each do |headline|
375
- headline["level"] = 0 if ispart.present? && headline["level"] == 1
373
+ headline['level'] = 0 if ispart.present? && headline['level'] == 1
376
374
  if first.nil?
377
- @htmltoc.add_item(headline["level"], filename+"#"+headline["id"], headline["title"], {:chaptype => chaptype, :notoc => headline["notoc"]})
375
+ @htmltoc.add_item(headline['level'], filename + '#' + headline['id'], headline['title'], { chaptype: chaptype, notoc: headline['notoc'] })
378
376
  else
379
- @htmltoc.add_item(headline["level"], filename, headline["title"], {:force_include => true, :chaptype => chaptype+prop_str, :notoc => headline["notoc"]})
377
+ @htmltoc.add_item(headline['level'], filename, headline['title'], { force_include: true, chaptype: chaptype + prop_str, notoc: headline['notoc'] })
380
378
  first = nil
381
379
  end
382
380
  end
383
381
  end
384
382
 
385
- def push_contents(basetmpdir)
383
+ def push_contents(_basetmpdir)
386
384
  @htmltoc.each_item do |level, file, title, args|
387
- next if level.to_i > @params["toclevel"] && args[:force_include].nil?
385
+ next if level.to_i > @config['toclevel'] && args[:force_include].nil?
388
386
  log("Push #{file} to ePUB contents.")
389
387
 
390
- hash = {"file" => file, "level" => level.to_i, "title" => title, "chaptype" => args[:chaptype]}
391
- if args[:id].present?
392
- hash["id"] = args[:id]
393
- end
394
- if args[:properties].present?
395
- hash["properties"] = args[:properties].split(" ")
396
- end
397
- if args[:notoc].present?
398
- hash["notoc"] = args[:notoc]
399
- end
388
+ hash = { 'file' => file, 'level' => level.to_i, 'title' => title, 'chaptype' => args[:chaptype] }
389
+ hash['id'] = args[:id] if args[:id].present?
390
+ hash['properties'] = args[:properties].split(' ') if args[:properties].present?
391
+ hash['notoc'] = args[:notoc] if args[:notoc].present?
400
392
  @producer.contents.push(Content.new(hash))
401
393
  end
402
394
  end
403
395
 
404
396
  def copy_stylesheet(basetmpdir)
405
- if @params["stylesheet"].size > 0
406
- @params["stylesheet"].each do |sfile|
407
- FileUtils.cp(sfile, basetmpdir)
408
- @producer.contents.push(Content.new("file" => sfile))
409
- end
397
+ return if @config['stylesheet'].empty?
398
+ @config['stylesheet'].each do |sfile|
399
+ FileUtils.cp(sfile, basetmpdir)
400
+ @producer.contents.push(Content.new('file' => sfile))
410
401
  end
411
402
  end
412
403
 
413
404
  def copy_frontmatter(basetmpdir)
414
- FileUtils.cp(@params["cover"], "#{basetmpdir}/#{File.basename(@params["cover"])}") if @params["cover"].present? && File.exist?(@params["cover"])
405
+ FileUtils.cp(@config['cover'], "#{basetmpdir}/#{File.basename(@config['cover'])}") if @config['cover'].present? && File.exist?(@config['cover'])
415
406
 
416
- if @params["titlepage"]
417
- if @params["titlefile"].nil?
418
- build_titlepage(basetmpdir, "titlepage.#{@params["htmlext"]}")
407
+ if @config['titlepage']
408
+ if @config['titlefile'].nil?
409
+ build_titlepage(basetmpdir, "titlepage.#{@config['htmlext']}")
419
410
  else
420
- FileUtils.cp(@params["titlefile"], "#{basetmpdir}/titlepage.#{@params["htmlext"]}")
411
+ FileUtils.cp(@config['titlefile'], "#{basetmpdir}/titlepage.#{@config['htmlext']}")
421
412
  end
422
- @htmltoc.add_item(1, "titlepage.#{@params['htmlext']}", @producer.res.v("titlepagetitle"), {:chaptype => "pre"})
413
+ @htmltoc.add_item(1, "titlepage.#{@config['htmlext']}", @producer.res.v('titlepagetitle'), chaptype: 'pre')
423
414
  end
424
415
 
425
- if @params["originaltitlefile"].present? && File.exist?(@params["originaltitlefile"])
426
- FileUtils.cp(@params["originaltitlefile"], "#{basetmpdir}/#{File.basename(@params["originaltitlefile"])}")
427
- @htmltoc.add_item(1, File.basename(@params["originaltitlefile"]), @producer.res.v("originaltitle"), {:chaptype => "pre"})
416
+ if @config['originaltitlefile'].present? && File.exist?(@config['originaltitlefile'])
417
+ FileUtils.cp(@config['originaltitlefile'], "#{basetmpdir}/#{File.basename(@config['originaltitlefile'])}")
418
+ @htmltoc.add_item(1, File.basename(@config['originaltitlefile']), @producer.res.v('originaltitle'), chaptype: 'pre')
428
419
  end
429
420
 
430
- if @params["creditfile"].present? && File.exist?(@params["creditfile"])
431
- FileUtils.cp(@params["creditfile"], "#{basetmpdir}/#{File.basename(@params["creditfile"])}")
432
- @htmltoc.add_item(1, File.basename(@params["creditfile"]), @producer.res.v("credittitle"), {:chaptype => "pre"})
421
+ if @config['creditfile'].present? && File.exist?(@config['creditfile'])
422
+ FileUtils.cp(@config['creditfile'], "#{basetmpdir}/#{File.basename(@config['creditfile'])}")
423
+ @htmltoc.add_item(1, File.basename(@config['creditfile']), @producer.res.v('credittitle'), chaptype: 'pre')
433
424
  end
425
+
426
+ true
434
427
  end
435
428
 
436
429
  def build_titlepage(basetmpdir, htmlfile)
437
430
  # TODO: should be created via epubcommon
438
- @title = CGI.escapeHTML(@params.name_of("booktitle"))
439
- File.open("#{basetmpdir}/#{htmlfile}", "w") do |f|
440
- @body = ""
441
- @body << "<div class=\"titlepage\">\n"
442
- @body << "<h1 class=\"tp-title\">#{CGI.escapeHTML(@params.name_of("booktitle"))}</h1>\n"
443
- if @params["subtitle"]
444
- @body << "<h2 class=\"tp-subtitle\">#{CGI.escapeHTML(@params.name_of("subtitle"))}</h2>\n"
445
- end
446
- if @params["aut"]
447
- @body << "<h2 class=\"tp-author\">#{CGI.escapeHTML(@params.names_of("aut").join(ReVIEW::I18n.t("names_splitter")))}</h2>\n"
448
- end
449
- if @params["prt"]
450
- @body << "<h3 class=\"tp-publisher\">#{CGI.escapeHTML(@params.names_of("prt").join(ReVIEW::I18n.t("names_splitter")))}</h3>\n"
451
- end
452
- @body << "</div>"
453
-
454
- @language = @producer.params['language']
455
- @stylesheets = @producer.params["stylesheet"]
431
+ @title = CGI.escapeHTML(@config.name_of('booktitle'))
432
+ File.open("#{basetmpdir}/#{htmlfile}", 'w') do |f|
433
+ @body = ''
434
+ @body << %Q(<div class="titlepage">\n)
435
+ @body << %Q(<h1 class="tp-title">#{CGI.escapeHTML(@config.name_of('booktitle'))}</h1>\n)
436
+ @body << %Q(<h2 class="tp-subtitle">#{CGI.escapeHTML(@config.name_of('subtitle'))}</h2>\n) if @config['subtitle']
437
+ @body << %Q(<h2 class="tp-author">#{CGI.escapeHTML(@config.names_of('aut').join(ReVIEW::I18n.t('names_splitter')))}</h2>\n) if @config['aut']
438
+ @body << %Q(<h3 class="tp-publisher">#{CGI.escapeHTML(@config.names_of('prt').join(ReVIEW::I18n.t('names_splitter')))}</h3>\n) if @config['prt']
439
+ @body << '</div>'
440
+
441
+ @language = @producer.config['language']
442
+ @stylesheets = @producer.config['stylesheet']
456
443
  tmplfile = File.expand_path(template_name, ReVIEW::Template::TEMPLATE_DIR)
457
444
  tmpl = ReVIEW::Template.load(tmplfile)
458
445
  f.write tmpl.result(binding)
@@ -460,76 +447,97 @@ module ReVIEW
460
447
  end
461
448
 
462
449
  def copy_backmatter(basetmpdir)
463
- if @params["profile"]
464
- FileUtils.cp(@params["profile"], "#{basetmpdir}/#{File.basename(@params["profile"])}")
465
- @htmltoc.add_item(1, File.basename(@params["profile"]), @producer.res.v("profiletitle"), {:chaptype => "post"})
450
+ if @config['profile']
451
+ FileUtils.cp(@config['profile'], "#{basetmpdir}/#{File.basename(@config['profile'])}")
452
+ @htmltoc.add_item(1, File.basename(@config['profile']), @producer.res.v('profiletitle'), chaptype: 'post')
466
453
  end
467
454
 
468
- if @params["advfile"]
469
- FileUtils.cp(@params["advfile"], "#{basetmpdir}/#{File.basename(@params["advfile"])}")
470
- @htmltoc.add_item(1, File.basename(@params["advfile"]), @producer.res.v("advtitle"), {:chaptype => "post"})
455
+ if @config['advfile']
456
+ FileUtils.cp(@config['advfile'], "#{basetmpdir}/#{File.basename(@config['advfile'])}")
457
+ @htmltoc.add_item(1, File.basename(@config['advfile']), @producer.res.v('advtitle'), chaptype: 'post')
471
458
  end
472
459
 
473
- if @params["colophon"]
474
- if @params["colophon"].kind_of?(String) # FIXME: このやり方はやめる?
475
- FileUtils.cp(@params["colophon"], "#{basetmpdir}/colophon.#{@params["htmlext"]}")
460
+ if @config['colophon']
461
+ if @config['colophon'].is_a?(String) # FIXME: should let obsolete this style?
462
+ FileUtils.cp(@config['colophon'], "#{basetmpdir}/colophon.#{@config['htmlext']}")
476
463
  else
477
- File.open("#{basetmpdir}/colophon.#{@params["htmlext"]}", "w") {|f| @producer.colophon(f) }
464
+ File.open("#{basetmpdir}/colophon.#{@config['htmlext']}", 'w') { |f| @producer.colophon(f) }
478
465
  end
479
- @htmltoc.add_item(1, "colophon.#{@params["htmlext"]}", @producer.res.v("colophontitle"), {:chaptype => "post"})
466
+ @htmltoc.add_item(1, "colophon.#{@config['htmlext']}", @producer.res.v('colophontitle'), chaptype: 'post')
480
467
  end
481
468
 
482
- if @params["backcover"]
483
- FileUtils.cp(@params["backcover"], "#{basetmpdir}/#{File.basename(@params["backcover"])}")
484
- @htmltoc.add_item(1, File.basename(@params["backcover"]), @producer.res.v("backcovertitle"), {:chaptype => "post"})
469
+ if @config['backcover']
470
+ FileUtils.cp(@config['backcover'], "#{basetmpdir}/#{File.basename(@config['backcover'])}")
471
+ @htmltoc.add_item(1, File.basename(@config['backcover']), @producer.res.v('backcovertitle'), chaptype: 'post')
485
472
  end
473
+
474
+ true
486
475
  end
487
476
 
488
477
  def write_buildlogtxt(basetmpdir, htmlfile, reviewfile)
489
- File.open("#{basetmpdir}/#{@buildlogtxt}", "a") do |f|
490
- f.puts "#{htmlfile},#{reviewfile}"
478
+ File.open("#{basetmpdir}/#{@buildlogtxt}", 'a') { |f| f.puts "#{htmlfile},#{reviewfile}" }
479
+ end
480
+
481
+ def check_image_size(basetmpdir, maxpixels, allow_exts = nil)
482
+ begin
483
+ require 'image_size'
484
+ rescue LoadError
485
+ return nil
486
+ end
487
+ require 'find'
488
+ allow_exts ||= @config['image_ext']
489
+
490
+ extre = Regexp.new('\\.(' + allow_exts.delete_if { |t| %w[ttf woff otf].include?(t) }.join('|') + ')', Regexp::IGNORECASE)
491
+ Find.find(basetmpdir) do |fname|
492
+ next unless fname.match(extre)
493
+ img = ImageSize.path(fname)
494
+ next if img.width.nil? || img.width * img.height <= maxpixels
495
+ h = Math.sqrt(img.height * maxpixels / img.width)
496
+ w = maxpixels / h
497
+ fname.sub!("#{basetmpdir}/", '')
498
+ warn "#{fname}: #{img.width}x#{img.height} exceeds a limit. suggeted value is #{w.to_i}x#{h.to_i}"
491
499
  end
500
+
501
+ true
492
502
  end
493
503
 
494
504
  class ReVIEWHeaderListener
495
505
  include REXML::StreamListener
496
506
  def initialize(headlines)
497
507
  @level = nil
498
- @content = ""
508
+ @content = ''
499
509
  @headlines = headlines
500
510
  end
501
511
 
502
512
  def tag_start(name, attrs)
503
513
  if name =~ /\Ah(\d+)/
504
- if @level.present?
505
- raise "#{name}, #{attrs}"
506
- end
514
+ raise "#{name}, #{attrs}" if @level.present?
507
515
  @level = $1.to_i
508
- @id = attrs["id"] if attrs["id"].present?
509
- @notoc = attrs["notoc"] if attrs["notoc"].present?
516
+ @id = attrs['id'] if attrs['id'].present?
517
+ @notoc = attrs['notoc'] if attrs['notoc'].present?
510
518
  elsif !@level.nil?
511
- if name == "img" && attrs["alt"].present?
512
- @content << attrs["alt"]
513
- elsif name == "a" && attrs["id"].present?
514
- @id = attrs["id"]
519
+ if name == 'img' && attrs['alt'].present?
520
+ @content << attrs['alt']
521
+ elsif name == 'a' && attrs['id'].present?
522
+ @id = attrs['id']
515
523
  end
516
524
  end
517
525
  end
518
526
 
519
527
  def tag_end(name)
520
528
  if name =~ /\Ah\d+/
521
- @headlines.push({"level" => @level, "id" => @id, "title" => @content, "notoc" => @notoc}) if @id.present?
522
- @content = ""
529
+ @headlines.push({ 'level' => @level, 'id' => @id, 'title' => @content, 'notoc' => @notoc }) if @id.present?
530
+ @content = ''
523
531
  @level = nil
524
532
  @id = nil
525
533
  @notoc = nil
526
534
  end
535
+
536
+ true
527
537
  end
528
538
 
529
539
  def text(text)
530
- if @level.present?
531
- @content << text.gsub("\t", " ") # FIXME: 区切り文字
532
- end
540
+ @content << text.gsub("\t", ' ') if @level.present?
533
541
  end
534
542
  end
535
543
  end