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,