murlsh 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -302,6 +302,7 @@ begin
302
302
  htmlentities 4.2.0
303
303
  json 1.2.3
304
304
  rack 1.0.0
305
+ rack-cache 0.5.2
305
306
  sqlite3-ruby 1.2.1
306
307
  }.each_slice(2) { |g,v| gemspec.add_dependency(g, ">= #{v}") }
307
308
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.8.0
data/config.ru CHANGED
@@ -3,16 +3,29 @@ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
3
3
  %w{
4
4
  yaml
5
5
 
6
+ rack/cache
7
+
6
8
  murlsh
7
9
  }.each { |m| require m }
8
10
 
11
+ config = YAML.load_file('config.yaml')
12
+
9
13
  # use Rack::ShowExceptions
14
+ use Rack::Cache,
15
+ :verbose => true,
16
+ :metastore => 'file:tmp/cache/rack/meta',
17
+ :entitystore => 'file:tmp/cache/rack/body'
10
18
  use Rack::ConditionalGet
11
19
  use Murlsh::EtagAddEncoding
12
20
  use Rack::Deflater
21
+ use Murlsh::FarFutureExpires, :patterns => %r{\.gen\.(css|js)$}
22
+
23
+ feed_path = URI.join(config.fetch('root_url'), config.fetch('feed_file')).path
24
+ use Murlsh::MustRevalidate, :patterns => %r{^#{Regexp.escape(feed_path)}$}
25
+
13
26
  use Rack::Static, :urls => %w{/css /js /swf}, :root => 'public'
14
27
  use Rack::Static, :urls => %w{/atom.xml /rss.xml}
15
28
 
16
- config = YAML.load_file('config.yaml')
29
+ # use Rack::Lint
17
30
 
18
31
  run Murlsh::Dispatch.new(config)
data/config.yaml CHANGED
@@ -9,7 +9,6 @@ flickr_api_key:
9
9
  gravatar_size: 32
10
10
  js_files:
11
11
  - js/jquery-1.4.2.min.js
12
- - js/jquery.cookie.js
13
12
  - js/jquery.jgrowl_compressed.js
14
13
  - js/js.js
15
14
  meta_tag_description: URLs found interesting by Matthew M. Boedicker
@@ -21,13 +21,15 @@ module Murlsh
21
21
 
22
22
  url_server = Murlsh::UrlServer.new(@config, db)
23
23
  flickr_server = Murlsh::FlickrServer.new(@config)
24
+ twitter_server = Murlsh::TwitterServer.new
24
25
 
25
26
  root_path = URI(@config.fetch('root_url')).path
26
27
 
27
28
  @dispatch = [
28
- [/^GET #{root_path}(url)?$/, url_server.method(:get)],
29
- [/^POST #{root_path}(url)?$/, url_server.method(:post)],
30
- [/^GET \/flickr$/, flickr_server.method(:get)],
29
+ [%r{^GET #{root_path}(url)?$}, url_server.method(:get)],
30
+ [%r{^POST #{root_path}(url)?$}, url_server.method(:post)],
31
+ [%r{^GET /flickr$}, flickr_server.method(:get)],
32
+ [%r{^GET /twitter/.+$}, twitter_server.method(:get)],
31
33
  ]
32
34
  end
33
35
 
data/lib/murlsh/doc.rb CHANGED
@@ -25,16 +25,28 @@ module Murlsh
25
25
  # Check a list of xpaths in order and return the inner html of the first
26
26
  # one that is not nil.
27
27
  def xpath_search(xpaths)
28
- xpaths.each do |xpath|
28
+ [*xpaths].each do |xpath|
29
29
  selection = (self/xpath).first
30
- return selection.inner_html unless selection.nil?
30
+ if selection; return (yield selection); end
31
31
  end
32
32
  nil
33
33
  end
34
34
 
35
35
  # Get the title of the document.
36
36
  def title
37
- xpath_search(%w{//html/head/title //head/title //html/title //title})
37
+ xpath_search(%w{
38
+ //html/head/title
39
+ //head/title
40
+ //html/title
41
+ //title
42
+ }) { |node| node.inner_html }
43
+ end
44
+
45
+ # Get the meta description of the document.
46
+ def description
47
+ xpath_search(
48
+ "//html/head/meta[@name='description']"
49
+ ) { |node| node['content'] }
38
50
  end
39
51
 
40
52
  end
@@ -0,0 +1,37 @@
1
+ %w{
2
+ rack
3
+ rack/utils
4
+ }.each { |m| require m }
5
+
6
+ module Murlsh
7
+
8
+ # Rack middleware to set a far future expires header for urls that match
9
+ # patterns.
10
+ class FarFutureExpires
11
+
12
+ def initialize(app, options={})
13
+ @app = app
14
+ @patterns = options[:patterns] ? [*options[:patterns]] : []
15
+ @future = options[:future] || 'Wed, 22 Jun 2019 20:07:00 GMT'
16
+ end
17
+
18
+ def call(env)
19
+ status, headers, body = @app.call(env)
20
+
21
+ req = Rack::Request.new(env)
22
+
23
+ headers = Rack::Utils::HeaderHash.new(headers)
24
+
25
+ @patterns.each do |pattern|
26
+ if pattern.match(req.path)
27
+ headers['Expires'] = @future
28
+ break
29
+ end
30
+ end
31
+
32
+ [status, headers, body]
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -1,4 +1,5 @@
1
1
  %w{
2
+ digest/sha1
2
3
  open-uri
3
4
 
4
5
  json
@@ -7,16 +8,15 @@ rack
7
8
 
8
9
  module Murlsh
9
10
 
10
- # Proxy for Flickr rest API flickr.photos.getinfo call to support conditional
11
- # get.
11
+ # Proxy for Flickr rest API to support conditional get and caching.
12
12
  #
13
13
  # Passes along query string with api key added, returns result from Flickr
14
- # with content type set to application/json and last modified header set.
14
+ # with cache-control, etag and last-modified headers set.
15
15
  class FlickrServer
16
16
 
17
17
  def initialize(config); @config = config; end
18
18
 
19
- # Proxy a flickr.photos.getinfo request to the Flickr rest API.
19
+ # Proxy a request to the Flickr API.
20
20
  def get(req)
21
21
  resp = Rack::Response.new
22
22
 
@@ -26,9 +26,6 @@ module Murlsh
26
26
  q = params.map { |k,v| "#{URI.encode(k)}=#{URI.encode(v)}" }.join('&')
27
27
 
28
28
  json_wrapped = open("http://api.flickr.com/services/rest/?#{q}") do |f|
29
- # for some reason Firefox will not cache if it's text/plain, which is
30
- # what Flickr returns
31
- resp['Content-Type'] = 'application/json'
32
29
  f.read
33
30
  end
34
31
 
@@ -36,6 +33,9 @@ module Murlsh
36
33
 
37
34
  json_parsed = JSON.parse(json)
38
35
 
36
+ resp['Cache-Control'] = 'max-age=86400'
37
+ resp['Content-Type'] = 'application/json'
38
+ resp['ETag'] = "\"#{Digest::SHA1.hexdigest(json_wrapped)}\""
39
39
  resp['Last-Modified'] = Time.at(
40
40
  json_parsed['photo']['dates']['lastupdate'].to_i).httpdate
41
41
 
data/lib/murlsh/markup.rb CHANGED
@@ -8,7 +8,7 @@ module Murlsh
8
8
  # Options:
9
9
  # * :prefix - prefix to append to all script urls
10
10
  def javascript(sources, options={})
11
- sources.to_a.each do |src|
11
+ [*sources].each do |src|
12
12
  script('', :type => 'text/javascript',
13
13
  :src => "#{options[:prefix]}#{src}")
14
14
  end
@@ -49,7 +49,7 @@ module Murlsh
49
49
  # * :media - optional media attribute
50
50
  # * :prefix - prepended to all CSS urls
51
51
  def css(hrefs, options={})
52
- hrefs.to_a.each do |href|
52
+ [*hrefs].each do |href|
53
53
  attrs = {
54
54
  :href => "#{options[:prefix]}#{href}",
55
55
  :rel => 'stylesheet',
@@ -0,0 +1,36 @@
1
+ %w{
2
+ rack
3
+ rack/utils
4
+ }.each { |m| require m }
5
+
6
+ module Murlsh
7
+
8
+ # Rack middleware to force caches to always revalidate for urls that match
9
+ # patterns.
10
+ class MustRevalidate
11
+
12
+ def initialize(app, options={})
13
+ @app = app
14
+ @patterns = options[:patterns] ? [*options[:patterns]] : []
15
+ end
16
+
17
+ def call(env)
18
+ status, headers, body = @app.call(env)
19
+
20
+ req = Rack::Request.new(env)
21
+
22
+ headers = Rack::Utils::HeaderHash.new(headers)
23
+
24
+ @patterns.each do |pattern|
25
+ if pattern.match(req.path)
26
+ headers['Cache-Control'] = 'must-revalidate, max-age=0'
27
+ break
28
+ end
29
+ end
30
+
31
+ [status, headers, body]
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,44 @@
1
+ %w{
2
+ digest/sha1
3
+ open-uri
4
+
5
+ json
6
+ rack
7
+ }.each { |m| require m }
8
+
9
+ module Murlsh
10
+
11
+ # Proxy for Twitter rest API to support conditional get and caching.
12
+ #
13
+ # Passes along path and query string, returns result from Twitter with
14
+ # cache-control, etag and last-modified headers set.
15
+ class TwitterServer
16
+
17
+ # Proxy a request to the Twitter API.
18
+ def get(req)
19
+ resp = Rack::Response.new
20
+
21
+ twitter_url = URI.join('http://api.twitter.com',
22
+ req.fullpath[/twitter\/(.+)/, 1])
23
+
24
+ json_wrapped = open(twitter_url) do |f|
25
+ resp['Content-Type'] = f.content_type
26
+ f.read
27
+ end
28
+
29
+ json = /.+?\((.+)\)/.match(json_wrapped)[1]
30
+
31
+ json_parsed = JSON.parse(json)
32
+
33
+ resp['Cache-Control'] = 'max-age=86400'
34
+ resp['ETag'] = "\"#{Digest::SHA1.hexdigest(json_wrapped)}\""
35
+ resp['Last-Modified'] = Time.parse(json_parsed['created_at']).httpdate
36
+
37
+ resp.body = json_wrapped
38
+
39
+ resp
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -41,26 +41,61 @@ module Murlsh
41
41
  # Get the HTML title.
42
42
  #
43
43
  # Options:
44
- # * :failproof - if true hide all exceptions and return empty string on failure
44
+ # * :failproof - if true hide all exceptions and return url on failure
45
45
  # * :headers - hash of headers to send in request
46
46
  def title(options={})
47
47
  return @title if defined?(@title)
48
- options[:headers] = default_headers.merge(options.fetch(:headers, {}))
49
48
 
50
49
  @title = to_s
51
- if might_have_title?(options)
50
+
51
+ d = doc(options)
52
+
53
+ if d and d.title and !d.title.empty?
54
+ @title = decode(d.title)
55
+ end
56
+
57
+ @title
58
+ end
59
+
60
+ # Get the HTML meta description.
61
+ #
62
+ # Options:
63
+ # * :failproof - if true hide all exceptions and return empty string on failure
64
+ # * :headers - hash of headers to send in request
65
+ def description(options={})
66
+ return @description if defined?(@description)
67
+
68
+ @description = ''
69
+
70
+ d = doc(options)
71
+
72
+ if d and d.description and !d.description.empty?
73
+ @description = decode(d.description)
74
+ end
75
+
76
+ @description
77
+ end
78
+
79
+ # Get the parsed Hpricot doc at this url.
80
+ #
81
+ # Options:
82
+ # * :failproof - if true hide all exceptions and return empty string on failure
83
+ # * :headers - hash of headers to send in request
84
+ def doc(options={})
85
+ return @doc if defined?(@doc)
86
+ options[:headers] = default_headers.merge(options.fetch(:headers, {}))
87
+
88
+ @doc = nil
89
+ if html?(options)
52
90
  Murlsh::failproof(options) do
53
91
  self.open(options[:headers]) do |f|
54
- doc = Hpricot(f).extend(Murlsh::Doc)
92
+ @doc = Hpricot(f).extend(Murlsh::Doc)
55
93
 
56
- if doc.title and !doc.title.empty?
57
- @title = HTMLEntities.new.decode(Iconv.conv('utf-8',
58
- doc.charset || f.charset, doc.title))
59
- end
94
+ @charset = @doc.charset || f.charset
60
95
  end
61
96
  end
62
97
  end
63
- @title
98
+ @doc
64
99
  end
65
100
 
66
101
  # Default headers sent with the request.
@@ -76,12 +111,17 @@ module Murlsh
76
111
  result
77
112
  end
78
113
 
79
- # Return true if the content type is likely to have a title that can be
80
- # parsed.
81
- def might_have_title?(options={})
114
+ # Return true if the content type is HTML.
115
+ def html?(options={})
82
116
  content_type(options)[/^text\/html/]
83
117
  end
84
118
 
119
+ # Convert from the character set of this url to utf-8 and decode HTML
120
+ # entities.
121
+ def decode(s)
122
+ HTMLEntities.new.decode(Iconv.conv('utf-8', @charset, s))
123
+ end
124
+
85
125
  end
86
126
 
87
127
  end
@@ -23,8 +23,9 @@ module Murlsh
23
23
  resp.set_content_type(req.env['HTTP_ACCEPT'], req.env['HTTP_USER_AGENT'])
24
24
 
25
25
  last_db_update = File::Stat.new(@config['db_file']).mtime
26
- resp['Last-Modified'] = last_db_update.httpdate
26
+ resp['Cache-Control'] = 'must-revalidate, max-age=0'
27
27
  resp['ETag'] = "W/\"#{last_db_update.to_i}#{req.params.sort}\""
28
+ resp['Last-Modified'] = last_db_update.httpdate
28
29
 
29
30
  resp.body = Murlsh::UrlBody.new(@config, @db, req)
30
31
 
@@ -57,11 +58,6 @@ module Murlsh
57
58
  resp = Rack::Response.new([mu].to_json, 200, {
58
59
  'Content-Type' => 'application/json' })
59
60
 
60
- resp.set_cookie('auth',
61
- :expires => Time.mktime(2015, 6, 22),
62
- :path => '/',
63
- :value => auth)
64
-
65
61
  resp
66
62
  else
67
63
  Rack::Response.new('Permission denied', 403, {
data/murlsh.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{murlsh}
8
- s.version = "0.7.0"
8
+ s.version = "0.8.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Matthew M. Boedicker"]
12
- s.date = %q{2010-04-10}
12
+ s.date = %q{2010-04-25}
13
13
  s.default_executable = %q{murlsh}
14
14
  s.description = %q{url sharing site framework with easy adding, title lookup, atom feed, thumbnails and embedding}
15
15
  s.email = %q{matthewm@boedicker.org}
@@ -34,12 +34,15 @@ Gem::Specification.new do |s|
34
34
  "lib/murlsh/doc.rb",
35
35
  "lib/murlsh/etag_add_encoding.rb",
36
36
  "lib/murlsh/failproof.rb",
37
+ "lib/murlsh/far_future_expires.rb",
37
38
  "lib/murlsh/flickr_server.rb",
38
39
  "lib/murlsh/markup.rb",
40
+ "lib/murlsh/must_revalidate.rb",
39
41
  "lib/murlsh/openlock.rb",
40
42
  "lib/murlsh/plugin.rb",
41
43
  "lib/murlsh/sqlite3_adapter.rb",
42
44
  "lib/murlsh/time_ago.rb",
45
+ "lib/murlsh/twitter_server.rb",
43
46
  "lib/murlsh/uri.rb",
44
47
  "lib/murlsh/uri_ask.rb",
45
48
  "lib/murlsh/url.rb",
@@ -52,6 +55,7 @@ Gem::Specification.new do |s|
52
55
  "plugins/add_post_50_update_rss.rb",
53
56
  "plugins/add_post_60_notify_hubs.rb",
54
57
  "plugins/add_pre_50_lookup_content_type_title.rb",
58
+ "plugins/add_pre_60_github_title.rb",
55
59
  "plugins/hostrec_50_redundant.rb",
56
60
  "plugins/hostrec_60_skip.rb",
57
61
  "plugins/time_50_ago.rb",
@@ -59,7 +63,6 @@ Gem::Specification.new do |s|
59
63
  "public/css/jquery.jgrowl.css",
60
64
  "public/css/screen.css",
61
65
  "public/js/jquery-1.4.2.min.js",
62
- "public/js/jquery.cookie.js",
63
66
  "public/js/jquery.jgrowl_compressed.js",
64
67
  "public/js/js.js",
65
68
  "public/swf/player_mp3_mini.swf",
@@ -104,6 +107,7 @@ Gem::Specification.new do |s|
104
107
  s.add_runtime_dependency(%q<htmlentities>, [">= 4.2.0"])
105
108
  s.add_runtime_dependency(%q<json>, [">= 1.2.3"])
106
109
  s.add_runtime_dependency(%q<rack>, [">= 1.0.0"])
110
+ s.add_runtime_dependency(%q<rack-cache>, [">= 0.5.2"])
107
111
  s.add_runtime_dependency(%q<sqlite3-ruby>, [">= 1.2.1"])
108
112
  else
109
113
  s.add_dependency(%q<activerecord>, [">= 2.3.4"])
@@ -113,6 +117,7 @@ Gem::Specification.new do |s|
113
117
  s.add_dependency(%q<htmlentities>, [">= 4.2.0"])
114
118
  s.add_dependency(%q<json>, [">= 1.2.3"])
115
119
  s.add_dependency(%q<rack>, [">= 1.0.0"])
120
+ s.add_dependency(%q<rack-cache>, [">= 0.5.2"])
116
121
  s.add_dependency(%q<sqlite3-ruby>, [">= 1.2.1"])
117
122
  end
118
123
  else
@@ -123,6 +128,7 @@ Gem::Specification.new do |s|
123
128
  s.add_dependency(%q<htmlentities>, [">= 4.2.0"])
124
129
  s.add_dependency(%q<json>, [">= 1.2.3"])
125
130
  s.add_dependency(%q<rack>, [">= 1.0.0"])
131
+ s.add_dependency(%q<rack-cache>, [">= 0.5.2"])
126
132
  s.add_dependency(%q<sqlite3-ruby>, [">= 1.2.1"])
127
133
  end
128
134
  end
@@ -0,0 +1,22 @@
1
+ %w{
2
+ murlsh
3
+ }.each { |m| require m }
4
+
5
+ module Murlsh
6
+
7
+ # Github project page titles are not very descriptive so add meta description
8
+ # to title.
9
+ class AddPre60GithubTitle < Plugin
10
+
11
+ Hook = 'add_pre'
12
+
13
+ def self.run(url, config)
14
+ if url.url[%r{http://github.com/\w+/\w+}]
15
+ ask = URI(url.url).extend(Murlsh::UriAsk)
16
+ url.title << " - #{ask.description}" unless ask.description.empty?
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ end
data/public/js/js.js CHANGED
@@ -170,7 +170,7 @@ Murlsh.hrefRes = {
170
170
  s3 :
171
171
  /^(http:\/\/static\.mmb\.s3\.amazonaws\.com\/[\w\-]+\.)(jpe?g|gif|pdf|png)$/i,
172
172
  twitter :
173
- /^http:\/\/twitter\.com\/\w+\/statuses\/(\d+)$/i,
173
+ /^http:\/\/twitter\.com\/\w+\/status(?:es)?\/(\d+)$/i,
174
174
  vimeo :
175
175
  /^http:\/\/(?:www\.)?vimeo\.com\/(\d+)$/i,
176
176
  youtube :
@@ -236,8 +236,9 @@ Murlsh.addExtra = function() {
236
236
  }
237
237
  } else if (match.twitter) {
238
238
  $.ajax({
239
- url : 'http://api.twitter.com/1/statuses/show/' + match.twitter[1] +
240
- '.json',
239
+ // url : 'http://api.twitter.com/1/statuses/show/' +
240
+ url : '/twitter/1/statuses/show/' +
241
+ match.twitter[1] + '.json',
241
242
  dataType : 'jsonp',
242
243
  success : function(d) {
243
244
  var nameLink = $('<a />', {
@@ -254,7 +255,8 @@ Murlsh.addExtra = function() {
254
255
  width : '48'
255
256
  }), null, nameLink);
256
257
  },
257
- context : $(this)
258
+ context : $(this),
259
+ jsonpCallback : 'twitterCallback' + match.twitter[1]
258
260
  });
259
261
  } else if (match.vimeo) {
260
262
  $.ajax({
@@ -318,6 +320,10 @@ Murlsh.iphoneInit = function() {
318
320
  href : '#bottom',
319
321
  text : 'bottom'
320
322
  }));
323
+
324
+ // change input types to html5 to make typing easier
325
+ $('#q').attr('type', 'search');
326
+ $('#url,#via').attr('type', 'url');
321
327
  };
322
328
 
323
329
  $(document).ready(function() {
@@ -342,7 +348,4 @@ $(document).ready(function() {
342
348
  }, 'json');
343
349
  });
344
350
 
345
- if ($.cookie('auth')) {
346
- $('#auth').val($.cookie('auth'));
347
- }
348
351
  });
data/spec/doc_spec.rb CHANGED
@@ -8,10 +8,13 @@ murlsh
8
8
 
9
9
  describe Murlsh::Doc do
10
10
 
11
- it 'should get the right title from an HTML page that has one' do
12
- html = <<eos
11
+ context 'when html has everything' do
12
+ subject do
13
+ html = <<eos
13
14
  <html>
14
15
  <head>
16
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
17
+ <meta name="description" content="the description" />
15
18
  <title>the title</title>
16
19
  </head>
17
20
  <body>
@@ -19,9 +22,31 @@ describe Murlsh::Doc do
19
22
  </body>
20
23
  </html>
21
24
  eos
25
+ Hpricot(html).extend(Murlsh::Doc)
26
+ end
22
27
 
23
- doc = Hpricot(html).extend(Murlsh::Doc)
24
- doc.title.should == 'the title'
28
+ its(:charset) { should == 'utf-8' }
29
+ its(:title) { should == 'the title' }
30
+ its(:description) { should == 'the description' }
31
+ end
32
+
33
+ context 'when html has nothing' do
34
+ subject do
35
+ html = <<eos
36
+ <html>
37
+ <head>
38
+ </head>
39
+ <body>
40
+ <h1>hi</h1>
41
+ </body>
42
+ </html>
43
+ eos
44
+ Hpricot(html).extend(Murlsh::Doc)
45
+ end
46
+
47
+ its(:charset) { should be_nil }
48
+ its(:title) { should be_nil }
49
+ its(:description) { should be_nil }
25
50
  end
26
51
 
27
52
  end
@@ -6,7 +6,7 @@ murlsh
6
6
 
7
7
  describe Murlsh::YamlOrderedHash do
8
8
 
9
- it 'should generate yaml with hash keys in sorted order' do
9
+ subject do
10
10
  h = {
11
11
  'd' => 4,
12
12
  'a' => 1,
@@ -15,14 +15,15 @@ describe Murlsh::YamlOrderedHash do
15
15
  }
16
16
 
17
17
  h.extend(Murlsh::YamlOrderedHash)
18
-
19
- h.to_yaml.should == <<EOS
18
+ end
19
+
20
+ its(:to_yaml) { should == <<EOS
20
21
  ---
21
22
  a: 1
22
23
  b: 2
23
24
  c: 3
24
25
  d: 4
25
26
  EOS
26
- end
27
+ }
27
28
 
28
29
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 7
7
+ - 8
8
8
  - 0
9
- version: 0.7.0
9
+ version: 0.8.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Matthew M. Boedicker
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-10 00:00:00 -04:00
17
+ date: 2010-04-25 00:00:00 -04:00
18
18
  default_executable: murlsh
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -116,9 +116,23 @@ dependencies:
116
116
  type: :runtime
117
117
  version_requirements: *id007
118
118
  - !ruby/object:Gem::Dependency
119
- name: sqlite3-ruby
119
+ name: rack-cache
120
120
  prerelease: false
121
121
  requirement: &id008 !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ segments:
126
+ - 0
127
+ - 5
128
+ - 2
129
+ version: 0.5.2
130
+ type: :runtime
131
+ version_requirements: *id008
132
+ - !ruby/object:Gem::Dependency
133
+ name: sqlite3-ruby
134
+ prerelease: false
135
+ requirement: &id009 !ruby/object:Gem::Requirement
122
136
  requirements:
123
137
  - - ">="
124
138
  - !ruby/object:Gem::Version
@@ -128,7 +142,7 @@ dependencies:
128
142
  - 1
129
143
  version: 1.2.1
130
144
  type: :runtime
131
- version_requirements: *id008
145
+ version_requirements: *id009
132
146
  description: url sharing site framework with easy adding, title lookup, atom feed, thumbnails and embedding
133
147
  email: matthewm@boedicker.org
134
148
  executables:
@@ -154,12 +168,15 @@ files:
154
168
  - lib/murlsh/doc.rb
155
169
  - lib/murlsh/etag_add_encoding.rb
156
170
  - lib/murlsh/failproof.rb
171
+ - lib/murlsh/far_future_expires.rb
157
172
  - lib/murlsh/flickr_server.rb
158
173
  - lib/murlsh/markup.rb
174
+ - lib/murlsh/must_revalidate.rb
159
175
  - lib/murlsh/openlock.rb
160
176
  - lib/murlsh/plugin.rb
161
177
  - lib/murlsh/sqlite3_adapter.rb
162
178
  - lib/murlsh/time_ago.rb
179
+ - lib/murlsh/twitter_server.rb
163
180
  - lib/murlsh/uri.rb
164
181
  - lib/murlsh/uri_ask.rb
165
182
  - lib/murlsh/url.rb
@@ -172,6 +189,7 @@ files:
172
189
  - plugins/add_post_50_update_rss.rb
173
190
  - plugins/add_post_60_notify_hubs.rb
174
191
  - plugins/add_pre_50_lookup_content_type_title.rb
192
+ - plugins/add_pre_60_github_title.rb
175
193
  - plugins/hostrec_50_redundant.rb
176
194
  - plugins/hostrec_60_skip.rb
177
195
  - plugins/time_50_ago.rb
@@ -179,7 +197,6 @@ files:
179
197
  - public/css/jquery.jgrowl.css
180
198
  - public/css/screen.css
181
199
  - public/js/jquery-1.4.2.min.js
182
- - public/js/jquery.cookie.js
183
200
  - public/js/jquery.jgrowl_compressed.js
184
201
  - public/js/js.js
185
202
  - public/swf/player_mp3_mini.swf
@@ -1,96 +0,0 @@
1
- /**
2
- * Cookie plugin
3
- *
4
- * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
5
- * Dual licensed under the MIT and GPL licenses:
6
- * http://www.opensource.org/licenses/mit-license.php
7
- * http://www.gnu.org/licenses/gpl.html
8
- *
9
- */
10
-
11
- /**
12
- * Create a cookie with the given name and value and other optional parameters.
13
- *
14
- * @example $.cookie('the_cookie', 'the_value');
15
- * @desc Set the value of a cookie.
16
- * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
17
- * @desc Create a cookie with all available options.
18
- * @example $.cookie('the_cookie', 'the_value');
19
- * @desc Create a session cookie.
20
- * @example $.cookie('the_cookie', null);
21
- * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
22
- * used when the cookie was set.
23
- *
24
- * @param String name The name of the cookie.
25
- * @param String value The value of the cookie.
26
- * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
27
- * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
28
- * If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
29
- * If set to null or omitted, the cookie will be a session cookie and will not be retained
30
- * when the the browser exits.
31
- * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
32
- * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
33
- * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
34
- * require a secure protocol (like HTTPS).
35
- * @type undefined
36
- *
37
- * @name $.cookie
38
- * @cat Plugins/Cookie
39
- * @author Klaus Hartl/klaus.hartl@stilbuero.de
40
- */
41
-
42
- /**
43
- * Get the value of a cookie with the given name.
44
- *
45
- * @example $.cookie('the_cookie');
46
- * @desc Get the value of a cookie.
47
- *
48
- * @param String name The name of the cookie.
49
- * @return The value of the cookie.
50
- * @type String
51
- *
52
- * @name $.cookie
53
- * @cat Plugins/Cookie
54
- * @author Klaus Hartl/klaus.hartl@stilbuero.de
55
- */
56
- jQuery.cookie = function(name, value, options) {
57
- if (typeof value != 'undefined') { // name and value given, set cookie
58
- options = options || {};
59
- if (value === null) {
60
- value = '';
61
- options.expires = -1;
62
- }
63
- var expires = '';
64
- if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
65
- var date;
66
- if (typeof options.expires == 'number') {
67
- date = new Date();
68
- date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
69
- } else {
70
- date = options.expires;
71
- }
72
- expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
73
- }
74
- // CAUTION: Needed to parenthesize options.path and options.domain
75
- // in the following expressions, otherwise they evaluate to undefined
76
- // in the packed version for some reason...
77
- var path = options.path ? '; path=' + (options.path) : '';
78
- var domain = options.domain ? '; domain=' + (options.domain) : '';
79
- var secure = options.secure ? '; secure' : '';
80
- document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
81
- } else { // only name given, get cookie
82
- var cookieValue = null;
83
- if (document.cookie && document.cookie != '') {
84
- var cookies = document.cookie.split(';');
85
- for (var i = 0; i < cookies.length; i++) {
86
- var cookie = jQuery.trim(cookies[i]);
87
- // Does this cookie string begin with the name we want?
88
- if (cookie.substring(0, name.length + 1) == (name + '=')) {
89
- cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
90
- break;
91
- }
92
- }
93
- }
94
- return cookieValue;
95
- }
96
- };