xpub 0.0.1

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.
@@ -0,0 +1,370 @@
1
+ module Xpub
2
+ class CallBook
3
+ class CallBuilder
4
+ attr_reader :name, :theme, :output
5
+
6
+ def initialize name, book
7
+ @name = name
8
+ @book = book
9
+ @theme = "default"
10
+ end
11
+
12
+ def output output
13
+ @output = output
14
+ end
15
+
16
+ def theme theme
17
+ @theme = theme
18
+ end
19
+
20
+ def build
21
+ raise "This method is not implement."
22
+ end
23
+
24
+ def validate
25
+ if @book.src_files.count == 0
26
+ raise "src_file is empty."
27
+ end
28
+ end
29
+
30
+ def src_path file
31
+ "#{Dir::getwd}/src/#{file}"
32
+ end
33
+
34
+ def tmp_path file
35
+ "#{Dir::getwd}/tmp/#{file}"
36
+ end
37
+
38
+ def output_path file
39
+ "#{Dir::getwd}/output/#{file}"
40
+ end
41
+
42
+ def copy_to_tmp files
43
+ files.each { |file|
44
+ pn = Pathname.new tmp_path(file.file)
45
+ FileUtils.mkdir_p(pn.dirname) unless FileTest.exist?(pn.dirname)
46
+
47
+ unless FileTest.exist?(tmp_path(file.file)) && File::mtime(src_path(file.file)) <= File::mtime(tmp_path(file.file))
48
+ puts "copy #{file.file} to tmp/".color :white
49
+ FileUtils.copy_entry(src_path(file.file), tmp_path(file.file))
50
+ end
51
+ }
52
+ end
53
+
54
+ def cmd_exec cmd, args, option
55
+
56
+ cmd_line = cmd + " " + args.map { |arg|
57
+ Shellwords.shellescape(arg)
58
+ }.join(" ")
59
+ puts cmd_line.color :cyan
60
+ stdout, stderr, status = Open3.capture3 cmd_line
61
+ if option[:v] || status != 0
62
+ puts stdout.color :green
63
+ end
64
+ if status != 0
65
+ puts stderr.color :red
66
+ puts "error!".color :red
67
+ exit
68
+ end
69
+ end
70
+ end
71
+
72
+ class CallEpubBuilder < CallBuilder
73
+ def initialize name, book
74
+ @vars = []
75
+ @meta = []
76
+ @template = "template.html"
77
+ @filter = "pandoc-filter.rb"
78
+ @stylesheet = "epub.css"
79
+ @metadata = "metadata.dat"
80
+ @page_progression_direction = "rtl"
81
+ @cover_image = nil
82
+
83
+ if book.title != ""
84
+ @vars << ["title", book.title]
85
+ end
86
+ super name, book
87
+ end
88
+
89
+ def page_progression_direction param
90
+ @page_progression_direction = param
91
+ end
92
+
93
+ def template param
94
+ @template = param
95
+ end
96
+
97
+ def filter param
98
+ @filter = param
99
+ end
100
+
101
+ def stylesheet param
102
+ @stylesheet = param
103
+ end
104
+
105
+ def metadata param
106
+ @metadata = param
107
+ end
108
+
109
+ def cover_image param
110
+ @cover_image = param
111
+ end
112
+
113
+ def meta_option
114
+ result = []
115
+ @meta.concat([["page-progression-direction", @page_progression_direction]]).each { |m|
116
+ result << "-M"
117
+ result << "#{m[0]}=#{m[1]}"
118
+ }
119
+ result
120
+ end
121
+
122
+ def vars_option
123
+ result = []
124
+ @vars.concat([[:book_name, @book.name]]).each { |v|
125
+ result << "-V"
126
+ result << "#{v[0]}=#{v[1]}"
127
+ }
128
+ result
129
+ end
130
+
131
+ def template_option
132
+ "--template=#{Dir::getwd}/theme/#{@theme}/#{@name}/#{@template}"
133
+ end
134
+
135
+ def filter_option
136
+ "--filter=#{Dir::getwd}/theme/#{@theme}/#{@name}/#{@filter}"
137
+ end
138
+
139
+ def stylesheet_option
140
+ "--epub-stylesheet=#{Dir::getwd}/theme/#{@theme}/#{@name}/#{@stylesheet}"
141
+ end
142
+
143
+ def metadata_option
144
+ "--epub-metadata=" + metadata_path
145
+ end
146
+
147
+ def metadata_path
148
+ tmp_path("#{@book.name}.#{@metadata}")
149
+ end
150
+
151
+ def metadata_template_path
152
+ "#{Dir::getwd}/theme/#{@theme}/#{@name}/#{@metadata}.erb"
153
+ end
154
+
155
+ def epub_path
156
+ output_path(@book.name) + '.epub'
157
+ end
158
+
159
+ def json_path
160
+ tmp_path(@book.name) + '.json'
161
+ end
162
+
163
+ def _build_resource files, option
164
+ copy_to_tmp files
165
+ end
166
+
167
+ def pandoc_cmd
168
+ "pandoc"
169
+ end
170
+
171
+ def pandoc_option option
172
+ option = [
173
+ "--epub-chapter-level=1",
174
+ "--toc",
175
+ "-f",
176
+ "markdown_phpextra+hard_line_breaks+raw_html",
177
+ "-s",
178
+ template_option,
179
+ filter_option,
180
+ stylesheet_option,
181
+ metadata_option
182
+ ]
183
+ if @cover_image
184
+ option << "--epub-cover-image=" + src_path(@cover_image)
185
+ end
186
+ option
187
+ end
188
+
189
+ def build_epub_metadata option
190
+ f = open metadata_template_path
191
+ erb = ERB.new f.read, nil, "-"
192
+ f.close
193
+ f = open metadata_path, "w"
194
+ f.write erb.result(binding)
195
+ f.close
196
+ end
197
+
198
+ def build option
199
+ build_epub_metadata option
200
+
201
+ if option['pandoc-json-output']
202
+ cmd_exec "cd #{tmp_path ""};"+ pandoc_cmd, ["-o", json_path, "-t", "json"].concat(pandoc_option option).concat(vars_option).concat(meta_option).concat(@book.src_files.map{ |f| f.full_path }), option
203
+ end
204
+ cmd_exec "cd #{tmp_path ""};"+ pandoc_cmd, ["-o", epub_path, "-t", "epub3"].concat(pandoc_option option).concat(vars_option).concat(meta_option).concat(@book.src_files.map{ |f| f.full_path }), option
205
+ end
206
+ end
207
+
208
+ class CallLatexBuilder < CallBuilder
209
+ attr_reader :template
210
+
211
+ def initialize name, book
212
+ @vars = []
213
+ @template = "template.tex"
214
+ @filter = "pandoc-filter.rb"
215
+ @hyoushi = []
216
+ @urahyoushi = []
217
+ super name, book
218
+ end
219
+
220
+ def documentclass param
221
+ @vars << [:documentclass, param]
222
+ end
223
+
224
+ def classoption param
225
+ @vars << [:classoption, param]
226
+ end
227
+
228
+ def prepartname param
229
+ @vars << [:prepartname, param]
230
+ end
231
+
232
+ def postpartname param
233
+ @vars << [:postpartname, param]
234
+ end
235
+
236
+ def prechaptername param
237
+ @vars << [:prechaptername, param]
238
+ end
239
+
240
+ def postchaptername param
241
+ @vars << [:postchaptername, param]
242
+ end
243
+
244
+ def template param
245
+ @template = param
246
+ end
247
+
248
+ def filter param
249
+ @filter = param
250
+ end
251
+
252
+ def vars_option
253
+ result = []
254
+ @vars.concat([[:book_name, @book.name]]).each { |v|
255
+ result << "-V"
256
+ result << "#{v[0]}=#{v[1]}"
257
+ }
258
+ result
259
+ end
260
+
261
+ def template_option
262
+ "--template=#{Dir::getwd}/theme/#{@theme}/#{@name}/#{@template}"
263
+ end
264
+
265
+ def filter_option
266
+ "--filter=#{Dir::getwd}/theme/#{@theme}/#{@name}/#{@filter}"
267
+ end
268
+
269
+ def tex_path
270
+ tmp_path(@book.name) + '.tex'
271
+ end
272
+
273
+ def json_path
274
+ tmp_path(@book.name) + '.json'
275
+ end
276
+
277
+ def dvi_path
278
+ tmp_path(@book.name) + '.dvi'
279
+ end
280
+
281
+ def pdf_path
282
+ if @output
283
+ output_path(@output) + '.pdf'
284
+ else
285
+ output_path(@book.name) + '.pdf'
286
+ end
287
+ end
288
+
289
+ def extractbb_cmd
290
+ "extractbb"
291
+ end
292
+
293
+ def _build_resource files, option
294
+ copy_to_tmp files
295
+ files.each { |file|
296
+ xbb = File.dirname(tmp_path(file.file)) + "/" + File.basename(tmp_path(file.file), ".*") + ".xbb"
297
+ unless FileTest.exist?(xbb) && File::mtime(tmp_path(file.file)) <= File::mtime(xbb)
298
+ cmd_exec extractbb_cmd, [tmp_path(file.file)], option
299
+ end
300
+ }
301
+ end
302
+
303
+ def build_resource option
304
+ _build_resource @book.resource_files, option
305
+ end
306
+
307
+ def pandoc_cmd
308
+ "pandoc"
309
+ end
310
+
311
+ def pandoc_option option
312
+ [
313
+ "--chapters",
314
+ "-f",
315
+ "markdown_phpextra+hard_line_breaks+raw_tex",
316
+ "-s",
317
+ template_option,
318
+ filter_option
319
+ ]
320
+ end
321
+
322
+ def latex_cmd
323
+ "uplatex"
324
+ end
325
+
326
+ def dvipdfm_cmd
327
+ "dvipdfmx"
328
+ end
329
+
330
+ def build option
331
+ if option['pandoc-json-output']
332
+ cmd_exec pandoc_cmd, ["-o", json_path, "-t", "json"].concat(pandoc_option option).concat(vars_option).concat(@book.src_files.map{ |f| f.full_path }), option
333
+ end
334
+ cmd_exec pandoc_cmd, ["-o", tex_path, "-t", "latex"].concat(pandoc_option option).concat(vars_option).concat(@book.src_files.map{ |f| f.full_path }), option
335
+
336
+ build_resource option
337
+
338
+ f = open(tmp_path(@book.name + ".before_body.tex"), "w") do |io|
339
+ io.puts @hyoushi.map { |h| h.latex @book, self} .join()
340
+ end
341
+
342
+ f = open(tmp_path(@book.name + ".after_body.tex"), "w") do |io|
343
+ io.puts @urahyoushi.map { |h| h.latex @book, self }.join()
344
+ end
345
+ cmd_exec latex_cmd, ["-output-directory=#{tmp_path ""}", tex_path], option
346
+ cmd_exec latex_cmd, ["-output-directory=#{tmp_path ""}", tex_path], option
347
+ unless FileTest.exist?(pdf_path) && (File::mtime(dvi_path) <= File::mtime(pdf_path))
348
+ cmd_exec "cd #{Shellwords.shellescape(tmp_path "")};#{dvipdfm_cmd}", ["-o", pdf_path, dvi_path], option
349
+ end
350
+ end
351
+ end
352
+ def epub_builder name, &block
353
+ call = CallEpubBuilder.new name, self
354
+ if block
355
+ call.instance_eval &block
356
+ end
357
+ call.validate
358
+ @builders << call
359
+ end
360
+
361
+ def latex_builder name, &block
362
+ call = CallLatexBuilder.new name, self
363
+ if block
364
+ call.instance_eval &block
365
+ end
366
+ call.validate
367
+ @builders << call
368
+ end
369
+ end
370
+ end
@@ -0,0 +1,159 @@
1
+ module Xpub
2
+ class CallBook
3
+ class CallLatexBuilder
4
+ class CallLatexOp
5
+ def initialize name, book, builder
6
+ @name = name
7
+ @book = book
8
+ @builder = builder
9
+ end
10
+ def validate
11
+ end
12
+
13
+ def template_path
14
+ "#{Dir::getwd}/theme/#{@builder.theme}/#{@name}/#{@metadata}.erb"
15
+ end
16
+
17
+ def latex book, builder
18
+ f = open template_path
19
+ erb = ERB.new f.read, nil, "-"
20
+ f.close
21
+ erb.result(binding)
22
+ end
23
+
24
+ end
25
+
26
+ class CallImgPageLatexOp < CallLatexOp
27
+ def initialize name, book, builder
28
+ @topoffset = "0in"
29
+ @leftoffset = "0in"
30
+ super name, book, builder
31
+ end
32
+
33
+ def topoffset param
34
+ @topoffset = param
35
+ end
36
+
37
+ def leftoffset param
38
+ @leftoffset = param
39
+ end
40
+
41
+ def file param
42
+ @file = param
43
+ end
44
+
45
+ def latex book, builder
46
+ <<"EOS"
47
+ \\enlargethispage{200truemm}%
48
+ \\thispagestyle{empty}%
49
+ \\vspace*{-1truein}
50
+ \\vspace*{-\\hoffset}
51
+ \\vspace*{-\\oddsidemargin}
52
+ \\vspace*{#{@leftoffset}}
53
+ \\noindent\\hspace*{-1in}\\hspace*{-\\voffset}\\hspace*{-\\topmargin}\\hspace*{-\\headheight}\\hspace*{-\\headsep}\\hspace*{#{@topoffset}}
54
+ \\includegraphics[width=\\paperheight,height=\\paperwidth]{#{@file}}
55
+ \\clearpage\n
56
+ EOS
57
+ end
58
+ end
59
+
60
+ class CallEmptyPageLatexOp < CallLatexOp
61
+ def initialize name, book, builder
62
+ @no_page_number = false
63
+ super name, book, builder
64
+ end
65
+
66
+ def no_page_number
67
+ @no_page_number = true
68
+ end
69
+
70
+ def latex book, builder
71
+ (@no_page_number ? "\\thispagestyle{empty}" : "") + " \\clearpage\n"
72
+ end
73
+ end
74
+
75
+ class CallInnerTitlePageLatexOp < CallLatexOp
76
+ def initialize name, book, builder
77
+ super name, book, builder
78
+ end
79
+
80
+ def latex book, builder
81
+ <<"EOS"
82
+ \\makeatletter
83
+ {
84
+ \\thispagestyle{empty}%
85
+ \\if@twocolumn\\@restonecoltrue\\onecolumn
86
+ \\else\\@restonecolfalse\\newpage\\fi
87
+ \\begin{minipage}<y>[c]{\\textheight}
88
+ \\begin{center}
89
+ \\vspace*{2.5cm}
90
+ {\\bf \\Huge #{book.title}}
91
+ \\end{center}
92
+ \\vspace*{0.5cm}
93
+ \\begin{center}
94
+ {\\bf \\Large #{book.subtitle}}
95
+ \\end{center}
96
+ \\vspace*{1.5cm}
97
+ \\begin{center}
98
+ {\\Large #{book.creators.map { |c| c.name }.join " "}}
99
+ \\end{center}
100
+ \\vspace*{1.5cm}
101
+ \\begin{flushleft}
102
+ #{book.description}
103
+ \\end{flushleft}
104
+ \\end{minipage}
105
+ \\if@restonecol\\twocolumn\\else\\newpage\\fi
106
+ }%
107
+ \\makeatother
108
+ EOS
109
+ end
110
+ end
111
+
112
+ def hyoushi_image_page name, &block
113
+ call = CallImgPageLatexOp.new name, @book, self
114
+ if block
115
+ call.instance_eval &block
116
+ end
117
+ call.validate
118
+ @hyoushi << call
119
+ end
120
+
121
+ def hyoushi_empty_page name, &block
122
+ call = CallEmptyPageLatexOp.new name, @book, self
123
+ if block
124
+ call.instance_eval &block
125
+ end
126
+ call.validate
127
+ @hyoushi << call
128
+ end
129
+
130
+ def hyoushi_inner_title_page name, &block
131
+ call = CallInnerTitlePageLatexOp.new name, @book, self
132
+ if block
133
+ call.instance_eval &block
134
+ end
135
+ call.validate
136
+ @hyoushi << call
137
+ end
138
+
139
+ def urahyoushi_image_page name, &block
140
+ call = CallImgPageLatexOp.new name, @book, self
141
+ if block
142
+ call.instance_eval &block
143
+ end
144
+ call.validate
145
+ @urahyoushi << call
146
+ end
147
+
148
+ def urahyoushi_empty_page name, &block
149
+ call = CallEmptyPageLatexOp.new name, @book, self
150
+ if block
151
+ call.instance_eval &block
152
+ end
153
+ call.validate
154
+ @urahyoushi << call
155
+ end
156
+
157
+ end
158
+ end
159
+ end