review 5.0.0 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-tex.yml +35 -0
  3. data/.github/workflows/ruby-win.yml +8 -4
  4. data/.github/workflows/ruby.yml +6 -2
  5. data/.rubocop.yml +24 -9
  6. data/NEWS.ja.md +215 -0
  7. data/NEWS.md +215 -1
  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 +10 -20
  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 +30 -38
  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 +23 -5
  28. data/doc/config.yml.sample-simple +1 -1
  29. data/doc/format.ja.md +49 -12
  30. data/doc/format.md +52 -12
  31. data/doc/quickstart.ja.md +11 -1
  32. data/doc/quickstart.md +11 -2
  33. data/doc/writing_vertical.ja.md +6 -0
  34. data/lib/review/book/base.rb +4 -0
  35. data/lib/review/book/book_unit.rb +15 -2
  36. data/lib/review/book/chapter.rb +3 -0
  37. data/lib/review/book/index.rb +5 -1
  38. data/lib/review/book/volume.rb +1 -0
  39. data/lib/review/builder.rb +90 -54
  40. data/lib/review/call_hook.rb +20 -0
  41. data/lib/review/catalog.rb +2 -0
  42. data/lib/review/compiler.rb +88 -52
  43. data/lib/review/configure.rb +64 -7
  44. data/lib/review/epubmaker/content.rb +113 -0
  45. data/lib/review/epubmaker/epubcommon.rb +372 -0
  46. data/lib/review/epubmaker/epubv2.rb +178 -0
  47. data/lib/review/epubmaker/epubv3.rb +231 -0
  48. data/lib/review/epubmaker/producer.rb +167 -0
  49. data/lib/review/epubmaker/reviewheaderlistener.rb +12 -2
  50. data/lib/review/epubmaker/zip_exporter.rb +84 -0
  51. data/lib/review/epubmaker.rb +114 -129
  52. data/lib/review/exception.rb +13 -0
  53. data/lib/review/htmlbuilder.rb +109 -67
  54. data/lib/review/htmlutils.rb +1 -1
  55. data/lib/review/i18n.rb +1 -0
  56. data/lib/review/i18n.yml +6 -0
  57. data/lib/review/idgxmlbuilder.rb +72 -48
  58. data/lib/review/idgxmlmaker.rb +15 -14
  59. data/lib/review/img_math.rb +239 -0
  60. data/lib/review/index_builder.rb +90 -32
  61. data/lib/review/init.rb +4 -4
  62. data/lib/review/latexbox.rb +58 -0
  63. data/lib/review/latexbuilder.rb +79 -58
  64. data/lib/review/latexutils.rb +9 -1
  65. data/lib/review/lineinput.rb +112 -2
  66. data/lib/review/loggable.rb +27 -0
  67. data/lib/review/logger.rb +89 -2
  68. data/lib/review/makerhelper.rb +7 -206
  69. data/lib/review/markdownbuilder.rb +44 -4
  70. data/lib/review/pdfmaker.rb +70 -51
  71. data/lib/review/plaintextbuilder.rb +20 -11
  72. data/lib/review/preprocessor/directive.rb +35 -0
  73. data/lib/review/preprocessor/line.rb +34 -0
  74. data/lib/review/preprocessor/repository.rb +177 -0
  75. data/lib/review/preprocessor.rb +105 -301
  76. data/lib/review/rstbuilder.rb +13 -4
  77. data/lib/review/sec_counter.rb +1 -0
  78. data/lib/review/template.rb +11 -1
  79. data/lib/review/textmaker.rb +23 -20
  80. data/lib/review/textutils.rb +10 -17
  81. data/lib/review/tocprinter.rb +93 -71
  82. data/lib/review/topbuilder.rb +44 -19
  83. data/lib/review/update.rb +5 -6
  84. data/lib/review/version.rb +1 -1
  85. data/lib/review/volumeprinter.rb +11 -12
  86. data/lib/review/webmaker.rb +31 -27
  87. data/lib/review/webtocprinter.rb +10 -9
  88. data/lib/review/yamlloader.rb +2 -1
  89. data/lib/review.rb +1 -1
  90. data/review.gemspec +5 -3
  91. data/samples/sample-book/src/config-epub2.yml +1 -1
  92. data/samples/sample-book/src/config.yml +1 -1
  93. data/samples/sample-book/src/lib/tasks/review.rake +19 -1
  94. data/samples/sample-book/src/lib/tasks/z01_copy_sty.rake +2 -1
  95. data/samples/syntax-book/ch01.re +1 -1
  96. data/samples/syntax-book/ch02.re +30 -6
  97. data/samples/syntax-book/ch03.re +1 -1
  98. data/samples/syntax-book/images/img3-2.png +0 -0
  99. data/samples/syntax-book/lib/tasks/z01_copy_sty.rake +2 -1
  100. data/templates/html/_colophon.html.erb +23 -0
  101. data/templates/html/_colophon_history.html.erb +9 -0
  102. data/templates/html/_cover.html.erb +10 -0
  103. data/templates/html/_part_body.html.erb +6 -0
  104. data/templates/html/_titlepage.html.erb +20 -0
  105. data/templates/html/layout-html5.html.erb +6 -0
  106. data/templates/html/layout-xhtml1.html.erb +6 -0
  107. data/templates/latex/config.erb +11 -0
  108. data/templates/latex/review-jlreq/review-base.sty +7 -9
  109. data/templates/latex/review-jlreq/review-jlreq.cls +48 -6
  110. data/templates/latex/review-jlreq/review-style.sty +6 -1
  111. data/templates/latex/review-jlreq/review-tcbox.sty +348 -0
  112. data/templates/latex/review-jlreq/reviewmacro.sty +5 -0
  113. data/templates/latex/review-jsbook/review-base.sty +13 -9
  114. data/templates/latex/review-jsbook/review-jsbook.cls +41 -6
  115. data/templates/latex/review-jsbook/review-style.sty +6 -1
  116. data/templates/latex/review-jsbook/review-tcbox.sty +348 -0
  117. data/templates/latex/review-jsbook/reviewmacro.sty +5 -0
  118. data/templates/opf/epubv2.opf.erb +7 -7
  119. data/templates/opf/epubv3.opf.erb +7 -7
  120. data/templates/opf/opf_manifest_epubv2.opf.erb +10 -0
  121. data/templates/opf/opf_manifest_epubv3.opf.erb +10 -0
  122. data/templates/opf/opf_metainfo_epubv2.opf.erb +17 -0
  123. data/templates/opf/opf_metainfo_epubv3.opf.erb +49 -0
  124. data/templates/opf/opf_tocx_epubv2.opf.erb +9 -0
  125. data/templates/opf/opf_tocx_epubv3.opf.erb +17 -0
  126. data/templates/web/html/layout-html5.html.erb +6 -5
  127. data/templates/web/html/layout-xhtml1.html.erb +6 -0
  128. data/test/assets/header_listener.html +35 -0
  129. data/test/assets/img_math/img1.png +0 -0
  130. data/test/assets/img_math/img2.png +0 -0
  131. data/test/assets/img_math/img3.png +0 -0
  132. data/test/assets/syntax_book_index_detail.txt +60 -0
  133. data/test/assets/test_template.tex +7 -1
  134. data/test/assets/test_template_backmatter.tex +7 -1
  135. data/test/run_test.rb +1 -1
  136. data/test/test_book_chapter.rb +27 -4
  137. data/test/test_builder.rb +10 -8
  138. data/test/test_catalog_converter_cmd.rb +1 -1
  139. data/test/test_epub3maker.rb +168 -124
  140. data/test/test_epubmaker.rb +248 -131
  141. data/test/test_epubmaker_cmd.rb +15 -4
  142. data/test/test_helper.rb +5 -4
  143. data/test/test_htmlbuilder.rb +170 -31
  144. data/test/test_idgxmlbuilder.rb +44 -23
  145. data/test/test_idgxmlmaker_cmd.rb +7 -3
  146. data/test/test_img_math.rb +111 -0
  147. data/test/test_index.rb +30 -4
  148. data/test/test_indexbuilder.rb +5 -5
  149. data/test/test_latexbuilder.rb +151 -26
  150. data/test/test_latexbuilder_v2.rb +18 -10
  151. data/test/test_lineinput.rb +20 -93
  152. data/test/test_markdownbuilder.rb +42 -0
  153. data/test/test_pdfmaker.rb +90 -0
  154. data/test/test_pdfmaker_cmd.rb +2 -2
  155. data/test/test_plaintextbuilder.rb +56 -40
  156. data/test/test_preprocessor.rb +188 -1
  157. data/test/test_reviewheaderlistener.rb +49 -0
  158. data/test/test_rstbuilder.rb +13 -0
  159. data/test/test_template.rb +12 -2
  160. data/test/test_textmaker_cmd.rb +5 -1
  161. data/test/test_tocprinter.rb +46 -0
  162. data/test/test_topbuilder.rb +50 -19
  163. data/test/test_update.rb +34 -34
  164. data/test/test_zip_exporter.rb +5 -6
  165. metadata +95 -17
  166. data/lib/epubmaker/content.rb +0 -111
  167. data/lib/epubmaker/epubcommon.rb +0 -449
  168. data/lib/epubmaker/epubv2.rb +0 -142
  169. data/lib/epubmaker/epubv3.rb +0 -235
  170. data/lib/epubmaker/producer.rb +0 -375
  171. data/lib/epubmaker/zip_exporter.rb +0 -81
  172. data/lib/epubmaker.rb +0 -23
  173. data/lib/lineinput.rb +0 -155
@@ -1,111 +0,0 @@
1
- # = content.rb -- Content object for EPUBMaker.
2
- #
3
- # Copyright (c) 2010-2020 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
- module EPUBMaker
12
- # EPUBMaker::Content represents a content data for EPUBMaker.
13
- # EPUBMaker#contents takes an array of Content.
14
- class Content
15
- # ID
16
- attr_accessor :id
17
- # File path (will accept #<anchor> suffix also)
18
- attr_accessor :file
19
- # MIME type
20
- attr_accessor :media
21
- # Title
22
- attr_accessor :title
23
- # Header level (from 1)
24
- attr_accessor :level
25
- # Show in TOC? nil:No.
26
- attr_accessor :notoc
27
- # Properties (EPUB3)
28
- attr_accessor :properties
29
- # Chapter type (pre/post/part/nil(body))
30
- attr_accessor :chaptype
31
-
32
- def inspect
33
- "<Content id=#{@id}, file=#{@file}, media=#{@media}, title=#{@title}, level=#{@level}, notoc=#{@notoc}, properties=#{@properties}, chaptype=#{@chaptype}>"
34
- end
35
-
36
- # :call-seq:
37
- # initialize(file, id, media, title, level, notoc)
38
- # initialize(hash)
39
- # Construct Content object by passing a sequence of parameters or hash.
40
- # Keys of +hash+ relate with each parameters.
41
- # +file+ (or +hash+["file"]) is required. Others are optional.
42
- def initialize(fileorhash, id = nil, media = nil, title = nil, level = nil, notoc = nil, properties = nil, chaptype = nil)
43
- if fileorhash.instance_of?(Hash)
44
- @id = fileorhash['id']
45
- @file = fileorhash['file']
46
- @media = fileorhash['media']
47
- @title = fileorhash['title']
48
- @level = fileorhash['level']
49
- @notoc = fileorhash['notoc']
50
- @properties = fileorhash['properties'] || []
51
- @chaptype = fileorhash['chaptype']
52
- else
53
- @file = fileorhash
54
- @id = id
55
- @media = media
56
- @title = title
57
- @level = level
58
- @notoc = notoc
59
- @properties = properties || []
60
- @chaptype = chaptype
61
- end
62
- complement
63
- end
64
-
65
- def ==(other)
66
- return false unless self.class == other.class
67
- [self.id, self.file, self.media, self.title, self.level, self.notoc, self.chaptype, self.properties] ==
68
- [other.id, other.file, other.media, other.title, other.level, other.notoc, other.chaptype, other.properties]
69
- end
70
-
71
- private
72
-
73
- # Complement other parameters by using file parameter.
74
- def complement
75
- if @id.nil?
76
- @id = @file.gsub(%r{[\\/. ]}, '-')
77
- end
78
- if @id =~ /\A[^a-z]/i
79
- @id = "rv-#{@id}"
80
- end
81
- @id = CGI.escape(@id).gsub('%', '_25_')
82
-
83
- if !@file.nil? && @media.nil?
84
- @media = @file.sub(/.+\./, '').downcase
85
- end
86
-
87
- case @media
88
- when 'xhtml', 'xml', 'html'
89
- @media = 'application/xhtml+xml'
90
- when 'css'
91
- @media = 'text/css'
92
- when 'jpg', 'jpeg', 'image/jpg'
93
- @media = 'image/jpeg'
94
- when 'png'
95
- @media = 'image/png'
96
- when 'gif'
97
- @media = 'image/gif'
98
- when 'svg', 'image/svg'
99
- @media = 'image/svg+xml'
100
- when 'ttf', 'otf'
101
- @media = 'application/vnd.ms-opentype'
102
- when 'woff'
103
- @media = 'application/font-woff'
104
- end
105
-
106
- if @id.nil? || @file.nil? || @media.nil?
107
- raise "Type error: #{id}, #{file}, #{media}, #{title}, #{notoc}"
108
- end
109
- end
110
- end
111
- end
@@ -1,449 +0,0 @@
1
- # = epubcommon.rb -- super class for EPUBv2 and EPUBv3
2
- #
3
- # Copyright (c) 2010-2019 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 'review/i18n'
12
- require 'review/template'
13
- begin
14
- require 'cgi/escape'
15
- rescue LoadError
16
- require 'cgi/util'
17
- end
18
-
19
- module EPUBMaker
20
- # EPUBCommon is the common class for EPUB producer.
21
- class EPUBCommon
22
- # Construct object with parameter hash +config+ and message resource hash +res+.
23
- def initialize(producer)
24
- @body_ext = ''
25
- @producer = producer
26
- @body_ext = nil
27
- end
28
-
29
- def h(str)
30
- CGI.escapeHTML(str)
31
- end
32
-
33
- # Return mimetype content.
34
- def mimetype
35
- 'application/epub+zip'
36
- end
37
-
38
- def opf_path
39
- "OEBPS/#{@producer.config['bookname']}.opf"
40
- end
41
-
42
- def opf_coverimage
43
- s = ''
44
- if @producer.config['coverimage']
45
- file = nil
46
- @producer.contents.each do |item|
47
- if !item.media.start_with?('image') || item.file !~ /#{@producer.config['coverimage']}\Z/
48
- next
49
- end
50
- s << %Q( <meta name="cover" content="#{item.id}"/>\n)
51
- file = item.file
52
- break
53
- end
54
-
55
- if file.nil?
56
- raise "coverimage #{@producer.config['coverimage']} not found. Abort."
57
- end
58
- end
59
- s
60
- end
61
-
62
- def ncx_isbn
63
- uid = @producer.config['isbn'] || @producer.config['urnid']
64
- %Q( <meta name="dtb:uid" content="#{uid}"/>\n)
65
- end
66
-
67
- def ncx_doctitle
68
- <<EOT
69
- <docTitle>
70
- <text>#{h(@producer.config['title'])}</text>
71
- </docTitle>
72
- <docAuthor>
73
- <text>#{@producer.config['aut'].nil? ? '' : h(join_with_separator(@producer.config['aut'], ReVIEW::I18n.t('names_splitter')))}</text>
74
- </docAuthor>
75
- EOT
76
- end
77
-
78
- def ncx_navmap(indentarray)
79
- s = <<EOT
80
- <navMap>
81
- <navPoint id="top" playOrder="1">
82
- <navLabel>
83
- <text>#{h(@producer.config['title'])}</text>
84
- </navLabel>
85
- <content src="#{@producer.config['cover']}"/>
86
- </navPoint>
87
- EOT
88
-
89
- nav_count = 2
90
-
91
- unless @producer.config['mytoc'].nil?
92
- s << <<EOT
93
- <navPoint id="toc" playOrder="#{nav_count}">
94
- <navLabel>
95
- <text>#{h(@producer.res.v('toctitle'))}</text>
96
- </navLabel>
97
- <content src="#{@producer.config['bookname']}-toc.#{@producer.config['htmlext']}"/>
98
- </navPoint>
99
- EOT
100
- nav_count += 1
101
- end
102
-
103
- @producer.contents.each do |item|
104
- next if item.title.nil?
105
- indent = indentarray.nil? ? [''] : indentarray
106
- level = item.level.nil? ? 0 : (item.level - 1)
107
- level = indent.size - 1 if level >= indent.size
108
- s << <<EOT
109
- <navPoint id="nav-#{nav_count}" playOrder="#{nav_count}">
110
- <navLabel>
111
- <text>#{indent[level]}#{h(item.title)}</text>
112
- </navLabel>
113
- <content src="#{item.file}"/>
114
- </navPoint>
115
- EOT
116
- nav_count += 1
117
- end
118
-
119
- s << <<EOT
120
- </navMap>
121
- EOT
122
- s
123
- end
124
-
125
- # Return container content.
126
- def container
127
- @opf_path = opf_path
128
- tmplfile = File.expand_path('./xml/container.xml.erb', ReVIEW::Template::TEMPLATE_DIR)
129
- tmpl = ReVIEW::Template.load(tmplfile)
130
- tmpl.result(binding)
131
- end
132
-
133
- # Return cover content.
134
- def cover(type = nil)
135
- @body_ext = type.nil? ? '' : %Q( epub:type="#{type}")
136
-
137
- if @producer.config['coverimage']
138
- file = @producer.coverimage
139
- raise "coverimage #{@producer.config['coverimage']} not found. Abort." unless file
140
- @body = <<-EOT
141
- <div id="cover-image" class="cover-image">
142
- <img src="#{file}" alt="#{h(@producer.config.name_of('title'))}" class="max"/>
143
- </div>
144
- EOT
145
- else
146
- @body = <<-EOT
147
- <h1 class="cover-title">#{h(@producer.config.name_of('title'))}</h1>
148
- EOT
149
- if @producer.config['subtitle']
150
- @body << <<-EOT
151
- <h2 class="cover-subtitle">#{h(@producer.config.name_of('subtitle'))}</h2>
152
- EOT
153
- end
154
- end
155
-
156
- @title = h(@producer.config.name_of('title'))
157
- @language = @producer.config['language']
158
- @stylesheets = @producer.config['stylesheet']
159
- tmplfile = if @producer.config['htmlversion'].to_i == 5
160
- File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
161
- else
162
- File.expand_path('./html/layout-xhtml1.html.erb', ReVIEW::Template::TEMPLATE_DIR)
163
- end
164
- tmpl = ReVIEW::Template.load(tmplfile)
165
- tmpl.result(binding)
166
- end
167
-
168
- # Return title (copying) content.
169
- # NOTE: this method is not used yet.
170
- # see lib/review/epubmaker.rb#build_titlepage
171
- def titlepage
172
- @title = h(@producer.config.name_of('title'))
173
-
174
- @body = <<EOT
175
- <h1 class="tp-title">#{@title}</h1>
176
- EOT
177
-
178
- if @producer.config['subtitle']
179
- @body << <<EOT
180
- <h2 class="tp-subtitle">#{h(@producer.config.name_of('subtitle'))}</h2>
181
- EOT
182
- end
183
-
184
- if @producer.config['aut']
185
- @body << <<EOT
186
- <p>
187
- <br />
188
- <br />
189
- </p>
190
- <h2 class="tp-author">#{h(join_with_separator(@producer.config.names_of('aut'), ReVIEW::I18n.t('names_splitter')))}</h2>
191
- EOT
192
- end
193
-
194
- publisher = @producer.config.names_of('pbl')
195
- if publisher
196
- @body << <<EOT
197
- <p>
198
- <br />
199
- <br />
200
- <br />
201
- <br />
202
- </p>
203
- <h3 class="tp-publisher">#{h(join_with_separator(publisher, ReVIEW::I18n.t('names_splitter')))}</h3>
204
- EOT
205
- end
206
-
207
- @language = @producer.config['language']
208
- @stylesheets = @producer.config['stylesheet']
209
- tmplfile = if @producer.config['htmlversion'].to_i == 5
210
- File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
211
- else
212
- File.expand_path('./html/layout-xhtml1.html.erb', ReVIEW::Template::TEMPLATE_DIR)
213
- end
214
- tmpl = ReVIEW::Template.load(tmplfile)
215
- tmpl.result(binding)
216
- end
217
-
218
- # Return colophon content.
219
- def colophon
220
- @title = h(@producer.res.v('colophontitle'))
221
- @body = <<EOT
222
- <div class="colophon">
223
- EOT
224
-
225
- if @producer.config['subtitle'].nil?
226
- @body << <<EOT
227
- <p class="title">#{h(@producer.config.name_of('title'))}</p>
228
- EOT
229
- else
230
- @body << <<EOT
231
- <p class="title">#{h(@producer.config.name_of('title'))}<br /><span class="subtitle">#{h(@producer.config.name_of('subtitle'))}</span></p>
232
- EOT
233
- end
234
-
235
- @body << colophon_history if @producer.config['date'] || @producer.config['history']
236
-
237
- @body << %Q( <table class="colophon">\n)
238
- @body << @producer.config['colophon_order'].map do |role|
239
- if @producer.config[role]
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)
241
- else
242
- ''
243
- end
244
- end.join
245
-
246
- @body << %Q( <tr><th>ISBN</th><td>#{@producer.isbn_hyphen}</td></tr>\n) if @producer.isbn_hyphen
247
- @body << %Q( </table>\n)
248
- if @producer.config['rights'] && !@producer.config['rights'].empty?
249
- @body << %Q( <p class="copyright">#{join_with_separator(@producer.config.names_of('rights').map { |m| h(m) }, '<br />')}</p>\n)
250
- end
251
- @body << %Q( </div>\n)
252
-
253
- @language = @producer.config['language']
254
- @stylesheets = @producer.config['stylesheet']
255
- tmplfile = if @producer.config['htmlversion'].to_i == 5
256
- File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
257
- else
258
- File.expand_path('./html/layout-xhtml1.html.erb', ReVIEW::Template::TEMPLATE_DIR)
259
- end
260
- tmpl = ReVIEW::Template.load(tmplfile)
261
- tmpl.result(binding)
262
- end
263
-
264
- def colophon_history
265
- buf = ''
266
- buf << %Q( <div class="pubhistory">\n)
267
- if @producer.config['history']
268
- @producer.config['history'].each_with_index do |items, edit|
269
- items.each_with_index do |item, rev|
270
- editstr = edit == 0 ? ReVIEW::I18n.t('first_edition') : ReVIEW::I18n.t('nth_edition', (edit + 1).to_s)
271
- revstr = ReVIEW::I18n.t('nth_impression', (rev + 1).to_s)
272
- if item =~ /\A\d+-\d+-\d+\Z/
273
- buf << %Q( <p>#{ReVIEW::I18n.t('published_by1', [date_to_s(item), editstr + revstr])}</p>\n)
274
- elsif item =~ /\A(\d+-\d+-\d+)[\s ](.+)/
275
- # custom date with string
276
- item.match(/\A(\d+-\d+-\d+)[\s ](.+)/) do |m|
277
- buf << %Q( <p>#{ReVIEW::I18n.t('published_by3', [date_to_s(m[1]), m[2]])}</p>\n)
278
- end
279
- else
280
- # free format
281
- buf << %Q( <p>#{item}</p>\n)
282
- end
283
- end
284
- end
285
- else
286
- buf << %Q( <p>#{ReVIEW::I18n.t('published_by2', date_to_s(@producer.config['date']))}</p>\n)
287
- end
288
- buf << %Q( </div>\n)
289
- buf
290
- end
291
-
292
- def date_to_s(date)
293
- require 'date'
294
- d = Date.parse(date)
295
- d.strftime(ReVIEW::I18n.t('date_format'))
296
- end
297
-
298
- # Return own toc content.
299
- def mytoc
300
- @title = h(@producer.res.v('toctitle'))
301
-
302
- @body = %Q( <h1 class="toc-title">#{h(@producer.res.v('toctitle'))}</h1>\n)
303
- if @producer.config['epubmaker']['flattoc'].nil?
304
- @body << hierarchy_ncx('ul')
305
- else
306
- @body << flat_ncx('ul', @producer.config['epubmaker']['flattocindent'])
307
- end
308
-
309
- @language = @producer.config['language']
310
- @stylesheets = @producer.config['stylesheet']
311
- tmplfile = if @producer.config['htmlversion'].to_i == 5
312
- File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
313
- else
314
- File.expand_path('./html/layout-xhtml1.html.erb', ReVIEW::Template::TEMPLATE_DIR)
315
- end
316
- tmpl = ReVIEW::Template.load(tmplfile)
317
- tmpl.result(binding)
318
- end
319
-
320
- def hierarchy_ncx(type)
321
- require 'rexml/document'
322
- level = 1
323
- find_jump = nil
324
- has_part = nil
325
- toclevel = @producer.config['toclevel'].to_i
326
-
327
- # check part existance
328
- @producer.contents.each do |item|
329
- next if item.notoc || item.chaptype != 'part'
330
-
331
- has_part = true
332
- break
333
- end
334
-
335
- if has_part
336
- @producer.contents.each do |item|
337
- if item.chaptype == 'part' && item.level > 0
338
- # sections in part
339
- item.level -= 1
340
- end
341
- # down level for part and chaps. pre, appendix, post are preserved
342
- if item.chaptype == 'part' || item.chaptype == 'body'
343
- item.level += 1
344
- end
345
- end
346
- toclevel += 1
347
- end
348
-
349
- doc = REXML::Document.new(%Q(<#{type} class="toc-h#{level}"><li /></#{type}>))
350
- doc.context[:attribute_quote] = :quote
351
-
352
- e = doc.root.elements[1] # first <li/>
353
- @producer.contents.each do |item|
354
- next if !item.notoc.nil? || item.level.nil? || item.file.nil? || item.title.nil? || item.level > toclevel
355
-
356
- if item.level == level
357
- e2 = e.parent.add_element('li')
358
- e = e2
359
- elsif item.level > level
360
- find_jump = true if (item.level - level) > 1
361
- # deeper
362
- (level + 1).upto(item.level) do |n|
363
- if e.size == 0
364
- # empty span for epubcheck
365
- e.attributes['style'] = 'list-style-type: none;'
366
- es = e.add_element('span', 'style' => 'display:none;')
367
- es.add_text(REXML::Text.new('&#xa0;', false, nil, true))
368
- end
369
-
370
- e2 = e.add_element(type, 'class' => "toc-h#{n}")
371
- e3 = e2.add_element('li')
372
- e = e3
373
- end
374
- level = item.level
375
- elsif item.level < level
376
- # shallower
377
- (level - 1).downto(item.level) { e = e.parent.parent }
378
- e2 = e.parent.add_element('li')
379
- e = e2
380
- level = item.level
381
- end
382
- e2 = e.add_element('a', 'href' => item.file)
383
- e2.add_text(REXML::Text.new(item.title, true))
384
- end
385
-
386
- warn %Q(found level jumping in table of contents. consider to use 'epubmaker:flattoc: true' for strict ePUB validator.) unless find_jump.nil?
387
-
388
- doc.to_s.gsub('<li/>', '').gsub('</li>', "</li>\n").gsub("<#{type} ", "\n" + '\&') # ugly
389
- end
390
-
391
- def flat_ncx(type, indent = nil)
392
- s = %Q(<#{type} class="toc-h1">\n)
393
- @producer.contents.each do |item|
394
- next if !item.notoc.nil? || item.level.nil? || item.file.nil? || item.title.nil? || item.level > @producer.config['toclevel'].to_i
395
- is = indent == true ? ' ' * item.level : ''
396
- s << %Q(<li><a href="#{item.file}">#{is}#{h(item.title)}</a></li>\n)
397
- end
398
- s << %Q(</#{type}>\n)
399
-
400
- s
401
- end
402
-
403
- def produce_write_common(basedir, tmpdir)
404
- File.open("#{tmpdir}/mimetype", 'w') { |f| @producer.mimetype(f) }
405
-
406
- FileUtils.mkdir_p("#{tmpdir}/META-INF")
407
- File.open("#{tmpdir}/META-INF/container.xml", 'w') { |f| @producer.container(f) }
408
-
409
- FileUtils.mkdir_p("#{tmpdir}/OEBPS")
410
- File.open(File.join(tmpdir, opf_path), 'w') { |f| @producer.opf(f) }
411
-
412
- if File.exist?("#{basedir}/#{@producer.config['cover']}")
413
- FileUtils.cp("#{basedir}/#{@producer.config['cover']}", "#{tmpdir}/OEBPS")
414
- else
415
- File.open("#{tmpdir}/OEBPS/#{@producer.config['cover']}", 'w') { |f| @producer.cover(f) }
416
- end
417
-
418
- @producer.contents.each do |item|
419
- next if item.file =~ /#/ # skip subgroup
420
- fname = "#{basedir}/#{item.file}"
421
- raise "#{fname} doesn't exist. Abort." unless File.exist?(fname)
422
- FileUtils.mkdir_p(File.dirname("#{tmpdir}/OEBPS/#{item.file}"))
423
- FileUtils.cp(fname, "#{tmpdir}/OEBPS/#{item.file}")
424
- end
425
- end
426
-
427
- def legacy_cover_and_title_file(loadfile, writefile)
428
- @title = @producer.config['booktitle']
429
- s = ''
430
- File.open(loadfile) do |f|
431
- f.each_line do |l|
432
- s << l
433
- end
434
- end
435
-
436
- File.open(writefile, 'w') do |f|
437
- f.puts s
438
- end
439
- end
440
-
441
- def join_with_separator(value, sep)
442
- if value.is_a?(Array)
443
- value.join(sep)
444
- else
445
- value
446
- end
447
- end
448
- end
449
- end
@@ -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