lib/epub/publication/package/manifest.rb in epub-parser-0.1.5 vs lib/epub/publication/package/manifest.rb in epub-parser-0.1.6
- old
+ new
@@ -1,5 +1,6 @@
+require 'set'
require 'enumerabler'
require 'epub/constants'
require 'epub/parser/content_document'
module EPUB
@@ -29,11 +30,11 @@
def nav
navs.first
end
def cover_image
- items.selector {|i| i.properties.include? 'cover-image'}.first
+ items.selector(&:cover_image?).first
end
def each_item
@items.each_value do |item|
yield item
@@ -55,26 +56,31 @@
# @return [Manifest] Returns the value of manifest
# @!attribute [rw] id
# @return [String] Returns the value of id
# @!attribute [rw] href
# @return [Addressable::URI] Returns the value of href,
- # which is relative path from rootfile(OPF file)
+ # which is relative IRI from rootfile(OPF file)
# @!attribute [rw] media_type
# @return [String] Returns the value of media_type
# @!attribute [rw] properties
- # @return [Array<String>] Returns the value of properties
+ # @return [Set<String>] Returns the value of properties
# @!attribute [rw] media_overlay
# @return [String] Returns the value of media_overlay
# @!attribute [rw] fallback
# @return [Item] Returns the value of attribute fallback
attr_accessor :manifest,
- :id, :href, :media_type, :fallback, :properties, :media_overlay
+ :id, :href, :media_type, :fallback, :media_overlay
+ attr_reader :properties
def initialize
- @properties = []
+ @properties = Set.new
end
+ def properties=(props)
+ @properties = props.kind_of?(Set) ? props : Set.new(props)
+ end
+
# @todo Handle circular fallback chain
def fallback_chain
@fallback_chain ||= traverse_fallback_chain([])
end
@@ -96,10 +102,14 @@
def nav?
properties.include? 'nav'
end
+ def cover_image?
+ properties.include? 'cover-image'
+ end
+
# @todo Handle circular fallback chain
def use_fallback_chain(options = {})
supported = EPUB::MediaType::CORE
if ad = options[:supported]
supported = supported | (ad.respond_to?(:to_ary) ? ad : [ad])
@@ -111,11 +121,11 @@
return yield self if supported.include? media_type
if (bindings = manifest.package.bindings) && (binding_media_type = bindings[media_type])
return yield binding_media_type.handler
end
return fallback.use_fallback_chain(options) {|fb| yield fb} if fallback
- raise EPUB::MediaType::UnsupportedError
+ raise EPUB::MediaType::UnsupportedMediaType
end
def content_document
return nil unless %w[application/xhtml+xml image/svg+xml].include? media_type
@content_document ||= Parser::ContentDocument.new(self).parse
@@ -123,9 +133,29 @@
# @return [Package::Spine::Itemref]
# @return nil when no Itemref refers this Item
def itemref
manifest.package.spine.itemrefs.find {|itemref| itemref.idref == id}
+ end
+
+ # @param iri [Addressable::URI] relative iri
+ # @return [Item]
+ # @return [nil] when item not found
+ # @raise ArgumentError when +iri+ is not relative
+ # @raise ArgumentError when +iri+ starts with "/"(slash)
+ # @note Algorithm stolen form Rack::Utils#clean_path_info
+ def find_item_by_relative_iri(iri)
+ raise ArgumentError, "Not relative: #{iri.inspect}" unless iri.relative?
+ raise ArgumentError, "Start with slash: #{iri.inspect}" if iri.to_s.start_with? Addressable::URI::SLASH
+ target_href = href + iri
+ segments = target_href.to_s.split(Addressable::URI::SLASH)
+ clean_segments = []
+ segments.each do |segment|
+ next if segment.empty? || segment == '.'
+ segment == '..' ? clean_segments.pop : clean_segments << segment
+ end
+ target_iri = Addressable::URI.parse(clean_segments.join(Addressable::URI::SLASH))
+ manifest.items.find { |item| item.href == target_iri}
end
def inspect
"#<%{class}:%{object_id} %{manifest} %{attributes}>" % {
:class => self.class,