ruby-oembed 0.7.6 → 0.8.1

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