gepub 0.6.4 → 0.6.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -4
- data/bin/gepuber +4 -0
- data/bin/gepubgen +65 -0
- data/lib/gepub/book.rb +118 -11
- data/lib/gepub/datemeta.rb +25 -0
- data/lib/gepub/item.rb +10 -1
- data/lib/gepub/meta.rb +2 -2
- data/lib/gepub/metadata.rb +24 -9
- data/lib/gepub/package.rb +11 -9
- data/lib/gepub/resource_builder.rb +1 -1
- data/lib/gepub/version.rb +1 -1
- data/lib/gepub.rb +1 -1
- data/spec/builder_spec.rb +21 -0
- data/spec/gepub_spec.rb +1 -1
- data/spec/metadata_spec.rb +13 -0
- metadata +11 -9
- data/lib/gepub/gepuber.rb +0 -41
data/README.md
CHANGED
@@ -21,15 +21,12 @@ a generic EPUB parser/generator library.
|
|
21
21
|
require 'rubygem'
|
22
22
|
require 'gepub'
|
23
23
|
builder = GEPUB::Builder.new {
|
24
|
-
unique_identifier 'http:/example.jp/bookid_in_url', 'BookID', 'URL'
|
25
24
|
language 'en'
|
26
|
-
|
25
|
+
unique_identifier 'http:/example.jp/bookid_in_url', 'BookID', 'URL'
|
27
26
|
title 'GEPUB Sample Book'
|
28
27
|
subtitle 'This book is just a sample'
|
29
|
-
alt 'ja' => 'これはあくまでサンプルです'
|
30
28
|
|
31
29
|
creator 'KOJIMA Satoshi'
|
32
|
-
alt 'ja' => '小嶋智'
|
33
30
|
|
34
31
|
contributors 'Denshobu', 'Asagaya Densho', 'Shonan Densho Teidan', 'eMagazine Torutaru'
|
35
32
|
|
@@ -40,7 +37,9 @@ a generic EPUB parser/generator library.
|
|
40
37
|
ordered {
|
41
38
|
file 'text/chap1.xhtml'
|
42
39
|
heading 'Chapter 1'
|
40
|
+
|
43
41
|
file 'text/chap1-1.xhtml'
|
42
|
+
|
44
43
|
file 'text/chap2.html'
|
45
44
|
heading 'Chapter 2'
|
46
45
|
}
|
data/bin/gepuber
CHANGED
data/bin/gepubgen
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'gepub'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
def usage
|
5
|
+
STDERR.print "gepubgen [-d destination ] [-c configfilename] <source-directory>\r\n"
|
6
|
+
exit 1
|
7
|
+
end
|
8
|
+
|
9
|
+
def srccheck(srcdir, configfilename)
|
10
|
+
if !File.exist?(srcdir) || !File.directory?(srcdir)
|
11
|
+
STDERR.print "#{srcdir} is not a directory"
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
if !File.exist?(File.join(srcdir, configfilename))
|
15
|
+
STDERR.print "#{configfilename} does not exists in#{srcdir}."
|
16
|
+
exit 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def destcheck(destdir)
|
21
|
+
if (File.exist?(destdir) && !File.directory?(destdir))
|
22
|
+
STDERR.print "#{destdir} is not a directory\n"
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
destbasedir = "."
|
28
|
+
configfilename = 'gepubgen.conf'
|
29
|
+
|
30
|
+
opt = OptionParser.new
|
31
|
+
|
32
|
+
usage if ARGV.length < 1
|
33
|
+
|
34
|
+
opt.on('-d [directory]') { |dir|
|
35
|
+
destbasedir = dir
|
36
|
+
}
|
37
|
+
|
38
|
+
opt.on('-c [configfilename]') { |name|
|
39
|
+
configfilename = name
|
40
|
+
}
|
41
|
+
|
42
|
+
destbasedir = File.expand_path(destbasedir)
|
43
|
+
|
44
|
+
srcdir = opt.parse(ARGV)[0]
|
45
|
+
srccheck(srcdir, configfilename)
|
46
|
+
|
47
|
+
epubname_to_generate = 'gepub_generated.epub'
|
48
|
+
|
49
|
+
Dir.chdir(srcdir)
|
50
|
+
begin
|
51
|
+
File.open(configfilename, 'rb') {
|
52
|
+
|io|
|
53
|
+
GEPUB::Builder.new {
|
54
|
+
table_of_contents = {}
|
55
|
+
(class<< self;self;end).send(
|
56
|
+
:define_method,
|
57
|
+
:epub_name, Proc.new { |name|
|
58
|
+
epubname_to_generate = name
|
59
|
+
})
|
60
|
+
eval "#{io.read}"
|
61
|
+
}.generate_epub(File.join(destbasedir, epubname_to_generate))
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
|
data/lib/gepub/book.rb
CHANGED
@@ -4,7 +4,76 @@ require 'nokogiri'
|
|
4
4
|
require 'zip/zip'
|
5
5
|
require 'fileutils'
|
6
6
|
|
7
|
+
# = GEPUB
|
8
|
+
# Author:: KOJIMA Satoshi
|
9
|
+
# namespace for gepub library.
|
10
|
+
# GEPUB::Book for parsing/generating, GEPUB::Builder for generating.
|
11
|
+
# GEPUB::Item holds data of resources like xhtml text, css, scripts, images, videos, etc.
|
12
|
+
# GEPUB::Meta holds metadata(title, creator, publisher, etc.) with its information (alternate script, display sequence, etc.)
|
13
|
+
|
7
14
|
module GEPUB
|
15
|
+
# Book is the basic class to hold data in EPUB files.
|
16
|
+
#
|
17
|
+
# It can generate and parse EPUB2/EPUB3 files. For generating a new EPUB file,
|
18
|
+
# consider to use GEPUB::Builder. Builder is specialized for generating EPUB,
|
19
|
+
# very easy to use and can handle almost every metadata of EPUB3.
|
20
|
+
#
|
21
|
+
# Book delegates many methods to objects in other class, so you can't find
|
22
|
+
# them in Book#methods or in ri/rdoc documentation. Their description is below.
|
23
|
+
#
|
24
|
+
# == \Package Attributes
|
25
|
+
# === Book#version (delegated to Package#version)
|
26
|
+
# returns OPF version.
|
27
|
+
# === Book#version=, Book#set_version (delegated to Package#version=)
|
28
|
+
# set OPF version
|
29
|
+
# === Book#unique_identifier (delegated to Package#unique_identifier)
|
30
|
+
# return unique_identifier ID value. identifier itself can be get by Book#identifier
|
31
|
+
# == \Metadata
|
32
|
+
# \Metadata items(e.g. title, creator, publisher, etc) are GEPUB::Meta objects.
|
33
|
+
# === Book#identifier (delegated to Package#identifier)
|
34
|
+
# return GEPUB::Meta object of unique identifier.
|
35
|
+
# === Book#identifier=(identifier) (delegated to Package#identifier=)
|
36
|
+
# set identifier (i.e. url, uuid, ISBN) as unique-identifier of EPUB.
|
37
|
+
# === Book#set_main_id(identifier, id = nil, type = nil) (delegated to Package#set_main_id)
|
38
|
+
# same as identifier=, but can specify id (in the opf xml) and identifier type(i.e. URL, uuid, ISBN, etc)
|
39
|
+
# === Book#add_identifier(string, id, type=nil) (delegated to Metadata#add_identifier)
|
40
|
+
# Set an identifier metadata. It it not unique-identifier in opf. Many EPUB files do not set identifier other than unique-identifier.
|
41
|
+
# === Book#add_title(content, id = nil, title_type = nil) (delegated to Metadata#add_title)
|
42
|
+
# add title metadata. title_type candidates is defined in TITLE_TYPES.
|
43
|
+
# === Book#set_title(content, id = nil, title_type = nil) (delegated to Metadata#set_title)
|
44
|
+
# clear all titles and then add title.
|
45
|
+
# === Book#title (delegated to Metadata)
|
46
|
+
# returns 'main' title Meta object. 'main' title is determined by this order:
|
47
|
+
# 1. title-type is 'main'
|
48
|
+
# 2. display-seq is smallest
|
49
|
+
# 3. appears first in opf file
|
50
|
+
# === Book#title_list (delegated to Metadata)
|
51
|
+
# returns titles list by display-seq or defined order.
|
52
|
+
# the title without display-seq is appear after titles with display-seq.
|
53
|
+
# === Book#add_creator(content, id = nil, role = 'aut') (delegated to Metadata#add_creator)
|
54
|
+
# add creator.
|
55
|
+
# === Book#creator
|
56
|
+
# returns 'main' creator Meta object. 'main' creator is determined as following:
|
57
|
+
# 1. display-seq is smallest
|
58
|
+
# 2. appears first in opf file
|
59
|
+
# === Book#creator_list (delegated to Metadata)
|
60
|
+
# returns creators list by display-seq or defined order.
|
61
|
+
# the creators without display-seq is appear after creators with display-seq.
|
62
|
+
# === Book#add_contributor(content, id = nil, role = 'aut') (delegated to Metadata#add_contributor)
|
63
|
+
# add contributor.
|
64
|
+
# === Book#contributor(content, id = nil, role = 'aut') (delegated to Metadata#contributor)
|
65
|
+
# returns 'main' contributor. 'main' contributor determined as following:
|
66
|
+
# 1. display-seq is smallest
|
67
|
+
# 2. appears first in opf file
|
68
|
+
# === Book#contributors_list (delegated to Metadata)
|
69
|
+
# returns contributors list by display-seq or defined order.
|
70
|
+
# the contributors without display-seq is appear after contributors with display-seq.
|
71
|
+
# === Book#set_lastmodified(date=nil) (delegated to Metadata#set_lastmodified)
|
72
|
+
# set last modified date.if date is nil, it sets current time.
|
73
|
+
# === Book#lastmodified (delegated to Metadata#lastmodified)
|
74
|
+
# returns Meta object contains last modified time.
|
75
|
+
# === setting and reading other metadata: publisher, language, coverage, date, description, format, relation, rights, source, subject, type (delegated to Metadata)
|
76
|
+
# they all have methods like: publisher(which returns 'main' publisher), add_publisher(content, id) (which add publisher), set_publisher or publisher= (clears and set publisher), and publisher_list(returns publisher Meta object in display-seq order).
|
8
77
|
class Book
|
9
78
|
MIMETYPE='mimetype'
|
10
79
|
MIMETYPE_CONTENTS='application/epub+zip'
|
@@ -19,6 +88,9 @@ module GEPUB
|
|
19
88
|
doc.css("#{defaultns}|rootfiles > #{defaultns}|rootfile")[0]['full-path']
|
20
89
|
end
|
21
90
|
|
91
|
+
# Parses existing EPUB2/EPUB3 files from an IO object, and creates new Book object.
|
92
|
+
# book = self.parse(File.new('some.epub'))
|
93
|
+
|
22
94
|
def self.parse(io)
|
23
95
|
files = {}
|
24
96
|
package = nil
|
@@ -65,7 +137,10 @@ module GEPUB
|
|
65
137
|
book
|
66
138
|
}
|
67
139
|
end
|
68
|
-
|
140
|
+
|
141
|
+
# creates new empty Book object.
|
142
|
+
# usually you do not need to specify any arguments.
|
143
|
+
|
69
144
|
def initialize(path='OEBPS/package.opf', attributes = {})
|
70
145
|
if File.extname(path) != '.opf'
|
71
146
|
warn 'GEPUB::Book#new interface changed. You must supply path to package.opf as first argument. If you want to set title, please use GEPUB::Book#title='
|
@@ -75,13 +150,18 @@ module GEPUB
|
|
75
150
|
yield book if block_given?
|
76
151
|
end
|
77
152
|
|
153
|
+
# add navigation text (which will appear on navigation document or table of contents) to an item.
|
154
|
+
# DEPRECATED: please use Item#toc_text or Item#toc_text_with_id, or Builder#heading
|
155
|
+
|
78
156
|
def add_nav(item, text, id = nil)
|
79
157
|
warn 'add_nav is deprecated: please use Item#toc_text'
|
80
158
|
@toc.push({ :item => item, :text => text, :id => id})
|
81
159
|
end
|
82
160
|
|
161
|
+
# add an item(i.e. html, images, audios, etc) to Book.
|
162
|
+
# the added item will be referenced by the first argument in the EPUB container.
|
83
163
|
def add_item(href, io_or_filename = nil, id = nil, attributes = {})
|
84
|
-
item = @package.add_item(href,
|
164
|
+
item = @package.add_item(href,nil,id,attributes)
|
85
165
|
toc = @toc
|
86
166
|
metaclass = (class << item;self;end)
|
87
167
|
metaclass.send(:define_method, :toc_text,
|
@@ -94,11 +174,29 @@ module GEPUB
|
|
94
174
|
toc.push(:item => item, :text => text, :id => id)
|
95
175
|
item
|
96
176
|
})
|
97
|
-
|
98
|
-
|
177
|
+
item.push_content_callback {
|
178
|
+
|i|
|
179
|
+
if File.extname(i.href) =~ /.x?html/
|
180
|
+
parsed = Nokogiri::XML::Document.parse(i.content)
|
181
|
+
ns_prefix = parsed.namespaces.invert['http://www.w3.org/1999/xhtml']
|
182
|
+
if ns_prefix.nil?
|
183
|
+
prefix = ''
|
184
|
+
else
|
185
|
+
prefix = "#{ns_prefix}:"
|
186
|
+
end
|
187
|
+
videos = parsed.xpath("//#{prefix}video[starts-with(@src,'http')]")
|
188
|
+
audios = parsed.xpath("//#{prefix}audio[starts-with(@src,'http')]")
|
189
|
+
if videos.size > 0 || audios.size > 0
|
190
|
+
i.add_property('remote-resources')
|
191
|
+
end
|
192
|
+
end
|
193
|
+
}
|
194
|
+
item.add_content io_or_filename unless io_or_filename.nil?
|
99
195
|
item
|
100
196
|
end
|
101
197
|
|
198
|
+
# same as add_item, but the item will be added to spine of the EPUB.
|
199
|
+
|
102
200
|
def add_ordered_item(href, io_or_filename = nil, id = nil, attributes = {})
|
103
201
|
item = @package.add_ordered_item(href,io_or_filename,id,attributes)
|
104
202
|
toc = @toc
|
@@ -114,11 +212,15 @@ module GEPUB
|
|
114
212
|
def method_missing(name,*args)
|
115
213
|
@package.send(name, *args)
|
116
214
|
end
|
117
|
-
|
215
|
+
|
216
|
+
# should call ordered() with block.
|
217
|
+
# within the block, all item added by add_item will be added to spine also.
|
118
218
|
def ordered(&block)
|
119
219
|
@package.ordered(&block)
|
120
220
|
end
|
121
221
|
|
222
|
+
# clenup and maintain consistency of metadata and items included in the Book
|
223
|
+
# object.
|
122
224
|
def cleanup
|
123
225
|
if version.to_f < 3.0 || @package.epub_backward_compat
|
124
226
|
if @package.manifest.item_list.select {
|
@@ -150,6 +252,7 @@ module GEPUB
|
|
150
252
|
end
|
151
253
|
end
|
152
254
|
|
255
|
+
# write EPUB to stream specified by the argument.
|
153
256
|
def write_to_epub_container(epub)
|
154
257
|
epub.put_next_entry('mimetype', '', '', Zip::ZipEntry::STORED)
|
155
258
|
epub << "application/epub+zip"
|
@@ -161,11 +264,14 @@ module GEPUB
|
|
161
264
|
|
162
265
|
@package.manifest.item_list.each {
|
163
266
|
|k, item|
|
164
|
-
|
165
|
-
|
267
|
+
if item.content != nil
|
268
|
+
epub.put_next_entry(@package.contents_prefix + item.href)
|
269
|
+
epub << item.content
|
270
|
+
end
|
166
271
|
}
|
167
272
|
end
|
168
273
|
|
274
|
+
# generates and returns StringIO contains EPUB.
|
169
275
|
def generate_epub_stream
|
170
276
|
cleanup
|
171
277
|
Zip::ZipOutputStream::write_buffer {
|
@@ -173,7 +279,8 @@ module GEPUB
|
|
173
279
|
write_to_epub_container(epub)
|
174
280
|
}
|
175
281
|
end
|
176
|
-
|
282
|
+
|
283
|
+
# writes EPUB to file. if file exists, it will be overwritten.
|
177
284
|
def generate_epub(path_to_epub)
|
178
285
|
cleanup
|
179
286
|
File.delete(path_to_epub) if File.exist?(path_to_epub)
|
@@ -182,7 +289,7 @@ module GEPUB
|
|
182
289
|
write_to_epub_container(epub)
|
183
290
|
}
|
184
291
|
end
|
185
|
-
|
292
|
+
|
186
293
|
def container_xml
|
187
294
|
<<EOF
|
188
295
|
<?xml version="1.0" encoding="UTF-8"?>
|
@@ -219,7 +326,7 @@ EOF
|
|
219
326
|
}
|
220
327
|
}
|
221
328
|
}
|
222
|
-
builder.to_xml
|
329
|
+
builder.to_xml(:encoding => 'utf-8')
|
223
330
|
end
|
224
331
|
|
225
332
|
def ncx_xml
|
@@ -254,7 +361,7 @@ EOF
|
|
254
361
|
}
|
255
362
|
}
|
256
363
|
}
|
257
|
-
builder.to_xml
|
364
|
+
builder.to_xml(:encoding => 'utf-8')
|
258
365
|
end
|
259
366
|
|
260
367
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
module GEPUB
|
5
|
+
class DateMeta < Meta
|
6
|
+
def initialize(name, content, parent, attributes = {}, refiners = {})
|
7
|
+
if content.is_a? String
|
8
|
+
content = Time.parse(content)
|
9
|
+
end
|
10
|
+
super(name, content, parent, attributes, refiners)
|
11
|
+
end
|
12
|
+
|
13
|
+
def content=(date)
|
14
|
+
if content.is_a? String
|
15
|
+
content = Time.parse(content)
|
16
|
+
end
|
17
|
+
@content = content
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s(locale = nil)
|
21
|
+
# date type don't have alternate scripts.
|
22
|
+
@content.utc.iso8601
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/gepub/item.rb
CHANGED
@@ -14,6 +14,7 @@ module GEPUB
|
|
14
14
|
@attributes['media-type'] = guess_mediatype if media_type.nil?
|
15
15
|
@parent = parent
|
16
16
|
@parent.register_item(self) unless @parent.nil?
|
17
|
+
@content_callback = []
|
17
18
|
self
|
18
19
|
end
|
19
20
|
|
@@ -56,7 +57,11 @@ module GEPUB
|
|
56
57
|
def add_raw_content(data)
|
57
58
|
@content = data
|
58
59
|
end
|
59
|
-
|
60
|
+
|
61
|
+
def push_content_callback(&block)
|
62
|
+
@content_callback << block
|
63
|
+
end
|
64
|
+
|
60
65
|
def add_content(io_or_filename)
|
61
66
|
io = io_or_filename
|
62
67
|
if io_or_filename.class == String
|
@@ -64,6 +69,10 @@ module GEPUB
|
|
64
69
|
end
|
65
70
|
io.binmode
|
66
71
|
@content = io.read
|
72
|
+
@content_callback.each {
|
73
|
+
|p|
|
74
|
+
p.call self
|
75
|
+
}
|
67
76
|
self
|
68
77
|
end
|
69
78
|
|
data/lib/gepub/meta.rb
CHANGED
@@ -93,7 +93,7 @@ module GEPUB
|
|
93
93
|
end
|
94
94
|
|
95
95
|
# using eval to parametarize Namespace and content.
|
96
|
-
eval "builder#{ ns.nil? || @name == 'meta' ? '' : '[ns]'}.#{@name}(@attributes.reject{|k,v| v.nil?}.merge(additional_attr)#{@content.nil? ? '' : ',
|
96
|
+
eval "builder#{ ns.nil? || @name == 'meta' ? '' : '[ns]'}.#{@name}(@attributes.reject{|k,v| v.nil?}.merge(additional_attr)#{@content.nil? ? '' : ', self.to_s'})"
|
97
97
|
|
98
98
|
if @refiners.size > 0 && opf_version.to_f >= 3.0
|
99
99
|
additional_attr['refines'] = "##{@attributes['id']}"
|
@@ -121,7 +121,7 @@ module GEPUB
|
|
121
121
|
}.reverse
|
122
122
|
localized = candidates[0].content if candidates.size > 0
|
123
123
|
end
|
124
|
-
(localized ||
|
124
|
+
(localized || self.content || super).to_s
|
125
125
|
end
|
126
126
|
end
|
127
127
|
end
|
data/lib/gepub/metadata.rb
CHANGED
@@ -96,9 +96,7 @@ module GEPUB
|
|
96
96
|
|
97
97
|
#TODO: should override for 'title'. // for 'main title' not always comes first.
|
98
98
|
define_method(node) {
|
99
|
-
|
100
|
-
@content_nodes[node][0]
|
101
|
-
end
|
99
|
+
get_first_node(node)
|
102
100
|
}
|
103
101
|
|
104
102
|
define_method('add_' + node) {
|
@@ -114,11 +112,16 @@ module GEPUB
|
|
114
112
|
|
115
113
|
define_method(node+'=') {
|
116
114
|
|content|
|
117
|
-
send(
|
118
|
-
add_metadata(node, content)
|
115
|
+
send('set_' + node, content, nil)
|
119
116
|
}
|
120
117
|
}
|
121
118
|
|
119
|
+
def get_first_node(node)
|
120
|
+
if !@content_nodes[node].nil? && @content_nodes[node].size > 0
|
121
|
+
@content_nodes[node][0]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
122
125
|
def add_identifier(string, id, type=nil)
|
123
126
|
raise 'id #{id} is already in use' if @id_pool[id]
|
124
127
|
identifier = add_metadata('identifier', string, id)
|
@@ -126,6 +129,10 @@ module GEPUB
|
|
126
129
|
identifier
|
127
130
|
end
|
128
131
|
|
132
|
+
def add_date(date, id)
|
133
|
+
add_metadata('date', date, id, DateMeta)
|
134
|
+
end
|
135
|
+
|
129
136
|
def identifier_by_id(id)
|
130
137
|
@content_nodes['identifier'].each {
|
131
138
|
|x|
|
@@ -133,8 +140,8 @@ module GEPUB
|
|
133
140
|
}
|
134
141
|
end
|
135
142
|
|
136
|
-
def add_metadata(name, content, id = nil)
|
137
|
-
meta =
|
143
|
+
def add_metadata(name, content, id = nil, itemclass = Meta)
|
144
|
+
meta = itemclass.new(name, content, self, { 'id' => id })
|
138
145
|
(@content_nodes[name] ||= []) << meta
|
139
146
|
yield self if block_given?
|
140
147
|
meta
|
@@ -148,7 +155,7 @@ module GEPUB
|
|
148
155
|
|
149
156
|
def set_title(content, id = nil, title_type = nil)
|
150
157
|
title_clear
|
151
|
-
add_title(content, id, title_type)
|
158
|
+
meta = add_title(content, id, title_type)
|
152
159
|
yield meta if block_given?
|
153
160
|
meta
|
154
161
|
end
|
@@ -170,6 +177,14 @@ module GEPUB
|
|
170
177
|
yield meta if block_given?
|
171
178
|
meta
|
172
179
|
end
|
180
|
+
|
181
|
+
def lastmodified
|
182
|
+
ret = (@content_nodes['meta'] ||=[]).select {
|
183
|
+
|meta|
|
184
|
+
meta['property'] == 'dcterms:modified'
|
185
|
+
}
|
186
|
+
ret.size == 0 ? nil : ret[0]
|
187
|
+
end
|
173
188
|
|
174
189
|
def set_lastmodified(date=nil)
|
175
190
|
date ||= Time.now
|
@@ -179,7 +194,7 @@ module GEPUB
|
|
179
194
|
@content_nodes['meta'].delete meta
|
180
195
|
end
|
181
196
|
}
|
182
|
-
add_metadata('meta', date.utc.strftime('%Y-%m-%dT%H:%M:%SZ'))['property'] = 'dcterms:modified'
|
197
|
+
add_metadata('meta', date.utc.strftime('%Y-%m-%dT%H:%M:%SZ'), nil, DateMeta)['property'] = 'dcterms:modified'
|
183
198
|
end
|
184
199
|
|
185
200
|
def add_oldstyle_meta(content, attributes = {})
|
data/lib/gepub/package.rb
CHANGED
@@ -86,7 +86,7 @@ module GEPUB
|
|
86
86
|
yield self if block_given?
|
87
87
|
end
|
88
88
|
|
89
|
-
['
|
89
|
+
['unique-identifier', 'xml:lang', 'dir', 'prefix', 'id'].each {
|
90
90
|
|name|
|
91
91
|
methodbase = name.gsub('-','_').sub('xml:lang', 'lang')
|
92
92
|
define_method(methodbase + '=') { |val| @attributes[name] = val }
|
@@ -115,12 +115,6 @@ module GEPUB
|
|
115
115
|
set_unique_identifier(id || @id_pool.generate_key(:prefix => 'BookId', :without_count => true))
|
116
116
|
@metadata.add_identifier identifier, unique_identifier, type
|
117
117
|
end
|
118
|
-
|
119
|
-
def specify_cover(item)
|
120
|
-
# ... not smart. should create old-meta on generating xml
|
121
|
-
@metadata.add_oldstyle_meta(nil, { 'name' => 'cover', 'content' => item.id })
|
122
|
-
item.add_properties 'cover-image'
|
123
|
-
end
|
124
118
|
|
125
119
|
def add_item(href, io_or_filename = nil, id = nil, attributes = {})
|
126
120
|
item = @manifest.add_item(id, href, nil, attributes)
|
@@ -193,12 +187,20 @@ module GEPUB
|
|
193
187
|
@metadata.language
|
194
188
|
end
|
195
189
|
|
196
|
-
def version
|
190
|
+
def version
|
191
|
+
@attributes['version']
|
192
|
+
end
|
193
|
+
|
194
|
+
def set_version(val)
|
197
195
|
@attributes['version'] = val
|
198
196
|
@metadata.opf_version = val
|
199
197
|
@manifest.opf_version = val
|
200
198
|
@spine.opf_version = val
|
201
199
|
end
|
200
|
+
|
201
|
+
def version=(val)
|
202
|
+
set_version(val)
|
203
|
+
end
|
202
204
|
|
203
205
|
def epub_version=(val)
|
204
206
|
warn 'epub_version= is deprecated. please use #version='
|
@@ -234,7 +236,7 @@ module GEPUB
|
|
234
236
|
@spine.to_xml(xml)
|
235
237
|
}
|
236
238
|
}
|
237
|
-
builder.to_xml
|
239
|
+
builder.to_xml(:encoding => 'utf-8')
|
238
240
|
end
|
239
241
|
|
240
242
|
|
data/lib/gepub/version.rb
CHANGED
data/lib/gepub.rb
CHANGED
@@ -9,13 +9,13 @@ end
|
|
9
9
|
require 'gepub/version'
|
10
10
|
require 'gepub/xml_util'
|
11
11
|
require 'gepub/meta'
|
12
|
+
require 'gepub/datemeta'
|
12
13
|
require 'gepub/metadata'
|
13
14
|
require 'gepub/manifest'
|
14
15
|
require 'gepub/spine'
|
15
16
|
require 'gepub/package'
|
16
17
|
require 'gepub/item'
|
17
18
|
require 'gepub/book'
|
18
|
-
require 'gepub/gepuber'
|
19
19
|
require 'gepub/builder_mixin'
|
20
20
|
require 'gepub/resource_builder'
|
21
21
|
require 'gepub/builder'
|
data/spec/builder_spec.rb
CHANGED
@@ -380,5 +380,26 @@ describe GEPUB::Builder do
|
|
380
380
|
}
|
381
381
|
end
|
382
382
|
|
383
|
+
it 'should create remote-resources' do
|
384
|
+
builder = GEPUB::Builder.new {
|
385
|
+
unique_identifier 'uid'
|
386
|
+
resources {
|
387
|
+
file 'with_remote.xhtml' => StringIO.new('<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"><head></head><body><div><p><video src="http://foo.bar">no video</video></p></div></body></html>')
|
388
|
+
}
|
389
|
+
}
|
390
|
+
builder.instance_eval {
|
391
|
+
@book.item_by_href('with_remote.xhtml').properties[0].should == 'remote-resources'
|
392
|
+
}
|
393
|
+
end
|
394
|
+
|
395
|
+
it 'should handle remote resource URL' do
|
396
|
+
builder = GEPUB::Builder.new {
|
397
|
+
unique_identifier 'uid'
|
398
|
+
resources {
|
399
|
+
file 'http://foo.bar'
|
400
|
+
}
|
401
|
+
}
|
402
|
+
# this should not raise 'No such file or directory'
|
403
|
+
end
|
383
404
|
end
|
384
405
|
end
|
data/spec/gepub_spec.rb
CHANGED
@@ -170,7 +170,6 @@ EOF
|
|
170
170
|
|
171
171
|
it "should generate correct epub2.0" do
|
172
172
|
epubname = File.join(File.dirname(__FILE__), 'testepub2.epub')
|
173
|
-
|
174
173
|
@book = GEPUB::Book.new('OEPBS/package.opf', { 'version' => '2.0'} )
|
175
174
|
@book.title = 'thetitle'
|
176
175
|
@book.creator = "theauthor"
|
@@ -191,4 +190,5 @@ EOF
|
|
191
190
|
system 'java', '-jar', jar, epubname
|
192
191
|
end
|
193
192
|
|
193
|
+
|
194
194
|
end
|
data/spec/metadata_spec.rb
CHANGED
@@ -125,6 +125,19 @@ describe GEPUB::Metadata do
|
|
125
125
|
xml.namespaces['xmlns:dc'].should == GEPUB::XMLUtil::DC_NS
|
126
126
|
end
|
127
127
|
|
128
|
+
it 'should handle date with Time object' do
|
129
|
+
metadata = GEPUB::Metadata.new
|
130
|
+
a = Time.parse '2012-02-27 20:00:00 UTC'
|
131
|
+
metadata.add_date(a, 'date')
|
132
|
+
metadata.date.to_s.should == '2012-02-27T20:00:00Z'
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should handle date with a not W3C-DTF string' do
|
136
|
+
metadata = GEPUB::Metadata.new
|
137
|
+
metadata.add_date('2012-02-28 05:00:00 +0900', 'date')
|
138
|
+
metadata.date.to_s.should == '2012-02-27T20:00:00Z'
|
139
|
+
end
|
140
|
+
|
128
141
|
it 'should generate metadata with id xml' do
|
129
142
|
metadata = GEPUB::Metadata.new
|
130
143
|
metadata.add_identifier('the_uid', nil)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gepub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.4
|
4
|
+
version: 0.6.4.1
|
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-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70282316619400 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '2'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70282316619400
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: nokogiri
|
27
|
-
requirement: &
|
27
|
+
requirement: &70282316618900 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.5.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70282316618900
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rubyzip
|
38
|
-
requirement: &
|
38
|
+
requirement: &70282316618440 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,13 +43,14 @@ dependencies:
|
|
43
43
|
version: 0.9.6
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70282316618440
|
47
47
|
description: gepub is a generic EPUB parser/generator. Generates and parse EPUB2 and
|
48
48
|
EPUB3
|
49
49
|
email:
|
50
50
|
- skoji@mac.com
|
51
51
|
executables:
|
52
52
|
- gepuber
|
53
|
+
- gepubgen
|
53
54
|
extensions: []
|
54
55
|
extra_rdoc_files: []
|
55
56
|
files:
|
@@ -59,6 +60,7 @@ files:
|
|
59
60
|
- README.md
|
60
61
|
- Rakefile
|
61
62
|
- bin/gepuber
|
63
|
+
- bin/gepubgen
|
62
64
|
- examples/builder_example.rb
|
63
65
|
- examples/generate_example.rb
|
64
66
|
- examples/image1.jpg
|
@@ -67,7 +69,7 @@ files:
|
|
67
69
|
- lib/gepub/book.rb
|
68
70
|
- lib/gepub/builder.rb
|
69
71
|
- lib/gepub/builder_mixin.rb
|
70
|
-
- lib/gepub/
|
72
|
+
- lib/gepub/datemeta.rb
|
71
73
|
- lib/gepub/item.rb
|
72
74
|
- lib/gepub/manifest.rb
|
73
75
|
- lib/gepub/meta.rb
|
data/lib/gepub/gepuber.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
|
3
|
-
module GEPUB
|
4
|
-
class Gepuber
|
5
|
-
def initialize(&block)
|
6
|
-
@block = block
|
7
|
-
end
|
8
|
-
|
9
|
-
def create
|
10
|
-
table_of_contents = {}
|
11
|
-
epub_name = 'gepuber_generated.epub'
|
12
|
-
GEPUB::Builder.new {
|
13
|
-
block.call
|
14
|
-
resources {
|
15
|
-
Dir.glob('*.css') {
|
16
|
-
|f|
|
17
|
-
file f
|
18
|
-
}
|
19
|
-
Dir.glob('img/*') {
|
20
|
-
|f|
|
21
|
-
if File.basename(f) == 'cover.jpg'
|
22
|
-
cover_image f
|
23
|
-
else
|
24
|
-
file f
|
25
|
-
end
|
26
|
-
}
|
27
|
-
|
28
|
-
ordered {
|
29
|
-
Dir.glob('[0-9]*.{xhtml,html}') {
|
30
|
-
|f|
|
31
|
-
file f
|
32
|
-
if table_of_contents[f]
|
33
|
-
heading table_of_contents[f]
|
34
|
-
end
|
35
|
-
}
|
36
|
-
}
|
37
|
-
}
|
38
|
-
}
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|