pubgen 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -1
- data/README.md +41 -24
- data/Rakefile +76 -1
- data/bin/pubgen +73 -53
- data/lib/pubgen.rb +1 -0
- data/lib/pubgen/container.rb +2 -0
- data/lib/pubgen/cover_page.rb +1 -0
- data/lib/pubgen/ncx.rb +6 -6
- data/lib/pubgen/opf.rb +25 -24
- data/lib/pubgen/version.rb +2 -1
- data/lib/pubgen/yaml.rb +130 -0
- data/pubgen.gemspec +3 -2
- data/test/output/will_oldham.yml +42 -0
- data/test/test_ncx.rb +0 -1
- data/test/test_opf.rb +0 -1
- data/test/toc_1/will_oldham.html +646 -0
- data/test/toc_1/will_oldham.yml +85 -0
- data/test/toc_2/couchdb.html +55 -0
- data/test/toc_2/couchdb.yml +64 -0
- metadata +23 -7
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# Pubgen
|
2
2
|
|
3
|
-
Pubgen is a command-line based epub generator.
|
4
|
-
a epub for you.
|
3
|
+
Pubgen is a command-line based epub generator. Make an epub with YAML.
|
5
4
|
|
6
5
|
## Installation
|
7
6
|
|
@@ -14,22 +13,26 @@ $ gem install pubgen
|
|
14
13
|
|
15
14
|
```bash
|
16
15
|
$ pubgen -h
|
17
|
-
pubgen,
|
16
|
+
pubgen 0.2.0, an epub generator. (http://github.com/9beach/pubgen)
|
18
17
|
|
19
18
|
Usage:
|
20
19
|
pubgen <yaml file> [-o <epub file>] [-v]
|
21
20
|
pubgen <yaml file> -m
|
21
|
+
pubgen -t <toc file> <epub root path>
|
22
22
|
|
23
|
-
-o, --output
|
23
|
+
-o, --output EPUB_FILE Specify output epub file path
|
24
24
|
-m, --meta-file-only Generate .opf, .ncx, mimetype, ...
|
25
|
+
-t, --toc TOC_FILE EPUB_ROOT Print YAML using TOC file
|
25
26
|
-v, --verbose Verbose output
|
26
27
|
```
|
27
28
|
|
28
29
|
## Quick Start
|
30
|
+
|
31
|
+
### Create an epub
|
29
32
|
|
30
33
|
Prepare files (documents, images, style sheets, etc.) that make up the
|
31
|
-
publication. iBooks requires strict xhtml. [`tidy -asxhtml`]
|
32
|
-
(http://tidy.sourceforge.net/) will be helpful.
|
34
|
+
publication. Apple's iBooks requires strict xhtml. [`tidy -asxhtml`]
|
35
|
+
(http://tidy.sourceforge.net/) will be helpful to you.
|
33
36
|
|
34
37
|
```bash
|
35
38
|
$ find .
|
@@ -45,7 +48,7 @@ $ find .
|
|
45
48
|
./style.css
|
46
49
|
```
|
47
50
|
|
48
|
-
Create the utf-8 encoded YAML file describing the publication. As
|
51
|
+
Create the utf-8 encoded YAML file describing the publication. As an example,
|
49
52
|
`will_oldham.yml`.
|
50
53
|
|
51
54
|
```yaml
|
@@ -71,7 +74,7 @@ metadata:
|
|
71
74
|
# See http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.6
|
72
75
|
#
|
73
76
|
# If you provide cover-image without cover-page, pubgen automatically
|
74
|
-
# generate cover-page xhtml, and add it to manifest and spine
|
77
|
+
# generate cover-page xhtml, and add it to manifest and spine.
|
75
78
|
guide:
|
76
79
|
toc-page:
|
77
80
|
title-page:
|
@@ -127,26 +130,40 @@ toc:
|
|
127
130
|
Run pubgen.
|
128
131
|
|
129
132
|
```bash
|
130
|
-
$ pubgen
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
133
|
+
$ pubgen <epub root>/will_oldham.yml -o out.epub
|
134
|
+
zip > out.epub
|
135
|
+
```
|
136
|
+
|
137
|
+
Done!
|
138
|
+
|
139
|
+
### Create meta files
|
140
|
+
|
141
|
+
If you understand [Open Packaging Format 2.0.1]
|
142
|
+
(http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm) spec, and want to edit some
|
143
|
+
properties of the epub before packaging, you can try pubgen with
|
144
|
+
`--meta-file-only` option.
|
145
|
+
|
146
|
+
```bash
|
147
|
+
$ cd <epub root>
|
148
|
+
$ pubgen will_oldham.yml -m
|
140
149
|
cat > META-INF/container.xml
|
141
150
|
cat > mimetype
|
142
151
|
cat > cover-pubgen.xhtml
|
143
152
|
cat > content.opf
|
144
153
|
cat > toc.ncx
|
145
|
-
|
146
|
-
|
147
|
-
mv .pubgen-4f4a210e/pubgen.epub 'Will Oldham_ Wikipedia, the free encyclopedia.epub'
|
148
|
-
rm -rf .pubgen-4f4a210e
|
149
|
-
# Successfully generated 'Will Oldham_ Wikipedia, the free encyclopedia.epub'
|
154
|
+
# Edit content.opf/toc.ncx, and archive epub with zip command
|
155
|
+
$ zip -r ../will_oldham.epub .
|
150
156
|
```
|
151
157
|
|
152
|
-
|
158
|
+
### Generate YAML using TOC file
|
159
|
+
|
160
|
+
Pubgen generates a YAML using TOC file. Pubgen-generated YAML is not complete,
|
161
|
+
but is probably quite useful.
|
162
|
+
|
163
|
+
```bash
|
164
|
+
$ pubgen -t <epub root>/contents/toc.html <epub root> > out.yml
|
165
|
+
$ vi out.yml # Open and complete YAML
|
166
|
+
$ cp out.yml <epub root>
|
167
|
+
$ pubgen <epub root>/out.yml -o out.epub
|
168
|
+
zip > out.epub
|
169
|
+
```
|
data/Rakefile
CHANGED
@@ -1,10 +1,85 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'rake/testtask'
|
3
3
|
|
4
|
-
task :default => [:
|
4
|
+
task :default => [:test_bad_options]
|
5
|
+
|
5
6
|
Rake::TestTask.new('test_units') do |t|
|
6
7
|
t.libs << %w[lib test]
|
7
8
|
t.pattern = 'test/test*.rb'
|
8
9
|
t.warning = true
|
10
|
+
# t.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def sh_echo_off(cmd)
|
14
|
+
%x[#{cmd}]
|
15
|
+
raise "Failed: #{cmd}" unless $?.success?
|
16
|
+
end
|
17
|
+
|
18
|
+
def sh_echo_off_failure(cmd)
|
19
|
+
%x[#{cmd} > /dev/null 2>&1]
|
20
|
+
raise "Not failed: #{cmd}" if $?.success?
|
21
|
+
end
|
22
|
+
|
23
|
+
$tmpdir = '.rake_test'
|
24
|
+
|
25
|
+
task :test_bad_options => :test_toc_2 do |t|
|
26
|
+
$stdout << "# task: #{t} => "
|
27
|
+
sh_echo_off_failure("bin/pubgen -t x.html -o a.epub")
|
28
|
+
sh_echo_off_failure("bin/pubgen -t x.html -m")
|
29
|
+
sh_echo_off_failure("bin/pubgen -o x.epub -m")
|
30
|
+
sh_echo_off_failure("bin/pubgen")
|
31
|
+
sh_echo_off_failure("bin/pubgen -t x.html")
|
32
|
+
sh_echo_off_failure("bin/pubgen -o")
|
33
|
+
sh_echo_off_failure("bin/pubgen -t")
|
34
|
+
puts "done!"
|
35
|
+
end
|
36
|
+
|
37
|
+
task :test_toc_2 => :test_toc_1 do |t|
|
38
|
+
$stdout << "# task: #{t} => "
|
39
|
+
sh_echo_off("mkdir -p #{$tmpdir}")
|
40
|
+
sh_echo_off("cp test/toc_2/couchdb.html #{$tmpdir}")
|
41
|
+
sh_echo_off("touch #{$tmpdir}/foreword.html #{$tmpdir}/preface.html " <<
|
42
|
+
"#{$tmpdir}/why.html #{$tmpdir}/consistency.html #{$tmpdir}/tour.html " <<
|
43
|
+
"#{$tmpdir}/api.html")
|
44
|
+
o_yml = "#{$tmpdir}/.out.yml"
|
45
|
+
sh_echo_off("bin/pubgen -t #{$tmpdir}/couchdb.html #{$tmpdir} > #{o_yml}")
|
46
|
+
sh_echo_off("diff test/toc_2/couchdb.yml #{o_yml}")
|
47
|
+
sh_echo_off("rm -rf #{$tmpdir}")
|
48
|
+
puts "done!"
|
49
|
+
end
|
50
|
+
|
51
|
+
task :test_toc_1 => :test_output do |t|
|
52
|
+
$stdout << "# task: #{t} => "
|
53
|
+
sh_echo_off("mkdir -p #{$tmpdir}")
|
54
|
+
o_yml = "#{$tmpdir}/.out.yml"
|
55
|
+
sh_echo_off("bin/pubgen -t test/toc_1/will_oldham.html test/toc_1 > #{o_yml}")
|
56
|
+
sh_echo_off("diff test/toc_1/will_oldham.yml #{o_yml}")
|
57
|
+
sh_echo_off("rm -rf #{$tmpdir}")
|
58
|
+
puts "done!"
|
59
|
+
end
|
60
|
+
|
61
|
+
task :test_output => :test_units do |t|
|
62
|
+
$stdout << "# task: #{t} => "
|
63
|
+
sh_echo_off("mkdir -p #{$tmpdir}/contents")
|
64
|
+
sh_echo_off("mkdir -p #{$tmpdir}/images")
|
65
|
+
sh_echo_off("cp test/output/will_oldham.yml #{$tmpdir}")
|
66
|
+
sh_echo_off("touch #{$tmpdir}/contents/a.html #{$tmpdir}/contents/b.html " <<
|
67
|
+
"#{$tmpdir}/images/1.jpg #{$tmpdir}/images/2.jpg " <<
|
68
|
+
"#{$tmpdir}/images/3.jpg #{$tmpdir}/images/cover.jpg " <<
|
69
|
+
"#{$tmpdir}/style.css")
|
70
|
+
sh_echo_off("bin/pubgen #{$tmpdir}/will_oldham.yml -o #{$tmpdir}/a.epub " <<
|
71
|
+
"> /dev/null")
|
72
|
+
sh_echo_off("rm -rf #{$tmpdir}")
|
73
|
+
puts "done!"
|
74
|
+
end
|
75
|
+
|
76
|
+
task :build_gem do
|
77
|
+
sh "gem build pubgen.gemspec"
|
78
|
+
end
|
79
|
+
|
80
|
+
task :push_gem => :build_gem do
|
81
|
+
$:.push File.expand_path("../lib", __FILE__)
|
82
|
+
require "pubgen/version"
|
83
|
+
sh "gem push pubgen-#{Pubgen::VERSION}.gem"
|
9
84
|
end
|
10
85
|
|
data/bin/pubgen
CHANGED
@@ -9,63 +9,92 @@ require 'zipruby'
|
|
9
9
|
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
10
10
|
require 'pubgen'
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
# just for one line log
|
13
|
+
def pubgen_log(log, verbose = true)
|
14
|
+
$stdout << log << "\n" if verbose
|
15
|
+
end
|
16
|
+
|
17
|
+
def pubgen_err(err)
|
18
|
+
$stderr << '# ' << err << "\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
help = <<EOF
|
22
|
+
pubgen #{Pubgen::VERSION}, an epub generator. (http://github.com/9beach/pubgen)
|
14
23
|
|
15
24
|
Usage:
|
16
25
|
pubgen <yaml file> [-o <epub file>] [-v]
|
17
26
|
pubgen <yaml file> -m
|
27
|
+
pubgen -t <toc file> <epub root path>
|
18
28
|
|
19
29
|
EOF
|
20
30
|
|
21
31
|
options = {}
|
22
32
|
opts = OptionParser.new do |opts|
|
23
|
-
opts.banner =
|
33
|
+
opts.banner = help
|
24
34
|
|
25
|
-
opts.on('-o', '--output
|
26
|
-
options[:epub_path] =
|
35
|
+
opts.on('-o', '--output EPUB_FILE', 'Specify output epub file path') do |o|
|
36
|
+
options[:epub_path] = o
|
27
37
|
end
|
28
|
-
|
29
|
-
|
30
|
-
options[:meta_file_only] = m
|
38
|
+
opts.on('-m', '--meta-file-only', 'Generate .opf, .ncx, mimetype, ...') do |o|
|
39
|
+
options[:meta_file_only] = o
|
31
40
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
41
|
+
opts.on('-t', '--toc TOC_FILE EPUB_ROOT', 'Print YAML using TOC file') do |o|
|
42
|
+
options[:toc_path] = o
|
43
|
+
end
|
44
|
+
opts.on('-v', '--verbose', 'Verbose output') do |o|
|
45
|
+
options[:verbose] = o
|
35
46
|
end
|
36
47
|
end
|
37
48
|
opts.parse!(ARGV)
|
38
49
|
|
39
50
|
# check options validity
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
51
|
+
option_count = 0
|
52
|
+
option_count += 1 if options[:meta_file_only] == true
|
53
|
+
option_count += 1 if options[:epub_path] != nil
|
54
|
+
option_count += 1 if options[:toc_path] != nil
|
55
|
+
|
56
|
+
if option_count > 1
|
57
|
+
$stderr << "pubgen: `--meta-file-only', `--output' and `--toc' " <<
|
58
|
+
"options cannot be combined\n\n" <<
|
59
|
+
"Try `pubgen -h' for more informations\n"
|
46
60
|
exit 1
|
47
61
|
end
|
48
62
|
|
49
63
|
if ARGV.size != 1
|
50
|
-
|
51
|
-
pubgen: specify a
|
52
|
-
|
53
|
-
|
54
|
-
|
64
|
+
if options[:toc_path] != nil
|
65
|
+
$stderr << "pubgen: specify a epub root path\n\n" <<
|
66
|
+
"Try `pubgen -h' for more informations\n"
|
67
|
+
else
|
68
|
+
$stderr << "pubgen: specify a yaml file\n\n" <<
|
69
|
+
"Try `pubgen -h' for more informations\n"
|
70
|
+
end
|
55
71
|
exit 1
|
56
|
-
else
|
57
|
-
options[:yaml_path] = ARGV[0]
|
58
72
|
end
|
73
|
+
|
74
|
+
# `--toc' option. process it and exit
|
75
|
+
if options[:toc_path] != nil
|
76
|
+
options[:epub_root] = ARGV[0]
|
77
|
+
begin
|
78
|
+
$stdout << Pubgen::YAML.generate(options[:epub_root], options[:toc_path])
|
79
|
+
rescue Exception=>e
|
80
|
+
pubgen_err(e.to_s)
|
81
|
+
exit 1
|
82
|
+
end
|
83
|
+
exit 0
|
84
|
+
end
|
85
|
+
|
86
|
+
# now, options[:toc_path] == nil
|
87
|
+
options[:yaml_path] = ARGV[0]
|
59
88
|
|
60
89
|
begin
|
61
90
|
yaml = YAML::load File.open(options[:yaml_path])
|
62
91
|
rescue Exception=>e
|
63
|
-
pubgen_err("While loading yaml: "
|
92
|
+
pubgen_err("While loading yaml: " << e.to_s)
|
64
93
|
exit 1
|
65
94
|
end
|
66
95
|
|
67
96
|
if yaml['metadata']['title'] == nil
|
68
|
-
pubgen_err("Failed to
|
97
|
+
pubgen_err("Failed to get the value of `title' attribute in: " <<
|
69
98
|
options[:yaml_path])
|
70
99
|
exit 1
|
71
100
|
end
|
@@ -77,15 +106,6 @@ if !options[:meta_file_only] && !options[:epub_path]
|
|
77
106
|
end
|
78
107
|
# options done
|
79
108
|
|
80
|
-
# just for one line log
|
81
|
-
def pubgen_log(log, verbose = true)
|
82
|
-
$stdout << log + "\n" if verbose
|
83
|
-
end
|
84
|
-
|
85
|
-
def pubgen_err(err)
|
86
|
-
$stderr << '# ' + err + "\n"
|
87
|
-
end
|
88
|
-
|
89
109
|
if yaml['metadata']['creator'] == nil
|
90
110
|
yaml['metadata']['creator'] = "pubgen-#{Pubgen::VERSION}"
|
91
111
|
end
|
@@ -102,35 +122,35 @@ begin
|
|
102
122
|
# temporal working directory
|
103
123
|
$tmpdir = ".pubgen-%08x" % Time.now.to_i
|
104
124
|
Dir.mkdir($tmpdir)
|
105
|
-
pubgen_log("mkdir "
|
125
|
+
pubgen_log("mkdir " << $tmpdir, options[:verbose])
|
106
126
|
|
107
127
|
# copy all the files of manifest to $tmpdir
|
108
128
|
yaml['manifest'].each do |file|
|
109
129
|
if Pubgen::OPF.valid_manifest_element?(file) == false
|
110
|
-
raise "Invalid manifest (not in sub-directory of yaml file): "
|
130
|
+
raise "Invalid manifest (not in sub-directory of yaml file): " << file
|
111
131
|
end
|
112
|
-
target_dir = "#{$tmpdir
|
132
|
+
target_dir = "#{File.join($tmpdir, File.dirname(file))}"
|
113
133
|
FileUtils.mkdir_p(target_dir)
|
114
|
-
FileUtils.cp("#{File.dirname(options[:yaml_path])
|
134
|
+
FileUtils.cp("#{File.join(File.dirname(options[:yaml_path]), file)}",
|
115
135
|
target_dir, :verbose=>options[:verbose])
|
116
136
|
end
|
117
137
|
|
118
138
|
# change pwd
|
119
139
|
Dir.chdir($tmpdir)
|
120
|
-
pubgen_log("cd "
|
140
|
+
pubgen_log("cd " << $tmpdir, options[:verbose])
|
121
141
|
end
|
122
142
|
|
123
143
|
# generate container.xml
|
124
144
|
# it's path is fixed (META-INF/container.xml)
|
125
145
|
Dir.mkdir('META-INF') if !File::directory?('META-INF')
|
126
|
-
container = File.new('META-INF
|
146
|
+
container = File.new(File.join('META-INF', 'container.xml'), 'w')
|
127
147
|
container.write(Pubgen::Container.generate)
|
128
148
|
container.close
|
129
|
-
pubgen_log(
|
149
|
+
pubgen_log("cat > #{File.join('META-INF', 'container.xml')}",
|
130
150
|
options[:meta_file_only] || options[:verbose])
|
131
151
|
|
132
152
|
# generate mimetype
|
133
|
-
# it's path is also fixed (
|
153
|
+
# it's path is also fixed (mimetype)
|
134
154
|
mimetype = File.new('mimetype', 'w')
|
135
155
|
mimetype.write('application/epub+zip')
|
136
156
|
mimetype.close
|
@@ -143,7 +163,7 @@ begin
|
|
143
163
|
cover_page = File.new(COVER_PAGE_PATH, 'w')
|
144
164
|
cover_page.write(Pubgen::CoverPage.generate(yaml['guide']['cover-image']))
|
145
165
|
cover_page.close
|
146
|
-
pubgen_log("cat > "
|
166
|
+
pubgen_log("cat > " << COVER_PAGE_PATH,
|
147
167
|
options[:meta_file_only] || options[:verbose])
|
148
168
|
|
149
169
|
# add/set it to manifest, spine, and cover-page
|
@@ -153,7 +173,7 @@ begin
|
|
153
173
|
end
|
154
174
|
|
155
175
|
# generate uuid
|
156
|
-
uuid = "%08x-" % Time.now.to_i
|
176
|
+
uuid = "%08x-" % Time.now.to_i <<
|
157
177
|
[4,4,4,12].map {|l| "%0#{l}x" % rand(1 << l*4) }.join('-')
|
158
178
|
# uuid = UUID.new.generate
|
159
179
|
|
@@ -161,7 +181,7 @@ begin
|
|
161
181
|
opf = File.new(Pubgen::Container.opf_path, 'w')
|
162
182
|
opf.write(Pubgen::OPF.generate(yaml, uuid))
|
163
183
|
opf.close
|
164
|
-
pubgen_log("cat > "
|
184
|
+
pubgen_log("cat > " << Pubgen::Container.opf_path,
|
165
185
|
options[:meta_file_only] || options[:verbose])
|
166
186
|
# pubgen automatically added .ncx file to opf's manifest
|
167
187
|
|
@@ -169,7 +189,7 @@ begin
|
|
169
189
|
ncx = File.new(Pubgen::OPF.ncx_path, 'w')
|
170
190
|
ncx.write(Pubgen::NCX.generate(yaml['metadata']['title'], yaml['toc'], uuid))
|
171
191
|
ncx.close
|
172
|
-
pubgen_log("cat > "
|
192
|
+
pubgen_log("cat > " << Pubgen::OPF.ncx_path,
|
173
193
|
options[:meta_file_only] || options[:verbose])
|
174
194
|
|
175
195
|
# make an epub
|
@@ -187,10 +207,10 @@ begin
|
|
187
207
|
|
188
208
|
# mv pubgen.epub to options[:epub_path]
|
189
209
|
Dir.chdir($pwd_old)
|
190
|
-
pubgen_log("cd "
|
191
|
-
FileUtils.mv($tmpdir
|
192
|
-
pubgen_log("mv #{$tmpdir
|
193
|
-
options[:verbose])
|
210
|
+
pubgen_log("cd " << $pwd_old, options[:verbose])
|
211
|
+
FileUtils.mv(File.join($tmpdir, 'pubgen.epub'), options[:epub_path])
|
212
|
+
pubgen_log("mv #{File.join($tmpdir, 'pubgen.epub')} " <<
|
213
|
+
"'#{options[:epub_path]}'", options[:verbose])
|
194
214
|
end
|
195
215
|
rescue Exception=>e
|
196
216
|
$exit_code = 1
|
@@ -199,11 +219,11 @@ ensure
|
|
199
219
|
# remove $tmpdir
|
200
220
|
if Dir.pwd != $pwd_old
|
201
221
|
Dir.chdir($pwd_old)
|
202
|
-
pubgen_log("cd "
|
222
|
+
pubgen_log("cd " << $pwd_old, options[:verbose])
|
203
223
|
end
|
204
224
|
if File::directory?($tmpdir)
|
205
225
|
FileUtils.rm_rf($tmpdir)
|
206
|
-
pubgen_log("rm -rf "
|
226
|
+
pubgen_log("rm -rf " << $tmpdir, options[:verbose])
|
207
227
|
end
|
208
228
|
end
|
209
229
|
|
data/lib/pubgen.rb
CHANGED