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,64 @@
1
+ # -*- coding: utf-8 -*-
2
+ module ReVIEW
3
+ class Configure < Hash
4
+
5
+ attr_accessor :maker
6
+
7
+ def self.values
8
+ Configure[
9
+ # These parameters can be overridden by YAML file.
10
+ "bookname"=> "example", # it defines epub file name also
11
+ "booktitle" => "Re:VIEW Sample Book",
12
+ "title" => nil,
13
+ "aut" => nil, # author
14
+ "prt" => nil, # printer(publisher)
15
+ "asn" => nil, # associated name
16
+ "ant" => nil, # bibliographic antecedent
17
+ "clb" => nil, # Collaborator
18
+ "edt" => nil, # Editor
19
+ "dsr" => nil, # Designer
20
+ "ill" => nil, # Illustrator
21
+ "pht" => nil, # Photographer
22
+ "trl" => nil, # Translator
23
+ "date" => nil, # publishing date
24
+ "rights" => nil, # Copyright messages
25
+ "description" => nil, # Description
26
+ "urnid" => nil, # Identifier (nil makes random uuid)
27
+ "stylesheet" => "stylesheet.css", # stylesheet file
28
+ "coverfile" => nil, # content file of body of cover page
29
+ "mytoc" => nil, # whether make own table of contents or not
30
+ "params" => "", # specify review2html parameters
31
+ "toclevel" => 3, # level of toc
32
+ "secnolevel" => 2, # level of section #
33
+ "epubversion" => 2,
34
+ "titlepage" => true, # Use title page
35
+ "toc" => nil, # Use table of contents in body
36
+ "colophon" => nil, # Use colophon
37
+ "debug" => nil, # debug flag
38
+ "catalogfile" => 'catalog.yml',
39
+ "language" => 'ja', # XXX default language should be JA??
40
+
41
+ "chapter_file" => 'CHAPS',
42
+ "part_file" => 'PART',
43
+ "reject_file" => 'REJECT',
44
+ "predef_file" => 'PREDEF',
45
+ "postdef_file" => 'POSTDEF',
46
+ "page_metric" => ReVIEW::Book::PageMetric.a5,
47
+ "ext" => '.re',
48
+ "image_dir" => 'images',
49
+ "image_types" => %w( .ai .psd .eps .pdf .tif .tiff .png .bmp .jpg .jpeg .gif .svg ),
50
+ "bib_file" => "bib.re",
51
+ "colophon_order" => %w(aut csl trl dsr ill cov edt pbl contact prt),
52
+ ]
53
+ end
54
+
55
+ def [](key)
56
+ if self.key?(key)
57
+ return self.fetch(key)
58
+ end
59
+ if @maker && self.key?(@maker)
60
+ return self.fetch(@maker).fetch(key, nil)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,18 @@
1
+ # epubbuilder.rb
2
+ # just for compatibility
3
+ #
4
+ # Copyright (c) 2010 Kenshi Muto
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
+ #
10
+
11
+ require 'review/htmlbuilder'
12
+
13
+ module ReVIEW
14
+
15
+ class EPUBBuilder < HTMLBuilder
16
+ end
17
+
18
+ end # module ReVIEW
@@ -0,0 +1,480 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (c) 2010-2015 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
+ require 'review'
11
+ require 'rexml/document'
12
+ require 'rexml/streamlistener'
13
+ require 'epubmaker'
14
+ require 'review/htmltoc'
15
+
16
+ module ReVIEW
17
+ class EPUBMaker
18
+ include ::EPUBMaker
19
+ include REXML
20
+
21
+ def initialize
22
+ @producer = nil
23
+ @htmltoc = nil
24
+ @buildlogtxt = "build-log.txt"
25
+ end
26
+
27
+ def log(s)
28
+ puts s if @params["debug"].present?
29
+ end
30
+
31
+ def load_yaml(yamlfile)
32
+ @params = ReVIEW::Configure.values.merge(YAML.load_file(yamlfile)) # FIXME:設定がRe:VIEW側とepubmaker/producer.rb側の2つに分かれて面倒
33
+ @producer = Producer.new(@params)
34
+ @producer.load(yamlfile)
35
+ @params = @producer.params
36
+ end
37
+
38
+ def produce(yamlfile, bookname=nil)
39
+ load_yaml(yamlfile)
40
+ I18n.setup(@params["language"])
41
+ bookname = @params["bookname"] if bookname.nil?
42
+ booktmpname = "#{bookname}-epub"
43
+
44
+ log("Loaded yaml file (#{yamlfile}). I will produce #{bookname}.epub.")
45
+
46
+ FileUtils.rm_f("#{bookname}.epub")
47
+ FileUtils.rm_rf(booktmpname) if @params["debug"]
48
+
49
+ basetmpdir = Dir.mktmpdir("#{bookname}-", Dir.pwd)
50
+ begin
51
+ log("Created first temporary directory as #{basetmpdir}.")
52
+
53
+ call_hook("hook_beforeprocess", basetmpdir)
54
+
55
+ @htmltoc = ReVIEW::HTMLToc.new(basetmpdir)
56
+ ## copy all files into basetmpdir
57
+ copy_stylesheet(basetmpdir)
58
+
59
+ copy_frontmatter(basetmpdir)
60
+ call_hook("hook_afterfrontmatter", basetmpdir)
61
+
62
+ build_body(basetmpdir, yamlfile)
63
+ call_hook("hook_afterbody", basetmpdir)
64
+
65
+ copy_backmatter(basetmpdir)
66
+ call_hook("hook_afterbackmatter", basetmpdir)
67
+
68
+ ## push contents in basetmpdir into @producer
69
+ push_contents(basetmpdir)
70
+
71
+ if @params["epubmaker"]["verify_target_images"].present?
72
+ verify_target_images(basetmpdir)
73
+ copy_images(@params["imagedir"], basetmpdir)
74
+ else
75
+ copy_images(@params["imagedir"], "#{basetmpdir}/images")
76
+ end
77
+
78
+ copy_resources("covers", "#{basetmpdir}/images")
79
+ copy_resources("adv", "#{basetmpdir}/images")
80
+ copy_resources(@params["fontdir"], "#{basetmpdir}/fonts", @params["font_ext"])
81
+
82
+ call_hook("hook_aftercopyimage", basetmpdir)
83
+
84
+ @producer.import_imageinfo("#{basetmpdir}/images", basetmpdir)
85
+ @producer.import_imageinfo("#{basetmpdir}/fonts", basetmpdir, @params["font_ext"])
86
+
87
+ epubtmpdir = nil
88
+ if @params["debug"].present?
89
+ epubtmpdir = "#{Dir.pwd}/#{booktmpname}"
90
+ Dir.mkdir(epubtmpdir)
91
+ end
92
+ log("Call ePUB producer.")
93
+ @producer.produce("#{bookname}.epub", basetmpdir, epubtmpdir)
94
+ log("Finished.")
95
+ ensure
96
+ FileUtils.remove_entry_secure basetmpdir if @params["debug"].nil?
97
+ end
98
+ end
99
+
100
+ def call_hook(hook_name, *params)
101
+ filename = @params["epubmaker"][hook_name]
102
+ log("Call #{hook_name}. (#{filename})")
103
+ if filename.present? && File.exist?(filename) && FileTest.executable?(filename)
104
+ if ENV["REVIEW_SAFE_MODE"].to_i & 1 > 0
105
+ warn "hook is prohibited in safe mode. ignored."
106
+ else
107
+ system(filename, *params)
108
+ end
109
+ end
110
+ end
111
+
112
+ def verify_target_images(basetmpdir)
113
+ @producer.contents.each do |content|
114
+ if content.media == "application/xhtml+xml"
115
+
116
+ File.open("#{basetmpdir}/#{content.file}") do |f|
117
+ Document.new(File.new(f)).each_element("//img") do |e|
118
+ @params["epubmaker"]["force_include_images"].push(e.attributes["src"])
119
+ if e.attributes["src"] =~ /svg\Z/i
120
+ content.properties.push("svg")
121
+ end
122
+ end
123
+ end
124
+ elsif content.media == "text/css"
125
+ File.open("#{basetmpdir}/#{content.file}") do |f|
126
+ f.each_line do |l|
127
+ l.scan(/url\((.+?)\)/) do |m|
128
+ @params["epubmaker"]["force_include_images"].push($1.strip)
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ @params["epubmaker"]["force_include_images"] = @params["epubmaker"]["force_include_images"].sort.uniq
135
+ end
136
+
137
+ def copy_images(resdir, destdir, allow_exts=nil)
138
+ return nil unless File.exist?(resdir)
139
+ allow_exts = @params["image_ext"] if allow_exts.nil?
140
+ FileUtils.mkdir_p(destdir)
141
+ if @params["epubmaker"]["verify_target_images"].present?
142
+ @params["epubmaker"]["force_include_images"].each do |file|
143
+ unless File.exist?(file)
144
+ warn "#{file} is not found, skip." if file !~ /\Ahttp[s]?:/
145
+ next
146
+ end
147
+ basedir = File.dirname(file)
148
+ FileUtils.mkdir_p("#{destdir}/#{basedir}")
149
+ log("Copy #{file} to the temporary directory.")
150
+ FileUtils.cp(file, "#{destdir}/#{basedir}")
151
+ end
152
+ else
153
+ recursive_copy_files(resdir, destdir, allow_exts)
154
+ end
155
+ end
156
+
157
+ def copy_resources(resdir, destdir, allow_exts=nil)
158
+ return nil unless File.exist?(resdir)
159
+ allow_exts = @params["image_ext"] if allow_exts.nil?
160
+ FileUtils.mkdir_p(destdir)
161
+ recursive_copy_files(resdir, destdir, allow_exts)
162
+ end
163
+
164
+ def recursive_copy_files(resdir, destdir, allow_exts)
165
+ Dir.open(resdir) do |dir|
166
+ dir.each do |fname|
167
+ next if fname =~ /\A\./
168
+ if FileTest.directory?("#{resdir}/#{fname}")
169
+ recursive_copy_files("#{resdir}/#{fname}", "#{destdir}/#{fname}", allow_exts)
170
+ else
171
+ if fname =~ /\.(#{allow_exts.join("|")})\Z/i
172
+ FileUtils.mkdir_p(destdir)
173
+ log("Copy #{resdir}/#{fname} to the temporary directory.")
174
+ FileUtils.cp("#{resdir}/#{fname}", destdir)
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ def build_body(basetmpdir, yamlfile)
182
+ @precount = 0
183
+ @bodycount = 0
184
+ @postcount = 0
185
+
186
+ @manifeststr = ""
187
+ @ncxstr = ""
188
+ @tocdesc = Array.new
189
+ # toccount = 2 ## not used
190
+
191
+ basedir = Dir.pwd
192
+ base_path = Pathname.new(basedir)
193
+ book = ReVIEW::Book.load(basedir)
194
+ book.load_config(yamlfile)
195
+ book.parts.each do |part|
196
+ htmlfile = nil
197
+ if part.name.present?
198
+ if part.file?
199
+ build_chap(part, base_path, basetmpdir, yamlfile, true)
200
+ else
201
+ htmlfile = "part_#{part.number}.#{@params["htmlext"]}"
202
+ build_part(part, basetmpdir, htmlfile)
203
+ title = ReVIEW::I18n.t("part", part.number)
204
+ title += ReVIEW::I18n.t("chapter_postfix") + part.name.strip if part.name.strip.present?
205
+ @htmltoc.add_item(0, htmlfile, title, {:chaptype => "part"})
206
+ write_buildlogtxt(basetmpdir, htmlfile, "")
207
+ end
208
+ end
209
+
210
+ part.chapters.each do |chap|
211
+ build_chap(chap, base_path, basetmpdir, yamlfile, nil)
212
+ end
213
+
214
+ end
215
+ end
216
+
217
+ def build_part(part, basetmpdir, htmlfile)
218
+ log("Create #{htmlfile} from a template.")
219
+ File.open("#{basetmpdir}/#{htmlfile}", "w") do |f|
220
+ @body = ""
221
+ @body << "<div class=\"part\">\n"
222
+ @body << "<h1 class=\"part-number\">#{ReVIEW::I18n.t("part", part.number)}</h1>\n"
223
+ if part.name.strip.present?
224
+ @body << "<h2 class=\"part-title\">#{part.name.strip}</h2>\n"
225
+ end
226
+ @body << "</div>\n"
227
+
228
+ @language = @producer.params['language']
229
+ @stylesheets = @producer.params["stylesheet"]
230
+ if @producer.params["htmlversion"].to_i == 5
231
+ tmplfile = File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
232
+ else
233
+ tmplfile = File.expand_path('./html/layout-xhtml1.html.erb', ReVIEW::Template::TEMPLATE_DIR)
234
+ end
235
+ tmpl = ReVIEW::Template.load(tmplfile)
236
+ f.write tmpl.result(binding)
237
+ end
238
+ end
239
+
240
+ def build_chap(chap, base_path, basetmpdir, yamlfile, ispart=nil)
241
+ filename = ""
242
+
243
+ chaptype = "body"
244
+ if ispart.present?
245
+ chaptype = "part"
246
+ elsif chap.on_PREDEF?
247
+ chaptype = "pre"
248
+ elsif chap.on_APPENDIX?
249
+ chaptype = "post"
250
+ end
251
+
252
+ if ispart.present?
253
+ filename = chap.path
254
+ else
255
+ filename = Pathname.new(chap.path).relative_path_from(base_path).to_s
256
+ end
257
+ id = filename.sub(/\.re\Z/, "")
258
+
259
+ if @params["epubmaker"]["rename_for_legacy"] && ispart.nil?
260
+ if chap.on_PREDEF?
261
+ @precount += 1
262
+ id = sprintf("pre%02d", @precount)
263
+ elsif chap.on_APPENDIX?
264
+ @postcount += 1
265
+ id = sprintf("post%02d", @postcount)
266
+ else
267
+ @bodycount += 1
268
+ id = sprintf("chap%02d", @bodycount)
269
+ end
270
+ end
271
+
272
+ htmlfile = "#{id}.#{@params["htmlext"]}"
273
+ write_buildlogtxt(basetmpdir, htmlfile, filename)
274
+ log("Create #{htmlfile} from #{filename}.")
275
+
276
+ level = @params["secnolevel"]
277
+
278
+ # TODO: It would be nice if we can modify level in PART, PREDEF, or POSTDEF.
279
+ # But we have to care about section number reference (@<hd>) also.
280
+ #
281
+ # if !ispart.nil?
282
+ # level = @params["part_secnolevel"]
283
+ # else
284
+ # level = @params["pre_secnolevel"] if chap.on_PREDEF?
285
+ # level = @params["post_secnolevel"] if chap.on_APPENDIX?
286
+ # end
287
+
288
+ stylesheet = ""
289
+ if @params["stylesheet"].size > 0
290
+ stylesheet = "--stylesheet=#{@params["stylesheet"].join(",")}"
291
+ end
292
+
293
+ ENV["REVIEWFNAME"] = filename
294
+ system("#{ReVIEW::MakerHelper.bindir}/review-compile-peg --yaml=#{yamlfile} --target=html --level=#{level} --htmlversion=#{@params["htmlversion"]} --epubversion=#{@params["epubversion"]} #{stylesheet} #{@params["params"]} #{filename} > \"#{basetmpdir}/#{htmlfile}\"")
295
+
296
+ write_info_body(basetmpdir, id, htmlfile, ispart, chaptype)
297
+ end
298
+
299
+ def detect_properties(path)
300
+ properties = []
301
+ File.open(path) do |f|
302
+ doc = REXML::Document.new(f)
303
+ if REXML::XPath.first(doc, "//m:math", {'m' => 'http://www.w3.org/1998/Math/MathML'})
304
+ properties<< "mathml"
305
+ end
306
+ if REXML::XPath.first(doc, "//s:svg", {'s' => 'http://www.w3.org/2000/svg'})
307
+ properties<< "svg"
308
+ end
309
+ end
310
+ properties
311
+ end
312
+
313
+ def write_info_body(basetmpdir, id, filename, ispart=nil, chaptype=nil)
314
+ headlines = []
315
+ # FIXME:nonumを修正する必要あり
316
+ path = File.join(basetmpdir, filename)
317
+ Document.parse_stream(File.new(path), ReVIEWHeaderListener.new(headlines))
318
+ properties = detect_properties(path)
319
+ prop_str = ""
320
+ if properties.present?
321
+ prop_str = ",properties="+properties.join(" ")
322
+ end
323
+ first = true
324
+ headlines.each do |headline|
325
+ headline["level"] = 0 if ispart.present? && headline["level"] == 1
326
+ if first.nil?
327
+ @htmltoc.add_item(headline["level"], filename+"#"+headline["id"], headline["title"], {:chaptype => chaptype})
328
+ else
329
+ @htmltoc.add_item(headline["level"], filename, headline["title"], {:force_include => true, :chaptype => chaptype+prop_str})
330
+ first = nil
331
+ end
332
+ end
333
+ end
334
+
335
+ def push_contents(basetmpdir)
336
+ @htmltoc.each_item do |level, file, title, args|
337
+ next if level.to_i > @params["toclevel"] && args[:force_include].nil?
338
+ log("Push #{file} to ePUB contents.")
339
+
340
+ hash = {"file" => file, "level" => level.to_i, "title" => title, "chaptype" => args[:chaptype]}
341
+ if args[:id].present?
342
+ hash["id"] = args[:id]
343
+ end
344
+ if args[:properties].present?
345
+ hash["properties"] = args[:properties].split(" ")
346
+ end
347
+ @producer.contents.push(Content.new(hash))
348
+ end
349
+ end
350
+
351
+ def copy_stylesheet(basetmpdir)
352
+ if @params["stylesheet"].size > 0
353
+ @params["stylesheet"].each do |sfile|
354
+ FileUtils.cp(sfile, basetmpdir)
355
+ @producer.contents.push(Content.new("file" => sfile))
356
+ end
357
+ end
358
+ end
359
+
360
+ def copy_frontmatter(basetmpdir)
361
+ FileUtils.cp(@params["cover"], "#{basetmpdir}/#{File.basename(@params["cover"])}") if @params["cover"].present? && File.exist?(@params["cover"])
362
+
363
+ if @params["titlepage"]
364
+ if @params["titlefile"].nil?
365
+ build_titlepage(basetmpdir, "titlepage.#{@params["htmlext"]}")
366
+ else
367
+ FileUtils.cp(@params["titlefile"], "#{basetmpdir}/titlepage.#{@params["htmlext"]}")
368
+ end
369
+ @htmltoc.add_item(1, "titlepage.#{@params['htmlext']}", @producer.res.v("titlepagetitle"), {:chaptype => "pre"})
370
+ end
371
+
372
+ if @params["originaltitlefile"].present? && File.exist?(@params["originaltitlefile"])
373
+ FileUtils.cp(@params["originaltitlefile"], "#{basetmpdir}/#{File.basename(@params["originaltitlefile"])}")
374
+ @htmltoc.add_item(1, File.basename(@params["originaltitlefile"]), @producer.res.v("originaltitle"), {:chaptype => "pre"})
375
+ end
376
+
377
+ if @params["creditfile"].present? && File.exist?(@params["creditfile"])
378
+ FileUtils.cp(@params["creditfile"], "#{basetmpdir}/#{File.basename(@params["creditfile"])}")
379
+ @htmltoc.add_item(1, File.basename(@params["creditfile"]), @producer.res.v("credittitle"), {:chaptype => "pre"})
380
+ end
381
+ end
382
+
383
+ def build_titlepage(basetmpdir, htmlfile)
384
+ File.open("#{basetmpdir}/#{htmlfile}", "w") do |f|
385
+ @body = ""
386
+ @body << "<div class=\"titlepage\">"
387
+ @body << "<h1 class=\"tp-title\">#{CGI.escapeHTML(@params["booktitle"])}</h1>"
388
+ if @params["aut"]
389
+ @body << "<h2 class=\"tp-author\">#{@params["aut"].join(", ")}</h2>"
390
+ end
391
+ if @params["prt"]
392
+ @body << "<h3 class=\"tp-publisher\">#{@params["prt"].join(", ")}</h3>"
393
+ end
394
+ @body << "</div>"
395
+
396
+ @language = @producer.params['language']
397
+ @stylesheets = @producer.params["stylesheet"]
398
+ if @producer.params["htmlversion"].to_i == 5
399
+ tmplfile = File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
400
+ else
401
+ tmplfile = File.expand_path('./html/layout-xhtml1.html.erb', ReVIEW::Template::TEMPLATE_DIR)
402
+ end
403
+ tmpl = ReVIEW::Template.load(tmplfile)
404
+ f.write tmpl.result(binding)
405
+ end
406
+ end
407
+
408
+ def copy_backmatter(basetmpdir)
409
+ if @params["profile"]
410
+ FileUtils.cp(@params["profile"], "#{basetmpdir}/#{File.basename(@params["profile"])}")
411
+ @htmltoc.add_item(1, File.basename(@params["profile"]), @producer.res.v("profiletitle"), {:chaptype => "post"})
412
+ end
413
+
414
+ if @params["advfile"]
415
+ FileUtils.cp(@params["advfile"], "#{basetmpdir}/#{File.basename(@params["advfile"])}")
416
+ @htmltoc.add_item(1, File.basename(@params["advfile"]), @producer.res.v("advtitle"), {:chaptype => "post"})
417
+ end
418
+
419
+ if @params["colophon"]
420
+ if @params["colophon"].instance_of?(String) # FIXME:このやり方はやめる?
421
+ FileUtils.cp(@params["colophon"], "#{basetmpdir}/colophon.#{@params["htmlext"]}")
422
+ else
423
+ File.open("#{basetmpdir}/colophon.#{@params["htmlext"]}", "w") {|f| @producer.colophon(f) }
424
+ end
425
+ @htmltoc.add_item(1, "colophon.#{@params["htmlext"]}", @producer.res.v("colophontitle"), {:chaptype => "post"})
426
+ end
427
+
428
+ if @params["backcover"]
429
+ FileUtils.cp(@params["backcover"], "#{basetmpdir}/#{File.basename(@params["backcover"])}")
430
+ @htmltoc.add_item(1, File.basename(@params["backcover"]), @producer.res.v("backcovertitle"), {:chaptype => "post"})
431
+ end
432
+ end
433
+
434
+ def write_buildlogtxt(basetmpdir, htmlfile, reviewfile)
435
+ File.open("#{basetmpdir}/#{@buildlogtxt}", "a") do |f|
436
+ f.puts "#{htmlfile},#{reviewfile}"
437
+ end
438
+ end
439
+
440
+ class ReVIEWHeaderListener
441
+ include REXML::StreamListener
442
+ def initialize(headlines)
443
+ @level = nil
444
+ @content = ""
445
+ @headlines = headlines
446
+ end
447
+
448
+ def tag_start(name, attrs)
449
+ if name =~ /\Ah(\d+)/
450
+ if @level.present?
451
+ raise "#{name}, #{attrs}"
452
+ end
453
+ @level = $1.to_i
454
+ @id = attrs["id"] if attrs["id"].present?
455
+ elsif !@level.nil?
456
+ if name == "img" && attrs["alt"].present?
457
+ @content << attrs["alt"]
458
+ elsif name == "a" && attrs["id"].present?
459
+ @id = attrs["id"]
460
+ end
461
+ end
462
+ end
463
+
464
+ def tag_end(name)
465
+ if name =~ /\Ah\d+/
466
+ @headlines.push({"level" => @level, "id" => @id, "title" => @content}) if @id.present?
467
+ @content = ""
468
+ @level = nil
469
+ @id = nil
470
+ end
471
+ end
472
+
473
+ def text(text)
474
+ if @level.present?
475
+ @content << text.gsub("\t", " ") # FIXME:区切り文字
476
+ end
477
+ end
478
+ end
479
+ end
480
+ end