gepub 0.6.2 → 0.6.3

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/.gitignore CHANGED
@@ -21,7 +21,7 @@ pkg
21
21
  ## PROJECT::SPECIFIC
22
22
  testepub.epub
23
23
  testepub2.epub
24
- example_test.epub
24
+ example_test*.epub
25
25
 
26
26
  ## BUNDLER
27
27
  Gemfile.lock
data/README.md CHANGED
@@ -9,15 +9,48 @@ a generic EPUB parser/generator library.
9
9
  ## FEATURES/PROBLEMS:
10
10
 
11
11
  * GEPUB::Book provides functionality to create EPUB file, and parsing EPUB file
12
- * from version 0.6, GEPUB::Book will be able handle almost every metadata in EPUB2/EPUB3.
13
- .. but is still beta version. Please inform me when you find bugs.
14
- * Will provide easy to generate EPUB class, like Nokogiri::XML::Generator.
12
+ * Handle every metadata in EPUB2/EPUB3.
13
+ * Soon, I will provide easy to generate EPUB class, like Nokogiri::XML::Generator.
15
14
 
16
15
  * See [issues](https://github.com/skoji/gepub/issues/) for known problems.
17
16
 
18
17
  ## SYNOPSIS:
19
18
 
20
- see examples directory.
19
+ ### Builder Example
20
+
21
+ require 'rubygem'
22
+ require 'gepub'
23
+ workdir = 'epub/example/'
24
+ builder = GEPUB::Builder.new {
25
+ unique_identifier 'http:/example.jp/bookid_in_url', 'BookID', 'URL'
26
+ language 'en'
27
+
28
+ title 'GEPUB Sample Book'
29
+ subtitle 'This book is just a sample'
30
+ alt 'ja' => 'これはあくまでサンプルです'
31
+
32
+ creator 'KOJIMA Satoshi'
33
+ alt 'ja' => '小嶋智'
34
+
35
+ contributors 'Denshobu', 'Asagaya Densho', 'Shonan Densho Teidan', 'eMagazine Torutaru'
36
+
37
+ date '2012-02-29T00:00:00Z'
38
+
39
+ resources(:workdir => workdir) {
40
+ cover_image 'img/image1.jpg' => 'image1.jpg'
41
+ ordered {
42
+ file 'text/chap1.xhtml'
43
+ heading 'Chapter 1'
44
+ file 'text/chap1-1.xhtml'
45
+ file 'text/chap2.html'
46
+ heading 'Chapter 2'
47
+ }
48
+ }
49
+ }
50
+ epubname = File.join(File.dirname(__FILE__), 'example_test_with_builder.epub')
51
+ builder.generate_epub(epubname)
52
+
53
+ [examples](https://github.com/skoji/gepub/tree/master/examples/)
21
54
 
22
55
  ## INSTALL:
23
56
 
@@ -0,0 +1,32 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'rubygem'
3
+ require 'gepub'
4
+ workdir = 'epub/example/'
5
+ builder = GEPUB::Builder.new {
6
+ unique_identifier 'http:/example.jp/bookid_in_url', 'BookID', 'URL'
7
+ language 'en'
8
+
9
+ title 'GEPUB Sample Book'
10
+ subtitle 'This book is just a sample'
11
+ alt 'ja' => 'これはあくまでサンプルです'
12
+
13
+ creator 'KOJIMA Satoshi'
14
+ alt 'ja' => '小嶋智'
15
+
16
+ contributors 'Denshobu', 'Asagaya Densho', 'Shonan Densho Teidan', 'eMagazine Torutaru'
17
+
18
+ date '2012-02-29T00:00:00Z'
19
+
20
+ resources(:workdir => workdir) {
21
+ cover_image 'img/image1.jpg' => 'image1.jpg'
22
+ ordered {
23
+ file 'text/chap1.xhtml'
24
+ heading 'Chapter 1'
25
+ file 'text/chap1-1.xhtml'
26
+ file 'text/chap2.html'
27
+ heading 'Chapter 2'
28
+ }
29
+ }
30
+ }
31
+ epubname = File.join(File.dirname(__FILE__), 'example_test_with_builder.epub')
32
+ builder.generate_epub(epubname)
data/gepub.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
8
8
  s.authors = ["KOJIMA Satoshi"]
9
9
  s.email = ["skoji@mac.com"]
10
10
  s.homepage = %q{http://github.com/skoji/gepub}
11
- s.summary = %q{a generic EPUB parser/generator.}
12
- s.description = %q{gepub is a EPUB parser/generator. Generates EPUB2 opf. will support EPUB3 parse/generation}
11
+ s.summary = %q{a generic EPUB library for Ruby.}
12
+ s.description = %q{gepub is a generic EPUB parser/generator. Generates and parse EPUB2 and EPUB3}
13
13
 
14
14
  s.rubyforge_project = "gepub"
15
15
 
data/lib/gepub/book.rb CHANGED
@@ -4,7 +4,6 @@ require 'nokogiri'
4
4
  require 'zip/zip'
5
5
  require 'fileutils'
6
6
 
7
-
8
7
  module GEPUB
9
8
  class Book
10
9
  MIMETYPE='mimetype'
@@ -81,20 +80,25 @@ module GEPUB
81
80
  @toc.push({ :item => item, :text => text, :id => id})
82
81
  end
83
82
 
84
- def add_item(href, io = nil, id = nil, attributes = {})
85
- item = @package.add_item(href,io,id,attributes)
83
+ def add_item(href, io_or_filename = nil, id = nil, attributes = {})
84
+ item = @package.add_item(href,io_or_filename,id,attributes)
86
85
  toc = @toc
87
86
  (class << item;self;end).send(:define_method, :toc_text,
88
87
  Proc.new { |text|
89
88
  toc.push(:item => item, :text => text, :id => nil)
90
89
  item
91
90
  })
91
+ (class << item;self;end).send(:define_method, :toc_text_with_id,
92
+ Proc.new { |text, id|
93
+ toc.push(:item => item, :text => text, :id => id)
94
+ item
95
+ })
92
96
  yield item if block_given?
93
97
  item
94
98
  end
95
99
 
96
- def add_ordered_item(href, io = nil, id = nil, attributes = {})
97
- item = @package.add_ordered_item(href,io,id,attributes)
100
+ def add_ordered_item(href, io_or_filename = nil, id = nil, attributes = {})
101
+ item = @package.add_ordered_item(href,io_or_filename,id,attributes)
98
102
  toc = @toc
99
103
  (class << item;self;end).send(:define_method, :toc_text,
100
104
  Proc.new { |text|
@@ -182,8 +186,9 @@ EOF
182
186
  doc.ol {
183
187
  @toc.each {
184
188
  |x|
189
+ id = x[:id].nil? ? "" : "##{x[:id]}"
185
190
  doc.li {
186
- doc.a({'href' => x[:item].href} ,x[:text])
191
+ doc.a({'href' => x[:item].href + id} ,x[:text])
187
192
  }
188
193
  }
189
194
  }
@@ -0,0 +1,127 @@
1
+ module GEPUB
2
+ class Builder
3
+ include BuilderMixin
4
+ class MetaItem
5
+ def initialize(item)
6
+ @item = item
7
+ end
8
+
9
+ def apply_one_to_multi
10
+ false
11
+ end
12
+
13
+ def alt(alternates = {})
14
+ @item.add_alternates(alternates)
15
+ end
16
+
17
+ def file_as(name)
18
+ @item.set_file_as(name)
19
+ end
20
+
21
+ def seq(num)
22
+ @item.set_display_seq(num)
23
+ end
24
+
25
+ def group_position(num)
26
+ @item.set_group_position(num)
27
+ end
28
+
29
+ def id(val)
30
+ @item['id'] = val
31
+ end
32
+ end
33
+
34
+ def initialize(attributes = {}, &block)
35
+ @last_defined_item = nil
36
+ @book = Book.new
37
+ instance_eval &block
38
+ # TODO check @book's consistency
39
+ true
40
+ end
41
+
42
+ # define base methods.
43
+ GEPUB::Metadata::CONTENT_NODE_LIST.each {
44
+ |name|
45
+ define_method(name) { |val| @last_defined_item = MetaItem.new(@book.send("add_#{name}".to_sym, val, nil)) }
46
+ }
47
+
48
+ GEPUB::TITLE_TYPE::TYPES.each {
49
+ |type|
50
+ case type
51
+ when 'main'
52
+ methodname = 'title'
53
+ when 'short'
54
+ methodname = 'short_title'
55
+ when 'expanded'
56
+ methodname = 'expandend_title'
57
+ else
58
+ methodname = type
59
+ end
60
+ define_method(methodname) { |val| @last_defined_item = MetaItem.new(@book.add_title(val, nil, type)) }
61
+ }
62
+
63
+ def collection(val, count = 1)
64
+ @last_defined_item =
65
+ MetaItem.new(@book.add_title(val, nil, GEPUB::TITLE_TYPE::COLLECTION).set_group_position(count.to_s))
66
+ end
67
+
68
+ def creator(val, role = 'aut')
69
+ MetaItem.new(@book.add_creator(val, nil, role))
70
+ end
71
+
72
+ def creators(*vals)
73
+ @last_defined_item = vals.map {
74
+ |v|
75
+ name = v
76
+ role = ''
77
+ name,role = v[0], v[1] if Array === name
78
+ MetaItem.new(@book.add_creator(name, nil, role))
79
+ }
80
+ end
81
+
82
+ def contributors(*vals)
83
+ @last_defined_item = vals.map {
84
+ |v|
85
+ name = v
86
+ role = nil
87
+ name,role = v[0], v[1] if Array === name
88
+ MetaItem.new(@book.add_contributor(name, nil, role))
89
+ }
90
+ end
91
+
92
+ def publishers(*vals)
93
+ @last_defined_item = vals.map {
94
+ |v|
95
+ MetaItem.new(@book.add_publisher(v, nil))
96
+ }
97
+ end
98
+
99
+ def unique_identifier(val, id = 'BookID', scheme = 'nil')
100
+ @last_defined_item = MetaItem.new(@book.set_main_id(val, id, scheme))
101
+ end
102
+
103
+ def alts(alt_vals = {})
104
+ raise "can't specify alts on single item" if ! Array === @last_defined_item
105
+ @last_defined_item.each_with_index {
106
+ |item, index|
107
+ item.alt Hash[*(alt_vals.map{|k,v| [k,v[index]]}.flatten)]
108
+ }
109
+ end
110
+
111
+ def contributor(val, role = nil)
112
+ MetaItem.new(@book.add_contributor(val, nil, role))
113
+ end
114
+
115
+ def generate_epub(path_to_epub)
116
+ @book.generate_epub(path_to_epub)
117
+ end
118
+
119
+ def resources(attributes = {}, &block)
120
+ ResourceBuilder.new(@book, attributes, &block)
121
+ end
122
+
123
+ def generate_epub_stream
124
+ # TODO should implement
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,29 @@
1
+ module GEPUB
2
+ module BuilderMixin
3
+ def method_missing(name, *args)
4
+ if Array === @last_defined_item &&
5
+ @last_defined_item.size > 0 &&
6
+ @last_defined_item[0].respond_to?(name.to_sym)
7
+
8
+ if !(@last_defined_item[0].apply_one_to_multi ||
9
+ @last_defined_item.size != 1) &&
10
+ @last_defined_item.size != args.size
11
+ warn "appling #{args} to #{@last_defined_item}: length differs."
12
+ end
13
+
14
+ @last_defined_item.each_with_index {
15
+ |item, i|
16
+ if item.apply_one_to_multi && args.size == 1
17
+ item.send(name, args[0])
18
+ elsif !args[i].nil?
19
+ item.send(name, args[i])
20
+ end
21
+ }
22
+ elsif @last_defined_item.respond_to?(name.to_sym)
23
+ @last_defined_item.send(name, *args)
24
+ else
25
+ super
26
+ end
27
+ end
28
+ end
29
+ end
data/lib/gepub/item.rb CHANGED
@@ -49,10 +49,19 @@ module GEPUB
49
49
  add_property('cover-image')
50
50
  end
51
51
 
52
+ def nav
53
+ add_property('nav')
54
+ end
55
+
52
56
  def add_raw_content(data)
53
57
  @content = data
54
58
  end
55
- def add_content(io)
59
+
60
+ def add_content(io_or_filename)
61
+ io = io_or_filename
62
+ if io_or_filename.class == String
63
+ io = File.new(io_or_filename)
64
+ end
56
65
  io.binmode
57
66
  @content = io.read
58
67
  self
@@ -44,11 +44,16 @@ module GEPUB
44
44
  @items.dup
45
45
  end
46
46
 
47
+ def items
48
+ @items.dup
49
+ end
50
+
47
51
  def item_by_href(href)
48
52
  @items_by_href[href]
49
53
  end
50
54
 
51
55
  def add_item(id,href,media_type, attributes = {})
56
+ id ||= @id_pool.generate_key(:prefix=>'item_'+ File.basename(href,'.*'), :without_count => true)
52
57
  @items[id] = item = Item.new(id,href,media_type,self, attributes)
53
58
  @items_by_href[href] = item
54
59
  item
data/lib/gepub/meta.rb CHANGED
@@ -61,7 +61,7 @@ module GEPUB
61
61
  self
62
62
  end
63
63
 
64
- ['title-type', 'identifier-type', 'display-seq', 'file-as', 'group-position'].each {
64
+ ['title-type', 'identifier-type', 'display-seq', 'file-as', 'group-position', 'role'].each {
65
65
  |name|
66
66
  methodbase = name.sub('-','_')
67
67
  define_method(methodbase + '=') { |val| refine(name, val); }
@@ -78,6 +78,14 @@ module GEPUB
78
78
  self
79
79
  end
80
80
 
81
+ def list_alternates
82
+ list = refiner_list('alternate-script').map {
83
+ |refiner|
84
+ [ refiner['xml:lang'], refiner.content ]
85
+ }
86
+ Hash[*list.flatten]
87
+ end
88
+
81
89
  def to_xml(builder, id_pool, ns = nil, additional_attr = {}, opf_version = '3.0')
82
90
  additional_attr ||= {}
83
91
  if @refiners.size > 0 && opf_version.to_f >= 3.0
@@ -5,7 +5,7 @@ require 'time'
5
5
  module GEPUB
6
6
  # metadata constants
7
7
  module TITLE_TYPE
8
- ['main','subtitle', 'short', 'collection', 'edition','expanded'].each {
8
+ TYPES = ['main','subtitle', 'short', 'collection', 'edition','expanded'].each {
9
9
  |type|
10
10
  const_set(type.upcase, type)
11
11
  }
@@ -145,6 +145,13 @@ module GEPUB
145
145
  yield meta if block_given?
146
146
  meta
147
147
  end
148
+
149
+ def set_title(content, id = nil, title_type = nil)
150
+ title_clear
151
+ add_title(content, id, title_type)
152
+ yield meta if block_given?
153
+ meta
154
+ end
148
155
 
149
156
  def add_person(name, content, id = nil, role = 'aut')
150
157
  meta = add_metadata(name, content, id).refine('role', role)
data/lib/gepub/package.rb CHANGED
@@ -29,7 +29,7 @@ module GEPUB
29
29
  if param[:without_count]
30
30
  k = prefix + suffix
31
31
  count -= 1
32
- param[:without_count] = nil
32
+ param.delete(:without_count)
33
33
  else
34
34
  k = prefix + count.to_s + suffix
35
35
  end
@@ -122,10 +122,9 @@ module GEPUB
122
122
  item.add_properties 'cover-image'
123
123
  end
124
124
 
125
- def add_item(href, io = nil, id = nil, attributes = {})
126
- id ||= @id_pool.generate_key(:prefix=>'item', :suffix=>'_'+ File.basename(href,'.*'), :without_count => true)
125
+ def add_item(href, io_or_filename = nil, id = nil, attributes = {})
127
126
  item = @manifest.add_item(id, href, nil, attributes)
128
- item.add_content(io) unless io.nil?
127
+ item.add_content(io_or_filename) unless io_or_filename.nil?
129
128
  @spine.push(item) if @ordered
130
129
  yield item if block_given?
131
130
  item
@@ -138,16 +137,27 @@ module GEPUB
138
137
  @ordered = nil
139
138
  end
140
139
 
141
- def add_ordered_item(href, io = nil, id = nil, attributes = {})
140
+ def add_ordered_item(href, io_or_filename = nil, id = nil, attributes = {})
142
141
  raise 'do not call add_ordered_item within ordered block.' if @ordered
143
- item = add_item(href, io, id, attributes)
142
+ item = add_item(href, io_or_filename, id, attributes)
144
143
  @spine.push(item)
145
144
 
146
145
  item
147
146
  end
148
147
 
148
+ def spine_items
149
+ spine.itemref_list.map {
150
+ |itemref|
151
+ @manifest.item_list[itemref.idref]
152
+ }
153
+ end
149
154
 
150
- def method_missing(name, *args)
155
+ def items
156
+ @manifest.item_list
157
+ end
158
+
159
+ def method_missing(name, *args)
160
+ return @manifest.send(name.to_sym, *args) if [:item_by_href].member? name
151
161
  Metadata::CONTENT_NODE_LIST.each {
152
162
  |x|
153
163
  case name.to_s
@@ -0,0 +1,147 @@
1
+ module GEPUB
2
+ class ResourceBuilder
3
+ include BuilderMixin
4
+ class ResourceItem
5
+ attr_reader :item
6
+ def initialize(item)
7
+ @item = item
8
+ end
9
+
10
+ def apply_one_to_multi
11
+ true
12
+ end
13
+
14
+ def media_type(val)
15
+ @item.set_media_type(val)
16
+ end
17
+
18
+ def method_missing(name, *args)
19
+ @item.send(name.to_sym, *args)
20
+ end
21
+ end
22
+
23
+ def initialize(book, attributes = {}, &block)
24
+ @last_defined_item = nil
25
+ @book = book
26
+ @file_postprocess = {}
27
+ @file_preprocess = {}
28
+ @files_postprocess = {}
29
+ @files_preprocess = {}
30
+ current_wd = Dir.getwd
31
+ Dir.chdir(attributes[:workdir]) unless attributes[:workdir].nil?
32
+ instance_eval &block
33
+ Dir.chdir current_wd
34
+ true
35
+ end
36
+
37
+ def ordered(&block)
38
+ @book.ordered {
39
+ instance_eval &block
40
+ }
41
+ end
42
+
43
+ def file(val)
44
+ raise "can't specify multiple files on file keyword" if Hash === val && val.length > 1
45
+
46
+ @file_preprocess.each {
47
+ |k,p|
48
+ p.call
49
+ }
50
+ @last_defined_item = ResourceItem.new(create_one_file(val))
51
+ @file_postprocess.each {
52
+ |k,p|
53
+ p.call
54
+ }
55
+ end
56
+
57
+ def files(*arg)
58
+ arg = arg[0] if arg.size == 1 && Hash === arg[0]
59
+ @files_preprocess.each {
60
+ |k,p|
61
+ p.call
62
+ }
63
+ @last_defined_item = arg.map {
64
+ |val|
65
+ ResourceItem.new(create_one_file(val))
66
+ }
67
+ @files_postprocess.each {
68
+ |k,p|
69
+ p.call
70
+ }
71
+ end
72
+
73
+ def cover_image(val)
74
+ file(val)
75
+ @last_defined_item.cover_image
76
+ end
77
+
78
+ def nav(val)
79
+ file(val)
80
+ @last_defined_item.nav
81
+ end
82
+
83
+ def heading(text, id = nil)
84
+ @last_defined_item.toc_text_with_id(text, id)
85
+ end
86
+
87
+ def with_media_type(*type)
88
+ raise 'with_media_type needs block.' unless block_given?
89
+ @file_postprocess['with_media_type'] = Proc.new { media_type(*type) }
90
+ @files_postprocess['with_media_type'] = Proc.new { media_type(*type) }
91
+ yield
92
+ @file_postprocess.delete('with_media_type')
93
+ @files_postprocess.delete('with_media_type')
94
+ end
95
+
96
+ def fallback_group
97
+ raise 'fallback_group needs block.' unless block_given?
98
+ count = 0
99
+ before = nil
100
+
101
+ @files_preprocess['fallback_group'] = Proc.new { raise "can't use files within fallback_group" }
102
+
103
+ @file_preprocess['fallback_group'] = Proc.new {
104
+ before = @last_defined_item
105
+ }
106
+
107
+ @file_postprocess['fallback_group'] = Proc.new {
108
+ if count > 0
109
+ before.item.set_fallback(@last_defined_item.item.id)
110
+ end
111
+ count += 1
112
+ }
113
+ yield
114
+ @files_preprocess.delete('fallback_group')
115
+ @file_postprocess.delete('fallback_group')
116
+ @file_preprocess.delete('fallback_group')
117
+ end
118
+
119
+ def fallback_chain_files(*arg)
120
+ files(*arg)
121
+ @last_defined_item.inject(nil) {
122
+ |item1, item2|
123
+ if !item1.nil?
124
+ item1.item.set_fallback(item2.item.id)
125
+ end
126
+ item2
127
+ }
128
+ end
129
+
130
+ private
131
+
132
+ def create_one_file(val)
133
+ name = val
134
+ io = val
135
+ if Hash === val
136
+ name = val.first[0]
137
+ io = val.first[1]
138
+ end
139
+ if Array === val
140
+ name = val[0]
141
+ io = val[1]
142
+ end
143
+ @book.add_item(name, io)
144
+ end
145
+ end
146
+
147
+ end
data/lib/gepub/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module GEPUB
2
- VERSION = "0.6.2"
2
+ VERSION = "0.6.3"
3
3
  end
data/lib/gepub.rb CHANGED
@@ -16,6 +16,10 @@ require 'gepub/package'
16
16
  require 'gepub/item'
17
17
  require 'gepub/book'
18
18
  require 'gepub/gepuber'
19
+ require 'gepub/builder_mixin'
20
+ require 'gepub/resource_builder'
21
+ require 'gepub/builder'
22
+
19
23
 
20
24
 
21
25
 
@@ -0,0 +1,356 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.dirname(__FILE__) + '/spec_helper.rb'
3
+ require 'rubygems'
4
+ describe GEPUB::Builder do
5
+ context 'metadata generating' do
6
+ it 'should generate language' do
7
+ builder = GEPUB::Builder.new {
8
+ language 'ja'
9
+ }
10
+ builder.instance_eval { @book.language }.to_s.should == 'ja'
11
+ end
12
+
13
+ it 'should generate uid' do
14
+ builder = GEPUB::Builder.new {
15
+ unique_identifier 'http://example.jp/as_url', 'BookID', 'url'
16
+ }
17
+ builder.instance_eval { @book.identifier }.to_s.should == 'http://example.jp/as_url'
18
+ builder.instance_eval { @book.identifier_list[0]['id']}.should == 'BookID'
19
+ builder.instance_eval { @book.identifier_list[0].identifier_type}.to_s.should == 'url'
20
+ end
21
+
22
+ it 'should generate title' do
23
+ builder = GEPUB::Builder.new {
24
+ title 'The Book Title'
25
+ }
26
+ builder.instance_eval { @book.title }.to_s.should == 'The Book Title'
27
+ builder.instance_eval { @book.title.title_type }.to_s.should == 'main'
28
+ end
29
+
30
+ it 'should generate title with type ' do
31
+ builder = GEPUB::Builder.new {
32
+ subtitle 'the sub-title'
33
+ }
34
+ builder.instance_eval { @book.title }.to_s.should == 'the sub-title'
35
+ builder.instance_eval { @book.title.title_type }.to_s.should == 'subtitle'
36
+ end
37
+
38
+ it 'should generate collection title ' do
39
+ builder = GEPUB::Builder.new {
40
+ collection 'the collection', 3
41
+ }
42
+ builder.instance_eval { @book.title }.to_s.should == 'the collection'
43
+ builder.instance_eval { @book.title.title_type }.to_s.should == 'collection'
44
+ builder.instance_eval { @book.title.group_position }.to_s.should == '3'
45
+ end
46
+
47
+ it 'should refine title: alternates ' do
48
+ builder = GEPUB::Builder.new {
49
+ collection 'the collection', 3
50
+ alt 'ja' => 'シリーズ'
51
+ }
52
+ builder.instance_eval { @book.title }.to_s.should == 'the collection'
53
+ builder.instance_eval { @book.title.title_type }.to_s.should == 'collection'
54
+ builder.instance_eval { @book.title.list_alternates['ja'] }.to_s.should == 'シリーズ'
55
+ end
56
+
57
+ it 'should refine title: file_as ' do
58
+ builder = GEPUB::Builder.new {
59
+ title 'メインタイトル'
60
+ file_as 'main title'
61
+ }
62
+ builder.instance_eval { @book.title }.to_s.should == 'メインタイトル'
63
+ builder.instance_eval { @book.title.title_type }.to_s.should == 'main'
64
+ builder.instance_eval { @book.title.file_as }.to_s.should == 'main title'
65
+ end
66
+
67
+ it 'should refine title: alt and file_as ' do
68
+ builder = GEPUB::Builder.new {
69
+ title 'メインタイトル'
70
+ file_as 'main title'
71
+ alt 'en' => 'The Main Title'
72
+ }
73
+ builder.instance_eval { @book.title }.to_s.should == 'メインタイトル'
74
+ builder.instance_eval { @book.title.title_type }.to_s.should == 'main'
75
+ builder.instance_eval { @book.title.file_as }.to_s.should == 'main title'
76
+ builder.instance_eval { @book.title.list_alternates['en'] }.to_s.should == 'The Main Title'
77
+ end
78
+
79
+ it 'should generate creator ' do
80
+ builder = GEPUB::Builder.new {
81
+ creator 'The Main Author'
82
+ }
83
+ builder.instance_eval { @book.creator }.to_s.should == 'The Main Author'
84
+ end
85
+
86
+ it 'should generate creator with role' do
87
+ builder = GEPUB::Builder.new {
88
+ creator 'The Illustrator', 'ill'
89
+ }
90
+ builder.instance_eval { @book.creator }.to_s.should == 'The Illustrator'
91
+ builder.instance_eval { @book.creator.role}.to_s.should == 'ill'
92
+ end
93
+
94
+ it 'should generate contributor ' do
95
+ builder = GEPUB::Builder.new {
96
+ contributor 'contributor', 'edt'
97
+ }
98
+ builder.instance_eval { @book.contributor }.to_s.should == 'contributor'
99
+ builder.instance_eval { @book.contributor.role}.to_s.should == 'edt'
100
+ end
101
+
102
+ it 'should generate multiple creators ' do
103
+ builder = GEPUB::Builder.new {
104
+ creators 'First Author', 'Second Author', ['Third Person', 'edt']
105
+ }
106
+ builder.instance_eval { @book.creator_list }.size.should == 3
107
+ builder.instance_eval { @book.creator_list[0] }.to_s.should == 'First Author'
108
+ builder.instance_eval { @book.creator_list[1] }.to_s.should == 'Second Author'
109
+ builder.instance_eval { @book.creator_list[2] }.to_s.should == 'Third Person'
110
+ builder.instance_eval { @book.creator_list[2].role }.to_s.should == 'edt'
111
+ end
112
+
113
+ it 'should generate multiple creators, and then add file_as at once ' do
114
+ builder = GEPUB::Builder.new {
115
+ creators 'First Author', 'Second Author', ['Third Person', 'edt']
116
+ file_as '1st', '2nd', '3rd'
117
+ }
118
+ builder.instance_eval { @book.creator_list }.size.should == 3
119
+ builder.instance_eval { @book.creator_list[0] }.to_s.should == 'First Author'
120
+ builder.instance_eval { @book.creator_list[0].file_as }.to_s.should == '1st'
121
+ builder.instance_eval { @book.creator_list[1] }.to_s.should == 'Second Author'
122
+ builder.instance_eval { @book.creator_list[1].file_as }.to_s.should == '2nd'
123
+ builder.instance_eval { @book.creator_list[2] }.to_s.should == 'Third Person'
124
+ builder.instance_eval { @book.creator_list[2].file_as }.to_s.should == '3rd'
125
+ builder.instance_eval { @book.creator_list[2].role }.to_s.should == 'edt'
126
+ end
127
+
128
+
129
+ it 'should generate multiple creators, and multiple alternates ' do
130
+ builder = GEPUB::Builder.new {
131
+ creators 'First Author', 'Second Author', ['Third Person', 'edt']
132
+ alts(
133
+ 'ja' => ['最初','二番目', '三番目'],
134
+ 'en' => ['first','second','third']
135
+ )
136
+ }
137
+ builder.instance_eval { @book.creator_list }.size.should == 3
138
+ builder.instance_eval { @book.creator_list[0] }.to_s.should == 'First Author'
139
+ builder.instance_eval { @book.creator_list[0].list_alternates['ja'] }.to_s.should == '最初'
140
+ builder.instance_eval { @book.creator_list[0].list_alternates['en'] }.to_s.should == 'first'
141
+ builder.instance_eval { @book.creator_list[1] }.to_s.should == 'Second Author'
142
+ builder.instance_eval { @book.creator_list[1].list_alternates['ja'] }.to_s.should == '二番目'
143
+ builder.instance_eval { @book.creator_list[1].list_alternates['en'] }.to_s.should == 'second'
144
+ builder.instance_eval { @book.creator_list[2] }.to_s.should == 'Third Person'
145
+ builder.instance_eval { @book.creator_list[2].list_alternates['ja'] }.to_s.should == '三番目'
146
+ builder.instance_eval { @book.creator_list[2].list_alternates['en'] }.to_s.should == 'third'
147
+ builder.instance_eval { @book.creator_list[2].role }.to_s.should == 'edt'
148
+ end
149
+ end
150
+ context 'resources' do
151
+ it 'should add a file to book' do
152
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
153
+ builder = GEPUB::Builder.new {
154
+ resources(:workdir => workdir) {
155
+ file('text/memo.txt')
156
+ }
157
+ }
158
+ builder.instance_eval{ @book.item_by_href('text/memo.txt') }.should_not be_nil
159
+ builder.instance_eval{ @book.item_by_href('text/memo.txt').content.chomp }.should == 'just a plain text.'
160
+ end
161
+
162
+ it 'should add files to book' do
163
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
164
+ builder = GEPUB::Builder.new {
165
+ resources(:workdir => workdir) {
166
+ files('text/memo.txt','text/cover.xhtml')
167
+ }
168
+ }
169
+ builder.instance_eval{ @book.item_by_href('text/memo.txt') }.should_not be_nil
170
+ builder.instance_eval{ @book.item_by_href('text/memo.txt').content.chomp }.should == 'just a plain text.'
171
+ builder.instance_eval{ @book.item_by_href('text/cover.xhtml') }.should_not be_nil
172
+ end
173
+
174
+ it 'should add files to book from IO object' do
175
+ io = File.new(File.join(File.dirname(__FILE__),'fixtures', 'builder', 'text', 'memo.txt'))
176
+ builder = GEPUB::Builder.new {
177
+ resources() {
178
+ file('text/memo.txt' => io)
179
+ }
180
+ }
181
+ builder.instance_eval{ @book.item_by_href('text/memo.txt') }.should_not be_nil
182
+ builder.instance_eval{ @book.item_by_href('text/memo.txt').content.chomp }.should == 'just a plain text.'
183
+ end
184
+
185
+ it 'should add image file as cover' do
186
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
187
+ builder = GEPUB::Builder.new {
188
+ resources(:workdir => workdir) {
189
+ cover_image 'img/cover.jpg'
190
+ }
191
+ }
192
+ builder.instance_eval{ @book.item_by_href('img/cover.jpg') }.should_not be_nil
193
+ builder.instance_eval{ @book.item_by_href('img/cover.jpg').properties.member? 'cover-image' }.should == true
194
+ end
195
+
196
+ it 'should add file as nav' do
197
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
198
+ builder = GEPUB::Builder.new {
199
+ resources(:workdir => workdir) {
200
+ nav 'text/nav.xhtml'
201
+ }
202
+ }
203
+ builder.instance_eval{ @book.item_by_href('text/nav.xhtml') }.should_not be_nil
204
+ builder.instance_eval{ @book.item_by_href('text/nav.xhtml').properties.member? 'nav' }.should == true
205
+ end
206
+
207
+ it 'should specify mediatype' do
208
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
209
+ builder = GEPUB::Builder.new {
210
+ resources(:workdir => workdir) {
211
+ file('resources/noise.m4')
212
+ media_type('audio/mp4')
213
+ }
214
+ }
215
+ builder.instance_eval{ @book.item_by_href('resources/noise.m4') }.should_not be_nil
216
+ builder.instance_eval{ @book.item_by_href('resources/noise.m4').media_type }.should == 'audio/mp4'
217
+ end
218
+
219
+ it 'should specify mediatype to files' do
220
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
221
+ builder = GEPUB::Builder.new {
222
+ resources(:workdir => workdir) {
223
+ files('resources/noise.m4', 'resources/noise_2.m4a')
224
+ media_type('audio/mp4')
225
+ }
226
+ }
227
+ builder.instance_eval{ @book.item_by_href('resources/noise.m4') }.should_not be_nil
228
+ builder.instance_eval{ @book.item_by_href('resources/noise.m4').media_type }.should == 'audio/mp4'
229
+
230
+ builder.instance_eval{ @book.item_by_href('resources/noise_2.m4a') }.should_not be_nil
231
+ builder.instance_eval{ @book.item_by_href('resources/noise_2.m4a').media_type }.should == 'audio/mp4'
232
+ end
233
+
234
+ it 'should specify mediatype to files using with_media_type' do
235
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
236
+ builder = GEPUB::Builder.new {
237
+ resources(:workdir => workdir) {
238
+ with_media_type('audio/mp4') {
239
+ file('resources/noise.m4')
240
+ file('resources/noise_2.m4a')
241
+ }
242
+ file('text/cover.xhtml')
243
+ }
244
+ }
245
+ builder.instance_eval{ @book.item_by_href('resources/noise.m4') }.should_not be_nil
246
+ builder.instance_eval{ @book.item_by_href('resources/noise.m4').media_type }.should == 'audio/mp4'
247
+
248
+ builder.instance_eval{ @book.item_by_href('resources/noise_2.m4a') }.should_not be_nil
249
+ builder.instance_eval{ @book.item_by_href('resources/noise_2.m4a').media_type }.should == 'audio/mp4'
250
+
251
+ builder.instance_eval{ @book.item_by_href('text/cover.xhtml') }.should_not be_nil
252
+ builder.instance_eval{ @book.item_by_href('text/cover.xhtml').media_type }.should == 'application/xhtml+xml'
253
+ end
254
+
255
+ it 'should add files to book in spine' do
256
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
257
+ builder = GEPUB::Builder.new {
258
+ resources(:workdir => workdir) {
259
+ ordered {
260
+ file('text/cover.xhtml')
261
+ file('text/memo.txt')
262
+ }
263
+ }
264
+ }
265
+ builder.instance_eval{ @book.item_by_href('text/cover.xhtml') }.should_not be_nil
266
+ builder.instance_eval{ @book.spine_items[0].href }.should == 'text/cover.xhtml'
267
+ builder.instance_eval{ @book.item_by_href('text/memo.txt') }.should_not be_nil
268
+ builder.instance_eval{ @book.spine_items[1].href }.should == 'text/memo.txt'
269
+ end
270
+
271
+ it 'should add files and heading' do
272
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
273
+ builder = GEPUB::Builder.new {
274
+ resources(:workdir => workdir) {
275
+ ordered {
276
+ file('text/cover.xhtml')
277
+ heading 'cover page'
278
+ file('text/memo.txt')
279
+ heading 'memo text'
280
+ }
281
+ }
282
+ }
283
+ builder.instance_eval{ @book.item_by_href('text/cover.xhtml') }.should_not be_nil
284
+ builder.instance_eval{ @book.spine_items[0].href }.should == 'text/cover.xhtml'
285
+ builder.instance_eval{ @book.item_by_href('text/memo.txt') }.should_not be_nil
286
+ builder.instance_eval{ @book.spine_items[1].href }.should == 'text/memo.txt'
287
+ builder.instance_eval{ @book.instance_eval { @toc[0][:item].href }}.should == 'text/cover.xhtml'
288
+ builder.instance_eval{ @book.instance_eval { @toc[0][:text] }}.should == 'cover page'
289
+ builder.instance_eval{ @book.instance_eval { @toc[1][:item].href }}.should == 'text/memo.txt'
290
+ builder.instance_eval{ @book.instance_eval { @toc[1][:text] }}.should == 'memo text'
291
+ end
292
+
293
+ it 'should handle fallback chain' do
294
+ # in this test, do not supply
295
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
296
+ builder = GEPUB::Builder.new {
297
+ resources(:workdir => workdir) {
298
+ fallback_group {
299
+ file 'chap3_docbook.xhtml' => nil
300
+ media_type('application/docbook+xml')
301
+ file 'chap3.xml' => nil
302
+ media_type("application/z3986-auth+xml")
303
+ file 'chap3.xhtml' => nil
304
+ }
305
+ }
306
+ }
307
+ builder.instance_eval {
308
+ fallbackid = @book.item_by_href('chap3_docbook.xhtml').fallback
309
+ @book.items[fallbackid].href.should == 'chap3.xml'
310
+
311
+ fallbackid = @book.items[fallbackid].fallback
312
+ @book.items[fallbackid].href.should == 'chap3.xhtml'
313
+ }
314
+ end
315
+
316
+ it 'should handle fallback chain with fallback_chain_files' do
317
+ # in this test, do not supply
318
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
319
+ builder = GEPUB::Builder.new {
320
+ resources(:workdir => workdir) {
321
+ fallback_chain_files 'chap3_docbook.xhtml' => nil, 'chap3.xml' => nil, 'chap3.xhtml' => nil
322
+ }
323
+ }
324
+ builder.instance_eval {
325
+ fallbackid = @book.item_by_href('chap3_docbook.xhtml').fallback
326
+ @book.items[fallbackid].href.should == 'chap3.xml'
327
+
328
+ fallbackid = @book.items[fallbackid].fallback
329
+ @book.items[fallbackid].href.should == 'chap3.xhtml'
330
+ }
331
+ end
332
+
333
+ it 'should handle fallback chain with fallback_chain_files in with_media_type' do
334
+ # in this test, do not supply
335
+ workdir = File.join(File.dirname(__FILE__),'fixtures', 'builder')
336
+ builder = GEPUB::Builder.new {
337
+ resources(:workdir => workdir) {
338
+ with_media_type('application/docbook+xml', 'application/z3986-auth+xml', 'application/xhtml+xml') {
339
+ fallback_chain_files 'chap3_docbook.xhtml' => nil, 'chap3.xml' => nil, 'chap3.xhtml' => nil
340
+ }
341
+ }
342
+ }
343
+ builder.instance_eval {
344
+ @book.item_by_href('chap3_docbook.xhtml').media_type.should == 'application/docbook+xml'
345
+ fallbackid = @book.item_by_href('chap3_docbook.xhtml').fallback
346
+ @book.items[fallbackid].href.should == 'chap3.xml'
347
+ @book.items[fallbackid].media_type.should == 'application/z3986-auth+xml'
348
+
349
+ fallbackid = @book.items[fallbackid].fallback
350
+ @book.items[fallbackid].href.should == 'chap3.xhtml'
351
+ @book.items[fallbackid].media_type.should == 'application/xhtml+xml'
352
+ }
353
+ end
354
+
355
+ end
356
+ end
data/spec/example_spec.rb CHANGED
@@ -3,7 +3,42 @@ require File.dirname(__FILE__) + '/spec_helper.rb'
3
3
  require 'rubygems'
4
4
 
5
5
  describe 'GEPUB usage' do
6
+ context 'On using Builder' do
7
+ end
8
+
6
9
  context 'On generating EPUB' do
10
+ it 'should generate simple EPUB3 with Builder' do
11
+ workdir = File.join(File.dirname(__FILE__), 'fixtures', 'testdata')
12
+ builder = GEPUB::Builder.new {
13
+ unique_identifier 'http:/example.jp/bookid_in_url', 'BookID', 'URL'
14
+ language 'ja'
15
+ title 'GEPUBサンプル文書'
16
+ file_as 'GEPUB Sample Book'
17
+ alt 'en' => 'GEPUB Sample Book (Japanese)',
18
+ 'el' => 'GEPUB δείγμα (Ιαπωνικά)',
19
+ 'th' => 'GEPUB ตัวอย่าง (ญี่ปุ่น)'
20
+
21
+ subtitle 'これはあくまでサンプルです'
22
+ alt 'en' => 'This book is just a sample'
23
+ creator '小嶋智'
24
+ contributors 'Denshobu', 'Asagaya Densho', 'Shonan Densho Teidan', 'eMagazine Torutaru'
25
+ resources(:workdir => workdir) {
26
+ cover_image 'img/image1.jpg' => 'image1.jpg'
27
+ ordered {
28
+ file 'text/chap1.xhtml' => StringIO.new('<html xmlns="http://www.w3.org/1999/xhtml"><head><title>c1</title></head><body><p>the first page</p></body></html>')
29
+ heading 'Chapter 1'
30
+ file 'text/chap1-1.xhtml' => StringIO.new('<html xmlns="http://www.w3.org/1999/xhtml"><head><title>c2</title></head><body><p>the second page</p></body></html>')
31
+ file 'text/chap2.html' => StringIO.new('<html xmlns="http://www.w3.org/1999/xhtml"><head><title>c3</title></head><body><p>the third page</p></body></html>')
32
+ heading 'Chapter 2'
33
+ }
34
+ }
35
+ }
36
+ epubname = File.join(File.dirname(__FILE__), 'example_test_with_builder.epub')
37
+ builder.generate_epub(epubname)
38
+ jar = File.join(File.dirname(__FILE__), 'fixtures/epubcheck-3.0b4/epubcheck-3.0b4.jar')
39
+ system 'java' '-jar', jar, epubname
40
+ end
41
+
7
42
  it 'should generate simple EPUB3 with rather complicated matadata' do
8
43
  book = GEPUB::Book.new
9
44
  book.set_main_id('http:/example.jp/bookid_in_url', 'BookID', 'URL')
@@ -33,10 +68,7 @@ describe 'GEPUB usage' do
33
68
  book.add_contributor('電子雑誌トルタル').set_display_seq(4).add_alternates('en' => 'eMagazine Torutaru')
34
69
 
35
70
  imgfile = File.join(File.dirname(__FILE__), 'fixtures', 'testdata', 'image1.jpg')
36
- File.open(imgfile) do
37
- |io|
38
- book.add_item('img/image1.jpg',io).cover_image
39
- end
71
+ book.add_item('img/image1.jpg',imgfile).cover_image
40
72
 
41
73
  # within ordered block, add_item will be added to spine.
42
74
  book.ordered {
Binary file
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <title>title</title>
5
+ </head>
6
+ <body>
7
+ <div class="cover_wrap">
8
+ <img class="cover" src="img/cover.jpg" alt="cover" />
9
+ </div>
10
+ </body>
11
+ </html>
@@ -0,0 +1 @@
1
+ just a plain text.
@@ -0,0 +1,12 @@
1
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
2
+ <head></head>
3
+ <body>
4
+ <nav epub:type="toc" id="toc">
5
+ <h1>Table of contents</h1>
6
+ <ol>
7
+ <li><a href="foobar.xhtml">Chapter 1</a> </li>
8
+ <li> <a href="barbar.xhtml">Chapter 2</a></li>
9
+ </ol>
10
+ </nav>
11
+ </body>
12
+ </html>
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.2
4
+ version: 0.6.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-20 00:00:00.000000000 Z
12
+ date: 2012-02-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70172284071640 !ruby/object:Gem::Requirement
16
+ requirement: &70335408467760 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '2'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70172284071640
24
+ version_requirements: *70335408467760
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: nokogiri
27
- requirement: &70172284071140 !ruby/object:Gem::Requirement
27
+ requirement: &70335408467260 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.5.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70172284071140
35
+ version_requirements: *70335408467260
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rubyzip
38
- requirement: &70172284070680 !ruby/object:Gem::Requirement
38
+ requirement: &70335408466800 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,9 +43,9 @@ dependencies:
43
43
  version: 0.9.6
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70172284070680
47
- description: gepub is a EPUB parser/generator. Generates EPUB2 opf. will support EPUB3
48
- parse/generation
46
+ version_requirements: *70335408466800
47
+ description: gepub is a generic EPUB parser/generator. Generates and parse EPUB2 and
48
+ EPUB3
49
49
  email:
50
50
  - skoji@mac.com
51
51
  executables:
@@ -60,21 +60,32 @@ files:
60
60
  - README.md
61
61
  - Rakefile
62
62
  - bin/gepuber
63
+ - examples/builder_example.rb
63
64
  - examples/generate_example.rb
64
65
  - examples/image1.jpg
65
66
  - gepub.gemspec
66
67
  - lib/gepub.rb
67
68
  - lib/gepub/book.rb
69
+ - lib/gepub/builder.rb
70
+ - lib/gepub/builder_mixin.rb
68
71
  - lib/gepub/gepuber.rb
69
72
  - lib/gepub/item.rb
70
73
  - lib/gepub/manifest.rb
71
74
  - lib/gepub/meta.rb
72
75
  - lib/gepub/metadata.rb
73
76
  - lib/gepub/package.rb
77
+ - lib/gepub/resource_builder.rb
74
78
  - lib/gepub/spine.rb
75
79
  - lib/gepub/version.rb
76
80
  - lib/gepub/xml_util.rb
81
+ - spec/builder_spec.rb
77
82
  - spec/example_spec.rb
83
+ - spec/fixtures/builder/img/cover.jpg
84
+ - spec/fixtures/builder/resources/noise.m4
85
+ - spec/fixtures/builder/resources/noise_2.m4a
86
+ - spec/fixtures/builder/text/cover.xhtml
87
+ - spec/fixtures/builder/text/memo.txt
88
+ - spec/fixtures/builder/text/nav.xhtml
78
89
  - spec/fixtures/epubcheck-3.0b4/COPYING.txt
79
90
  - spec/fixtures/epubcheck-3.0b4/README.txt
80
91
  - spec/fixtures/epubcheck-3.0b4/epubcheck-3.0b4.jar
@@ -118,9 +129,16 @@ rubyforge_project: gepub
118
129
  rubygems_version: 1.8.11
119
130
  signing_key:
120
131
  specification_version: 3
121
- summary: a generic EPUB parser/generator.
132
+ summary: a generic EPUB library for Ruby.
122
133
  test_files:
134
+ - spec/builder_spec.rb
123
135
  - spec/example_spec.rb
136
+ - spec/fixtures/builder/img/cover.jpg
137
+ - spec/fixtures/builder/resources/noise.m4
138
+ - spec/fixtures/builder/resources/noise_2.m4a
139
+ - spec/fixtures/builder/text/cover.xhtml
140
+ - spec/fixtures/builder/text/memo.txt
141
+ - spec/fixtures/builder/text/nav.xhtml
124
142
  - spec/fixtures/epubcheck-3.0b4/COPYING.txt
125
143
  - spec/fixtures/epubcheck-3.0b4/README.txt
126
144
  - spec/fixtures/epubcheck-3.0b4/epubcheck-3.0b4.jar