review-peg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/.rubocop.yml +47 -0
  4. data/.rubocop_todo.yml +605 -0
  5. data/.travis.yml +18 -0
  6. data/COPYING +515 -0
  7. data/ChangeLog +2449 -0
  8. data/Dockerfile +22 -0
  9. data/Gemfile +6 -0
  10. data/README.rdoc +81 -0
  11. data/Rakefile +51 -0
  12. data/bin/review-catalog-converter-peg +129 -0
  13. data/bin/review-check-peg +169 -0
  14. data/bin/review-checkdep-peg +63 -0
  15. data/bin/review-compile-peg +202 -0
  16. data/bin/review-epubmaker-legacy-peg +1024 -0
  17. data/bin/review-epubmaker-peg +44 -0
  18. data/bin/review-index-peg +110 -0
  19. data/bin/review-init-peg +151 -0
  20. data/bin/review-pdfmaker-peg +18 -0
  21. data/bin/review-preproc-peg +131 -0
  22. data/bin/review-validate-peg +51 -0
  23. data/bin/review-vol-peg +100 -0
  24. data/debian/README.Debian +12 -0
  25. data/debian/README.source +5 -0
  26. data/debian/changelog +5 -0
  27. data/debian/compat +1 -0
  28. data/debian/control +22 -0
  29. data/debian/copyright +62 -0
  30. data/debian/docs +6 -0
  31. data/debian/manpage.1.ex +59 -0
  32. data/debian/patches/path.diff +91 -0
  33. data/debian/patches/series +1 -0
  34. data/debian/review.install +13 -0
  35. data/debian/review.links +4 -0
  36. data/debian/rules +13 -0
  37. data/debian/source/format +1 -0
  38. data/doc/NEWS.ja.md +350 -0
  39. data/doc/NEWS.md +354 -0
  40. data/doc/catalog.ja.md +53 -0
  41. data/doc/catalog.md +52 -0
  42. data/doc/format.ja.md +734 -0
  43. data/doc/format.md +746 -0
  44. data/doc/format_idg.ja.md +203 -0
  45. data/doc/quickstart.ja.md +222 -0
  46. data/doc/quickstart.md +252 -0
  47. data/doc/ruby-uuid/README +11 -0
  48. data/doc/ruby-uuid/README.ja +34 -0
  49. data/doc/sample.css +108 -0
  50. data/doc/sample.yml +238 -0
  51. data/lib/epubmaker.rb +24 -0
  52. data/lib/epubmaker/content.rb +93 -0
  53. data/lib/epubmaker/epubcommon.rb +424 -0
  54. data/lib/epubmaker/epubv2.rb +139 -0
  55. data/lib/epubmaker/epubv3.rb +222 -0
  56. data/lib/epubmaker/producer.rb +330 -0
  57. data/lib/lineinput.rb +107 -0
  58. data/lib/review.rb +3 -0
  59. data/lib/review/book.rb +43 -0
  60. data/lib/review/book/base.rb +401 -0
  61. data/lib/review/book/chapter.rb +100 -0
  62. data/lib/review/book/compilable.rb +184 -0
  63. data/lib/review/book/image_finder.rb +71 -0
  64. data/lib/review/book/index.rb +413 -0
  65. data/lib/review/book/page_metric.rb +47 -0
  66. data/lib/review/book/part.rb +54 -0
  67. data/lib/review/book/volume.rb +67 -0
  68. data/lib/review/builder.rb +452 -0
  69. data/lib/review/catalog.rb +52 -0
  70. data/lib/review/compiler.rb +5183 -0
  71. data/lib/review/compiler/literals_1_9.kpeg +22 -0
  72. data/lib/review/compiler/literals_1_9.rb +435 -0
  73. data/lib/review/configure.rb +64 -0
  74. data/lib/review/epubbuilder.rb +18 -0
  75. data/lib/review/epubmaker.rb +480 -0
  76. data/lib/review/ewbbuilder.rb +381 -0
  77. data/lib/review/exception.rb +21 -0
  78. data/lib/review/extentions.rb +4 -0
  79. data/lib/review/extentions/array.rb +25 -0
  80. data/lib/review/extentions/object.rb +9 -0
  81. data/lib/review/extentions/string.rb +33 -0
  82. data/lib/review/htmlbuilder.rb +1166 -0
  83. data/lib/review/htmllayout.rb +41 -0
  84. data/lib/review/htmltoc.rb +45 -0
  85. data/lib/review/htmlutils.rb +90 -0
  86. data/lib/review/i18n.rb +96 -0
  87. data/lib/review/i18n.yml +169 -0
  88. data/lib/review/idgxmlbuilder.rb +1233 -0
  89. data/lib/review/inaobuilder.rb +357 -0
  90. data/lib/review/latexbuilder.rb +941 -0
  91. data/lib/review/latexindex.rb +35 -0
  92. data/lib/review/latexutils.rb +95 -0
  93. data/lib/review/layout.tex.erb +340 -0
  94. data/lib/review/lineinput.rb +17 -0
  95. data/lib/review/location.rb +24 -0
  96. data/lib/review/makerhelper.rb +67 -0
  97. data/lib/review/markdownbuilder.rb +339 -0
  98. data/lib/review/node.rb +288 -0
  99. data/lib/review/pdfmaker.rb +332 -0
  100. data/lib/review/preprocessor.rb +530 -0
  101. data/lib/review/review.kpeg +745 -0
  102. data/lib/review/sec_counter.rb +69 -0
  103. data/lib/review/template.rb +21 -0
  104. data/lib/review/textbuilder.rb +17 -0
  105. data/lib/review/textutils.rb +16 -0
  106. data/lib/review/tocparser.rb +348 -0
  107. data/lib/review/tocprinter.rb +205 -0
  108. data/lib/review/topbuilder.rb +796 -0
  109. data/lib/review/unfold.rb +138 -0
  110. data/lib/review/version.rb +3 -0
  111. data/lib/uuid.rb +312 -0
  112. data/review.gemspec +32 -0
  113. data/templates/html/layout-html5.html.erb +17 -0
  114. data/templates/html/layout-xhtml1.html.erb +20 -0
  115. data/templates/ncx/epubv2.ncx.erb +11 -0
  116. data/templates/opf/epubv2.opf.erb +21 -0
  117. data/templates/opf/epubv3.opf.erb +18 -0
  118. data/templates/xml/container.xml.erb +6 -0
  119. data/test/CHAPS +2 -0
  120. data/test/assets/test.xml.erb +3 -0
  121. data/test/assets/test_template.tex +255 -0
  122. data/test/assets/test_template_backmatter.tex +32 -0
  123. data/test/bib.re +13 -0
  124. data/test/book_test_helper.rb +35 -0
  125. data/test/sample-book/README.md +7 -0
  126. data/test/sample-book/src/Rakefile +58 -0
  127. data/test/sample-book/src/_cover.html +3 -0
  128. data/test/sample-book/src/catalog.yml +10 -0
  129. data/test/sample-book/src/ch01.re +71 -0
  130. data/test/sample-book/src/ch02.re +3 -0
  131. data/test/sample-book/src/config.yml +186 -0
  132. data/test/sample-book/src/images/ch01-imgsample.jpg +0 -0
  133. data/test/sample-book/src/images/cover.jpg +0 -0
  134. data/test/sample-book/src/preface.re +15 -0
  135. data/test/sample-book/src/sty/jumoline.sty +310 -0
  136. data/test/sample-book/src/sty/reviewmacro.sty +39 -0
  137. data/test/sample-book/src/style.css +251 -0
  138. data/test/sample-book/src/vendor/jumoline/README +29 -0
  139. data/test/sample-book/src/vendor/jumoline/jumoline.dtx +2988 -0
  140. data/test/sample-book/src/vendor/jumoline/jumoline.ins +6 -0
  141. data/test/test.re +43 -0
  142. data/test/test_book.rb +556 -0
  143. data/test/test_book_chapter.rb +280 -0
  144. data/test/test_book_part.rb +54 -0
  145. data/test/test_builder.rb +80 -0
  146. data/test/test_catalog.rb +119 -0
  147. data/test/test_catalog_converter_cmd.rb +73 -0
  148. data/test/test_compiler.rb +92 -0
  149. data/test/test_configure.rb +50 -0
  150. data/test/test_epub3maker.rb +529 -0
  151. data/test/test_epubmaker.rb +569 -0
  152. data/test/test_epubmaker_cmd.rb +40 -0
  153. data/test/test_helper.rb +92 -0
  154. data/test/test_htmlbuilder.rb +1114 -0
  155. data/test/test_htmltoc.rb +32 -0
  156. data/test/test_htmlutils.rb +50 -0
  157. data/test/test_i18n.rb +180 -0
  158. data/test/test_idgxmlbuilder.rb +608 -0
  159. data/test/test_image_finder.rb +82 -0
  160. data/test/test_inaobuilder.rb +245 -0
  161. data/test/test_index.rb +174 -0
  162. data/test/test_latexbuilder.rb +732 -0
  163. data/test/test_lineinput.rb +182 -0
  164. data/test/test_makerhelper.rb +66 -0
  165. data/test/test_markdownbuilder.rb +125 -0
  166. data/test/test_pdfmaker.rb +171 -0
  167. data/test/test_pdfmaker_cmd.rb +40 -0
  168. data/test/test_preprocessor.rb +23 -0
  169. data/test/test_review_ext.rb +31 -0
  170. data/test/test_template.rb +26 -0
  171. data/test/test_textutils.rb +32 -0
  172. data/test/test_topbuilder.rb +291 -0
  173. data/test/test_uuid.rb +157 -0
  174. metadata +357 -0
@@ -0,0 +1,424 @@
1
+ # encoding: utf-8
2
+ # = epubcommon.rb -- super class for EPUBv2 and EPUBv3
3
+ #
4
+ # Copyright (c) 2010-2014 Kenshi Muto and Masayoshi Takahashi
5
+ #
6
+ # This program is free software.
7
+ # You can distribute or modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ # For details of the GNU LGPL, see the file "COPYING".
10
+ #
11
+
12
+ require 'epubmaker/producer'
13
+ require 'review/i18n'
14
+ require 'cgi'
15
+ require 'shellwords'
16
+
17
+ module EPUBMaker
18
+
19
+ # EPUBCommon is the common class for EPUB producer.
20
+ class EPUBCommon
21
+ # Construct object with parameter hash +params+ and message resource hash +res+.
22
+ def initialize(producer)
23
+ @producer = producer
24
+ end
25
+
26
+ # Return mimetype content.
27
+ def mimetype
28
+ "application/epub+zip"
29
+ end
30
+
31
+ def opf_path
32
+ "OEBPS/#{@producer.params["bookname"]}.opf"
33
+ end
34
+
35
+ def opf_coverimage
36
+ s = ""
37
+ if @producer.params["coverimage"]
38
+ file = nil
39
+ @producer.contents.each do |item|
40
+ if item.media =~ /\Aimage/ && item.file =~ /#{@producer.params["coverimage"]}\Z/
41
+ s << %Q[ <meta name="cover" content="#{item.id}"/>\n]
42
+ file = item.file
43
+ break
44
+ end
45
+ end
46
+ raise "coverimage #{@producer.params["coverimage"]} not found. Abort." if file.nil?
47
+ end
48
+ s
49
+ end
50
+
51
+ def ncx_isbn
52
+ if @producer.params["isbn"].nil?
53
+ %Q[ <meta name="dtb:uid" content="#{@producer.params["urnid"]}"/>\n]
54
+ else
55
+ %Q[ <meta name="dtb:uid" content="#{@producer.params["isbn"]}"/>\n]
56
+ end
57
+ end
58
+
59
+ def ncx_doctitle
60
+ <<EOT
61
+ <docTitle>
62
+ <text>#{CGI.escapeHTML(@producer.params["title"])}</text>
63
+ </docTitle>
64
+ <docAuthor>
65
+ <text>#{@producer.params["aut"].nil? ? "" : CGI.escapeHTML(@producer.params["aut"].join(", "))}</text>
66
+ </docAuthor>
67
+ EOT
68
+ end
69
+
70
+ def ncx_navmap(indentarray)
71
+ s = <<EOT
72
+ <navMap>
73
+ <navPoint id="top" playOrder="1">
74
+ <navLabel>
75
+ <text>#{CGI.escapeHTML(@producer.params["title"])}</text>
76
+ </navLabel>
77
+ <content src="#{@producer.params["cover"]}"/>
78
+ </navPoint>
79
+ EOT
80
+
81
+ nav_count = 2
82
+
83
+ unless @producer.params["mytoc"].nil?
84
+ s << <<EOT
85
+ <navPoint id="toc" playOrder="#{nav_count}">
86
+ <navLabel>
87
+ <text>#{@producer.res.v("toctitle")}</text>
88
+ </navLabel>
89
+ <content src="#{@producer.params["bookname"]}-toc.#{@producer.params["htmlext"]}"/>
90
+ </navPoint>
91
+ EOT
92
+ nav_count += 1
93
+ end
94
+
95
+ @producer.contents.each do |item|
96
+ next if item.title.nil?
97
+ indent = indentarray.nil? ? [""] : indentarray
98
+ level = item.level.nil? ? 0 : (item.level - 1)
99
+ level = indent.size - 1 if level >= indent.size
100
+ s << <<EOT
101
+ <navPoint id="nav-#{nav_count}" playOrder="#{nav_count}">
102
+ <navLabel>
103
+ <text>#{indent[level]}#{CGI.escapeHTML(item.title)}</text>
104
+ </navLabel>
105
+ <content src="#{item.file}"/>
106
+ </navPoint>
107
+ EOT
108
+ nav_count += 1
109
+ end
110
+
111
+ s << <<EOT
112
+ </navMap>
113
+ EOT
114
+ s
115
+ end
116
+
117
+ # Return container content.
118
+ def container
119
+ @opf_path = opf_path
120
+ tmplfile = File.expand_path('./xml/container.xml.erb', ReVIEW::Template::TEMPLATE_DIR)
121
+ tmpl = ReVIEW::Template.load(tmplfile)
122
+ tmpl.result(binding)
123
+ end
124
+
125
+ # Return cover content.
126
+ def cover(type=nil)
127
+ @body_ext = type.nil? ? "" : " epub:type=\"#{type}\""
128
+
129
+ if @producer.params["coverimage"]
130
+ file = @producer.coverimage
131
+ if !file
132
+ raise "coverimage #{@producer.params["coverimage"]} not found. Abort."
133
+ end
134
+ @body = <<-EOT
135
+ <div id="cover-image" class="cover-image">
136
+ <img src="#{file}" alt="#{CGI.escapeHTML(@producer.params["title"])}" class="max"/>
137
+ </div>
138
+ EOT
139
+ else
140
+ @body = <<-EOT
141
+ <h1 class="cover-title">#{CGI.escapeHTML(@producer.params["title"])}</h1>
142
+ EOT
143
+ end
144
+
145
+ @title = @producer.params['title']
146
+ @language = @producer.params['language']
147
+ @stylesheets = @producer.params["stylesheet"]
148
+ if @producer.params["htmlversion"].to_i == 5
149
+ tmplfile = File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
150
+ else
151
+ tmplfile = File.expand_path('./html/layout-xhtml1.html.erb', ReVIEW::Template::TEMPLATE_DIR)
152
+ end
153
+ tmpl = ReVIEW::Template.load(tmplfile)
154
+ tmpl.result(binding)
155
+ end
156
+
157
+ # Return title (copying) content.
158
+ def titlepage
159
+ @title = @producer.params["title"]
160
+
161
+ @body = <<EOT
162
+ <h1 class="tp-title">#{CGI.escapeHTML(@title)}</h1>
163
+ EOT
164
+ if @producer.params["aut"]
165
+ @body << <<EOT
166
+ <p>
167
+ <br />
168
+ <br />
169
+ </p>
170
+ <h2 class="tp-author">#{CGI.escapeHTML(@producer.params["aut"].join(", "))}</h2>
171
+ EOT
172
+ end
173
+
174
+ publisher = @producer.params["pbl"] || @producer.params["prt"] # XXX Backward Compatiblity
175
+ if publisher
176
+ @body << <<EOT
177
+ <p>
178
+ <br />
179
+ <br />
180
+ <br />
181
+ <br />
182
+ </p>
183
+ <h3 class="tp-publisher">#{CGI.escapeHTML(publisher.join(", "))}</h3>
184
+ EOT
185
+ end
186
+
187
+ @language = @producer.params['language']
188
+ @stylesheets = @producer.params["stylesheet"]
189
+ if @producer.params["htmlversion"].to_i == 5
190
+ tmplfile = File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
191
+ else
192
+ tmplfile = File.expand_path('./html/layout-xhtml1.html.erb', ReVIEW::Template::TEMPLATE_DIR)
193
+ end
194
+ tmpl = ReVIEW::Template.load(tmplfile)
195
+ tmpl.result(binding)
196
+ end
197
+
198
+ # Return colophon content.
199
+ def colophon
200
+ @title = @producer.res.v("colophontitle")
201
+ @body = <<EOT
202
+ <div class="colophon">
203
+ EOT
204
+
205
+ if @producer.params["subtitle"].nil?
206
+ @body << <<EOT
207
+ <p class="title">#{CGI.escapeHTML(@producer.params["title"])}</p>
208
+ EOT
209
+ else
210
+ @body << <<EOT
211
+ <p class="title">#{CGI.escapeHTML(@producer.params["title"])}<br /><span class="subtitle">#{CGI.escapeHTML(@producer.params["subtitle"])}</span></p>
212
+ EOT
213
+ end
214
+
215
+ if @producer.params["date"] || @producer.params["history"]
216
+ @body << %Q[ <div class="pubhistory">\n]
217
+ if @producer.params["history"]
218
+ @producer.params["history"].each_with_index do |items, edit|
219
+ items.each_with_index do |item, rev|
220
+ editstr = (edit == 0) ? ReVIEW::I18n.t("first_edition") : ReVIEW::I18n.t("nth_edition","#{edit+1}")
221
+ revstr = ReVIEW::I18n.t("nth_impression", "#{rev+1}")
222
+ if item =~ /\A\d+\-\d+\-\d+\Z/
223
+ @body << %Q[ <p>#{ReVIEW::I18n.t("published_by1", [date_to_s(item), editstr+revstr])}</p>\n]
224
+ else
225
+ # custom date with string
226
+ item.match(/\A(\d+\-\d+\-\d+)[\s ](.+)/) do |m|
227
+ @body << %Q[ <p>#{ReVIEW::I18n.t("published_by3", [date_to_s(m[1]), m[2]])}</p>\n]
228
+ end
229
+ end
230
+ end
231
+ end
232
+ else
233
+ @body << %Q[ <p>#{ReVIEW::I18n.t("published_by2", date_to_s(@producer.params["date"]))}</p>\n]
234
+ end
235
+ @body << %Q[ </div>\n]
236
+ end
237
+
238
+ @body << %Q[ <table class="colophon">\n]
239
+ @body << %w[aut csl trl dsr ill edt pbl prt pht].map{ |role|
240
+ if @producer.params[role]
241
+ %Q[ <tr><th>#{@producer.res.v(role)}</th><td>#{CGI.escapeHTML(@producer.params[role].join(", "))}</td></tr>\n]
242
+ else
243
+ ""
244
+ end
245
+ }.join("")
246
+
247
+ if @producer.params["isbn"].to_s =~ /\A\d{10}\Z/ || @producer.params["isbn"].to_s =~ /\A\d{13}\Z/
248
+ isbn = nil
249
+ str = @producer.params["isbn"].to_s
250
+ if str.size == 10
251
+ isbn = "#{str[0..0]}-#{str[1..5]}-#{str[6..8]}-#{str[9..9]}"
252
+ else
253
+ isbn = "#{str[0..2]}-#{str[3..3]}-#{str[4..8]}-#{str[9..11]}-#{str[12..12]}"
254
+ end
255
+ @body << %Q[ <tr><th>ISBN</th><td>#{isbn}</td></tr>\n]
256
+ end
257
+ @body << %Q[ </table>\n]
258
+ if !@producer.params["rights"].nil? && @producer.params["rights"].size > 0
259
+ @body << %Q[ <p class="copyright">#{@producer.params["rights"].join("<br />")}</p>]
260
+ end
261
+ @body << %Q[ </div>\n]
262
+
263
+ @language = @producer.params['language']
264
+ @stylesheets = @producer.params["stylesheet"]
265
+ if @producer.params["htmlversion"].to_i == 5
266
+ tmplfile = File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
267
+ else
268
+ tmplfile = File.expand_path('./html/layout-xhtml1.html.erb', ReVIEW::Template::TEMPLATE_DIR)
269
+ end
270
+ tmpl = ReVIEW::Template.load(tmplfile)
271
+ tmpl.result(binding)
272
+ end
273
+
274
+ def date_to_s(date)
275
+ require 'date'
276
+ d = Date.parse(date)
277
+ d.strftime(ReVIEW::I18n.t("date_format"))
278
+ end
279
+
280
+ # Return own toc content.
281
+ def mytoc
282
+ @title = @producer.res.v("toctitle")
283
+
284
+ @body = %Q[ <h1 class="toc-title">#{@producer.res.v("toctitle")}</h1>\n]
285
+ if @producer.params["epubmaker"]["flattoc"].nil?
286
+ @body << hierarchy_ncx("ul")
287
+ else
288
+ @body << flat_ncx("ul", @producer.params["epubmaker"]["flattocindent"])
289
+ end
290
+
291
+ @language = @producer.params['language']
292
+ @stylesheets = @producer.params["stylesheet"]
293
+ if @producer.params["htmlversion"].to_i == 5
294
+ tmplfile = File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
295
+ else
296
+ tmplfile = File.expand_path('./html/layout-xhtml1.html.erb', ReVIEW::Template::TEMPLATE_DIR)
297
+ end
298
+ tmpl = ReVIEW::Template.load(tmplfile)
299
+ tmpl.result(binding)
300
+ end
301
+
302
+ def hierarchy_ncx(type)
303
+ require 'rexml/document'
304
+ level = 1
305
+ find_jump = nil
306
+ has_part = nil
307
+ toclevel = @producer.params["toclevel"].to_i
308
+
309
+ # check part existance
310
+ @producer.contents.each do |item|
311
+ if item.notoc.nil? && item.chaptype == "part"
312
+ has_part = true
313
+ break
314
+ end
315
+ end
316
+
317
+ if !has_part.nil?
318
+ @producer.contents.each do |item|
319
+ item.level += 1 if item.chaptype == "part" || item.chaptype == "body"
320
+ item.notoc = true if (item.chaptype == "pre" || item.chaptype == "post") && !item.level.nil? && (item.level + 1 == toclevel) # FIXME: 部があるときに前後の処理が困難
321
+ end
322
+ toclevel += 1
323
+ end
324
+
325
+ doc = REXML::Document.new(%Q[<#{type} class="toc-h#{level}"><li /></#{type}>])
326
+ doc.context[:attribute_quote] = :quote
327
+
328
+ e = doc.root.elements[1] # first <li/>
329
+ @producer.contents.each do |item|
330
+ next if !item.notoc.nil? || item.level.nil? || item.file.nil? || item.title.nil? || item.level > toclevel
331
+
332
+ if item.level == level
333
+ e2 = e.parent.add_element("li")
334
+ e = e2
335
+ elsif item.level > level
336
+ find_jump = true if (item.level - level) > 1
337
+ # deeper
338
+ (level + 1).upto(item.level) do |n|
339
+ if e.size == 0
340
+ # empty span for epubcheck
341
+ e.attributes["style"] = "list-style-type: none;"
342
+ es = e.add_element("span", {"style"=>"display:none;"})
343
+ es.add_text(REXML::Text.new("&#xa0;", false, nil, true))
344
+ end
345
+
346
+ e2 = e.add_element(type, {"class" => "toc-h#{n}"})
347
+ e3 = e2.add_element("li")
348
+ e = e3
349
+ end
350
+ level = item.level
351
+ elsif item.level < level
352
+ # shallower
353
+ (level - 1).downto(item.level) do |n|
354
+ e = e.parent.parent
355
+ end
356
+ e2 = e.parent.add_element("li")
357
+ e = e2
358
+ level = item.level
359
+ end
360
+ e2 = e.add_element("a", {"href" => item.file})
361
+ e2.add_text(REXML::Text.new(item.title, true))
362
+ end
363
+
364
+ warn "found level jumping in table of contents. consider to use 'epubmaker:flattoc: true' for strict ePUB validator." unless find_jump.nil?
365
+
366
+ doc.to_s.gsub("<li/>", "").gsub("</li>", "</li>\n").gsub("<#{type} ", "\n" + '\&') # ugly
367
+ end
368
+
369
+ def flat_ncx(type, indent=nil)
370
+ s = %Q[<#{type} class="toc-h1">\n]
371
+ @producer.contents.each do |item|
372
+ next if !item.notoc.nil? || item.level.nil? || item.file.nil? || item.title.nil? || item.level > @producer.params["toclevel"].to_i
373
+ is = indent == true ? " " * item.level : ""
374
+ s << %Q[<li><a href="#{item.file}">#{is}#{CGI.escapeHTML(item.title)}</a></li>\n]
375
+ end
376
+ s << %Q[</#{type}>\n]
377
+
378
+ s
379
+ end
380
+
381
+ def produce_write_common(basedir, tmpdir)
382
+ File.open("#{tmpdir}/mimetype", "w") {|f| @producer.mimetype(f) }
383
+
384
+ FileUtils.mkdir_p("#{tmpdir}/META-INF")
385
+ File.open("#{tmpdir}/META-INF/container.xml", "w") {|f| @producer.container(f) }
386
+
387
+ FileUtils.mkdir_p("#{tmpdir}/OEBPS")
388
+ File.open(File.join(tmpdir, opf_path), "w") {|f| @producer.opf(f) }
389
+
390
+ if File.exist?("#{basedir}/#{@producer.params["cover"]}")
391
+ FileUtils.cp("#{basedir}/#{@producer.params["cover"]}", "#{tmpdir}/OEBPS")
392
+ else
393
+ File.open("#{tmpdir}/OEBPS/#{@producer.params["cover"]}", "w") {|f| @producer.cover(f) }
394
+ end
395
+
396
+ @producer.contents.each do |item|
397
+ next if item.file =~ /#/ # skip subgroup
398
+ fname = "#{basedir}/#{item.file}"
399
+ raise "#{fname} doesn't exist. Abort." unless File.exist?(fname)
400
+ FileUtils.mkdir_p(File.dirname("#{tmpdir}/OEBPS/#{item.file}"))
401
+ FileUtils.cp(fname, "#{tmpdir}/OEBPS/#{item.file}")
402
+ end
403
+ end
404
+
405
+ def export_zip(tmpdir, epubfile)
406
+ Dir.chdir(tmpdir) {|d| `#{@producer.params["epubmaker"]["zip_stage1"]} #{epubfile.shellescape} mimetype` }
407
+ Dir.chdir(tmpdir) {|d| `#{@producer.params["epubmaker"]["zip_stage2"]} #{epubfile.shellescape} META-INF OEBPS #{@producer.params["epubmaker"]["zip_addpath"]}` }
408
+ end
409
+
410
+ def legacy_cover_and_title_file(loadfile, writefile)
411
+ @title = @producer.params["booktitle"]
412
+ s = ""
413
+ File.open(loadfile) do |f|
414
+ f.each_line do |l|
415
+ s << l
416
+ end
417
+ end
418
+
419
+ File.open(writefile, "w") do |f|
420
+ f.puts s
421
+ end
422
+ end
423
+ end
424
+ end
@@ -0,0 +1,139 @@
1
+ # encoding: utf-8
2
+ # = epubv2.rb -- EPUB version 2 producer.
3
+ #
4
+ # Copyright (c) 2010-2015 Kenshi Muto and Masayoshi Takahashi
5
+ #
6
+ # This program is free software.
7
+ # You can distribute or modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ # For details of the GNU LGPL, see the file "COPYING".
10
+ #
11
+
12
+ require 'epubmaker/epubcommon'
13
+ require 'cgi'
14
+
15
+ module EPUBMaker
16
+
17
+ # EPUBv2 is EPUB version 2 producer.
18
+ class EPUBv2 < EPUBCommon
19
+ # Construct object with parameter hash +params+ and message resource hash +res+.
20
+ def initialize(producer)
21
+ super
22
+ end
23
+
24
+ # Return opf file content.
25
+ def opf
26
+ @opf_metainfo = opf_metainfo
27
+ @opf_coverimage = opf_coverimage
28
+ @opf_manifest = opf_manifest
29
+ @opf_toc = opf_tocx
30
+
31
+ tmplfile = File.expand_path('./opf/epubv2.opf.erb', ReVIEW::Template::TEMPLATE_DIR)
32
+ tmpl = ReVIEW::Template.load(tmplfile)
33
+ return tmpl.result(binding)
34
+ end
35
+
36
+ def opf_metainfo
37
+ s = ""
38
+ %w[title language date type format source description relation coverage subject rights].each do |item|
39
+ next if @producer.params[item].nil?
40
+ if @producer.params[item].instance_of?(Array)
41
+ s << @producer.params[item].map {|i| %Q[ <dc:#{item}>#{CGI.escapeHTML(i.to_s)}</dc:#{item}>\n]}.join
42
+ else
43
+ s << %Q[ <dc:#{item}>#{CGI.escapeHTML(@producer.params[item].to_s)}</dc:#{item}>\n]
44
+ end
45
+ end
46
+
47
+ # ID
48
+ if @producer.params["isbn"].nil?
49
+ s << %Q[ <dc:identifier id="BookId">#{@producer.params["urnid"]}</dc:identifier>\n]
50
+ else
51
+ s << %Q[ <dc:identifier id="BookId" opf:scheme="ISBN">#{@producer.params["isbn"]}</dc:identifier>\n]
52
+ end
53
+
54
+ # creator (should be array)
55
+ %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|
56
+ next if @producer.params[role].nil?
57
+ @producer.params[role].each do |v|
58
+ s << %Q[ <dc:creator opf:role="#{role.sub('a-', '')}">#{CGI.escapeHTML(v)}</dc:creator>\n]
59
+ end
60
+ end
61
+
62
+ # contributor (should be array)
63
+ %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|
64
+ next if @producer.params[role].nil?
65
+ @producer.params[role].each do |v|
66
+ s << %Q[ <dc:contributor opf:role="#{role}">#{CGI.escapeHTML(v)}</dc:contributor>\n]
67
+ if role == "prt"
68
+ s << %Q[ <dc:publisher>#{v}</dc:publisher>\n]
69
+ end
70
+ end
71
+ end
72
+
73
+ s
74
+ end
75
+
76
+ def opf_manifest
77
+ s = ""
78
+ s << <<EOT
79
+ <manifest>
80
+ <item id="ncx" href="#{@producer.params["bookname"]}.ncx" media-type="application/x-dtbncx+xml"/>
81
+ <item id="#{@producer.params["bookname"]}" href="#{@producer.params["cover"]}" media-type="application/xhtml+xml"/>
82
+ EOT
83
+
84
+ s << %Q[ <item id="toc" href="#{@producer.params["bookname"]}-toc.#{@producer.params["htmlext"]}" media-type="application/xhtml+xml"/>\n] if @producer.params["toc"] && @producer.params["mytoc"]
85
+
86
+ @producer.contents.each do |item|
87
+ next if item.file =~ /#/ # skip subgroup
88
+ s << %Q[ <item id="#{item.id}" href="#{item.file}" media-type="#{item.media}"/>\n]
89
+ end
90
+ s << %Q[ </manifest>\n]
91
+ s
92
+ end
93
+
94
+ def opf_tocx
95
+ if @producer.params["epubmaker"]["cover_linear"] && @producer.params["epubmaker"]["cover_linear"] != "no"
96
+ cover_linear = "yes"
97
+ else
98
+ cover_linear = "no"
99
+ end
100
+
101
+ s = ""
102
+ s << %Q[ <spine toc="ncx">\n]
103
+ s << %Q[ <itemref idref="#{@producer.params["bookname"]}" linear="#{cover_linear}"/>\n]
104
+ s << %Q[ <itemref idref="toc" />\n] unless @producer.params["mytoc"].nil?
105
+
106
+ @producer.contents.each do |item|
107
+ next if item.media !~ /xhtml\+xml/ # skip non XHTML
108
+ s << %Q[ <itemref idref="#{item.id}"/>\n] if item.notoc.nil?
109
+ end
110
+ s << %Q[ </spine>\n]
111
+ s
112
+ end
113
+
114
+ # Return ncx content. +indentarray+ has prefix marks for each level.
115
+ def ncx(indentarray)
116
+ @ncx_isbn = ncx_isbn
117
+ @ncx_doctitle = ncx_doctitle
118
+ @ncx_navmap = ncx_navmap(indentarray)
119
+
120
+ tmplfile = File.expand_path('./ncx/epubv2.ncx.erb', ReVIEW::Template::TEMPLATE_DIR)
121
+ tmpl = ReVIEW::Template.load(tmplfile)
122
+ return tmpl.result(binding)
123
+ end
124
+
125
+ # Produce EPUB file +epubfile+.
126
+ # +basedir+ points the directory has contents.
127
+ # +tmpdir+ defines temporary directory.
128
+ def produce(epubfile, basedir, tmpdir)
129
+ produce_write_common(basedir, tmpdir)
130
+
131
+ File.open("#{tmpdir}/OEBPS/#{@producer.params["bookname"]}.ncx", "w") {|f| @producer.ncx(f, @producer.params["epubmaker"]["ncxindent"]) }
132
+ File.open("#{tmpdir}/OEBPS/#{@producer.params["bookname"]}-toc.#{@producer.params["htmlext"]}", "w") {|f| @producer.mytoc(f) } unless @producer.params["mytoc"].nil?
133
+
134
+ @producer.call_hook(@producer.params["epubmaker"]["hook_prepack"], tmpdir)
135
+ export_zip(tmpdir, epubfile)
136
+ end
137
+
138
+ end
139
+ end