netshade-oembed_links 0.0.3

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/README ADDED
@@ -0,0 +1,68 @@
1
+ This is the oembed_links gem. It allows you to easily parse text and
2
+ query configured providers for embedding information on the links
3
+ inside the text. A sample configuration file for configuring the
4
+ library has been included (oembed_links_example.yml), though you
5
+ may also configure the library programmatically (see rdocs).
6
+
7
+
8
+
9
+ To get started quickly (in irb):
10
+
11
+ require 'oembed_links'
12
+ OEmbed.register({:method => "NetHTTP"},
13
+ {:flickr => "http://www.flickr.com/services/oembed/",
14
+ :vimeo => "http://www.vimeo.com/api/oembed.{format}"},
15
+ {:flickr => { :format => "xml", :schemes => ["http://www.flickr.com/photos/*"]},
16
+ :vimeo => { :format => "json", :schemes => ["http://www.vimeo.com/*"]}})
17
+
18
+ # Simple transformation
19
+ OEmbed.transform("This is my flickr URL http://www.flickr.com/photos/bees/2341623661/ and all I did was show the URL straight to the picture")
20
+
21
+ # More complex transformation
22
+ OEmbed.transform("This is my flickr URL http://www.flickr.com/photos/bees/2341623661/ and this is a vimeo URL http://www.vimeo.com/757219 wow neat") do |r, url|
23
+ r.audio? { |a| "It's unlikely flickr or vimeo will give me audio" }
24
+ r.photo? { |p| "<img src='#{p["url"]}' alt='Sweet, a photo named #{p["title"]}' />" }
25
+ r.from?(:vimeo) { |v| "<div class='vimeo'>#{v['html']}</div>" }
26
+ end
27
+
28
+ # Transformation to drive affiliate links to Amazon to our department and help us buy some laptops (hint)
29
+ OEmbed.register_provider(:oohembed,
30
+ "http://oohembed.com/oohembed/",
31
+ "json",
32
+ "http://*.amazon.(com|co.uk|de|ca|jp)/*/(gp/product|o/ASIN|obidos/ASIN|dp)/*",
33
+ "http://*.amazon.(com|co.uk|de|ca|jp)/(gp/product|o/ASIN|obidos/ASIN|dp)/*")
34
+ OEmbed.transform("Here is a link to amazon http://www.amazon.com/Complete-Aubrey-Maturin-Novels/dp/039306011X/ref=pd_bbs_sr_2 wow") do |res, url|
35
+ res.matches?(/amazon/) { |d|
36
+ unless url =~ /(&|\?)tag=[^&]+/i
37
+ url += ((url.index("?")) ? "&" : "?")
38
+ url += "tag=wwwindystarco-20"
39
+ end
40
+ <<-EOHTML
41
+ <div style="text-align:center;">
42
+ <a href='#{url}' target='_blank'>
43
+ <img src='#{d['thumbnail_url']}' border='0' /><br />
44
+ #{d['title']} #{"<br />by #{d['author']}" if d['author']}
45
+ </a>
46
+ </div>
47
+ EOHTML
48
+ }
49
+ end
50
+
51
+
52
+ To get started quickly in Rails:
53
+
54
+ Copy the included oembed_links_example.yml file to RAILS_ROOT/config/oembed_links.yml,
55
+ add a dependency to the gem in your environment.rb ( config.gem "oembed_links" )
56
+ and start your server. That's it.
57
+
58
+
59
+
60
+
61
+ See the rdocs for much more complete examples. The specs directory has some examples of programmatic
62
+ use, but the test to code ratio is slim atm.
63
+
64
+ Thanks to the Indianapolis Star I&D department for open sourcing this; most notably Chris Vannoy for giving the okay.
65
+
66
+
67
+ CZ - chris.zelenak!at!!indystar.com
68
+
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ Gem::manage_gems
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+ CLEAN.include("pkg")
6
+
7
+ spec = eval(File.read("oembed_links.gemspec")) # I'm going to hell, etc. etc.
8
+
9
+ task :default => [:clean, :repackage]
10
+
11
+ Rake::GemPackageTask.new(spec) do |pkg|
12
+ pkg.need_tar = true
13
+ end
14
+
@@ -0,0 +1,19 @@
1
+ require 'net/http'
2
+
3
+ class OEmbed
4
+ module Fetchers
5
+ class NetHTTP
6
+
7
+ def name
8
+ "NetHTTP"
9
+ end
10
+
11
+ def fetch(url)
12
+ Net::HTTP.get(URI.parse(url))
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+
19
+ OEmbed.register_fetcher(OEmbed::Fetchers::NetHTTP)
@@ -0,0 +1,18 @@
1
+ require 'json'
2
+
3
+ class OEmbed
4
+ module Formatters
5
+ class JSON
6
+
7
+ def name
8
+ "json"
9
+ end
10
+
11
+ def format(txt)
12
+ ::JSON.parse(txt)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ OEmbed.register_formatter(OEmbed::Formatters::JSON)
@@ -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
+ OEmbed.register_formatter(OEmbed::Formatters::LibXML)
@@ -0,0 +1,102 @@
1
+ # The class used to represent data returned by the server.
2
+ #
3
+ class OEmbed
4
+ class Response
5
+
6
+ def initialize(provider, url, response_object)
7
+ @provider = provider
8
+ @url = url
9
+ @response = response_object
10
+ @rendered_via_provider = @rendered_via_regex = @rendered_via_type = false
11
+ @rendered = nil
12
+ end
13
+
14
+ def to_s
15
+ @response["html"] || @response["url"]
16
+ end
17
+
18
+ # If no content has been explicitly rendered for this Response,
19
+ # the default representation of the data will be returned.
20
+ def rendered_content
21
+ @rendered || self.to_s
22
+ end
23
+
24
+ # Test if this response has been returned from
25
+ # the given provider_name.
26
+ def from?(provider_name, &block)
27
+ if @provider.to_s === provider_name.to_s
28
+ if can_render_type?(:provider)
29
+ @rendered_via_provider = true
30
+ return render_content(&block)
31
+ end
32
+ end
33
+ end
34
+
35
+ # Test if this response came from a URL
36
+ # that matches the given regex.
37
+ def matches?(regex, &block)
38
+ if @url =~ regex
39
+ if can_render_type?(:regex)
40
+ @rendered_via_regex = true
41
+ render_content(&block)
42
+ end
43
+ end
44
+ end
45
+
46
+ # Lowest priority renderer, which will execute
47
+ # a block regardless of conditions so long as
48
+ # no content has yet been rendered for this response.
49
+ def any?(&block)
50
+ if can_render_type?
51
+ return render_content(&block)
52
+ end
53
+ end
54
+
55
+ # Provides the mechanism to allow .audio?, .video?
56
+ # and other .type? checking methods. The value of the
57
+ # method name will be compared against the "type" field
58
+ # from the returned server data.
59
+ def method_missing(msym, *args, &block)
60
+ mname = msym.to_s
61
+ if mname[mname.size - 1, mname.size] == "?"
62
+ ts = mname[0..mname.size - 2]
63
+ if @response["type"] == ts
64
+ if can_render_type?(:type)
65
+ @rendered_via_type = true
66
+ return render_content(&block)
67
+ end
68
+ end
69
+ else
70
+ raise NoMethodError.new("No such method #{msym.to_s}", msym, *args)
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ # Needlessly stupid priority for rendering.
77
+ def can_render_type?(type = nil)
78
+ if type == :provider
79
+ !@rendered_via_provider
80
+ elsif type == :regex
81
+ !@rendered_via_provider && !@rendered_via_regex
82
+ elsif type == :type
83
+ !@rendered_via_provider && !@rendered_via_regex && !@rendered_via_type
84
+ else
85
+ !has_rendered?
86
+ end
87
+ end
88
+
89
+ def has_rendered?
90
+ !@rendered.nil?
91
+ end
92
+
93
+ def render_content(&block)
94
+ if block_given?
95
+ @rendered = yield(@response)
96
+ else
97
+ @rendered = self.to_s
98
+ end
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,307 @@
1
+ require 'cgi'
2
+ require 'uri'
3
+ require 'yaml'
4
+ require 'oembed_links/response'
5
+
6
+ # The OEmbed class is the interface to class registration functions
7
+ # such as register_provider, register_formatter, etc., as well as
8
+ # the seat of the main .transform() function. If you are using OEmbed
9
+ # inside a Rails application, the process of initialization will be
10
+ # handled for you by the init.rb file. Create a file called
11
+ # oembed_links.yml inside your RAILS_ROOT/config directory, giving it
12
+ # a format like:
13
+ #
14
+ # :config:
15
+ # :method: "NetHTTP"
16
+ #
17
+ # :providers:
18
+ # :provider_1: "http://provider1.com/oembed.{format}"
19
+ # :provider_2: "http://provider2.com/oembed.{format}"
20
+ #
21
+ # :provider_1:
22
+ # :format: "json"
23
+ # :schemes:
24
+ # - "http://provider1.com/links/*/user/*"
25
+ # - "http://provider1.com/photos/*/user/*"
26
+ #
27
+ # :provider_2:
28
+ # :format: "xml"
29
+ # :schemes:
30
+ # - "http://provider2.com/videos/*"
31
+ #
32
+ #
33
+ # If you are not using the library in a Rails app, you can still create
34
+ # a YAML file like above and register it using OEmbed.register_yaml_file("/path/to/file.yml")
35
+ #
36
+ # You may also programmatically register information into the app using the
37
+ # register function, which takes a hash of configuration options, a
38
+ # provider hash, and the provider scheme hash.
39
+ #
40
+ # You may also register providers ad hoc using the OEmbed.register_provider
41
+ # function.
42
+ #
43
+ # To transform text, use the OEmbed.transform function, like:
44
+ #
45
+ # OEmbed.transform("This is my text and here's a picture http://www.flickr.com/path/to/a/photo")
46
+ #
47
+ # OEmbed.transform("Same text http://youtube.com/videos/somevideo") do |r, url|
48
+ # r.from?(:youtube) { |vid| vid["html"] }
49
+ # end
50
+ #
51
+ # See the OEmbed.transform function for more details.
52
+ #
53
+ #
54
+ # The OEmbed library by default uses net/http, libxml and json libraries for
55
+ # fetching network data, parsing xml and parsing json, respectively. These
56
+ # libraries are loaded by default.
57
+ #
58
+ # If you want to write your own mechanism for fetching HTTP data, parsing XML
59
+ # data, JSON data, or some other format, see the OEmbed::Fetchers::NetHTTP and
60
+ # OEmbed::Formatters::JSON for simple examples in terms of API. Once your new
61
+ # class mirrors these classes, you can register it with OEmbed by using
62
+ # OEmbed.register_formatter(class) or OEmbed.register_fetcher(class).
63
+ #
64
+ # NOTE that the default formatters and fetcher are EXTREMELY naive. There is no
65
+ # attempt at error handling, connection timeouts, or the like. If you need richer
66
+ # functionality you should subclass the existing formatters / fetchers and register them.
67
+ #
68
+ class OEmbed
69
+
70
+ # Configure OEmbed with all necessary information - library configuration,
71
+ # oembed provider urls, and the supported schemes and formats of said providers.
72
+ #
73
+ # The configuration hash should follow the form:
74
+ # { :method => "NameOfFetcher" }
75
+ # Note that the name of the fetcher is NOT the classname, but the arbitrarily
76
+ # chosen name provided by that class' .name() method. By default, it will
77
+ # be NetHTTP.
78
+ #
79
+ # The provider hash will be a hash where the keys are the symbolic names of the
80
+ # providers, eg. :vimeo, and the values are the URL strings used to query those providers.
81
+ # You may use the substring {format} inside these URLs to indicate that the
82
+ # given provider URL requires the format desired to be inserted at that point.
83
+ # Whatever format you have configured that provider for in the provider_scheme_hash
84
+ # will be inserted when they are queried.
85
+ #
86
+ # The provider_scheme_hash is a hash with two keys - the first key is the format
87
+ # key, which will either be the string "json" or the string "xml". The other
88
+ # key will be the schemes key, which contains an array of supported URL schemes
89
+ # by the provider.
90
+ #
91
+ # It is assumed that all hashes passed in use symbols for keys. Do not use string
92
+ # keys. This decision is totally arbitrary and without any technical merit.
93
+ #
94
+ # It is assumed that all provider names are symbols. Same rules as above.
95
+ #
96
+ def self.register(config_hash = { }, provider_hash = { }, provider_scheme_hash = { })
97
+ @fetch_method = (config_hash[:method] || "NetHTTP")
98
+ @config = config_hash
99
+ provider_hash.each do |provider, url|
100
+ config = provider_scheme_hash[provider]
101
+ raise "No Schemes were provided for #{provider.to_s}" if config.nil? ||
102
+ config[:schemes].nil? ||
103
+ config[:schemes].empty?
104
+ self.register_provider(provider, url, config[:format] || "json", *config[:schemes])
105
+ end
106
+ end
107
+
108
+ # The configuration hash passed into register() or parsed from the YAML file
109
+ def self.config
110
+ @config
111
+ end
112
+
113
+ # Register a provider with OEmbed. The provider name should be a symbol,
114
+ # like :flickr. The URL should be a string representing the endpoint
115
+ # for that provider, and may include the {format} substring to indicate
116
+ # how that provider should be notified of the desired format.
117
+ # format is either the string "json", or the string "xml".
118
+ # The list of schemes is an array of strings representing the different
119
+ # URL schemes supported by the provider. These strings follow the form:
120
+ #
121
+ # http://*.somedomain.*/*/*
122
+ #
123
+ # All schemes should use * to indicate variable text matched until the
124
+ # next non-* character or end of line.
125
+ def self.register_provider(provider, url, format = "json", *schemes)
126
+ @schemes ||= [ ]
127
+ @urls ||= { }
128
+ @formats ||= { }
129
+
130
+ @formats[provider] = format
131
+ @urls[provider] = url.gsub(/\{format\}/i, format)
132
+ schemes.each do |scheme|
133
+ sanitized_scheme = scheme.gsub(/([\.\?])/) { |str| "\\#{$1}" }.gsub(/\*/, '.+?')
134
+ @schemes << [Regexp.new("^" + sanitized_scheme + "$"), provider]
135
+ end
136
+ end
137
+
138
+ # Loads the YAML file at the specified path and registers
139
+ # its information with OEmbed.
140
+ def self.register_yaml_file(file)
141
+ y = YAML.load(File.read(file))
142
+ self.register(y.delete(:config),
143
+ y.delete(:providers),
144
+ y)
145
+ end
146
+
147
+ # Clear all registration information; really only valuable in testing
148
+ def self.clear_registrations
149
+ @schemes = []
150
+ @urls = { }
151
+ @formats = { }
152
+ @formatters = { }
153
+ @fetchers = { }
154
+ self.register_formatter(OEmbed::Formatters::LibXML)
155
+ self.register_formatter(OEmbed::Formatters::JSON)
156
+ self.register_fetcher(OEmbed::Fetchers::NetHTTP)
157
+ end
158
+
159
+ # Register a new formatter. klass is the class object of the desired formatter.
160
+ # A new instance of klass will be created and stored. This instance MUST
161
+ # respond to the methods "name" and "format".
162
+ def self.register_formatter(klass)
163
+ @formatters ||= { }
164
+ inst = klass.new
165
+ @formatters[inst.name] = inst
166
+ end
167
+
168
+ # Register a new fetcher. klass is the class object of the desired fetcher.
169
+ # A new instance of klass will be created and stored. This instance MUST
170
+ # respond to the methods "name" and "fetch".
171
+ def self.register_fetcher(klass)
172
+ @fetchers ||= { }
173
+ inst = klass.new
174
+ @fetchers[inst.name] = inst
175
+ end
176
+
177
+ # Get the OEmbed::Response object for a given URL and provider. If you wish
178
+ # to pass extra attributes to the provider, provide a hash as the last attribute
179
+ # with keys and values representing the keys and values of the added querystring
180
+ # parameters.
181
+ def self.get_url_for_provider(url, provider, *attribs)
182
+ purl = @urls[provider]
183
+ eurl = CGI.escape(url)
184
+ purl += (purl.index("?")) ? "&" : "?"
185
+ purl += "url=#{eurl}"
186
+ attrib_hash = (attribs.last.is_a?(Hash)) ? attribs.last : { }
187
+ attrib_hash.each do |k, v|
188
+ purl += "&#{CGI.escape(k)}=#{CGI.escape(v)}"
189
+ end
190
+ fetcher = @fetchers[@fetch_method] || @fetchers[@fetchers.keys.first]
191
+ formatter = @formatters[@formats[provider]]
192
+ response = fetcher.fetch(purl)
193
+ formatter.format(response)
194
+ end
195
+
196
+ # Transform all URLs supported by configured providers by the passed-in
197
+ # block or by outputting their "html" attributes ( or "url" attributes
198
+ # if no "html" attribute exists ). You may pass in a hash to specify
199
+ # extra parameters that should be appended to the querystrings to any
200
+ # matching providers (see OEmbed.get_url_for_provider). If you pass a
201
+ # block to this method, that block will be executed for each URL
202
+ # found in txt that has a matching provider. This block will be passed
203
+ # the OEmbed::Response object representing the embedding information for that
204
+ # url.
205
+ #
206
+ # OEmbed.transform supports two additional parameters:
207
+ #
208
+ # use_strict: Optionally use Ruby's stricter URI detection regex. While
209
+ # this will be technically correct regex, not all URLs
210
+ # use correct syntax. If this is false, URLs will be detected
211
+ # by the incredibly naive approach of finding any instance of
212
+ # http:// or https://, and finding anything that is not whitespace
213
+ # after that.
214
+ #
215
+ # Example:
216
+ # OEmbed.transform("all my urls are correctly formed", true)
217
+ #
218
+ # (options hash): This hash is used to append extra querystring parameters
219
+ # to the oembed provider. For example:
220
+ # OEmbed.transform("blah", false, :max_width => 320, :max_height => 200)
221
+ #
222
+ # You may fine tune the appearance of the embedding information by using the
223
+ # following forms:
224
+ #
225
+ # OEmbed.transform(some_string) do |r, url|
226
+ # r.from?(:provider_name) { |content| content["html"] }
227
+ # r.matches?(/some_regex_against_the_url/) { |content| content["title"] }
228
+ # r.video? { |video| content["html"] }
229
+ # r.audio? { |audio| content["html"] }
230
+ # r.hedgehog? { |hog| content["title"] }
231
+ # r.photo? { |photo| "<img src='#{photo["url"]}' title='#{photo['title']} />" }
232
+ # r.any? { |anythingelse| content["title"] }
233
+ # end
234
+ #
235
+ # The priority of these conditions is as follows:
236
+ # The first matching block for provider (.from?(:provider_name)) takes precendence OVER
237
+ # The first matching block for a URL regex (.matches?(/some_regex_against_the_url/)) takes precedence OVER
238
+ # The first matching block for a type equivalent (.video?, .audio?, .hedgehog?, .photo?) takes precendence OVER
239
+ # The match anything block (.any?)
240
+ #
241
+ #
242
+ #
243
+ #
244
+ # You do not need to specify an .any? block if you do not intend to perform any special
245
+ # transformations upon its data; the OEmbed::Response object will output either its html attribute
246
+ # (if it exists) or its url attribute.
247
+ #
248
+ # The value passed to these conditional blocks is a hash representing the data returned
249
+ # by the server. The keys of all the attributes will be strings.
250
+ #
251
+ # NOTE: The type equivalent blocks (.video?, .audio?, .hedgehog?, .photo?, etc.) perform
252
+ # an equality test between the method name and the type returned by the OEmbed provider.
253
+ # You may specify any type name you wish as the method name, and its type will be checked
254
+ # appropriately (as shown by the obviously trivial .hedgehog? method name).
255
+ #
256
+ def self.transform(txt, use_strict = false, *attribs, &block)
257
+ ret = txt.dup
258
+
259
+ if use_strict
260
+ URI.extract(txt, "http") do |u|
261
+ transform_url_for_text!(u, ret, *attribs, &block)
262
+ end
263
+ else
264
+ simple_extract(txt) do |u|
265
+ transform_url_for_text!(u, ret, *attribs, &block)
266
+ end
267
+ end
268
+
269
+ return ret
270
+ end
271
+
272
+ private
273
+
274
+ # stupid simple copy of URI.extract to allow for looser URI detection
275
+ def self.simple_extract(str, &block)
276
+ reg = /(https?:\/\/[^\s]+)/i
277
+ if block_given?
278
+ str.scan(reg) { yield $& }
279
+ nil
280
+ else
281
+ result = []
282
+ str.scan(reg) { result.push $& }
283
+ result
284
+ end
285
+ end
286
+
287
+ # extraction of inner loop of .transform(), to allow for easier
288
+ # parameterization of OEmbed
289
+ def self.transform_url_for_text!(u, txt, *attribs, &block)
290
+ unless (vschemes = @schemes.select { |a| u =~ a[0] }).empty?
291
+ regex, provider = vschemes.first
292
+ data = get_url_for_provider(u, provider, *attribs)
293
+ response = OEmbed::Response.new(provider, u, data)
294
+ if block.nil?
295
+ txt.gsub!(u, response.to_s)
296
+ else
297
+ yield(response, u)
298
+ txt.gsub!(u, response.rendered_content)
299
+ end
300
+ end
301
+ end
302
+
303
+
304
+ end
305
+ require 'oembed_links/formatters/json'
306
+ require 'oembed_links/formatters/xml'
307
+ require 'oembed_links/fetchers/net_http'
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "oembed_links"
3
+ s.version = "0.0.3"
4
+ s.author = "Indianapolis Star"
5
+ s.email = "bugs at indystar dot com"
6
+ s.homepage = "http://www.indystar.com"
7
+ s.platform = Gem::Platform::RUBY
8
+ s.summary = "a library for using the OEmbed format (http://oembed.com/) to acquire embedding information for freetext"
9
+ s.files = ["Rakefile", "README", "oembed_links_example.yml", "oembed_links.gemspec", "lib", "lib/oembed_links.rb", "lib/oembed_links", "lib/oembed_links/formatters", "lib/oembed_links/fetchers", "lib/oembed_links/response.rb", "lib/oembed_links/formatters/json.rb", "lib/oembed_links/formatters/xml.rb", "lib/oembed_links/fetchers/net_http.rb", "rails", "rails/init.rb", "spec", "spec/spec_helper.rb", "spec/oembed_links_spec.rb", "spec/oembed_links_test.yml" ]
10
+ s.require_path = "lib"
11
+ s.has_rdoc = true
12
+ s.extra_rdoc_files = ['README']
13
+ s.add_dependency(%q<json>)
14
+ s.add_dependency(%q<libxml-ruby>)
15
+ end
@@ -0,0 +1,40 @@
1
+ :config:
2
+ :method: "NetHTTP"
3
+
4
+ :providers:
5
+ :oohembed: "http://oohembed.com/oohembed/"
6
+ :vimeo: "http://www.vimeo.com/api/oembed.{format}"
7
+ :hulu: "http://www.hulu.com/api/oembed.{format}"
8
+ :flickr: "http://www.flickr.com/services/oembed"
9
+
10
+ :oohembed:
11
+ :format: "json"
12
+ :schemes:
13
+ - "http://*.amazon.(com|co.uk|de|ca|jp)/*/(gp/product|o/ASIN|obidos/ASIN|dp)/*"
14
+ - "http://*.amazon.(com|co.uk|de|ca|jp)/(gp/product|o/ASIN|obidos/ASIN|dp)/*"
15
+ - "http://*.collegehumor.com/video:*"
16
+ - "http://*.funnyordie.com/videos/*"
17
+ - "http://video.google.com/videoplay?*"
18
+ - "http://*.imdb.com/title/tt*/"
19
+ - "http://*.metacafe.com/watch/*"
20
+ - "http://*.slideshare.net/*"
21
+ - "http://twitter.com/*/statuses/*"
22
+ - "http://*.wikipedia.org/wiki/*"
23
+ - "http://*.wordpress.com/yyyy/mm/dd/*"
24
+ - "http://*.youtube.com/watch*"
25
+
26
+ :vimeo:
27
+ :format: "json"
28
+ :schemes:
29
+ - "http://www.vimeo.com/groups/*/*"
30
+ - "http://www.vimeo.com/*"
31
+
32
+ :hulu:
33
+ :format: "xml"
34
+ :schemes:
35
+ - "http://www.hulu.com/watch/*"
36
+
37
+ :flickr:
38
+ :format: "xml"
39
+ :schemes:
40
+ - "http://*.flickr.com/*"
data/rails/init.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'oembed_links'
2
+
3
+ yaml_file = File.join(RAILS_ROOT, "config", "oembed_links.yml")
4
+ if File.exists?(yaml_file)
5
+ OEmbed::register_yaml_file(yaml_file)
6
+ end
7
+
@@ -0,0 +1,128 @@
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
+ clear_urls
9
+ end
10
+
11
+ it "should default to NetHTTP if no method is specified in configuration" do
12
+ OEmbed.register()
13
+ OEmbed.instance_variable_get("@fetch_method").should == "NetHTTP"
14
+ end
15
+
16
+ it "should throw an error if you provide provider URLs but no scheme or format information" do
17
+ lambda { OEmbed.register({ }, { :fake => "http://fake" })}.should raise_error
18
+ end
19
+
20
+ it "should throw an error if you don't provide any scheme urls for registration" do
21
+ lambda { OEmbed.register({ }, { :fake => "http://fake" }, { :fake => { :format => "json", :schemes => []}})}.should raise_error
22
+ end
23
+
24
+ it "should default to json format if none is specified" do
25
+ OEmbed.register({ }, { :fake => "http://fake" }, { :fake => { :schemes => ["http://fake/*"]}})
26
+ OEmbed.instance_variable_get("@formats")[:fake].should == "json"
27
+ end
28
+
29
+ it "should support loading a configuration via YAML" do
30
+ OEmbed.register_yaml_file(File.join(File.dirname(__FILE__), "oembed_links_test.yml"))
31
+ OEmbed.instance_variable_get("@urls").size.should == 3
32
+ end
33
+
34
+ it "should support ad hoc addition of providers" do
35
+ OEmbed.register_yaml_file(File.join(File.dirname(__FILE__), "oembed_links_test.yml"))
36
+ OEmbed.instance_variable_get("@urls").size.should == 3
37
+ OEmbed.register_provider(:test4, "http://test4/oembed.{format}", "xml", "http://test4.*/*", "http://test4.*/foo/*")
38
+ OEmbed.instance_variable_get("@urls").size.should == 4
39
+ end
40
+
41
+ it "should support adding new fetchers" do
42
+
43
+ OEmbed.register_fetcher(FakeFetcher)
44
+ OEmbed.register({ :method => "fake_fetcher"},
45
+ { :fake => "http://fake" },
46
+ { :fake => {
47
+ :format => "json",
48
+ :schemes => "http://fake/*"
49
+ }})
50
+ OEmbed.transform("http://fake/bar/baz").should == "fakecontent"
51
+ end
52
+
53
+ it "should support adding new formatters" do
54
+ OEmbed.register_formatter(FakeFormatter)
55
+ OEmbed.register({ :method => "fake_fetcher"},
56
+ { :fake => "http://fake" },
57
+ { :fake => {
58
+ :format => "fake_formatter",
59
+ :schemes => "http://fake/*"
60
+ }})
61
+ url_provides("")
62
+ OEmbed.transform("http://fake/bar/baz").should == "http://fakesville"
63
+ end
64
+
65
+ end
66
+
67
+ describe OEmbed, "transforming functions" do
68
+ include SpecHelper
69
+ before(:each) do
70
+ OEmbed.clear_registrations
71
+ clear_urls
72
+ url_provides({
73
+ "html" => "foo",
74
+ "type" => "video"
75
+ }.to_json)
76
+ OEmbed.register_yaml_file(File.join(File.dirname(__FILE__), "oembed_links_test.yml"))
77
+ end
78
+
79
+ it "should always give priority to provider conditional blocks" do
80
+ OEmbed.transform("http://test1.net/foo") do |r, url|
81
+ r.any? { |a| "any" }
82
+ r.video? { |v| "video" }
83
+ r.from?(:test1) { |t| "test1" }
84
+ r.matches?(/./) { |m| "regex" }
85
+ end.should == "test1"
86
+ end
87
+
88
+ it "should always give priority regex conditional blocks over all others except provider" do
89
+ OEmbed.transform("http://test1.net/foo") do |r, url|
90
+ r.any? { |a| "any" }
91
+ r.video? { |v| "video" }
92
+ r.matches?(/./) { |m| "regex" }
93
+ end.should == "regex"
94
+ OEmbed.transform("http://test1.net/foo") do |r, url|
95
+ r.matches?(/./) { |m| "regex" }
96
+ r.any? { |a| "any" }
97
+ r.video? { |v| "video" }
98
+ end.should == "regex"
99
+ end
100
+
101
+ it "should recognize the type of content and handle the conditional block appropriately" do
102
+ OEmbed.transform("http://test1.net/foo") do |r, url|
103
+ r.any? { |a| "any" }
104
+ r.video? { |v| "video" }
105
+ end.should == "video"
106
+ url_provides({
107
+ "html" => "bar",
108
+ "type" => "hedgehog"
109
+ }.to_json)
110
+ OEmbed.transform("http://test1.net/foo") do |r, url|
111
+ r.video? { |v| "video" }
112
+ r.hedgehog? { |v| "hedgey"}
113
+ end.should == "hedgey"
114
+ end
115
+
116
+ it "should still output the content of a url if no transforming blocks match it" do
117
+ OEmbed.transform("http://test1.net/foo") do |r, url|
118
+ r.audio? { |a| "audio" }
119
+ r.hedgehog? { |v| "hedgey"}
120
+ r.from?(:test2) { |t| "test2" }
121
+ r.matches?(/baz/) { |m| "regex" }
122
+ end.should == "foo"
123
+ end
124
+
125
+
126
+ end
127
+
128
+
@@ -0,0 +1,26 @@
1
+ :config:
2
+ :method: "NetHTTP"
3
+
4
+ :providers:
5
+ :test1: "http://test1/dude/{format}/"
6
+ :test2: "http://test2.{format}"
7
+ :test3: "http://test3"
8
+
9
+
10
+ :test1:
11
+ :format: "json"
12
+ :schemes:
13
+ - "http://test1.*/*"
14
+ - "http://test1/*/test/*"
15
+
16
+ :test2:
17
+ :format: "xml"
18
+ :schemes:
19
+ - "http://test2.*/*/stuff/*"
20
+ - "http://test2/foo/bar/*"
21
+
22
+ :test3:
23
+ :format: "json"
24
+ :schemes:
25
+ - "http://test3/foo/*"
26
+
@@ -0,0 +1,62 @@
1
+ $: << File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'oembed_links'
3
+
4
+ module SpecHelper
5
+
6
+ def url_provides(content)
7
+ Net::HTTP.fake_content(content)
8
+ end
9
+
10
+ def clear_urls
11
+ Net::HTTP.clear_fakes
12
+ end
13
+
14
+ end
15
+
16
+ require 'net/http'
17
+ module Net
18
+ class HTTP
19
+
20
+ def self.fake_content(content)
21
+ @content = content
22
+ end
23
+
24
+
25
+ def self.clear_fakes
26
+ @content = nil
27
+ end
28
+
29
+ def self.get(uri)
30
+ return @content
31
+ end
32
+
33
+ end
34
+ end
35
+
36
+
37
+ require 'json'
38
+ class FakeFetcher
39
+ def name
40
+ "fake_fetcher"
41
+ end
42
+
43
+ def fetch(url)
44
+ {
45
+ "url" => "fakecontent"
46
+ }.to_json
47
+ end
48
+ end
49
+
50
+ class FakeFormatter
51
+ def name
52
+ "fake_formatter"
53
+ end
54
+
55
+ def format(txt)
56
+ {
57
+ "url" => "http://fakesville"
58
+ }
59
+ end
60
+ end
61
+
62
+
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: netshade-oembed_links
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Indianapolis Star
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-07-08 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: json
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: libxml-ruby
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0"
32
+ version:
33
+ description:
34
+ email: bugs at indystar dot com
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - README
41
+ files:
42
+ - Rakefile
43
+ - README
44
+ - oembed_links_example.yml
45
+ - oembed_links.gemspec
46
+ - lib
47
+ - lib/oembed_links.rb
48
+ - lib/oembed_links
49
+ - lib/oembed_links/formatters
50
+ - lib/oembed_links/fetchers
51
+ - lib/oembed_links/response.rb
52
+ - lib/oembed_links/formatters/json.rb
53
+ - lib/oembed_links/formatters/xml.rb
54
+ - lib/oembed_links/fetchers/net_http.rb
55
+ - rails
56
+ - rails/init.rb
57
+ - spec
58
+ - spec/spec_helper.rb
59
+ - spec/oembed_links_spec.rb
60
+ - spec/oembed_links_test.yml
61
+ has_rdoc: true
62
+ homepage: http://www.indystar.com
63
+ post_install_message:
64
+ rdoc_options: []
65
+
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "0"
73
+ version:
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ version:
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 1.2.0
84
+ signing_key:
85
+ specification_version: 2
86
+ summary: a library for using the OEmbed format (http://oembed.com/) to acquire embedding information for freetext
87
+ test_files: []
88
+