60 | EOHTML
61 | }
62 | end
63 |
64 |
65 | To get started quickly in Rails:
66 |
67 | Copy the included oembed_links_example.yml file to RAILS_ROOT/config/oembed_links.yml,
68 | add a dependency to the gem in your environment.rb ( config.gem "oembed_links" )
69 | and start your server. That's it. If you'd like to transform the oembedded content via
70 | templates, you can do so using the following syntax:
71 |
72 | OEmbed.transform(text_to_transform) do |res, url|
73 | res.video?(:template => "oembed/video")
74 | res.from?(:a_provider, :template => "a_provider/oembed")
75 | res.matches?(/some_regex/, :template => "shared/oembed_link")
76 | res.any?(:template => "shared/oembed_link")
77 | end
78 |
79 | This presumes you have a directory in your Rails views directory called "oembed", and a file
80 | of the form "video.html.erb" or "video.rhtml". If you are not using Rails, you may still use the
81 | template functionality, but you must specify the full path to the template. When you are integrating
82 | with Rails, you may use any template library that is installed for your Rails app; when you are using
83 | the absolute filename method, you only have access to ERB, Erubis or HAML.
84 |
85 | As of version 0.0.9, your Rails oembed templates have access to all the traditional Rails template helper methods
86 | (such as Rails' link_to, image_tag, etc.); the templates are processed using the Rails template rendering
87 | pipeline, and as such may even do evil things like access your Models.
88 |
89 | See the RDocs for OEmbed::TemplateResolver for more information regarding templates and oembed_links.
90 |
91 | See the rdocs for much more complete examples. The specs directory has some examples of programmatic
92 | use, but the test to code ratio is slim atm.
93 |
94 | == INSTALL:
95 |
96 | sudo gem install oembed_links
97 | (from github)
98 | gem sources -a http://gems.github.com
99 | sudo gem install netshade-oembed_links
100 |
101 | == LICENSE:
102 |
103 | (The MIT License)
104 |
105 | Copyright (c) 2008 Indianapolis Star
106 |
107 | Permission is hereby granted, free of charge, to any person obtaining
108 | a copy of this software and associated documentation files (the
109 | 'Software'), to deal in the Software without restriction, including
110 | without limitation the rights to use, copy, modify, merge, publish,
111 | distribute, sublicense, and/or sell copies of the Software, and to
112 | permit persons to whom the Software is furnished to do so, subject to
113 | the following conditions:
114 |
115 | The above copyright notice and this permission notice shall be
116 | included in all copies or substantial portions of the Software.
117 |
118 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
119 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
120 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
121 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
122 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
123 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
124 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
125 |
--------------------------------------------------------------------------------
/spec/oembed_links_spec.rb:
--------------------------------------------------------------------------------
1 | require File.join(File.dirname(__FILE__), "spec_helper")
2 |
3 | describe OEmbed, "registration tasks" do
4 | include SpecHelper
5 |
6 | before(:each) do
7 | OEmbed.clear_registrations
8 | OEmbed.load_default_libs
9 | clear_urls
10 | end
11 |
12 | it "should default to NetHTTP if no method is specified in configuration" do
13 | OEmbed.register()
14 | OEmbed.instance_variable_get("@fetch_method").should == "NetHTTP"
15 | end
16 |
17 | it "should throw an error if you provide provider URLs but no scheme or format information" do
18 | lambda { OEmbed.register({ }, { :fake => "http://fake" })}.should raise_error
19 | end
20 |
21 | it "should throw an error if you don't provide any scheme urls for registration" do
22 | lambda { OEmbed.register({ }, { :fake => "http://fake" }, { :fake => { :format => "json", :schemes => []}})}.should raise_error
23 | end
24 |
25 | it "should default to json format if none is specified" do
26 | OEmbed.register({ }, { :fake => "http://fake" }, { :fake => { :schemes => ["http://fake/*"]}})
27 | OEmbed.instance_variable_get("@formats")[:fake].should == "json"
28 | end
29 |
30 | it "should support loading a configuration via YAML" do
31 | OEmbed.register_yaml_file(File.join(File.dirname(__FILE__), "oembed_links_test.yml"))
32 | OEmbed.instance_variable_get("@urls").size.should == 3
33 | end
34 |
35 | it "should support ad hoc addition of providers" do
36 | OEmbed.register_yaml_file(File.join(File.dirname(__FILE__), "oembed_links_test.yml"))
37 | OEmbed.instance_variable_get("@urls").size.should == 3
38 | OEmbed.register_provider(:test4, "http://test4/oembed.{format}", "xml", "http://test4.*/*", "http://test4.*/foo/*")
39 | OEmbed.instance_variable_get("@urls").size.should == 4
40 | end
41 |
42 | it "should support adding new fetchers" do
43 |
44 | OEmbed.register_fetcher(FakeFetcher)
45 | OEmbed.register({ :method => "fake_fetcher"},
46 | { :fake => "http://fake" },
47 | { :fake => {
48 | :format => "json",
49 | :schemes => "http://fake/*"
50 | }})
51 | OEmbed.transform("http://fake/bar/baz").should == "fakecontent"
52 | end
53 |
54 | it "should support adding new formatters" do
55 | OEmbed.register_formatter(FakeFormatter)
56 | OEmbed.register({ :method => "fake_fetcher"},
57 | { :fake => "http://fake" },
58 | { :fake => {
59 | :format => "fake_formatter",
60 | :schemes => "http://fake/*"
61 | }})
62 | url_provides("")
63 | OEmbed.transform("http://fake/bar/baz").should == "http://fakesville"
64 | end
65 |
66 | it "should allow selective loading of formatters through the load_default_libs function" do
67 | OEmbed.clear_registrations
68 | OEmbed.load_default_libs
69 | OEmbed.instance_variable_get("@formatters")["xml"].class.should == OEmbed::Formatters::LibXML
70 | OEmbed.clear_registrations
71 | OEmbed.load_default_libs("libxml")
72 | OEmbed.instance_variable_get("@formatters")["xml"].class.should == OEmbed::Formatters::HpricotXML
73 | OEmbed.clear_registrations
74 | OEmbed.load_default_libs("libxml", "hpricot")
75 | OEmbed.instance_variable_get("@formatters")["xml"].class.should == OEmbed::Formatters::RubyXML
76 | end
77 |
78 | it "should support the hpricot formatter" do
79 | OEmbed.clear_registrations
80 | OEmbed.load_default_libs("libxml")
81 | url_provides(<<-EOXML)
82 |
83 |
84 | bar
85 |
86 | EOXML
87 | OEmbed.register_provider(:test, "http://test4/oembed.{format}", "xml", "http://test.*/*")
88 | OEmbed.transform("http://test.com/bar/baz").should == "bar"
89 | end
90 |
91 | it "should support the rexml formatter" do
92 | OEmbed.clear_registrations
93 | OEmbed.load_default_libs("libxml", "hpricot")
94 | url_provides(<<-EOXML)
95 |
96 |
97 | barxml
98 |
99 | EOXML
100 | OEmbed.register_provider(:test, "http://test4/oembed.{format}", "xml", "http://test.*/*")
101 | OEmbed.transform("http://test.com/bar/baz").should == "barxml"
102 | end
103 |
104 |
105 |
106 | end
107 |
108 | describe OEmbed, "transforming functions" do
109 | include SpecHelper
110 | before(:each) do
111 | OEmbed.clear_registrations
112 | OEmbed.load_default_libs
113 | clear_urls
114 | url_provides({
115 | "html" => "foo",
116 | "type" => "video"
117 | }.to_json)
118 | OEmbed.register_yaml_file(File.join(File.dirname(__FILE__), "oembed_links_test.yml"))
119 | @current_path = File.dirname(__FILE__)
120 | @template_path = File.join(@current_path, "templates")
121 | end
122 |
123 | it "should always give priority to provider conditional blocks" do
124 | OEmbed.transform("http://test1.net/foo") do |r, url|
125 | r.none? { "none" }
126 | r.any? { |a| "any" }
127 | r.video? { |v| "video" }
128 | r.from?(:test1) { |t| "test1" }
129 | r.matches?(/./) { |m| "regex" }
130 | end.should == "test1"
131 | end
132 |
133 | it "should always give priority regex conditional blocks over all others except provider" do
134 | OEmbed.transform("http://test1.net/foo") do |r, url|
135 | r.none? { "none" }
136 | r.any? { |a| "any" }
137 | r.video? { |v| "video" }
138 | r.matches?(/./) { |m| "regex" }
139 | end.should == "regex"
140 | OEmbed.transform("http://test1.net/foo") do |r, url|
141 | r.matches?(/./) { |m| "regex" }
142 | r.any? { |a| "any" }
143 | r.video? { |v| "video" }
144 | end.should == "regex"
145 | end
146 |
147 | it "should recognize the type of content and handle the conditional block appropriately" do
148 | OEmbed.transform("http://test1.net/foo") do |r, url|
149 | r.none? { "none" }
150 | r.any? { |a| "any" }
151 | r.video? { |v| "video" }
152 | end.should == "video"
153 | url_provides({
154 | "html" => "bar",
155 | "type" => "hedgehog"
156 | }.to_json)
157 | OEmbed.transform("http://test1.net/foo") do |r, url|
158 | r.video? { |v| "video" }
159 | r.hedgehog? { |v| "hedgey"}
160 | end.should == "hedgey"
161 | end
162 |
163 | it "should still output the content of a url if no transforming blocks match it" do
164 | OEmbed.transform("http://test1.net/foo") do |r, url|
165 | r.audio? { |a| "audio" }
166 | r.hedgehog? { |v| "hedgey"}
167 | r.from?(:test2) { |t| "test2" }
168 | r.matches?(/baz/) { |m| "regex" }
169 | end.should == "http://test1.net/foo"
170 | end
171 |
172 | it "should transform only urls which have registered providers" do
173 | OEmbed.transform("http://test1.net/foo and http://not.a.valid.url.host/fake are urls") do |r, url|
174 | r.video? { |v| "video" }
175 | end.should == "video and http://not.a.valid.url.host/fake are urls"
176 | end
177 |
178 | it "should pass control to the .none? block if no scheme matched" do
179 | OEmbed.transform("http://not.a.valid.url.host/fake") do |r, url|
180 | r.none? { "nomatch" }
181 | r.audio? { |a| "audio" }
182 | r.hedgehog? { |v| "hedgey"}
183 | r.from?(:test2) { |t| "test2" }
184 | r.matches?(/baz/) { |m| "regex" }
185 | end.should == "nomatch"
186 | end
187 |
188 | it "should allow templates to be used to process the output" do
189 | url_provides({
190 | "url" => "template!"
191 | }.to_json)
192 |
193 | OEmbed.transform("http://test1.net/foo") do |r, url|
194 | r.any?(:template => File.join(@template_path, "test.rhtml"))
195 | end.should == "template! rhtml"
196 | end
197 |
198 |
199 | it "should allow a template root to be set programmatically to process the output" do
200 | url_provides({
201 | "url" => "template!"
202 | }.to_json)
203 | OEmbed::TemplateResolver.template_root = @template_path
204 | OEmbed.transform("http://test1.net/foo") do |r, url|
205 | r.any?(:template => "test.html.erb")
206 | end.should == "template! erb"
207 | end
208 |
209 | it "should allow for selection of different template renderers" do
210 | url_provides({
211 | "url" => "template!"
212 | }.to_json)
213 | defined?(Erubis).should_not == true
214 | defined?(Haml).should_not == true
215 | OEmbed::TemplateResolver.template_root = @template_path
216 | OEmbed::TemplateResolver.template_processor = :erubis
217 | OEmbed.transform("http://test1.net/foo") do |r, url|
218 | r.any?(:template => "test.html.erb")
219 | end.should == "template! erb"
220 | defined?(Erubis).should == "constant"
221 | OEmbed::TemplateResolver.template_processor = :haml
222 | OEmbed.transform("http://test1.net/foo") do |r, url|
223 | r.any?(:template => "test.haml")
224 | end.should == "template! haml"
225 | defined?(Haml).should == "constant"
226 | end
227 |
228 | it "should throw an exception if a path to a template specified does not exist" do
229 | url_provides({
230 | "url" => "template!"
231 | }.to_json)
232 | lambda { OEmbed.transform("http://test1.net/foo") do |r, url|
233 | r.any?(:template => "does.not.exist")
234 | end }.should raise_error
235 | end
236 |
237 |
238 | end
239 |
240 |
241 | describe OEmbed, "Rails template resolving functions" do
242 | include SpecHelper
243 | before(:each) do
244 | OEmbed.clear_registrations
245 | OEmbed.load_default_libs
246 | clear_urls
247 | url_provides({
248 | "html" => "foo",
249 | "type" => "video",
250 | "url" => "rails"
251 | }.to_json)
252 | OEmbed.register_yaml_file(File.join(File.dirname(__FILE__), "oembed_links_test.yml"))
253 | OEmbed::TemplateResolver.template_processor = nil
254 | @current_path = File.dirname(__FILE__)
255 | @template_path = File.join(@current_path, "templates")
256 |
257 | require 'actionpack'
258 | require 'action_controller'
259 | require 'action_controller/test_process'
260 |
261 | class ::ApplicationController < ActionController::Base
262 |
263 | end
264 | ApplicationController.view_paths += [File.dirname(__FILE__)]
265 | ActiveSupport::Dependencies.mark_for_unload(ApplicationController)
266 | end
267 |
268 | it "should support Rails-like template paths for template selection" do
269 |
270 | OEmbed.transform("http://test1.net/foo") do |r, url|
271 | r.any?(:template => ("templates/test"))
272 | end.should == "rails erb"
273 | end
274 |
275 | it "should support Rails-like template paths with extension specified" do
276 | OEmbed.transform("http://test1.net/foo") do |r, url|
277 | r.any?(:template => "templates/test.rhtml")
278 | end.should == "rails rhtml"
279 | end
280 |
281 | end
282 |
283 |
284 |
285 |
286 |
287 |
--------------------------------------------------------------------------------
/lib/oembed_links.rb:
--------------------------------------------------------------------------------
1 | require 'cgi'
2 | require 'uri'
3 | require 'yaml'
4 | require 'oembed_links/template_resolver'
5 | require 'oembed_links/response'
6 |
7 | # The OEmbed class is the interface to class registration functions
8 | # such as register_provider, register_formatter, etc., as well as
9 | # the seat of the main .transform() function. If you are using OEmbed
10 | # inside a Rails application, the process of initialization will be
11 | # handled for you by the init.rb file. Create a file called
12 | # oembed_links.yml inside your RAILS_ROOT/config directory, giving it
13 | # a format like:
14 | #
15 | # :config:
16 | # :method: "NetHTTP"
17 | #
18 | # :providers:
19 | # :provider_1: "http://provider1.com/oembed.{format}"
20 | # :provider_2: "http://provider2.com/oembed.{format}"
21 | #
22 | # :provider_1:
23 | # :format: "json"
24 | # :schemes:
25 | # - "http://provider1.com/links/*/user/*"
26 | # - "http://provider1.com/photos/*/user/*"
27 | #
28 | # :provider_2:
29 | # :format: "xml"
30 | # :schemes:
31 | # - "http://provider2.com/videos/*"
32 | #
33 | #
34 | # If you are not using the library in a Rails app, you can still create
35 | # a YAML file like above and register it using OEmbed.register_yaml_file("/path/to/file.yml")
36 | #
37 | # You may also programmatically register information into the app using the
38 | # register function, which takes a hash of configuration options, a
39 | # provider hash, and the provider scheme hash.
40 | #
41 | # You may also register providers ad hoc using the OEmbed.register_provider
42 | # function.
43 | #
44 | # To transform text, use the OEmbed.transform function, like:
45 | #
46 | # OEmbed.transform("This is my text and here's a picture http://www.flickr.com/path/to/a/photo")
47 | #
48 | # OEmbed.transform("Same text http://youtube.com/videos/somevideo") do |r, url|
49 | # r.from?(:youtube) { |vid| vid["html"] }
50 | # end
51 | #
52 | # OEmbed.transform("Some more text from http://en.wikipedia.com/wiki/Dinosaurs!") do |r, url|
53 | # r.from?(:wikipedia, :template => "links/wiki_links")
54 | # end
55 | #
56 | # See the OEmbed.transform function for more details.
57 | #
58 | #
59 | # The OEmbed library by default uses net/http, libxml and json libraries for
60 | # fetching network data, parsing xml and parsing json, respectively. These
61 | # libraries are loaded by default.
62 | #
63 | # If you want to write your own mechanism for fetching HTTP data, parsing XML
64 | # data, JSON data, or some other format, see the OEmbed::Fetchers::NetHTTP and
65 | # OEmbed::Formatters::JSON for simple examples in terms of API. Once your new
66 | # class mirrors these classes, you can register it with OEmbed by using
67 | # OEmbed.register_formatter(class) or OEmbed.register_fetcher(class).
68 | #
69 | # NOTE that the default formatters and fetcher are EXTREMELY naive. There is no
70 | # attempt at error handling, connection timeouts, or the like. If you need richer
71 | # functionality you should subclass the existing formatters / fetchers and register them.
72 | #
73 | class OEmbed
74 |
75 | # Configure OEmbed with all necessary information - library configuration,
76 | # oembed provider urls, and the supported schemes and formats of said providers.
77 | #
78 | # The configuration hash should follow the form:
79 | # { :method => "NameOfFetcher" }
80 | # Note that the name of the fetcher is NOT the classname, but the arbitrarily
81 | # chosen name provided by that class' .name() method. By default, it will
82 | # be NetHTTP.
83 | #
84 | # The provider hash will be a hash where the keys are the symbolic names of the
85 | # providers, eg. :vimeo, and the values are the URL strings used to query those providers.
86 | # You may use the substring {format} inside these URLs to indicate that the
87 | # given provider URL requires the format desired to be inserted at that point.
88 | # Whatever format you have configured that provider for in the provider_scheme_hash
89 | # will be inserted when they are queried.
90 | #
91 | # The provider_scheme_hash is a hash with two keys - the first key is the format
92 | # key, which will either be the string "json" or the string "xml". The other
93 | # key will be the schemes key, which contains an array of supported URL schemes
94 | # by the provider.
95 | #
96 | # It is assumed that all hashes passed in use symbols for keys. Do not use string
97 | # keys. This decision is totally arbitrary and without any technical merit.
98 | #
99 | # It is assumed that all provider names are symbols. Same rules as above.
100 | #
101 | def self.register(config_hash = { }, provider_hash = { }, provider_scheme_hash = { })
102 | @fetch_method = (config_hash[:method] || "NetHTTP")
103 | @config = config_hash
104 | provider_hash.each do |provider, url|
105 | config = provider_scheme_hash[provider]
106 | raise "No Schemes were provided for #{provider.to_s}" if config.nil? ||
107 | config[:schemes].nil? ||
108 | config[:schemes].empty?
109 | self.register_provider(provider, url, config[:format] || "json", *config[:schemes])
110 | end
111 | end
112 |
113 | # The configuration hash passed into register() or parsed from the YAML file
114 | def self.config
115 | @config
116 | end
117 |
118 | # Register a provider with OEmbed. The provider name should be a symbol,
119 | # like :flickr. The URL should be a string representing the endpoint
120 | # for that provider, and may include the {format} substring to indicate
121 | # how that provider should be notified of the desired format.
122 | # format is either the string "json", or the string "xml".
123 | # The list of schemes is an array of strings representing the different
124 | # URL schemes supported by the provider. These strings follow the form:
125 | #
126 | # http://*.somedomain.*/*/*
127 | #
128 | # All schemes should use * to indicate variable text matched until the
129 | # next non-* character or end of line.
130 | def self.register_provider(provider, url, format = "json", *schemes)
131 | @schemes ||= [ ]
132 | @urls ||= { }
133 | @formats ||= { }
134 |
135 | @formats[provider] = format
136 | @urls[provider] = url.gsub(/\{format\}/i, format)
137 | schemes.each do |scheme|
138 | sanitized_scheme = scheme.gsub(/([\.\?])/) { |str| "\\#{$1}" }.gsub(/\*/, '.+?')
139 | @schemes << [Regexp.new("^" + sanitized_scheme + "$"), provider]
140 | end
141 | end
142 |
143 | # Loads the YAML file at the specified path and registers
144 | # its information with OEmbed.
145 | def self.register_yaml_file(file)
146 | y = YAML.load(File.read(file))
147 | self.register(y.delete(:config),
148 | y.delete(:providers),
149 | y)
150 | end
151 |
152 | # Clear all registration information; really only valuable in testing
153 | def self.clear_registrations()
154 | @schemes = []
155 | @urls = { }
156 | @formats = { }
157 | @formatters = { }
158 | @fetchers = { }
159 | end
160 |
161 | # Load the default JSON and XML formatters, autodetecting
162 | # formatters when possible; load the default fetcher as well
163 | def self.load_default_libs(*ignore_formats)
164 | self.autodetect_xml_formatters(*ignore_formats)
165 | require 'oembed_links/formatters/json'
166 | self.register_formatter(OEmbed::Formatters::JSON)
167 | require 'oembed_links/fetchers/net_http'
168 | self.register_fetcher(OEmbed::Fetchers::NetHTTP)
169 | end
170 |
171 | # Register a new formatter. klass is the class object of the desired formatter.
172 | # A new instance of klass will be created and stored. This instance MUST
173 | # respond to the methods "name" and "format".
174 | def self.register_formatter(klass)
175 | @formatters ||= { }
176 | inst = klass.new
177 | @formatters[inst.name] = inst
178 | end
179 |
180 | # Register a new fetcher. klass is the class object of the desired fetcher.
181 | # A new instance of klass will be created and stored. This instance MUST
182 | # respond to the methods "name" and "fetch".
183 | def self.register_fetcher(klass)
184 | @fetchers ||= { }
185 | inst = klass.new
186 | @fetchers[inst.name] = inst
187 | end
188 |
189 | # Get the OEmbed::Response object for a given URL and provider. If you wish
190 | # to pass extra attributes to the provider, provide a hash as the last attribute
191 | # with keys and values representing the keys and values of the added querystring
192 | # parameters.
193 | def self.get_url_for_provider(url, provider, *attribs)
194 | purl = @urls[provider]
195 | eurl = CGI.escape(url)
196 | purl += (purl.index("?")) ? "&" : "?"
197 | purl += "url=#{eurl}"
198 | attrib_hash = (attribs.last.is_a?(Hash)) ? attribs.last : { }
199 | attrib_hash.each do |k, v|
200 | purl += "{CGI.escape(k)}=#{CGI.escape(v)}"
201 | end
202 | fetcher = @fetchers[@fetch_method] || @fetchers[@fetchers.keys.first]
203 | formatter = @formatters[@formats[provider]]
204 | response = fetcher.fetch(purl)
205 | formatter.format(response)
206 | end
207 |
208 | # Transform all URLs supported by configured providers by the passed-in
209 | # block or by outputting their "html" attributes ( or "url" attributes
210 | # if no "html" attribute exists ). You may pass in a hash to specify
211 | # extra parameters that should be appended to the querystrings to any
212 | # matching providers (see OEmbed.get_url_for_provider). If you pass a
213 | # block to this method, that block will be executed for each URL
214 | # found in txt that has a matching provider. This block will be passed
215 | # the OEmbed::Response object representing the embedding information for that
216 | # url.
217 | #
218 | # OEmbed.transform supports two additional parameters:
219 | #
220 | # use_strict: Optionally use Ruby's stricter URI detection regex. While
221 | # this will be technically correct regex, not all URLs
222 | # use correct syntax. If this is false, URLs will be detected
223 | # by the incredibly naive approach of finding any instance of
224 | # http:// or https://, and finding anything that is not whitespace
225 | # after that.
226 | #
227 | # Example:
228 | # OEmbed.transform("all my urls are correctly formed", true)
229 | #
230 | # (options hash): This hash is used to append extra querystring parameters
231 | # to the oembed provider. For example:
232 | # OEmbed.transform("blah", false, :max_width => 320, :max_height => 200)
233 | #
234 | # You may fine tune the appearance of the embedding information by using the
235 | # following forms:
236 | #
237 | # OEmbed.transform(some_string) do |r, url|
238 | # r.from?(:provider_name) { |content| content["html"] }
239 | # r.matches?(/some_regex_against_the_url/) { |content| content["title"] }
240 | # r.video?(:template => "videos/oembed_link")
241 | # r.audio? { |audio| content["html"] }
242 | # r.hedgehog?(:template => File.join(File.dirname(__FILE__), "templates", "hedgehogs.haml"))
243 | # r.photo? { |photo| "" }
244 | # r.any? { |anythingelse| content["title"] }
245 | # end
246 | #
247 | # The priority of these conditions is as follows:
248 | # The first matching block for provider (.from?(:provider_name)) takes precendence OVER
249 | # The first matching block for a URL regex (.matches?(/some_regex_against_the_url/)) takes precedence OVER
250 | # The first matching block for a type equivalent (.video?, .audio?, .hedgehog?, .photo?) takes precendence OVER
251 | # The match anything block (.any?)
252 | #
253 | #
254 | #
255 | #
256 | # You do not need to specify an .any? block if you do not intend to perform any special
257 | # transformations upon its data; the OEmbed::Response object will output either its html attribute
258 | # (if it exists) or its url attribute.
259 | #
260 | # The value passed to these conditional blocks is a hash representing the data returned
261 | # by the server. The keys of all the attributes will be strings.
262 | #
263 | # If you specify the :template option, a template will be found for you based on your current engironment.
264 | # Currently there is support for Haml, Erubis and ERB templates. Each template will have the following
265 | # local variables available to it:
266 | #
267 | # url : The URL for which OEmbed data exists
268 | # data : A hash of the actual OEmbed data for that URL
269 | # response : The OEmbed::Response object for the URL
270 | #
271 | #
272 | # If you are using Rails, you may specify your template relative to your application's
273 | # view root (eg "photos/flickr_oembed"), and your template will be found based on your application settings.
274 | # For more options regarding template support, see the documentation for OEmbed::TemplateResolver.
275 | #
276 | # NOTE: The type equivalent blocks (.video?, .audio?, .hedgehog?, .photo?, etc.) perform
277 | # an equality test between the method name and the type returned by the OEmbed provider.
278 | # You may specify any type name you wish as the method name, and its type will be checked
279 | # appropriately (as shown by the obviously trivial .hedgehog? method name).
280 | #
281 | def self.transform(txt, use_strict = false, *attribs, &block)
282 | ret = txt.dup
283 |
284 | if use_strict
285 | URI.extract(txt, "http") do |u|
286 | transform_url_for_text!(u, ret, *attribs, &block)
287 | end
288 | else
289 | simple_extract(txt) do |u|
290 | transform_url_for_text!(u, ret, *attribs, &block)
291 | end
292 | end
293 |
294 | return ret
295 | end
296 |
297 | # Determine the XML formatter that can be loaded for
298 | # this system based on what libraries are present
299 | def self.autodetect_xml_formatters(*ignore)
300 | loaded_lib = false
301 | unless ignore.include? "libxml"
302 | begin
303 | require 'libxml'
304 | require 'oembed_links/formatters/lib_xml'
305 | self.register_formatter(OEmbed::Formatters::LibXML)
306 | loaded_lib = true
307 | rescue LoadError
308 | # Silently fail: LibXML XML formatter not found
309 | end
310 | end
311 | unless loaded_lib || ignore.include?("hpricot")
312 | begin
313 | require 'hpricot'
314 | require 'oembed_links/formatters/hpricot_xml'
315 | self.register_formatter(OEmbed::Formatters::HpricotXML)
316 | loaded_lib = true
317 | rescue LoadError
318 | # Silently fail: Hpricot XML formatter not found
319 | end
320 | end
321 | unless loaded_lib || ignore.include?("rexml")
322 | require 'oembed_links/formatters/ruby_xml'
323 | self.register_formatter(OEmbed::Formatters::RubyXML)
324 | loaded_lib = true
325 | end
326 | raise StandardError.new("No XML formatter could be autodetected") unless loaded_lib
327 | end
328 |
329 | private
330 |
331 | # stupid simple copy of URI.extract to allow for looser URI detection
332 | def self.simple_extract(str, &block)
333 | reg = /(https?:\/\/[^\s]+)/i
334 | if block_given?
335 | str.scan(reg) { yield $& }
336 | nil
337 | else
338 | result = []
339 | str.scan(reg) { result.push $& }
340 | result
341 | end
342 | end
343 |
344 | # extraction of inner loop of .transform(), to allow for easier
345 | # parameterization of OEmbed
346 | def self.transform_url_for_text!(u, txt, *attribs, &block)
347 | unless (vschemes = @schemes.select { |a| u =~ a[0] }).empty?
348 | regex, provider = vschemes.first
349 | data = get_url_for_provider(u, provider, *attribs)
350 | response = OEmbed::Response.new(provider, u, data)
351 | if block.nil?
352 | txt.gsub!(u, response.to_s)
353 | else
354 | yield(response, u)
355 | (response.has_rendered?) ? txt.gsub!(u, response.rendered_content) : txt
356 | end
357 | else
358 | if block.nil?
359 | txt
360 | else
361 | response = OEmbed::Response.new("", u, {})
362 | yield(response, u)
363 | (response.has_rendered?) ? txt.gsub!(u, response.rendered_content) : txt
364 | end
365 | end
366 | end
367 | end
368 |
369 |
370 | OEmbed.load_default_libs
371 |
372 |
--------------------------------------------------------------------------------