oembed_links 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CREDIT +4 -0
- data/History.txt +33 -0
- data/Manifest.txt +30 -0
- data/README.txt +124 -0
- data/Rakefile +12 -0
- data/lib/oembed_links.rb +371 -0
- data/lib/oembed_links/fetchers/curb.rb +22 -0
- data/lib/oembed_links/fetchers/net_http.rb +19 -0
- data/lib/oembed_links/fetchers/ruby_tubesday.rb +23 -0
- data/lib/oembed_links/formatters/hpricot_xml.rb +37 -0
- data/lib/oembed_links/formatters/json.rb +18 -0
- data/lib/oembed_links/formatters/lib_xml.rb +36 -0
- data/lib/oembed_links/formatters/ruby_xml.rb +34 -0
- data/lib/oembed_links/response.rb +115 -0
- data/lib/oembed_links/template_resolver.rb +128 -0
- data/oembed_links.gemspec +36 -0
- data/oembed_links_example.yml +46 -0
- data/rails/init.rb +7 -0
- data/spec/oembed_links_spec.rb +286 -0
- data/spec/oembed_links_test.yml +26 -0
- data/spec/spec_helper.rb +62 -0
- data/spec/templates/test.haml +1 -0
- data/spec/templates/test.html.erb +1 -0
- data/spec/templates/test.rhtml +1 -0
- metadata +111 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'curb'
|
2
|
+
|
3
|
+
class OEmbed
|
4
|
+
module Fetchers
|
5
|
+
class Curb
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
end
|
9
|
+
|
10
|
+
def name
|
11
|
+
"Curb"
|
12
|
+
end
|
13
|
+
|
14
|
+
def fetch(url)
|
15
|
+
Curl::Easy.perform(url).body_str
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
OEmbed.register_fetcher(OEmbed::Fetchers::Curb)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'ruby_tubesday'
|
2
|
+
|
3
|
+
class OEmbed
|
4
|
+
module Fetchers
|
5
|
+
class RubyTubesday
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@client = ::RubyTubesday.new(:verify_ssl => false)
|
9
|
+
end
|
10
|
+
|
11
|
+
def name
|
12
|
+
"RubyTubesday"
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch(url)
|
16
|
+
@client.get(url)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
OEmbed.register_fetcher(OEmbed::Fetchers::RubyTubesday)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'hpricot'
|
2
|
+
|
3
|
+
class OEmbed
|
4
|
+
module Formatters
|
5
|
+
class HpricotXML
|
6
|
+
|
7
|
+
def name
|
8
|
+
"xml"
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
# This is an extremely naive XML doc to hash
|
14
|
+
# formatter. Cases like arrays represented in
|
15
|
+
# XML will not work; only strings, ints and
|
16
|
+
# floats will be converted.
|
17
|
+
def format(txt)
|
18
|
+
doc = ::Hpricot.XML(txt)
|
19
|
+
h = { }
|
20
|
+
(doc/"/oembed/*").each do |elem|
|
21
|
+
if elem.is_a? Hpricot::Elem
|
22
|
+
c = elem.innerHTML
|
23
|
+
if c =~ /^[0-9]+$/
|
24
|
+
c = c.to_i
|
25
|
+
elsif c=~ /^[0-9]+\.[0-9]+$/
|
26
|
+
c = c.to_f
|
27
|
+
end
|
28
|
+
h[elem.name.strip] = c
|
29
|
+
end
|
30
|
+
end
|
31
|
+
return h
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'libxml'
|
2
|
+
|
3
|
+
class OEmbed
|
4
|
+
module Formatters
|
5
|
+
class LibXML
|
6
|
+
|
7
|
+
def name
|
8
|
+
"xml"
|
9
|
+
end
|
10
|
+
|
11
|
+
# This is an extremely naive XML doc to hash
|
12
|
+
# formatter. Cases like arrays represented in
|
13
|
+
# XML will not work; only strings, ints and
|
14
|
+
# floats will be converted.
|
15
|
+
def format(txt)
|
16
|
+
parser = ::LibXML::XML::Parser.string(txt)
|
17
|
+
doc = parser.parse
|
18
|
+
h = { }
|
19
|
+
doc.root.children.each do |node|
|
20
|
+
unless node.name.strip.empty?
|
21
|
+
c = node.content
|
22
|
+
if c =~ /^[0-9]+$/
|
23
|
+
c = c.to_i
|
24
|
+
elsif c=~ /^[0-9]+\.[0-9]+$/
|
25
|
+
c = c.to_f
|
26
|
+
end
|
27
|
+
h[node.name.strip] = c
|
28
|
+
end
|
29
|
+
end
|
30
|
+
return h
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
|
4
|
+
class OEmbed
|
5
|
+
module Formatters
|
6
|
+
class RubyXML
|
7
|
+
|
8
|
+
def name
|
9
|
+
"xml"
|
10
|
+
end
|
11
|
+
|
12
|
+
# This is an extremely naive XML doc to hash
|
13
|
+
# formatter. Cases like arrays represented in
|
14
|
+
# XML will not work; only strings, ints and
|
15
|
+
# floats will be converted.
|
16
|
+
def format(txt)
|
17
|
+
doc = ::REXML::Document.new(txt)
|
18
|
+
h = { }
|
19
|
+
doc.elements.each("/oembed/*") do |elem|
|
20
|
+
c = elem.text
|
21
|
+
if c =~ /^[0-9]+$/
|
22
|
+
c = c.to_i
|
23
|
+
elsif c=~ /^[0-9]+\.[0-9]+$/
|
24
|
+
c = c.to_f
|
25
|
+
end
|
26
|
+
h[elem.name.strip] = c
|
27
|
+
end
|
28
|
+
return h
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# The class used to represent data returned by the server.
|
2
|
+
#
|
3
|
+
|
4
|
+
class OEmbed
|
5
|
+
class Response
|
6
|
+
|
7
|
+
def initialize(provider, url, response_object)
|
8
|
+
@provider = provider
|
9
|
+
@url = url
|
10
|
+
@response = response_object || {}
|
11
|
+
@rendered_via_provider = @rendered_via_regex = @rendered_via_type = false
|
12
|
+
@rendered = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
@response["html"] || @response["url"]
|
17
|
+
end
|
18
|
+
|
19
|
+
# If no content has been explicitly rendered for this Response,
|
20
|
+
# the default representation of the data will be returned.
|
21
|
+
def rendered_content
|
22
|
+
@rendered || self.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# Case where url has not matched at all
|
27
|
+
def none?(*args, &block)
|
28
|
+
if @response.keys.empty? && !has_rendered?
|
29
|
+
return render_content(*args, &block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Test if this response has been returned from
|
34
|
+
# the given provider_name.
|
35
|
+
def from?(provider_name, *args, &block)
|
36
|
+
if @provider.to_s === provider_name.to_s
|
37
|
+
if can_render_type?(:provider)
|
38
|
+
@rendered_via_provider = true
|
39
|
+
return render_content(*args, &block)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Test if this response came from a URL
|
45
|
+
# that matches the given regex.
|
46
|
+
def matches?(regex, *args, &block)
|
47
|
+
if @url =~ regex
|
48
|
+
if can_render_type?(:regex)
|
49
|
+
@rendered_via_regex = true
|
50
|
+
render_content(*args, &block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Lowest priority renderer, which will execute
|
56
|
+
# a block regardless of conditions so long as
|
57
|
+
# no content has yet been rendered for this response.
|
58
|
+
def any?(*args, &block)
|
59
|
+
if can_render_type?
|
60
|
+
return render_content(*args, &block)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Provides the mechanism to allow .audio?, .video?
|
65
|
+
# and other .type? checking methods. The value of the
|
66
|
+
# method name will be compared against the "type" field
|
67
|
+
# from the returned server data.
|
68
|
+
def method_missing(msym, *args, &block)
|
69
|
+
mname = msym.to_s
|
70
|
+
if mname[mname.size - 1, mname.size] == "?"
|
71
|
+
ts = mname[0..mname.size - 2]
|
72
|
+
if @response["type"] == ts
|
73
|
+
if can_render_type?(:type)
|
74
|
+
@rendered_via_type = true
|
75
|
+
return render_content(*args, &block)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
else
|
79
|
+
raise NoMethodError.new("No such method #{msym.to_s}", msym, *args)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def has_rendered?
|
84
|
+
!@rendered.nil?
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# Needlessly stupid priority for rendering.
|
90
|
+
def can_render_type?(type = nil)
|
91
|
+
if type == :provider
|
92
|
+
!@rendered_via_provider
|
93
|
+
elsif type == :regex
|
94
|
+
!@rendered_via_provider && !@rendered_via_regex
|
95
|
+
elsif type == :type
|
96
|
+
!@rendered_via_provider && !@rendered_via_regex && !@rendered_via_type
|
97
|
+
else
|
98
|
+
!has_rendered?
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def render_content(*args, &block)
|
104
|
+
options = (args.last.is_a?(Hash)) ? args.last : { }
|
105
|
+
if options[:template]
|
106
|
+
@rendered = TemplateResolver.eval_template_for_path(options[:template], @url, @response, self).strip
|
107
|
+
elsif block_given?
|
108
|
+
@rendered = yield(@response).strip
|
109
|
+
else
|
110
|
+
@rendered = self.to_s.strip
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
class OEmbed
|
2
|
+
# The TemplateResolver class acts as a filesystem path resolver for finding
|
3
|
+
# templates, as well as a template renderer. Currently support is enabled for
|
4
|
+
# Haml, Erubis, and ERB templates; if you wish to force a particular type of processor
|
5
|
+
# for any of the templates used, you may set it by specifing it with template_processor=
|
6
|
+
# method. You can specify a base path for resolving template names with the template_root=
|
7
|
+
# method.
|
8
|
+
class TemplateResolver
|
9
|
+
|
10
|
+
# Specify the base filesystem path for resolving templates.
|
11
|
+
def self.template_root=(r)
|
12
|
+
@template_root = r
|
13
|
+
end
|
14
|
+
|
15
|
+
# Get the current base filesystem path, or nil
|
16
|
+
def self.template_root
|
17
|
+
@template_root
|
18
|
+
end
|
19
|
+
|
20
|
+
# Specify the template processor to use for rendering templates;
|
21
|
+
# this will be used regardless of file extension
|
22
|
+
def self.template_processor=(p)
|
23
|
+
p = p.to_s if p.is_a? Symbol
|
24
|
+
raise "Unsupported processor type" unless ["erb", "haml", "erubis", nil].include?(p)
|
25
|
+
@template_processor = p
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return the current forced template processor, or nil
|
29
|
+
def self.template_processor
|
30
|
+
@template_processor
|
31
|
+
end
|
32
|
+
|
33
|
+
# Resolves the template path for the given (potentially relative) path
|
34
|
+
# If the given path is found to exist immediately, whether by itself
|
35
|
+
# or when combined with the optionally present template_root (OEmbed::TemplateResolver.template_root),
|
36
|
+
# it is returned immediately.
|
37
|
+
#
|
38
|
+
# If no path is found for the supplied template path, an exception
|
39
|
+
# is raised.
|
40
|
+
def self.resolve_template_path(path)
|
41
|
+
tmp_path = (@template_root) ? File.join(@template_root, path) : path
|
42
|
+
found_path = nil
|
43
|
+
if File.exists?(tmp_path)
|
44
|
+
found_path = tmp_path
|
45
|
+
end
|
46
|
+
unless found_path
|
47
|
+
raise StandardError.new("File not found: #{path}")
|
48
|
+
else
|
49
|
+
return found_path
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Evaluate the template at the given (possibly relative) path,
|
54
|
+
# assigning the template the local variables url, data and response.
|
55
|
+
# If ApplicationController and ActionController have been defined, then
|
56
|
+
# it is assumed that you are specifying a Rails template path, and an instance
|
57
|
+
# ApplicationController will be used to render the results. You may use
|
58
|
+
# Rails-style helpers / models inside your template, as the ActionView rendering
|
59
|
+
# pipeline will be used. NOTE that to accomplish this, the Rails TestRequest
|
60
|
+
# and TestResponse classes will be loaded and used, if they have not been loaded already.
|
61
|
+
#
|
62
|
+
# If no Rails style template was found or you are not using rails, the following actions take place:
|
63
|
+
# If you specify a template processor (via OEmbed::TemplateResolver.template_processor=)
|
64
|
+
# then it will be used to process the template at the given path (taking any configured template_root
|
65
|
+
# into account. Otherwise a processor will be selected on the following criterion:
|
66
|
+
#
|
67
|
+
# If the file extension is haml, then the Haml library will be required and used
|
68
|
+
# If the Erubis library has been loaded or the file extension is erubis, the Erubis library will be used
|
69
|
+
# In all other cases, the ERB library will be used
|
70
|
+
#
|
71
|
+
|
72
|
+
#
|
73
|
+
# The evaluated result of the template will be returned.
|
74
|
+
def self.eval_template_for_path(path, url, data, response)
|
75
|
+
rendered_response = nil
|
76
|
+
if defined?(ApplicationController) && defined?(ActionController)
|
77
|
+
if !defined?(ActionController::TestRequest) ||
|
78
|
+
!defined?(ActionController::TestResponse)
|
79
|
+
require 'action_controller/test_process'
|
80
|
+
end
|
81
|
+
@app_c ||= ApplicationController.new
|
82
|
+
rendered_response = @app_c.process(ActionController::TestRequest.new,
|
83
|
+
ActionController::TestResponse.new,
|
84
|
+
:render_for_file,
|
85
|
+
path,
|
86
|
+
200,
|
87
|
+
nil,
|
88
|
+
{ :data => data,
|
89
|
+
:url => url,
|
90
|
+
:response => response }).body
|
91
|
+
end
|
92
|
+
if rendered_response.nil? && actual_path = resolve_template_path(path)
|
93
|
+
contents = File.read(actual_path)
|
94
|
+
processor = (@template_processor || File.extname(actual_path)[1..4]).to_s
|
95
|
+
has_erubis = defined?(Erubis)
|
96
|
+
if processor == "haml"
|
97
|
+
require 'haml' unless defined?(Haml)
|
98
|
+
rendered_response = Haml::Engine.new(contents).render({ }, :data => data, :url => url, :response => response)
|
99
|
+
elsif processor == "erubis" || has_erubis
|
100
|
+
require 'erubis' unless has_erubis
|
101
|
+
rendered_response = Erubis::Eruby.new(contents).result(:data => data, :url => url, :response => response)
|
102
|
+
else
|
103
|
+
require 'erb' unless defined?(ERB)
|
104
|
+
rendered_response = ERBTemplate.new(url, data, response).evaluate(contents)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
return rendered_response.chomp
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
class ERBTemplate
|
113
|
+
attr_reader :url, :data, :response
|
114
|
+
|
115
|
+
def initialize(u, d, r)
|
116
|
+
@url = u
|
117
|
+
@data = d
|
118
|
+
@response = r
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
def evaluate(contents)
|
123
|
+
ERB.new(contents).result(binding)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{oembed_links}
|
3
|
+
s.version = "0.1.9"
|
4
|
+
|
5
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
6
|
+
s.authors = ["Indianapolis Star MD&D"]
|
7
|
+
s.date = %q{2008-10-16}
|
8
|
+
s.description = %q{Easy OEmbed integration for Ruby (and Rails).}
|
9
|
+
s.email = ["bugs@indy.com"]
|
10
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
|
11
|
+
s.files = ["CREDIT", "History.txt", "Manifest.txt", "README.txt", "Rakefile", "lib", "lib/oembed_links", "lib/oembed_links.rb", "lib/oembed_links/fetchers", "lib/oembed_links/fetchers/net_http.rb", "lib/oembed_links/fetchers/ruby_tubesday.rb", "lib/oembed_links/fetchers/curb.rb", "lib/oembed_links/formatters", "lib/oembed_links/formatters/hpricot_xml.rb", "lib/oembed_links/formatters/json.rb", "lib/oembed_links/formatters/lib_xml.rb", "lib/oembed_links/formatters/ruby_xml.rb", "lib/oembed_links/response.rb", "lib/oembed_links/template_resolver.rb", "oembed_links.gemspec", "oembed_links_example.yml", "rails", "rails/init.rb", "spec", "spec/oembed_links_spec.rb", "spec/oembed_links_test.yml", "spec/spec_helper.rb", "spec/templates", "spec/templates/test.haml", "spec/templates/test.html.erb", "spec/templates/test.rhtml"]
|
12
|
+
s.has_rdoc = true
|
13
|
+
s.homepage = %q{http://indystar.com/}
|
14
|
+
s.rdoc_options = ["--main", "README.txt"]
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.rubyforge_project = %q{oembed_links}
|
17
|
+
s.rubygems_version = %q{1.3.0}
|
18
|
+
s.summary = %q{}
|
19
|
+
|
20
|
+
if s.respond_to? :specification_version then
|
21
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
22
|
+
s.specification_version = 2
|
23
|
+
|
24
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
25
|
+
s.add_development_dependency(%q<json>)
|
26
|
+
s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
|
27
|
+
s.add_dependency(%q<json>)
|
28
|
+
else
|
29
|
+
s.add_dependency(%q<json>)
|
30
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
31
|
+
end
|
32
|
+
else
|
33
|
+
s.add_dependency(%q<json>)
|
34
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
35
|
+
end
|
36
|
+
end
|