review 2.3.0 → 2.4.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 (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