murlsh 0.2.4 → 0.3.0

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.textile CHANGED
@@ -16,8 +16,8 @@ Phusion Passenger Setup:
16
16
 
17
17
  <pre>
18
18
  <code>
19
- rake gemspec build
20
- gem install pkg/murlsh-x.x.x.gem
19
+ gem sources -a http://gemcutter.org/
20
+ gem install murlsh
21
21
  </code>
22
22
  </pre>
23
23
 
data/Rakefile CHANGED
@@ -175,6 +175,7 @@ begin
175
175
  gemspec.email = 'matthewm@boedicker.org'
176
176
  gemspec.homepage = 'http://github.com/mmb/murlsh'
177
177
  gemspec.authors = ['Matthew M. Boedicker']
178
+ gemspec.executables = %w{murlsh}
178
179
 
179
180
  %w{
180
181
  activerecord 2.3.4
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.4
1
+ 0.3.0
data/bin/murlsh CHANGED
@@ -6,7 +6,7 @@ FileUtils.cp_r(
6
6
  %w{.htaccess config.ru config.yaml plugins/ public/ Rakefile}.collect { |x|
7
7
  File.join(File.dirname(__FILE__), '..', x) }, '.', :verbose => true)
8
8
 
9
- FileUtils.mkdir('tmp')
9
+ FileUtils.mkdir_p('tmp', :verbose => true)
10
10
 
11
11
  puts <<eos
12
12
  Next steps:
data/config.yaml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- auth_file: /home/mm6/murlsh_users
2
+ auth_file: murlsh_users
3
3
  description: URLs found interesting by Matthew M. Boedicker
4
4
  db_file: murlsh.db
5
5
  feed_file: atom.xml
@@ -5,8 +5,14 @@ require 'uri'
5
5
 
6
6
  module Murlsh
7
7
 
8
+ # ATOM feed builder.
8
9
  class AtomFeed
9
10
 
11
+ # root_url is the base url for the feed items.
12
+ #
13
+ # Options:
14
+ # * :filename - the file name of the feed (atom.xml)
15
+ # * :title - the feed title
10
16
  def initialize(root_url, options={})
11
17
  options = {
12
18
  :filename => 'atom.xml',
@@ -18,6 +24,7 @@ module Murlsh
18
24
  setup_id_fields
19
25
  end
20
26
 
27
+ # Set up fields to use for building item ids.
21
28
  def setup_id_fields
22
29
  uri_parsed = URI(@root_url)
23
30
 
@@ -28,6 +35,7 @@ module Murlsh
28
35
  @path = uri_parsed.path
29
36
  end
30
37
 
38
+ # Generate the feed and write it to the filesystem with locking.
31
39
  def write(entries, path)
32
40
  open(path, 'w') do |f|
33
41
  f.flock(File::LOCK_EX)
@@ -38,6 +46,8 @@ module Murlsh
38
46
  end
39
47
  end
40
48
 
49
+ # Build the feed using XML builder. Options are passed to
50
+ # Builder::XmlMarkup.new.
41
51
  def make(entries, options={})
42
52
  xm = Builder::XmlMarkup.new(options)
43
53
  xm.instruct! :xml
@@ -62,10 +72,12 @@ module Murlsh
62
72
  xm
63
73
  end
64
74
 
75
+ # Build the entry's id.
65
76
  def entry_id(url)
66
77
  "tag:#{@domain},#{url.time.strftime('%Y-%m-%d')}:#{@host}#{@path}#{url.id}"
67
78
  end
68
79
 
80
+ # Add an ATOM enclosure if the url is an image.
69
81
  def enclosure(xm, mu)
70
82
  xm.link(:rel => 'enclosure', :type => mu.content_type, :href => mu.url,
71
83
  :title => 'Full-size') if mu.is_image?
data/lib/murlsh/auth.rb CHANGED
@@ -6,12 +6,21 @@ require 'digest/md5'
6
6
 
7
7
  module Murlsh
8
8
 
9
+ # Interface to authentication file. Format of authentication file:
10
+ #
11
+ # username,MD5 hash of email address,bcrypted password
12
+ #
13
+ # Authentication is done using password only to make adding easier and
14
+ # because there will be a small number of trusted users.
15
+ #
16
+ # See Rakefile for user maintenance tasks.
9
17
  class Auth
10
18
 
11
19
  def initialize(file)
12
20
  @file = file
13
21
  end
14
22
 
23
+ # Authenticate a user by password. Return their name and email if correct.
15
24
  def auth(password)
16
25
  CSV::Reader.parse(open(@file)) do |row|
17
26
  return { :name => row[0], :email => row[1] } if
@@ -19,6 +28,7 @@ module Murlsh
19
28
  end
20
29
  end
21
30
 
31
+ # Add a user to the authentication file.
22
32
  def add_user(username, email, password)
23
33
  open(@file, 'a') do |f|
24
34
  f.flock(File::LOCK_EX)
@@ -11,8 +11,10 @@ yaml
11
11
 
12
12
  module Murlsh
13
13
 
14
+ # Dispatch requests.
14
15
  class Dispatch
15
16
 
17
+ # Set up config hash and database connection.
16
18
  def initialize
17
19
  @config = YAML.load_file('config.yaml')
18
20
  @url_root = URI(@config.fetch('root_url')).path
@@ -25,6 +27,7 @@ module Murlsh
25
27
  @url_server = Murlsh::UrlServer.new(@config, @db)
26
28
  end
27
29
 
30
+ # Rack call.
28
31
  def call(env)
29
32
  dispatch = {
30
33
  ['GET', @url_root] => [@url_server, :get],
@@ -41,6 +44,7 @@ module Murlsh
41
44
  obj.send(meth, req).finish
42
45
  end
43
46
 
47
+ # Called if the request is not found.
44
48
  def not_found(req)
45
49
  Rack::Response.new("<p>#{req.url} not found</p>
46
50
 
@@ -4,6 +4,7 @@ require 'uri'
4
4
 
5
5
  class URI::Generic
6
6
 
7
+ # Return the path and query string.
7
8
  def path_query
8
9
  path + (query ? "?#{query}" : '')
9
10
  end
@@ -14,6 +15,11 @@ module Murlsh
14
15
 
15
16
  module_function
16
17
 
18
+ # Try to get the content type of a url.
19
+ #
20
+ # Options:
21
+ # * :failproof - if true hide all exceptions and return empty string on failure
22
+ # * :headers - hash of headers to send in request
17
23
  def get_content_type(url, options={})
18
24
  options[:headers] = default_headers(url).merge(
19
25
  options.fetch(:headers, {}))
@@ -48,6 +54,10 @@ module Murlsh
48
54
  uri.is_a?(URI::HTTP) ? uri : URI(uri)
49
55
  end
50
56
 
57
+ # Create a Net::HTTP to a host and port.
58
+ #
59
+ # Options:
60
+ # * :debug - stream to write debug output to
51
61
  def make_net_http(url, options={})
52
62
  net_http = Net::HTTP.new(url.host, url.port)
53
63
  net_http.use_ssl = (url.scheme == 'https')
@@ -55,16 +65,14 @@ module Murlsh
55
65
  net_http
56
66
  end
57
67
 
58
- # Get the response to HTTP HEAD. If HEAD not allowed do GET.
68
+ # Get the response to HTTP HEAD. If HEAD returns anything other than success
69
+ # try GET.
59
70
  def get_resp(http, url, headers={})
60
- resp = http.request_head(url.path_query, headers)
61
- if Net::HTTPMethodNotAllowed === resp
62
- http.request_get(url.path_query, headers)
63
- else
64
- resp
65
- end
71
+ resp = http.request_head(url.path_query, headers) === Net::HTTPSuccess ?
72
+ resp : http.request_get(url.path_query, headers)
66
73
  end
67
74
 
75
+ # Get default headers sent with the request. Can be based on url.
68
76
  def default_headers(url)
69
77
  result = {
70
78
  'User-Agent' =>
@@ -10,6 +10,11 @@ module Murlsh
10
10
 
11
11
  module_function
12
12
 
13
+ # Try to get the title of a url.
14
+ #
15
+ # Options:
16
+ # * :failproof - if true hide all exceptions and return empty string on failure
17
+ # * :headers - hash of headers to send in request
13
18
  def get_title(url, options={})
14
19
  options[:headers] = default_headers(url).merge(
15
20
  options.fetch(:headers, {}))
@@ -35,6 +40,8 @@ module Murlsh
35
40
  (result and !result.empty?) ? result : url
36
41
  end
37
42
 
43
+ # Return true if the content type is likely to have a title that can be
44
+ # parsed.
38
45
  def might_have_title(content_type)
39
46
  content_type[/^text\/html/]
40
47
  end
data/lib/murlsh/markup.rb CHANGED
@@ -1,7 +1,12 @@
1
1
  module Murlsh
2
2
 
3
+ # Helper mixin for XML builder.
3
4
  module Markup
4
5
 
6
+ # Javascript link builder. Takes list of script urls.
7
+ #
8
+ # Options:
9
+ # * :prefix - prefix to append to all script urls
5
10
  def javascript(sources, options={})
6
11
  sources.to_a.each do |src|
7
12
  script('', :type => 'text/javascript',
@@ -9,6 +14,15 @@ module Murlsh
9
14
  end
10
15
  end
11
16
 
17
+ # Image tag builder.
18
+ #
19
+ # Options:
20
+ # * :href - make the image a link to this url
21
+ # * :prefix - prefix to append to all image urls
22
+ # * :size - image size if square or [w, h]
23
+ # * :text - text for alt and title tag
24
+ #
25
+ # Any other options in hash will be added as attributes.
12
26
  def murlsh_img(options={})
13
27
  img_convert_prefix(options)
14
28
  img_convert_size(options)
@@ -24,10 +38,16 @@ module Murlsh
24
38
  end
25
39
  end
26
40
 
41
+ # ATOM feed link builder.
27
42
  def atom(href)
28
43
  link(:rel => 'alternate', :type => 'application/atom+xml', :href => href)
29
44
  end
30
45
 
46
+ # CSS link builder.
47
+ #
48
+ # Options:
49
+ # * :media - optional media attribute
50
+ # * :prefix - prepended to all CSS urls
31
51
  def css(hrefs, options={})
32
52
  hrefs.to_a.each do |href|
33
53
  attrs = {
@@ -40,10 +60,16 @@ module Murlsh
40
60
  end
41
61
  end
42
62
 
63
+ # Meta tag builder. Takes a hash of name => content.
43
64
  def metas(tags)
44
65
  tags.each { |k,v| meta(:name => k, :content => v) }
45
66
  end
46
67
 
68
+ # Gravatar builder. Takes MD5 hash of email address.
69
+ # Options:
70
+ # * 'd' - default Gravatar (identicon, monsterid, or wavatar)
71
+ # * 's' - size (0 - 512)
72
+ # * 'r' - rating (g, pg, r or x)
47
73
  def gravatar(email_hash, options={})
48
74
  query = options.reject do |k,v|
49
75
  not ((k == 'd' and %w{identicon monsterid wavatar}.include?(v)) or
@@ -60,6 +86,7 @@ module Murlsh
60
86
  murlsh_img(options)
61
87
  end
62
88
 
89
+ # Query string builder. Takes hash of query string variables.
63
90
  def build_query(h)
64
91
  h.empty? ? '' :
65
92
  '?' + h.collect { |k,v| URI.escape("#{k}=#{v}") }.join('&')
data/lib/murlsh/plugin.rb CHANGED
@@ -1,13 +1,26 @@
1
1
  module Murlsh
2
2
 
3
+ # Superclass for plugins. How plugins are registered.
4
+ #
5
+ # Hooks:
6
+ # * add_pre - called before a new url is saved
7
+ # run arguments (url, config hash)
8
+ # * add_post - called after a new url is saved
9
+ # run arguments (config hash)
10
+ # * hostrec - called to post process the domain that shows after links
11
+ # run arguments (domain, url, title)
3
12
  class Plugin
4
13
 
14
+ # Called when a plugin class inherits from this class (the way plugins
15
+ # are registered).
5
16
  def self.inherited(child)
6
17
  registered << child
7
18
  end
8
19
 
20
+ # Get registered plugins by hook (add_pre, add_post, etc.)
9
21
  def self.hooks(name)
10
- matches = registered.select { |p| p::Hook == name }
22
+ matches = registered.select { |p| p::Hook == name }.
23
+ sort { |a,b| a.to_s <=> b.to_s }
11
24
 
12
25
  if block_given?
13
26
  matches.each { |p| yield p }
@@ -3,6 +3,7 @@ require 'uri'
3
3
 
4
4
  module Murlsh
5
5
 
6
+ # For parsing query strings from referring search engines.
6
7
  class Referrer
7
8
 
8
9
  def initialize(url)
@@ -19,6 +20,7 @@ module Murlsh
19
20
  end
20
21
  end
21
22
 
23
+ # Get the searched for string from a search engine query string.
22
24
  def search_query(qmap=Qmap)
23
25
  if hostpath and query_string
24
26
  qmap.each_pair do |r,v|
@@ -34,6 +36,7 @@ module Murlsh
34
36
  nil
35
37
  end
36
38
 
39
+ # Regex host match to name of query string parameter.
37
40
  Qmap = {
38
41
  /^www\.google\.(bs|ca|com|cz|dk|es|fi|nl)(\/m)?\/search$/ => 'q',
39
42
  /^www\.bing\.com\/search$/ => 'q',
@@ -2,6 +2,7 @@ require 'active_record/connection_adapters/sqlite3_adapter'
2
2
 
3
3
  class ActiveRecord::ConnectionAdapters::SQLite3Adapter
4
4
 
5
+ # Add MATCH function for regex matching.
5
6
  def initialize(connection, logger, config)
6
7
  super
7
8
  @connection.create_function('MATCH', 2) do |func,search_in,search_for|
data/lib/murlsh/time.rb CHANGED
@@ -2,6 +2,8 @@ require 'time'
2
2
 
3
3
  class Time
4
4
 
5
+ # Return a string of the approximate amount of time that has passed since
6
+ # this time.
5
7
  def fuzzy
6
8
  days_ago = (Time.now.to_i - to_i) / 86400
7
9
 
data/lib/murlsh/url.rb CHANGED
@@ -5,36 +5,35 @@ require 'uri'
5
5
 
6
6
  module Murlsh
7
7
 
8
+ # URL ActiveRecord.
8
9
  class Url < ActiveRecord::Base
9
10
 
11
+ # Get the title of this url.
10
12
  def title
11
13
  read_attribute(:title) || read_attribute(:url) || 'title missing'
12
14
  end
13
15
 
16
+ # Return true if this url has the same author as another url.
14
17
  def same_author?(other)
15
18
  other and other.email and other.name and
16
19
  email and name and email == other.email and name == other.name
17
20
  end
18
21
 
19
- Widely_known = %w{
20
- wikipedia.org
21
- flickr.com
22
- github.com
23
- twitter.com
24
- vimeo.com
25
- youtube.com
26
- }
27
-
22
+ # Return text showing what domain a link goes to.
28
23
  def hostrec
29
24
  begin
30
25
  domain = URI(url).host[/[a-z\d-]+\.[a-z]{2,}(\.[a-z]{2})?$/].downcase
31
26
  rescue Exception => e
32
27
  domain = nil
33
28
  end
34
- yield domain unless !domain or title.downcase.index(domain) or
35
- Widely_known.include?(domain)
29
+
30
+ domain = Murlsh::Plugin.hooks('hostrec').inject(domain) {
31
+ |result,plugin| plugin.run(result, url, title) }
32
+
33
+ yield domain if domain
36
34
  end
37
35
 
36
+ # Return true if this url is an image.
38
37
  def is_image?
39
38
  %w{image/gif image/jpeg image/png}.include?(content_type)
40
39
  end
@@ -1,5 +1,6 @@
1
1
  module Murlsh
2
2
 
3
+ # Url list page builder.
3
4
  class UrlBody < Builder::XmlMarkup
4
5
  include Murlsh::Markup
5
6
 
@@ -8,12 +9,14 @@ module Murlsh
8
9
  super(:indent => 2)
9
10
  end
10
11
 
12
+ # Fetch urls base on query string parameters.
11
13
  def urls
12
14
  Murlsh::Url.all(:conditions => search_conditions, :order => 'id DESC',
13
15
  :limit => @req.params['n'] ? @req.params['n'].to_i :
14
16
  @config.fetch('num_posts_page', 100))
15
17
  end
16
18
 
19
+ # Search conditions builder for ActiveRecord conditions.
17
20
  def search_conditions
18
21
  if @q
19
22
  search_cols = %w{name title url}
@@ -24,6 +27,7 @@ module Murlsh
24
27
  end
25
28
  end
26
29
 
30
+ # Url list page body builder.
27
31
  def each
28
32
  instruct! :xml
29
33
  declare! :DOCTYPE, :html, :PUBLIC, '-//W3C//DTD XHTML 1.1//EN',
@@ -65,10 +69,12 @@ module Murlsh
65
69
  clear
66
70
  powered_by
67
71
  js
72
+ div('', :id => 'bottom')
68
73
  }
69
74
  }
70
75
  end
71
76
 
77
+ # Head builder.
72
78
  def headd
73
79
  head {
74
80
  titlee
@@ -84,20 +90,24 @@ module Murlsh
84
90
  }
85
91
  end
86
92
 
93
+ # Title builder.
87
94
  def titlee
88
95
  title(@config.fetch('page_title', '') + (@q ? " /#{@q}" : ''))
89
96
  end
90
97
 
98
+ # Google verification link builder.
91
99
  def google_verify
92
100
  (gv = @config.fetch('google_verify')) and metas('verify-v1' => gv)
93
101
  end
94
102
 
103
+ # Feed icon builder.
95
104
  def feed_icon
96
105
  div(:class => 'icon') {
97
106
  a('feed', :href => @config.fetch('feed_file'), :class => 'feed')
98
107
  }
99
108
  end
100
109
 
110
+ # Search form builder.
101
111
  def search_form
102
112
  form(:action => '', :method => 'get') {
103
113
  value = @q
@@ -113,6 +123,7 @@ module Murlsh
113
123
  }
114
124
  end
115
125
 
126
+ # Url add form builder.
116
127
  def add_form
117
128
  form(:action => '', :method => 'post') {
118
129
  fieldset(:id => 'add') {
@@ -125,15 +136,18 @@ module Murlsh
125
136
  }
126
137
  end
127
138
 
139
+ # Url add form input builder.
128
140
  def add_form_input(label, id, size, tipe='text')
129
141
  label(label, :for => id)
130
142
  input(:type => tipe, :id => id, :name => id, :size => size)
131
143
  end
132
144
 
145
+ # Clear div builder.
133
146
  def clear
134
147
  div(:style => 'clear : both')
135
148
  end
136
149
 
150
+ # Powered by builder.
137
151
  def powered_by
138
152
  self.p {
139
153
  text! 'powered by '
@@ -141,6 +155,7 @@ module Murlsh
141
155
  }
142
156
  end
143
157
 
158
+ # Required javascript builder.
144
159
  def js
145
160
  javascript(%w{
146
161
  jquery-1.3.2.min.js
@@ -6,6 +6,7 @@ rack
6
6
 
7
7
  module Murlsh
8
8
 
9
+ # Build responses for HTTP requests.
9
10
  class UrlServer
10
11
 
11
12
  def initialize(config, db)
@@ -16,6 +17,8 @@ module Murlsh
16
17
  Dir['plugins/*.rb'].each { |p| load p }
17
18
  end
18
19
 
20
+ # Respond to a GET request. Return a page of urls based on the query
21
+ # string parameters.
19
22
  def get(req)
20
23
  resp = Murlsh::XhtmlResponse.new
21
24
 
@@ -30,6 +33,7 @@ module Murlsh
30
33
  resp
31
34
  end
32
35
 
36
+ # Respond to a POST request. Add the new url and return json.
33
37
  def post(req)
34
38
  resp = Rack::Response.new
35
39
 
@@ -42,16 +46,15 @@ module Murlsh
42
46
  ActiveRecord::Base.establish_connection(:adapter => 'sqlite3',
43
47
  :database => @config.fetch('db_file'))
44
48
 
45
- content_type = Murlsh.get_content_type(url)
46
49
  mu = Murlsh::Url.new do |u|
47
50
  u.time = Time.now.gmtime
48
51
  u.url = url
49
52
  u.email = user[:email]
50
53
  u.name = user[:name]
51
- u.title = Murlsh.get_title(url, :content_type => content_type)
52
- u.content_type = content_type
53
54
  end
54
55
 
56
+ Murlsh::Plugin.hooks('add_pre') { |p| p.run(mu, @config) }
57
+
55
58
  mu.save
56
59
 
57
60
  Murlsh::Plugin.hooks('add_post') { |p| p.run(@config) }
@@ -1,9 +1,10 @@
1
1
  module Murlsh
2
2
 
3
+ # Set the content type correctly based on accept header and user agent.
3
4
  class XhtmlResponse < Rack::Response
4
5
 
5
- # set the content type to application/xhtml+xml for anything that
6
- # claims to accept it, for anything else or IE use text/html
6
+ # Set the content type to application/xhtml+xml for anything that
7
+ # claims to accept it, for anything else or IE use text/html.
7
8
  def set_content_type(http_accept, http_user_agent)
8
9
  self['Content-Type'] = if http_accept and
9
10
  http_accept[/((\*|application)\/\*|application\/xhtml\+xml)/i] and
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.2.4"
8
+ s.version = "0.3.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-10-23}
12
+ s.date = %q{2009-11-05}
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}
@@ -43,6 +43,9 @@ Gem::Specification.new do |s|
43
43
  "lib/murlsh/url_server.rb",
44
44
  "lib/murlsh/xhtml_response.rb",
45
45
  "murlsh.gemspec",
46
+ "plugins/hostrec_redundant.rb",
47
+ "plugins/hostrec_skip.rb",
48
+ "plugins/lookup_content_type_title.rb",
46
49
  "plugins/update_feed.rb",
47
50
  "public/css/jquery.jgrowl.css",
48
51
  "public/css/phone.css",
@@ -0,0 +1,14 @@
1
+ module Murlsh
2
+
3
+ # skip showing host record if domain is contained in title
4
+ class HostrecRedundant < Plugin
5
+
6
+ Hook = 'hostrec'
7
+
8
+ def self.run(domain, url, title)
9
+ domain unless (title and domain and title.downcase.index(domain))
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,23 @@
1
+ module Murlsh
2
+
3
+ # skip showing host record for some domains
4
+ class HostrecSkip < Plugin
5
+
6
+ Hook = 'hostrec'
7
+
8
+ def self.run(domain, url, title)
9
+ domain unless Skips.include?(domain)
10
+ end
11
+
12
+ Skips = %w{
13
+ wikipedia.org
14
+ flickr.com
15
+ github.com
16
+ twitter.com
17
+ vimeo.com
18
+ youtube.com
19
+ }
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,17 @@
1
+ require 'murlsh'
2
+
3
+ module Murlsh
4
+
5
+ # try to fetch the content type and title of a url
6
+ class LookupContentTypeTitle < Plugin
7
+
8
+ Hook = 'add_pre'
9
+
10
+ def self.run(url, config)
11
+ url.content_type = Murlsh.get_content_type(url.url)
12
+ url.title = Murlsh.get_title(url.url, :content_type => url.content_type)
13
+ end
14
+
15
+ end
16
+
17
+ end
data/public/css/phone.css CHANGED
@@ -1,3 +1,7 @@
1
+ a.feed {
2
+ display : none;
3
+ }
4
+
1
5
  body {
2
6
  margin : 0;
3
7
  padding : 0;
@@ -9,6 +13,14 @@ body {
9
13
  width : 290px;
10
14
  }
11
15
 
16
+ #urls li {
17
+ overflow : hidden;
18
+ }
19
+
12
20
  input#q {
13
21
  width : 130px;
14
22
  }
23
+
24
+ input#url {
25
+ width : 160px;
26
+ }
data/public/js/js.js CHANGED
@@ -205,7 +205,12 @@ Murlsh.orientation_changed = function() {
205
205
  window.onorientationchange = Murlsh.orientation_changed;
206
206
 
207
207
  $(document).ready(function() {
208
- Murlsh.orientation_changed();
208
+ 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'));
213
+ }
209
214
  $('a').map(Murlsh.add_extra);
210
215
  $('#urls li:even').addClass('even');
211
216
 
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.2.4
4
+ version: 0.3.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-10-23 00:00:00 -04:00
12
+ date: 2009-11-05 00:00:00 -05:00
13
13
  default_executable: murlsh
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -116,6 +116,9 @@ files:
116
116
  - lib/murlsh/url_server.rb
117
117
  - lib/murlsh/xhtml_response.rb
118
118
  - murlsh.gemspec
119
+ - plugins/hostrec_redundant.rb
120
+ - plugins/hostrec_skip.rb
121
+ - plugins/lookup_content_type_title.rb
119
122
  - plugins/update_feed.rb
120
123
  - public/css/jquery.jgrowl.css
121
124
  - public/css/phone.css