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,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