review 5.0.0 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-tex.yml +31 -0
  3. data/.github/workflows/ruby-win.yml +3 -3
  4. data/.github/workflows/ruby.yml +1 -1
  5. data/.rubocop.yml +15 -7
  6. data/NEWS.ja.md +108 -0
  7. data/NEWS.md +108 -0
  8. data/README.md +7 -6
  9. data/Rakefile +7 -2
  10. data/bin/review +2 -4
  11. data/bin/review-catalog-converter +3 -3
  12. data/bin/review-check +6 -8
  13. data/bin/review-checkdep +1 -4
  14. data/bin/review-compile +2 -5
  15. data/bin/review-epub2html +1 -4
  16. data/bin/review-epubmaker +3 -4
  17. data/bin/review-idgxmlmaker +1 -3
  18. data/bin/review-index +11 -5
  19. data/bin/review-init +1 -4
  20. data/bin/review-pdfmaker +1 -3
  21. data/bin/review-preproc +2 -4
  22. data/bin/review-textmaker +1 -3
  23. data/bin/review-update +1 -4
  24. data/bin/review-validate +3 -3
  25. data/bin/review-vol +1 -4
  26. data/bin/review-webmaker +1 -3
  27. data/doc/config.yml.sample +21 -5
  28. data/doc/config.yml.sample-simple +1 -1
  29. data/doc/format.ja.md +21 -10
  30. data/doc/format.md +21 -10
  31. data/doc/quickstart.ja.md +11 -1
  32. data/doc/quickstart.md +11 -2
  33. data/lib/review.rb +1 -1
  34. data/lib/review/book/base.rb +4 -0
  35. data/lib/review/book/book_unit.rb +3 -0
  36. data/lib/review/book/chapter.rb +3 -0
  37. data/lib/review/book/index.rb +1 -0
  38. data/lib/review/book/volume.rb +1 -0
  39. data/lib/review/builder.rb +8 -1
  40. data/lib/review/call_hook.rb +20 -0
  41. data/lib/review/catalog.rb +1 -0
  42. data/lib/review/compiler.rb +27 -10
  43. data/lib/review/configure.rb +64 -7
  44. data/lib/review/epubmaker.rb +93 -96
  45. data/lib/review/epubmaker/content.rb +113 -0
  46. data/lib/review/epubmaker/epubcommon.rb +372 -0
  47. data/lib/review/epubmaker/epubv2.rb +178 -0
  48. data/lib/review/epubmaker/epubv3.rb +231 -0
  49. data/lib/review/epubmaker/producer.rb +168 -0
  50. data/lib/review/epubmaker/reviewheaderlistener.rb +12 -2
  51. data/lib/review/epubmaker/zip_exporter.rb +84 -0
  52. data/lib/review/exception.rb +6 -0
  53. data/lib/review/htmlbuilder.rb +36 -49
  54. data/lib/review/htmlutils.rb +1 -1
  55. data/lib/review/i18n.rb +1 -0
  56. data/lib/review/idgxmlbuilder.rb +33 -30
  57. data/lib/review/idgxmlmaker.rb +3 -1
  58. data/lib/review/img_math.rb +245 -0
  59. data/lib/review/index_builder.rb +1 -0
  60. data/lib/review/init.rb +4 -4
  61. data/lib/review/latexbox.rb +58 -0
  62. data/lib/review/latexbuilder.rb +30 -19
  63. data/lib/review/latexutils.rb +9 -1
  64. data/lib/review/lineinput.rb +112 -2
  65. data/lib/review/logger.rb +41 -2
  66. data/lib/review/makerhelper.rb +2 -205
  67. data/lib/review/markdownbuilder.rb +32 -1
  68. data/lib/review/pdfmaker.rb +31 -29
  69. data/lib/review/plaintextbuilder.rb +9 -1
  70. data/lib/review/preprocessor.rb +12 -6
  71. data/lib/review/rstbuilder.rb +1 -1
  72. data/lib/review/sec_counter.rb +1 -0
  73. data/lib/review/template.rb +6 -0
  74. data/lib/review/textmaker.rb +11 -7
  75. data/lib/review/textutils.rb +2 -10
  76. data/lib/review/tocprinter.rb +85 -68
  77. data/lib/review/topbuilder.rb +18 -11
  78. data/lib/review/update.rb +5 -6
  79. data/lib/review/version.rb +1 -1
  80. data/lib/review/volumeprinter.rb +4 -5
  81. data/lib/review/webmaker.rb +18 -13
  82. data/lib/review/webtocprinter.rb +10 -9
  83. data/lib/review/yamlloader.rb +2 -1
  84. data/review.gemspec +5 -3
  85. data/samples/sample-book/src/config-epub2.yml +1 -1
  86. data/samples/sample-book/src/config.yml +1 -1
  87. data/samples/sample-book/src/lib/tasks/review.rake +17 -1
  88. data/samples/syntax-book/ch01.re +1 -1
  89. data/samples/syntax-book/ch02.re +21 -6
  90. data/samples/syntax-book/ch03.re +1 -1
  91. data/samples/syntax-book/images/img3-2.png +0 -0
  92. data/templates/html/_colophon.html.erb +23 -0
  93. data/templates/html/_colophon_history.html.erb +9 -0
  94. data/templates/html/_cover.html.erb +10 -0
  95. data/templates/html/_part_body.html.erb +6 -0
  96. data/templates/html/_titlepage.html.erb +20 -0
  97. data/templates/html/layout-html5.html.erb +6 -0
  98. data/templates/html/layout-xhtml1.html.erb +6 -0
  99. data/templates/latex/config.erb +8 -0
  100. data/templates/latex/review-jlreq/review-base.sty +4 -5
  101. data/templates/latex/review-jlreq/review-jlreq.cls +10 -2
  102. data/templates/latex/review-jlreq/review-style.sty +6 -1
  103. data/templates/latex/review-jlreq/review-tcbox.sty +348 -0
  104. data/templates/latex/review-jlreq/reviewmacro.sty +5 -0
  105. data/templates/latex/review-jsbook/review-base.sty +5 -7
  106. data/templates/latex/review-jsbook/review-jsbook.cls +10 -2
  107. data/templates/latex/review-jsbook/review-style.sty +6 -1
  108. data/templates/latex/review-jsbook/review-tcbox.sty +348 -0
  109. data/templates/latex/review-jsbook/reviewmacro.sty +5 -0
  110. data/templates/opf/epubv2.opf.erb +7 -7
  111. data/templates/opf/epubv3.opf.erb +7 -7
  112. data/templates/opf/opf_manifest_epubv2.opf.erb +10 -0
  113. data/templates/opf/opf_manifest_epubv3.opf.erb +10 -0
  114. data/templates/opf/opf_metainfo_epubv2.opf.erb +17 -0
  115. data/templates/opf/opf_metainfo_epubv3.opf.erb +49 -0
  116. data/templates/opf/opf_tocx_epubv2.opf.erb +9 -0
  117. data/templates/opf/opf_tocx_epubv3.opf.erb +17 -0
  118. data/templates/web/html/layout-html5.html.erb +6 -5
  119. data/templates/web/html/layout-xhtml1.html.erb +6 -0
  120. data/test/assets/header_listener.html +35 -0
  121. data/test/assets/img_math/img1.png +0 -0
  122. data/test/assets/img_math/img2.png +0 -0
  123. data/test/assets/img_math/img3.png +0 -0
  124. data/test/assets/syntax_book_index_detail.txt +58 -0
  125. data/test/assets/test_template.tex +4 -1
  126. data/test/assets/test_template_backmatter.tex +4 -1
  127. data/test/run_test.rb +1 -1
  128. data/test/test_book_chapter.rb +2 -2
  129. data/test/test_catalog_converter_cmd.rb +1 -1
  130. data/test/test_epub3maker.rb +168 -124
  131. data/test/test_epubmaker.rb +243 -131
  132. data/test/test_epubmaker_cmd.rb +2 -2
  133. data/test/test_helper.rb +5 -4
  134. data/test/test_htmlbuilder.rb +64 -6
  135. data/test/test_idgxmlbuilder.rb +13 -0
  136. data/test/test_idgxmlmaker_cmd.rb +7 -3
  137. data/test/test_img_math.rb +111 -0
  138. data/test/test_indexbuilder.rb +5 -5
  139. data/test/test_latexbuilder.rb +107 -4
  140. data/test/test_lineinput.rb +20 -93
  141. data/test/test_markdownbuilder.rb +29 -0
  142. data/test/test_pdfmaker.rb +71 -0
  143. data/test/test_pdfmaker_cmd.rb +2 -2
  144. data/test/test_plaintextbuilder.rb +10 -18
  145. data/test/test_reviewheaderlistener.rb +49 -0
  146. data/test/test_template.rb +12 -2
  147. data/test/test_textmaker_cmd.rb +5 -1
  148. data/test/test_tocprinter.rb +46 -0
  149. data/test/test_topbuilder.rb +6 -1
  150. data/test/test_update.rb +34 -34
  151. data/test/test_zip_exporter.rb +5 -6
  152. metadata +91 -17
  153. data/lib/epubmaker.rb +0 -23
  154. data/lib/epubmaker/content.rb +0 -111
  155. data/lib/epubmaker/epubcommon.rb +0 -449
  156. data/lib/epubmaker/epubv2.rb +0 -142
  157. data/lib/epubmaker/epubv3.rb +0 -235
  158. data/lib/epubmaker/producer.rb +0 -375
  159. data/lib/epubmaker/zip_exporter.rb +0 -81
  160. data/lib/lineinput.rb +0 -155
@@ -1,142 +0,0 @@
1
- # = epubv2.rb -- EPUB version 2 producer.
2
- #
3
- # Copyright (c) 2010-2017 Kenshi Muto and Masayoshi Takahashi
4
- #
5
- # This program is free software.
6
- # You can distribute or modify this program under the terms of
7
- # the GNU LGPL, Lesser General Public License version 2.1.
8
- # For details of the GNU LGPL, see the file "COPYING".
9
- #
10
-
11
- require 'epubmaker/epubcommon'
12
- require 'epubmaker/zip_exporter'
13
-
14
- module EPUBMaker
15
- # EPUBv2 is EPUB version 2 producer.
16
- class EPUBv2 < EPUBCommon
17
- # Construct object with parameter hash +config+ and message resource hash +res+.
18
- def initialize(producer) # rubocop:disable Lint/UselessMethodDefinition
19
- super
20
- end
21
-
22
- # Return opf file content.
23
- def opf
24
- @opf_metainfo = opf_metainfo
25
- @opf_coverimage = opf_coverimage
26
- @opf_manifest = opf_manifest
27
- @opf_toc = opf_tocx
28
-
29
- tmplfile = File.expand_path('./opf/epubv2.opf.erb', ReVIEW::Template::TEMPLATE_DIR)
30
- tmpl = ReVIEW::Template.load(tmplfile)
31
- tmpl.result(binding)
32
- end
33
-
34
- def opf_metainfo
35
- s = ''
36
- %w[title language date type format source description relation coverage subject rights].each do |item|
37
- next unless @producer.config[item]
38
- if @producer.config[item].is_a?(Array)
39
- s << @producer.config.names_of(item).map { |i| %Q( <dc:#{item}>#{h(i)}</dc:#{item}>\n) }.join
40
- else
41
- s << %Q( <dc:#{item}>#{h(@producer.config.name_of(item).to_s)}</dc:#{item}>\n)
42
- end
43
- end
44
-
45
- # ID
46
- if @producer.config['isbn'].nil?
47
- s << %Q( <dc:identifier id="BookId">#{@producer.config['urnid']}</dc:identifier>\n)
48
- else
49
- s << %Q( <dc:identifier id="BookId" opf:scheme="ISBN">#{@producer.config['isbn']}</dc:identifier>\n)
50
- end
51
-
52
- # creator (should be array)
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|
54
- next unless @producer.config[role]
55
- @producer.config.names_of(role).each do |v|
56
- s << %Q( <dc:creator opf:role="#{role.sub('a-', '')}">#{h(v)}</dc:creator>\n)
57
- end
58
- end
59
-
60
- # contributor (should be array)
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|
62
- next unless @producer.config[role]
63
- @producer.config.names_of(role).each do |v|
64
- s << %Q( <dc:contributor opf:role="#{role}">#{h(v)}</dc:contributor>\n)
65
- if role == 'prt'
66
- s << %Q( <dc:publisher>#{v}</dc:publisher>\n)
67
- end
68
- end
69
- end
70
-
71
- s
72
- end
73
-
74
- def opf_manifest
75
- s = ''
76
- s << <<EOT
77
- <manifest>
78
- <item id="ncx" href="#{@producer.config['bookname']}.ncx" media-type="application/x-dtbncx+xml"/>
79
- <item id="#{@producer.config['bookname']}" href="#{@producer.config['cover']}" media-type="application/xhtml+xml"/>
80
- EOT
81
-
82
- s << %Q( <item id="toc" href="#{@producer.config['bookname']}-toc.#{@producer.config['htmlext']}" media-type="application/xhtml+xml"/>\n) if @producer.config['toc'] && @producer.config['mytoc']
83
-
84
- @producer.contents.each do |item|
85
- next if item.file =~ /#/ # skip subgroup
86
- s << %Q( <item id="#{item.id}" href="#{item.file}" media-type="#{item.media}"/>\n)
87
- end
88
- s << %Q( </manifest>\n)
89
- s
90
- end
91
-
92
- def opf_tocx
93
- cover_linear = if @producer.config['epubmaker']['cover_linear'] && @producer.config['epubmaker']['cover_linear'] != 'no'
94
- 'yes'
95
- else
96
- 'no'
97
- end
98
-
99
- s = ''
100
- s << %Q( <spine toc="ncx">\n)
101
- s << %Q( <itemref idref="#{@producer.config['bookname']}" linear="#{cover_linear}"/>\n)
102
- s << %Q( <itemref idref="toc" />\n) unless @producer.config['mytoc'].nil?
103
-
104
- @producer.contents.each do |item|
105
- next if item.media !~ /xhtml\+xml/ # skip non XHTML
106
- s << %Q( <itemref idref="#{item.id}"/>\n)
107
- end
108
- s << %Q( </spine>\n)
109
- s
110
- end
111
-
112
- # Return ncx content. +indentarray+ has prefix marks for each level.
113
- def ncx(indentarray)
114
- @ncx_isbn = ncx_isbn
115
- @ncx_doctitle = ncx_doctitle
116
- @ncx_navmap = ncx_navmap(indentarray)
117
-
118
- tmplfile = File.expand_path('./ncx/epubv2.ncx.erb', ReVIEW::Template::TEMPLATE_DIR)
119
- ReVIEW::Template.load(tmplfile).result(binding)
120
- end
121
-
122
- # Produce EPUB file +epubfile+.
123
- # +basedir+ points the directory has contents.
124
- # +tmpdir+ defines temporary directory.
125
- def produce(epubfile, basedir, tmpdir)
126
- produce_write_common(basedir, tmpdir)
127
-
128
- File.open("#{tmpdir}/OEBPS/#{@producer.config['bookname']}.ncx", 'w') do |f|
129
- @producer.ncx(f, @producer.config['epubmaker']['ncxindent'])
130
- end
131
- if @producer.config['mytoc']
132
- File.open("#{tmpdir}/OEBPS/#{@producer.config['bookname']}-toc.#{@producer.config['htmlext']}", 'w') do |f|
133
- @producer.mytoc(f)
134
- end
135
- end
136
-
137
- @producer.call_hook(@producer.config['epubmaker']['hook_prepack'], tmpdir)
138
- expoter = EPUBMaker::ZipExporter.new(tmpdir, @producer.config)
139
- expoter.export_zip(epubfile)
140
- end
141
- end
142
- end
@@ -1,235 +0,0 @@
1
- # = epubv3.rb -- EPUB version 3 producer.
2
- #
3
- # Copyright (c) 2010-2017 Kenshi Muto
4
- #
5
- # This program is free software.
6
- # You can distribute or modify this program under the terms of
7
- # the GNU LGPL, Lesser General Public License version 2.1.
8
- # For details of the GNU LGPL, see the file "COPYING".
9
- #
10
-
11
- require 'epubmaker/epubcommon'
12
- require 'epubmaker/zip_exporter'
13
-
14
- module EPUBMaker
15
- # EPUBv3 is EPUB version 3 producer.
16
- class EPUBv3 < EPUBCommon
17
- # Construct object with parameter hash +config+ and message resource hash +res+.
18
- def initialize(producer)
19
- super
20
- @opf_prefix = {}
21
- if @producer.config['opf_prefix'].present?
22
- @producer.config['opf_prefix'].each { |k, v| @opf_prefix[k] = v }
23
- end
24
- end
25
-
26
- # Return opf file content.
27
- def opf
28
- @opf_metainfo = opf_metainfo
29
- @opf_coverimage = opf_coverimage
30
- @opf_manifest = opf_manifest
31
- @opf_toc = opf_tocx
32
- @package_attrs = ''
33
-
34
- if @opf_prefix && @opf_prefix.size > 0
35
- prefixes_str = @opf_prefix.map { |k, v| %Q(#{k}: #{v}) }.join(' ')
36
- @package_attrs << %Q( prefix="#{prefixes_str}")
37
- end
38
-
39
- tmplfile = File.expand_path('./opf/epubv3.opf.erb', ReVIEW::Template::TEMPLATE_DIR)
40
- ReVIEW::Template.load(tmplfile).result(binding)
41
- end
42
-
43
- # rubocop:disable Metrics/PerceivedComplexity
44
- def opf_metainfo
45
- s = ''
46
- %w[title language date type format source description relation coverage subject rights].each do |item|
47
- next unless @producer.config[item]
48
- if @producer.config[item].is_a?(Array)
49
- @producer.config[item].each_with_index do |v, i|
50
- if v.is_a?(Hash)
51
- s << %Q( <dc:#{item} id="#{item}-#{i}">#{h(v['name'])}</dc:#{item}>\n)
52
- v.each_pair do |name, val|
53
- next if name == 'name'
54
- s << %Q( <meta refines="##{item}-#{i}" property="#{name}">#{h(val)}</meta>\n)
55
- end
56
- else
57
- s << %Q( <dc:#{item} id="#{item}-#{i}">#{h(v.to_s)}</dc:#{item}>\n)
58
- end
59
- end
60
- elsif @producer.config[item].is_a?(Hash)
61
- s << %Q( <dc:#{item} id="#{item}">#{h(@producer.config[item]['name'])}</dc:#{item}>\n)
62
- @producer.config[item].each_pair do |name, val|
63
- next if name == 'name'
64
- s << %Q( <meta refines="##{item}" property="#{name}">#{h(val)}</meta>\n)
65
- end
66
- else
67
- s << %Q( <dc:#{item} id="#{item}">#{h(@producer.config[item].to_s)}</dc:#{item}>\n)
68
- end
69
- end
70
-
71
- s << %Q( <meta property="dcterms:modified">#{@producer.config['modified']}</meta>\n)
72
-
73
- # ID
74
- if @producer.config['isbn'].nil?
75
- s << %Q( <dc:identifier id="BookId">#{@producer.config['urnid']}</dc:identifier>\n)
76
- else
77
- s << %Q( <dc:identifier id="BookId">#{@producer.config['isbn']}</dc:identifier>\n)
78
- end
79
-
80
- # creator (should be array)
81
- %w[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-csl 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 aut].each do |role|
82
- next unless @producer.config[role]
83
- @producer.config[role].each_with_index do |v, i|
84
- if v.is_a?(Hash)
85
- s << %Q( <dc:creator id="#{role}-#{i}">#{h(v['name'])}</dc:creator>\n)
86
- s << %Q( <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role.sub('a-', '')}</meta>\n)
87
- v.each_pair do |name, val|
88
- next if name == 'name'
89
- s << %Q( <meta refines="##{role.sub('a-', '')}-#{i}" property="#{name}">#{h(val)}</meta>\n)
90
- end
91
- else
92
- s << %Q( <dc:creator id="#{role}-#{i}">#{h(v)}</dc:creator>\n)
93
- s << %Q( <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role.sub('a-', '')}</meta>\n)
94
- end
95
- end
96
- end
97
-
98
- # contributor (should be array)
99
- %w[adp ann arr art asn aqt aft aui ant bkp clb cmm csl dsr edt ill lyr mdc mus nrt oth pbd pbl pht prt red rev spn ths trc trl].each do |role|
100
- next unless @producer.config[role]
101
- @producer.config[role].each_with_index do |v, i|
102
- if v.is_a?(Hash)
103
- s << %Q( <dc:contributor id="#{role}-#{i}">#{h(v['name'])}</dc:contributor>\n)
104
- s << %Q( <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role}</meta>\n)
105
- v.each_pair do |name, val|
106
- next if name == 'name'
107
- s << %Q( <meta refines="##{role}-#{i}" property="#{name}">#{h(val)}</meta>\n)
108
- end
109
- else
110
- s << %Q( <dc:contributor id="#{role}-#{i}">#{h(v)}</dc:contributor>\n)
111
- s << %Q( <meta refines="##{role}-#{i}" property="role" scheme="marc:relators">#{role}</meta>\n)
112
- end
113
-
114
- if %w[prt pbl].include?(role)
115
- if v.is_a?(Hash)
116
- s << %Q( <dc:publisher id="pub-#{role}-#{i}">#{h(v['name'])}</dc:publisher>\n)
117
- s << %Q( <meta refines="#pub-#{role}-#{i}" property="role" scheme="marc:relators">#{role}</meta>\n)
118
- v.each_pair do |name, val|
119
- next if name == 'name'
120
- s << %Q( <meta refines="#pub-#{role}-#{i}" property="#{name}">#{h(val)}</meta>\n)
121
- end
122
- else
123
- s << %Q( <dc:publisher id="pub-#{role}-#{i}">#{h(v)}</dc:publisher>\n)
124
- s << %Q( <meta refines="#pub-#{role}-#{i}" property="role" scheme="marc:relators">prt</meta>\n)
125
- end
126
- end
127
- end
128
- end
129
-
130
- ## add custom <meta> element
131
- if @producer.config['opf_meta'].present?
132
- @producer.config['opf_meta'].each do |k, v|
133
- s << %Q( <meta property="#{k}">#{h(v)}</meta>\n)
134
- end
135
- end
136
-
137
- s
138
- end
139
- # rubocop:enable Metrics/PerceivedComplexity
140
-
141
- def opf_manifest
142
- s = ''
143
- s << <<EOT
144
- <manifest>
145
- <item properties="nav" id="#{@producer.config['bookname']}-toc.#{@producer.config['htmlext']}" href="#{@producer.config['bookname']}-toc.#{@producer.config['htmlext']}" media-type="application/xhtml+xml"/>
146
- <item id="#{@producer.config['bookname']}" href="#{@producer.config['cover']}" media-type="application/xhtml+xml"/>
147
- EOT
148
-
149
- if @producer.config['coverimage']
150
- @producer.contents.each do |item|
151
- next if !item.media.start_with?('image') || File.basename(item.file) != @producer.config['coverimage']
152
- s << %Q( <item properties="cover-image" id="cover-#{item.id}" href="#{item.file}" media-type="#{item.media}"/>\n)
153
- item.id = nil
154
- break
155
- end
156
- end
157
-
158
- @producer.contents.each do |item|
159
- next if item.file =~ /#/ || item.id.nil? # skip subgroup, or id=nil (for cover)
160
- propstr = ''
161
- if item.properties.size > 0
162
- propstr = %Q( properties="#{item.properties.sort.uniq.join(' ')}")
163
- end
164
- s << %Q( <item id="#{item.id}" href="#{item.file}" media-type="#{item.media}"#{propstr}/>\n)
165
- end
166
- s << %Q( </manifest>\n)
167
-
168
- s
169
- end
170
-
171
- def opf_tocx
172
- if @producer.config['epubmaker']['cover_linear'] && @producer.config['epubmaker']['cover_linear'] != 'no'
173
- cover_linear = 'yes'
174
- else
175
- cover_linear = 'no'
176
- end
177
-
178
- s = ''
179
- if @producer.config['direction']
180
- s << %Q( <spine page-progression-direction="#{@producer.config['direction']}">\n)
181
- else
182
- s << %Q( <spine>\n)
183
- end
184
- s << %Q( <itemref idref="#{@producer.config['bookname']}" linear="#{cover_linear}"/>\n)
185
-
186
- toc = nil
187
- @producer.contents.each do |item|
188
- next if item.media !~ /xhtml\+xml/ # skip non XHTML
189
- if toc.nil? && item.chaptype != 'pre'
190
- if @producer.config['toc']
191
- s << %Q( <itemref idref="#{@producer.config['bookname']}-toc.#{@producer.config['htmlext']}" />\n)
192
- end
193
- toc = true
194
- end
195
- s << %Q( <itemref idref="#{item.id}"/>\n)
196
- end
197
- s << %Q( </spine>\n)
198
-
199
- s
200
- end
201
-
202
- def ncx(indentarray)
203
- ncx_main = if @producer.config['epubmaker']['flattoc'].nil?
204
- hierarchy_ncx('ol')
205
- else
206
- flat_ncx('ol', @producer.config['epubmaker']['flattocindent'])
207
- end
208
-
209
- @body = <<EOT
210
- <nav xmlns:epub="http://www.idpf.org/2007/ops" epub:type="toc" id="toc">
211
- <h1 class="toc-title">#{h(@producer.res.v('toctitle'))}</h1>
212
- #{ncx_main} </nav>
213
- EOT
214
-
215
- @title = h(@producer.res.v('toctitle'))
216
- @language = @producer.config['language']
217
- @stylesheets = @producer.config['stylesheet']
218
- tmplfile = File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
219
- ReVIEW::Template.load(tmplfile).result(binding)
220
- end
221
-
222
- # Produce EPUB file +epubfile+.
223
- # +basedir+ points the directory has contents.
224
- # +tmpdir+ defines temporary directory.
225
- def produce(epubfile, basedir, tmpdir)
226
- produce_write_common(basedir, tmpdir)
227
-
228
- File.open("#{tmpdir}/OEBPS/#{@producer.config['bookname']}-toc.#{@producer.config['htmlext']}", 'w') { |f| @producer.ncx(f, @producer.config['epubmaker']['ncxindent']) }
229
-
230
- @producer.call_hook(@producer.config['epubmaker']['hook_prepack'], tmpdir)
231
- expoter = EPUBMaker::ZipExporter.new(tmpdir, @producer.config)
232
- expoter.export_zip(epubfile)
233
- end
234
- end
235
- end
@@ -1,375 +0,0 @@
1
- # = producer.rb -- EPUB producer.
2
- #
3
- # Copyright (c) 2010-2017 Kenshi Muto
4
- #
5
- # This program is free software.
6
- # You can distribute or modify this program under the terms of
7
- # the GNU LGPL, Lesser General Public License version 2.1.
8
- # For details of the GNU LGPL, see the file "COPYING".
9
-
10
- require 'tmpdir'
11
- require 'fileutils'
12
- require 'review/yamlloader'
13
- require 'epubmaker/content'
14
- require 'epubmaker/epubv2'
15
- require 'epubmaker/epubv3'
16
- require 'review/i18n'
17
- require 'review/configure'
18
- require 'review/extentions/hash'
19
-
20
- module EPUBMaker
21
- # EPUBMaker produces EPUB file.
22
- class Producer
23
- # Array of content objects.
24
- attr_accessor :contents
25
- # Parameter hash.
26
- attr_accessor :config
27
- # Message resource object.
28
- attr_reader :res
29
-
30
- # Take YAML +file+ and return parameter hash.
31
- def self.load(file)
32
- if file.nil? || !File.exist?(file)
33
- raise "Can't open #{file}."
34
- end
35
- loader = ReVIEW::YAMLLoader.new
36
- loader.load_file(file)
37
- end
38
-
39
- # Take YAML +file+ and update parameter hash.
40
- def load(file)
41
- if file.nil? || !File.exist?(file)
42
- raise "Can't open #{file}."
43
- end
44
- loader = ReVIEW::YAMLLoader.new
45
- merge_config(@config.deep_merge(loader.load_file(file)))
46
- end
47
-
48
- def warn(msg)
49
- @logger.warn(msg)
50
- end
51
-
52
- # Construct producer object.
53
- # +config+ takes initial parameter hash. This parameters can be overriden by EPUBMaker#load or EPUBMaker#merge_config.
54
- # +version+ takes EPUB version (default is 2).
55
- def initialize(config = nil, version = nil)
56
- @contents = []
57
- @config = ReVIEW::Configure.new
58
- @epub = nil
59
- @config['epubversion'] = version unless version.nil?
60
- @res = ReVIEW::I18n
61
- @logger = ReVIEW.logger
62
-
63
- merge_config(config) if config
64
- end
65
-
66
- def coverimage
67
- return nil unless config['coverimage']
68
- @contents.each do |item|
69
- if item.media.start_with?('image') && item.file =~ /#{config['coverimage']}\Z/
70
- return item.file
71
- end
72
- end
73
- nil
74
- end
75
-
76
- # Update parameters by merging from new parameter hash +config+.
77
- def merge_config(config)
78
- @config.deep_merge!(config)
79
- complement
80
-
81
- unless @config['epubversion'].nil?
82
- case @config['epubversion'].to_i
83
- when 2
84
- @epub = EPUBMaker::EPUBv2.new(self)
85
- when 3
86
- @epub = EPUBMaker::EPUBv3.new(self)
87
- else
88
- raise "Invalid EPUB version (#{@config['epubversion']}.)"
89
- end
90
- end
91
- if config['language']
92
- ReVIEW::I18n.locale = config['language']
93
- end
94
- support_legacy_maker
95
- end
96
-
97
- # Write mimetype file to IO object +wobj+.
98
- def mimetype(wobj)
99
- s = @epub.mimetype
100
- if !s.nil? && !wobj.nil?
101
- wobj.print s
102
- end
103
- end
104
-
105
- # Write opf file to IO object +wobj+.
106
- def opf(wobj)
107
- s = @epub.opf
108
- if !s.nil? && !wobj.nil?
109
- wobj.puts s
110
- end
111
- end
112
-
113
- # Write ncx file to IO object +wobj+. +indentarray+ defines prefix
114
- # string for each level.
115
- def ncx(wobj, indentarray = [])
116
- s = @epub.ncx(indentarray)
117
- if !s.nil? && !wobj.nil?
118
- wobj.puts s
119
- end
120
- end
121
-
122
- # Write container file to IO object +wobj+.
123
- def container(wobj)
124
- s = @epub.container
125
- if !s.nil? && !wobj.nil?
126
- wobj.puts s
127
- end
128
- end
129
-
130
- # Write cover file to IO object +wobj+.
131
- # If Producer#config["coverimage"] is defined, it will be used for
132
- # the cover image.
133
- def cover(wobj)
134
- type = @config['epubversion'] >= 3 ? 'cover' : nil
135
- s = @epub.cover(type)
136
- if !s.nil? && !wobj.nil?
137
- wobj.puts s
138
- end
139
- end
140
-
141
- # Write title file (copying) to IO object +wobj+.
142
- def titlepage(wobj)
143
- s = @epub.titlepage
144
- if !s.nil? && !wobj.nil?
145
- wobj.puts s
146
- end
147
- end
148
-
149
- # Write colophon file to IO object +wobj+.
150
- def colophon(wobj)
151
- s = @epub.colophon
152
- if !s.nil? && !wobj.nil?
153
- wobj.puts s
154
- end
155
- end
156
-
157
- # Write own toc file to IO object +wobj+.
158
- def mytoc(wobj)
159
- s = @epub.mytoc
160
- if !s.nil? && !wobj.nil?
161
- wobj.puts s
162
- end
163
- end
164
-
165
- # Add informations of figure files in +path+ to contents array.
166
- # +base+ defines a string to remove from path name.
167
- def import_imageinfo(path, base = nil, allow_exts = nil)
168
- return nil unless File.exist?(path)
169
- allow_exts ||= @config['image_ext']
170
- Dir.foreach(path) do |f|
171
- next if f.start_with?('.')
172
- if f =~ /\.(#{allow_exts.join('|')})\Z/i
173
- path.chop! if path =~ %r{/\Z}
174
- if base.nil?
175
- @contents.push(EPUBMaker::Content.new('file' => "#{path}/#{f}"))
176
- else
177
- @contents.push(EPUBMaker::Content.new('file' => "#{path.sub(base + '/', '')}/#{f}"))
178
- end
179
- end
180
- if FileTest.directory?("#{path}/#{f}")
181
- import_imageinfo("#{path}/#{f}", base)
182
- end
183
- end
184
- end
185
-
186
- alias_method :importImageInfo, :import_imageinfo
187
-
188
- # Produce EPUB file +epubfile+.
189
- # +basedir+ points the directory has contents (default: current directory.)
190
- # +tmpdir+ defines temporary directory.
191
- def produce(epubfile, basedir = nil, tmpdir = nil)
192
- current = Dir.pwd
193
- basedir ||= current
194
-
195
- # use Dir to solve a path for Windows (see #1011)
196
- new_tmpdir = Dir[File.join(tmpdir.nil? ? Dir.mktmpdir : tmpdir)][0]
197
- if epubfile !~ %r{\A/}
198
- epubfile = "#{current}/#{epubfile}"
199
- end
200
-
201
- # FIXME: error check
202
- File.unlink(epubfile) if File.exist?(epubfile)
203
-
204
- begin
205
- @epub.produce(epubfile, basedir, new_tmpdir)
206
- ensure
207
- FileUtils.rm_r(new_tmpdir) if tmpdir.nil?
208
- end
209
- end
210
-
211
- def call_hook(filename, *params)
212
- return 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
-
220
- def isbn_hyphen
221
- str = @config['isbn'].to_s
222
-
223
- if str =~ /\A\d{10}\Z/
224
- return "#{str[0..0]}-#{str[1..5]}-#{str[6..8]}-#{str[9..9]}"
225
- end
226
- if str =~ /\A\d{13}\Z/
227
- return "#{str[0..2]}-#{str[3..3]}-#{str[4..8]}-#{str[9..11]}-#{str[12..12]}"
228
- end
229
- nil
230
- end
231
-
232
- private
233
-
234
- # Complement parameters.
235
- def complement
236
- @config['htmlext'] ||= 'html'
237
- defaults = ReVIEW::Configure.new.merge(
238
- 'language' => 'ja',
239
- 'date' => Time.now.strftime('%Y-%m-%d'),
240
- 'modified' => Time.now.utc.strftime('%Y-%02m-%02dT%02H:%02M:%02SZ'),
241
- 'isbn' => nil,
242
- 'toclevel' => 2,
243
- 'stylesheet' => [],
244
- 'epubversion' => 3,
245
- 'htmlversion' => 5,
246
- 'secnolevel' => 2,
247
- 'pre_secnolevel' => 0,
248
- 'post_secnolevel' => 1,
249
- 'part_secnolevel' => 1,
250
- 'titlepage' => true,
251
- 'titlefile' => nil,
252
- 'originaltitlefile' => nil,
253
- 'profile' => nil,
254
- 'colophon' => nil,
255
- 'colophon_order' => %w[aut csl trl dsr ill edt pbl prt pht],
256
- 'direction' => 'ltr',
257
- 'epubmaker' => {
258
- 'flattoc' => nil,
259
- 'flattocindent' => true,
260
- 'ncx_indent' => [],
261
- 'zip_stage1' => 'zip -0Xq',
262
- 'zip_stage2' => 'zip -Xr9Dq',
263
- 'zip_addpath' => nil,
264
- 'hook_beforeprocess' => nil,
265
- 'hook_afterfrontmatter' => nil,
266
- 'hook_afterbody' => nil,
267
- 'hook_afterbackmatter' => nil,
268
- 'hook_aftercopyimage' => nil,
269
- 'hook_prepack' => nil,
270
- 'rename_for_legacy' => nil,
271
- 'verify_target_images' => nil,
272
- 'force_include_images' => [],
273
- 'cover_linear' => nil,
274
- 'back_footnote' => nil
275
- },
276
- 'externallink' => true,
277
- 'contentdir' => '.',
278
- 'imagedir' => 'images',
279
- 'fontdir' => 'fonts',
280
- 'image_ext' => %w[png gif jpg jpeg svg ttf woff otf],
281
- 'image_maxpixels' => 4_000_000,
282
- 'font_ext' => %w[ttf woff otf]
283
- )
284
-
285
- @config = defaults.deep_merge(@config)
286
- @config['title'] = @config['booktitle'] unless @config['title']
287
-
288
- deprecated_parameters = {
289
- 'ncxindent' => 'epubmaker:ncxindent',
290
- 'flattoc' => 'epubmaker:flattoc',
291
- 'flattocindent' => 'epubmaker:flattocindent',
292
- 'hook_beforeprocess' => 'epubmaker:hook_beforeprocess',
293
- 'hook_afterfrontmatter' => 'epubmaker:hook_afterfrontmatter',
294
- 'hook_afterbody' => 'epubmaker:hook_afterbody',
295
- 'hook_afterbackmatter' => 'epubmaker:hook_afterbackmatter',
296
- 'hook_aftercopyimage' => 'epubmaker:hook_aftercopyimage',
297
- 'hook_prepack' => 'epubmaker:hook_prepack',
298
- 'rename_for_legacy' => 'epubmaker:rename_for_legacy',
299
- 'zip_stage1' => 'epubmaker:zip_stage1',
300
- 'zip_stage2' => 'epubmaker:zip_stage2',
301
- 'zip_addpath' => 'epubmaker:zip_addpath',
302
- 'verify_target_images' => 'epubmaker:verify_target_images',
303
- 'force_include_images' => 'epubmaker:force_include_images',
304
- 'cover_linear' => 'epubmaker:cover_linear'
305
- }
306
-
307
- deprecated_parameters.each_pair do |k, v|
308
- next if @config[k].nil?
309
- sa = v.split(':', 2)
310
- warn "Parameter #{k} is deprecated. Use:\n#{sa[0]}:\n #{sa[1]}: ...\n\n"
311
- @config[sa[0]][sa[1]] = @config[k]
312
- @config.delete(k)
313
- end
314
-
315
- if @config['epubversion'] >= 3
316
- @config['htmlversion'] = 5
317
- end
318
-
319
- @config.maker = 'epubmaker'
320
- @config['cover'] = "#{@config['bookname']}.#{@config['htmlext']}" unless @config['cover']
321
-
322
- %w[bookname title].each do |k|
323
- raise "Key #{k} must have a value. Abort." unless @config[k]
324
- end
325
- # array
326
- %w[subject aut
327
- 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
328
- 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
329
- adp ann arr art asn aut aqt aft aui ant bkp clb cmm dsr edt
330
- ill lyr mdc mus nrt oth pht pbl prt red rev spn ths trc trl
331
- stylesheet rights].each do |item|
332
- next unless @config[item]
333
- if @config[item].is_a?(String)
334
- @config[item] = [@config[item]]
335
- end
336
- end
337
- # optional
338
- # type, format, identifier, source, relation, coverpage, aut
339
- end
340
-
341
- def support_legacy_maker
342
- # legacy review-epubmaker support
343
- if @config['flag_legacy_coverfile'].nil? && !@config['coverfile'].nil? && File.exist?(@config['coverfile'])
344
- @config['cover'] = "#{@config['bookname']}-cover.#{@config['htmlext']}"
345
- @epub.legacy_cover_and_title_file(@config['coverfile'], @config['cover'])
346
- @config['flag_legacy_coverfile'] = true
347
- warn %Q(Parameter 'coverfile' is obsolete. Please use 'cover' and make complete html file with header and footer.)
348
- end
349
-
350
- if @config['flag_legacy_titlepagefile'].nil? && !@config['titlepagefile'].nil? && File.exist?(@config['titlepagefile'])
351
- @config['titlefile'] = "#{@config['bookname']}-title.#{@config['htmlext']}"
352
- @config['titlepage'] = true
353
- @epub.legacy_cover_and_title_file(@config['titlepagefile'], @config['titlefile'])
354
- @config['flag_legacy_titlepagefile'] = true
355
- warn %Q(Parameter 'titlepagefile' is obsolete. Please use 'titlefile' and make complete html file with header and footer.)
356
- end
357
-
358
- if @config['flag_legacy_backcoverfile'].nil? && !@config['backcoverfile'].nil? && File.exist?(@config['backcoverfile'])
359
- @config['backcover'] = "#{@config['bookname']}-backcover.#{@config['htmlext']}"
360
- @epub.legacy_cover_and_title_file(@config['backcoverfile'], @config['backcover'])
361
- @config['flag_legacy_backcoverfile'] = true
362
- warn %Q(Parameter 'backcoverfile' is obsolete. Please use 'backcover' and make complete html file with header and footer.)
363
- end
364
-
365
- if @config['flag_legacy_pubhistory'].nil? && @config['pubhistory']
366
- @config['history'] = [[]]
367
- @config['pubhistory'].split("\n").each { |date| @config['history'][0].push(date.sub(/(\d+)年(\d+)月(\d+)日/, '\1-\2-\3')) }
368
- @config['flag_legacy_pubhistory'] = true
369
- warn %Q(Parameter 'pubhistory' is obsolete. Please use 'history' array.)
370
- end
371
-
372
- true
373
- end
374
- end
375
- end