peregrin 1.1.4 → 1.2.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 +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
|