review 4.2.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-win.yml +11 -5
  3. data/.rubocop.yml +113 -24
  4. data/NEWS.ja.md +94 -0
  5. data/NEWS.md +94 -0
  6. data/bin/review-catalog-converter +1 -1
  7. data/bin/review-check +2 -4
  8. data/bin/review-checkdep +1 -1
  9. data/bin/review-compile +8 -14
  10. data/bin/review-validate +1 -1
  11. data/doc/config.yml.sample +4 -1
  12. data/doc/config.yml.sample-simple +1 -1
  13. data/doc/format.ja.md +83 -4
  14. data/doc/format.md +84 -7
  15. data/doc/makeindex.ja.md +2 -2
  16. data/doc/quickstart.ja.md +3 -3
  17. data/doc/quickstart.md +2 -2
  18. data/lib/epubmaker/content.rb +3 -2
  19. data/lib/epubmaker/epubcommon.rb +33 -25
  20. data/lib/epubmaker/epubv2.rb +5 -6
  21. data/lib/epubmaker/epubv3.rb +20 -18
  22. data/lib/review/book.rb +2 -2
  23. data/lib/review/book/base.rb +61 -25
  24. data/lib/review/book/bib.rb +21 -0
  25. data/lib/review/book/book_unit.rb +155 -0
  26. data/lib/review/book/chapter.rb +30 -26
  27. data/lib/review/book/index.rb +23 -185
  28. data/lib/review/book/index/item.rb +7 -1
  29. data/lib/review/book/part.rb +21 -9
  30. data/lib/review/book/volume.rb +1 -1
  31. data/lib/review/builder.rb +68 -13
  32. data/lib/review/catalog.rb +2 -2
  33. data/lib/review/compiler.rb +159 -73
  34. data/lib/review/configure.rb +22 -1
  35. data/lib/review/converter.rb +1 -1
  36. data/lib/review/epub2html.rb +6 -1
  37. data/lib/review/epubmaker.rb +12 -23
  38. data/lib/review/htmlbuilder.rb +36 -7
  39. data/lib/review/htmlutils.rb +7 -10
  40. data/lib/review/i18n.rb +1 -1
  41. data/lib/review/idgxmlbuilder.rb +51 -6
  42. data/lib/review/idgxmlmaker.rb +9 -14
  43. data/lib/review/index_builder.rb +653 -0
  44. data/lib/review/init.rb +5 -13
  45. data/lib/review/latexbuilder.rb +65 -4
  46. data/lib/review/logger.rb +2 -2
  47. data/lib/review/makerhelper.rb +11 -0
  48. data/lib/review/markdownbuilder.rb +19 -1
  49. data/lib/review/pdfmaker.rb +17 -36
  50. data/lib/review/plaintextbuilder.rb +48 -2
  51. data/lib/review/preprocessor.rb +5 -5
  52. data/lib/review/rstbuilder.rb +25 -6
  53. data/lib/review/sec_counter.rb +13 -0
  54. data/lib/review/textmaker.rb +4 -12
  55. data/lib/review/tocprinter.rb +2 -3
  56. data/lib/review/topbuilder.rb +26 -0
  57. data/lib/review/update.rb +7 -7
  58. data/lib/review/version.rb +1 -1
  59. data/lib/review/volumeprinter.rb +2 -3
  60. data/lib/review/webmaker.rb +9 -20
  61. data/review.gemspec +2 -2
  62. data/samples/sample-book/src/config.yml +1 -1
  63. data/samples/syntax-book/Gemfile +1 -1
  64. data/samples/syntax-book/config.yml +1 -1
  65. data/templates/latex/config.erb +27 -23
  66. data/templates/latex/review-jlreq/README.md +3 -1
  67. data/templates/latex/review-jlreq/review-base.sty +31 -15
  68. data/templates/latex/review-jlreq/review-jlreq.cls +8 -24
  69. data/templates/latex/review-jsbook/README.md +7 -5
  70. data/templates/latex/review-jsbook/review-base.sty +34 -16
  71. data/templates/latex/review-jsbook/review-jsbook.cls +4 -2
  72. data/templates/web/html/layout-html5.html.erb +1 -1
  73. data/test/assets/test_template.tex +3 -3
  74. data/test/assets/test_template_backmatter.tex +3 -3
  75. data/test/book_test_helper.rb +11 -5
  76. data/test/test_book.rb +54 -63
  77. data/test/test_book_chapter.rb +93 -52
  78. data/test/test_builder.rb +24 -15
  79. data/test/test_converter.rb +1 -0
  80. data/test/test_epub3maker.rb +2 -2
  81. data/test/test_epubmaker.rb +8 -0
  82. data/test/test_helper.rb +4 -1
  83. data/test/test_htmlbuilder.rb +627 -56
  84. data/test/test_htmlutils.rb +0 -12
  85. data/test/test_i18n.rb +33 -33
  86. data/test/test_idgxmlbuilder.rb +358 -11
  87. data/test/test_idgxmlmaker_cmd.rb +1 -1
  88. data/test/test_index.rb +62 -52
  89. data/test/test_indexbuilder.rb +52 -0
  90. data/test/test_latexbuilder.rb +547 -10
  91. data/test/test_latexbuilder_v2.rb +43 -5
  92. data/test/test_logger.rb +7 -7
  93. data/test/test_makerhelper.rb +0 -12
  94. data/test/test_markdownbuilder.rb +3 -0
  95. data/test/test_pdfmaker.rb +13 -12
  96. data/test/test_pdfmaker_cmd.rb +1 -1
  97. data/test/test_plaintextbuilder.rb +422 -7
  98. data/test/test_review_ext.rb +2 -1
  99. data/test/test_rstbuilder.rb +25 -1
  100. data/test/test_sec_counter.rb +156 -0
  101. data/test/test_textmaker_cmd.rb +1 -1
  102. data/test/test_topbuilder.rb +187 -10
  103. data/test/test_update.rb +10 -10
  104. data/test/test_webtocprinter.rb +12 -12
  105. data/vendor/gentombow/LICENSE +1 -1
  106. data/vendor/gentombow/Makefile +0 -1
  107. data/vendor/gentombow/bounddvi-en.pdf +0 -0
  108. data/vendor/gentombow/bounddvi-en.tex +1 -0
  109. data/vendor/gentombow/bounddvi.pdf +0 -0
  110. data/vendor/gentombow/bounddvi.sty +30 -7
  111. data/vendor/gentombow/bounddvi.tex +1 -0
  112. data/vendor/gentombow/create_archive.sh +1 -0
  113. data/vendor/gentombow/gentombow-ja.pdf +0 -0
  114. data/vendor/gentombow/gentombow-ja.tex +9 -0
  115. data/vendor/gentombow/gentombow.pdf +0 -0
  116. data/vendor/gentombow/gentombow.sty +32 -10
  117. data/vendor/gentombow/gentombow.tex +8 -0
  118. data/vendor/gentombow/tests/gentombow-01-pdfx.tex +8 -0
  119. data/vendor/gentombow/tests/gentombow-02-pdfx.tex +8 -0
  120. data/vendor/jsclasses/Makefile +3 -2
  121. data/vendor/jsclasses/create_archive.sh +5 -5
  122. data/vendor/jsclasses/jis/Makefile +3 -2
  123. data/vendor/jsclasses/jis/jsarticle.cls +22 -18
  124. data/vendor/jsclasses/jis/jsbook.cls +22 -18
  125. data/vendor/jsclasses/jis/jsclasses.dtx +94 -13
  126. data/vendor/jsclasses/jis/jsclasses.ins +15 -5
  127. data/vendor/jsclasses/jis/jslogo.ins +9 -0
  128. data/vendor/jsclasses/jis/jslogo.sty +1 -13
  129. data/vendor/jsclasses/jis/jspf.cls +22 -18
  130. data/vendor/jsclasses/jis/jsreport.cls +22 -18
  131. data/vendor/jsclasses/jis/jsverb.ins +9 -0
  132. data/vendor/jsclasses/jis/jsverb.sty +1 -13
  133. data/vendor/jsclasses/jis/kiyou.cls +22 -18
  134. data/vendor/jsclasses/jis/minijs.sty +65 -22
  135. data/vendor/jsclasses/jis/okumacro.ins +9 -0
  136. data/vendor/jsclasses/jis/okumacro.sty +1 -13
  137. data/vendor/jsclasses/jis/okuverb.ins +9 -0
  138. data/vendor/jsclasses/jis/okuverb.sty +1 -13
  139. data/vendor/jsclasses/jis/winjis.sty +23 -19
  140. data/vendor/jsclasses/jsarticle.cls +22 -18
  141. data/vendor/jsclasses/jsbook.cls +22 -18
  142. data/vendor/jsclasses/jsclasses.dtx +94 -13
  143. data/vendor/jsclasses/jsclasses.ins +15 -5
  144. data/vendor/jsclasses/jsclasses.pdf +0 -0
  145. data/vendor/jsclasses/jslogo.ins +9 -0
  146. data/vendor/jsclasses/jslogo.pdf +0 -0
  147. data/vendor/jsclasses/jslogo.sty +1 -13
  148. data/vendor/jsclasses/jspf.cls +22 -18
  149. data/vendor/jsclasses/jsreport.cls +22 -18
  150. data/vendor/jsclasses/jsverb.ins +9 -0
  151. data/vendor/jsclasses/jsverb.pdf +0 -0
  152. data/vendor/jsclasses/jsverb.sty +1 -13
  153. data/vendor/jsclasses/kiyou.cls +22 -18
  154. data/vendor/jsclasses/minijs.sty +68 -22
  155. data/vendor/jsclasses/okumacro.ins +9 -0
  156. data/vendor/jsclasses/okumacro.pdf +0 -0
  157. data/vendor/jsclasses/okumacro.sty +1 -13
  158. data/vendor/jsclasses/okuverb.ins +9 -0
  159. data/vendor/jsclasses/okuverb.pdf +0 -0
  160. data/vendor/jsclasses/okuverb.sty +1 -13
  161. data/vendor/jsclasses/tests/relfont.tex +10 -0
  162. data/vendor/jsclasses/winjis.sty +23 -19
  163. metadata +14 -6
  164. data/.rubocop_todo.yml +0 -7
  165. data/lib/review/book/compilable.rb +0 -174
@@ -10,7 +10,11 @@
10
10
 
11
11
  require 'review/i18n'
12
12
  require 'review/template'
13
- require 'cgi'
13
+ begin
14
+ require 'cgi/escape'
15
+ rescue LoadError
16
+ require 'cgi/util'
17
+ end
14
18
 
15
19
  module EPUBMaker
16
20
  # EPUBCommon is the common class for EPUB producer.
@@ -22,6 +26,10 @@ module EPUBMaker
22
26
  @body_ext = nil
23
27
  end
24
28
 
29
+ def h(str)
30
+ CGI.escapeHTML(str)
31
+ end
32
+
25
33
  # Return mimetype content.
26
34
  def mimetype
27
35
  'application/epub+zip'
@@ -59,10 +67,10 @@ module EPUBMaker
59
67
  def ncx_doctitle
60
68
  <<EOT
61
69
  <docTitle>
62
- <text>#{CGI.escapeHTML(@producer.config['title'])}</text>
70
+ <text>#{h(@producer.config['title'])}</text>
63
71
  </docTitle>
64
72
  <docAuthor>
65
- <text>#{@producer.config['aut'].nil? ? '' : CGI.escapeHTML(join_with_separator(@producer.config['aut'], ReVIEW::I18n.t('names_splitter')))}</text>
73
+ <text>#{@producer.config['aut'].nil? ? '' : h(join_with_separator(@producer.config['aut'], ReVIEW::I18n.t('names_splitter')))}</text>
66
74
  </docAuthor>
67
75
  EOT
68
76
  end
@@ -72,7 +80,7 @@ EOT
72
80
  <navMap>
73
81
  <navPoint id="top" playOrder="1">
74
82
  <navLabel>
75
- <text>#{CGI.escapeHTML(@producer.config['title'])}</text>
83
+ <text>#{h(@producer.config['title'])}</text>
76
84
  </navLabel>
77
85
  <content src="#{@producer.config['cover']}"/>
78
86
  </navPoint>
@@ -84,7 +92,7 @@ EOT
84
92
  s << <<EOT
85
93
  <navPoint id="toc" playOrder="#{nav_count}">
86
94
  <navLabel>
87
- <text>#{CGI.escapeHTML(@producer.res.v('toctitle'))}</text>
95
+ <text>#{h(@producer.res.v('toctitle'))}</text>
88
96
  </navLabel>
89
97
  <content src="#{@producer.config['bookname']}-toc.#{@producer.config['htmlext']}"/>
90
98
  </navPoint>
@@ -100,7 +108,7 @@ EOT
100
108
  s << <<EOT
101
109
  <navPoint id="nav-#{nav_count}" playOrder="#{nav_count}">
102
110
  <navLabel>
103
- <text>#{indent[level]}#{CGI.escapeHTML(item.title)}</text>
111
+ <text>#{indent[level]}#{h(item.title)}</text>
104
112
  </navLabel>
105
113
  <content src="#{item.file}"/>
106
114
  </navPoint>
@@ -131,21 +139,21 @@ EOT
131
139
  raise "coverimage #{@producer.config['coverimage']} not found. Abort." unless file
132
140
  @body = <<-EOT
133
141
  <div id="cover-image" class="cover-image">
134
- <img src="#{file}" alt="#{CGI.escapeHTML(@producer.config.name_of('title'))}" class="max"/>
142
+ <img src="#{file}" alt="#{h(@producer.config.name_of('title'))}" class="max"/>
135
143
  </div>
136
144
  EOT
137
145
  else
138
146
  @body = <<-EOT
139
- <h1 class="cover-title">#{CGI.escapeHTML(@producer.config.name_of('title'))}</h1>
147
+ <h1 class="cover-title">#{h(@producer.config.name_of('title'))}</h1>
140
148
  EOT
141
149
  if @producer.config['subtitle']
142
150
  @body << <<-EOT
143
- <h2 class="cover-subtitle">#{CGI.escapeHTML(@producer.config.name_of('subtitle'))}</h2>
151
+ <h2 class="cover-subtitle">#{h(@producer.config.name_of('subtitle'))}</h2>
144
152
  EOT
145
153
  end
146
154
  end
147
155
 
148
- @title = CGI.escapeHTML(@producer.config.name_of('title'))
156
+ @title = h(@producer.config.name_of('title'))
149
157
  @language = @producer.config['language']
150
158
  @stylesheets = @producer.config['stylesheet']
151
159
  tmplfile = if @producer.config['htmlversion'].to_i == 5
@@ -161,7 +169,7 @@ EOT
161
169
  # NOTE: this method is not used yet.
162
170
  # see lib/review/epubmaker.rb#build_titlepage
163
171
  def titlepage
164
- @title = CGI.escapeHTML(@producer.config.name_of('title'))
172
+ @title = h(@producer.config.name_of('title'))
165
173
 
166
174
  @body = <<EOT
167
175
  <h1 class="tp-title">#{@title}</h1>
@@ -169,7 +177,7 @@ EOT
169
177
 
170
178
  if @producer.config['subtitle']
171
179
  @body << <<EOT
172
- <h2 class="tp-subtitle">#{CGI.escapeHTML(@producer.config.name_of('subtitle'))}</h2>
180
+ <h2 class="tp-subtitle">#{h(@producer.config.name_of('subtitle'))}</h2>
173
181
  EOT
174
182
  end
175
183
 
@@ -179,7 +187,7 @@ EOT
179
187
  <br />
180
188
  <br />
181
189
  </p>
182
- <h2 class="tp-author">#{CGI.escapeHTML(join_with_separator(@producer.config.names_of('aut'), ReVIEW::I18n.t('names_splitter')))}</h2>
190
+ <h2 class="tp-author">#{h(join_with_separator(@producer.config.names_of('aut'), ReVIEW::I18n.t('names_splitter')))}</h2>
183
191
  EOT
184
192
  end
185
193
 
@@ -192,7 +200,7 @@ EOT
192
200
  <br />
193
201
  <br />
194
202
  </p>
195
- <h3 class="tp-publisher">#{CGI.escapeHTML(join_with_separator(publisher, ReVIEW::I18n.t('names_splitter')))}</h3>
203
+ <h3 class="tp-publisher">#{h(join_with_separator(publisher, ReVIEW::I18n.t('names_splitter')))}</h3>
196
204
  EOT
197
205
  end
198
206
 
@@ -209,18 +217,18 @@ EOT
209
217
 
210
218
  # Return colophon content.
211
219
  def colophon
212
- @title = CGI.escapeHTML(@producer.res.v('colophontitle'))
220
+ @title = h(@producer.res.v('colophontitle'))
213
221
  @body = <<EOT
214
222
  <div class="colophon">
215
223
  EOT
216
224
 
217
225
  if @producer.config['subtitle'].nil?
218
226
  @body << <<EOT
219
- <p class="title">#{CGI.escapeHTML(@producer.config.name_of('title'))}</p>
227
+ <p class="title">#{h(@producer.config.name_of('title'))}</p>
220
228
  EOT
221
229
  else
222
230
  @body << <<EOT
223
- <p class="title">#{CGI.escapeHTML(@producer.config.name_of('title'))}<br /><span class="subtitle">#{CGI.escapeHTML(@producer.config.name_of('subtitle'))}</span></p>
231
+ <p class="title">#{h(@producer.config.name_of('title'))}<br /><span class="subtitle">#{h(@producer.config.name_of('subtitle'))}</span></p>
224
232
  EOT
225
233
  end
226
234
 
@@ -229,7 +237,7 @@ EOT
229
237
  @body << %Q( <table class="colophon">\n)
230
238
  @body << @producer.config['colophon_order'].map do |role|
231
239
  if @producer.config[role]
232
- %Q( <tr><th>#{CGI.escapeHTML(@producer.res.v(role))}</th><td>#{CGI.escapeHTML(join_with_separator(@producer.config.names_of(role), ReVIEW::I18n.t('names_splitter')))}</td></tr>\n)
240
+ %Q( <tr><th>#{h(@producer.res.v(role))}</th><td>#{h(join_with_separator(@producer.config.names_of(role), ReVIEW::I18n.t('names_splitter')))}</td></tr>\n)
233
241
  else
234
242
  ''
235
243
  end
@@ -238,7 +246,7 @@ EOT
238
246
  @body << %Q( <tr><th>ISBN</th><td>#{@producer.isbn_hyphen}</td></tr>\n) if @producer.isbn_hyphen
239
247
  @body << %Q( </table>\n)
240
248
  if @producer.config['rights'] && !@producer.config['rights'].empty?
241
- @body << %Q( <p class="copyright">#{join_with_separator(@producer.config.names_of('rights').map { |m| CGI.escapeHTML(m) }, '<br />')}</p>\n)
249
+ @body << %Q( <p class="copyright">#{join_with_separator(@producer.config.names_of('rights').map { |m| h(m) }, '<br />')}</p>\n)
242
250
  end
243
251
  @body << %Q( </div>\n)
244
252
 
@@ -261,11 +269,11 @@ EOT
261
269
  items.each_with_index do |item, rev|
262
270
  editstr = edit == 0 ? ReVIEW::I18n.t('first_edition') : ReVIEW::I18n.t('nth_edition', (edit + 1).to_s)
263
271
  revstr = ReVIEW::I18n.t('nth_impression', (rev + 1).to_s)
264
- if item =~ /\A\d+\-\d+\-\d+\Z/
272
+ if item =~ /\A\d+-\d+-\d+\Z/
265
273
  buf << %Q( <p>#{ReVIEW::I18n.t('published_by1', [date_to_s(item), editstr + revstr])}</p>\n)
266
- elsif item =~ /\A(\d+\-\d+\-\d+)[\s ](.+)/
274
+ elsif item =~ /\A(\d+-\d+-\d+)[\s ](.+)/
267
275
  # custom date with string
268
- item.match(/\A(\d+\-\d+\-\d+)[\s ](.+)/) do |m|
276
+ item.match(/\A(\d+-\d+-\d+)[\s ](.+)/) do |m|
269
277
  buf << %Q( <p>#{ReVIEW::I18n.t('published_by3', [date_to_s(m[1]), m[2]])}</p>\n)
270
278
  end
271
279
  else
@@ -289,9 +297,9 @@ EOT
289
297
 
290
298
  # Return own toc content.
291
299
  def mytoc
292
- @title = CGI.escapeHTML(@producer.res.v('toctitle'))
300
+ @title = h(@producer.res.v('toctitle'))
293
301
 
294
- @body = %Q( <h1 class="toc-title">#{CGI.escapeHTML(@producer.res.v('toctitle'))}</h1>\n)
302
+ @body = %Q( <h1 class="toc-title">#{h(@producer.res.v('toctitle'))}</h1>\n)
295
303
  if @producer.config['epubmaker']['flattoc'].nil?
296
304
  @body << hierarchy_ncx('ul')
297
305
  else
@@ -385,7 +393,7 @@ EOT
385
393
  @producer.contents.each do |item|
386
394
  next if !item.notoc.nil? || item.level.nil? || item.file.nil? || item.title.nil? || item.level > @producer.config['toclevel'].to_i
387
395
  is = indent == true ? ' ' * item.level : ''
388
- s << %Q(<li><a href="#{item.file}">#{is}#{CGI.escapeHTML(item.title)}</a></li>\n)
396
+ s << %Q(<li><a href="#{item.file}">#{is}#{h(item.title)}</a></li>\n)
389
397
  end
390
398
  s << %Q(</#{type}>\n)
391
399
 
@@ -9,14 +9,13 @@
9
9
  #
10
10
 
11
11
  require 'epubmaker/epubcommon'
12
- require 'cgi'
13
12
  require 'epubmaker/zip_exporter'
14
13
 
15
14
  module EPUBMaker
16
15
  # EPUBv2 is EPUB version 2 producer.
17
16
  class EPUBv2 < EPUBCommon
18
17
  # Construct object with parameter hash +config+ and message resource hash +res+.
19
- def initialize(producer)
18
+ def initialize(producer) # rubocop:disable Lint/UselessMethodDefinition
20
19
  super
21
20
  end
22
21
 
@@ -37,9 +36,9 @@ module EPUBMaker
37
36
  %w[title language date type format source description relation coverage subject rights].each do |item|
38
37
  next unless @producer.config[item]
39
38
  if @producer.config[item].is_a?(Array)
40
- s << @producer.config.names_of(item).map { |i| %Q( <dc:#{item}>#{CGI.escapeHTML(i)}</dc:#{item}>\n) }.join
39
+ s << @producer.config.names_of(item).map { |i| %Q( <dc:#{item}>#{h(i)}</dc:#{item}>\n) }.join
41
40
  else
42
- s << %Q( <dc:#{item}>#{CGI.escapeHTML(@producer.config.name_of(item).to_s)}</dc:#{item}>\n)
41
+ s << %Q( <dc:#{item}>#{h(@producer.config.name_of(item).to_s)}</dc:#{item}>\n)
43
42
  end
44
43
  end
45
44
 
@@ -54,7 +53,7 @@ module EPUBMaker
54
53
  %w[aut a-adp a-ann a-arr a-art a-asn a-aqt a-aft a-aui a-ant a-bkp a-clb a-cmm a-dsr a-edt a-ill a-lyr a-mdc a-mus a-nrt a-oth a-pht a-prt a-red a-rev a-spn a-ths a-trc a-trl].each do |role|
55
54
  next unless @producer.config[role]
56
55
  @producer.config.names_of(role).each do |v|
57
- s << %Q( <dc:creator opf:role="#{role.sub('a-', '')}">#{CGI.escapeHTML(v)}</dc:creator>\n)
56
+ s << %Q( <dc:creator opf:role="#{role.sub('a-', '')}">#{h(v)}</dc:creator>\n)
58
57
  end
59
58
  end
60
59
 
@@ -62,7 +61,7 @@ module EPUBMaker
62
61
  %w[adp ann arr art asn aqt aft aui ant bkp clb cmm dsr edt ill lyr mdc mus nrt oth pht prt red rev spn ths trc trl].each do |role|
63
62
  next unless @producer.config[role]
64
63
  @producer.config.names_of(role).each do |v|
65
- s << %Q( <dc:contributor opf:role="#{role}">#{CGI.escapeHTML(v)}</dc:contributor>\n)
64
+ s << %Q( <dc:contributor opf:role="#{role}">#{h(v)}</dc:contributor>\n)
66
65
  if role == 'prt'
67
66
  s << %Q( <dc:publisher>#{v}</dc:publisher>\n)
68
67
  end
@@ -40,6 +40,7 @@ module EPUBMaker
40
40
  ReVIEW::Template.load(tmplfile).result(binding)
41
41
  end
42
42
 
43
+ # rubocop:disable Metrics/PerceivedComplexity
43
44
  def opf_metainfo
44
45
  s = ''
45
46
  %w[title language date type format source description relation coverage subject rights].each do |item|
@@ -47,23 +48,23 @@ module EPUBMaker
47
48
  if @producer.config[item].is_a?(Array)
48
49
  @producer.config[item].each_with_index do |v, i|
49
50
  if v.is_a?(Hash)
50
- s << %Q( <dc:#{item} id="#{item}-#{i}">#{CGI.escapeHTML(v['name'])}</dc:#{item}>\n)
51
+ s << %Q( <dc:#{item} id="#{item}-#{i}">#{h(v['name'])}</dc:#{item}>\n)
51
52
  v.each_pair do |name, val|
52
53
  next if name == 'name'
53
- s << %Q( <meta refines="##{item}-#{i}" property="#{name}">#{CGI.escapeHTML(val)}</meta>\n)
54
+ s << %Q( <meta refines="##{item}-#{i}" property="#{name}">#{h(val)}</meta>\n)
54
55
  end
55
56
  else
56
- s << %Q( <dc:#{item} id="#{item}-#{i}">#{CGI.escapeHTML(v.to_s)}</dc:#{item}>\n)
57
+ s << %Q( <dc:#{item} id="#{item}-#{i}">#{h(v.to_s)}</dc:#{item}>\n)
57
58
  end
58
59
  end
59
60
  elsif @producer.config[item].is_a?(Hash)
60
- s << %Q( <dc:#{item} id="#{item}">#{CGI.escapeHTML(@producer.config[item]['name'])}</dc:#{item}>\n)
61
+ s << %Q( <dc:#{item} id="#{item}">#{h(@producer.config[item]['name'])}</dc:#{item}>\n)
61
62
  @producer.config[item].each_pair do |name, val|
62
63
  next if name == 'name'
63
- s << %Q( <meta refines="##{item}" property="#{name}">#{CGI.escapeHTML(val)}</meta>\n)
64
+ s << %Q( <meta refines="##{item}" property="#{name}">#{h(val)}</meta>\n)
64
65
  end
65
66
  else
66
- s << %Q( <dc:#{item} id="#{item}">#{CGI.escapeHTML(@producer.config[item].to_s)}</dc:#{item}>\n)
67
+ s << %Q( <dc:#{item} id="#{item}">#{h(@producer.config[item].to_s)}</dc:#{item}>\n)
67
68
  end
68
69
  end
69
70
 
@@ -81,14 +82,14 @@ module EPUBMaker
81
82
  next unless @producer.config[role]
82
83
  @producer.config[role].each_with_index do |v, i|
83
84
  if v.is_a?(Hash)
84
- s << %Q( <dc:creator id="#{role}-#{i}">#{CGI.escapeHTML(v['name'])}</dc:creator>\n)
85
+ s << %Q( <dc:creator id="#{role}-#{i}">#{h(v['name'])}</dc:creator>\n)
85
86
  s << %Q( <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role.sub('a-', '')}</meta>\n)
86
87
  v.each_pair do |name, val|
87
88
  next if name == 'name'
88
- s << %Q( <meta refines="##{role.sub('a-', '')}-#{i}" property="#{name}">#{CGI.escapeHTML(val)}</meta>\n)
89
+ s << %Q( <meta refines="##{role.sub('a-', '')}-#{i}" property="#{name}">#{h(val)}</meta>\n)
89
90
  end
90
91
  else
91
- s << %Q( <dc:creator id="#{role}-#{i}">#{CGI.escapeHTML(v)}</dc:creator>\n)
92
+ s << %Q( <dc:creator id="#{role}-#{i}">#{h(v)}</dc:creator>\n)
92
93
  s << %Q( <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role.sub('a-', '')}</meta>\n)
93
94
  end
94
95
  end
@@ -99,27 +100,27 @@ module EPUBMaker
99
100
  next unless @producer.config[role]
100
101
  @producer.config[role].each_with_index do |v, i|
101
102
  if v.is_a?(Hash)
102
- s << %Q( <dc:contributor id="#{role}-#{i}">#{CGI.escapeHTML(v['name'])}</dc:contributor>\n)
103
+ s << %Q( <dc:contributor id="#{role}-#{i}">#{h(v['name'])}</dc:contributor>\n)
103
104
  s << %Q( <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role}</meta>\n)
104
105
  v.each_pair do |name, val|
105
106
  next if name == 'name'
106
- s << %Q( <meta refines="##{role}-#{i}" property="#{name}">#{CGI.escapeHTML(val)}</meta>\n)
107
+ s << %Q( <meta refines="##{role}-#{i}" property="#{name}">#{h(val)}</meta>\n)
107
108
  end
108
109
  else
109
- s << %Q( <dc:contributor id="#{role}-#{i}">#{CGI.escapeHTML(v)}</dc:contributor>\n)
110
+ s << %Q( <dc:contributor id="#{role}-#{i}">#{h(v)}</dc:contributor>\n)
110
111
  s << %Q( <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role}</meta>\n)
111
112
  end
112
113
 
113
114
  if %w[prt pbl].include?(role)
114
115
  if v.is_a?(Hash)
115
- s << %Q( <dc:publisher id="pub-#{role}-#{i}">#{CGI.escapeHTML(v['name'])}</dc:publisher>\n)
116
+ s << %Q( <dc:publisher id="pub-#{role}-#{i}">#{h(v['name'])}</dc:publisher>\n)
116
117
  s << %Q( <meta refines="#pub-#{role}-#{i}" property="role" scheme="marc:relators">#{role}</meta>\n)
117
118
  v.each_pair do |name, val|
118
119
  next if name == 'name'
119
- s << %Q( <meta refines="#pub-#{role}-#{i}" property="#{name}">#{CGI.escapeHTML(val)}</meta>\n)
120
+ s << %Q( <meta refines="#pub-#{role}-#{i}" property="#{name}">#{h(val)}</meta>\n)
120
121
  end
121
122
  else
122
- s << %Q( <dc:publisher id="pub-#{role}-#{i}">#{CGI.escapeHTML(v)}</dc:publisher>\n)
123
+ s << %Q( <dc:publisher id="pub-#{role}-#{i}">#{h(v)}</dc:publisher>\n)
123
124
  s << %Q( <meta refines="#pub-#{role}-#{i}" property="role" scheme="marc:relators">prt</meta>\n)
124
125
  end
125
126
  end
@@ -129,12 +130,13 @@ module EPUBMaker
129
130
  ## add custom <meta> element
130
131
  if @producer.config['opf_meta'].present?
131
132
  @producer.config['opf_meta'].each do |k, v|
132
- s << %Q( <meta property="#{k}">#{CGI.escapeHTML(v)}</meta>\n)
133
+ s << %Q( <meta property="#{k}">#{h(v)}</meta>\n)
133
134
  end
134
135
  end
135
136
 
136
137
  s
137
138
  end
139
+ # rubocop:enable Metrics/PerceivedComplexity
138
140
 
139
141
  def opf_manifest
140
142
  s = ''
@@ -206,11 +208,11 @@ EOT
206
208
 
207
209
  @body = <<EOT
208
210
  <nav xmlns:epub="http://www.idpf.org/2007/ops" epub:type="toc" id="toc">
209
- <h1 class="toc-title">#{CGI.escapeHTML(@producer.res.v('toctitle'))}</h1>
211
+ <h1 class="toc-title">#{h(@producer.res.v('toctitle'))}</h1>
210
212
  #{ncx_main} </nav>
211
213
  EOT
212
214
 
213
- @title = CGI.escapeHTML(@producer.res.v('toctitle'))
215
+ @title = h(@producer.res.v('toctitle'))
214
216
  @language = @producer.config['language']
215
217
  @stylesheets = @producer.config['stylesheet']
216
218
  tmplfile = File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
@@ -18,8 +18,8 @@ require 'review/book/index'
18
18
 
19
19
  module ReVIEW
20
20
  module Book
21
- def self.load(dir)
22
- Base.load(dir)
21
+ def self.load(_dir)
22
+ raise NotImplementedError, 'ReVIEW::Book.load is obsoleted. Please use ReVIEW::Book::Base.new.'
23
23
  end
24
24
  end
25
25
  end
@@ -9,26 +9,34 @@
9
9
  #
10
10
  require 'review/configure'
11
11
  require 'review/catalog'
12
+ require 'review/book/bib'
12
13
 
13
14
  module ReVIEW
14
15
  module Book
15
16
  class Base
16
17
  attr_accessor :config
17
18
  attr_writer :parts
18
- attr_writer :catalog
19
+ attr_accessor :catalog
19
20
  attr_reader :basedir
21
+ attr_accessor :bibpaper_index
20
22
 
21
- def self.load(dir = '.')
22
- new(dir)
23
+ def self.load(basedir = '.', config: nil)
24
+ new(basedir, config: config)
23
25
  end
24
26
 
25
- def initialize(basedir = '.')
27
+ def initialize(basedir = '.', config: nil)
26
28
  @basedir = basedir
27
29
  @logger = ReVIEW.logger
28
30
  @parts = nil
29
31
  @chapter_index = nil
30
- @config = ReVIEW::Configure.values
32
+ @config = config || ReVIEW::Configure.values
31
33
  @catalog = nil
34
+ @bibpaper_index = nil
35
+ catalog_path = filename_join(@basedir, @config['catalogfile'])
36
+ if catalog_path && File.file?(catalog_path)
37
+ parse_catalog_file(catalog_path)
38
+ end
39
+
32
40
  @warn_old_files = {} # XXX for checking CHAPS, PREDEF, POSTDEF
33
41
  @basedir_seen = {}
34
42
  update_rubyenv
@@ -44,6 +52,14 @@ module ReVIEW
44
52
  end
45
53
  end
46
54
 
55
+ def execute_indexer
56
+ return unless @catalog
57
+
58
+ parts.each do |part|
59
+ part.chapters.each(&:execute_indexer)
60
+ end
61
+ end
62
+
47
63
  def bib_file
48
64
  config['bib_file']
49
65
  end
@@ -94,6 +110,30 @@ module ReVIEW
94
110
  end
95
111
  end
96
112
 
113
+ def create_chapter_index
114
+ chapter_index = ChapterIndex.new
115
+ each_chapter do |chap|
116
+ chapter_index.add_item(Index::Item.new(chap.id, chap.number, chap))
117
+ end
118
+ parts.each do |prt|
119
+ if prt.id.present?
120
+ chapter_index.add_item(Index::Item.new(prt.id, prt.number, prt))
121
+ end
122
+ end
123
+ chapter_index
124
+ end
125
+
126
+ def generate_indexes
127
+ if bib_exist?
128
+ bib = ReVIEW::Book::Bib.new(file_content: bib_content, book: self)
129
+ bib.generate_indexes(use_bib: true)
130
+ @bibpaper_index = bib.bibpaper_index
131
+ end
132
+ self.each_chapter(&:generate_indexes)
133
+ self.parts.map(&:generate_indexes)
134
+ @chapter_index = create_chapter_index
135
+ end
136
+
97
137
  def parts
98
138
  @parts ||= read_parts
99
139
  end
@@ -101,7 +141,7 @@ module ReVIEW
101
141
  def parts_in_file
102
142
  # TODO: should be `parts.find_all{|part| part.present? and part.file?}` ?
103
143
  parts.find_all do |part|
104
- part if part.present? and part.file?
144
+ part if part.present? && part.file?
105
145
  end
106
146
  end
107
147
 
@@ -136,15 +176,7 @@ module ReVIEW
136
176
 
137
177
  def chapter_index
138
178
  return @chapter_index if @chapter_index
139
- @chapter_index = ChapterIndex.new
140
- each_chapter do |chap|
141
- @chapter_index.add_item(Index::Item.new(chap.id, chap.number, chap))
142
- end
143
- parts.each do |prt|
144
- if prt.id.present?
145
- @chapter_index.add_item(Index::Item.new(prt.id, prt.number, prt))
146
- end
147
- end
179
+ @chapter_index = create_chapter_index
148
180
  @chapter_index
149
181
  end
150
182
 
@@ -183,17 +215,15 @@ module ReVIEW
183
215
  @config.merge!(new_conf)
184
216
  end
185
217
 
186
- def catalog
187
- return @catalog if @catalog.present?
188
-
189
- catalogfile_path = filename_join(@basedir, config['catalogfile'])
190
- if File.file?(catalogfile_path)
191
- @catalog = File.open(catalogfile_path, 'rt:BOM|utf-8') { |f| Catalog.new(f) }
218
+ def parse_catalog_file(path)
219
+ unless File.file?(path)
220
+ raise FileNotFound, "catalog.yml is not found #{path}"
192
221
  end
193
- if @catalog
222
+
223
+ File.open(path, 'rt:BOM|utf-8') do |f|
224
+ @catalog = Catalog.new(f)
194
225
  @catalog.validate!(@config, basedir)
195
226
  end
196
- @catalog
197
227
  end
198
228
 
199
229
  def read_chaps
@@ -252,6 +282,10 @@ module ReVIEW
252
282
  File.exist?(File.join(contentdir, bib_file))
253
283
  end
254
284
 
285
+ def bib_content
286
+ File.read(File.join(contentdir, bib_file))
287
+ end
288
+
255
289
  def prefaces
256
290
  if catalog
257
291
  return Part.mkpart_from_namelist(self, catalog.predef)
@@ -333,8 +367,8 @@ module ReVIEW
333
367
  end
334
368
  end
335
369
 
336
- chap = read_chaps.map(&:strip).join("\n").split(/\n{2,}/).
337
- map do |part_chunk|
370
+ # rubocop:disable Style/RedundantAssignment
371
+ chap = read_chaps.map(&:strip).join("\n").split(/\n{2,}/).map do |part_chunk|
338
372
  chaps = part_chunk.split.map { |chapid| Chapter.new(self, num += 1, chapid, File.join(contentdir, chapid)) }
339
373
  if part_exist? && read_part.size > part
340
374
  Part.new(self, part += 1, chaps, read_part[part - 1])
@@ -342,6 +376,8 @@ module ReVIEW
342
376
  Part.new(self, nil, chaps)
343
377
  end
344
378
  end
379
+ # rubocop:enable Style/RedundantAssignment
380
+
345
381
  chap
346
382
  end
347
383