pubgen 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +34 -27
- data/Rakefile +10 -0
- data/bin/pubgen +40 -33
- data/lib/pubgen.rb +1 -0
- data/lib/pubgen/container.rb +4 -4
- data/lib/pubgen/cover_page.rb +3 -5
- data/lib/pubgen/ncx.rb +32 -36
- data/lib/pubgen/opf.rb +56 -57
- data/lib/pubgen/version.rb +3 -0
- data/pubgen.gemspec +5 -2
- data/test/helper.rb +1 -0
- data/test/test_cover_page.rb +11 -0
- data/test/test_ncx.rb +90 -0
- data/test/test_opf.rb +112 -0
- metadata +12 -6
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Pubgen
|
2
2
|
|
3
|
-
Pubgen is a
|
4
|
-
|
3
|
+
Pubgen is a command-line based epub generator. With a simple YAML, Pubgen make
|
4
|
+
a epub for you.
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
@@ -14,7 +14,7 @@ $ gem install pubgen
|
|
14
14
|
|
15
15
|
```bash
|
16
16
|
$ pubgen -h
|
17
|
-
pubgen
|
17
|
+
pubgen, a epub generator. (http://github.com/9beach/pubgen)
|
18
18
|
|
19
19
|
Usage:
|
20
20
|
pubgen <yaml file> [-o <epub file>] [-v]
|
@@ -28,15 +28,13 @@ Usage:
|
|
28
28
|
## Quick Start
|
29
29
|
|
30
30
|
Prepare files (documents, images, style sheets, etc.) that make up the
|
31
|
-
publication. iBooks requires strict xhtml
|
32
|
-
|
31
|
+
publication. iBooks requires strict xhtml. [`tidy -asxhtml`]
|
32
|
+
(http://tidy.sourceforge.net/) will be helpful.
|
33
33
|
|
34
34
|
```bash
|
35
35
|
$ find .
|
36
36
|
.
|
37
37
|
./contents
|
38
|
-
./contents/a-1.html
|
39
|
-
./contents/a-2.html
|
40
38
|
./contents/a.html
|
41
39
|
./contents/b.html
|
42
40
|
./images
|
@@ -46,14 +44,14 @@ $ find .
|
|
46
44
|
./images/cover.jpg
|
47
45
|
./style.css
|
48
46
|
```
|
49
|
-
|
47
|
+
|
48
|
+
Create the utf-8 encoded YAML file describing the publication. As a example,
|
50
49
|
`will_oldham.yml`.
|
51
50
|
|
52
51
|
```yaml
|
53
52
|
# METADATA: Publication metadata (title, author, publisher, etc.).
|
54
53
|
#
|
55
54
|
# See http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.2
|
56
|
-
# -*- encoding: utf-8 -*-
|
57
55
|
metadata:
|
58
56
|
title: "Will Oldham: Wikipedia, the free encyclopedia"
|
59
57
|
creator: Wikipedia
|
@@ -61,7 +59,7 @@ metadata:
|
|
61
59
|
language: en
|
62
60
|
subject: American alternative country singers
|
63
61
|
publisher:
|
64
|
-
|
62
|
+
contributor:
|
65
63
|
description:
|
66
64
|
source: "http://en.wikipedia.org/wiki/Will_Oldham"
|
67
65
|
rights:
|
@@ -71,19 +69,22 @@ metadata:
|
|
71
69
|
# publication, such as table of contents, foreword, bibliography, etc.
|
72
70
|
#
|
73
71
|
# See http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.6
|
72
|
+
#
|
73
|
+
# If you provide cover-image without cover-page, pubgen automatically
|
74
|
+
# generate cover-page xhtml, and add it to manifest and spine
|
74
75
|
guide:
|
75
76
|
toc-page:
|
76
77
|
title-page:
|
77
|
-
# If you provide cover-image without cover-page, pubgen automatically
|
78
|
-
# generate cover-page xhtml, and add it to manifest and spine
|
79
|
-
cover-image: images/cover.jpg
|
80
78
|
cover-page:
|
79
|
+
cover-image: images/cover.jpg
|
81
80
|
|
82
81
|
# MANIFEST: A list of files (documents, images, style sheets, etc.) that make
|
83
82
|
# up the publication.
|
84
83
|
#
|
85
|
-
#
|
86
|
-
#
|
84
|
+
# See http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.3
|
85
|
+
#
|
86
|
+
# All the file paths in manifest ought to be relative to yaml's path and in the
|
87
|
+
# same or sub-directory of yaml. Say yaml's path is /book/a.yaml.
|
87
88
|
# - a/b/c.html # good. in the sub-directory
|
88
89
|
# - d.jpg # good. in the same directory
|
89
90
|
# - ./e.jpg # good. in the same directory
|
@@ -93,8 +94,6 @@ guide:
|
|
93
94
|
# - ../book/f.png # bad. although in the same directory
|
94
95
|
manifest:
|
95
96
|
- contents/a.html
|
96
|
-
- contents/a-1.html
|
97
|
-
- contents/a-2.html
|
98
97
|
- contents/b.html
|
99
98
|
- images/cover.jpg
|
100
99
|
- images/1.jpg
|
@@ -103,18 +102,26 @@ manifest:
|
|
103
102
|
- style.css
|
104
103
|
|
105
104
|
# SPINE: An arrangement of documents providing a linear reading order.
|
105
|
+
#
|
106
|
+
# See http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4
|
106
107
|
spine:
|
107
108
|
- contents/a.html
|
108
|
-
- contents/a-1.html
|
109
|
-
- contents/a-2.html
|
110
109
|
- contents/b.html
|
111
110
|
|
112
111
|
# TOC: Table of contents
|
112
|
+
#
|
113
|
+
# See http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4.1
|
113
114
|
toc:
|
114
|
-
|
115
|
-
|
116
|
-
-
|
117
|
-
|
115
|
+
# Add a colon suffix to indent
|
116
|
+
- 1 Music -- contents/a.html:
|
117
|
+
- 1.1 Discography -- contents/a.html#discography:
|
118
|
+
- 1.1.1 Studio albums -- contents/a.html#studio_albums
|
119
|
+
- 1.2 Response -- contents/a.html#response
|
120
|
+
- 2 Film -- contents/b.html:
|
121
|
+
- 2.1 Filmography -- contents/b.html#filmography
|
122
|
+
- 3 Photography -- contents/b.html#photography
|
123
|
+
- 4 References -- contents/b.html#references
|
124
|
+
- 5 External links -- contents/b.html#external_links
|
118
125
|
```
|
119
126
|
|
120
127
|
Run pubgen.
|
@@ -123,8 +130,6 @@ Run pubgen.
|
|
123
130
|
$ pubgen /path/to/will_oldham.yml -v
|
124
131
|
mkdir .pubgen-4f4a210e
|
125
132
|
cp ./contents/a.html .pubgen-4f4a210e/contents
|
126
|
-
cp ./contents/a-1.html .pubgen-4f4a210e/contents
|
127
|
-
cp ./contents/a-2.html .pubgen-4f4a210e/contents
|
128
133
|
cp ./contents/b.html .pubgen-4f4a210e/contents
|
129
134
|
cp ./images/cover.jpg .pubgen-4f4a210e/images
|
130
135
|
cp ./images/1.jpg .pubgen-4f4a210e/images
|
@@ -138,8 +143,10 @@ cat > cover-pubgen.xhtml
|
|
138
143
|
cat > content.opf
|
139
144
|
cat > toc.ncx
|
140
145
|
zip > pubgen.epub
|
141
|
-
cd /path/to/
|
142
|
-
mv .pubgen-4f4a210e
|
146
|
+
cd /path/to/prev_dir
|
147
|
+
mv .pubgen-4f4a210e/pubgen.epub 'Will Oldham_ Wikipedia, the free encyclopedia.epub'
|
143
148
|
rm -rf .pubgen-4f4a210e
|
144
149
|
# Successfully generated 'Will Oldham_ Wikipedia, the free encyclopedia.epub'
|
145
150
|
```
|
151
|
+
|
152
|
+
Done!
|
data/Rakefile
ADDED
data/bin/pubgen
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
PACKAGE = 'pubgen'
|
4
|
-
VERSION = '0.1.2'
|
5
|
-
|
6
3
|
require 'yaml'
|
7
4
|
require 'fileutils'
|
8
5
|
require 'optparse'
|
@@ -13,11 +10,11 @@ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
|
13
10
|
require 'pubgen'
|
14
11
|
|
15
12
|
HELP = <<EOF
|
16
|
-
|
13
|
+
pubgen #{Pubgen::VERSION}, a epub generator. (http://github.com/9beach/pubgen)
|
17
14
|
|
18
15
|
Usage:
|
19
|
-
|
20
|
-
|
16
|
+
pubgen <yaml file> [-o <epub file>] [-v]
|
17
|
+
pubgen <yaml file> -m
|
21
18
|
|
22
19
|
EOF
|
23
20
|
|
@@ -42,18 +39,18 @@ opts.parse!(ARGV)
|
|
42
39
|
# check options validity
|
43
40
|
if (options[:meta_file_only] == true && options[:epub_path] != nil)
|
44
41
|
$stderr << <<EOF
|
45
|
-
|
42
|
+
pubgen: `--meta-file-only' with `--output EPUB_PATH', not allowed
|
46
43
|
|
47
|
-
Try
|
44
|
+
Try `pubgen -h' for more informations
|
48
45
|
EOF
|
49
46
|
exit 1
|
50
47
|
end
|
51
48
|
|
52
49
|
if ARGV.size != 1
|
53
50
|
$stderr << <<EOF
|
54
|
-
|
51
|
+
pubgen: specify a yaml file
|
55
52
|
|
56
|
-
Try
|
53
|
+
Try `pubgen -h' for more informations
|
57
54
|
EOF
|
58
55
|
exit 1
|
59
56
|
else
|
@@ -68,7 +65,8 @@ rescue Exception=>e
|
|
68
65
|
end
|
69
66
|
|
70
67
|
if yaml['metadata']['title'] == nil
|
71
|
-
pubgen_err("Failed to find the value of 'title' attribute in: " +
|
68
|
+
pubgen_err("Failed to find the value of 'title' attribute in: " +
|
69
|
+
options[:yaml_path])
|
72
70
|
exit 1
|
73
71
|
end
|
74
72
|
|
@@ -77,20 +75,23 @@ if !options[:meta_file_only] && !options[:epub_path]
|
|
77
75
|
options[:epub_path] = yaml['metadata']['title'] + ".epub"
|
78
76
|
options[:epub_path].gsub!(/[\/:?]/, "_") # file-system friendly
|
79
77
|
end
|
80
|
-
#
|
78
|
+
# options done
|
81
79
|
|
82
|
-
# just for one line
|
80
|
+
# just for one line log
|
83
81
|
def pubgen_log(log, verbose = true)
|
84
82
|
$stdout << log + "\n" if verbose
|
85
83
|
end
|
86
84
|
|
87
|
-
# just for one line
|
88
85
|
def pubgen_err(err)
|
89
86
|
$stderr << '# ' + err + "\n"
|
90
87
|
end
|
91
88
|
|
92
|
-
|
93
|
-
yaml['metadata']['
|
89
|
+
if yaml['metadata']['creator'] == nil
|
90
|
+
yaml['metadata']['creator'] = "pubgen-#{Pubgen::VERSION}"
|
91
|
+
end
|
92
|
+
if yaml['metadata']['contributor'] == nil
|
93
|
+
yaml['metadata']['contributor'] = "pubgen-#{Pubgen::VERSION}"
|
94
|
+
end
|
94
95
|
|
95
96
|
$tmpdir = ""
|
96
97
|
$pwd_old = Dir.pwd
|
@@ -98,19 +99,20 @@ $exit_code = 0
|
|
98
99
|
|
99
100
|
begin
|
100
101
|
if !options[:meta_file_only]
|
101
|
-
#
|
102
|
+
# temporal working directory
|
102
103
|
$tmpdir = ".pubgen-%08x" % Time.now.to_i
|
103
104
|
Dir.mkdir($tmpdir)
|
104
105
|
pubgen_log("mkdir " + $tmpdir, options[:verbose])
|
105
106
|
|
106
|
-
# copy all files of manifest to $tmpdir
|
107
|
+
# copy all the files of manifest to $tmpdir
|
107
108
|
yaml['manifest'].each do |file|
|
108
109
|
if Pubgen::OPF.valid_manifest_element?(file) == false
|
109
110
|
raise "Invalid manifest (not in sub-directory of yaml file): " + file
|
110
111
|
end
|
111
112
|
target_dir = "#{$tmpdir}/#{File.dirname(file)}"
|
112
113
|
FileUtils.mkdir_p(target_dir)
|
113
|
-
FileUtils.cp("#{File.dirname(options[:yaml_path])}/#{file}",
|
114
|
+
FileUtils.cp("#{File.dirname(options[:yaml_path])}/#{file}",
|
115
|
+
target_dir, :verbose=>options[:verbose])
|
114
116
|
end
|
115
117
|
|
116
118
|
# change pwd
|
@@ -119,15 +121,16 @@ begin
|
|
119
121
|
end
|
120
122
|
|
121
123
|
# generate container.xml
|
122
|
-
# it's
|
124
|
+
# it's path is fixed (META-INF/container.xml)
|
123
125
|
Dir.mkdir('META-INF') if !File::directory?('META-INF')
|
124
126
|
container = File.new('META-INF/container.xml', 'w')
|
125
127
|
container.write(Pubgen::Container.generate)
|
126
128
|
container.close
|
127
|
-
pubgen_log('cat > META-INF/container.xml',
|
129
|
+
pubgen_log('cat > META-INF/container.xml',
|
130
|
+
options[:meta_file_only] || options[:verbose])
|
128
131
|
|
129
132
|
# generate mimetype
|
130
|
-
# it's
|
133
|
+
# it's path is also fixed (./mimetype)
|
131
134
|
mimetype = File.new('mimetype', 'w')
|
132
135
|
mimetype.write('application/epub+zip')
|
133
136
|
mimetype.close
|
@@ -135,12 +138,13 @@ begin
|
|
135
138
|
|
136
139
|
# pubgen automatically generates cover page if cover-image is given without
|
137
140
|
# cover-page
|
138
|
-
if
|
141
|
+
if yaml['guide']['cover-image'] != nil && yaml['guide']['cover-page'] == nil
|
139
142
|
COVER_PAGE_PATH = 'cover-pubgen.xhtml'
|
140
143
|
cover_page = File.new(COVER_PAGE_PATH, 'w')
|
141
144
|
cover_page.write(Pubgen::CoverPage.generate(yaml['guide']['cover-image']))
|
142
145
|
cover_page.close
|
143
|
-
pubgen_log("cat > " + COVER_PAGE_PATH,
|
146
|
+
pubgen_log("cat > " + COVER_PAGE_PATH,
|
147
|
+
options[:meta_file_only] || options[:verbose])
|
144
148
|
|
145
149
|
# add/set it to manifest, spine, and cover-page
|
146
150
|
yaml['manifest'] << COVER_PAGE_PATH
|
@@ -149,24 +153,26 @@ begin
|
|
149
153
|
end
|
150
154
|
|
151
155
|
# generate uuid
|
152
|
-
uuid = "%08x" % Time.now.to_i +
|
153
|
-
|
156
|
+
uuid = "%08x-" % Time.now.to_i +
|
157
|
+
[4,4,4,12].map {|l| "%0#{l}x" % rand(1 << l*4) }.join('-')
|
154
158
|
# uuid = UUID.new.generate
|
155
159
|
|
156
|
-
# generate opf file
|
160
|
+
# generate .opf file
|
157
161
|
opf = File.new(Pubgen::Container.opf_path, 'w')
|
158
162
|
opf.write(Pubgen::OPF.generate(yaml, uuid))
|
159
163
|
opf.close
|
160
|
-
pubgen_log("cat > " + Pubgen::Container.opf_path,
|
161
|
-
|
164
|
+
pubgen_log("cat > " + Pubgen::Container.opf_path,
|
165
|
+
options[:meta_file_only] || options[:verbose])
|
166
|
+
# pubgen automatically added .ncx file to opf's manifest
|
162
167
|
|
163
|
-
# generate ncx file
|
168
|
+
# generate .ncx file
|
164
169
|
ncx = File.new(Pubgen::OPF.ncx_path, 'w')
|
165
170
|
ncx.write(Pubgen::NCX.generate(yaml['metadata']['title'], yaml['toc'], uuid))
|
166
171
|
ncx.close
|
167
|
-
pubgen_log("cat > " + Pubgen::OPF.ncx_path,
|
172
|
+
pubgen_log("cat > " + Pubgen::OPF.ncx_path,
|
173
|
+
options[:meta_file_only] || options[:verbose])
|
168
174
|
|
169
|
-
#
|
175
|
+
# make an epub
|
170
176
|
if !options[:meta_file_only]
|
171
177
|
Zip::Archive.open("pubgen.epub", Zip::CREATE | Zip::TRUNC) do |ar|
|
172
178
|
Dir.glob('**/*').each do |path|
|
@@ -183,7 +189,8 @@ begin
|
|
183
189
|
Dir.chdir($pwd_old)
|
184
190
|
pubgen_log("cd " + $pwd_old, options[:verbose])
|
185
191
|
FileUtils.mv($tmpdir + "/pubgen.epub", options[:epub_path])
|
186
|
-
pubgen_log("mv #{$tmpdir}
|
192
|
+
pubgen_log("mv #{$tmpdir}/pubgen.epub '#{options[:epub_path]}'",
|
193
|
+
options[:verbose])
|
187
194
|
end
|
188
195
|
rescue Exception=>e
|
189
196
|
$exit_code = 1
|
data/lib/pubgen.rb
CHANGED
data/lib/pubgen/container.rb
CHANGED
@@ -7,11 +7,11 @@ module Pubgen
|
|
7
7
|
def self.generate
|
8
8
|
<<EOF
|
9
9
|
<?xml version="1.0"?>
|
10
|
-
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns
|
11
|
-
>
|
10
|
+
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:\
|
11
|
+
container">
|
12
12
|
<rootfiles>
|
13
|
-
<rootfile full-path="#{opf_path}" media-type="application
|
14
|
-
/>
|
13
|
+
<rootfile full-path="#{opf_path}" media-type="application/\
|
14
|
+
oebps-package+xml"/>
|
15
15
|
</rootfiles>
|
16
16
|
</container>
|
17
17
|
EOF
|
data/lib/pubgen/cover_page.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
module Pubgen
|
2
2
|
module CoverPage
|
3
|
-
def self.need_to_generate?(guide)
|
4
|
-
guide['cover-image'] != nil && guide['cover-page'] == nil
|
5
|
-
end
|
6
|
-
|
7
3
|
def self.generate(cover_image)
|
8
4
|
<<EOF
|
9
5
|
<?xml version='1.0' encoding='utf-8'?>
|
@@ -19,7 +15,9 @@ module Pubgen
|
|
19
15
|
</head>
|
20
16
|
<body>
|
21
17
|
<div>
|
22
|
-
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org
|
18
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/\
|
19
|
+
1999/xlink" version="1.1" width="100%" height="100%" viewBox="0 0 469 616" \
|
20
|
+
preserveAspectRatio="xMinYMin">
|
23
21
|
<image width="469" height="616" xlink:href="#{cover_image}"/>
|
24
22
|
</svg>
|
25
23
|
</div>
|
data/lib/pubgen/ncx.rb
CHANGED
@@ -2,72 +2,68 @@ module Pubgen
|
|
2
2
|
module NCX
|
3
3
|
def self.generate(title, toc, uuid)
|
4
4
|
# header
|
5
|
-
toc_xml =
|
6
|
-
# NavPoint traces indentation, so we need class and instantiation of it
|
7
|
-
nav_point = NavPointImpl.new
|
8
|
-
toc.each do |name_and_path|
|
9
|
-
toc_xml += nav_point.generate(name_and_path)
|
10
|
-
end
|
11
|
-
# footer
|
12
|
-
toc_xml += TOC_XML_FOOTER
|
13
|
-
end
|
14
|
-
|
15
|
-
# define NavPointImpl class and some constants
|
16
|
-
# they are all private, only Pubgen.NCX.generate use them
|
17
|
-
NAVPOINT_XML_HEADER_FORMAT = <<EOF
|
18
|
-
<navPoint id="d%03d" playOrder="%d">
|
19
|
-
<navLabel>
|
20
|
-
<text>%s</text>
|
21
|
-
</navLabel>
|
22
|
-
<content src="%s"/>
|
23
|
-
EOF
|
24
|
-
NAVPOINT_XML_FOOTER = " </navPoint>\n"
|
25
|
-
TOC_XML_HEADER_FORMAT = <<EOF
|
5
|
+
toc_xml = <<EOF
|
26
6
|
<?xml version='1.0' encoding='utf-8'?>
|
27
|
-
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1"
|
7
|
+
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" \
|
8
|
+
xml:lang="en">
|
28
9
|
<head>
|
29
|
-
<meta content="
|
10
|
+
<meta content="#{uuid}" name="dtb:uid"/>
|
30
11
|
<meta content="2" name="dtb:depth"/>
|
31
12
|
<meta content="pubgen" name="dtb:generator"/>
|
32
13
|
<meta content="0" name="dtb:totalPageCount"/>
|
33
14
|
<meta content="0" name="dtb:maxPageNumber"/>
|
34
15
|
</head>
|
35
16
|
<docTitle>
|
36
|
-
<text
|
17
|
+
<text>#{CGI.escapeHTML(title || '')}</text>
|
37
18
|
</docTitle>
|
38
19
|
<navMap>
|
39
20
|
EOF
|
40
|
-
|
21
|
+
# NavPoint traces indentation, so we need class and instantiation of it
|
22
|
+
nav_point = NavPointImpl.new
|
23
|
+
toc.each do |name_and_path|
|
24
|
+
toc_xml += nav_point.generate(name_and_path)
|
25
|
+
end
|
26
|
+
# footer
|
27
|
+
toc_xml += " </navMap>\n</ncx>"
|
28
|
+
end
|
41
29
|
|
30
|
+
# define NavPointImpl class
|
31
|
+
# it's private. only Pubgen.NCX.generate use it
|
42
32
|
class NavPointImpl
|
43
33
|
private
|
44
34
|
def generate_impl(name_and_path, depth)
|
45
|
-
header =
|
46
|
-
|
47
|
-
|
35
|
+
header = <<EOF
|
36
|
+
<navPoint id="d%03d" playOrder="%d">
|
37
|
+
<navLabel>
|
38
|
+
<text>%s</text>
|
39
|
+
</navLabel>
|
40
|
+
<content src="%s"/>
|
41
|
+
EOF
|
42
|
+
footer = " </navPoint>\n"
|
48
43
|
if depth
|
49
44
|
depth.times do
|
50
|
-
header
|
51
|
-
footer
|
45
|
+
header.gsub!(/^/, ' ')
|
46
|
+
footer.gsub!(/^/, ' ')
|
52
47
|
end
|
53
48
|
end
|
54
49
|
|
50
|
+
@play_order += 1
|
55
51
|
navpoint_xml = ''
|
56
52
|
if name_and_path.is_a?(String)
|
57
53
|
if name_and_path.split(" -- ").size != 2
|
58
54
|
raise "Bad toc contents format: " + name_and_path
|
59
55
|
end
|
60
|
-
navpoint_xml = header % [@
|
61
|
-
|
62
|
-
|
56
|
+
navpoint_xml = header % [@play_order, @play_order,
|
57
|
+
CGI.escapeHTML(name_and_path.split(" -- ")[0]),
|
58
|
+
name_and_path.split(" -- ")[1]]
|
63
59
|
else
|
64
60
|
# if not string, it's hash map with just one element
|
65
61
|
name_and_path.each do |key, value|
|
66
62
|
if key.split(" -- ").size != 2
|
67
63
|
raise "Bad toc contents format: " + key
|
68
64
|
end
|
69
|
-
navpoint_xml = header % [@
|
70
|
-
|
65
|
+
navpoint_xml = header % [@play_order, @play_order,
|
66
|
+
CGI.escapeHTML(key.split(" -- ")[0]), key.split(" -- ")[1]]
|
71
67
|
value.each do |v|
|
72
68
|
navpoint_xml += generate_impl(v, depth + 1)
|
73
69
|
end
|
@@ -79,7 +75,7 @@ EOF
|
|
79
75
|
|
80
76
|
public
|
81
77
|
def initialize
|
82
|
-
@
|
78
|
+
@play_order = 0
|
83
79
|
end
|
84
80
|
|
85
81
|
def generate(name_and_path)
|
data/lib/pubgen/opf.rb
CHANGED
@@ -3,49 +3,32 @@ require 'cgi'
|
|
3
3
|
module Pubgen
|
4
4
|
module OPF
|
5
5
|
def self.ncx_path
|
6
|
-
|
6
|
+
'toc.ncx'
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.generate(yaml, uuid)
|
10
10
|
cover_id, manifest_xml, file2id =
|
11
|
-
|
12
|
-
|
11
|
+
OPFImpl.get_cover_id_and_manifest_xml(yaml['guide']['cover-image'],
|
12
|
+
yaml['manifest'])
|
13
13
|
metadata_xml = OPFImpl.get_metadata_xml(yaml['metadata'], uuid, cover_id)
|
14
14
|
spine_xml = OPFImpl.get_spine_xml(yaml['spine'], file2id)
|
15
15
|
guide_xml = OPFImpl.get_guide_xml(yaml['guide'], file2id)
|
16
|
-
|
17
|
-
|
16
|
+
|
17
|
+
<<EOF
|
18
|
+
<?xml version='1.0' encoding='utf-8'?>
|
19
|
+
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" \
|
20
|
+
unique-identifier="uuid_id">
|
21
|
+
#{metadata_xml}#{manifest_xml}#{spine_xml}#{guide_xml}</package>
|
22
|
+
EOF
|
18
23
|
end
|
19
24
|
|
25
|
+
# sub directories and relative paths
|
20
26
|
def self.valid_manifest_element?(e)
|
21
27
|
e[0..2] != "../" && e[0] != "/"
|
22
28
|
end
|
23
29
|
|
24
|
-
# define OPFImpl class
|
25
|
-
#
|
26
|
-
NCX_PATH = "toc.ncx"
|
27
|
-
METADATA_FORMAT = <<EOF
|
28
|
-
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
|
29
|
-
<dc:title>%s</dc:title>
|
30
|
-
<dc:creator opf:role="aut">%s</dc:creator>
|
31
|
-
<dc:date>%s</dc:date>
|
32
|
-
<dc:language>%s</dc:language>
|
33
|
-
<dc:subject>%s</dc:subject>
|
34
|
-
<dc:publisher>%s</dc:publisher>
|
35
|
-
<dc:description>%s</dc:description>
|
36
|
-
<dc:contributor opf:role="bkp">%s</dc:contributor>
|
37
|
-
<dc:source>%s</dc:source>
|
38
|
-
<dc:rights>%s</dc:rights>
|
39
|
-
<dc:relation>%s</dc:relation>
|
40
|
-
<dc:identifier id="BookID" opf:scheme="UUID">%s</dc:identifier>%s
|
41
|
-
</metadata>
|
42
|
-
EOF
|
43
|
-
OPF_XML_HEADER = <<EOF
|
44
|
-
<?xml version='1.0' encoding='utf-8'?>
|
45
|
-
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="uuid_id">
|
46
|
-
EOF
|
47
|
-
OPF_XML_FOOTER = '</package>'
|
48
|
-
|
30
|
+
# define OPFImpl class
|
31
|
+
# it's private. only Pubgen.OPF.generate use it
|
49
32
|
module OPFImpl
|
50
33
|
def self.guess_media_type(filename)
|
51
34
|
case filename.downcase
|
@@ -78,10 +61,12 @@ EOF
|
|
78
61
|
|
79
62
|
manifest.each do |path|
|
80
63
|
if OPF.valid_manifest_element?(path) == false
|
81
|
-
raise "
|
64
|
+
raise "A manifest file, #{path} is not in sub-directory of " +
|
65
|
+
"yaml file"
|
82
66
|
end
|
83
67
|
id = "i%03d" % no
|
84
|
-
manifest_xml += " <item id=\"#{id}\" href=\"#{path}\"
|
68
|
+
manifest_xml += " <item id=\"#{id}\" href=\"#{path}\" " +
|
69
|
+
"media-type=\"#{guess_media_type(path)}\"/>\n"
|
85
70
|
if path == cover_path
|
86
71
|
cover_id = id
|
87
72
|
end
|
@@ -91,34 +76,45 @@ EOF
|
|
91
76
|
end
|
92
77
|
|
93
78
|
if cover_path && cover_id == nil
|
94
|
-
raise "
|
79
|
+
raise "Failed to find cover-image from manifest"
|
95
80
|
end
|
96
81
|
|
97
|
-
manifest_xml += " <item id=\"ncx\" href=\"#{
|
82
|
+
manifest_xml += " <item id=\"ncx\" href=\"#{OPF.ncx_path}\" " +
|
83
|
+
"media-type=\"application/x-dtbncx+xml\"/>\n </manifest>\n"
|
98
84
|
|
99
85
|
return cover_id, manifest_xml, file2id
|
100
86
|
end
|
101
87
|
|
88
|
+
def self.cgi_escape(text)
|
89
|
+
CGI.escapeHTML(text || '')
|
90
|
+
end
|
91
|
+
|
102
92
|
def self.get_metadata_xml(metadata, uuid, cover_id)
|
103
93
|
cover_id_xml = ''
|
104
94
|
if cover_id != nil
|
105
|
-
cover_id_xml = "\n <meta name=\"cover\" content=\"
|
95
|
+
cover_id_xml = "\n <meta name=\"cover\" content=\"#{cover_id}\"/>"
|
106
96
|
end
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
97
|
+
<<EOF
|
98
|
+
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" \
|
99
|
+
xmlns:opf="http://www.idpf.org/2007/opf">
|
100
|
+
<dc:title>#{cgi_escape(metadata['title'])}</dc:title>
|
101
|
+
<dc:creator opf:role="aut">#{cgi_escape(metadata['creator'])}\
|
102
|
+
</dc:creator>
|
103
|
+
<dc:date>#{cgi_escape((metadata['date'].is_a?(Fixnum) ? \
|
104
|
+
metadata['date'].to_s : metadata['date']))}</dc:date>
|
105
|
+
<dc:language>#{cgi_escape(metadata['language'])}</dc:language>
|
106
|
+
<dc:subject>#{cgi_escape(metadata['subject'])}</dc:subject>
|
107
|
+
<dc:publisher>#{cgi_escape(metadata['publisher'])}</dc:publisher>
|
108
|
+
<dc:description>#{cgi_escape(metadata['description'])}</dc:description>
|
109
|
+
<dc:contributor opf:role="bkp">#{cgi_escape(metadata['contributor'])}\
|
110
|
+
</dc:contributor>
|
111
|
+
<dc:source>#{cgi_escape(metadata['source'])}</dc:source>
|
112
|
+
<dc:rights>#{cgi_escape(metadata['rights'])}</dc:rights>
|
113
|
+
<dc:relation>#{cgi_escape(metadata['relation'])}</dc:relation>
|
114
|
+
<dc:identifier id="BookID" opf:scheme="UUID">#{uuid}</dc:identifier>\
|
115
|
+
#{cover_id_xml}
|
116
|
+
</metadata>
|
117
|
+
EOF
|
122
118
|
end
|
123
119
|
|
124
120
|
def self.get_guide_xml(guide, file2id)
|
@@ -126,25 +122,28 @@ EOF
|
|
126
122
|
cover_page = guide['cover-page']
|
127
123
|
if cover_page != nil
|
128
124
|
if file2id[cover_page] == nil
|
129
|
-
raise "
|
125
|
+
raise "Failed to find cover-page from manifest"
|
130
126
|
else
|
131
|
-
guide_xml += " <reference href=\"
|
127
|
+
guide_xml += " <reference href=\"#{cover_page}\" " +
|
128
|
+
"type=\"cover\" title=\"Cover\"/>\n"
|
132
129
|
end
|
133
130
|
end
|
134
131
|
toc_page = guide['toc-page']
|
135
132
|
if toc_page != nil
|
136
133
|
if file2id[toc_page] == nil
|
137
|
-
raise "
|
134
|
+
raise "Failed to find toc-page from manifest"
|
138
135
|
else
|
139
|
-
guide_xml += " <reference href=\"
|
136
|
+
guide_xml += " <reference href=\"#{toc_page}\" type=\"toc\" " +
|
137
|
+
"title=\"Table of Contents\"/>\n"
|
140
138
|
end
|
141
139
|
end
|
142
140
|
title_page = guide['title-page']
|
143
141
|
if title_page != nil
|
144
142
|
if file2id[title_page] == nil
|
145
|
-
raise "
|
143
|
+
raise "Failed to find title-page from manifest"
|
146
144
|
else
|
147
|
-
guide_xml += " <reference href=\"
|
145
|
+
guide_xml += " <reference href=\"#{title_page}\" " +
|
146
|
+
"type=\"title-page\" title=\"Title Page\"/>\n"
|
148
147
|
end
|
149
148
|
end
|
150
149
|
guide_xml += " </guide>\n"
|
@@ -156,7 +155,7 @@ EOF
|
|
156
155
|
if file2id[path] != nil
|
157
156
|
spine_xml += " <itemref idref=\"#{file2id[path]}\"/>\n"
|
158
157
|
else
|
159
|
-
raise "
|
158
|
+
raise "Failed to find spine element `#{path}' from manifest"
|
160
159
|
end
|
161
160
|
end
|
162
161
|
spine_xml += " </spine>\n"
|
data/pubgen.gemspec
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
|
+
$:.push File.expand_path("../lib", __FILE__)
|
4
|
+
require "pubgen/version"
|
5
|
+
|
3
6
|
Gem::Specification.new do |s|
|
4
7
|
s.name = "pubgen"
|
5
|
-
s.version =
|
8
|
+
s.version = Pubgen::VERSION
|
6
9
|
s.platform = Gem::Platform::RUBY
|
7
10
|
s.author = "9beach"
|
8
11
|
s.email = ["9beach@gmail.com"]
|
@@ -12,6 +15,6 @@ Gem::Specification.new do |s|
|
|
12
15
|
s.bindir = 'bin'
|
13
16
|
s.require_paths = ["lib"]
|
14
17
|
s.summary = "command-line based epub generator"
|
15
|
-
s.description = "Pubgen is a simple command-line based epub generator. With
|
18
|
+
s.description = "Pubgen is a simple command-line based epub generator. With a plain YAML, Pubgen generate the epub for you."
|
16
19
|
s.add_dependency "zipruby"
|
17
20
|
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'pubgen'
|
data/test/test_ncx.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
require 'helper'
|
5
|
+
|
6
|
+
$test_yaml = <<EOF
|
7
|
+
metadata:
|
8
|
+
title: "Will Oldham"
|
9
|
+
creator: Wikipedia
|
10
|
+
date: 2012
|
11
|
+
language: en
|
12
|
+
subject: American alternative country singers
|
13
|
+
publisher: 9beach
|
14
|
+
contributor: 9valley
|
15
|
+
description: describe here
|
16
|
+
source: "http://en.wikipedia.org/wiki/Will_Oldham"
|
17
|
+
rights: I've got no right
|
18
|
+
relation: bad relation
|
19
|
+
|
20
|
+
guide:
|
21
|
+
toc-page: contents/a.html
|
22
|
+
title-page: contents/b.html
|
23
|
+
cover-page: contents/c.html
|
24
|
+
cover-image: images/cover.jpg
|
25
|
+
|
26
|
+
manifest:
|
27
|
+
- contents/a.html
|
28
|
+
- contents/b.html
|
29
|
+
- contents/c.html
|
30
|
+
- images/cover.jpg
|
31
|
+
- images/1.jpg
|
32
|
+
- images/2.jpg
|
33
|
+
- images/3.jpg
|
34
|
+
- style.css
|
35
|
+
|
36
|
+
spine:
|
37
|
+
- contents/a.html
|
38
|
+
- contents/b.html
|
39
|
+
- contents/c.html
|
40
|
+
|
41
|
+
toc:
|
42
|
+
- 1 Music -- contents/a.html:
|
43
|
+
- 1.1 Discography -- contents/a.html#discography:
|
44
|
+
- 1.1.1 Studio albums -- contents/a.html#studio_albums
|
45
|
+
- 1.2 Response -- contents/a.html#response
|
46
|
+
- 2 Film -- contents/b.html:
|
47
|
+
- 2.1 Filmography -- contents/b.html#filmography
|
48
|
+
- 3 Photography -- contents/b.html#photography
|
49
|
+
- 4 References -- contents/b.html#references
|
50
|
+
- 5 External links -- contents/c.html
|
51
|
+
EOF
|
52
|
+
|
53
|
+
class TestNCX < Test::Unit::TestCase
|
54
|
+
def setup
|
55
|
+
$yaml = YAML::load $test_yaml
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_generate
|
59
|
+
xml = Pubgen::NCX.generate('English Patient', $yaml['toc'], '1111')
|
60
|
+
|
61
|
+
assert_match(/<meta content="1111" name="dtb:uid"\/>/, xml)
|
62
|
+
assert_match(/^ <navPoint id="d001" playOrder="1">/, xml)
|
63
|
+
assert_match(/^ <content src="contents\/a.html"/, xml)
|
64
|
+
assert_match(/^ <text>1 Music</, xml)
|
65
|
+
assert_match(/^ <navPoint id="d002" playOrder="2">/, xml)
|
66
|
+
assert_match(/^ <content src="contents\/a.html#discography"/, xml)
|
67
|
+
assert_match(/^ <text>1.1 Discography</, xml)
|
68
|
+
assert_match(/^ <navPoint id="d003" playOrder="3">/, xml)
|
69
|
+
assert_match(/^ <content src="contents\/a.html#studio_albums"/, xml)
|
70
|
+
assert_match(/^ <text>1.1.1 Studio albums</, xml)
|
71
|
+
assert_match(/^ <navPoint id="d004" playOrder="4">/, xml)
|
72
|
+
assert_match(/^ <content src="contents\/a.html#response"/, xml)
|
73
|
+
assert_match(/^ <text>1.2 Response</, xml)
|
74
|
+
assert_match(/^ <navPoint id="d005" playOrder="5">/, xml)
|
75
|
+
assert_match(/^ <content src="contents\/b.html"/, xml)
|
76
|
+
assert_match(/^ <text>2 Film</, xml)
|
77
|
+
assert_match(/^ <navPoint id="d006" playOrder="6">/, xml)
|
78
|
+
assert_match(/^ <content src="contents\/b.html#filmography"/, xml)
|
79
|
+
assert_match(/^ <text>2.1 Filmography</, xml)
|
80
|
+
assert_match(/^ <navPoint id="d007" playOrder="7">/, xml)
|
81
|
+
assert_match(/^ <content src="contents\/b.html#photography"/, xml)
|
82
|
+
assert_match(/^ <text>3 Photography</, xml)
|
83
|
+
assert_match(/^ <navPoint id="d008" playOrder="8">/, xml)
|
84
|
+
assert_match(/^ <content src="contents\/b.html#references"/, xml)
|
85
|
+
assert_match(/^ <text>4 References</, xml)
|
86
|
+
assert_match(/^ <navPoint id="d009" playOrder="9">/, xml)
|
87
|
+
assert_match(/^ <content src="contents\/c.html"/, xml)
|
88
|
+
assert_match(/^ <text>5 External links</, xml)
|
89
|
+
end
|
90
|
+
end
|
data/test/test_opf.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
require 'helper'
|
5
|
+
|
6
|
+
$test_yaml = <<EOF
|
7
|
+
metadata:
|
8
|
+
title: "Will Oldham"
|
9
|
+
creator: Wikipedia
|
10
|
+
date: 2012
|
11
|
+
language: en
|
12
|
+
subject: American alternative country singers
|
13
|
+
publisher: 9beach
|
14
|
+
contributor: 9valley
|
15
|
+
description: describe here
|
16
|
+
source: "http://en.wikipedia.org/wiki/Will_Oldham"
|
17
|
+
rights: I've got no right
|
18
|
+
relation: bad relation
|
19
|
+
|
20
|
+
guide:
|
21
|
+
toc-page: contents/a.html
|
22
|
+
title-page: contents/b.html
|
23
|
+
cover-page: contents/c.html
|
24
|
+
cover-image: images/cover.jpg
|
25
|
+
|
26
|
+
manifest:
|
27
|
+
- contents/a.html
|
28
|
+
- contents/b.html
|
29
|
+
- contents/c.html
|
30
|
+
- images/cover.jpg
|
31
|
+
- images/1.jpg
|
32
|
+
- images/2.jpg
|
33
|
+
- images/3.jpg
|
34
|
+
- style.css
|
35
|
+
|
36
|
+
spine:
|
37
|
+
- contents/a.html
|
38
|
+
- contents/b.html
|
39
|
+
- contents/c.html
|
40
|
+
|
41
|
+
toc:
|
42
|
+
- 1 Music -- contents/a.html:
|
43
|
+
- 1.1 Discography -- contents/a.html#discography:
|
44
|
+
- 1.1.1 Studio albums -- contents/a.html#studio_albums
|
45
|
+
- 1.2 Response -- contents/a.html#response
|
46
|
+
- 2 Film -- contents/b.html:
|
47
|
+
- 2.1 Filmography -- contents/b.html#filmography
|
48
|
+
- 3 Photography -- contents/b.html#photography
|
49
|
+
- 4 References -- contents/b.html#references
|
50
|
+
- 5 External links -- contents/c.html
|
51
|
+
EOF
|
52
|
+
|
53
|
+
class TestOPF < Test::Unit::TestCase
|
54
|
+
def setup
|
55
|
+
$yaml = YAML::load $test_yaml
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_metadata
|
59
|
+
xml = Pubgen::OPF.generate($yaml, 'aaaaaaaa-1111')
|
60
|
+
assert_match(/<dc:title>Will Oldham<\/dc:[^>].*>/, xml)
|
61
|
+
assert_match(/<dc:creator opf:role="aut">Wikipedia<\/dc:[^>].*>/, xml)
|
62
|
+
assert_match(/<dc:date>2012<\/dc:[^>].*>/, xml)
|
63
|
+
assert_match(/<dc:language>en<\/dc:[^>].*>/, xml)
|
64
|
+
assert_match(/<dc:subject>American alternative country singers<\/dc:[^>].*>/, xml)
|
65
|
+
assert_match(/<dc:publisher>9beach<\/dc:[^>].*>/, xml)
|
66
|
+
assert_match(/<dc:description>describe here<\/dc:[^>].*>/, xml)
|
67
|
+
assert_match(/<dc:source>http:\/\/en.wikipedia.org\/wiki\/Will_Oldham<\/dc:[^>].*>/, xml)
|
68
|
+
assert_match(/<dc:rights>I've got no right<\/dc:[^>].*>/, xml)
|
69
|
+
assert_match(/<dc:relation>bad relation<\/dc:[^>].*>/, xml)
|
70
|
+
assert_match(/<dc:contributor opf:role="bkp">9valley<\/dc:[^>].*>/, xml)
|
71
|
+
assert_match(/<dc:identifier id="BookID" opf:scheme="UUID">aaaaaaaa-1111<\/dc:[^>].*>/, xml)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_guide
|
75
|
+
xml = Pubgen::OPF.generate($yaml, 'aaaaaaaa')
|
76
|
+
|
77
|
+
assert_match(/reference href="contents\/a.html" type="toc"/, xml)
|
78
|
+
assert_match(/reference href="contents\/b.html" type="title-page"/, xml)
|
79
|
+
assert_match(/reference href="contents\/c.html" type="cover"/, xml)
|
80
|
+
assert_match(/<meta name="cover" content/, xml)
|
81
|
+
|
82
|
+
$yaml['guide']['cover-image'] = nil
|
83
|
+
xml = Pubgen::OPF.generate($yaml, 'aaaaaaa')
|
84
|
+
assert_no_match(/<meta name="cover" content/, xml)
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_manifest
|
88
|
+
xml = Pubgen::OPF.generate($yaml, 'a')
|
89
|
+
assert_match(/item id="i001" href="contents\/a.html" media-type="application\/xhtml\+xml"\/>/, xml)
|
90
|
+
assert_match(/item id="i002" href="contents\/b.html" media-type="application\/xhtml\+xml"\/>/, xml)
|
91
|
+
assert_match(/item id="i003" href="contents\/c.html" media-type="application\/xhtml\+xml"\/>/, xml)
|
92
|
+
assert_match(/item id="i004" href="images\/cover.jpg" media-type="image\/jpeg"\/>/, xml)
|
93
|
+
assert_match(/item id="i005" href="images\/1.jpg" media-type="image\/jpeg"\/>/, xml)
|
94
|
+
assert_match(/item id="i006" href="images\/2.jpg" media-type="image\/jpeg"\/>/, xml)
|
95
|
+
assert_match(/item id="i007" href="images\/3.jpg" media-type="image\/jpeg"\/>/, xml)
|
96
|
+
assert_match(/item id="i008" href="style.css" media-type="text\/css"\/>/, xml)
|
97
|
+
assert_match(/item id="ncx" href="#{Pubgen::OPF.ncx_path}" media-type="application\/x-dtbncx\+xml"\/>/, xml)
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_spine
|
101
|
+
xml = Pubgen::OPF.generate($yaml, 'aaaaaaaa-1111')
|
102
|
+
assert_match(/<itemref idref="i001"\/>/, xml)
|
103
|
+
assert_match(/<itemref idref="i002"\/>/, xml)
|
104
|
+
assert_match(/<itemref idref="i003"\/>/, xml)
|
105
|
+
assert_no_match(/<itemref idref="i004"\/>/, xml)
|
106
|
+
assert_no_match(/<itemref idref="i005"\/>/, xml)
|
107
|
+
assert_no_match(/<itemref idref="i006"\/>/, xml)
|
108
|
+
assert_no_match(/<itemref idref="i007"\/>/, xml)
|
109
|
+
assert_no_match(/<itemref idref="i008"\/>/, xml)
|
110
|
+
assert_no_match(/<itemref idref="ncx"\/>/, xml)
|
111
|
+
end
|
112
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pubgen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-27 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: zipruby
|
16
|
-
requirement: &
|
16
|
+
requirement: &15276980 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,9 +21,9 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
25
|
-
description: Pubgen is a simple command-line based epub generator. With
|
26
|
-
|
24
|
+
version_requirements: *15276980
|
25
|
+
description: Pubgen is a simple command-line based epub generator. With a plain YAML,
|
26
|
+
Pubgen generate the epub for you.
|
27
27
|
email:
|
28
28
|
- 9beach@gmail.com
|
29
29
|
executables:
|
@@ -34,13 +34,19 @@ files:
|
|
34
34
|
- .gitignore
|
35
35
|
- LICENSE
|
36
36
|
- README.md
|
37
|
+
- Rakefile
|
37
38
|
- bin/pubgen
|
38
39
|
- lib/pubgen.rb
|
39
40
|
- lib/pubgen/container.rb
|
40
41
|
- lib/pubgen/cover_page.rb
|
41
42
|
- lib/pubgen/ncx.rb
|
42
43
|
- lib/pubgen/opf.rb
|
44
|
+
- lib/pubgen/version.rb
|
43
45
|
- pubgen.gemspec
|
46
|
+
- test/helper.rb
|
47
|
+
- test/test_cover_page.rb
|
48
|
+
- test/test_ncx.rb
|
49
|
+
- test/test_opf.rb
|
44
50
|
homepage: https://github.com/9beach/pubgen
|
45
51
|
licenses: []
|
46
52
|
post_install_message:
|