ruby-oembed 0.7.6 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. data/.gitignore +4 -1
  2. data/CHANGELOG.rdoc +49 -0
  3. data/Gemfile.lock +13 -8
  4. data/README.rdoc +79 -0
  5. data/Rakefile +21 -6
  6. data/lib/oembed/errors.rb +23 -4
  7. data/lib/oembed/formatter/json/backends/activesupportjson.rb +28 -0
  8. data/lib/oembed/formatter/json/backends/jsongem.rb +31 -0
  9. data/lib/oembed/formatter/json/backends/yaml.rb +85 -0
  10. data/lib/oembed/formatter/json.rb +69 -0
  11. data/lib/oembed/formatter/xml/backends/rexml.rb +44 -0
  12. data/lib/oembed/formatter/xml/backends/xmlsimple.rb +39 -0
  13. data/lib/oembed/formatter/xml.rb +76 -0
  14. data/lib/oembed/formatter.rb +97 -0
  15. data/lib/oembed/provider.rb +102 -38
  16. data/lib/oembed/provider_discovery.rb +19 -7
  17. data/lib/oembed/providers/embedly_urls.yml +487 -0
  18. data/lib/oembed/providers/oohembed_urls.yml +17 -0
  19. data/lib/oembed/providers.rb +68 -11
  20. data/lib/oembed/response/link.rb +14 -0
  21. data/lib/oembed/response/photo.rb +12 -0
  22. data/lib/oembed/response/rich.rb +11 -0
  23. data/lib/oembed/response/video.rb +10 -0
  24. data/lib/oembed/response.rb +58 -10
  25. data/lib/oembed/version.rb +18 -0
  26. data/lib/oembed.rb +2 -1
  27. data/lib/tasks/oembed.rake +45 -0
  28. data/lib/tasks/rspec.rake +5 -0
  29. data/ruby-oembed.gemspec +38 -17
  30. data/spec/formatter/json/.DS_Store +0 -0
  31. data/spec/formatter/json/jsongem_backend_spec.rb +34 -0
  32. data/spec/formatter/json/yaml_backend_spec.rb +30 -0
  33. data/spec/formatter/xml/rexml_backend_spec.rb +30 -0
  34. data/spec/formatter/xml/xmlsimple_backend_spec.rb +34 -0
  35. data/spec/formatter_spec.rb +35 -0
  36. data/spec/provider_spec.rb +189 -24
  37. data/spec/providers_spec.rb +20 -1
  38. data/spec/response_spec.rb +129 -48
  39. data/spec/spec_helper.rb +5 -6
  40. metadata +45 -38
  41. data/CHANGELOG.md +0 -29
  42. data/README.md +0 -50
  43. data/VERSION +0 -1
  44. data/lib/oembed/embedly_urls.json +0 -227
  45. data/lib/oembed/formatters.rb +0 -40
  46. data/rails/init.rb +0 -3
data/.gitignore CHANGED
@@ -1,2 +1,5 @@
1
1
  /pkg
2
- /.bundle
2
+ /.bundle
3
+ /rails_oembed
4
+ /doc
5
+ .DS_Store
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,49 @@
1
+ = CHANGELOG
2
+
3
+ == 0.8.1 - 27 February 2011
4
+
5
+ * Removed all dependencies on external gems. XML is parsed using REXML and JSON can be parsed using YAML thanks to the convert_json_to_yaml method borrowed from Rails! (Marcos Wright Kuhns)
6
+ * Fixed several errors that cropped up when the json gem wasn't installed. (Marcos Wright Kuhns)
7
+ * OEmbed::Response#field now always return Strings. Previously, some JSON values were parsed into other Object types, like Integer and Float instances.
8
+ * OEmbed::Response#url has been renamed OEmbed::Response#request_url because OEmbed::Response::Photo#url should be the URL of the static photo to be used by the oEmbed consumer.
9
+ * OEmbed::Response.create_for now requires the format parameter.
10
+ * OEmbed::Formatter backends won't try to load gems that haven't already been loaded. (Marcos Wright Kuhns)
11
+ * Better code documentation, all around. (Marcos Wright Kuhns)
12
+
13
+ === Deprecations & Removals
14
+
15
+ * Removed the OEmbed::Response::METHODS constant.
16
+ * OEmbed::Provders::Pownce has been removed since pownce.com is no longer active.
17
+ * Provider#url and Provider#name will be removed at some point in the future.
18
+ * All direct raw calls will be made private at some point in the future (i.e. Provider#raw, Providers#raw, and ProviderDiscovery#raw)
19
+
20
+ == 0.8.0 - Unreleased
21
+
22
+ * Added OEmbed::Formatter Backends, to remove the dependency on the json gem and make adding support for other parsing libraries easier. This also fixes GitHub Issue =1. (Marcos Wright Kuhns)
23
+ * Catch invalid endpoint URLs on OEmbed::Provider instantiation. (Marcos Wright Kuhns)
24
+ * Jeweler uses the new OEmbed::Version Class. (Marcos Wright Kuhns)
25
+ * Corrected syntax for Youtube provider in the README (Ryan Richards)
26
+ * Removed the deprecated rails/init.rb file. (Marcos Wright Kuhns)
27
+
28
+ == 0.7.6 - 11 October 2010
29
+
30
+ * Released all recent changes to judofyr/master on GitHub. (Marcos Wright Kuhns)
31
+ * Added CHANGELOG & LICENSE information. (Marcos Wright Kuhns)
32
+
33
+ == 0.7.5 - 29 September 2010
34
+
35
+ * Updated the list of {Embedly}[http://embed.ly] URL schemes. (Aris Bartee)
36
+ * {rvmrc file}[http://rvm.beginrescueend.com/workflow/rvmrc/] added. (Aris Bartee)
37
+
38
+ == 0.7.0 - 23 August 2010
39
+
40
+ * Gemified. (Aris Bartee)
41
+ * Added the {Embedly}[http://embed.ly] Provider. (Alex Kessinger)
42
+ * OEmbed::Response now includes the original request url. (Colin Shea)
43
+ * Unregistering providers with duplicate URL patterns works. (Marcos Wright Kuhns)
44
+
45
+ == 0.0.0 - May 2008 - July 2010
46
+
47
+ * Initial work & release as a library (Magnus Holm, et al.)
48
+ * Many Providers supported, including {OohEmbed}[http://oohembed.com].
49
+ * Support for JSON (via the json gem) and XML (via the xml-simple gem).
data/Gemfile.lock CHANGED
@@ -1,25 +1,31 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby-oembed (0.7.6)
5
- json
6
- xml-simple
4
+ ruby-oembed (0.8.0)
7
5
 
8
6
  GEM
9
7
  remote: http://rubygems.org/
10
8
  specs:
9
+ diff-lcs (1.1.2)
11
10
  gemcutter (0.6.1)
12
11
  git (1.2.5)
13
12
  jeweler (1.4.0)
14
13
  gemcutter (>= 0.1.0)
15
14
  git (>= 1.2.5)
16
15
  rubyforge (>= 2.0.0)
17
- json (1.4.6)
16
+ json (1.5.1)
18
17
  json_pure (1.4.6)
19
- rspec (1.3.0)
18
+ rspec (2.5.0)
19
+ rspec-core (~> 2.5.0)
20
+ rspec-expectations (~> 2.5.0)
21
+ rspec-mocks (~> 2.5.0)
22
+ rspec-core (2.5.1)
23
+ rspec-expectations (2.5.0)
24
+ diff-lcs (~> 1.1.2)
25
+ rspec-mocks (2.5.0)
20
26
  rubyforge (2.0.4)
21
27
  json_pure (>= 1.1.7)
22
- xml-simple (1.0.12)
28
+ xml-simple (1.0.14)
23
29
 
24
30
  PLATFORMS
25
31
  ruby
@@ -27,6 +33,5 @@ PLATFORMS
27
33
  DEPENDENCIES
28
34
  jeweler
29
35
  json
30
- rspec
36
+ rspec (>= 2.0)
31
37
  ruby-oembed!
32
- xml-simple
data/README.rdoc ADDED
@@ -0,0 +1,79 @@
1
+ = ruby-oembed http://stillmaintained.com/metavida/ruby-oembed.png
2
+
3
+ An oEmbed consumer library written in Ruby, letting you easily get embeddable HTML representations of supported web pages, based on their URLs. See {oembed.com}[http://oembed.com] for more about the protocol.
4
+
5
+ = Installation
6
+
7
+ gem install ruby-oembed
8
+
9
+ = Get Started
10
+
11
+ == Providers
12
+
13
+ Get information about a URL via an OEmbed::Provider. This library comes with many Providers built right in, to make your life easy.
14
+
15
+ resource = OEmbed::Providers::Youtube.get("http://www.youtube.com/watch?v=2BYXBC8WQ5k")
16
+ resource.video? #=> true
17
+ resource.thumbnail_url #=> "http://i3.ytimg.com/vi/2BYXBC8WQ5k/hqdefault.jpg"
18
+ resource.html #=> <<-HTML
19
+ <object width="425" height="344">
20
+ <param name="movie" value="http://www.youtube.com/v/2BYXBC8WQ5k?fs=1"></param>
21
+ <param name="allowFullScreen" value="true"></param>
22
+ <param name="allowscriptaccess" value="always"></param>
23
+ <embed src="http://www.youtube.com/v/2BYXBC8WQ5k?fs=1" type="application/x-shockwave-flash" width="425" height="344" allowscriptaccess="always" allowfullscreen="true"></embed>
24
+ </object>
25
+ HTML
26
+
27
+ If you'd like to use a provider that isn't included in the library, it's easy to create one. Just provide the oEmbed API endpoint and URL scheme(s).
28
+
29
+ my_provider = OEmbed::Provider.new("http://my.cool-service.com/api/oembed_endpoint.{format}")
30
+ my_provider << "http://*.cool-service.com/image/*"
31
+ my_provider << "http://*.cool-service.com/video/*"
32
+ resource = my_provider.get("http://a.cool-service.com/video/1") #=> OEmbed::Response
33
+ resource.provider.name #=> "My Cool Service"
34
+
35
+ To use multiple Providers at once, simply register them.
36
+
37
+ OEmbed::Providers.register(OEmbed::Providers::Youtube, my_provider)
38
+ resource = OEmbed::Providers.get("http://www.youtube.com/watch?v=2BYXBC8WQ5k") #=> OEmbed::Response
39
+ resource.type #=> "video"
40
+ resource.provider.name #=> "Youtube"
41
+
42
+ Last but not least, ruby-oembed supports both {oohEmbed}[http://oohembed.com] and {Embedly}[http://embed.ly]. These services are provider aggregators. Each supports a wide array of websites ranging from {Amazon.com}[http://www.amazon.com] to {xkcd}[http://www.xkcd.com].
43
+
44
+ == Formatters
45
+
46
+ This library works wonderfully on it's on, but can get a speed boost by using 3rd party libraries to parse oEmbed data. To use a 3rd party Formatter, just be sure to require the library _before_ ruby-oembed.
47
+
48
+ require 'json'
49
+ require 'xmlsimple'
50
+ require 'oembed'
51
+
52
+ OEmbed::Formatter::JSON.backend #=> OEmbed::Formatter::JSON::Backends::JSONGem
53
+ OEmbed::Formatter::XML.backend #=> OEmbed::Formatter::XML::Backends::XmlSimple
54
+
55
+ The following, optional, backends are currently supported:
56
+ * The {JSON implementation for Ruby}[http://flori.github.com/json/]
57
+ * Rails' ActiveSupport::JSON (confirmed to work with Rails 3.0.x and should work with Rails 2.0+)
58
+ * {XmlSimple}[http://xml-simple.rubyforge.org/]
59
+
60
+ = Lend a Hand
61
+
62
+ Code for the ruby-oembed library is {hosted on GitHub}[http://github.com/judofyr/ruby-oembed].
63
+
64
+ # Get the code.
65
+ git clone git://github.com/judofyr/ruby-oembed.git
66
+ cd ruby-oembed
67
+ # Install all development-related gems.
68
+ gem install bundler
69
+ bundle install
70
+ # Run the tests.
71
+ rake specs
72
+
73
+ If you encounter any bug, feel free to {create an Issue}[http://github.com/judofyr/ruby-oembed/issues].
74
+
75
+ To submit a patch, please {fork}[http://help.github.com/forking/] the library and commit your changes along with relevant tests. Once you're happy with the changes, {send a pull request}[http://help.github.com/pull-requests/].
76
+
77
+ = License
78
+
79
+ This code is free to use under the terms of the MIT license.
data/Rakefile CHANGED
@@ -1,17 +1,32 @@
1
+ require File.expand_path(File.join(__FILE__, '../lib/oembed/version'))
2
+
1
3
  begin
2
4
  require 'jeweler'
5
+
6
+ Dir[File.join(File.dirname(__FILE__), "lib/tasks/*.rake")].sort.each { |ext| load ext }
7
+
3
8
  Jeweler::Tasks.new do |gemspec|
4
9
  gemspec.name = "ruby-oembed"
10
+ gemspec.version = OEmbed::Version
11
+ gemspec.homepage = "http://github.com/judofyr/ruby-oembed"
5
12
  gemspec.summary = "oEmbed for Ruby"
6
- gemspec.description = "An oEmbed client written in Ruby, letting you easily get embeddable HTML representations of a supported web pages, based on their URLs. See http://oembed.com for more about the protocol."
13
+ gemspec.description = "An oEmbed consumer library written in Ruby, letting you easily get embeddable HTML representations of supported web pages, based on their URLs. See http://oembed.com for more information about the protocol."
14
+ gemspec.license = "MIT"
7
15
  gemspec.email = "arisbartee@gmail.com"
8
- gemspec.homepage = "http://github.com/judofyr/ruby-oembed"
9
16
  gemspec.authors = ["Magnus Holm","Alex Kessinger","Aris Bartee","Marcos Wright Kuhns"]
10
- gemspec.add_dependency("json")
11
- gemspec.add_dependency("xml-simple")
12
- gemspec.add_development_dependency("rspec")
17
+ gemspec.add_development_dependency("json")
18
+ gemspec.add_development_dependency("xml-simple")
19
+ gemspec.add_development_dependency("rspec", ">=2.0")
20
+
21
+ gemspec.rdoc_options = %W(
22
+ --main README.rdoc
23
+ --title #{gemspec.full_name}
24
+ --inline-source
25
+ --exclude tasks
26
+ CHANGELOG.rdoc
27
+ )
13
28
  end
14
29
  Jeweler::GemcutterTasks.new
15
30
  rescue LoadError
16
31
  puts "Jeweler not available. Install it with: gem install jeweler"
17
- end
32
+ end
data/lib/oembed/errors.rb CHANGED
@@ -1,28 +1,47 @@
1
1
  module OEmbed
2
+
3
+ # A generic OEmbed-related Error. The OEmbed library does its best to capture all internal
4
+ # errors and wrap them in an OEmbed::Error class so that the error-handling code in your
5
+ # application can more easily identify the source of errors.
6
+ #
7
+ # The following Classes inherit from OEmbed::Error
8
+ # * OEmbed::FormatNotSupported
9
+ # * OEmbed::NotFound
10
+ # * OEmbed::ParseError
11
+ # * OEmbed::UnknownFormat
12
+ # * OEmbed::UnknownResponse
2
13
  class Error < StandardError
3
14
  end
4
15
 
5
- class NotFound < OEmbed::Error
16
+ # This is a test
17
+ class NotFound < OEmbed::Error # :nodoc:
6
18
  def to_s
7
19
  "No embeddable content at '#{super}'"
8
20
  end
9
21
  end
10
22
 
11
- class UnknownFormat < OEmbed::Error
23
+ class UnknownFormat < OEmbed::Error # :nodoc:
12
24
  def to_s
13
25
  "The provider doesn't support the '#{super}' format"
14
26
  end
15
27
  end
16
28
 
17
- class FormatNotSupported < OEmbed::Error
29
+ class FormatNotSupported < OEmbed::Error # :nodoc:
18
30
  def to_s
19
31
  "This server doesn't have the correct libraries installed to support the '#{super}' format"
20
32
  end
21
33
  end
22
34
 
23
- class UnknownResponse < OEmbed::Error
35
+ class UnknownResponse < OEmbed::Error # :nodoc:
24
36
  def to_s
25
37
  "Got unknown response (#{super}) from server"
26
38
  end
27
39
  end
40
+
41
+ class ParseError < OEmbed::Error # :nodoc:
42
+ def to_s
43
+ "There was an error parsing the server response (#{super})"
44
+ end
45
+ end
46
+
28
47
  end
@@ -0,0 +1,28 @@
1
+ # Only allow this backend if ActiveSupport::JSON is already loaded
2
+ raise LoadError, "ActiveSupport::JSON isn't available. require 'activesupport/json'" unless defined?(ActiveSupport::JSON)
3
+
4
+ module OEmbed
5
+ module Formatter
6
+ module JSON
7
+ module Backends
8
+ module ActiveSupportJSON
9
+ ParseError = ::ActiveSupport::JSON.parse_error
10
+ extend self
11
+
12
+ # Parses a JSON string or IO and convert it into an object.
13
+ def decode(json)
14
+ ::ActiveSupport::JSON.decode(json)
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ # Only allow this backend if it parses JSON strings the way we expect it to
24
+ begin
25
+ raise unless OEmbed::Formatter.test_backend(OEmbed::Formatter::JSON::Backends::ActiveSupportJSON)
26
+ rescue
27
+ raise LoadError, "The version of ActiveSupport::JSON you have installed isn't parsing JSON like ruby-oembed expected."
28
+ end
@@ -0,0 +1,31 @@
1
+ # Only allow this backend the json gem is already loaded
2
+ raise LoadError, "The json library isn't available. require 'json'" unless defined?(JSON)
3
+
4
+ module OEmbed
5
+ module Formatter
6
+ module JSON
7
+ module Backends
8
+ module JSONGem
9
+ ParseError = ::JSON::ParserError
10
+ extend self
11
+
12
+ # Parses a JSON string or IO and convert it into an object.
13
+ def decode(json)
14
+ if json.respond_to?(:read)
15
+ json = json.read
16
+ end
17
+ ::JSON.parse(json)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ # Only allow this backend if it parses JSON strings the way we expect it to
27
+ begin
28
+ raise unless OEmbed::Formatter.test_backend(OEmbed::Formatter::JSON::Backends::JSONGem)
29
+ rescue
30
+ raise LoadError, "The version of the json library you have installed isn't parsing JSON like ruby-oembed expected."
31
+ end
@@ -0,0 +1,85 @@
1
+ # Unlike other backends, require YAML if it's not already loaded
2
+ require 'yaml' unless defined?(YAML)
3
+
4
+ module OEmbed
5
+ module Formatter
6
+ module JSON
7
+ module Backends
8
+ # Use the YAML library, part of the standard library, to parse JSON values that has been converted to YAML.
9
+ module Yaml
10
+ ParseError = ::StandardError
11
+ extend self
12
+
13
+ # Parses a JSON string or IO and converts it into an object.
14
+ def decode(json)
15
+ if json.respond_to?(:read)
16
+ json = json.read
17
+ end
18
+ YAML.load(convert_json_to_yaml(json))
19
+ rescue ArgumentError
20
+ raise ParseError, "Invalid JSON string"
21
+ end
22
+
23
+ protected
24
+ # Ensure that ":" and "," are always followed by a space
25
+ def convert_json_to_yaml(json) #:nodoc:
26
+ require 'strscan' unless defined? ::StringScanner
27
+ scanner, quoting, marks, pos = ::StringScanner.new(json), false, [], nil
28
+ scanner.scan_until(/\{/)
29
+ while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/)
30
+ case char = scanner[1]
31
+ when '"', "'"
32
+ if !quoting
33
+ quoting = char
34
+ pos = scanner.pos
35
+ elsif quoting == char
36
+ quoting = false
37
+ end
38
+ when ":",","
39
+ marks << scanner.pos - 1 unless quoting
40
+ when "\\"
41
+ scanner.skip(/\\/)
42
+ end
43
+ end
44
+ raise ParseError unless scanner.scan_until(/\}/)
45
+
46
+ if marks.empty?
47
+ raise ParseError
48
+ else
49
+ left_pos = [-1].push(*marks)
50
+ right_pos = marks << scanner.pos + scanner.rest_size
51
+ output = []
52
+ left_pos.each_with_index do |left, i|
53
+ scanner.pos = left.succ
54
+ chunk = scanner.peek(right_pos[i] - scanner.pos + 1)
55
+ chunk.gsub!(/\\([\\\/]|u[[:xdigit:]]{4})/) do
56
+ ustr = $1
57
+ if ustr.index('u') == 0
58
+ [ustr[1..-1].to_i(16)].pack("U")
59
+ elsif ustr == '\\'
60
+ '\\\\'
61
+ else
62
+ ustr
63
+ end
64
+ end
65
+ output << chunk
66
+ end
67
+ output = output * " "
68
+
69
+ output.gsub!(/\\\//, '/')
70
+ output
71
+ end
72
+ end
73
+
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ # Only allow this backend if it parses JSON strings the way we expect it to
81
+ begin
82
+ raise unless OEmbed::Formatter.test_backend(OEmbed::Formatter::JSON::Backends::Yaml)
83
+ rescue
84
+ raise LoadError, "The version of the YAML library you have installed isn't parsing JSON like ruby-oembed expected."
85
+ end
@@ -0,0 +1,69 @@
1
+ module OEmbed
2
+ module Formatter
3
+ # Handles parsing JSON values using the best available backend.
4
+ module JSON
5
+ # A Array of all available backends, listed in order of preference.
6
+ DECODERS = %w(ActiveSupportJSON JSONGem Yaml)
7
+
8
+ class << self
9
+
10
+ # Returns true if there is a valid JSON backend. Otherwise, raises OEmbed::FormatNotSupported
11
+ def supported?
12
+ !!backend
13
+ end
14
+
15
+ # Parses a JSON string or IO and convert it into an object
16
+ def decode(json)
17
+ backend.decode(json)
18
+ end
19
+
20
+ # Returns the current JSON backend.
21
+ def backend
22
+ set_default_backend unless defined?(@backend)
23
+ raise OEmbed::FormatNotSupported, :json unless defined?(@backend)
24
+ @backend
25
+ end
26
+
27
+ def backend=(name)
28
+ if name.is_a?(Module)
29
+ @backend = name
30
+ else
31
+ already_required = false
32
+ begin
33
+ already_required = OEmbed::Formatter::JSON::Backends.const_defined?(name, false)
34
+ rescue ArgumentError # we're dealing with ruby < 1.9 where const_defined? only takes 1 argument, but behaves the way we want it to.
35
+ already_required = OEmbed::Formatter::JSON::Backends.const_defined?(name)
36
+ rescue NameError # no backends have been loaded yet
37
+ already_required = false
38
+ end
39
+
40
+ require "oembed/formatter/json/backends/#{name.to_s.downcase}" unless already_required
41
+ @backend = OEmbed::Formatter::JSON::Backends::const_get(name)
42
+ end
43
+ @parse_error = @backend::ParseError
44
+ end
45
+
46
+ def with_backend(name)
47
+ old_backend, self.backend = backend, name
48
+ yield
49
+ ensure
50
+ self.backend = old_backend
51
+ end
52
+
53
+ def set_default_backend
54
+ DECODERS.find do |name|
55
+ begin
56
+ self.backend = name
57
+ true
58
+ rescue LoadError
59
+ # Try next decoder.
60
+ false
61
+ end
62
+ end
63
+ end
64
+
65
+ end
66
+
67
+ end # JSON
68
+ end
69
+ end
@@ -0,0 +1,44 @@
1
+ # Unlike other backends, require REXML if it's not already loaded
2
+ require 'rexml/document' unless defined?(REXML)
3
+
4
+ module OEmbed
5
+ module Formatter
6
+ module XML
7
+ module Backends
8
+ # Use the REXML library, part of the standard library, to parse XML values.
9
+ module REXML
10
+ ParseError = ::REXML::ParseException
11
+ extend self
12
+
13
+ # Parses an XML string or IO and convert it into an object
14
+ def decode(xml)
15
+ if !xml.respond_to?(:read)
16
+ xml = StringIO.new(xml)
17
+ end
18
+ obj = {}
19
+ doc = ::REXML::Document.new(xml)
20
+ doc.elements[1].elements.each do |el|
21
+ obj[el.name] = el.text
22
+ end
23
+ obj
24
+ rescue
25
+ case $!
26
+ when ParseError
27
+ raise $!
28
+ else
29
+ raise ParseError, "Couldn't parse the given document."
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ # Only allow this backend if it parses XML strings the way we expect it to
40
+ begin
41
+ raise unless OEmbed::Formatter.test_backend(OEmbed::Formatter::XML::Backends::REXML)
42
+ rescue
43
+ raise LoadError, "The version of the REXML library you have installed isn't parsing XML like ruby-oembed expected."
44
+ end
@@ -0,0 +1,39 @@
1
+ # Only allow this backend the xml-simple gem is already loaded
2
+ raise ::LoadError, "The xml-simple library isn't available. require 'xmlsimple'" unless defined?(XmlSimple)
3
+
4
+ module OEmbed
5
+ module Formatter
6
+ module XML
7
+ module Backends
8
+ # Use the xml-simple gem to parse XML values.
9
+ module XmlSimple
10
+ ParseError = ::ArgumentError
11
+ extend self
12
+
13
+ # Parses an XML string or IO and convert it into an object.
14
+ def decode(xml)
15
+ if !xml.respond_to?(:read)
16
+ xml = StringIO.new(xml)
17
+ end
18
+ ::XmlSimple.xml_in(xml, 'ForceArray'=>false)
19
+ rescue
20
+ case $!
21
+ when ::ArgumentError
22
+ raise $!
23
+ else
24
+ raise ::ArgumentError, "Couldn't parse the given document."
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ # Only allow this backend if it parses XML strings the way we expect it to
35
+ begin
36
+ raise unless OEmbed::Formatter.test_backend(OEmbed::Formatter::XML::Backends::XmlSimple)
37
+ rescue
38
+ raise ::LoadError, "The version of the xml-simple library you have installed isn't parsing XML like ruby-oembed expected."
39
+ end
@@ -0,0 +1,76 @@
1
+ module OEmbed
2
+ module Formatter
3
+ # Handles parsing XML values using the best available backend.
4
+ module XML
5
+ # A Array of all available backends, listed in order of preference.
6
+ DECODERS = %w(XmlSimple REXML)
7
+
8
+ class << self
9
+
10
+ # Returns true if there is a valid XML backend. Otherwise, raises OEmbed::FormatNotSupported
11
+ def supported?
12
+ !!backend
13
+ end
14
+
15
+ # Parses an XML string or IO and convert it into an object
16
+ def decode(xml)
17
+ backend.decode(xml)
18
+ end
19
+
20
+ # Returns the current XML backend.
21
+ def backend
22
+ set_default_backend unless defined?(@backend)
23
+ raise OEmbed::FormatNotSupported, :xml unless defined?(@backend)
24
+ @backend
25
+ end
26
+
27
+ # Sets the current XML backend. Raises a LoadError if the given
28
+ # backend cannot be loaded
29
+ # OEmbed::Formatter::XML.backend = 'REXML'
30
+ def backend=(name)
31
+ if name.is_a?(Module)
32
+ @backend = name
33
+ else
34
+ already_required = false
35
+ begin
36
+ already_required = OEmbed::Formatter::XML::Backends.const_defined?(name, false)
37
+ rescue ArgumentError # we're dealing with ruby < 1.9 where const_defined? only takes 1 argument, but behaves the way we want it to.
38
+ already_required = OEmbed::Formatter::XML::Backends.const_defined?(name)
39
+ rescue NameError # no backends have been loaded yet
40
+ already_required = false
41
+ end
42
+
43
+ require "oembed/formatter/xml/backends/#{name.to_s.downcase}" unless already_required
44
+ @backend = OEmbed::Formatter::XML::Backends.const_get(name)
45
+ end
46
+ @parse_error = @backend::ParseError
47
+ end
48
+
49
+ # Perform a set of operations using a backend other than the current one.
50
+ # OEmbed::Formatter::XML.with_backend('XmlSimple') do
51
+ # OEmbed::Formatter::XML.decode(xml_value)
52
+ # end
53
+ def with_backend(name)
54
+ old_backend, self.backend = backend, name
55
+ yield
56
+ ensure
57
+ self.backend = old_backend
58
+ end
59
+
60
+ def set_default_backend
61
+ DECODERS.find do |name|
62
+ begin
63
+ self.backend = name
64
+ true
65
+ rescue LoadError
66
+ # Try next decoder.
67
+ false
68
+ end
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ end # XML
75
+ end
76
+ end