peregrin 1.1.4 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +6 -1
- data/lib/formats/epub.rb +91 -61
- data/lib/formats/zhook.rb +1 -2
- data/lib/peregrin/blueprint.rb +38 -0
- data/lib/peregrin/book.rb +50 -6
- data/lib/peregrin/version.rb +1 -1
- data/lib/peregrin.rb +1 -0
- data/test/formats/epub_test.rb +36 -0
- data/test/utils/componentizer_test.rb +4 -1
- metadata +8 -18
data/README.md
CHANGED
@@ -150,4 +150,9 @@ deeper meaning.
|
|
150
150
|
|
151
151
|
## History
|
152
152
|
|
153
|
-
* 1.
|
153
|
+
* 1.2.0
|
154
|
+
- Metadata files like OPF, OCX now first-class citizens called 'blueprints'
|
155
|
+
- Page progression direction from EPUB3 (@nono)
|
156
|
+
- Fixed-layout attributes for components (@nono)
|
157
|
+
* 1.1.4
|
158
|
+
- Basic EPUB3 and EPUB fixed-layout read support (@klacointe)
|
data/lib/formats/epub.rb
CHANGED
@@ -35,7 +35,7 @@ class Peregrin::Epub
|
|
35
35
|
begin
|
36
36
|
book = Peregrin::Book.new
|
37
37
|
epub = new(book)
|
38
|
-
epub.send(:
|
38
|
+
epub.send(:load_blueprints, zf)
|
39
39
|
rescue => e
|
40
40
|
raise e.class.new(path)
|
41
41
|
end
|
@@ -70,7 +70,7 @@ class Peregrin::Epub
|
|
70
70
|
|
71
71
|
|
72
72
|
def to_book(options = {})
|
73
|
-
|
73
|
+
@book.deep_clone
|
74
74
|
end
|
75
75
|
|
76
76
|
|
@@ -81,84 +81,86 @@ class Peregrin::Epub
|
|
81
81
|
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
82
82
|
|
83
83
|
def load_from_path(epub_path)
|
84
|
-
docs = nil
|
85
84
|
Zip::Archive.open(epub_path) { |zipfile|
|
86
|
-
|
87
|
-
extract_properties
|
88
|
-
extract_components(zipfile
|
89
|
-
extract_chapters(zipfile
|
90
|
-
extract_cover(zipfile
|
85
|
+
load_blueprints(zipfile)
|
86
|
+
extract_properties
|
87
|
+
extract_components(zipfile)
|
88
|
+
extract_chapters(zipfile)
|
89
|
+
extract_cover(zipfile)
|
91
90
|
}
|
92
91
|
@book.read_resource_proc = lambda { |resource|
|
93
|
-
media_path = from_opf_root(
|
94
|
-
media_path =
|
92
|
+
media_path = from_opf_root(resource.src)
|
93
|
+
media_path = uri_unescape(media_path)
|
95
94
|
Zip::Archive.open(epub_path) { |zipfile| zipfile.content(media_path) }
|
96
95
|
}
|
97
96
|
end
|
98
97
|
|
99
98
|
|
100
|
-
def
|
99
|
+
def load_blueprints(zipfile)
|
101
100
|
# The OCF file.
|
102
101
|
begin
|
103
102
|
ocf_content = zipfile.content(OCF_PATH)
|
104
|
-
|
103
|
+
ocf = @book.add_blueprint(:ocf, OCF_PATH, ocf_content)
|
105
104
|
rescue
|
106
105
|
raise FailureLoadingOCF
|
107
106
|
end
|
108
107
|
|
109
108
|
# The OPF file.
|
110
109
|
begin
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
)
|
115
|
-
docs[:opf_root] = File.dirname(docs[:opf_path])
|
116
|
-
opf_content = zipfile.content(docs[:opf_path])
|
117
|
-
docs[:opf] = Nokogiri::XML::Document.parse(opf_content)
|
110
|
+
opf_xp = '//ocf:rootfile[@media-type="application/oebps-package+xml"]'
|
111
|
+
opf_src = ocf.document.at_xpath(opf_xp, NAMESPACES[:ocf])['full-path']
|
112
|
+
opf_content = zipfile.content(opf_src)
|
113
|
+
opf = @book.add_blueprint(:opf, opf_src, opf_content)
|
118
114
|
rescue
|
119
115
|
raise FailureLoadingOPF
|
120
116
|
end
|
121
117
|
|
122
|
-
#
|
123
|
-
|
118
|
+
# EPUB version
|
119
|
+
pkg_elem = opf.document.at_xpath('//opf:package', NAMESPACES[:opf])
|
120
|
+
@epub_version = pkg_elem['version']
|
124
121
|
|
125
122
|
# The NCX file.
|
126
|
-
# Must be present only with Ebook < 3.0 but can be
|
123
|
+
# Must be present only with Ebook < 3.0 but can be used
|
124
|
+
# for forward compatibility
|
127
125
|
begin
|
128
|
-
spine =
|
126
|
+
spine = opf.document.at_xpath('//opf:spine', NAMESPACES[:opf])
|
129
127
|
ncx_id = spine['toc'] ? spine['toc'] : 'ncx'
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
)
|
134
|
-
|
135
|
-
|
136
|
-
ncx_content = zipfile.content(docs[:ncx_path])
|
137
|
-
docs[:ncx] = Nokogiri::XML::Document.parse(ncx_content)
|
138
|
-
rescue => e
|
128
|
+
ncx_xp = "//opf:manifest/opf:item[@id=#{escape_for_xpath(ncx_id)}]"
|
129
|
+
ncx_href = opf.document.at_xpath(ncx_xp, NAMESPACES[:opf])['href']
|
130
|
+
ncx_src = from_opf_root(ncx_href)
|
131
|
+
ncx_content = zipfile.content(ncx_src)
|
132
|
+
ncx = @book.add_blueprint(:ncx, ncx_src, ncx_content)
|
133
|
+
rescue
|
139
134
|
# Only raise an exeption for Ebook with version lower than 3.0
|
140
|
-
raise FailureLoadingNCX if
|
135
|
+
raise FailureLoadingNCX if epub_version < 3
|
141
136
|
end
|
142
137
|
|
143
138
|
# The NAV file. (Epub3 only)
|
144
|
-
if
|
139
|
+
if epub_version >= 3
|
145
140
|
begin
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
)
|
150
|
-
nav_content = zipfile.content(
|
151
|
-
|
141
|
+
nav_xp = "//opf:manifest/opf:item[contains"+
|
142
|
+
"(concat(' ', normalize-space(@properties), ' '), ' nav ')]"
|
143
|
+
nav_href = opf.document.at_xpath(nav_xp, NAMESPACES[:opf])['href']
|
144
|
+
nav_src = from_opf_root(nav_href)
|
145
|
+
nav_content = zipfile.content(nav_src)
|
146
|
+
nav = @book.add_blueprint(:nav, nav_src, nav_content)
|
152
147
|
rescue => e
|
153
148
|
raise FailureLoadingNAV
|
154
149
|
end
|
155
150
|
end
|
156
151
|
|
157
|
-
|
152
|
+
# The others
|
153
|
+
inf_rels = %w[container manifest metadata signature encryption rights]
|
154
|
+
inf_rels.each { |rel|
|
155
|
+
src = "META-INF/#{rel}.xml"
|
156
|
+
next unless zipfile.find(src)
|
157
|
+
bp = @book.add_blueprint(rel.to_sym, src, zipfile.content(src))
|
158
|
+
}
|
158
159
|
end
|
159
160
|
|
160
161
|
|
161
|
-
def extract_properties
|
162
|
+
def extract_properties
|
163
|
+
opf_doc = @book.blueprint_for(:opf).document
|
162
164
|
meta_elems = opf_doc.at_xpath(
|
163
165
|
'//opf:metadata',
|
164
166
|
NAMESPACES[:opf]
|
@@ -184,11 +186,21 @@ class Peregrin::Epub
|
|
184
186
|
}
|
185
187
|
@book.add_property(name, content, atts) unless name.nil?
|
186
188
|
}
|
189
|
+
|
190
|
+
# Assign EPUB version
|
191
|
+
@book.add_format_property('source', 'EPUB')
|
192
|
+
@book.add_format_property('version', @epub_version) if @epub_version
|
193
|
+
|
194
|
+
# Extract page-turning direction
|
195
|
+
if spine = opf_doc.at_xpath('//opf:spine', NAMESPACES[:opf])
|
196
|
+
dir = spine['page-progression-direction']
|
197
|
+
@book.add_format_property('page-progression-direction', dir) if dir
|
198
|
+
end
|
187
199
|
end
|
188
200
|
|
189
201
|
|
190
|
-
def extract_components(zipfile
|
191
|
-
|
202
|
+
def extract_components(zipfile)
|
203
|
+
opf_doc = @book.blueprint_for(:opf).document
|
192
204
|
manifest = opf_doc.at_xpath('//opf:manifest', NAMESPACES[:opf])
|
193
205
|
spine = opf_doc.at_xpath('//opf:spine', NAMESPACES[:opf])
|
194
206
|
|
@@ -201,18 +213,20 @@ class Peregrin::Epub
|
|
201
213
|
href = item['href']
|
202
214
|
linear = iref['linear'] != 'no'
|
203
215
|
begin
|
204
|
-
content = zipfile.content(from_opf_root(
|
216
|
+
content = zipfile.content(from_opf_root(href))
|
205
217
|
rescue
|
206
|
-
href =
|
207
|
-
content = zipfile.content(from_opf_root(
|
218
|
+
href = uri_unescape(href)
|
219
|
+
content = zipfile.content(from_opf_root(href))
|
208
220
|
end
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
221
|
+
atts = { :id => id, :linear => linear ? "yes" : "no" }
|
222
|
+
iref['properties'].split(/\s+/).each do |prop|
|
223
|
+
if prop =~ /^rendition:(layout|orientation|spread)-(.+)$/
|
224
|
+
atts["rendition:#{$1}"] = $2
|
225
|
+
else
|
226
|
+
atts[prop] = true
|
227
|
+
end
|
228
|
+
end if iref['properties']
|
229
|
+
@book.add_component(href, content, item['media-type'], atts)
|
216
230
|
end
|
217
231
|
}
|
218
232
|
|
@@ -231,14 +245,16 @@ class Peregrin::Epub
|
|
231
245
|
}
|
232
246
|
end
|
233
247
|
|
234
|
-
|
235
|
-
|
236
|
-
|
248
|
+
|
249
|
+
def extract_chapters(zipfile)
|
250
|
+
if epub_version >= 3 && nav = @book.blueprint_for(:nav)
|
251
|
+
extract_nav_chapters(zipfile, nav.document)
|
237
252
|
else
|
238
|
-
extract_ncx_chapters(zipfile,
|
253
|
+
extract_ncx_chapters(zipfile, @book.blueprint_for(:ncx).document)
|
239
254
|
end
|
240
255
|
end
|
241
256
|
|
257
|
+
|
242
258
|
# Epub < 3.0 only
|
243
259
|
def extract_ncx_chapters(zipfile, ncx_doc)
|
244
260
|
curse = lambda { |point|
|
@@ -259,6 +275,7 @@ class Peregrin::Epub
|
|
259
275
|
}
|
260
276
|
end
|
261
277
|
|
278
|
+
|
262
279
|
# Epub >= 3.0 only
|
263
280
|
def extract_nav_chapters(zipfile, nav_doc)
|
264
281
|
curse = lambda { |point, position|
|
@@ -286,7 +303,7 @@ class Peregrin::Epub
|
|
286
303
|
end
|
287
304
|
|
288
305
|
|
289
|
-
def extract_cover(zipfile
|
306
|
+
def extract_cover(zipfile)
|
290
307
|
@book.cover = nil
|
291
308
|
|
292
309
|
# 1. Cover image referenced from metadata
|
@@ -310,7 +327,7 @@ class Peregrin::Epub
|
|
310
327
|
if res.media_type.match(/^image\//)
|
311
328
|
@book.cover = res
|
312
329
|
else
|
313
|
-
path = from_opf_root(
|
330
|
+
path = from_opf_root(res.src)
|
314
331
|
begin
|
315
332
|
doc = Nokogiri::XML::Document.parse(zipfile.content(path))
|
316
333
|
src = nil
|
@@ -582,7 +599,9 @@ class Peregrin::Epub
|
|
582
599
|
end
|
583
600
|
|
584
601
|
|
585
|
-
def from_opf_root(
|
602
|
+
def from_opf_root(*args)
|
603
|
+
opf = @book.blueprint_for(:opf)
|
604
|
+
opf_root = File.dirname(opf.src)
|
586
605
|
if opf_root && !opf_root.empty? && opf_root != '.'
|
587
606
|
File.join(opf_root, *args)
|
588
607
|
else
|
@@ -596,6 +615,17 @@ class Peregrin::Epub
|
|
596
615
|
end
|
597
616
|
|
598
617
|
|
618
|
+
def uri_unescape(str)
|
619
|
+
@uri_parser ||= URI.const_defined?(:Parser) ? URI::Parser.new : URI
|
620
|
+
@uri_parser.unescape(str)
|
621
|
+
end
|
622
|
+
|
623
|
+
|
624
|
+
def epub_version
|
625
|
+
@epub_version ? @epub_version.to_f : 0
|
626
|
+
end
|
627
|
+
|
628
|
+
|
599
629
|
class ValidationError < ::RuntimeError
|
600
630
|
|
601
631
|
def initialize(path = nil)
|
data/lib/formats/zhook.rb
CHANGED
@@ -118,8 +118,6 @@ class Peregrin::Zhook
|
|
118
118
|
}
|
119
119
|
|
120
120
|
# Add rel links and convert to html string
|
121
|
-
first_path = bk.components.first.src
|
122
|
-
last_path = bk.components.last.src
|
123
121
|
boilerplate_rel_links <<
|
124
122
|
'<link rel="first" href="'+bk.components.first.src+'" />' +
|
125
123
|
'<link rel="last" href="'+bk.components.last.src+'" />'
|
@@ -361,6 +359,7 @@ class Peregrin::Zhook
|
|
361
359
|
|
362
360
|
|
363
361
|
def self.extract_properties_from_index(book)
|
362
|
+
book.add_format_property('source', 'Zhook')
|
364
363
|
doc = Nokogiri::HTML::Document.parse(
|
365
364
|
book.components.first.contents
|
366
365
|
)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Some ebook formats contain 'metadata' files that describe the contents of
|
2
|
+
# the ebook package. Since Peregrin use 'metadata' to refer to key-value pairs
|
3
|
+
# of information about the book, we call these files 'blueprints'.
|
4
|
+
#
|
5
|
+
class Peregrin::Blueprint < Peregrin::Resource
|
6
|
+
|
7
|
+
attr_accessor(:rel, :contents)
|
8
|
+
|
9
|
+
def initialize(rel, src, contents, media_type = 'application/xml', atts = {})
|
10
|
+
@rel = rel
|
11
|
+
@contents = contents
|
12
|
+
super(src, media_type, atts)
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def document
|
17
|
+
raise "Not an XML document: #{src}" unless xml?
|
18
|
+
@document ||= Nokogiri::XML::Document.parse(contents)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def xml?
|
23
|
+
media_type.match(/xml$/) ? true : false
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def marshal_dump
|
28
|
+
instance_variables.inject({}) { |acc, v|
|
29
|
+
v.to_s == '@document' ? acc : acc.update(v => instance_variable_get(v))
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def marshal_load(h)
|
35
|
+
h.each_pair { |k, v| instance_variable_set(k, v) }
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/lib/peregrin/book.rb
CHANGED
@@ -10,19 +10,21 @@ class Peregrin::Book
|
|
10
10
|
# children arrays.
|
11
11
|
attr_accessor :chapters
|
12
12
|
|
13
|
-
# An array of Properties.
|
13
|
+
# An array of Properties containg the ebook-supplied metadata.
|
14
14
|
attr_accessor :properties
|
15
15
|
|
16
|
+
# An array of Properties relating to the format of the ebook.
|
17
|
+
attr_accessor :format_properties
|
18
|
+
|
16
19
|
# An array of Resources.
|
17
20
|
attr_accessor :resources
|
18
21
|
|
22
|
+
# An array of Blueprints (ie, metadata files like the OPF or NCX).
|
23
|
+
attr_accessor :blueprints
|
24
|
+
|
19
25
|
# A Resource that is used for the book cover.
|
20
26
|
attr_accessor :cover
|
21
27
|
|
22
|
-
# The current version of document specifications
|
23
|
-
# Only used for Epub for now
|
24
|
-
attr_accessor :version
|
25
|
-
|
26
28
|
# A proc that copies a resource to the given destination.
|
27
29
|
attr_writer :read_resource_proc
|
28
30
|
|
@@ -31,12 +33,14 @@ class Peregrin::Book
|
|
31
33
|
@components = []
|
32
34
|
@chapters = []
|
33
35
|
@properties = []
|
36
|
+
@format_properties = []
|
34
37
|
@resources = []
|
38
|
+
@blueprints = []
|
35
39
|
end
|
36
40
|
|
37
41
|
|
38
42
|
def all_files
|
39
|
-
@components + @resources
|
43
|
+
@components + @resources + @blueprints
|
40
44
|
end
|
41
45
|
|
42
46
|
|
@@ -50,6 +54,16 @@ class Peregrin::Book
|
|
50
54
|
end
|
51
55
|
|
52
56
|
|
57
|
+
def add_blueprint(*args)
|
58
|
+
@blueprints.push(Peregrin::Blueprint.new(*args)).last
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def blueprint_for(rel)
|
63
|
+
@blueprints.detect { |bp| bp.rel == rel }
|
64
|
+
end
|
65
|
+
|
66
|
+
|
53
67
|
def add_chapter(*args)
|
54
68
|
@chapters.push(Peregrin::Chapter.new(*args)).last
|
55
69
|
end
|
@@ -67,6 +81,36 @@ class Peregrin::Book
|
|
67
81
|
end
|
68
82
|
|
69
83
|
|
84
|
+
def add_format_property(*args)
|
85
|
+
@format_properties.push(Peregrin::Property.new(*args)).last
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
def format_property_for(key)
|
90
|
+
key = key.to_s
|
91
|
+
prop = @format_properties.detect { |p| p.key == key }
|
92
|
+
prop ? prop.value : nil
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
# The current version of document specifications.
|
97
|
+
# Only used for EPUB for now.
|
98
|
+
#
|
99
|
+
def version
|
100
|
+
v = format_property_for('version')
|
101
|
+
v ? v.to_f : nil
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
# The page progression direction.
|
106
|
+
# Can be "ltr" (left to right), "rtl" (right to left) or nil (omitted).
|
107
|
+
# Only used for EPUB for now.
|
108
|
+
#
|
109
|
+
def direction
|
110
|
+
format_property_for('page-progression-direction')
|
111
|
+
end
|
112
|
+
|
113
|
+
|
70
114
|
def read_resource(resource_path)
|
71
115
|
@read_resource_proc.call(resource_path) if @read_resource_proc
|
72
116
|
end
|
data/lib/peregrin/version.rb
CHANGED
data/lib/peregrin.rb
CHANGED
data/test/formats/epub_test.rb
CHANGED
@@ -89,6 +89,7 @@ class Peregrin::Tests::EpubTest < Test::Unit::TestCase
|
|
89
89
|
assert_equal("cover.png", epub.to_book.cover.src)
|
90
90
|
end
|
91
91
|
|
92
|
+
|
92
93
|
def test_extracting_epub3_fixed_layout_properties
|
93
94
|
epub = Peregrin::Epub.read("test/fixtures/epubs/epub3_fixed_layout.epub")
|
94
95
|
book = epub.to_book
|
@@ -98,6 +99,20 @@ class Peregrin::Tests::EpubTest < Test::Unit::TestCase
|
|
98
99
|
assert_equal("both", book.property_for('rendition:spread'))
|
99
100
|
end
|
100
101
|
|
102
|
+
|
103
|
+
def test_extracting_epub3_fixed_layout_itemref
|
104
|
+
epub = Peregrin::Epub.read("test/fixtures/epubs/haruko-html-jpeg-20120524.epub")
|
105
|
+
book = epub.to_book
|
106
|
+
assert_equal(true, book.components[0].attributes["page-spread-left"])
|
107
|
+
assert_equal(nil, book.components[0].attributes["page-spread-right"])
|
108
|
+
assert_equal(nil, book.components[1].attributes["page-spread-left"])
|
109
|
+
assert_equal(true, book.components[1].attributes["page-spread-right"])
|
110
|
+
assert_equal(true, book.components.last.attributes["page-spread-left"])
|
111
|
+
assert_equal(nil, book.components.last.attributes["page-spread-right"])
|
112
|
+
assert_equal("reflowable", book.components.last.attributes["rendition:layout"])
|
113
|
+
end
|
114
|
+
|
115
|
+
|
101
116
|
def test_extracting_version
|
102
117
|
epub = Peregrin::Epub.read("test/fixtures/epubs/epub3_fixed_layout.epub")
|
103
118
|
assert_equal(3.0, epub.to_book.version)
|
@@ -106,6 +121,7 @@ class Peregrin::Tests::EpubTest < Test::Unit::TestCase
|
|
106
121
|
assert_equal(2.0, epub.to_book.version)
|
107
122
|
end
|
108
123
|
|
124
|
+
|
109
125
|
def test_extracting_chapters_from_ocx
|
110
126
|
epub = Peregrin::Epub.read("test/fixtures/epubs/strunk.epub")
|
111
127
|
assert_equal(9, epub.to_book.chapters.count)
|
@@ -117,6 +133,7 @@ class Peregrin::Tests::EpubTest < Test::Unit::TestCase
|
|
117
133
|
assert_equal(27, epub.to_book.chapters.last.position)
|
118
134
|
end
|
119
135
|
|
136
|
+
|
120
137
|
def test_extracting_chapters_from_nav
|
121
138
|
epub = Peregrin::Epub.read("test/fixtures/epubs/epub3_fixed_layout.epub")
|
122
139
|
assert_equal(3, epub.to_book.chapters.count)
|
@@ -128,6 +145,7 @@ class Peregrin::Tests::EpubTest < Test::Unit::TestCase
|
|
128
145
|
assert_equal(3, epub.to_book.chapters.last.position)
|
129
146
|
end
|
130
147
|
|
148
|
+
|
131
149
|
def test_extracting_nested_chapters_from_nav
|
132
150
|
epub = Peregrin::Epub.read("test/fixtures/epubs/epub3_nested_nav.epub")
|
133
151
|
assert_equal(11, epub.to_book.chapters.count)
|
@@ -175,6 +193,7 @@ class Peregrin::Tests::EpubTest < Test::Unit::TestCase
|
|
175
193
|
)
|
176
194
|
end
|
177
195
|
|
196
|
+
|
178
197
|
def test_read_epub_to_write_epub
|
179
198
|
epub = Peregrin::Epub.read("test/fixtures/epubs/strunk.epub")
|
180
199
|
epub.write("test/output/strunk_test2.epub")
|
@@ -185,6 +204,23 @@ class Peregrin::Tests::EpubTest < Test::Unit::TestCase
|
|
185
204
|
end
|
186
205
|
|
187
206
|
|
207
|
+
def test_extracting_direction
|
208
|
+
epub = Peregrin::Epub.read("test/fixtures/epubs/strunk.epub")
|
209
|
+
assert_equal(nil, epub.to_book.direction)
|
210
|
+
epub = Peregrin::Epub.read("test/fixtures/epubs/haruko-html-jpeg-20120524.epub")
|
211
|
+
assert_equal("rtl", epub.to_book.direction)
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
def test_extracting_blueprints
|
216
|
+
epub = Peregrin::Epub.read("test/fixtures/epubs/epub3_fixed_layout.epub")
|
217
|
+
assert_equal(
|
218
|
+
[:container, :nav, :ncx, :ocf, :opf],
|
219
|
+
epub.to_book.blueprints.collect(&:rel).sort
|
220
|
+
)
|
221
|
+
end
|
222
|
+
|
223
|
+
|
188
224
|
protected
|
189
225
|
|
190
226
|
def strunk_book
|
@@ -37,7 +37,10 @@ class Peregrin::Tests::ComponentizerTest < Test::Unit::TestCase
|
|
37
37
|
assert_equal(
|
38
38
|
whitewash(
|
39
39
|
"<!DOCTYPE html>" +
|
40
|
-
"<html><head
|
40
|
+
"<html><head>" +
|
41
|
+
"<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">" +
|
42
|
+
"<title>Components test 1</title>" +
|
43
|
+
"</head><body>" +
|
41
44
|
"<article><h2>B</h2></article>" +
|
42
45
|
"</body></html>"
|
43
46
|
),
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: peregrin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
4
|
+
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 1
|
7
|
+
- 2
|
8
8
|
- 1
|
9
|
-
|
10
|
-
version: 1.1.4
|
9
|
+
version: 1.2.1
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Joseph Pearson
|
@@ -15,17 +14,16 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2012-
|
17
|
+
date: 2012-09-29 00:00:00 +10:00
|
18
|
+
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: nokogiri
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
-
none: false
|
25
24
|
requirements:
|
26
25
|
- - ">="
|
27
26
|
- !ruby/object:Gem::Version
|
28
|
-
hash: 3
|
29
27
|
segments:
|
30
28
|
- 0
|
31
29
|
version: "0"
|
@@ -35,11 +33,9 @@ dependencies:
|
|
35
33
|
name: zipruby
|
36
34
|
prerelease: false
|
37
35
|
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
-
none: false
|
39
36
|
requirements:
|
40
37
|
- - ">="
|
41
38
|
- !ruby/object:Gem::Version
|
42
|
-
hash: 3
|
43
39
|
segments:
|
44
40
|
- 0
|
45
41
|
version: "0"
|
@@ -49,11 +45,9 @@ dependencies:
|
|
49
45
|
name: mime-types
|
50
46
|
prerelease: false
|
51
47
|
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
-
none: false
|
53
48
|
requirements:
|
54
49
|
- - ">="
|
55
50
|
- !ruby/object:Gem::Version
|
56
|
-
hash: 3
|
57
51
|
segments:
|
58
52
|
- 0
|
59
53
|
version: "0"
|
@@ -63,11 +57,9 @@ dependencies:
|
|
63
57
|
name: rake
|
64
58
|
prerelease: false
|
65
59
|
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
60
|
requirements:
|
68
61
|
- - ">="
|
69
62
|
- !ruby/object:Gem::Version
|
70
|
-
hash: 3
|
71
63
|
segments:
|
72
64
|
- 0
|
73
65
|
version: "0"
|
@@ -87,6 +79,7 @@ files:
|
|
87
79
|
- lib/formats/epub.rb
|
88
80
|
- lib/formats/ochook.rb
|
89
81
|
- lib/formats/zhook.rb
|
82
|
+
- lib/peregrin/blueprint.rb
|
90
83
|
- lib/peregrin/book.rb
|
91
84
|
- lib/peregrin/chapter.rb
|
92
85
|
- lib/peregrin/component.rb
|
@@ -106,6 +99,7 @@ files:
|
|
106
99
|
- test/utils/outliner_test.rb
|
107
100
|
- README.md
|
108
101
|
- MIT-LICENSE
|
102
|
+
has_rdoc: true
|
109
103
|
homepage: http://ochook.org/peregrin
|
110
104
|
licenses: []
|
111
105
|
|
@@ -118,27 +112,23 @@ rdoc_options:
|
|
118
112
|
require_paths:
|
119
113
|
- lib
|
120
114
|
required_ruby_version: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
115
|
requirements:
|
123
116
|
- - ">="
|
124
117
|
- !ruby/object:Gem::Version
|
125
|
-
hash: 3
|
126
118
|
segments:
|
127
119
|
- 0
|
128
120
|
version: "0"
|
129
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
-
none: false
|
131
122
|
requirements:
|
132
123
|
- - ">="
|
133
124
|
- !ruby/object:Gem::Version
|
134
|
-
hash: 3
|
135
125
|
segments:
|
136
126
|
- 0
|
137
127
|
version: "0"
|
138
128
|
requirements: []
|
139
129
|
|
140
130
|
rubyforge_project: nowarning
|
141
|
-
rubygems_version: 1.
|
131
|
+
rubygems_version: 1.3.6
|
142
132
|
signing_key:
|
143
133
|
specification_version: 3
|
144
134
|
summary: Peregrin - ebook conversion
|