review-peg 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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