sinatra-support 1.1.2 → 1.1.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/HISTORY.md CHANGED
@@ -1,3 +1,9 @@
1
+ v1.1.3 - May 27, 2011
2
+ ---------------------
3
+
4
+ ### Added:
5
+ * `Sinatra::UserAgentHelpers` for browser detection
6
+
1
7
  v1.1.2 - May 27, 2011
2
8
  ---------------------
3
9
 
@@ -8,6 +8,7 @@ module Sinatra
8
8
  autoload :HtmlHelpers, File.expand_path('../support/htmlhelpers', __FILE__)
9
9
  autoload :JsSupport, File.expand_path('../support/jssupport', __FILE__)
10
10
  autoload :OhmErrorHelpers, File.expand_path('../support/ohmerrorhelpers', __FILE__)
11
+ autoload :UserAgentHelpers,File.expand_path('../support/useragenthelpers', __FILE__)
11
12
  autoload :Numeric, File.expand_path('../support/numeric', __FILE__)
12
13
  autoload :IfHelpers, File.expand_path('../support/ifhelpers', __FILE__)
13
14
  autoload :I18nSupport, File.expand_path('../support/i18nsupport', __FILE__)
@@ -0,0 +1,134 @@
1
+ # == Usage
2
+ #
3
+ # register Sinatra::UserAgentHelpers
4
+ #
5
+ # == Example
6
+ #
7
+ # After you have registered the UserAgentHelpers, use the {#browser} helper to
8
+ # check for features:
9
+ #
10
+ # <% if browser.ios? %>
11
+ # <p>Download our mobile app!</p>
12
+ # <% end %>
13
+ #
14
+ # Or use the #body_class method:
15
+ #
16
+ # <body class="<%= browser.body_class %>">
17
+ #
18
+ # The above line can have an output like so:
19
+ #
20
+ # <body class="webkit safari mac">
21
+ # <body class="windows ie ie6">
22
+ #
23
+ # == Helper
24
+ #
25
+ # #browser -- provides the browser helper. Refer to the {UserAgent} class
26
+ # for more info.
27
+ #
28
+ module Sinatra::UserAgentHelpers
29
+ def browser
30
+ UserAgent.new(env['HTTP_USER_AGENT'] || '')
31
+ end
32
+ end
33
+
34
+ class UserAgent
35
+ UA_REGEXP = %r{([^ /]+)/([^ ]+)(?: \(([^)]+)\))?}
36
+
37
+ def initialize(ua)
38
+ @ua_string = ua
39
+ @ua = ua.scan(UA_REGEXP).map { |r|
40
+ r[2] = r[2].split(';').map { |s| s.strip } unless r[2].nil?
41
+ { :product => r[0], :version => r[1], :details => r[2] }
42
+ }
43
+ end
44
+
45
+ # Browsers
46
+ def webkit?() product?('AppleWebKit'); end
47
+ def chrome?() product?('Chrome'); end
48
+ def safari?() product?('Safari') && !chrome?; end
49
+ def ios?() product?('Safari') && product?('Mobile'); end
50
+ def gecko?() product?('Gecko'); end
51
+ def opera?() product?('Opera'); end
52
+ def ie?() detail?(/^MSIE/, 'Mozilla'); end
53
+
54
+ # OS's and devices
55
+ def linux?() detail?(/^Linux/, 'Mozilla'); end
56
+ def iphone?() detail?(/^iPhone/, 'Mozilla'); end
57
+ def rim?() detail?(/^Blackberry/, 'Mozilla'); end
58
+ def android?() detail?(/^Android/, 'Mozilla'); end
59
+ def android1?() detail?(/^Android 1\./, 'Mozilla'); end
60
+ def android2?() detail?(/^Android 2\./, 'Mozilla'); end
61
+ def nokia?() detail?(/^Nokia/, 'Mozilla') || detail?(/^Series[38]0/, 'Mozilla'); end
62
+ def ipad?() detail?(/^iPad/, 'Mozilla'); end
63
+ def windows?() detail?(/^Windows/, 'Mozilla'); end
64
+ def osx?() detail?(/^(Intel )?Mac OS X/, 'Mozilla'); end
65
+ def mac?() detail?(/^Macintosh/, 'Mozilla') || osx?; end
66
+ def blackberry?() detail?(/^Blackberry/, 'Mozilla'); end
67
+
68
+ # IE
69
+ def ie9?() detail?('MSIE 9.0', 'Mozilla'); end
70
+ def ie8?() detail?('MSIE 8.0', 'Mozilla'); end
71
+ def ie7?() detail?(/^MSIE 7.0/, 'Mozilla'); end
72
+ def ie6?() detail?(/^MSIE 6/, 'Mozilla'); end
73
+
74
+ # Different Firefox versions
75
+ def gecko40?() gecko_version?(20100401, 20110101); end
76
+ def gecko36?() gecko_version?(20091111, 20100401); end
77
+ def gecko35?() gecko_version?(20090612, 20091111); end
78
+ def gecko30?() gecko_version?(20080610, 20090612); end
79
+ def gecko20?() gecko_version?(20061010, 20080610); end
80
+ def gecko_old?() gecko_version?(0, 20061010); end
81
+
82
+ def gecko_version?(from, to)
83
+ g = product('Gecko')
84
+ return nil if g.nil?
85
+ v = g[:version][0...8].to_i
86
+ (v >= from) and (v < to)
87
+ end
88
+
89
+ # Returns the list of applicable browser features.
90
+ #
91
+ # == Examples
92
+ #
93
+ # <body class="<%= browser.body_class %>">
94
+ #
95
+ # This can return one of the following:
96
+ #
97
+ # <body class="ios webkit ipad">
98
+ # <body class="chrome linux webkit">
99
+ # <body class="gecko linux">
100
+ # <body class="windows ie ie6">
101
+ #
102
+ def body_class
103
+ (%w(webkit chrome safari ios gecko opera ie linux) +
104
+ %w(blackberry nokia android iphone) +
105
+ %w(gecko36 gecko35 gecko30 gecko20 gecko_old) +
106
+ %w(ipad windows osx mac ie6 ie7 ie8 ie9)).map do |aspect|
107
+ aspect if self.send :"#{aspect}?"
108
+ end.compact.join(' ')
109
+ end
110
+
111
+ private
112
+ def to_s() @ua_string; end
113
+ def inspect() @ua.inspect; end
114
+
115
+ # Checks for, say, 'Gecko' in 'Gecko/3.9.82'
116
+ def product?(str)
117
+ !! product(str)
118
+ end
119
+
120
+ def product(str)
121
+ @ua.detect { |p| p[:product] == str }
122
+ end
123
+
124
+ # Checks for, say, 'MSIE' in 'Mozilla/5.0 (MSIE; x; x)'
125
+ def detail?(detail, prod=nil)
126
+ !! @ua.detect { |p|
127
+ prod.nil? || prod == p[:product] && has_spec(p[:details], detail)
128
+ }
129
+ end
130
+
131
+ def has_spec(haystack, spec)
132
+ !haystack.nil? && haystack.detect { |d| d.match(spec) }
133
+ end
134
+ end
@@ -1,6 +1,6 @@
1
1
  module Sinatra
2
2
  module Support
3
- VERSION = "1.1.2"
3
+ VERSION = "1.1.3"
4
4
 
5
5
  def self.version
6
6
  VERSION
@@ -0,0 +1,25 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ Encoding.default_external = 'utf-8'
4
+
5
+ class UserAgentAppTest < Test::Unit::TestCase
6
+ include Rack::Test::Methods
7
+
8
+ class App < Sinatra::Base
9
+ helpers Sinatra::UserAgentHelpers
10
+ get('/class') { "<body class='#{browser.body_class}'>" }
11
+ end
12
+
13
+ UA_CHROME = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_7) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.68 Safari/534.24"
14
+
15
+ def app
16
+ App.new
17
+ end
18
+
19
+ test "boogie" do
20
+ header 'User-Agent', UA_CHROME
21
+ get '/class'
22
+
23
+ assert_equal "<body class='webkit chrome osx mac'>", last_response.body.strip
24
+ end
25
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: sinatra-support
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.1.2
5
+ version: 1.1.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Cyril David
@@ -116,6 +116,7 @@ files:
116
116
  - lib/sinatra/support/multirender.rb
117
117
  - lib/sinatra/support/numeric.rb
118
118
  - lib/sinatra/support/ohmerrorhelpers.rb
119
+ - lib/sinatra/support/useragenthelpers.rb
119
120
  - lib/sinatra/support/version.rb
120
121
  - lib/sinatra/support.rb
121
122
  - test/fixtures/css/style-less.less
@@ -141,6 +142,7 @@ files:
141
142
  - test/test_multirender.rb
142
143
  - test/test_numeric.rb
143
144
  - test/test_ohmerror.rb
145
+ - test/test_useragent_app.rb
144
146
  - HISTORY.md
145
147
  - Rakefile
146
148
  has_rdoc: true