pubgen 0.1.2 → 0.1.3
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.
- 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:
|