gepub 0.6.4.6 → 0.6.5.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/gepub.gemspec +3 -3
- data/lib/gepub/book.rb +43 -15
- data/lib/gepub/builder.rb +163 -0
- data/lib/gepub/item.rb +58 -21
- data/lib/gepub/rubyzip_patch.rb +11 -0
- data/lib/gepub/version.rb +2 -1
- data/lib/gepub.rb +1 -1
- data/spec/builder_spec.rb +60 -0
- data/spec/gepub_spec.rb +7 -1
- metadata +13 -12
    
        data/gepub.gemspec
    CHANGED
    
    | @@ -18,7 +18,7 @@ Gem::Specification.new do |s| | |
| 18 18 | 
             
              s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         | 
| 19 19 | 
             
              s.require_paths = ["lib"]
         | 
| 20 20 |  | 
| 21 | 
            -
              s.add_development_dependency "rspec", " | 
| 22 | 
            -
              s.add_runtime_dependency "nokogiri", " | 
| 23 | 
            -
              s.add_runtime_dependency "rubyzip", " | 
| 21 | 
            +
              s.add_development_dependency "rspec", "~> 2"
         | 
| 22 | 
            +
              s.add_runtime_dependency "nokogiri", "~> 1.5.0"
         | 
| 23 | 
            +
              s.add_runtime_dependency "rubyzip", "= 0.9.6.1"
         | 
| 24 24 | 
             
            end
         | 
    
        data/lib/gepub/book.rb
    CHANGED
    
    | @@ -7,19 +7,23 @@ require 'fileutils' | |
| 7 7 | 
             
            # = GEPUB 
         | 
| 8 8 | 
             
            # Author:: KOJIMA Satoshi
         | 
| 9 9 | 
             
            # namespace for gepub library.
         | 
| 10 | 
            -
            # GEPUB::Book  | 
| 11 | 
            -
            # GEPUB:: | 
| 10 | 
            +
            # The core class is GEPUB::Book. It holds metadata and contents of EPUB file. metadata and contents can be accessed
         | 
| 11 | 
            +
            # through GEPUB::Meta and GEPUB::Item.
         | 
| 12 | 
            +
            # For generating EPUB file,  use GEPUB::Builder.
         | 
| 13 | 
            +
            # GEPUB::Item holds information and data  of resources like xhtml text, css, scripts, images, videos, etc.
         | 
| 12 14 | 
             
            # GEPUB::Meta holds metadata(title, creator, publisher, etc.) with its information (alternate script, display sequence, etc.)
         | 
| 13 15 |  | 
| 14 16 | 
             
            module GEPUB
         | 
| 15 | 
            -
              # Book is the  | 
| 17 | 
            +
              # Book is the class to hold data in EPUB files.
         | 
| 16 18 | 
             
              # 
         | 
| 17 | 
            -
              # It can generate and parse EPUB2/EPUB3 files. | 
| 18 | 
            -
              # | 
| 19 | 
            -
              #  | 
| 19 | 
            +
              # It can generate and parse EPUB2/EPUB3 files.
         | 
| 20 | 
            +
              #
         | 
| 21 | 
            +
              # If you want to generate a new EPUB file, consider using GEPUB::Builder instead
         | 
| 22 | 
            +
              # of using Book directly.
         | 
| 23 | 
            +
              # Builder is a wrapper class of Book specialized for generating EPUB.
         | 
| 20 24 | 
             
              # 
         | 
| 21 25 | 
             
              # 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  | 
| 26 | 
            +
              # them in Book#methods or in ri/rdoc documentation. Their descriptions are below.
         | 
| 23 27 | 
             
              #
         | 
| 24 28 | 
             
              # == \Package Attributes
         | 
| 25 29 | 
             
              # === Book#version (delegated to Package#version)
         | 
| @@ -133,7 +137,7 @@ module GEPUB | |
| 133 137 | 
             
                      end
         | 
| 134 138 | 
             
                    }
         | 
| 135 139 | 
             
                    book = Book.new(package.path)
         | 
| 136 | 
            -
                    book.instance_eval { @package = package; @ | 
| 140 | 
            +
                    book.instance_eval { @package = package; @optional_files = files }
         | 
| 137 141 | 
             
                    book
         | 
| 138 142 | 
             
                  }
         | 
| 139 143 | 
             
                end
         | 
| @@ -150,6 +154,22 @@ module GEPUB | |
| 150 154 | 
             
                  yield book if block_given?
         | 
| 151 155 | 
             
                end
         | 
| 152 156 |  | 
| 157 | 
            +
             | 
| 158 | 
            +
                # Get optional(not required in EPUB specification) files in the container.
         | 
| 159 | 
            +
                def optional_files
         | 
| 160 | 
            +
                  @optional_files || {}
         | 
| 161 | 
            +
                end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                # Add an optional file to the container
         | 
| 164 | 
            +
                def add_optional_file(path, io_or_filename)
         | 
| 165 | 
            +
                  io = io_or_filename
         | 
| 166 | 
            +
                  if io_or_filename.class == String
         | 
| 167 | 
            +
                    io = File.new(io_or_filename)
         | 
| 168 | 
            +
                  end
         | 
| 169 | 
            +
                  io.binmode
         | 
| 170 | 
            +
                  (@optional_files ||= {})[path] = io.read
         | 
| 171 | 
            +
                end
         | 
| 172 | 
            +
                
         | 
| 153 173 | 
             
                # add navigation text (which will appear on navigation document or table of contents) to an item.
         | 
| 154 174 | 
             
                # DEPRECATED: please use Item#toc_text or Item#toc_text_with_id, or Builder#heading
         | 
| 155 175 |  | 
| @@ -236,22 +256,30 @@ module GEPUB | |
| 236 256 | 
             
                end
         | 
| 237 257 |  | 
| 238 258 | 
             
                # write EPUB to stream specified by the argument.
         | 
| 239 | 
            -
                def write_to_epub_container(epub) | 
| 259 | 
            +
                def write_to_epub_container(epub)
         | 
| 240 260 | 
             
                  epub.put_next_entry('mimetype', '', '', Zip::ZipEntry::STORED)
         | 
| 241 261 | 
             
                  epub << "application/epub+zip"
         | 
| 242 | 
            -
                  epub.put_next_entry('META-INF/container.xml')
         | 
| 243 | 
            -
                  epub << container_xml.force_to_bin
         | 
| 244 262 |  | 
| 245 | 
            -
                   | 
| 246 | 
            -
                   | 
| 263 | 
            +
                  entries = {}
         | 
| 264 | 
            +
                  optional_files.each {
         | 
| 265 | 
            +
                    |k, content|
         | 
| 266 | 
            +
                    entries[k] = content
         | 
| 267 | 
            +
                  }
         | 
| 247 268 |  | 
| 269 | 
            +
                  entries['META-INF/container.xml'] = container_xml
         | 
| 270 | 
            +
                  entries[@package.path] = opf_xml
         | 
| 248 271 | 
             
                  @package.manifest.item_list.each {
         | 
| 249 272 | 
             
                    |k, item|
         | 
| 250 273 | 
             
                    if item.content != nil
         | 
| 251 | 
            -
                       | 
| 252 | 
            -
                       epub << item.content.force_to_bin
         | 
| 274 | 
            +
                      entries[@package.contents_prefix + item.href] = item.content
         | 
| 253 275 | 
             
                    end
         | 
| 254 276 | 
             
                  }
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                  entries.sort_by { |k,v| k }.each {
         | 
| 279 | 
            +
                    |k,v|
         | 
| 280 | 
            +
                    epub.put_next_entry(k)
         | 
| 281 | 
            +
                    epub << v.force_to_bin
         | 
| 282 | 
            +
                  }
         | 
| 255 283 | 
             
                end
         | 
| 256 284 |  | 
| 257 285 | 
             
                # generates and returns StringIO contains EPUB.
         | 
    
        data/lib/gepub/builder.rb
    CHANGED
    
    | @@ -1,4 +1,152 @@ | |
| 1 | 
            +
            # -*- coding: utf-8 -*-
         | 
| 1 2 | 
             
            module GEPUB
         | 
| 3 | 
            +
              #
         | 
| 4 | 
            +
              # Builder is a wrapper class of Book. It provides DSL to create new EPUB file.
         | 
| 5 | 
            +
              #
         | 
| 6 | 
            +
              # = Synopsys
         | 
| 7 | 
            +
              #      # -*- coding: utf-8 -*-
         | 
| 8 | 
            +
              #      # GEPUB::Builder example.
         | 
| 9 | 
            +
              #      require 'ruby gem'
         | 
| 10 | 
            +
              #      require 'gepub'
         | 
| 11 | 
            +
              #
         | 
| 12 | 
            +
              #      builder = GEPUB::Builder.new {
         | 
| 13 | 
            +
              #        # In the root block, you can define metadata.
         | 
| 14 | 
            +
              #        # You can define title, creator(s), contributor(s), publisher(s), date, unique_identifier, identifier, language.
         | 
| 15 | 
            +
              #        # Title can be specified with title, subtitle, collection, short_title, expanded_title, edition. 
         | 
| 16 | 
            +
              #        # You can also define description, format, relation, right, source, subject, type.
         | 
| 17 | 
            +
              #        # You can 'refine' last-defined metadata by refiner/attributes methods
         | 
| 18 | 
            +
              #        # Refiner methods contains : file_as, alt 
         | 
| 19 | 
            +
              #        
         | 
| 20 | 
            +
              #
         | 
| 21 | 
            +
              #        language 'ja'
         | 
| 22 | 
            +
              #
         | 
| 23 | 
            +
              #        title 'タイトル'
         | 
| 24 | 
            +
              #        alt 'en' => 'main title'
         | 
| 25 | 
            +
              #        file_as 'main title'
         | 
| 26 | 
            +
              #
         | 
| 27 | 
            +
              #        subtitle 'サブタイトル'  
         | 
| 28 | 
            +
              #        alt 'en' => 'subtitle'
         | 
| 29 | 
            +
              #
         | 
| 30 | 
            +
              #        # collection title and position in the collection:
         | 
| 31 | 
            +
              #        collection 'gepub sample book series', 2
         | 
| 32 | 
            +
              #
         | 
| 33 | 
            +
              #        #specifying creator
         | 
| 34 | 
            +
              #        creator 'author1','aut'
         | 
| 35 | 
            +
              #        alt 'ja' =>'日本語名' ,'en' =>'english name for author1'
         | 
| 36 | 
            +
              #        id 'the_first_author'
         | 
| 37 | 
            +
              #
         | 
| 38 | 
            +
              #        #specifying multiple creator
         | 
| 39 | 
            +
              #        creators 'author1', 'author2', ['editor1', 'edt']
         | 
| 40 | 
            +
              #
         | 
| 41 | 
            +
              #        contributor 'contributor'
         | 
| 42 | 
            +
              #        contributors 'contributor1', 'contributor2'
         | 
| 43 | 
            +
              #        # easy way to write alt {'ja' =>'日本語 for contributor1'}, {'ja' => '日本語 for contributor2'}
         | 
| 44 | 
            +
              #        alts 'ja' => ['日本語 for contributor1','日本語 for contributor2'] 
         | 
| 45 | 
            +
              #
         | 
| 46 | 
            +
              #        publisher '出版社'
         | 
| 47 | 
            +
              #        alt 'en' => 'ThePublisher'
         | 
| 48 | 
            +
              #        
         | 
| 49 | 
            +
              #        date '2012-02-21T00:00:00Z'
         | 
| 50 | 
            +
              #
         | 
| 51 | 
            +
              #        unique_identifier 'the_unique_id_in_uuid', 'uuid'
         | 
| 52 | 
            +
              #        identifier 'http://other_id','url'
         | 
| 53 | 
            +
              #        identifier 'http://another_id','url'
         | 
| 54 | 
            +
              #
         | 
| 55 | 
            +
              #        # in resources block, you can define resources by its relative path and datasource.
         | 
| 56 | 
            +
              #        # item creator methods are: files, file.
         | 
| 57 | 
            +
              #        resources(:workdir => '~/epub_source') {
         | 
| 58 | 
            +
              #          # Reads from file. in EPUB container, they are placed at the same path.
         | 
| 59 | 
            +
              #          file 'img/image0.jpg'
         | 
| 60 | 
            +
              #          files('img/image.jpg','img/image2.jpg')
         | 
| 61 | 
            +
              #          glob 'img/*.jpg' # means files(Dir.glob('img/*.jpg'))
         | 
| 62 | 
            +
              #
         | 
| 63 | 
            +
              #          # Reads from file. will be placed at path indicated by key.
         | 
| 64 | 
            +
              #          files('img/image.jpg' => 'imgage.jpg')
         | 
| 65 | 
            +
              #
         | 
| 66 | 
            +
              #          # Read from IO object.
         | 
| 67 | 
            +
              #          files('img/image.png' => supplied_io, 'img/image2.png' => supplied_io2)
         | 
| 68 | 
            +
              #
         | 
| 69 | 
            +
              #          # this will be end in error:
         | 
| 70 | 
            +
              #          # files(io1, io2)
         | 
| 71 | 
            +
              #
         | 
| 72 | 
            +
              #          # specify remote resource.
         | 
| 73 | 
            +
              #          # only referenced from the EPUB package.
         | 
| 74 | 
            +
              #          file 'http://example.com/video/remote_video.qt'
         | 
| 75 | 
            +
              #          media_type('video/quicktime')
         | 
| 76 | 
            +
              #
         | 
| 77 | 
            +
              #          # specify media type. 
         | 
| 78 | 
            +
              #          file 'resources/pv.mp4'
         | 
| 79 | 
            +
              #          media_type('video/mp4')
         | 
| 80 | 
            +
              #
         | 
| 81 | 
            +
              #          files('audio/voice1.mp4','audio/music1.mp4')
         | 
| 82 | 
            +
              #          media_type('audio/mp4')  # applied to all items in the line above.
         | 
| 83 | 
            +
              #
         | 
| 84 | 
            +
              #          # media_type to some file
         | 
| 85 | 
            +
              #          with_media_type('video/mp4') {
         | 
| 86 | 
            +
              #            file 'resources/v1.mp4'
         | 
| 87 | 
            +
              #            file 'resources/v2.mp4'
         | 
| 88 | 
            +
              #            file 'resources/v3.mp4'
         | 
| 89 | 
            +
              #          }
         | 
| 90 | 
            +
              #
         | 
| 91 | 
            +
              #          # with_media_type and media_type 
         | 
| 92 | 
            +
              #          with_media_type('video/mp4') {
         | 
| 93 | 
            +
              #            file 'resources/v1.mp4'
         | 
| 94 | 
            +
              #            file 'resources/v2.mp4'
         | 
| 95 | 
            +
              #            file 'resources/a4.mp4'
         | 
| 96 | 
            +
              #            media_type 'audio/mp4' # override with_media_type
         | 
| 97 | 
            +
              #          }
         | 
| 98 | 
            +
              #
         | 
| 99 | 
            +
              #          # Read from IO object: loop
         | 
| 100 | 
            +
              #          # supplied_IOs = { 'path' => io, 'path' => io... }
         | 
| 101 | 
            +
              #          supplied_IOs.each {
         | 
| 102 | 
            +
              #            |name, io|
         | 
| 103 | 
            +
              #            file name => io
         | 
| 104 | 
            +
              #          }
         | 
| 105 | 
            +
              #
         | 
| 106 | 
            +
              #          file 'css/default.css'
         | 
| 107 | 
            +
              #
         | 
| 108 | 
            +
              #          # indicate property.
         | 
| 109 | 
            +
              #          # this is cover image.
         | 
| 110 | 
            +
              #          cover_image 'img/cover.jpg'
         | 
| 111 | 
            +
              #
         | 
| 112 | 
            +
              #          # this is navigation document.
         | 
| 113 | 
            +
              #          nav 'text/toc.xhtml'
         | 
| 114 | 
            +
              #
         | 
| 115 | 
            +
              #          # ordered item. will be added to spine.
         | 
| 116 | 
            +
              #          ordered {
         | 
| 117 | 
            +
              #            # specify texts on table of contents for auto-generated toc.
         | 
| 118 | 
            +
              #            # (if you supply navigation document with method 'nav',  'heading' has no effect.)
         | 
| 119 | 
            +
              #            file('text/chap1.xhtml')
         | 
| 120 | 
            +
              #            heading 'Chapter 1'
         | 
| 121 | 
            +
              #            file 'text/chap2.xhtml'
         | 
| 122 | 
            +
              #            
         | 
| 123 | 
            +
              #            # fallback chain: style 1
         | 
| 124 | 
            +
              #            fallback_group {
         | 
| 125 | 
            +
              #              file 'chap3_docbook.xhtml'
         | 
| 126 | 
            +
              #              mimetype('application/docbook+xml')
         | 
| 127 | 
            +
              #              file 'chap3.xml'
         | 
| 128 | 
            +
              #              mimetype "application/z3986-auth+xml"
         | 
| 129 | 
            +
              #              file 'chap3.xhtml'
         | 
| 130 | 
            +
              #            }
         | 
| 131 | 
            +
              #
         | 
| 132 | 
            +
              #            # fallback chain: style 2
         | 
| 133 | 
            +
              #            fallback_chain_files 'chap4_docbook.xhtml', 'chap4.xml', 'chap4.xhtml'
         | 
| 134 | 
            +
              #            mimetype('application/docbook+xml','application/z3986-auth+xml' 'application/xhtml+xml')
         | 
| 135 | 
            +
              #
         | 
| 136 | 
            +
              #            # fallback chain: style 3 + with_mimetype
         | 
| 137 | 
            +
              #            with_mimetype('application/docbook+xml','application/z3986-auth+xml' 'application/xhtml+xml') {
         | 
| 138 | 
            +
              #              fallback_chain_files 'chap5_docbook.xhtml', 'chap5.xml', 'chap5.xhtml' 
         | 
| 139 | 
            +
              #              fallback_chain_files 'chap6_docbook.xhtml', 'chap6.xml', 'chap6.xhtml' 
         | 
| 140 | 
            +
              #              fallback_chain_files 'chap7_docbook.xhtml', 'chap7.xml', 'chap7.xhtml' 
         | 
| 141 | 
            +
              #            }
         | 
| 142 | 
            +
              #
         | 
| 143 | 
            +
              #          }
         | 
| 144 | 
            +
              #        }
         | 
| 145 | 
            +
              #      }
         | 
| 146 | 
            +
              #
         | 
| 147 | 
            +
              #      builder.generate_epub('sample.epub')
         | 
| 148 | 
            +
             | 
| 149 | 
            +
             | 
| 2 150 | 
             
              class Builder
         | 
| 3 151 | 
             
                include BuilderMixin
         | 
| 4 152 | 
             
                class MetaItem
         | 
| @@ -112,6 +260,21 @@ module GEPUB | |
| 112 260 | 
             
                  MetaItem.new(@book.add_contributor(val, nil, role))
         | 
| 113 261 | 
             
                end
         | 
| 114 262 |  | 
| 263 | 
            +
                # set optional file.
         | 
| 264 | 
            +
                # val should be String or Hash.
         | 
| 265 | 
            +
                # if val is String, file is read from the File specified by string and stored in EPUB to the path specified by string.
         | 
| 266 | 
            +
                # if val is Hash, file is read from the value and stored in EPUB to the path specified by the key.
         | 
| 267 | 
            +
                def optional_file(val)
         | 
| 268 | 
            +
                  path = val
         | 
| 269 | 
            +
                  io = val if String === val
         | 
| 270 | 
            +
                  if Hash === val
         | 
| 271 | 
            +
                    raise 'argument to optional_file should be length 1' if val.size != 1
         | 
| 272 | 
            +
                    path = val.first[0]
         | 
| 273 | 
            +
                    io = val.first[1]
         | 
| 274 | 
            +
                  end
         | 
| 275 | 
            +
                  @book.add_optional_file(path, io)
         | 
| 276 | 
            +
                end
         | 
| 277 | 
            +
                
         | 
| 115 278 | 
             
                def generate_epub(path_to_epub)
         | 
| 116 279 | 
             
                  @book.generate_epub(path_to_epub)
         | 
| 117 280 | 
             
                end
         | 
    
        data/lib/gepub/item.rb
    CHANGED
    
    | @@ -1,4 +1,10 @@ | |
| 1 1 | 
             
            module GEPUB
         | 
| 2 | 
            +
              #
         | 
| 3 | 
            +
              # an Object to hold metadata and content of item in manifest.
         | 
| 4 | 
            +
              #
         | 
| 5 | 
            +
              # following methods are created dynamically.
         | 
| 6 | 
            +
              # #id, #id=, #set_id, #href, #href=, #set_href, #media_type, #media_type=, #set_media_type,
         | 
| 7 | 
            +
              # #fallback, #fallback=, #set_fallback, #media_overlay, #media_overlay=, #set_media_overlay
         | 
| 2 8 | 
             
              class Item
         | 
| 3 9 | 
             
                attr_accessor :content
         | 
| 4 10 | 
             
                def self.create(parent, attributes = {})
         | 
| @@ -6,6 +12,12 @@ module GEPUB | |
| 6 12 | 
             
                           attributes.reject { |k,v| ['id','href','media-type'].member?(k) })
         | 
| 7 13 | 
             
                end
         | 
| 8 14 |  | 
| 15 | 
            +
                #
         | 
| 16 | 
            +
                # create Item.
         | 
| 17 | 
            +
                # 
         | 
| 18 | 
            +
                # if mediatype is not specified, it will be guessed from extension name.
         | 
| 19 | 
            +
                # Item can't guess media type for videos and  audios, so you should specify one.
         | 
| 20 | 
            +
                # 
         | 
| 9 21 | 
             
                def initialize(itemid, itemhref, itemmediatype = nil, parent = nil, attributes = {})
         | 
| 10 22 | 
             
                  if attributes['properties'].class == String
         | 
| 11 23 | 
             
                    attributes['properties'] = attributes['properties'].split(' ')
         | 
| @@ -14,7 +26,6 @@ module GEPUB | |
| 14 26 | 
             
                  @attributes['media-type'] =  guess_mediatype if media_type.nil?
         | 
| 15 27 | 
             
                  @parent = parent
         | 
| 16 28 | 
             
                  @parent.register_item(self) unless @parent.nil?
         | 
| 17 | 
            -
                  @content_callback = []
         | 
| 18 29 | 
             
                  self
         | 
| 19 30 | 
             
                end
         | 
| 20 31 |  | 
| @@ -25,14 +36,16 @@ module GEPUB | |
| 25 36 | 
             
                  define_method(methodbase) { @attributes[name] }
         | 
| 26 37 | 
             
                }
         | 
| 27 38 |  | 
| 39 | 
            +
                # get item's id
         | 
| 28 40 | 
             
                def itemid
         | 
| 29 41 | 
             
                  id
         | 
| 30 42 | 
             
                end
         | 
| 31 43 |  | 
| 44 | 
            +
                # get mediatype of the item.
         | 
| 32 45 | 
             
                def mediatype
         | 
| 33 46 | 
             
                  media_type
         | 
| 34 47 | 
             
                end
         | 
| 35 | 
            -
             | 
| 48 | 
            +
             | 
| 36 49 | 
             
                def [](x)
         | 
| 37 50 | 
             
                  @attributes[x]
         | 
| 38 51 | 
             
                end
         | 
| @@ -40,28 +53,61 @@ module GEPUB | |
| 40 53 | 
             
                def []=(x,y)
         | 
| 41 54 | 
             
                  @attributes[x] = y
         | 
| 42 55 | 
             
                end
         | 
| 43 | 
            -
             | 
| 56 | 
            +
             | 
| 57 | 
            +
                # add value to properties attribute.
         | 
| 44 58 | 
             
                def add_property(property)
         | 
| 45 59 | 
             
                  (@attributes['properties'] ||=[]) << property
         | 
| 46 60 | 
             
                  self
         | 
| 47 61 | 
             
                end
         | 
| 48 62 |  | 
| 63 | 
            +
                # set 'cover-image' property to the Item.
         | 
| 64 | 
            +
                # On generating EPUB, EPUB2-style cover image meta item will be added.
         | 
| 49 65 | 
             
                def cover_image
         | 
| 50 66 | 
             
                  add_property('cover-image')
         | 
| 51 67 | 
             
                end
         | 
| 52 68 |  | 
| 69 | 
            +
                # set 'nav' property to the Item.
         | 
| 53 70 | 
             
                def nav
         | 
| 54 71 | 
             
                  add_property('nav')
         | 
| 55 72 | 
             
                end
         | 
| 56 73 |  | 
| 57 | 
            -
                 | 
| 58 | 
            -
             | 
| 74 | 
            +
                # guess and set content property from contents.
         | 
| 75 | 
            +
                def guess_content_property
         | 
| 76 | 
            +
                  if File.extname(self.href) =~ /.x?html/
         | 
| 77 | 
            +
                    @attributes['properties'] = (@attributes['properties'] || []).reject {
         | 
| 78 | 
            +
                      |x| x == 'svg' || x == 'mathml' || x == 'switch' || x == 'remote-resources'
         | 
| 79 | 
            +
                    }
         | 
| 80 | 
            +
                    parsed = Nokogiri::XML::Document.parse(@content)
         | 
| 81 | 
            +
                    ns_prefix =  parsed.namespaces.invert['http://www.w3.org/1999/xhtml']
         | 
| 82 | 
            +
                    if ns_prefix.nil?
         | 
| 83 | 
            +
                      prefix = ''
         | 
| 84 | 
            +
                    else
         | 
| 85 | 
            +
                      prefix = "#{ns_prefix}:"
         | 
| 86 | 
            +
                    end
         | 
| 87 | 
            +
                    videos = parsed.xpath("//#{prefix}video[starts-with(@src,'http')]")
         | 
| 88 | 
            +
                    audios = parsed.xpath("//#{prefix}audio[starts-with(@src,'http')]")
         | 
| 89 | 
            +
                    if videos.size > 0 || audios.size > 0
         | 
| 90 | 
            +
                      self.add_property('remote-resources')
         | 
| 91 | 
            +
                    end
         | 
| 92 | 
            +
                    if parsed.xpath("//p:math", { 'p' => 'http://www.w3.org/1998/Math/MathML' }).size > 0
         | 
| 93 | 
            +
                      self.add_property('mathml')
         | 
| 94 | 
            +
                    end
         | 
| 95 | 
            +
                    if parsed.xpath("//s:svg", { 's' => 'http://www.w3.org/2000/svg' }).size > 0
         | 
| 96 | 
            +
                      self.add_property('svg')
         | 
| 97 | 
            +
                    end
         | 
| 98 | 
            +
                    if parsed.xpath("//epub:switch", { 'epub' => 'http://www.idpf.org/2007/ops' }).size > 0
         | 
| 99 | 
            +
                      self.add_property('switch')
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
                  end
         | 
| 59 102 | 
             
                end
         | 
| 60 103 |  | 
| 61 | 
            -
                 | 
| 62 | 
            -
             | 
| 104 | 
            +
                # add content data to the item.
         | 
| 105 | 
            +
                def add_raw_content(data)
         | 
| 106 | 
            +
                  @content = data
         | 
| 107 | 
            +
                  guess_content_property
         | 
| 63 108 | 
             
                end
         | 
| 64 109 |  | 
| 110 | 
            +
                # add content form io or file to the item
         | 
| 65 111 | 
             
                def add_content(io_or_filename)
         | 
| 66 112 | 
             
                  io = io_or_filename
         | 
| 67 113 | 
             
                  if io_or_filename.class == String
         | 
| @@ -69,23 +115,11 @@ module GEPUB | |
| 69 115 | 
             
                  end
         | 
| 70 116 | 
             
                  io.binmode
         | 
| 71 117 | 
             
                  @content = io.read
         | 
| 72 | 
            -
                   | 
| 73 | 
            -
                    parsed = Nokogiri::XML::Document.parse(@content)
         | 
| 74 | 
            -
                    ns_prefix =  parsed.namespaces.invert['http://www.w3.org/1999/xhtml']
         | 
| 75 | 
            -
                      if ns_prefix.nil?
         | 
| 76 | 
            -
                        prefix = ''
         | 
| 77 | 
            -
                      else
         | 
| 78 | 
            -
                        prefix = "#{ns_prefix}:"
         | 
| 79 | 
            -
                      end
         | 
| 80 | 
            -
                      videos = parsed.xpath("//#{prefix}video[starts-with(@src,'http')]")
         | 
| 81 | 
            -
                      audios = parsed.xpath("//#{prefix}audio[starts-with(@src,'http')]")
         | 
| 82 | 
            -
                      if videos.size > 0 || audios.size > 0
         | 
| 83 | 
            -
                        self.add_property('remote-resources')
         | 
| 84 | 
            -
                      end
         | 
| 85 | 
            -
                  end
         | 
| 118 | 
            +
                  guess_content_property
         | 
| 86 119 | 
             
                  self
         | 
| 87 120 | 
             
                end
         | 
| 88 121 |  | 
| 122 | 
            +
                # generate xml to supplied Nokogiri builder.
         | 
| 89 123 | 
             
                def to_xml(builder, opf_version = '3.0')
         | 
| 90 124 | 
             
                  attr = @attributes.dup
         | 
| 91 125 | 
             
                  if opf_version.to_f < 3.0
         | 
| @@ -93,6 +127,9 @@ module GEPUB | |
| 93 127 | 
             
                  end
         | 
| 94 128 | 
             
                  if !attr['properties'].nil?
         | 
| 95 129 | 
             
                    attr['properties'] = attr['properties'].join(' ')
         | 
| 130 | 
            +
                    if attr['properties'].size == 0
         | 
| 131 | 
            +
                      attr.delete 'properties'
         | 
| 132 | 
            +
                    end
         | 
| 96 133 | 
             
                  end
         | 
| 97 134 | 
             
                  builder.item(attr)
         | 
| 98 135 | 
             
                end
         | 
    
        data/lib/gepub/version.rb
    CHANGED
    
    
    
        data/lib/gepub.rb
    CHANGED
    
    
    
        data/spec/builder_spec.rb
    CHANGED
    
    | @@ -437,5 +437,65 @@ describe GEPUB::Builder do | |
| 437 437 | 
             
                  }
         | 
| 438 438 | 
             
                  # this should not raise 'No such file or directory'
         | 
| 439 439 | 
             
                end
         | 
| 440 | 
            +
             | 
| 441 | 
            +
                it 'should handle mathml' do
         | 
| 442 | 
            +
                  builder = GEPUB::Builder.new {
         | 
| 443 | 
            +
                    unique_identifier 'uid'
         | 
| 444 | 
            +
                    resources {
         | 
| 445 | 
            +
                      file 'mathml.xhtml' => StringIO.new('<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"><head></head><body><div><p><math xmlns="http://www.w3.org/1998/Math/MathML"></math></p></div></body></html>')
         | 
| 446 | 
            +
                    }
         | 
| 447 | 
            +
                  }
         | 
| 448 | 
            +
                  builder.instance_eval {
         | 
| 449 | 
            +
                    @book.item_by_href('mathml.xhtml').properties[0].should == 'mathml'
         | 
| 450 | 
            +
                  }
         | 
| 451 | 
            +
                end
         | 
| 452 | 
            +
             | 
| 453 | 
            +
                it 'should handle svg' do
         | 
| 454 | 
            +
                  builder = GEPUB::Builder.new {
         | 
| 455 | 
            +
                    unique_identifier 'uid'
         | 
| 456 | 
            +
                    resources {
         | 
| 457 | 
            +
                      file 'svg.xhtml' => StringIO.new('<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"><head></head><body><div><p><svg xmlns="http://www.w3.org/2000/svg"></svg></p></div></body></html>')
         | 
| 458 | 
            +
                    }
         | 
| 459 | 
            +
                  }
         | 
| 460 | 
            +
                  builder.instance_eval {
         | 
| 461 | 
            +
                    @book.item_by_href('svg.xhtml').properties[0].should == 'svg'
         | 
| 462 | 
            +
                  }
         | 
| 463 | 
            +
                end
         | 
| 464 | 
            +
             | 
| 465 | 
            +
                it 'should handle epub:switch' do
         | 
| 466 | 
            +
                  builder = GEPUB::Builder.new {
         | 
| 467 | 
            +
                    unique_identifier 'uid'
         | 
| 468 | 
            +
                    resources {
         | 
| 469 | 
            +
                      file 'switch.xhtml' => StringIO.new('<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"><head></head><body><div><p>
         | 
| 470 | 
            +
            <epub:switch>
         | 
| 471 | 
            +
               <epub:case required-namespace="http://www.xml-cml.org/schema">
         | 
| 472 | 
            +
                  <cml xmlns="http://www.xml-cml.org/schema">
         | 
| 473 | 
            +
                     <molecule id="sulfuric-acid">
         | 
| 474 | 
            +
                        <formula id="f1" concise="H 2 S 1 O 4"/>
         | 
| 475 | 
            +
                     </molecule>
         | 
| 476 | 
            +
                  </cml>
         | 
| 477 | 
            +
               </epub:case>
         | 
| 478 | 
            +
               <epub:default>
         | 
| 479 | 
            +
                  <p>H<sub>2</sub>SO<sub>4</sub></p>
         | 
| 480 | 
            +
               </epub:default>
         | 
| 481 | 
            +
            </epub:switch></p></div></body></html>')
         | 
| 482 | 
            +
                    }
         | 
| 483 | 
            +
                  }
         | 
| 484 | 
            +
                  builder.instance_eval {
         | 
| 485 | 
            +
                    @book.item_by_href('switch.xhtml').properties[0].should == 'switch'
         | 
| 486 | 
            +
                  }
         | 
| 487 | 
            +
                end
         | 
| 488 | 
            +
             | 
| 489 | 
            +
                it 'should handle optional file' do
         | 
| 490 | 
            +
                  builder = GEPUB::Builder.new {
         | 
| 491 | 
            +
                    optional_file 'META-INF/test.xml' => StringIO.new('<test></test>')
         | 
| 492 | 
            +
                  }
         | 
| 493 | 
            +
                  builder.instance_eval {
         | 
| 494 | 
            +
                    @book.optional_files.size.should == 1
         | 
| 495 | 
            +
                  }
         | 
| 496 | 
            +
                  builder.instance_eval {      
         | 
| 497 | 
            +
                    @book.optional_files['META-INF/test.xml']
         | 
| 498 | 
            +
                  }.should_not be_nil
         | 
| 499 | 
            +
                end
         | 
| 440 500 | 
             
              end
         | 
| 441 501 | 
             
            end
         | 
    
        data/spec/gepub_spec.rb
    CHANGED
    
    | @@ -189,6 +189,12 @@ EOF | |
| 189 189 | 
             
                jar = File.join(File.dirname(__FILE__), 'fixtures/epubcheck-3.0b4/epubcheck-3.0b4.jar')
         | 
| 190 190 | 
             
                system 'java', '-jar', jar, epubname
         | 
| 191 191 | 
             
              end
         | 
| 192 | 
            -
             | 
| 192 | 
            +
              it 'should generate epub with extra file' do
         | 
| 193 | 
            +
                epubname = File.join(File.dirname(__FILE__), 'testepub3.epub')
         | 
| 194 | 
            +
                @book.add_optional_file('META-INF/foobar.xml', StringIO.new('<foo></foo>'))
         | 
| 195 | 
            +
                @book.generate_epub(epubname)
         | 
| 196 | 
            +
                jar = File.join(File.dirname(__FILE__), 'fixtures/epubcheck-3.0b4/epubcheck-3.0b4.jar')
         | 
| 197 | 
            +
                system 'java', '-jar', jar, epubname
         | 
| 198 | 
            +
              end
         | 
| 193 199 |  | 
| 194 200 | 
             
            end
         | 
    
        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 | 
            +
              version: 0.6.5.1
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -9,41 +9,41 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2012-03- | 
| 12 | 
            +
            date: 2012-03-13 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: rspec
         | 
| 16 | 
            -
              requirement: & | 
| 16 | 
            +
              requirement: &70119775057080 !ruby/object:Gem::Requirement
         | 
| 17 17 | 
             
                none: false
         | 
| 18 18 | 
             
                requirements:
         | 
| 19 | 
            -
                - -  | 
| 19 | 
            +
                - - ~>
         | 
| 20 20 | 
             
                  - !ruby/object:Gem::Version
         | 
| 21 21 | 
             
                    version: '2'
         | 
| 22 22 | 
             
              type: :development
         | 
| 23 23 | 
             
              prerelease: false
         | 
| 24 | 
            -
              version_requirements: * | 
| 24 | 
            +
              version_requirements: *70119775057080
         | 
| 25 25 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 26 26 | 
             
              name: nokogiri
         | 
| 27 | 
            -
              requirement: & | 
| 27 | 
            +
              requirement: &70119775056340 !ruby/object:Gem::Requirement
         | 
| 28 28 | 
             
                none: false
         | 
| 29 29 | 
             
                requirements:
         | 
| 30 | 
            -
                - -  | 
| 30 | 
            +
                - - ~>
         | 
| 31 31 | 
             
                  - !ruby/object:Gem::Version
         | 
| 32 32 | 
             
                    version: 1.5.0
         | 
| 33 33 | 
             
              type: :runtime
         | 
| 34 34 | 
             
              prerelease: false
         | 
| 35 | 
            -
              version_requirements: * | 
| 35 | 
            +
              version_requirements: *70119775056340
         | 
| 36 36 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 37 37 | 
             
              name: rubyzip
         | 
| 38 | 
            -
              requirement: & | 
| 38 | 
            +
              requirement: &70119775055860 !ruby/object:Gem::Requirement
         | 
| 39 39 | 
             
                none: false
         | 
| 40 40 | 
             
                requirements:
         | 
| 41 | 
            -
                - -  | 
| 41 | 
            +
                - - =
         | 
| 42 42 | 
             
                  - !ruby/object:Gem::Version
         | 
| 43 | 
            -
                    version: 0.9.6
         | 
| 43 | 
            +
                    version: 0.9.6.1
         | 
| 44 44 | 
             
              type: :runtime
         | 
| 45 45 | 
             
              prerelease: false
         | 
| 46 | 
            -
              version_requirements: * | 
| 46 | 
            +
              version_requirements: *70119775055860
         | 
| 47 47 | 
             
            description: gepub is a generic EPUB parser/generator. Generates and parse EPUB2 and
         | 
| 48 48 | 
             
              EPUB3
         | 
| 49 49 | 
             
            email:
         | 
| @@ -76,6 +76,7 @@ files: | |
| 76 76 | 
             
            - lib/gepub/metadata.rb
         | 
| 77 77 | 
             
            - lib/gepub/package.rb
         | 
| 78 78 | 
             
            - lib/gepub/resource_builder.rb
         | 
| 79 | 
            +
            - lib/gepub/rubyzip_patch.rb
         | 
| 79 80 | 
             
            - lib/gepub/spine.rb
         | 
| 80 81 | 
             
            - lib/gepub/version.rb
         | 
| 81 82 | 
             
            - lib/gepub/xml_util.rb
         |