gepub 0.6.4 → 0.6.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|