epub-parser 0.3.7 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ac4cf6d94841545616b908ef95b0028d8ba6e6ad266b48b1a616c67f18c881b
4
- data.tar.gz: 630f88dbacaba24a28364a5cb87d98b6778fdb1504eba785b470495cb8823bda
3
+ metadata.gz: 02fa97ea55de70030b58276b77bfbba26d43f5f99a77c7bffb86aec8b6afaf9e
4
+ data.tar.gz: c07fe68a8715101082628bb10fee8f3869d3874467aeba8598df89e79a72e442
5
5
  SHA512:
6
- metadata.gz: 827f7b42fedec851ee5f3146bba19477cb80b457fdb2c98c69dff872772175bb70a877d686e851eb90744b1cf14974de46300494c5a810fcf7d9c873e2b537b1
7
- data.tar.gz: 6607c5d2a5cbd63c4d9bca7eecaa7b71dfc5be49c828f0d8fdc44fd3cb4e3ee825bbb5e2adb5b06023b54ff2900ef9624cd2a3625a3f77376db12c762f3b42a0
6
+ metadata.gz: 7c03dcea199c65a84f1c184bbfa07c6d42583167ab26398e3159ec421e2c3205b57e39200d006f22f7f3fbf6dbb7567a7b9424d309123e724dc59ce584ee790e
7
+ data.tar.gz: a04003670af41618c26ecb7acd1ec0cda0063961b40c3b5fa0c9d6de21e2c7462eaac7205d6a577df69a05056f04f85ec8cf9044262e2d6bd9c24933d2ca4c04
@@ -53,7 +53,7 @@ pages:
53
53
  dependencies:
54
54
  - test:2.5
55
55
  script:
56
- - rake doc:yard
56
+ - bundle exec rake doc:yard
57
57
  - mv doc public
58
58
  - mv coverage public/
59
59
  artifacts:
@@ -1,5 +1,12 @@
1
1
  = CHANGELOG
2
2
 
3
+ == 0.3.8
4
+
5
+ * [REFACTORING]Add {EPUB::Parser::NokogiriAttributeWithPrefix} and use `Nokogiri::XML::Node#attribute_with_prefix` instead of `EPUB::Parser::Utils#extract_attribute`
6
+ * Set default value for detect_encoding argument for {EPUB::Publication::Package::Manifest::Item#read} to false
7
+ * Make XML library switchable between REXML and Nokogiri
8
+ * Make REXML a default XML backend
9
+
3
10
  == 0.3.7
4
11
 
5
12
  * Strip leading and trailing white spaces from identifiers. See http://www.idpf.org/epub/31/spec/epub-packages.html#sec-opf-dcidentifier for details.
@@ -3,7 +3,6 @@
3
3
  = {doctitle}
4
4
 
5
5
  image:https://gitlab.com/KitaitiMakoto/epub-parser/badges/master/build.svg[link="https://gitlab.com/KitaitiMakoto/epub-parser/commits/master", title="pipeline status"]
6
- image:https://gemnasium.com/KitaitiMakoto/epub-parser.png[link="https://gitlab.com/KitaitiMakoto/epub-parser/commits/master",title="Dependency Status"]
7
6
  image:https://badge.fury.io/rb/epub-parser.svg[link="https://gemnasium.com/KitaitiMakoto/epub-parser",title="Gem Version"]
8
7
  image:https://gitlab.com/KitaitiMakoto/epub-parser/badges/master/coverage.svg[link="https://kitaitimakoto.gitlab.io/epub-parser/coverage/",title="coverage report"]
9
8
 
@@ -160,8 +159,6 @@ Then documentation will be available in `doc` directory.
160
159
  == REQUIREMENTS
161
160
 
162
161
  * Ruby 2.3.0 or later
163
- * `patch` command to install Nokogiri
164
- * C compiler to compile Nokogiri
165
162
 
166
163
  == SIMILAR EFFORTS
167
164
 
@@ -177,6 +174,13 @@ If you find other gems, please tell me or request a pull request.
177
174
 
178
175
  == RECENT CHANGES
179
176
 
177
+ === 0.3.8
178
+
179
+ * [REFACTORING]Add {EPUB::Parser::NokogiriAttributeWithPrefix} and use `Nokogiri::XML::Node#attribute_with_prefix` instead of `EPUB::Parser::Utils#extract_attribute`
180
+ * Set default value for detect_encoding argument for {EPUB::Publication::Package::Manifest::Item#read} to false
181
+ * Make XML library switchable between REXML and Nokogiri
182
+ * Make REXML a default XML backend
183
+
180
184
  === 0.3.7
181
185
 
182
186
  * Strip leading and trailing white spaces from identifiers
@@ -189,25 +193,18 @@ If you find other gems, please tell me or request a pull request.
189
193
  * [BUG FIX]Ignore fragment when find item by relative IRI
190
194
  * Disable https://github.com/ko1/pretty_backtrace[PrettyBacktrace] by default
191
195
 
192
- === 0.3.5
193
-
194
- * [BUG FIX]Fix a bug that {EPUB::ContentDocument::Navigation::Item#item} is `nil` when `href` includes double dots(`..`)(Thanks https://gitlab.com/aelkiss[aelkiss]!)
195
-
196
196
  See {file:CHANGELOG.adoc} for older changelogs and details.
197
197
 
198
198
  == TODOS
199
199
 
200
200
  * Consider to implement IRI feature instead of to use Addressable
201
- * EPUB 3.0.1
202
- * EPUB 3.1
201
+ * EPUB 3.2
203
202
  * Help features for `epub-open` tool
204
203
  * Vocabulary Association Mechanisms
205
204
  * Implementing navigation document and so on
206
205
  * Media Overlays
207
206
  * Content Document
208
207
  * Digital Signature
209
- * Using SAX on parsing
210
- * Abstraction of XML parser(making it possible to use REXML, standard bundled XML library of Ruby)
211
208
  * Handle with encodings other than UTF-8
212
209
 
213
210
  == DONE
@@ -221,6 +218,7 @@ See {file:CHANGELOG.adoc} for older changelogs and details.
221
218
  * Archive library abstraction
222
219
  * Extracting and organizing common behavior from some classes to modules
223
220
  * Multiple rootfiles
221
+ * Abstraction of XML parser(making it possible to use REXML, standard bundled XML library of Ruby)
224
222
 
225
223
  == LICENSE
226
224
 
data/Rakefile CHANGED
@@ -4,7 +4,8 @@ require 'rubygems/tasks'
4
4
  require 'yard'
5
5
  require 'rdoc/task'
6
6
  require 'epub/parser/version'
7
- require 'zipruby'
7
+ require 'archive/zip'
8
+ require 'stringio'
8
9
  require 'epub/maker'
9
10
 
10
11
  task :default => :test
@@ -21,16 +22,38 @@ namespace :test do
21
22
  input_dir = 'test/fixtures/book'
22
23
  EPUB::Maker.archive input_dir
23
24
  small_file = File.read("#{input_dir}/OPS/case-sensitive.xhtml")
24
- Zip::Archive.open "#{input_dir}.epub" do |archive|
25
- archive.add_buffer 'OPS/CASE-SENSITIVE.xhtml', small_file.sub('small file name', 'LARGE FILE NAME')
25
+ File.open "#{input_dir}.epub" do |archive_in|
26
+ File.open "#{input_dir}.epub.tmp", "w" do |archive_out|
27
+ Archive::Zip.open archive_in, :r do |z_in|
28
+ Archive::Zip.open archive_out, :w do |z_out|
29
+ z_in.each do |entry|
30
+ z_out << entry
31
+ end
32
+ entry = Archive::Zip::Entry::File.new("OPS/CASE-SENSITIVE.xhtml")
33
+ entry.file_data = StringIO.new(small_file.sub('small file name', 'LARGE FILE NAME'))
34
+ z_out << entry
35
+ end
36
+ end
37
+ end
26
38
  end
39
+ File.rename "#{input_dir}.epub.tmp", "#{input_dir}.epub"
27
40
  end
28
41
 
29
- Rake::TestTask.new do |task|
30
- task.test_files = FileList['test/**/test_*.rb']
31
- task.warning = true
32
- task.options = '--no-show-detail-immediately --verbose'
42
+ # TODO: Test with both REXML and Nokogiri in testing framework
43
+ %w[REXML Nokogiri].each do |xml_backend|
44
+ task "set_xml_backend_#{xml_backend.downcase}" do
45
+ ENV["EPUB_PARSER_XML_BACKEND"] = xml_backend
46
+ end
47
+
48
+ Rake::TestTask.new "test_with_#{xml_backend.downcase}" do |task|
49
+ task.test_files = FileList['test/**/test_*.rb']
50
+ task.warning = true
51
+ task.options = '--no-show-detail-immediately --verbose'
52
+ EPUB::Parser::XMLDocument.backend = xml_backend
53
+ end
54
+ task "test_with_#{xml_backend.downcase}" => "set_xml_backend_#{xml_backend.downcase}"
33
55
  end
56
+ task :test => [:test_with_rexml, :test_with_nokogiri]
34
57
  end
35
58
 
36
59
  task :doc => 'doc:default'
@@ -117,6 +117,14 @@ ret == book # => true; this API is not good I feel... Welcome suggestion!
117
117
  # do something with your book
118
118
  ----
119
119
 
120
+ ==== Switching XML Library
121
+
122
+ EPUB Parser uses https://ruby-doc.org/stdlib-2.5.3/libdoc/rexml/rdoc/index.html[REXML], a standard-bundled library, by default. You can use https://www.nokogiri.org/[Nokogiri], a Ruby bindings for http://xmlsoft.org/[Libxml2] and http://xmlsoft.org/XSLT/[Libxslt] and more if you have already installed Nokogiri gem by RubyGems or Bundler.
123
+
124
+ ----
125
+ EPUB::Parser::XMLDocument.backend = :Nokogiri
126
+ ----
127
+
120
128
  ==== Switching ZIP library
121
129
 
122
130
  EPUB Parser uses https://github.com/javanthropus/archive-zip[Archive::Zip], a pure Ruby ZIP library, by default. You can use https://bitbucket.org/winebarrel/zip-ruby/wiki/Home[Zip/Ruby], a Ruby bindings for https://libzip.org/[libzip] if you have already installed Zip/Ruby gem by RubyGems or Bundler.
@@ -197,8 +205,6 @@ Then documentation will be available in `doc` directory.
197
205
  == Requirements
198
206
 
199
207
  * Ruby 2.2.0 or later
200
- * `patch` command to install Nokogiri
201
- * C compiler to compile Zip/Ruby and Nokogiri
202
208
 
203
209
  == History
204
210
 
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
26
26
 
27
27
  s.add_development_dependency 'rake'
28
28
  s.add_development_dependency 'rubygems-tasks'
29
- s.add_development_dependency 'zipruby'
29
+ s.add_development_dependency 'zipruby' unless RUBY_PLATFORM.match /mingw/
30
30
  s.add_development_dependency 'pry'
31
31
  s.add_development_dependency 'pry-doc'
32
32
  s.add_development_dependency 'test-unit'
@@ -39,9 +39,9 @@ Gem::Specification.new do |s|
39
39
  s.add_development_dependency 'pretty_backtrace'
40
40
  s.add_development_dependency 'epub-maker'
41
41
  s.add_development_dependency 'asciidoctor'
42
+ s.add_development_dependency 'nokogiri', '>= 1.6.0', '< 1.9'
42
43
 
43
44
  s.add_runtime_dependency 'archive-zip'
44
- s.add_runtime_dependency 'nokogiri', '>= 1.6.0', '< 1.9'
45
45
  s.add_runtime_dependency 'addressable', '>= 2.3.5'
46
46
  s.add_runtime_dependency 'rchardet', '>= 1.6.1'
47
47
  s.add_runtime_dependency 'epub-cfi'
@@ -18,7 +18,7 @@ module EPUB
18
18
  # @return [String] Returns the value of title element.
19
19
  # If none, returns empty string
20
20
  def title
21
- title_elem = nokogiri.search('title').first
21
+ title_elem = rexml.get_elements('.//title').first
22
22
  if title_elem
23
23
  title_elem.text
24
24
  else
@@ -29,12 +29,12 @@ module EPUB
29
29
 
30
30
  # @return [REXML::Document] content as REXML::Document object
31
31
  def rexml
32
- require 'rexml/document'
33
32
  @rexml ||= REXML::Document.new(raw_document)
34
33
  end
35
34
 
36
35
  # @return [Nokogiri::XML::Document] content as Nokogiri::XML::Document object
37
36
  def nokogiri
37
+ require 'nokogiri'
38
38
  @nokogiri ||= Nokogiri.XML(raw_document)
39
39
  end
40
40
  end
@@ -1,7 +1,6 @@
1
1
  require 'epub'
2
2
  require 'epub/constants'
3
3
  require 'epub/book'
4
- require 'nokogiri'
5
4
 
6
5
  module EPUB
7
6
  class Parser
@@ -96,7 +95,7 @@ module EPUB
96
95
  end
97
96
 
98
97
  require 'epub/parser/version'
99
- require 'epub/parser/utils'
98
+ require 'epub/parser/xml_document'
100
99
  require 'epub/parser/ocf'
101
100
  require 'epub/parser/publication'
102
101
  require 'epub/parser/content_document'
@@ -1,12 +1,11 @@
1
1
  require 'epub/content_document'
2
2
  require 'epub/constants'
3
- require 'epub/parser/utils'
4
- require 'nokogiri'
3
+ require 'epub/parser/xml_document'
5
4
 
6
5
  module EPUB
7
6
  class Parser
8
7
  class ContentDocument
9
- include Utils
8
+ using XMLDocument::Refinements
10
9
 
11
10
  # @param [EPUB::Publication::Package::Manifest::Item] item
12
11
  def initialize(item)
@@ -28,7 +27,7 @@ module EPUB
28
27
  end
29
28
  return content_document if content_document.nil?
30
29
  content_document.item = @item
31
- document = Nokogiri.XML(@item.read)
30
+ document = XMLDocument.new(@item.read)
32
31
  # parse_content_document(document)
33
32
  if @item.nav?
34
33
  content_document.navigations = parse_navigations(document)
@@ -36,70 +35,75 @@ module EPUB
36
35
  content_document
37
36
  end
38
37
 
39
- # @param [Nokogiri::HTML::Document] document HTML document or element including nav
38
+ # @param [XMLDocument, REXML::Document, Nokogiri::HTML::Document] document HTML document or element including nav
40
39
  # @return [Array<EPUB::ContentDocument::Navigation::Nav>] navs array of Nav object
41
40
  def parse_navigations(document)
42
- document.search('/xhtml:html/xhtml:body//xhtml:nav', EPUB::NAMESPACES).collect {|elem| parse_navigation elem}
41
+ document.each_element_by_xpath('/xhtml:html/xhtml:body//xhtml:nav', EPUB::NAMESPACES).collect {|elem| parse_navigation elem}
43
42
  end
44
43
 
45
- # @param [Nokogiri::XML::Element] element nav element
44
+ # @param [REXML::Element, Nokogiri::XML::Element] element nav element
46
45
  # @return [EPUB::ContentDocument::Navigation::Nav] nav Nav object
47
46
  def parse_navigation(element)
48
47
  nav = EPUB::ContentDocument::Navigation::Navigation.new
49
48
  nav.text = find_heading(element)
50
- hidden = extract_attribute(element, 'hidden')
49
+ hidden = element.attribute_with_prefix('hidden')
51
50
  nav.hidden = hidden.nil? ? nil : true
52
- nav.type = extract_attribute(element, 'type', 'epub')
53
- element.xpath('./xhtml:ol/xhtml:li', EPUB::NAMESPACES).map do |elem|
51
+ nav.type = element.attribute_with_prefix('type', 'epub')
52
+ element.each_element_by_xpath('./xhtml:ol/xhtml:li', EPUB::NAMESPACES).map do |elem|
54
53
  nav.items << parse_navigation_item(elem)
55
54
  end
56
55
 
57
56
  nav
58
57
  end
59
58
 
60
- # @param [Nokogiri::XML::Element] element li element
59
+ # @param [REXML::Element, Nokogiri::XML::Element] element li element
61
60
  def parse_navigation_item(element)
62
61
  item = EPUB::ContentDocument::Navigation::Item.new
63
- a_or_span = element.xpath('./xhtml:a[1]|xhtml:span[1]', EPUB::NAMESPACES).first
62
+ a_or_span = element.each_element_by_xpath('./xhtml:a[1]|xhtml:span[1]', EPUB::NAMESPACES).first
64
63
  return a_or_span if a_or_span.nil?
65
64
 
66
- item.text = a_or_span.text
65
+ item.text = a_or_span.content
67
66
  if a_or_span.name == 'a'
68
67
  if item.text.empty?
69
- embedded_content = a_or_span.xpath('./xhtml:audio[1]|xhtml:canvas[1]|xhtml:embed[1]|xhtml:iframe[1]|xhtml:img[1]|xhtml:math[1]|xhtml:object[1]|xhtml:svg[1]|xhtml:video[1]', EPUB::NAMESPACES).first
68
+ embedded_content = a_or_span.each_element_by_xpath('./xhtml:audio[1]|xhtml:canvas[1]|xhtml:embed[1]|xhtml:iframe[1]|xhtml:img[1]|xhtml:math[1]|xhtml:object[1]|xhtml:svg[1]|xhtml:video[1]', EPUB::NAMESPACES).first
70
69
  unless embedded_content.nil?
71
70
  case embedded_content.name
72
71
  when 'audio', 'canvas', 'embed', 'iframe'
73
- item.text = extract_attribute(embedded_content, 'name') || extract_attribute(embedded_content, 'srcdoc')
72
+ item.text = embedded_content.attribute_with_prefix('name') || embedded_content.attribute_with_prefix('srcdoc')
74
73
  when 'img'
75
- item.text = extract_attribute(embedded_content, 'alt')
74
+ item.text = embedded_content.attribute_with_prefix('alt')
76
75
  when 'math', 'object'
77
- item.text = extract_attribute(embedded_content, 'name')
76
+ item.text = embedded_content.attribute_with_prefix('name')
78
77
  when 'svg', 'video'
79
78
  else
80
79
  end
81
80
  end
82
- item.text = extract_attribute(a_or_span, 'title').to_s if item.text.nil? || item.text.empty?
81
+ item.text = a_or_span.attribute_with_prefix('title').to_s if item.text.nil? || item.text.empty?
83
82
  end
84
- item.href = extract_attribute(a_or_span, 'href')
83
+ item.href = a_or_span.attribute_with_prefix('href')
85
84
  item.item = @item.find_item_by_relative_iri(item.href)
86
85
  end
87
- item.items = element.xpath('./xhtml:ol[1]/xhtml:li', EPUB::NAMESPACES).map {|li| parse_navigation_item(li)}
86
+ item.items = element.each_element_by_xpath('./xhtml:ol[1]/xhtml:li', EPUB::NAMESPACES).map {|li| parse_navigation_item(li)}
88
87
 
89
88
  item
90
89
  end
91
90
 
92
91
  private
93
92
 
94
- # @param [Nokogiri::XML::Element] element nav element
93
+ # @param [REXML::Element, Nokogiri::XML::Element] element nav element
95
94
  # @return [String] heading heading text
96
95
  def find_heading(element)
97
- heading = element.xpath('./xhtml:h1|xhtml:h2|xhtml:h3|xhtml:h4|xhtml:h5|xhtml:h6|xhtml:hgroup', EPUB::NAMESPACES).first
96
+ heading = element.each_element_by_xpath('./xhtml:h1|xhtml:h2|xhtml:h3|xhtml:h4|xhtml:h5|xhtml:h6|xhtml:hgroup', EPUB::NAMESPACES).first
98
97
 
99
98
  return nil if heading.nil?
100
- return heading.text unless heading.name == 'hgroup'
99
+ return heading.content unless heading.name == 'hgroup'
101
100
 
102
- (heading/'h1' || heading/'h2' || heading/'h3' || heading/'h4' || heading/'h5' || heading/'h6').first.text
101
+ (heading.each_element_by_xpath(".//xhtml:h1", EPUB::NAMESPACES) ||
102
+ heading.each_element_by_xpath(".//xhtml:h2", EPUB::NAMESPACES) ||
103
+ heading.each_element_by_xpath(".//xhtml:h3", EPUB::NAMESPACES) ||
104
+ heading.each_element_by_xpath(".//xhtml:h4", EPUB::NAMESPACES) ||
105
+ heading.each_element_by_xpath(".//xhtml:h5", EPUB::NAMESPACES) ||
106
+ heading.each_element_by_xpath(".//xhtml:h6", EPUB::NAMESPACES)).first.content
103
107
  end
104
108
  end
105
109
  end
@@ -1,23 +1,24 @@
1
1
  module EPUB
2
2
  class Parser
3
3
  module Metadata
4
+ using XMLDocument::Refinements
5
+
4
6
  def parse_metadata(elem, unique_identifier_id, default_namespace)
5
7
  metadata = EPUB::Publication::Package::Metadata.new
6
8
  id_map = {}
7
9
 
8
10
  default_namespace_uri = EPUB::NAMESPACES[default_namespace]
9
- elem.element_children.each do |child|
10
- namespace_uri = child.namespace && child.namespace.href
11
+ elem.each_element do |child|
11
12
  elem_name = child.name
12
13
 
13
14
  model =
14
- case namespace_uri
15
+ case child.namespace_uri
15
16
  when EPUB::NAMESPACES['dc']
16
17
  case elem_name
17
18
  when 'identifier'
18
19
  identifier = build_model(child, :Identifier, ['id'])
19
20
  metadata.identifiers << identifier
20
- identifier.scheme = extract_attribute(child, 'scheme', 'opf')
21
+ identifier.scheme = child.attribute_with_prefix('scheme', 'opf')
21
22
  identifier
22
23
  when 'title'
23
24
  title = build_model(child, :Title)
@@ -44,8 +45,8 @@ module EPUB
44
45
  when 'link'
45
46
  link = build_model(child, :Link, %w[id media-type])
46
47
  metadata.links << link
47
- link.href = extract_attribute(child, 'href')
48
- link.rel = Set.new(extract_attribute(child, 'rel').split(/\s+/))
48
+ link.href = child.attribute_with_prefix('href')
49
+ link.rel = Set.new(child.attribute_with_prefix('rel').split(/\s+/))
49
50
  link
50
51
  else
51
52
  build_unsupported_model(child)
@@ -65,7 +66,7 @@ module EPUB
65
66
  id_map[model.id] = {refinee: model}
66
67
  end
67
68
 
68
- refines = extract_attribute(child, 'refines')
69
+ refines = child.attribute_with_prefix('refines')
69
70
  if refines && refines.start_with?('#')
70
71
  id = refines[1..-1]
71
72
  id_map[id] ||= {}
@@ -87,7 +88,7 @@ module EPUB
87
88
  model = EPUB::Metadata.const_get(klass).new
88
89
  attributes.each do |attr|
89
90
  writer_name = (attr == "content") ? "meta_content=" : "#{attr.gsub('-', '_')}="
90
- model.__send__ writer_name, extract_attribute(elem, attr)
91
+ model.__send__ writer_name, elem.attribute_with_prefix(attr)
91
92
  end
92
93
  model.content = elem.content unless klass == :Link
93
94
  model.content.strip! if klass == :Identifier
@@ -2,12 +2,12 @@ require 'epub/constants'
2
2
  require 'epub/ocf'
3
3
  require 'epub/ocf/physical_container'
4
4
  require 'epub/parser/metadata'
5
- require 'nokogiri'
5
+ require "epub/parser/xml_document"
6
6
 
7
7
  module EPUB
8
8
  class Parser
9
9
  class OCF
10
- include Utils
10
+ using XMLDocument::Refinements
11
11
  include Metadata
12
12
 
13
13
  DIRECTORY = 'META-INF'
@@ -37,11 +37,11 @@ module EPUB
37
37
 
38
38
  def parse_container(xml)
39
39
  container = EPUB::OCF::Container.new
40
- doc = Nokogiri.XML(xml)
41
- doc.xpath('/ocf:container/ocf:rootfiles/ocf:rootfile', EPUB::NAMESPACES).each do |elem|
40
+ doc = XMLDocument.new(xml)
41
+ doc.each_element_by_xpath "/ocf:container/ocf:rootfiles/ocf:rootfile", EPUB::NAMESPACES do |elem|
42
42
  rootfile = EPUB::OCF::Container::Rootfile.new
43
- rootfile.full_path = Addressable::URI.parse(extract_attribute(elem, 'full-path'))
44
- rootfile.media_type = extract_attribute(elem, 'media-type')
43
+ rootfile.full_path = Addressable::URI.parse(elem.attribute_with_prefix('full-path'))
44
+ rootfile.media_type = elem.attribute_with_prefix('media-type')
45
45
  container.rootfiles << rootfile
46
46
  end
47
47
 
@@ -59,14 +59,14 @@ module EPUB
59
59
  end
60
60
 
61
61
  def parse_metadata(content)
62
- doc = Nokogiri.XML(content)
62
+ doc = XMLDocument.new(content)
63
63
  unless multiple_rendition_metadata?(doc)
64
64
  warn "Not implemented: #{self.class}##{__method__}" if $VERBOSE
65
65
  metadata = EPUB::OCF::UnknownFormatMetadata.new
66
66
  metadata.content = content
67
67
  return metadata
68
68
  end
69
- super(doc.root, doc.root['unique-identifier'], 'metadata')
69
+ super(doc.root, doc.root.attribute_with_prefix('unique-identifier'), 'metadata')
70
70
  end
71
71
 
72
72
  def parse_rights(content)
@@ -82,7 +82,7 @@ module EPUB
82
82
  def multiple_rendition_metadata?(doc)
83
83
  doc.root &&
84
84
  doc.root.name == 'metadata' &&
85
- doc.namespaces['xmlns'] == EPUB::NAMESPACES['metadata']
85
+ doc.root.namespaces['xmlns'] == EPUB::NAMESPACES['metadata']
86
86
  end
87
87
  end
88
88
  end
@@ -1,5 +1,4 @@
1
1
  require 'strscan'
2
- require 'nokogiri'
3
2
  require 'epub/publication'
4
3
  require 'epub/constants'
5
4
  require 'epub/parser/metadata'
@@ -7,7 +6,7 @@ require 'epub/parser/metadata'
7
6
  module EPUB
8
7
  class Parser
9
8
  class Publication
10
- include Utils
9
+ using XMLDocument::Refinements
11
10
  include Metadata
12
11
 
13
12
  class << self
@@ -19,7 +18,7 @@ module EPUB
19
18
  end
20
19
 
21
20
  def initialize(opf)
22
- @doc = Nokogiri.XML(opf)
21
+ @doc = XMLDocument.new(opf)
23
22
  end
24
23
 
25
24
  def parse
@@ -36,33 +35,33 @@ module EPUB
36
35
  package = EPUB::Publication::Package.new
37
36
  elem = doc.root
38
37
  %w[version xml:lang dir id].each do |attr|
39
- package.__send__ "#{attr.gsub(/\:/, '_')}=", extract_attribute(elem, attr)
38
+ package.__send__ "#{attr.gsub(/\:/, '_')}=", elem.attribute_with_prefix(attr)
40
39
  end
41
- package.prefix = parse_prefix(extract_attribute(elem, 'prefix'))
40
+ package.prefix = parse_prefix(elem.attribute_with_prefix('prefix'))
42
41
  EPUB::Publication.__send__ :include, EPUB::Publication::FixedLayout if package.prefix.key? EPUB::Publication::FixedLayout::PREFIX_KEY
43
42
 
44
43
  package
45
44
  end
46
45
 
47
46
  def parse_metadata(doc)
48
- super(doc.xpath('/opf:package/opf:metadata', EPUB::NAMESPACES).first, doc.root['unique-identifier'], 'opf')
47
+ super(doc.each_element_by_xpath('/opf:package/opf:metadata', EPUB::NAMESPACES).first, doc.root.attribute_with_prefix('unique-identifier'), 'opf')
49
48
  end
50
49
 
51
50
  def parse_manifest(doc)
52
51
  manifest = EPUB::Publication::Package::Manifest.new
53
- elem = doc.xpath('/opf:package/opf:manifest', EPUB::NAMESPACES).first
54
- manifest.id = extract_attribute(elem, 'id')
52
+ elem = doc.each_element_by_xpath('/opf:package/opf:manifest', EPUB::NAMESPACES).first
53
+ manifest.id = elem.attribute_with_prefix('id')
55
54
 
56
55
  fallback_map = {}
57
- elem.xpath('./opf:item', EPUB::NAMESPACES).each do |e|
56
+ elem.each_element_by_xpath('./opf:item', EPUB::NAMESPACES).each do |e|
58
57
  item = EPUB::Publication::Package::Manifest::Item.new
59
58
  %w[id media-type media-overlay].each do |attr|
60
- item.__send__ "#{attr.gsub(/-/, '_')}=", extract_attribute(e, attr)
59
+ item.__send__ "#{attr.gsub(/-/, '_')}=", e.attribute_with_prefix(attr)
61
60
  end
62
- item.href = extract_attribute(e, 'href')
63
- fallback = extract_attribute(e, 'fallback')
61
+ item.href = e.attribute_with_prefix('href')
62
+ fallback = e.attribute_with_prefix('fallback')
64
63
  fallback_map[fallback] = item if fallback
65
- properties = extract_attribute(e, 'properties')
64
+ properties = e.attribute_with_prefix('properties')
66
65
  item.properties = properties.split(' ') if properties
67
66
  manifest << item
68
67
  end
@@ -75,18 +74,18 @@ module EPUB
75
74
 
76
75
  def parse_spine(doc)
77
76
  spine = EPUB::Publication::Package::Spine.new
78
- elem = doc.xpath('/opf:package/opf:spine', EPUB::NAMESPACES).first
77
+ elem = doc.each_element_by_xpath('/opf:package/opf:spine', EPUB::NAMESPACES).first
79
78
  %w[id toc page-progression-direction].each do |attr|
80
- spine.__send__ "#{attr.gsub(/-/, '_')}=", extract_attribute(elem, attr)
79
+ spine.__send__ "#{attr.gsub(/-/, '_')}=", elem.attribute_with_prefix(attr)
81
80
  end
82
81
 
83
- elem.xpath('./opf:itemref', EPUB::NAMESPACES).each do |e|
82
+ elem.each_element_by_xpath('./opf:itemref', EPUB::NAMESPACES).each do |e|
84
83
  itemref = EPUB::Publication::Package::Spine::Itemref.new
85
84
  %w[idref id].each do |attr|
86
- itemref.__send__ "#{attr}=", extract_attribute(e, attr)
85
+ itemref.__send__ "#{attr}=", e.attribute_with_prefix(attr)
87
86
  end
88
- itemref.linear = (extract_attribute(e, 'linear') != 'no')
89
- properties = extract_attribute(e, 'properties')
87
+ itemref.linear = (e.attribute_with_prefix('linear') != 'no')
88
+ properties = e.attribute_with_prefix('properties')
90
89
  itemref.properties = properties.split(' ') if properties
91
90
  spine << itemref
92
91
  end
@@ -96,12 +95,12 @@ module EPUB
96
95
 
97
96
  def parse_guide(doc)
98
97
  guide = EPUB::Publication::Package::Guide.new
99
- doc.xpath('/opf:package/opf:guide/opf:reference', EPUB::NAMESPACES).each do |ref|
98
+ doc.each_element_by_xpath '/opf:package/opf:guide/opf:reference', EPUB::NAMESPACES do |ref|
100
99
  reference = EPUB::Publication::Package::Guide::Reference.new
101
100
  %w[type title].each do |attr|
102
- reference.__send__ "#{attr}=", extract_attribute(ref, attr)
101
+ reference.__send__ "#{attr}=", ref.attribute_with_prefix(attr)
103
102
  end
104
- reference.href = extract_attribute(ref, 'href')
103
+ reference.href = ref.attribute_with_prefix('href')
105
104
  guide << reference
106
105
  end
107
106
 
@@ -110,10 +109,10 @@ module EPUB
110
109
 
111
110
  def parse_bindings(doc, handler_map)
112
111
  bindings = EPUB::Publication::Package::Bindings.new
113
- doc.xpath('/opf:package/opf:bindings/opf:mediaType', EPUB::NAMESPACES).each do |elem|
112
+ doc.each_element_by_xpath '/opf:package/opf:bindings/opf:mediaType', EPUB::NAMESPACES do |elem|
114
113
  media_type = EPUB::Publication::Package::Bindings::MediaType.new
115
- media_type.media_type = extract_attribute(elem, 'media-type')
116
- media_type.handler = handler_map[extract_attribute(elem, 'handler')]
114
+ media_type.media_type = elem.attribute_with_prefix('media-type')
115
+ media_type.handler = handler_map[elem.attribute_with_prefix('handler')]
117
116
  bindings << media_type
118
117
  end
119
118
 
@@ -1,5 +1,5 @@
1
1
  module EPUB
2
2
  class Parser
3
- VERSION = "0.3.7"
3
+ VERSION = "0.3.8"
4
4
  end
5
5
  end
@@ -0,0 +1,77 @@
1
+ require "rexml/document"
2
+ begin
3
+ require "nokogiri"
4
+ rescue LoadError
5
+ end
6
+
7
+ module EPUB
8
+ class Parser
9
+ class XMLDocument
10
+ class << self
11
+ attr_accessor :backend
12
+
13
+ def new(xml)
14
+ if backend == :Nokogiri
15
+ Nokogiri.XML(xml)
16
+ else
17
+ REXML::Document.new(xml)
18
+ end
19
+ end
20
+ end
21
+
22
+ module Refinements
23
+ [REXML::Element, REXML::Text].each do |klass|
24
+ refine klass do
25
+ %i[document element text].each do |type|
26
+ define_method "#{type}?" do
27
+ node_type == type
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ refine REXML::Element do
34
+ def each_element_by_xpath(xpath, namespaces = nil, &block)
35
+ REXML::XPath.each self, xpath, namespaces, &block
36
+ end
37
+
38
+ def attribute_with_prefix(name, prefix = nil)
39
+ attribute(name, EPUB::NAMESPACES[prefix])&.value
40
+ end
41
+
42
+ alias namespace_uri namespace
43
+
44
+ def content
45
+ texts.join
46
+ end
47
+ end
48
+
49
+ refine REXML::Text do
50
+ alias content value
51
+ end
52
+
53
+ if const_defined? :Nokogiri
54
+ refine Nokogiri::XML::Node do
55
+ def each_element_by_xpath(xpath, namespaces = nil, &block)
56
+ xpath(xpath, namespaces).each &block
57
+ end
58
+
59
+ def attribute_with_prefix(name, prefix = nil)
60
+ attribute_with_ns(name, EPUB::NAMESPACES[prefix])&.value
61
+ end
62
+
63
+ def each_element(xpath = nil, &block)
64
+ element_children.each(&block)
65
+ end
66
+
67
+ alias elements element_children
68
+
69
+ def namespace_uri
70
+ namespace.href
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -39,6 +39,7 @@ module EPUB
39
39
  @prefix = {}
40
40
  end
41
41
 
42
+ # @return [EPUB::Metadata::Identifier] Unique Identifier
42
43
  def unique_identifier
43
44
  @metadata.unique_identifier
44
45
  end
@@ -136,14 +136,12 @@ module EPUB
136
136
 
137
137
  # Read content from EPUB archive
138
138
  #
139
- # @param detect_encoding [Boolean] Whether #read tries auto-detection of character encoding. The default value will become +false+ in the near future.
139
+ # @param detect_encoding [Boolean] Whether #read tries auto-detection of character encoding. The default value is +false+.
140
140
  # @return [String] Content with encoding:
141
141
  # US-ASCII when the content is not in text format such images.
142
142
  # UTF-8 when the content is in text format and +detect_encoding+ is +false+.
143
143
  # auto-detected encoding when the content is in text format and +detect_encoding+ is +true+.
144
- def read(detect_encoding: true)
145
- warn "[#{self.class}##{__method__}]Autodetection of character encoding is deprecated. Pass keyword argument detect_encoding with true explicitly." if detect_encoding
146
-
144
+ def read(detect_encoding: false)
147
145
  raw_content = manifest.package.book.container_adapter.read(manifest.package.book.epub_file, entry_name)
148
146
 
149
147
  unless media_type.start_with?('text/') or
@@ -1,8 +1,11 @@
1
1
  require 'epub/publication'
2
+ require "epub/parser/xml_document"
2
3
 
3
4
  module EPUB
4
5
  module Searcher
5
6
  class Publication
7
+ using Parser::XMLDocument::Refinements
8
+
6
9
  class << self
7
10
  def search_text(package, word, **options)
8
11
  new(package).search_text(word, options)
@@ -28,7 +31,7 @@ module EPUB
28
31
  spine_step = Result::Step.new(:element, 2, {:name => 'spine', :id => spine.id})
29
32
  spine.each_itemref.with_index do |itemref, index|
30
33
  itemref_step = Result::Step.new(:itemref, index, {:id => itemref.id})
31
- XHTML::ALGORITHMS[algorithm].search_text(Nokogiri.XML(itemref.item.read), word).each do |sub_result|
34
+ XHTML::ALGORITHMS[algorithm].search_text(Parser::XMLDocument.new(itemref.item.read), word).each do |sub_result|
32
35
  results << Result.new([spine_step, itemref_step] + sub_result.parent_steps, sub_result.start_steps, sub_result.end_steps)
33
36
  end
34
37
  end
@@ -38,7 +41,7 @@ module EPUB
38
41
 
39
42
  # @todo: Refactoring
40
43
  # @return [Array<Hash>] An array of rearch results. Each result is composed of:
41
- # :element: [Nokogiri::XML::ELement] Found element
44
+ # :element: [REXML::Element, Nokogiri::XML::ELement] Found element
42
45
  # :itemref: [EPUB::Publication::Package::Spine::Itemref] Itemref that element's document belongs to
43
46
  # :location: [EPUB::CFI::Location] CFI that indicates the element
44
47
  # :package: [EPUB::Publication::Package] Package that the element belongs to
@@ -55,10 +58,15 @@ module EPUB
55
58
  path_to_itemref = EPUB::CFI::Path.new([spine_step, itemref_step])
56
59
  content_document = itemref.item.content_document
57
60
  next unless content_document
58
- doc = content_document.nokogiri
59
61
  elems = if xpath
60
- doc.xpath(xpath, namespaces)
62
+ doc = Parser::XMLDocument.new(content_document.read)
63
+ doc.each_element_by_xpath(xpath, namespaces)
61
64
  else
65
+ begin
66
+ doc = content_document.nokogiri
67
+ rescue LoadError
68
+ raise "#{self.class}##{__method__} with `css` argument requires Nokogiri gem for now. Install Nokogiri and then try again."
69
+ end
62
70
  doc.css(css)
63
71
  end
64
72
  elems.each do |elem|
@@ -96,13 +104,13 @@ module EPUB
96
104
  current_node = doc.root
97
105
  path_in_doc.steps.each do |step|
98
106
  if step.element?
99
- current_node = current_node.element_children[step.value / 2 - 1]
107
+ current_node = current_node.elements.to_a[step.value / 2 - 1]
100
108
  else
101
109
  element_index = (step.value - 1) / 2 - 1
102
110
  if element_index == -1
103
111
  current_node = current_node.children.first
104
112
  else
105
- prev = current_node.element_children[element_index]
113
+ prev = current_node.elements.to_a[element_index]
106
114
  break unless prev
107
115
  current_node = prev.next_sibling
108
116
  break unless current_node
@@ -120,8 +128,9 @@ module EPUB
120
128
  def find_path(elem)
121
129
  steps = []
122
130
  until elem.parent.document?
123
- index = elem.parent.element_children.index(elem)
124
- assertion = elem["id"] ? EPUB::CFI::IDAssertion.new(elem["id"]) : nil
131
+ index = elem.parent.elements.to_a.index(elem)
132
+ id_attr = elem.attribute_with_prefix("id")
133
+ assertion = id_attr ? EPUB::CFI::IDAssertion.new(id_attr) : nil
125
134
  steps.unshift EPUB::CFI::Step.new((index + 1) * 2, assertion)
126
135
  elem = elem.parent
127
136
  end
@@ -1,13 +1,15 @@
1
1
  require 'epub'
2
- require 'epub/parser/utils'
2
+ require 'epub/parser/xml_document'
3
3
 
4
4
  module EPUB
5
5
  module Searcher
6
6
  class XHTML
7
+ using Parser::XMLDocument::Refinements
8
+
7
9
  ALGORITHMS = {}
8
10
 
9
11
  class << self
10
- # @param element [Nokogiri::XML::Element, Nokogiri::XML::Document]
12
+ # @param element [REXML::Element, REXML::Document, Nokogiri::XML::Element, Nokogiri::XML::Document]
11
13
  # @param word [String]
12
14
  # @return [Array<Result>]
13
15
  def search_text(element, word)
@@ -21,7 +23,7 @@ module EPUB
21
23
  end
22
24
 
23
25
  class Restricted < self
24
- # @param element [Nokogiri::XML::Element]
26
+ # @param element [REXML::Element, Nokogiri::XML::Element]
25
27
  # @return [Array<Result>]
26
28
  def search_text(word, element=nil)
27
29
  results = []
@@ -29,9 +31,9 @@ module EPUB
29
31
  elem_index = 0
30
32
  (element || @element).children.each do |child|
31
33
  if child.element?
32
- child_step = Result::Step.new(:element, elem_index, {:name => child.name, :id => Parser::Utils.extract_attribute(child, 'id')})
34
+ child_step = Result::Step.new(:element, elem_index, {:name => child.name, :id => child.attribute_with_prefix('id')})
33
35
  if child.name == 'img'
34
- if Parser::Utils.extract_attribute(child, 'alt').index(word)
36
+ if child.attribute_with_prefix('alt').index(word)
35
37
  results << Result.new([child_step], nil, nil)
36
38
  end
37
39
  else
@@ -76,10 +78,10 @@ module EPUB
76
78
  elem_index = 0
77
79
  element.children.each do |child|
78
80
  if child.element?
79
- child_step = [:element, elem_index, {:name => child.name, :id => Parser::Utils.extract_attribute(child, 'id')}]
81
+ child_step = [:element, elem_index, {:name => child.name, :id => child.attribute_with_prefix('id')}]
80
82
  elem_index += 1
81
83
  if child.name == 'img'
82
- alt = Parser::Utils.extract_attribute(child, 'alt')
84
+ alt = child.attribute_with_prefix('alt')
83
85
  next if alt.nil? || alt.empty?
84
86
  indices[content.length] = [child_step]
85
87
  content << alt
@@ -15,3 +15,4 @@ if ENV["PRETTY_BACKTRACE"]
15
15
  end
16
16
 
17
17
  require 'epub/parser'
18
+ EPUB::Parser::XMLDocument.backend = ENV["EPUB_PARSER_XML_BACKEND"].to_sym
@@ -43,15 +43,19 @@ class TestOCFPhysicalContainer < Test::Unit::TestCase
43
43
  end
44
44
  end
45
45
 
46
- require 'epub/ocf/physical_container/zipruby'
47
- class TestZipruby < self
48
- include ConcreteContainer
49
-
50
- def setup
51
- super
52
- @class = EPUB::OCF::PhysicalContainer::Zipruby
53
- @container = @class.new(@container_path)
46
+ begin
47
+ require 'epub/ocf/physical_container/zipruby'
48
+ class TestZipruby < self
49
+ include ConcreteContainer
50
+
51
+ def setup
52
+ super
53
+ @class = EPUB::OCF::PhysicalContainer::Zipruby
54
+ @container = @class.new(@container_path)
55
+ end
54
56
  end
57
+ rescue LoadError
58
+ warn "Skip TestOPFPhysicalContainer::TestZipRuby"
55
59
  end
56
60
 
57
61
  class TestUnpackedDirectory < self
@@ -1,6 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require File.expand_path 'helper', File.dirname(__FILE__)
3
- require 'zipruby'
4
3
 
5
4
  class TestParserOCF < Test::Unit::TestCase
6
5
  def setup
@@ -8,12 +7,8 @@ class TestParserOCF < Test::Unit::TestCase
8
7
  EPUB::OCF::PhysicalContainer.open(file) {|container|
9
8
  @parser = EPUB::Parser::OCF.new(container)
10
9
  }
11
- @container_xml = Zip::Archive.open(file) {|archive|
12
- archive.fopen('META-INF/container.xml').read
13
- }
14
- @metadata_xml = Zip::Archive.open(file) {|archive|
15
- archive.fopen('META-INF/metadata.xml').read
16
- }
10
+ @container_xml = File.read("test/fixtures/book/META-INF/container.xml")
11
+ @metadata_xml = File.read("test/fixtures/book/META-INF/metadata.xml")
17
12
  end
18
13
 
19
14
  def test_parsed_container_has_two_rootfiles
@@ -1,22 +1,14 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require File.expand_path 'helper', File.dirname(__FILE__)
3
- require 'zipruby'
4
3
 
5
4
  class TestParserPublication < Test::Unit::TestCase
6
5
  def setup
7
- file = 'test/fixtures/book.epub'
8
- rootfile = 'OPS/ルートファイル.opf'
9
- @zip = Zip::Archive.open(file)
10
- opf = @zip.fopen(rootfile).read
6
+ opf = File.read("test/fixtures/book/OPS/ルートファイル.opf")
11
7
  @opf = Nokogiri.XML(opf)
12
8
  @parser = EPUB::Parser::Publication.new(opf)
13
9
  @package = @parser.parse_package(@opf)
14
10
  end
15
11
 
16
- def teardown
17
- @zip.close
18
- end
19
-
20
12
  def test_parse_package
21
13
  assert_equal '3.0', @package.version
22
14
  end
@@ -9,7 +9,7 @@ class TestSearcher < Test::Unit::TestCase
9
9
  super
10
10
  opf_path = File.expand_path('../fixtures/book/OPS/ルートファイル.opf', __FILE__)
11
11
  nav_path = File.expand_path('../fixtures/book/OPS/nav.xhtml', __FILE__)
12
- @package = EPUB::Parser::Publication.new(open(opf_path)).parse
12
+ @package = EPUB::Parser::Publication.new(File.read(opf_path)).parse
13
13
  @package.spine.each_itemref do |itemref|
14
14
  stub(itemref.item).read {
15
15
  itemref.idref == 'nav' ? File.read(nav_path) : '<html></html>'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: epub-parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.7
4
+ version: 0.3.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - KITAITI Makoto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-06 00:00:00.000000000 Z
11
+ date: 2018-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -221,39 +221,39 @@ dependencies:
221
221
  - !ruby/object:Gem::Version
222
222
  version: '0'
223
223
  - !ruby/object:Gem::Dependency
224
- name: archive-zip
224
+ name: nokogiri
225
225
  requirement: !ruby/object:Gem::Requirement
226
226
  requirements:
227
227
  - - ">="
228
228
  - !ruby/object:Gem::Version
229
- version: '0'
230
- type: :runtime
229
+ version: 1.6.0
230
+ - - "<"
231
+ - !ruby/object:Gem::Version
232
+ version: '1.9'
233
+ type: :development
231
234
  prerelease: false
232
235
  version_requirements: !ruby/object:Gem::Requirement
233
236
  requirements:
234
237
  - - ">="
235
238
  - !ruby/object:Gem::Version
236
- version: '0'
239
+ version: 1.6.0
240
+ - - "<"
241
+ - !ruby/object:Gem::Version
242
+ version: '1.9'
237
243
  - !ruby/object:Gem::Dependency
238
- name: nokogiri
244
+ name: archive-zip
239
245
  requirement: !ruby/object:Gem::Requirement
240
246
  requirements:
241
247
  - - ">="
242
248
  - !ruby/object:Gem::Version
243
- version: 1.6.0
244
- - - "<"
245
- - !ruby/object:Gem::Version
246
- version: '1.9'
249
+ version: '0'
247
250
  type: :runtime
248
251
  prerelease: false
249
252
  version_requirements: !ruby/object:Gem::Requirement
250
253
  requirements:
251
254
  - - ">="
252
255
  - !ruby/object:Gem::Version
253
- version: 1.6.0
254
- - - "<"
255
- - !ruby/object:Gem::Version
256
- version: '1.9'
256
+ version: '0'
257
257
  - !ruby/object:Gem::Dependency
258
258
  name: addressable
259
259
  requirement: !ruby/object:Gem::Requirement
@@ -362,8 +362,8 @@ files:
362
362
  - lib/epub/parser/metadata.rb
363
363
  - lib/epub/parser/ocf.rb
364
364
  - lib/epub/parser/publication.rb
365
- - lib/epub/parser/utils.rb
366
365
  - lib/epub/parser/version.rb
366
+ - lib/epub/parser/xml_document.rb
367
367
  - lib/epub/publication.rb
368
368
  - lib/epub/publication/fixed_layout.rb
369
369
  - lib/epub/publication/package.rb
@@ -1,20 +0,0 @@
1
- module EPUB
2
- class Parser
3
- module Utils
4
- # Extract the value of attribute of element
5
- #
6
- # @todo Refinement Nokogiri::XML::Node instead of use this method after Ruby 2.0 becomes popular
7
- #
8
- # @param [Nokogiri::XML::Element] element
9
- # @param [String] name name of attribute excluding namespace prefix
10
- # @param [String, nil] prefix XML namespace prefix in {EPUB::NAMESPACES} keys
11
- # @return [String] value of attribute when the attribute exists
12
- # @return nil when the attribute doesn't exist
13
- def extract_attribute(element, name, prefix=nil)
14
- attr = element.attribute_with_ns(name, EPUB::NAMESPACES[prefix])
15
- attr.nil? ? nil : attr.value
16
- end
17
- module_function :extract_attribute
18
- end
19
- end
20
- end