gepub 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
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