review 3.2.0 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (282) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-tex.yml +31 -0
  3. data/.github/workflows/ruby-win.yml +45 -0
  4. data/.github/workflows/ruby.yml +27 -0
  5. data/.rubocop.yml +167 -42
  6. data/.travis.yml +1 -1
  7. data/Dockerfile +21 -5
  8. data/NEWS.ja.md +428 -1
  9. data/NEWS.md +429 -2
  10. data/README.md +11 -7
  11. data/Rakefile +7 -2
  12. data/appveyor.yml +0 -20
  13. data/bin/review +2 -4
  14. data/bin/review-catalog-converter +5 -5
  15. data/bin/review-check +13 -17
  16. data/bin/review-checkdep +3 -6
  17. data/bin/review-compile +13 -22
  18. data/bin/review-epub2html +1 -4
  19. data/bin/review-epubmaker +3 -4
  20. data/bin/review-idgxmlmaker +14 -0
  21. data/bin/review-index +5 -86
  22. data/bin/review-init +1 -4
  23. data/bin/review-pdfmaker +1 -3
  24. data/bin/review-preproc +11 -13
  25. data/bin/review-textmaker +1 -3
  26. data/bin/review-update +1 -4
  27. data/bin/review-validate +7 -7
  28. data/bin/review-vol +5 -82
  29. data/bin/review-webmaker +1 -3
  30. data/doc/config.yml.sample +67 -16
  31. data/doc/config.yml.sample-simple +4 -3
  32. data/doc/format.ja.md +133 -21
  33. data/doc/format.md +135 -34
  34. data/doc/makeindex.ja.md +2 -2
  35. data/doc/pdfmaker.ja.md +43 -1
  36. data/doc/pdfmaker.md +42 -1
  37. data/doc/quickstart.ja.md +55 -25
  38. data/doc/quickstart.md +47 -17
  39. data/lib/review.rb +1 -1
  40. data/lib/review/book.rb +2 -2
  41. data/lib/review/book/base.rb +89 -90
  42. data/lib/review/book/bib.rb +21 -0
  43. data/lib/review/book/book_unit.rb +158 -0
  44. data/lib/review/book/chapter.rb +51 -29
  45. data/lib/review/book/index.rb +42 -248
  46. data/lib/review/book/index/item.rb +46 -0
  47. data/lib/review/book/page_metric.rb +7 -7
  48. data/lib/review/book/part.rb +45 -10
  49. data/lib/review/book/volume.rb +5 -5
  50. data/lib/review/builder.rb +171 -54
  51. data/lib/review/call_hook.rb +20 -0
  52. data/lib/review/catalog.rb +15 -17
  53. data/lib/review/compiler.rb +240 -102
  54. data/lib/review/configure.rb +101 -12
  55. data/lib/review/converter.rb +1 -1
  56. data/lib/review/epub2html.rb +6 -1
  57. data/lib/review/epubmaker.rb +120 -118
  58. data/lib/review/epubmaker/content.rb +113 -0
  59. data/lib/review/epubmaker/epubcommon.rb +372 -0
  60. data/lib/review/epubmaker/epubv2.rb +178 -0
  61. data/lib/review/epubmaker/epubv3.rb +231 -0
  62. data/lib/review/epubmaker/producer.rb +168 -0
  63. data/lib/review/epubmaker/reviewheaderlistener.rb +12 -2
  64. data/lib/review/epubmaker/zip_exporter.rb +84 -0
  65. data/lib/review/exception.rb +6 -0
  66. data/lib/review/extentions/string.rb +0 -4
  67. data/lib/review/htmlbuilder.rb +147 -149
  68. data/lib/review/htmlutils.rb +10 -14
  69. data/lib/review/i18n.rb +4 -3
  70. data/lib/review/idgxmlbuilder.rb +229 -103
  71. data/lib/review/idgxmlmaker.rb +188 -0
  72. data/lib/review/img_math.rb +245 -0
  73. data/lib/review/index_builder.rb +654 -0
  74. data/lib/review/init-web/finish.html +10 -0
  75. data/lib/review/init-web/index.html +190 -0
  76. data/lib/review/init-web/review-layout-design.js +691 -0
  77. data/lib/review/init.rb +124 -41
  78. data/lib/review/latexbox.rb +58 -0
  79. data/lib/review/latexbuilder.rb +249 -97
  80. data/lib/review/latexutils.rb +9 -1
  81. data/lib/review/lineinput.rb +113 -3
  82. data/lib/review/logger.rb +43 -8
  83. data/lib/review/makerhelper.rb +13 -186
  84. data/lib/review/markdownbuilder.rb +75 -39
  85. data/lib/review/md2inaobuilder.rb +3 -5
  86. data/lib/review/pdfmaker.rb +88 -83
  87. data/lib/review/plaintextbuilder.rb +158 -83
  88. data/lib/review/preprocessor.rb +30 -24
  89. data/lib/review/rstbuilder.rb +58 -39
  90. data/lib/review/sec_counter.rb +14 -0
  91. data/lib/review/template.rb +6 -0
  92. data/lib/review/textmaker.rb +29 -17
  93. data/lib/review/textutils.rb +68 -2
  94. data/lib/review/tocprinter.rb +242 -97
  95. data/lib/review/topbuilder.rb +147 -61
  96. data/lib/review/update.rb +27 -28
  97. data/lib/review/version.rb +1 -1
  98. data/lib/review/volumeprinter.rb +97 -0
  99. data/lib/review/webmaker.rb +36 -35
  100. data/lib/review/webtocprinter.rb +39 -35
  101. data/lib/review/yamlloader.rb +4 -0
  102. data/review.gemspec +8 -5
  103. data/samples/sample-book/README.md +7 -2
  104. data/samples/sample-book/src/.gitignore +154 -0
  105. data/samples/sample-book/src/config-ebook.yml +4 -0
  106. data/samples/sample-book/src/config-epub2.yml +1 -1
  107. data/samples/sample-book/src/config-jlreq-ebook.yml +4 -0
  108. data/samples/sample-book/src/config-jlreq.yml +6 -0
  109. data/samples/sample-book/src/config.yml +3 -3
  110. data/samples/sample-book/src/lib/tasks/review.rake +45 -14
  111. data/samples/sample-book/src/lib/tasks/z01_copy_sty.rake +14 -8
  112. data/samples/syntax-book/Gemfile +1 -1
  113. data/samples/syntax-book/ch01.re +3 -1
  114. data/samples/syntax-book/ch02.re +28 -21
  115. data/samples/syntax-book/ch03.re +4 -7
  116. data/samples/syntax-book/config-jlreq-lualatex.yml +4 -0
  117. data/samples/syntax-book/config-jlreq.yml +5 -0
  118. data/samples/syntax-book/config-print.yml +3 -0
  119. data/samples/syntax-book/config.yml +1 -1
  120. data/samples/syntax-book/images/img3-2.png +0 -0
  121. data/samples/syntax-book/lib/tasks/review.rake +30 -15
  122. data/samples/syntax-book/lib/tasks/z01_copy_sty.rake +14 -8
  123. data/templates/html/_colophon.html.erb +23 -0
  124. data/templates/html/_colophon_history.html.erb +9 -0
  125. data/templates/html/_cover.html.erb +10 -0
  126. data/templates/html/_part_body.html.erb +6 -0
  127. data/templates/html/_titlepage.html.erb +20 -0
  128. data/templates/html/layout-html5.html.erb +6 -0
  129. data/templates/html/layout-xhtml1.html.erb +6 -0
  130. data/templates/latex/config.erb +45 -27
  131. data/templates/latex/layout.tex.erb +1 -0
  132. data/templates/latex/review-jlreq/README.md +3 -1
  133. data/templates/latex/review-jlreq/review-base.sty +124 -37
  134. data/templates/latex/review-jlreq/review-jlreq.cls +29 -22
  135. data/templates/latex/review-jlreq/review-style.sty +9 -1
  136. data/templates/latex/review-jlreq/review-tcbox.sty +348 -0
  137. data/templates/latex/review-jlreq/reviewmacro.sty +5 -0
  138. data/templates/latex/review-jsbook/README.md +46 -5
  139. data/templates/latex/review-jsbook/review-base.sty +111 -30
  140. data/templates/latex/review-jsbook/review-jsbook.cls +16 -2
  141. data/templates/latex/review-jsbook/review-style.sty +10 -2
  142. data/templates/latex/review-jsbook/review-tcbox.sty +348 -0
  143. data/templates/latex/review-jsbook/reviewmacro.sty +5 -0
  144. data/templates/opf/epubv2.opf.erb +7 -7
  145. data/templates/opf/epubv3.opf.erb +7 -7
  146. data/templates/opf/opf_manifest_epubv2.opf.erb +10 -0
  147. data/templates/opf/opf_manifest_epubv3.opf.erb +10 -0
  148. data/templates/opf/opf_metainfo_epubv2.opf.erb +17 -0
  149. data/templates/opf/opf_metainfo_epubv3.opf.erb +49 -0
  150. data/templates/opf/opf_tocx_epubv2.opf.erb +9 -0
  151. data/templates/opf/opf_tocx_epubv3.opf.erb +17 -0
  152. data/templates/web/html/layout-html5.html.erb +9 -8
  153. data/templates/web/html/layout-xhtml1.html.erb +6 -0
  154. data/test/assets/header_listener.html +35 -0
  155. data/test/assets/img_math/img1.png +0 -0
  156. data/test/assets/img_math/img2.png +0 -0
  157. data/test/assets/img_math/img3.png +0 -0
  158. data/test/assets/syntax_book_index_detail.txt +58 -0
  159. data/test/assets/test_template.tex +20 -9
  160. data/test/assets/test_template_backmatter.tex +20 -9
  161. data/test/book_test_helper.rb +11 -5
  162. data/test/run_test.rb +1 -1
  163. data/test/test_book.rb +123 -78
  164. data/test/test_book_chapter.rb +99 -56
  165. data/test/test_book_part.rb +3 -3
  166. data/test/test_builder.rb +24 -15
  167. data/test/test_catalog.rb +19 -42
  168. data/test/test_catalog_converter_cmd.rb +1 -1
  169. data/test/test_converter.rb +1 -0
  170. data/test/test_epub3maker.rb +170 -126
  171. data/test/test_epubmaker.rb +249 -129
  172. data/test/test_epubmaker_cmd.rb +16 -9
  173. data/test/test_helper.rb +23 -11
  174. data/test/test_htmlbuilder.rb +1083 -114
  175. data/test/test_htmlutils.rb +0 -12
  176. data/test/test_i18n.rb +37 -37
  177. data/test/test_idgxmlbuilder.rb +627 -27
  178. data/test/test_idgxmlmaker_cmd.rb +50 -0
  179. data/test/test_image_finder.rb +52 -70
  180. data/test/test_img_math.rb +111 -0
  181. data/test/test_index.rb +62 -52
  182. data/test/test_indexbuilder.rb +52 -0
  183. data/test/test_latexbuilder.rb +1189 -59
  184. data/test/test_latexbuilder_v2.rb +74 -34
  185. data/test/test_lineinput.rb +20 -93
  186. data/test/test_logger.rb +17 -4
  187. data/test/test_makerhelper.rb +2 -14
  188. data/test/test_markdownbuilder.rb +77 -4
  189. data/test/test_md2inaobuilder.rb +12 -2
  190. data/test/test_pdfmaker.rb +101 -12
  191. data/test/test_pdfmaker_cmd.rb +102 -8
  192. data/test/test_plaintextbuilder.rb +562 -31
  193. data/test/test_review_ext.rb +2 -1
  194. data/test/test_reviewheaderlistener.rb +49 -0
  195. data/test/test_rstbuilder.rb +58 -5
  196. data/test/test_sec_counter.rb +156 -0
  197. data/test/test_template.rb +12 -2
  198. data/test/test_textmaker_cmd.rb +58 -0
  199. data/test/test_textutils.rb +109 -2
  200. data/test/test_tocprinter.rb +46 -0
  201. data/test/test_topbuilder.rb +400 -17
  202. data/test/test_update.rb +53 -44
  203. data/test/test_webtocprinter.rb +75 -43
  204. data/test/test_yamlloader.rb +13 -0
  205. data/test/test_zip_exporter.rb +5 -6
  206. data/vendor/gentombow/LICENSE +1 -1
  207. data/vendor/gentombow/Makefile +0 -1
  208. data/vendor/gentombow/bounddvi-en.pdf +0 -0
  209. data/vendor/gentombow/bounddvi-en.tex +1 -0
  210. data/vendor/gentombow/bounddvi.pdf +0 -0
  211. data/vendor/gentombow/bounddvi.sty +30 -7
  212. data/vendor/gentombow/bounddvi.tex +1 -0
  213. data/vendor/gentombow/create_archive.sh +1 -0
  214. data/vendor/gentombow/gentombow-ja.pdf +0 -0
  215. data/vendor/gentombow/gentombow-ja.tex +9 -0
  216. data/vendor/gentombow/gentombow.pdf +0 -0
  217. data/vendor/gentombow/gentombow.sty +32 -10
  218. data/vendor/gentombow/gentombow.tex +8 -0
  219. data/vendor/gentombow/tests/gentombow-01-pdfx.tex +8 -0
  220. data/vendor/gentombow/tests/gentombow-02-pdfx.tex +8 -0
  221. data/vendor/jsclasses/LICENSE +1 -1
  222. data/vendor/jsclasses/Makefile +3 -2
  223. data/vendor/jsclasses/create_archive.sh +5 -5
  224. data/vendor/jsclasses/jis/Makefile +3 -2
  225. data/vendor/jsclasses/jis/jsarticle.cls +74 -31
  226. data/vendor/jsclasses/jis/jsbook.cls +74 -31
  227. data/vendor/jsclasses/jis/jsclasses.dtx +176 -36
  228. data/vendor/jsclasses/jis/jsclasses.ins +15 -5
  229. data/vendor/jsclasses/jis/jslogo.dtx +4 -4
  230. data/vendor/jsclasses/jis/jslogo.ins +9 -0
  231. data/vendor/jsclasses/jis/jslogo.sty +4 -16
  232. data/vendor/jsclasses/jis/jspf.cls +73 -30
  233. data/vendor/jsclasses/jis/jsreport.cls +74 -31
  234. data/vendor/jsclasses/jis/jsverb.ins +9 -0
  235. data/vendor/jsclasses/jis/jsverb.sty +1 -13
  236. data/vendor/jsclasses/jis/kiyou.cls +74 -31
  237. data/vendor/jsclasses/jis/minijs.sty +65 -22
  238. data/vendor/jsclasses/jis/okumacro.dtx +4 -5
  239. data/vendor/jsclasses/jis/okumacro.ins +9 -0
  240. data/vendor/jsclasses/jis/okumacro.sty +4 -17
  241. data/vendor/jsclasses/jis/okuverb.ins +9 -0
  242. data/vendor/jsclasses/jis/okuverb.sty +1 -13
  243. data/vendor/jsclasses/jis/winjis.sty +23 -19
  244. data/vendor/jsclasses/jsarticle.cls +74 -31
  245. data/vendor/jsclasses/jsbook.cls +74 -31
  246. data/vendor/jsclasses/jsclasses.dtx +176 -36
  247. data/vendor/jsclasses/jsclasses.ins +15 -5
  248. data/vendor/jsclasses/jsclasses.pdf +0 -0
  249. data/vendor/jsclasses/jslogo.dtx +4 -4
  250. data/vendor/jsclasses/jslogo.ins +9 -0
  251. data/vendor/jsclasses/jslogo.pdf +0 -0
  252. data/vendor/jsclasses/jslogo.sty +4 -16
  253. data/vendor/jsclasses/jspf.cls +73 -30
  254. data/vendor/jsclasses/jsreport.cls +74 -31
  255. data/vendor/jsclasses/jsverb.ins +9 -0
  256. data/vendor/jsclasses/jsverb.pdf +0 -0
  257. data/vendor/jsclasses/jsverb.sty +1 -13
  258. data/vendor/jsclasses/kiyou.cls +74 -31
  259. data/vendor/jsclasses/minijs.sty +68 -22
  260. data/vendor/jsclasses/okumacro.dtx +4 -5
  261. data/vendor/jsclasses/okumacro.ins +9 -0
  262. data/vendor/jsclasses/okumacro.pdf +0 -0
  263. data/vendor/jsclasses/okumacro.sty +4 -17
  264. data/vendor/jsclasses/okuverb.ins +9 -0
  265. data/vendor/jsclasses/okuverb.pdf +0 -0
  266. data/vendor/jsclasses/okuverb.sty +1 -13
  267. data/vendor/jsclasses/tests/relfont.tex +10 -0
  268. data/vendor/jsclasses/winjis.sty +23 -19
  269. metadata +136 -23
  270. data/.rubocop_todo.yml +0 -7
  271. data/lib/epubmaker.rb +0 -23
  272. data/lib/epubmaker/content.rb +0 -110
  273. data/lib/epubmaker/epubcommon.rb +0 -441
  274. data/lib/epubmaker/epubv2.rb +0 -143
  275. data/lib/epubmaker/epubv3.rb +0 -233
  276. data/lib/epubmaker/producer.rb +0 -375
  277. data/lib/epubmaker/zip_exporter.rb +0 -81
  278. data/lib/lineinput.rb +0 -155
  279. data/lib/review/book/compilable.rb +0 -173
  280. data/lib/review/tocparser.rb +0 -271
  281. data/samples/syntax-book/review-ext.rb +0 -14
  282. data/test/test_tocparser.rb +0 -25
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2012-2018 Masanori Kado, Masayoshi Takahashi, Kenshi Muto
2
+ # Copyright (c) 2012-2021 Masanori Kado, Masayoshi Takahashi, Kenshi Muto
3
3
  #
4
4
  # This program is free software.
5
5
  # You can distribute or modify this program under the terms of
@@ -7,15 +7,16 @@
7
7
  # For details of the GNU LGPL, see the file "COPYING".
8
8
  #
9
9
  require 'securerandom'
10
+ require 'review/yamlloader'
10
11
 
11
12
  module ReVIEW
12
13
  class Configure < Hash
13
14
  attr_accessor :maker
14
15
 
15
- def self.values
16
+ def self.values # rubocop:disable Metrics/MethodLength
16
17
  conf = Configure[
17
18
  # These parameters can be overridden by YAML file.
18
- 'bookname' => 'example', # it defines epub file name also
19
+ 'bookname' => 'book', # it defines epub file name also
19
20
  'booktitle' => 'Re:VIEW Sample Book',
20
21
  'title' => nil,
21
22
  'aut' => nil, # author
@@ -31,8 +32,8 @@ module ReVIEW
31
32
  'date' => Time.now.strftime('%Y-%m-%d'), # publishing date
32
33
  'rights' => nil, # Copyright messages
33
34
  'description' => nil, # Description
34
- 'urnid' => "urn:uid:#{SecureRandom.uuid}", # Identifier
35
- 'stylesheet' => 'stylesheet.css', # stylesheet file
35
+ 'urnid' => "urn:uuid:#{SecureRandom.uuid}", # Identifier
36
+ 'stylesheet' => [], # stylesheet file
36
37
  'coverfile' => nil, # content file of body of cover page
37
38
  'mytoc' => nil, # whether make own table of contents or not
38
39
  'params' => '', # specify review2html parameters
@@ -45,8 +46,7 @@ module ReVIEW
45
46
  'debug' => nil, # debug flag
46
47
  'catalogfile' => 'catalog.yml',
47
48
  'language' => 'ja', # XXX default language should be JA??
48
- 'mathml' => nil, # for HTML
49
- 'imgmath' => nil, # for HTML
49
+ 'math_format' => nil,
50
50
  'htmlext' => 'html',
51
51
  'htmlversion' => 5,
52
52
  'contentdir' => '.',
@@ -63,8 +63,11 @@ module ReVIEW
63
63
  'image_types' => %w[.ai .psd .eps .pdf .tif .tiff .png .bmp .jpg .jpeg .gif .svg],
64
64
  'bib_file' => 'bib.re',
65
65
  'words_file' => nil,
66
- 'colophon_order' => %w[aut csl trl dsr ill cov edt pbl contact prt],
66
+ 'colophon_order' => %w[aut csl trl dsr ill cov edt pbl contact prt pht],
67
+ 'chapterlink' => true,
67
68
  'externallink' => true,
69
+ 'join_lines_by_lang' => nil, # experimental. default should be nil
70
+ 'table_row_separator' => 'tabs',
68
71
  # for IDGXML
69
72
  'tableopt' => nil,
70
73
  'listinfo' => nil,
@@ -73,22 +76,25 @@ module ReVIEW
73
76
  'structuredxml' => nil,
74
77
  'pt_to_mm_unit' => 0.3528, # DTP: 1pt = 0.3528mm, JIS: 1pt = 0.3514mm
75
78
  # for LaTeX
76
- 'image_scale2width' => true,
77
79
  'footnotetext' => nil,
78
80
  'texcommand' => 'uplatex',
79
- 'texoptions' => '-interaction=nonstopmode -file-line-error',
81
+ 'texoptions' => '-interaction=nonstopmode -file-line-error -halt-on-error',
80
82
  '_texdocumentclass' => ['review-jsbook', ''],
83
+ 'texstyle' => ['reviewmacro'],
81
84
  'dvicommand' => 'dvipdfmx',
82
85
  'dvioptions' => '-d 5 -z 9',
83
86
  # for PDFMaker
84
87
  'pdfmaker' => {
88
+ 'image_scale2width' => true,
85
89
  'makeindex' => nil, # Make index page
86
90
  'makeindex_command' => 'mendex', # works only when makeindex is true
87
91
  'makeindex_options' => '-f -r -I utf8',
88
92
  'makeindex_sty' => nil,
89
93
  'makeindex_dic' => nil,
90
94
  'makeindex_mecab' => true,
91
- 'makeindex_mecab_opts' => '-Oyomi'
95
+ 'makeindex_mecab_opts' => '-Oyomi',
96
+ 'use_cover_nombre' => true,
97
+ 'use_original_image_size' => nil
92
98
  },
93
99
  'imgmath_options' => {
94
100
  'format' => 'png',
@@ -99,14 +105,96 @@ module ReVIEW
99
105
  'preamble_file' => nil,
100
106
  'fontsize' => 10,
101
107
  'lineheight' => 10 * 1.2,
102
- 'pdfcrop_pixelize_cmd' => 'pdftocairo -png -r 90 -f %p -l %p -singlefile %i %O',
108
+ 'pdfcrop_pixelize_cmd' => 'pdftocairo -%t -r 90 -f %p -l %p -singlefile %i %O',
103
109
  'dvipng_cmd' => 'dvipng -T tight -z 9 -p %p -l %p -o %o %i'
110
+ },
111
+ 'caption_position' => {
112
+ 'list' => 'top',
113
+ 'image' => 'bottom',
114
+ 'table' => 'top',
115
+ 'equation' => 'top'
116
+ },
117
+ # for EPUBMaker
118
+ 'modified' => Time.now.utc.strftime('%Y-%02m-%02dT%02H:%02M:%02SZ'),
119
+ 'isbn' => nil,
120
+ 'titlefile' => nil,
121
+ 'originaltitlefile' => nil,
122
+ 'profile' => nil,
123
+ 'direction' => 'ltr',
124
+ 'image_maxpixels' => 4_000_000,
125
+ 'font_ext' => %w[ttf woff otf],
126
+ 'epubmaker' => {
127
+ 'flattoc' => nil,
128
+ 'flattocindent' => true,
129
+ 'ncx_indent' => [],
130
+ 'zip_stage1' => 'zip -0Xq',
131
+ 'zip_stage2' => 'zip -Xr9Dq',
132
+ 'zip_addpath' => nil,
133
+ 'hook_beforeprocess' => nil,
134
+ 'hook_afterfrontmatter' => nil,
135
+ 'hook_afterbody' => nil,
136
+ 'hook_afterbackmatter' => nil,
137
+ 'hook_aftercopyimage' => nil,
138
+ 'hook_prepack' => nil,
139
+ 'rename_for_legacy' => nil,
140
+ 'verify_target_images' => nil,
141
+ 'force_include_images' => [],
142
+ 'cover_linear' => nil,
143
+ 'back_footnote' => nil
104
144
  }
105
145
  ]
106
146
  conf.maker = nil
107
147
  conf
108
148
  end
109
149
 
150
+ def self.create(maker: nil, yamlfile: nil, config: nil)
151
+ conf = self.values
152
+ conf.maker = maker
153
+
154
+ if yamlfile
155
+ begin
156
+ loader = ReVIEW::YAMLLoader.new
157
+ conf.deep_merge!(loader.load_file(yamlfile))
158
+ rescue => e
159
+ raise ReVIEW::ConfigError, "yaml error #{e.message}"
160
+ end
161
+ end
162
+
163
+ # YAML configs will be overridden by command line options.
164
+ if config
165
+ conf.deep_merge!(config)
166
+ end
167
+
168
+ conf.migrate_parameters
169
+
170
+ conf
171
+ end
172
+
173
+ def migrate_parameters
174
+ # string to array
175
+ %w[subject aut
176
+ 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
177
+ 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
178
+ adp ann arr art asn aut aqt aft aui ant bkp clb cmm dsr edt
179
+ ill lyr mdc mus nrt oth pht pbl prt red rev spn ths trc trl
180
+ stylesheet rights].each do |item|
181
+ if self[item] && self[item].is_a?(String)
182
+ self[item] = [self[item]]
183
+ end
184
+ end
185
+
186
+ # backward compatibility
187
+ if self['mathml']
188
+ warn '"mathml: true" is obsoleted. Please use "math_format: mathml"'
189
+ self['math_format'] = 'mathml'
190
+ end
191
+
192
+ if self['imgmath']
193
+ warn '"imgmath: true" is obsoleted. Please use "math_format: imgmath"'
194
+ self['math_format'] = 'imgmath'
195
+ end
196
+ end
197
+
110
198
  def [](key)
111
199
  maker = self.maker
112
200
  if maker && self.key?(maker) && self.fetch(maker) && self.fetch(maker).key?(key)
@@ -115,6 +203,7 @@ module ReVIEW
115
203
  if self.key?(key)
116
204
  return self.fetch(key)
117
205
  end
206
+
118
207
  nil
119
208
  end
120
209
 
@@ -17,7 +17,7 @@ module ReVIEW
17
17
  chap_name = File.basename(file, '.*')
18
18
  chap = @book.chapter(chap_name)
19
19
  result = @compiler.compile(chap)
20
- File.open(output_path, 'w') { |f| f.puts result }
20
+ File.write(output_path, result)
21
21
  end
22
22
  end
23
23
  end
@@ -8,10 +8,15 @@
8
8
 
9
9
  require 'zip'
10
10
  require 'rexml/document'
11
- require 'cgi'
12
11
  require 'optparse'
13
12
  require 'review/version'
14
13
 
14
+ begin
15
+ require 'cgi/escape'
16
+ rescue
17
+ require 'cgi/util'
18
+ end
19
+
15
20
  module ReVIEW
16
21
  class Epub2Html
17
22
  def self.execute(*args)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010-2019 Kenshi Muto and Masayoshi Takahashi
1
+ # Copyright (c) 2010-2021 Kenshi Muto and Masayoshi Takahashi
2
2
  #
3
3
  # This program is free software.
4
4
  # You can distribute or modify this program under the terms of
@@ -13,59 +13,48 @@ require 'review/book'
13
13
  require 'review/configure'
14
14
  require 'review/converter'
15
15
  require 'review/latexbuilder'
16
- require 'review/yamlloader'
17
16
  require 'review/version'
18
17
  require 'review/htmltoc'
19
18
  require 'review/htmlbuilder'
19
+ require 'review/img_math'
20
20
 
21
- require 'review/yamlloader'
22
21
  require 'rexml/document'
23
22
  require 'rexml/streamlistener'
24
- require 'epubmaker'
23
+ require 'review/call_hook'
24
+ require 'review/epubmaker/producer'
25
+ require 'review/epubmaker/content'
26
+ require 'review/epubmaker/epubv2'
27
+ require 'review/epubmaker/epubv3'
25
28
  require 'review/epubmaker/reviewheaderlistener'
26
29
  require 'review/makerhelper'
27
30
 
28
31
  module ReVIEW
29
32
  class EPUBMaker
30
- include ::EPUBMaker
31
- include REXML
32
33
  include MakerHelper
34
+ include ReVIEW::CallHook
33
35
 
34
36
  def initialize
35
37
  @producer = nil
36
38
  @htmltoc = nil
37
39
  @buildlogtxt = 'build-log.txt'
38
40
  @logger = ReVIEW.logger
41
+ @img_math = nil
42
+ @basedir = nil
39
43
  end
40
44
 
41
45
  def error(msg)
42
- @logger.error "#{File.basename($PROGRAM_NAME, '.*')}: #{msg}"
46
+ @logger.error msg
43
47
  exit 1
44
48
  end
45
49
 
46
50
  def warn(msg)
47
- @logger.warn "#{File.basename($PROGRAM_NAME, '.*')}: #{msg}"
51
+ @logger.warn msg
48
52
  end
49
53
 
50
54
  def log(msg)
51
55
  @logger.debug(msg)
52
56
  end
53
57
 
54
- def load_yaml(yamlfile)
55
- loader = ReVIEW::YAMLLoader.new
56
- @config = ReVIEW::Configure.values
57
- begin
58
- @config.deep_merge!(loader.load_file(yamlfile))
59
- rescue => e
60
- error "yaml error #{e.message}"
61
- end
62
-
63
- @producer = Producer.new(@config)
64
- @producer.load(yamlfile)
65
- @config = @producer.config
66
- @config.maker = 'epubmaker'
67
- end
68
-
69
58
  def self.execute(*args)
70
59
  self.new.execute(*args)
71
60
  end
@@ -73,6 +62,7 @@ module ReVIEW
73
62
  def parse_opts(args)
74
63
  cmd_config = {}
75
64
  opts = OptionParser.new
65
+ @buildonly = nil
76
66
 
77
67
  opts.banner = 'Usage: review-epubmaker [options] configfile [export_filename]'
78
68
  opts.version = ReVIEW::VERSION
@@ -81,6 +71,7 @@ module ReVIEW
81
71
  exit 0
82
72
  end
83
73
  opts.on('--[no-]debug', 'Keep temporary files.') { |debug| cmd_config['debug'] = debug }
74
+ opts.on('-y', '--only file1,file2,...', 'Build only specified files.') { |v| @buildonly = v.split(/\s*,\s*/).map { |m| m.strip.sub(/\.re\Z/, '') } }
84
75
 
85
76
  opts.parse!(args)
86
77
  if args.size < 1 || args.size > 2
@@ -92,23 +83,29 @@ module ReVIEW
92
83
  end
93
84
 
94
85
  def execute(*args)
95
- @config = ReVIEW::Configure.values
96
- @config.maker = 'epubmaker'
97
86
  cmd_config, yamlfile, exportfile = parse_opts(args)
98
87
  error "#{yamlfile} not found." unless File.exist?(yamlfile)
99
88
 
100
- load_yaml(yamlfile)
101
- @config.deep_merge!(cmd_config)
89
+ @config = ReVIEW::Configure.create(maker: 'epubmaker',
90
+ yamlfile: yamlfile,
91
+ config: cmd_config)
92
+ @producer = ReVIEW::EPUBMaker::Producer.new(@config)
102
93
  update_log_level
103
94
  log("Loaded yaml file (#{yamlfile}).")
95
+ @basedir = File.absolute_path(File.dirname(yamlfile))
104
96
 
105
97
  produce(yamlfile, exportfile)
106
98
  end
107
99
 
108
100
  def update_log_level
109
101
  if @config['debug']
110
- @logger.level = Logger::DEBUG
111
- else
102
+ if @logger.ttylogger?
103
+ ReVIEW.logger = nil
104
+ @logger = ReVIEW.logger(level: 'debug')
105
+ else
106
+ @logger.level = Logger::DEBUG
107
+ end
108
+ elsif !@logger.ttylogger?
112
109
  @logger.level = Logger::INFO
113
110
  end
114
111
  end
@@ -131,6 +128,7 @@ module ReVIEW
131
128
  bookname ||= @config['bookname']
132
129
  booktmpname = "#{bookname}-epub"
133
130
 
131
+ @img_math = ReVIEW::ImgMath.new(@config)
134
132
  begin
135
133
  @config.check_version(ReVIEW::VERSION)
136
134
  rescue ReVIEW::ConfigError => e
@@ -143,31 +141,30 @@ module ReVIEW
143
141
  FileUtils.rm_rf(booktmpname)
144
142
  end
145
143
 
146
- cleanup_mathimg
144
+ @img_math.cleanup_mathimg
147
145
 
148
146
  basetmpdir = build_path
149
147
  begin
150
148
  log("Created first temporary directory as #{basetmpdir}.")
151
149
 
152
- call_hook('hook_beforeprocess', basetmpdir)
150
+ call_hook('hook_beforeprocess', basetmpdir, base_dir: @basedir)
153
151
 
154
152
  @htmltoc = ReVIEW::HTMLToc.new(basetmpdir)
155
153
  ## copy all files into basetmpdir
156
154
  copy_stylesheet(basetmpdir)
157
155
 
158
156
  copy_frontmatter(basetmpdir)
159
- call_hook('hook_afterfrontmatter', basetmpdir)
157
+ call_hook('hook_afterfrontmatter', basetmpdir, base_dir: @basedir)
160
158
 
161
159
  build_body(basetmpdir, yamlfile)
162
- call_hook('hook_afterbody', basetmpdir)
160
+ call_hook('hook_afterbody', basetmpdir, base_dir: @basedir)
163
161
 
164
162
  copy_backmatter(basetmpdir)
165
163
 
166
- math_dir = "./#{@config['imagedir']}/_review_math"
167
- if @config['imgmath'] && File.exist?(File.join(math_dir, '__IMGMATH_BODY__.tex'))
168
- make_math_images(math_dir)
164
+ if @config['math_format'] == 'imgmath'
165
+ @img_math.make_math_images
169
166
  end
170
- call_hook('hook_afterbackmatter', basetmpdir)
167
+ call_hook('hook_afterbackmatter', basetmpdir, base_dir: @basedir)
171
168
 
172
169
  ## push contents in basetmpdir into @producer
173
170
  push_contents(basetmpdir)
@@ -183,7 +180,7 @@ module ReVIEW
183
180
  copy_resources('adv', File.join(basetmpdir, @config['imagedir']))
184
181
  copy_resources(@config['fontdir'], File.join(basetmpdir, 'fonts'), @config['font_ext'])
185
182
 
186
- call_hook('hook_aftercopyimage', basetmpdir)
183
+ call_hook('hook_aftercopyimage', basetmpdir, base_dir: @basedir)
187
184
 
188
185
  @producer.import_imageinfo(File.join(basetmpdir, @config['imagedir']), basetmpdir)
189
186
  @producer.import_imageinfo(File.join(basetmpdir, 'fonts'), basetmpdir, @config['font_ext'])
@@ -196,34 +193,24 @@ module ReVIEW
196
193
  Dir.mkdir(epubtmpdir)
197
194
  end
198
195
  log('Call ePUB producer.')
199
- @producer.produce("#{bookname}.epub", basetmpdir, epubtmpdir)
196
+ @producer.produce("#{bookname}.epub", basetmpdir, epubtmpdir, base_dir: @basedir)
200
197
  log('Finished.')
198
+ @logger.success("built #{bookname}.epub")
201
199
  rescue ApplicationError => e
202
200
  raise if @config['debug']
201
+
203
202
  error(e.message)
204
203
  ensure
205
204
  FileUtils.remove_entry_secure(basetmpdir) unless @config['debug']
206
205
  end
207
206
  end
208
207
 
209
- def call_hook(hook_name, *params)
210
- filename = @config['epubmaker'][hook_name]
211
- log("Call #{hook_name}. (#{filename})")
212
- if filename.present? && File.exist?(filename) && FileTest.executable?(filename)
213
- if ENV['REVIEW_SAFE_MODE'].to_i & 1 > 0
214
- warn 'hook is prohibited in safe mode. ignored.'
215
- else
216
- system(filename, *params)
217
- end
218
- end
219
- end
220
-
221
208
  def verify_target_images(basetmpdir)
222
209
  @producer.contents.each do |content|
223
210
  case content.media
224
211
  when 'application/xhtml+xml'
225
212
  File.open("#{basetmpdir}/#{content.file}") do |f|
226
- Document.new(File.new(f)).each_element('//img') do |e|
213
+ REXML::Document.new(File.new(f)).each_element('//img') do |e|
227
214
  @config['epubmaker']['force_include_images'].push(e.attributes['src'])
228
215
  if e.attributes['src'] =~ /svg\Z/i
229
216
  content.properties.push('svg')
@@ -245,12 +232,13 @@ module ReVIEW
245
232
 
246
233
  def copy_images(resdir, destdir, allow_exts = nil)
247
234
  return nil unless File.exist?(resdir)
235
+
248
236
  allow_exts ||= @config['image_ext']
249
237
  FileUtils.mkdir_p(destdir)
250
238
  if @config['epubmaker']['verify_target_images'].present?
251
239
  @config['epubmaker']['force_include_images'].each do |file|
252
240
  unless File.exist?(file)
253
- if file !~ /\Ahttp[s]?:/
241
+ if file !~ /\Ahttps?:/
254
242
  warn "#{file} is not found, skip."
255
243
  end
256
244
  next
@@ -267,6 +255,7 @@ module ReVIEW
267
255
 
268
256
  def copy_resources(resdir, destdir, allow_exts = nil)
269
257
  return nil unless File.exist?(resdir)
258
+
270
259
  allow_exts ||= @config['image_ext']
271
260
  FileUtils.mkdir_p(destdir)
272
261
  recursive_copy_files(resdir, destdir, allow_exts)
@@ -276,6 +265,7 @@ module ReVIEW
276
265
  Dir.open(resdir) do |dir|
277
266
  dir.each do |fname|
278
267
  next if fname.start_with?('.')
268
+
279
269
  if FileTest.directory?(File.join(resdir, fname))
280
270
  recursive_copy_files(File.join(resdir, fname), File.join(destdir, fname), allow_exts)
281
271
  elsif fname =~ /\.(#{allow_exts.join('|')})\Z/i
@@ -305,9 +295,8 @@ module ReVIEW
305
295
 
306
296
  basedir = File.dirname(yamlfile)
307
297
  base_path = Pathname.new(basedir)
308
- book = ReVIEW::Book.load(basedir)
309
- book.config = @config
310
- @converter = ReVIEW::Converter.new(book, ReVIEW::HTMLBuilder.new)
298
+ book = ReVIEW::Book::Base.new(basedir, config: @config)
299
+ @converter = ReVIEW::Converter.new(book, ReVIEW::HTMLBuilder.new(img_math: @img_math))
311
300
  @compile_errors = nil
312
301
 
313
302
  book.parts.each do |part|
@@ -336,19 +325,13 @@ module ReVIEW
336
325
  def build_part(part, basetmpdir, htmlfile)
337
326
  log("Create #{htmlfile} from a template.")
338
327
  File.open(File.join(basetmpdir, htmlfile), 'w') do |f|
339
- @body = ''
340
- @body << %Q(<div class="part">\n)
341
- @body << %Q(<h1 class="part-number">#{CGI.escapeHTML(ReVIEW::I18n.t('part', part.number))}</h1>\n)
342
- if part.name.strip.present?
343
- @body << %Q(<h2 class="part-title">#{CGI.escapeHTML(part.name.strip)}</h2>\n)
344
- end
345
- @body << %Q(</div>\n)
328
+ @part_number = part.number
329
+ @part_title = part.name.strip
330
+ @body = ReVIEW::Template.generate(path: 'html/_part_body.html.erb', binding: binding)
346
331
 
347
332
  @language = @producer.config['language']
348
333
  @stylesheets = @producer.config['stylesheet']
349
- tmplfile = File.expand_path(template_name, ReVIEW::Template::TEMPLATE_DIR)
350
- tmpl = ReVIEW::Template.load(tmplfile)
351
- f.write tmpl.result(binding)
334
+ f.write ReVIEW::Template.generate(path: template_name, binding: binding)
352
335
  end
353
336
  end
354
337
 
@@ -394,6 +377,11 @@ module ReVIEW
394
377
  end
395
378
  end
396
379
 
380
+ if @buildonly && !@buildonly.include?(id)
381
+ warn "skip #{id}.re"
382
+ return
383
+ end
384
+
397
385
  htmlfile = "#{id}.#{@config['htmlext']}"
398
386
  write_buildlogtxt(basetmpdir, htmlfile, filename)
399
387
  log("Create #{htmlfile} from #{filename}.")
@@ -440,11 +428,25 @@ module ReVIEW
440
428
  properties
441
429
  end
442
430
 
443
- def write_info_body(basetmpdir, _id, filename, ispart = nil, chaptype = nil)
431
+ def parse_headlines(path)
444
432
  headlines = []
433
+
434
+ File.open(path) do |htmlio|
435
+ REXML::Document.parse_stream(htmlio, ReVIEWHeaderListener.new(headlines))
436
+ end
437
+
438
+ headlines
439
+ end
440
+
441
+ def write_info_body(basetmpdir, _id, filename, ispart = nil, chaptype = nil)
445
442
  path = File.join(basetmpdir, filename)
446
- htmlio = File.new(path)
447
- Document.parse_stream(htmlio, ReVIEWHeaderListener.new(headlines))
443
+ headlines = parse_headlines(path)
444
+
445
+ if headlines.empty?
446
+ warn "#{filename} is discarded because there is no heading. Use `=[notoc]' or `=[nodisp]' to exclude headlines from the table of contents."
447
+ return
448
+ end
449
+
448
450
  properties = detect_properties(path)
449
451
  if properties.present?
450
452
  prop_str = ',properties=' + properties.join(' ')
@@ -472,73 +474,82 @@ module ReVIEW
472
474
  first = nil
473
475
  end
474
476
  end
475
- htmlio.close
476
477
  end
477
478
 
478
479
  def push_contents(_basetmpdir)
479
480
  @htmltoc.each_item do |level, file, title, args|
480
481
  next if level.to_i > @config['toclevel'] && args[:force_include].nil?
482
+
481
483
  log("Push #{file} to ePUB contents.")
482
484
 
483
- hash = { 'file' => file,
484
- 'level' => level.to_i,
485
- 'title' => title,
486
- 'chaptype' => args[:chaptype] }
485
+ params = { file: file,
486
+ level: level.to_i,
487
+ title: title,
488
+ chaptype: args[:chaptype] }
487
489
  if args[:id].present?
488
- hash['id'] = args[:id]
490
+ params[:id] = args[:id]
489
491
  end
490
492
  if args[:properties].present?
491
- hash['properties'] = args[:properties].split(' ')
493
+ params[:properties] = args[:properties].split(' ') # rubocop:disable Style/RedundantArgument
492
494
  end
493
495
  if args[:notoc].present?
494
- hash['notoc'] = args[:notoc]
496
+ params[:notoc] = args[:notoc]
495
497
  end
496
- @producer.contents.push(Content.new(hash))
498
+ @producer.contents.push(ReVIEW::EPUBMaker::Content.new(**params))
497
499
  end
498
500
  end
499
501
 
500
502
  def copy_stylesheet(basetmpdir)
501
503
  return if @config['stylesheet'].empty?
504
+
502
505
  @config['stylesheet'].each do |sfile|
506
+ unless File.exist?(sfile)
507
+ error "stylesheet: #{sfile} is not found."
508
+ end
503
509
  FileUtils.cp(sfile, basetmpdir)
504
- @producer.contents.push(Content.new('file' => sfile))
510
+ @producer.contents.push(ReVIEW::EPUBMaker::Content.new(file: sfile))
511
+ end
512
+ end
513
+
514
+ def copy_static_file(configname, destdir, destfilename: nil)
515
+ destfilename ||= @config[configname]
516
+ unless File.exist?(@config[configname])
517
+ error "#{configname}: #{@config[configname]} is not found."
505
518
  end
519
+ FileUtils.cp(@config[configname],
520
+ File.join(destdir, destfilename))
506
521
  end
507
522
 
508
523
  def copy_frontmatter(basetmpdir)
509
524
  if @config['cover'].present? && File.exist?(@config['cover'])
510
- FileUtils.cp(@config['cover'],
511
- File.join(basetmpdir, File.basename(@config['cover'])))
525
+ copy_static_file('cover', basetmpdir)
512
526
  end
513
527
 
514
528
  if @config['titlepage']
515
529
  if @config['titlefile'].nil?
516
530
  build_titlepage(basetmpdir, "titlepage.#{@config['htmlext']}")
517
531
  else
518
- FileUtils.cp(@config['titlefile'],
519
- File.join(basetmpdir, "titlepage.#{@config['htmlext']}"))
532
+ copy_static_file('titlefile', basetmpdir, destfilename: "titlepage.#{@config['htmlext']}")
520
533
  end
521
534
  @htmltoc.add_item(1,
522
535
  "titlepage.#{@config['htmlext']}",
523
- @producer.res.v('titlepagetitle'),
536
+ ReVIEW::I18n.t('titlepagetitle'),
524
537
  chaptype: 'pre')
525
538
  end
526
539
 
527
- if @config['originaltitlefile'].present? && File.exist?(@config['originaltitlefile'])
528
- FileUtils.cp(@config['originaltitlefile'],
529
- File.join(basetmpdir, File.basename(@config['originaltitlefile'])))
540
+ if @config['originaltitlefile'].present?
541
+ copy_static_file('originaltitlefile', basetmpdir)
530
542
  @htmltoc.add_item(1,
531
543
  File.basename(@config['originaltitlefile']),
532
- @producer.res.v('originaltitle'),
544
+ ReVIEW::I18n.t('originaltitle'),
533
545
  chaptype: 'pre')
534
546
  end
535
547
 
536
- if @config['creditfile'].present? && File.exist?(@config['creditfile'])
537
- FileUtils.cp(@config['creditfile'],
538
- File.join(basetmpdir, File.basename(@config['creditfile'])))
548
+ if @config['creditfile'].present?
549
+ copy_static_file('creditfile', basetmpdir)
539
550
  @htmltoc.add_item(1,
540
551
  File.basename(@config['creditfile']),
541
- @producer.res.v('credittitle'),
552
+ ReVIEW::I18n.t('credittitle'),
542
553
  chaptype: 'pre')
543
554
  end
544
555
 
@@ -547,71 +558,60 @@ module ReVIEW
547
558
 
548
559
  def build_titlepage(basetmpdir, htmlfile)
549
560
  # TODO: should be created via epubcommon
550
- @title = CGI.escapeHTML(@config.name_of('booktitle'))
561
+ @title = h(@config.name_of('booktitle'))
551
562
  File.open(File.join(basetmpdir, htmlfile), 'w') do |f|
552
563
  @body = ''
553
564
  @body << %Q(<div class="titlepage">\n)
554
- @body << %Q(<h1 class="tp-title">#{CGI.escapeHTML(@config.name_of('booktitle'))}</h1>\n)
565
+ @body << %Q(<h1 class="tp-title">#{h(@config.name_of('booktitle'))}</h1>\n)
555
566
  if @config['subtitle']
556
- @body << %Q(<h2 class="tp-subtitle">#{CGI.escapeHTML(@config.name_of('subtitle'))}</h2>\n)
567
+ @body << %Q(<h2 class="tp-subtitle">#{h(@config.name_of('subtitle'))}</h2>\n)
557
568
  end
558
569
  if @config['aut']
559
- @body << %Q(<h2 class="tp-author">#{CGI.escapeHTML(@config.names_of('aut').join(ReVIEW::I18n.t('names_splitter')))}</h2>\n)
570
+ @body << %Q(<h2 class="tp-author">#{h(@config.names_of('aut').join(ReVIEW::I18n.t('names_splitter')))}</h2>\n)
560
571
  end
561
572
  if @config['pbl']
562
- @body << %Q(<h3 class="tp-publisher">#{CGI.escapeHTML(@config.names_of('pbl').join(ReVIEW::I18n.t('names_splitter')))}</h3>\n)
573
+ @body << %Q(<h3 class="tp-publisher">#{h(@config.names_of('pbl').join(ReVIEW::I18n.t('names_splitter')))}</h3>\n)
563
574
  end
564
575
  @body << '</div>'
565
576
 
566
577
  @language = @producer.config['language']
567
578
  @stylesheets = @producer.config['stylesheet']
568
- tmplfile = File.expand_path(template_name, ReVIEW::Template::TEMPLATE_DIR)
569
- tmpl = ReVIEW::Template.load(tmplfile)
570
- f.write tmpl.result(binding)
579
+ f.write ReVIEW::Template.generate(path: template_name, binding: binding)
571
580
  end
572
581
  end
573
582
 
574
583
  def copy_backmatter(basetmpdir)
575
584
  if @config['profile']
576
- FileUtils.cp(@config['profile'],
577
- File.join(basetmpdir, File.basename(@config['profile'])))
585
+ copy_static_file('profile', basetmpdir)
578
586
  @htmltoc.add_item(1,
579
587
  File.basename(@config['profile']),
580
- @producer.res.v('profiletitle'),
588
+ ReVIEW::I18n.t('profiletitle'),
581
589
  chaptype: 'post')
582
590
  end
583
591
 
584
592
  if @config['advfile']
585
- FileUtils.cp(@config['advfile'],
586
- File.join(basetmpdir, File.basename(@config['advfile'])))
593
+ copy_static_file('advfile', basetmpdir)
587
594
  @htmltoc.add_item(1,
588
595
  File.basename(@config['advfile']),
589
- @producer.res.v('advtitle'),
596
+ ReVIEW::I18n.t('advtitle'),
590
597
  chaptype: 'post')
591
598
  end
592
599
 
593
600
  if @config['colophon']
594
- if @config['colophon'].is_a?(String) # FIXME: should let obsolete this style?
595
- FileUtils.cp(@config['colophon'],
596
- File.join(basetmpdir, "colophon.#{@config['htmlext']}"))
597
- else
598
- filename = File.join(basetmpdir, "colophon.#{@config['htmlext']}")
599
- File.open(filename, 'w') do |f|
600
- @producer.colophon(f)
601
- end
601
+ if @config['colophon'].is_a?(String)
602
+ copy_static_file('colophon', basetmpdir, destfilename: "colophon.#{@config['htmlext']}") # override pre-built colophon
602
603
  end
603
604
  @htmltoc.add_item(1,
604
605
  "colophon.#{@config['htmlext']}",
605
- @producer.res.v('colophontitle'),
606
+ ReVIEW::I18n.t('colophontitle'),
606
607
  chaptype: 'post')
607
608
  end
608
609
 
609
610
  if @config['backcover']
610
- FileUtils.cp(@config['backcover'],
611
- File.join(basetmpdir, File.basename(@config['backcover'])))
611
+ copy_static_file('backcover', basetmpdir)
612
612
  @htmltoc.add_item(1,
613
613
  File.basename(@config['backcover']),
614
- @producer.res.v('backcovertitle'),
614
+ ReVIEW::I18n.t('backcovertitle'),
615
615
  chaptype: 'post')
616
616
  end
617
617
 
@@ -637,8 +637,10 @@ module ReVIEW
637
637
  extre = Regexp.new(pat, Regexp::IGNORECASE)
638
638
  Find.find(basetmpdir) do |fname|
639
639
  next unless fname.match(extre)
640
+
640
641
  img = ImageSize.path(fname)
641
642
  next if img.width.nil? || img.width * img.height <= maxpixels
643
+
642
644
  h = Math.sqrt(img.height * maxpixels / img.width)
643
645
  w = maxpixels / h
644
646
  fname.sub!("#{basetmpdir}/", '')