murlsh 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1 +1,3 @@
1
1
  *~
2
+ public/css/*.gen.css
3
+ public/js/*.gen.js
data/.htaccess CHANGED
@@ -5,3 +5,7 @@ AddOutputFilterByType DEFLATE application/xhtml+xml
5
5
  AddOutputFilterByType DEFLATE application/xml
6
6
  AddOutputFilterByType DEFLATE text/css
7
7
  AddOutputFilterByType DEFLATE text/html
8
+
9
+ <FilesMatch "\.gen\.(css|js)$">
10
+ Header add Expires "Wed, 22 Jun 2019 20:07:00 GMT"
11
+ </FilesMatch>
data/README.textile CHANGED
@@ -30,3 +30,5 @@ edit config.yaml
30
30
  rake db:init user:add
31
31
  </code>
32
32
  </pre>
33
+
34
+ Questions and comments: "matthewm@boedicker.org":mailto:matthewm@boedicker.org
data/Rakefile CHANGED
@@ -1,21 +1,27 @@
1
1
  $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
2
 
3
- require 'rubygems'
3
+ %w{
4
+ cgi
5
+ digest/md5
6
+ net/http
7
+ pp
8
+ uri
9
+ yaml
4
10
 
5
- require 'murlsh'
11
+ rubygems
6
12
 
7
- require 'flog'
8
- require 'rake/testtask'
9
- require 'sqlite3'
13
+ flog
14
+ rake/testtask
15
+ sqlite3
10
16
 
11
- require 'pp'
12
- require 'yaml'
17
+ murlsh
18
+ }.each { |d| require d }
13
19
 
14
20
  config = YAML.load_file('config.yaml')
15
21
 
16
22
  desc "Test remote content type fetch for a URL and show errors."
17
23
  task :content_type, :url do |t, args|
18
- puts Murlsh.get_content_type(args.url, :failproof => false)
24
+ puts Murlsh.get_content_type(args.url, :failproof => false, :debug => STDOUT)
19
25
  end
20
26
 
21
27
  namespace :db do
@@ -56,7 +62,8 @@ namespace :db do
56
62
  email TEXT,
57
63
  name TEXT,
58
64
  title TEXT,
59
- content_type TEXT);
65
+ content_type TEXT,
66
+ via TEXT);
60
67
  ")
61
68
  end
62
69
 
@@ -67,10 +74,12 @@ namespace :db do
67
74
 
68
75
  end
69
76
 
70
- namespace :dreamhost do
77
+ directory 'tmp'
71
78
 
72
- desc "Restart Passenger."
73
- task :restart do
79
+ namespace :passenger do
80
+
81
+ desc 'Restart Passenger.'
82
+ task :restart => ['tmp'] do
74
83
  open('tmp/restart.txt', 'w') { |f| }
75
84
  end
76
85
 
@@ -92,7 +101,7 @@ end
92
101
 
93
102
  desc "Test remote title fetch for a URL and show errors."
94
103
  task :title, :url do |t, args|
95
- puts Murlsh.get_title(args.url, :failproof => false)
104
+ puts Murlsh.get_title(args.url, :failproof => false, :debug => STDOUT)
96
105
  end
97
106
 
98
107
  desc 'Try to fetch the title for a url and update it in the database.'
@@ -124,9 +133,6 @@ end
124
133
 
125
134
  desc "Validate XHTML."
126
135
  task :validate do
127
- require 'cgi'
128
- require 'net/http'
129
-
130
136
  net_http = Net::HTTP.new('validator.w3.org', 80)
131
137
  #net_http.set_debug_output(STDOUT)
132
138
 
@@ -152,15 +158,93 @@ task :post_sh do
152
158
  #!/bin/sh
153
159
 
154
160
  URL="$1"
155
- AUTH="$2" # password can be passed as second parameter or hardcoded here
161
+ VIA="$2"
162
+ AUTH="$3" # password can be passed as second parameter or hardcoded here
156
163
 
157
164
  curl \\
158
165
  --data-urlencode "url=${URL}" \\
159
166
  --data-urlencode "auth=${AUTH}" \\
167
+ --data-urlencode "via=${VIA}" \\
160
168
  #{config.fetch('root_url')}
161
169
  EOS
162
170
  end
163
171
 
172
+ # Concatenate some files and return the result as a string.
173
+ def cat(in_files, sep=nil)
174
+ result = ''
175
+ in_files.each do |fname|
176
+ open(fname) do |h|
177
+ while (line = h.gets) do; result << line; end
178
+ result << sep if sep
179
+ end
180
+ end
181
+ result
182
+ end
183
+
184
+ directory 'public/css'
185
+
186
+ namespace :css do
187
+
188
+ desc 'Combine and compress css.'
189
+ task :compress => ['public/css'] do
190
+ combined = cat(config['css_files'].collect { |x| "public/#{x}" }, "\n")
191
+
192
+ md5sum = Digest::MD5.hexdigest(combined)
193
+
194
+ filename = "#{md5sum}.gen.css"
195
+
196
+ out = "public/css/#{filename}"
197
+
198
+ open(out, 'w') { |f| f.write(combined) }
199
+ puts "generated #{out}"
200
+
201
+ compressed_url = "css/#{filename}"
202
+
203
+ unless config['css_compressed'] == compressed_url
204
+ config['css_compressed'] = compressed_url
205
+ open('config.yaml', 'w') { |f| YAML.dump(config, f) }
206
+ puts "updated config with css_compressed = #{compressed_url}"
207
+ end
208
+ end
209
+
210
+ end
211
+
212
+ directory 'public/js'
213
+
214
+ namespace :js do
215
+
216
+ desc 'Combine and compress javascript.'
217
+ task :compress => ['public/js'] do
218
+ combined = cat(config['js_files'].collect { |x| "public/#{x}" } )
219
+
220
+ compressed = Net::HTTP.post_form(
221
+ URI.parse('http://closure-compiler.appspot.com/compile'), {
222
+ 'compilation_level' => 'SIMPLE_OPTIMIZATIONS',
223
+ 'js_code' => combined,
224
+ 'output_format' => 'text',
225
+ 'output_info' => 'compiled_code',
226
+ }).body
227
+
228
+ md5sum = Digest::MD5.hexdigest(compressed)
229
+
230
+ filename = "#{md5sum}.gen.js"
231
+
232
+ out = "public/js/#{filename}"
233
+
234
+ open(out, 'w') { |f| f.write(compressed) }
235
+ puts "generated #{out}"
236
+
237
+ compressed_url = "js/#{filename}"
238
+
239
+ unless config['js_compressed'] == compressed_url
240
+ config['js_compressed'] = compressed_url
241
+ open('config.yaml', 'w') { |f| YAML.dump(config, f) }
242
+ puts "updated config with js_compressed = #{compressed_url}"
243
+ end
244
+ end
245
+
246
+ end
247
+
164
248
  def ask(prompt, sep=':')
165
249
  print "#{prompt}#{sep} "
166
250
  return STDIN.gets.chomp
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
data/config.yaml CHANGED
@@ -9,10 +9,11 @@ num_posts_feed: 25
9
9
  num_posts_page: 100
10
10
  page_title: mmb url share
11
11
  root_url: http://urls.matthewm.boedicker.org/
12
- css_prefix: css/
13
- img_prefix: img/
14
- js_prefix: js/
15
- swf_prefix: swf/
16
12
  css_files:
17
- - jquery.jgrowl.css
18
- - screen.css
13
+ - css/jquery.jgrowl.css
14
+ - css/screen.css
15
+ js_files:
16
+ - js/jquery-1.3.2.min.js
17
+ - js/jquery.cookie.js
18
+ - js/jquery.jgrowl_compressed.js
19
+ - js/js.js
@@ -37,20 +37,14 @@ module Murlsh
37
37
 
38
38
  # Generate the feed and write it to the filesystem with locking.
39
39
  def write(entries, path)
40
- open(path, 'w') do |f|
41
- f.flock(File::LOCK_EX)
42
-
43
- make(entries, :target => f)
44
-
45
- f.flock(File::LOCK_UN)
46
- end
40
+ Murlsh::openlock(path, 'w') { |f| make(entries, :target => f) }
47
41
  end
48
42
 
49
43
  # Build the feed using XML builder. Options are passed to
50
44
  # Builder::XmlMarkup.new.
51
45
  def make(entries, options={})
52
46
  xm = Builder::XmlMarkup.new(options)
53
- xm.instruct! :xml
47
+ xm.instruct!(:xml)
54
48
 
55
49
  xm.feed(:xmlns => 'http://www.w3.org/2005/Atom') {
56
50
  xm.id(@root_url)
data/lib/murlsh/auth.rb CHANGED
@@ -30,11 +30,9 @@ module Murlsh
30
30
 
31
31
  # Add a user to the authentication file.
32
32
  def add_user(username, email, password)
33
- open(@file, 'a') do |f|
34
- f.flock(File::LOCK_EX)
33
+ Murlsh::openlock(@file, 'a') do |f|
35
34
  f.write("#{[username, Digest::MD5.hexdigest(email),
36
35
  BCrypt::Password.create(password)].join(',')}\n")
37
- f.flock(File::LOCK_UN)
38
36
  end
39
37
  end
40
38
 
@@ -0,0 +1,12 @@
1
+ module Murlsh
2
+
3
+ module_function
4
+
5
+ # Open a file with an exclusive lock.
6
+ def openlock(*args)
7
+ open(*args) do |f|
8
+ f.flock(File::LOCK_EX) ; yield f ; f.flock(File::LOCK_UN)
9
+ end
10
+ end
11
+
12
+ end
@@ -38,7 +38,7 @@ module Murlsh
38
38
 
39
39
  # Regex host match to name of query string parameter.
40
40
  Qmap = {
41
- /^www\.google\.(bs|ca|com|cz|dk|es|fi|nl)(\/m)?\/search$/ => 'q',
41
+ /^www\.google\.(bs|ca|com|cz|dk|es|fi|it|nl|no)(\/m)?\/search$/ => 'q',
42
42
  /^www\.bing\.com\/search$/ => 'q',
43
43
  }
44
44
 
data/lib/murlsh/url.rb CHANGED
@@ -3,6 +3,10 @@ require 'active_record'
3
3
 
4
4
  require 'uri'
5
5
 
6
+ module URI
7
+ def domain; host[/[a-z\d-]+\.[a-z]{2,}(\.[a-z]{2})?$/].downcase; end
8
+ end
9
+
6
10
  module Murlsh
7
11
 
8
12
  # URL ActiveRecord.
@@ -21,11 +25,7 @@ module Murlsh
21
25
 
22
26
  # Return text showing what domain a link goes to.
23
27
  def hostrec
24
- begin
25
- domain = URI(url).host[/[a-z\d-]+\.[a-z]{2,}(\.[a-z]{2})?$/].downcase
26
- rescue Exception => e
27
- domain = nil
28
- end
28
+ domain = begin; URI(url).domain; rescue Exception; end
29
29
 
30
30
  domain = Murlsh::Plugin.hooks('hostrec').inject(domain) {
31
31
  |result,plugin| plugin.run(result, url, title) }
@@ -33,6 +33,16 @@ module Murlsh
33
33
  yield domain if domain
34
34
  end
35
35
 
36
+ # Yield the url that the url came from.
37
+ def viarec
38
+ if via
39
+ begin
40
+ yield URI(via)
41
+ rescue Exception
42
+ end
43
+ end
44
+ end
45
+
36
46
  # Return true if this url is an image.
37
47
  def is_image?
38
48
  %w{image/gif image/jpeg image/png}.include?(content_type)
@@ -6,7 +6,7 @@ module Murlsh
6
6
 
7
7
  def initialize(config, db, req)
8
8
  @config, @db, @req, @q = config, db, req, req.params['q']
9
- super(:indent => 2)
9
+ super(:indent => @config['xhtml_indent'] || 0)
10
10
  end
11
11
 
12
12
  # Fetch urls base on query string parameters.
@@ -56,7 +56,15 @@ module Murlsh
56
56
 
57
57
  a(mu.title.strip.gsub(/\s+/, ' '), :href => mu.url)
58
58
 
59
- mu.hostrec { |hostrec| span(hostrec, :class => 'host') }
59
+ mu.hostrec do |hostrec|
60
+ text!(' ')
61
+ span(hostrec, :class => 'host')
62
+ end
63
+ mu.viarec do |via|
64
+ span(:class => 'via') {
65
+ text!(' (via '); a(via.domain, :href => via); text!(')')
66
+ }
67
+ end
60
68
  span(", #{mu.time.fuzzy}", :class => 'date') if
61
69
  @config.fetch('show_dates', true) and mu.time
62
70
  last = mu
@@ -82,10 +90,7 @@ module Murlsh
82
90
  :viewport =>
83
91
  'width=device-width,minimum-scale=1.0,maximum-scale=1.0')
84
92
  google_verify
85
- css(@config.fetch('css_files', []),
86
- :prefix => @config.fetch('css_prefix', ''))
87
- css('phone.css', :media => 'only screen and (max-device-width: 480px)',
88
- :prefix => @config.fetch('css_prefix', ''))
93
+ css(@config['css_compressed'] || @config['css_files'])
89
94
  atom(@config.fetch('feed_file'))
90
95
  }
91
96
  end
@@ -128,6 +133,7 @@ module Murlsh
128
133
  form(:action => '', :method => 'post') {
129
134
  fieldset(:id => 'add') {
130
135
  self.p { add_form_input('Add URL:', 'url', 32) }
136
+ self.p { add_form_input('Via:', 'via', 32) }
131
137
  self.p {
132
138
  add_form_input('Password:', 'auth', 16, 'password')
133
139
  input(:type => 'button', :id => 'submit', :value => 'Add')
@@ -156,14 +162,7 @@ module Murlsh
156
162
  end
157
163
 
158
164
  # Required javascript builder.
159
- def js
160
- javascript(%w{
161
- jquery-1.3.2.min.js
162
- jquery.cookie.js
163
- jquery.jgrowl_compressed.js
164
- js.js
165
- }, :prefix => @config.fetch('js_prefix', ''))
166
- end
165
+ def js; javascript(@config['js_compressed'] || @config['js_files']); end
167
166
 
168
167
  end
169
168
 
@@ -10,8 +10,7 @@ module Murlsh
10
10
  class UrlServer
11
11
 
12
12
  def initialize(config, db)
13
- @config = config
14
- @db = db
13
+ @config, @db = config, db
15
14
  ActiveRecord::Base.default_timezone = :utc
16
15
 
17
16
  Dir['plugins/*.rb'].each { |p| load p }
@@ -35,11 +34,7 @@ module Murlsh
35
34
 
36
35
  # Respond to a POST request. Add the new url and return json.
37
36
  def post(req)
38
- resp = Rack::Response.new
39
-
40
- url = req.params['url']
41
-
42
- unless url.empty?
37
+ unless req.params['url'].empty?
43
38
  auth = req.params['auth']
44
39
  if user = auth.empty? ? nil : Murlsh::Auth.new(
45
40
  @config.fetch('auth_file')).auth(auth)
@@ -48,9 +43,10 @@ module Murlsh
48
43
 
49
44
  mu = Murlsh::Url.new do |u|
50
45
  u.time = Time.now.gmtime
51
- u.url = url
46
+ u.url = req.params['url']
52
47
  u.email = user[:email]
53
48
  u.name = user[:name]
49
+ u.via = req.params['via'] unless (req.params['via'] || []).empty?
54
50
  end
55
51
 
56
52
  Murlsh::Plugin.hooks('add_pre') { |p| p.run(mu, @config) }
@@ -59,25 +55,22 @@ module Murlsh
59
55
 
60
56
  Murlsh::Plugin.hooks('add_post') { |p| p.run(@config) }
61
57
 
62
- resp['Content-Type'] = 'application/json'
58
+ resp = Rack::Response.new([mu].to_json, 200, {
59
+ 'Content-Type' => 'application/json' })
63
60
 
64
61
  resp.set_cookie('auth',
65
62
  :expires => Time.mktime(2015, 6, 22),
66
63
  :path => '/',
67
64
  :value => auth)
68
65
 
69
- resp.body = [mu].to_json
66
+ resp
70
67
  else
71
- resp.status = 403
72
- resp['Content-Type'] = 'text/plain'
73
- resp.write('Permission denied')
68
+ Rack::Response.new('Permission denied', 403, {
69
+ 'Content-Type' => 'text/plain' })
74
70
  end
75
71
  else
76
- resp.status = 500
77
- resp['Content-Type'] = 'text/plain'
78
- resp.write('No url')
72
+ Rack::Response.new('No url', 500, { 'Content-Type' => 'text/plain' })
79
73
  end
80
- resp
81
74
  end
82
75
 
83
76
  end
data/lib/murlsh.rb CHANGED
@@ -2,6 +2,7 @@ require 'murlsh/auth'
2
2
  require 'murlsh/dispatch'
3
3
  require 'murlsh/get_content_type'
4
4
  require 'murlsh/get_title'
5
+ require 'murlsh/openlock'
5
6
  require 'murlsh/plugin'
6
7
  require 'murlsh/referrer'
7
8
  require 'murlsh/sqlite3_adapter'
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.3.0"
8
+ s.version = "0.4.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{2009-11-05}
12
+ s.date = %q{2009-12-13}
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,6 +34,7 @@ Gem::Specification.new do |s|
34
34
  "lib/murlsh/get_content_type.rb",
35
35
  "lib/murlsh/get_title.rb",
36
36
  "lib/murlsh/markup.rb",
37
+ "lib/murlsh/openlock.rb",
37
38
  "lib/murlsh/plugin.rb",
38
39
  "lib/murlsh/referrer.rb",
39
40
  "lib/murlsh/sqlite3_adapter.rb",
@@ -48,7 +49,6 @@ Gem::Specification.new do |s|
48
49
  "plugins/lookup_content_type_title.rb",
49
50
  "plugins/update_feed.rb",
50
51
  "public/css/jquery.jgrowl.css",
51
- "public/css/phone.css",
52
52
  "public/css/screen.css",
53
53
  "public/js/jquery-1.3.2.min.js",
54
54
  "public/js/jquery.cookie.js",
@@ -1,5 +1,6 @@
1
1
  body {
2
- font-family : sans-serif;
2
+ font-size : 1em;
3
+ line-height : 1.5em;
3
4
  }
4
5
 
5
6
  img {
@@ -8,7 +9,7 @@ img {
8
9
 
9
10
  #urls {
10
11
  list-style-type : none;
11
- width : 480px;
12
+ width : 600px;
12
13
  }
13
14
 
14
15
  li {
@@ -16,13 +17,6 @@ li {
16
17
  float : left;
17
18
  padding : 10px 20px 10px 10px;
18
19
  width : 100%;
19
- border-bottom : 1px solid #f6f6f6;
20
- }
21
-
22
- li.even {
23
- background-color : #eee;
24
- border-right : 1px solid #ddd;
25
- border-bottom : 1px solid #ccc;
26
20
  }
27
21
 
28
22
  div.icon {
@@ -30,10 +24,12 @@ div.icon {
30
24
  margin : 0 0.5em 0 0;
31
25
  }
32
26
 
33
- div.name {
34
- float : left;
35
- font-style : italic;
36
- margin-right : 0.5em;
27
+ a:link {
28
+ color : #000;
29
+ }
30
+
31
+ a:visited {
32
+ color : #808080;
37
33
  }
38
34
 
39
35
  a:link, a:visited, a:active {
@@ -44,6 +40,12 @@ a:hover {
44
40
  text-decoration : underline;
45
41
  }
46
42
 
43
+ div.name {
44
+ float : left;
45
+ font-style : italic;
46
+ margin-right : 0.5em;
47
+ }
48
+
47
49
  img.thumb, li object {
48
50
  float : left;
49
51
  margin-right : 10px;
@@ -92,3 +94,35 @@ div.jGrowl div.jGrowl-closer {
92
94
  float : right;
93
95
  width : auto;
94
96
  }
97
+
98
+ /* iphone */
99
+ @media screen and (max-device-width : 480px) {
100
+
101
+ a.feed {
102
+ display : none;
103
+ }
104
+
105
+ body {
106
+ margin : 0;
107
+ padding : 0;
108
+ }
109
+
110
+ #urls {
111
+ margin : 0;
112
+ padding-left : 0;
113
+ width : 290px;
114
+ }
115
+
116
+ #urls li {
117
+ overflow : hidden;
118
+ }
119
+
120
+ input#q {
121
+ width : 130px;
122
+ }
123
+
124
+ input#url {
125
+ width : 160px;
126
+ }
127
+
128
+ }
data/public/js/js.js CHANGED
@@ -1,23 +1,46 @@
1
+ "use strict";
2
+
1
3
  var Murlsh = {};
2
4
 
3
- Murlsh.new_img = function(src, text) {
4
- return $('<img />').attr({
5
+ Murlsh.tag = function(name, attr, text) {
6
+ var klass;
7
+ var result = $('<' + name + ' />');
8
+
9
+ if (attr) {
10
+ if (attr.klass) {
11
+ klass = attr.klass;
12
+ delete attr.klass;
13
+ }
14
+ result.attr(attr);
15
+ }
16
+
17
+ if (text) {
18
+ result.text(text);
19
+ }
20
+
21
+ if (klass) {
22
+ result.addClass(klass);
23
+ }
24
+
25
+ return result;
26
+ };
27
+
28
+ Murlsh.img = function(src, text) {
29
+ text = text || '';
30
+ return Murlsh.tag('img', {
5
31
  src : src,
6
32
  alt : text,
7
33
  title : text
8
34
  });
9
35
  };
10
36
 
11
- Murlsh.close = function() {
12
- $(this).parent().remove();
13
- };
14
-
15
- Murlsh.closer_add = function(x) {
16
- var html = (typeof x == 'object') ? $('<div />').append(x).html() : x;
37
+ Murlsh.closer_add = function(x, header) {
38
+ var html = (typeof x == 'object') ? Murlsh.tag('div').append(x).html() : x;
17
39
 
18
40
  $.jGrowl(html, {
19
41
  closeTemplate : 'X',
20
42
  glue :'before',
43
+ header : header,
21
44
  sticky : true
22
45
  });
23
46
  };
@@ -33,34 +56,40 @@ Murlsh.object_tag = function(data, height, width, params) {
33
56
  };
34
57
 
35
58
  Murlsh.flickr_thumb = function(d) {
36
- var base = 'http://farm' + d.photo.farm + '.static.flickr.com/' +
37
- d.photo.server + '/' + d.photo.id + '_';
38
- var zoom;
39
- if (d.photo.originalsecret) {
40
- zoom = base + d.photo.originalsecret + '_o.' + d.photo.originalformat;
41
- } else {
42
- zoom = base + d.photo.secret + '_m.jpg';
43
- }
59
+ var photo = d.photo;
60
+ if (d.stat == 'ok') {
61
+ var base = 'http://farm' + photo.farm + '.static.flickr.com/' +
62
+ photo.server + '/' + photo.id + '_';
63
+ var zoom;
64
+ if (photo.originalsecret) {
65
+ zoom = base + photo.originalsecret + '_o.' + photo.originalformat;
66
+ } else {
67
+ zoom = base + photo.secret + '_m.jpg';
68
+ }
44
69
 
45
- return Murlsh.new_img(base + d.photo.secret + '_s.jpg',
46
- d.photo.title._content).addClass(
47
- 'thumb flickr').data('zoom', zoom);
70
+ var owner = photo.owner;
71
+ return Murlsh.img(base + photo.secret + '_s.jpg',
72
+ photo.title._content +
73
+ (owner && owner.username ? ' by ' + owner.username : '')
74
+ ).addClass('thumb flickr').data('zoom', zoom);
75
+ }
48
76
  };
49
77
 
50
78
  Murlsh.flickr_click = function() {
51
- Murlsh.closer_add(Murlsh.new_img($(this).data('zoom'), ''));
79
+ Murlsh.closer_add(Murlsh.img($(this).data('zoom')));
52
80
  };
53
81
 
54
- Murlsh.imageshack_thumb = function(prefix, ext) {
55
- return Murlsh.new_img(prefix + 'th.' + ext, '').addClass('thumb imgshack');
82
+ Murlsh.img_thumb = function(prefix, ext) {
83
+ return Murlsh.img(prefix + 'th.' +
84
+ (ext.match(/^pdf$/i) ? 'png' : ext)).addClass('thumb');
56
85
  };
57
86
 
58
- Murlsh.imageshack_click = function() {
59
- Murlsh.closer_add(Murlsh.new_img($(this).data('href'), ''));
87
+ Murlsh.img_click = function() {
88
+ Murlsh.closer_add(Murlsh.img($(this).data('href')));
60
89
  };
61
90
 
62
91
  Murlsh.vimeo_thumb = function(d) {
63
- return Murlsh.new_img(d.thumbnail_url, d.title).addClass('thumb vimeo').attr({
92
+ return Murlsh.img(d.thumbnail_url, d.title).addClass('thumb vimeo').attr({
64
93
  height : d.thumbnail_height,
65
94
  width : d.thumbnail_width
66
95
  });
@@ -71,7 +100,7 @@ Murlsh.vimeo_click = function() {
71
100
  };
72
101
 
73
102
  Murlsh.youtube_thumb = function(id) {
74
- return Murlsh.new_img('http://img.youtube.com/vi/' + id + '/1.jpg',
103
+ return Murlsh.img('http://img.youtube.com/vi/' + id + '/1.jpg',
75
104
  'click to watch').addClass('thumb youtube').data('id', id);
76
105
  };
77
106
 
@@ -81,109 +110,99 @@ Murlsh.youtube_click = function() {
81
110
  Murlsh.closer_add(Murlsh.object_tag(movie, 344, 425, [{ name : 'movie', value : movie }]));
82
111
  };
83
112
 
113
+ Murlsh.thumb_insert = function(img, click_function, a) {
114
+ if (img) {
115
+ if (Murlsh.is_iphone()) {
116
+ a.prepend(img);
117
+ } else {
118
+ a.before(img.click(click_function));
119
+ }
120
+ }
121
+ };
122
+
84
123
  Murlsh.is_iphone = function() {
85
124
  return navigator.userAgent.match(/i(phone|pod)/i);
86
125
  };
87
126
 
127
+ Murlsh.href_res = {
128
+ flickr :
129
+ /^http:\/\/(?:www\.)?flickr\.com\/photos\/[^\/]+?\/([0-9]+)/i,
130
+ imageshack :
131
+ /^(http:\/\/img\d+\.imageshack\.us\/img\d+\/\d+\/\w+\.)(jpe?g|gif|png)$/i,
132
+ mp3 :
133
+ /.*\.mp3$/i,
134
+ s3 :
135
+ /^(http:\/\/static\.mmb\.s3\.amazonaws.com\/.*\.)(jpe?g|gif|pdf|png)$/i,
136
+ vimeo :
137
+ /^http:\/\/(?:www\.)?vimeo\.com\/([0-9]+)$/i,
138
+ youtube :
139
+ /^http:\/\/(?:(?:www|uk)\.)?youtube\.com\/watch\?v=(.+?)(?:&|$)/i
140
+ };
141
+
88
142
  Murlsh.add_extra = function() {
89
143
  var this_a = $(this);
90
144
 
91
145
  var href = $(this).attr('href');
92
146
 
93
- var flickr_match =
94
- /^http:\/\/(?:www\.)?flickr\.com\/photos\/[^\/]+?\/([0-9]+)/i.exec(
95
- href);
96
-
97
- var imageshack_match =
98
- /^(http:\/\/img\d+\.imageshack\.us\/img\d+\/\d+\/\w+\.)(jpg|gif|png)$/i.exec(
99
- href);
100
-
101
- var mp3_match = /.*\.mp3$/i.exec(href);
102
-
103
- var s3_match =
104
- /^(http:\/\/static\.mmb\.s3\.amazonaws.com\/.*\.)(jpg|gif|png)$/i.exec(
105
- href);
106
-
107
- var vimeo_match = /^http:\/\/(?:www\.)?vimeo\.com\/([0-9]+)$/i.exec(href);
108
-
109
- var youtube_match =
110
- /^http:\/\/(?:(?:www|uk)\.)?youtube\.com\/watch\?v=(.+?)(?:&|$)/i.exec(
111
- href);
147
+ var match = {};
148
+ $.each(Murlsh.href_res, function(x, re) { return !(match[x] = re.exec(href)); });
112
149
 
113
150
  var thumb;
114
- var thumb_insert_func;
115
151
 
116
- if (flickr_match) {
117
- thumb_insert_func = function flickr_thumb_insert(d) {
118
- var img = Murlsh.flickr_thumb(d);
119
- if (Murlsh.is_iphone()) {
120
- this_a.prepend(img);
121
- } else {
122
- this_a.before(img.click(Murlsh.flickr_click));
123
- }
152
+ if (match.flickr) {
153
+ var callback = function(d) {
154
+ Murlsh.thumb_insert(Murlsh.flickr_thumb(d), Murlsh.flickr_click, this_a);
124
155
  };
125
156
  $.getJSON('http://api.flickr.com/services/rest/?api_key=d04e574aaf11bf2e1c03cba4ee7e5725&method=flickr.photos.getinfo&format=json&photo_id=' +
126
- flickr_match[1] + '&jsoncallback=?', thumb_insert_func);
127
- } else if (imageshack_match) {
128
- thumb = Murlsh.imageshack_thumb(imageshack_match[1], imageshack_match[2]);
129
- this_a.html('imageshack.us');
130
- if (Murlsh.is_iphone()) {
131
- this_a.prepend(thumb);
132
- } else {
133
- this_a.before(thumb.data('href', imageshack_match[0]).click(
134
- Murlsh.imageshack_click));
135
- }
136
- } else if (mp3_match) {
157
+ match.flickr[1] + '&jsoncallback=?', callback);
158
+ } else if (match.imageshack) {
159
+ thumb = Murlsh.img_thumb(match.imageshack[1], match.imageshack[2]).data(
160
+ 'href', match.imageshack[0]);
161
+ Murlsh.thumb_insert(thumb, Murlsh.img_click, this_a.html('imageshack.us'));
162
+ } else if (match.mp3) {
137
163
  var swf = 'swf/player_mp3_mini.swf';
138
164
  $(this).before(Murlsh.object_tag(swf, 20, 200, [
139
165
  { name : 'bgcolor', value : '#000000' },
140
- { name : 'FlashVars', value : 'mp3=' + mp3_match[0] },
166
+ { name : 'FlashVars', value : 'mp3=' + match.mp3[0] },
141
167
  { name : 'movie', value : swf }
142
168
  ]));
143
- } else if (s3_match) {
144
- thumb = Murlsh.imageshack_thumb(s3_match[1], s3_match[2]);
145
- if (Murlsh.is_iphone()) {
146
- this_a.html(thumb);
169
+ } else if (match.s3) {
170
+ thumb = Murlsh.img_thumb(match.s3[1], match.s3[2]);
171
+ if (match.s3[2].match(/^pdf$/i)) {
172
+ this_a.before(thumb).html('pdf');
147
173
  } else {
148
- this_a.html('link');
149
- this_a.before(thumb.data('href', s3_match[0]).click(
150
- Murlsh.imageshack_click));
151
- }
152
- } else if (vimeo_match) {
153
- thumb_insert_func = function vimeo_thumb_insert(d) {
154
- var img = Murlsh.vimeo_thumb(d);
155
174
  if (Murlsh.is_iphone()) {
156
- this_a.prepend(img);
175
+ this_a.html(thumb);
157
176
  } else {
158
- this_a.before(img.data('embed_html', d.html).click(
159
- Murlsh.vimeo_click));
177
+ this_a.html('link');
178
+ this_a.before(thumb.data('href', match.s3[0]).click(Murlsh.img_click));
160
179
  }
180
+ }
181
+ } else if (match.vimeo) {
182
+ var callback = function(d) {
183
+ var thumb = Murlsh.vimeo_thumb(d).data('embed_html', d.html);
184
+ Murlsh.thumb_insert(thumb, Murlsh.vimeo_click, this_a);
161
185
  };
162
186
  $.getJSON('http://vimeo.com/api/oembed.json?url=http%3A//vimeo.com/' +
163
- vimeo_match[1] + '&callback=?', thumb_insert_func);
164
- } else if (youtube_match) {
165
- var img = Murlsh.youtube_thumb(youtube_match[1]);
166
- if (Murlsh.is_iphone()) {
167
- $(this).prepend(img);
168
- } else {
169
- $(this).before(img.click(Murlsh.youtube_click));
170
- }
187
+ match.vimeo[1] + '&callback=?', callback);
188
+ } else if (match.youtube) {
189
+ thumb = Murlsh.youtube_thumb(match.youtube[1]);
190
+ Murlsh.thumb_insert(thumb, Murlsh.youtube_click, this_a);
171
191
  }
172
192
  };
173
193
 
174
194
  Murlsh.format_li = function(d) {
175
- var li = $('<li />').append($('<a />').attr('href', d.url).text(
176
- d.title));
195
+ var li = Murlsh.tag('li').append(Murlsh.tag('a', { href : d.url }, d.title));
177
196
 
178
197
  if (d.name) {
179
- li.prepend($('<div />').addClass('name').text(d.name));
198
+ li.prepend(Murlsh.tag('div', { klass : 'name' }, d.name));
180
199
  }
181
200
 
182
201
  var icon_size = 32;
183
202
 
184
203
  if (d.email) {
185
- li.prepend($('<div />').addClass('icon').append(
186
- Murlsh.new_img(
204
+ li.prepend(Murlsh.tag('div', { klass : 'icon' }).append(
205
+ Murlsh.img(
187
206
  'http://www.gravatar.com/avatar/' + d.email + '?s=' + icon_size,
188
207
  d.name).attr({
189
208
  width : icon_size,
@@ -194,29 +213,31 @@ Murlsh.format_li = function(d) {
194
213
  return li;
195
214
  };
196
215
 
197
- Murlsh.orientation_changed = function() {
198
- if (window.orientation === 0 || window.orientation == 180) {
199
- $('#urls').width(290);
200
- } else {
201
- $('#urls').width(450);
202
- }
203
- };
216
+ Murlsh.iphone_init = function() {
217
+ window.onorientationchange = function() {
218
+ if (window.orientation === 0 || window.orientation == 180) {
219
+ $('#urls').width(290);
220
+ } else {
221
+ $('#urls').width(450);
222
+ }
223
+ };
224
+
225
+ window.onorientationchange();
204
226
 
205
- window.onorientationchange = Murlsh.orientation_changed;
227
+ $('#urls li:first').prepend(Murlsh.tag('a', { href : '#bottom' }, 'bottom'));
228
+ $('#urls li:last').append(Murlsh.tag('a', { href : '#urls' }, 'top'));
229
+ };
206
230
 
207
231
  $(document).ready(function() {
208
232
  if (Murlsh.is_iphone()) {
209
- Murlsh.orientation_changed();
210
- $('#urls li:first').prepend($('<a />').attr('href', '#bottom').text(
211
- 'bottom'));
212
- $('#urls li:last').append($('<a />').attr('href', '#urls').text('top'));
233
+ Murlsh.iphone_init();
213
234
  }
214
- $('a').map(Murlsh.add_extra);
215
- $('#urls li:even').addClass('even');
235
+ $('#urls a').map(Murlsh.add_extra);
216
236
 
217
237
  $('#submit').click(function() {
218
238
  $.post('url', {
219
239
  url : $('#url').val(),
240
+ via : $('#via').val(),
220
241
  auth : $('#auth').val()
221
242
  }, function(d) {
222
243
  $.each(d, function(i, v) {
@@ -225,6 +246,7 @@ $(document).ready(function() {
225
246
  $(li).children('a:first').map(Murlsh.add_extra);
226
247
  });
227
248
  $('#url').val('');
249
+ $('#via').val('');
228
250
  }, 'json');
229
251
  });
230
252
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: murlsh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew M. Boedicker
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-05 00:00:00 -05:00
12
+ date: 2009-12-13 00:00:00 -05:00
13
13
  default_executable: murlsh
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -107,6 +107,7 @@ files:
107
107
  - lib/murlsh/get_content_type.rb
108
108
  - lib/murlsh/get_title.rb
109
109
  - lib/murlsh/markup.rb
110
+ - lib/murlsh/openlock.rb
110
111
  - lib/murlsh/plugin.rb
111
112
  - lib/murlsh/referrer.rb
112
113
  - lib/murlsh/sqlite3_adapter.rb
@@ -121,7 +122,6 @@ files:
121
122
  - plugins/lookup_content_type_title.rb
122
123
  - plugins/update_feed.rb
123
124
  - public/css/jquery.jgrowl.css
124
- - public/css/phone.css
125
125
  - public/css/screen.css
126
126
  - public/js/jquery-1.3.2.min.js
127
127
  - public/js/jquery.cookie.js
data/public/css/phone.css DELETED
@@ -1,26 +0,0 @@
1
- a.feed {
2
- display : none;
3
- }
4
-
5
- body {
6
- margin : 0;
7
- padding : 0;
8
- }
9
-
10
- #urls {
11
- margin : 0;
12
- padding-left : 0;
13
- width : 290px;
14
- }
15
-
16
- #urls li {
17
- overflow : hidden;
18
- }
19
-
20
- input#q {
21
- width : 130px;
22
- }
23
-
24
- input#url {
25
- width : 160px;
26
- }