browser 0.1.6 → 0.2.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.
- checksums.yaml +7 -0
- data/.gitignore +2 -1
- data/.travis.yml +8 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +70 -38
- data/README.md +114 -0
- data/Rakefile +12 -10
- data/browser.gemspec +2 -4
- data/config.ru +2 -0
- data/gemfiles/rails3.gemfile +4 -0
- data/gemfiles/rails3.gemfile.lock +111 -0
- data/lib/browser.rb +57 -283
- data/lib/browser/action_controller.rb +9 -7
- data/lib/browser/meta/base.rb +20 -0
- data/lib/browser/meta/generic_browser.rb +9 -0
- data/lib/browser/meta/id.rb +9 -0
- data/lib/browser/meta/ie.rb +18 -0
- data/lib/browser/meta/ios.rb +9 -0
- data/lib/browser/meta/mobile.rb +9 -0
- data/lib/browser/meta/modern.rb +9 -0
- data/lib/browser/meta/platform.rb +9 -0
- data/lib/browser/meta/safari.rb +9 -0
- data/lib/browser/meta/webkit.rb +9 -0
- data/lib/browser/methods/devices.rb +33 -0
- data/lib/browser/methods/ie.rb +40 -0
- data/lib/browser/methods/language.rb +131 -0
- data/lib/browser/methods/mobile.rb +23 -0
- data/lib/browser/methods/platform.rb +54 -0
- data/lib/browser/middleware.rb +43 -0
- data/lib/browser/middleware/context.rb +20 -0
- data/lib/browser/middleware/context/additions.rb +16 -0
- data/lib/browser/middleware/context/url_methods.rb +13 -0
- data/lib/browser/rails.rb +14 -0
- data/lib/browser/version.rb +2 -2
- data/test/browser_test.rb +220 -74
- data/test/middleware_test.rb +32 -0
- data/test/sample_app.rb +27 -0
- data/test/test_helper.rb +2 -1
- metadata +43 -57
- data/README.rdoc +0 -75
data/lib/browser.rb
CHANGED
@@ -1,15 +1,35 @@
|
|
1
1
|
require "set"
|
2
2
|
|
3
|
+
require "browser/middleware"
|
4
|
+
require "browser/middleware/context"
|
5
|
+
require "browser/rails" if defined?(::Rails)
|
6
|
+
|
7
|
+
require "browser/methods/ie"
|
8
|
+
require "browser/methods/platform"
|
9
|
+
require "browser/methods/mobile"
|
10
|
+
require "browser/methods/devices"
|
11
|
+
require "browser/methods/language"
|
12
|
+
|
13
|
+
require "browser/meta/base"
|
14
|
+
require "browser/meta/generic_browser"
|
15
|
+
require "browser/meta/id"
|
16
|
+
require "browser/meta/ie"
|
17
|
+
require "browser/meta/ios"
|
18
|
+
require "browser/meta/mobile"
|
19
|
+
require "browser/meta/modern"
|
20
|
+
require "browser/meta/platform"
|
21
|
+
require "browser/meta/safari"
|
22
|
+
require "browser/meta/webkit"
|
23
|
+
|
3
24
|
class Browser
|
4
|
-
|
5
|
-
|
25
|
+
include IE
|
26
|
+
include Platform
|
27
|
+
include Mobile
|
28
|
+
include Devices
|
29
|
+
include Language
|
6
30
|
|
7
31
|
# Set browser's UA string.
|
8
32
|
attr_accessor :user_agent
|
9
|
-
|
10
|
-
# Set browser's preferred language
|
11
|
-
attr_writer :accept_language
|
12
|
-
|
13
33
|
alias :ua :user_agent
|
14
34
|
alias :ua= :user_agent=
|
15
35
|
|
@@ -17,141 +37,25 @@ class Browser
|
|
17
37
|
:android => "Android",
|
18
38
|
:blackberry => "BlackBerry",
|
19
39
|
:chrome => "Chrome",
|
40
|
+
:core_media => "Apple CoreMedia",
|
20
41
|
:firefox => "Firefox",
|
21
42
|
:ie => "Internet Explorer",
|
22
43
|
:ipad => "iPad",
|
23
44
|
:iphone => "iPhone",
|
24
45
|
:ipod => "iPod Touch",
|
25
46
|
:opera => "Opera",
|
26
|
-
:
|
27
|
-
:safari => "Safari",
|
47
|
+
:phantom_js => "PhantomJS",
|
28
48
|
:psp => "PlayStation Portable",
|
29
49
|
:quicktime => "QuickTime",
|
30
|
-
:
|
31
|
-
}
|
50
|
+
:safari => "Safari",
|
32
51
|
|
33
|
-
|
34
|
-
:
|
35
|
-
:opera => /Opera\/.*? Version\/([\d.]+)/
|
52
|
+
# This must be last item, since Ruby 1.9+ has ordered keys.
|
53
|
+
:other => "Other",
|
36
54
|
}
|
37
55
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
"af" => "Afrikaans",
|
42
|
-
"sq" => "Albanian",
|
43
|
-
"eu" => "Basque",
|
44
|
-
"bg" => "Bulgarian",
|
45
|
-
"be" => "Byelorussian",
|
46
|
-
"ca" => "Catalan",
|
47
|
-
"zh" => "Chinese",
|
48
|
-
"zh-cn" => "Chinese/China",
|
49
|
-
"zh-tw" => "Chinese/Taiwan",
|
50
|
-
"zh-hk" => "Chinese/Hong Kong",
|
51
|
-
"zh-sg" => "Chinese/singapore",
|
52
|
-
"hr" => "Croatian",
|
53
|
-
"cs" => "Czech",
|
54
|
-
"da" => "Danish",
|
55
|
-
"nl" => "Dutch",
|
56
|
-
"nl-nl" => "Dutch/Netherlands",
|
57
|
-
"nl-be" => "Dutch/Belgium",
|
58
|
-
"en" => "English",
|
59
|
-
"en-gb" => "English/United Kingdom",
|
60
|
-
"en-us" => "English/United States",
|
61
|
-
"en-au" => "English/Australian",
|
62
|
-
"en-ca" => "English/Canada",
|
63
|
-
"en-nz" => "English/New Zealand",
|
64
|
-
"en-ie" => "English/Ireland",
|
65
|
-
"en-za" => "English/South Africa",
|
66
|
-
"en-jm" => "English/Jamaica",
|
67
|
-
"en-bz" => "English/Belize",
|
68
|
-
"en-tt" => "English/Trinidad",
|
69
|
-
"et" => "Estonian",
|
70
|
-
"fo" => "Faeroese",
|
71
|
-
"fa" => "Farsi",
|
72
|
-
"fi" => "Finnish",
|
73
|
-
"fr" => "French",
|
74
|
-
"fr-be" => "French/Belgium",
|
75
|
-
"fr-fr" => "French/France",
|
76
|
-
"fr-ch" => "French/Switzerland",
|
77
|
-
"fr-ca" => "French/Canada",
|
78
|
-
"fr-lu" => "French/Luxembourg",
|
79
|
-
"gd" => "Gaelic",
|
80
|
-
"gl" => "Galician",
|
81
|
-
"de" => "German",
|
82
|
-
"de-at" => "German/Austria",
|
83
|
-
"de-de" => "German/Germany",
|
84
|
-
"de-ch" => "German/Switzerland",
|
85
|
-
"de-lu" => "German/Luxembourg",
|
86
|
-
"de-li" => "German/Liechtenstein",
|
87
|
-
"el" => "Greek",
|
88
|
-
"he" => "Hebrew",
|
89
|
-
"he-il" => "Hebrew/Israel",
|
90
|
-
"hi" => "Hindi",
|
91
|
-
"hu" => "Hungarian",
|
92
|
-
"ie-ee" => "Internet Explorer/Easter Egg",
|
93
|
-
"is" => "Icelandic",
|
94
|
-
"id" => "Indonesian",
|
95
|
-
"in" => "Indonesian",
|
96
|
-
"ga" => "Irish",
|
97
|
-
"it" => "Italian",
|
98
|
-
"it-ch" => "Italian/ Switzerland",
|
99
|
-
"ja" => "Japanese",
|
100
|
-
"km" => "Khmer",
|
101
|
-
"km-kh" => "Khmer/Cambodia",
|
102
|
-
"ko" => "Korean",
|
103
|
-
"lv" => "Latvian",
|
104
|
-
"lt" => "Lithuanian",
|
105
|
-
"mk" => "Macedonian",
|
106
|
-
"ms" => "Malaysian",
|
107
|
-
"mt" => "Maltese",
|
108
|
-
"no" => "Norwegian",
|
109
|
-
"pl" => "Polish",
|
110
|
-
"pt" => "Portuguese",
|
111
|
-
"pt-br" => "Portuguese/Brazil",
|
112
|
-
"rm" => "Rhaeto-Romanic",
|
113
|
-
"ro" => "Romanian",
|
114
|
-
"ro-mo" => "Romanian/Moldavia",
|
115
|
-
"ru" => "Russian",
|
116
|
-
"ru-mo" => "Russian /Moldavia",
|
117
|
-
"gd" => "Scots Gaelic",
|
118
|
-
"sr" => "Serbian",
|
119
|
-
"sk" => "Slovack",
|
120
|
-
"sl" => "Slovenian",
|
121
|
-
"sb" => "Sorbian",
|
122
|
-
"es" => "Spanish",
|
123
|
-
"es-do" => "Spanish",
|
124
|
-
"es-ar" => "Spanish/Argentina",
|
125
|
-
"es-co" => "Spanish/Colombia",
|
126
|
-
"es-mx" => "Spanish/Mexico",
|
127
|
-
"es-es" => "Spanish/Spain",
|
128
|
-
"es-gt" => "Spanish/Guatemala",
|
129
|
-
"es-cr" => "Spanish/Costa Rica",
|
130
|
-
"es-pa" => "Spanish/Panama",
|
131
|
-
"es-ve" => "Spanish/Venezuela",
|
132
|
-
"es-pe" => "Spanish/Peru",
|
133
|
-
"es-ec" => "Spanish/Ecuador",
|
134
|
-
"es-cl" => "Spanish/Chile",
|
135
|
-
"es-uy" => "Spanish/Uruguay",
|
136
|
-
"es-py" => "Spanish/Paraguay",
|
137
|
-
"es-bo" => "Spanish/Bolivia",
|
138
|
-
"es-sv" => "Spanish/El salvador",
|
139
|
-
"es-hn" => "Spanish/Honduras",
|
140
|
-
"es-ni" => "Spanish/Nicaragua",
|
141
|
-
"es-pr" => "Spanish/Puerto Rico",
|
142
|
-
"sx" => "Sutu",
|
143
|
-
"sv" => "Swedish",
|
144
|
-
"sv-se" => "Swedish/Sweden",
|
145
|
-
"sv-fi" => "Swedish/Finland",
|
146
|
-
"ts" => "Thai",
|
147
|
-
"tn" => "Tswana",
|
148
|
-
"tr" => "Turkish",
|
149
|
-
"uk" => "Ukrainian",
|
150
|
-
"ur" => "Urdu",
|
151
|
-
"vi" => "Vietnamese",
|
152
|
-
"xh" => "Xshosa",
|
153
|
-
"ji" => "Yiddish",
|
154
|
-
"zu" => "Zulu"
|
56
|
+
VERSIONS = {
|
57
|
+
:default => %r[(?:Version|MSIE|Firefox|Chrome|CriOS|QuickTime|BlackBerry[^/]+|CoreMedia v|PhantomJS)[/ ]?([a-z0-9.]+)]i,
|
58
|
+
:opera => %r[(?:Opera/.*? Version/([\d.]+)|Chrome/([\d.]+).*?OPR)]
|
155
59
|
}
|
156
60
|
|
157
61
|
# Create a new browser instance and set
|
@@ -163,8 +67,8 @@ class Browser
|
|
163
67
|
# })
|
164
68
|
#
|
165
69
|
def initialize(options = {}, &block)
|
166
|
-
|
167
|
-
|
70
|
+
self.user_agent = (options[:user_agent] || options[:ua]).to_s
|
71
|
+
self.accept_language = options[:accept_language].to_s
|
168
72
|
|
169
73
|
yield self if block_given?
|
170
74
|
end
|
@@ -174,30 +78,10 @@ class Browser
|
|
174
78
|
NAMES[id]
|
175
79
|
end
|
176
80
|
|
177
|
-
#
|
81
|
+
# Get the browser identifier.
|
178
82
|
def id
|
179
|
-
|
180
|
-
|
181
|
-
when iphone? then :iphone
|
182
|
-
when ipad? then :ipad
|
183
|
-
when ipod? then :ipod
|
184
|
-
when ie? then :ie
|
185
|
-
when opera? then :opera
|
186
|
-
when firefox? then :firefox
|
187
|
-
when android? then :android
|
188
|
-
when blackberry? then :blackberry
|
189
|
-
when safari? then :safari
|
190
|
-
when psp? then :psp
|
191
|
-
when quicktime? then :quicktime
|
192
|
-
when core_media? then :core_media
|
193
|
-
else
|
194
|
-
:other
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
# Return an array with all preferred languages that this browser accepts.
|
199
|
-
def accept_language
|
200
|
-
@accept_language.gsub(/;q=[\d.]+/, "").split(",").collect {|l| l.downcase.gsub(/\s/m, "")}
|
83
|
+
NAMES.keys
|
84
|
+
.find {|id| respond_to?("#{id}?") ? public_send("#{id}?") : id }
|
201
85
|
end
|
202
86
|
|
203
87
|
# Return major version.
|
@@ -207,17 +91,16 @@ class Browser
|
|
207
91
|
|
208
92
|
# Return the full version.
|
209
93
|
def full_version
|
210
|
-
_, v = *ua.match(VERSIONS.fetch(id, VERSIONS[:default]))
|
211
|
-
v || "0.0"
|
94
|
+
_, *v = *ua.match(VERSIONS.fetch(id, VERSIONS[:default]))
|
95
|
+
v.compact.first || "0.0"
|
212
96
|
end
|
213
97
|
|
214
|
-
# Return true if browser
|
215
|
-
def
|
216
|
-
webkit? ||
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
ie? && ua.match(TRIDENT_VERSION_REGEX) && version.to_i < ($1.to_i + 4)
|
98
|
+
# Return true if browser is modern (Webkit, Firefox 17+, IE9+, Opera 12+).
|
99
|
+
def modern?
|
100
|
+
webkit? ||
|
101
|
+
(firefox? && version.to_i >= 17) ||
|
102
|
+
(ie? && version.to_i >= 9) ||
|
103
|
+
(opera? && version.to_i >= 12)
|
221
104
|
end
|
222
105
|
|
223
106
|
# Detect if browser is WebKit-based.
|
@@ -225,54 +108,24 @@ class Browser
|
|
225
108
|
!!(ua =~ /AppleWebKit/i)
|
226
109
|
end
|
227
110
|
|
228
|
-
# Detect if browser is ios?.
|
229
|
-
def ios?
|
230
|
-
ipod? || ipad? || iphone?
|
231
|
-
end
|
232
|
-
|
233
|
-
# Detect if browser is mobile.
|
234
|
-
def mobile?
|
235
|
-
!!(ua =~ /(Mobi(le)?|Symbian|MIDP|Windows CE)/) || blackberry? || psp? || opera_mini?
|
236
|
-
end
|
237
|
-
|
238
111
|
# Detect if browser is QuickTime
|
239
112
|
def quicktime?
|
240
113
|
!!(ua =~ /QuickTime/i)
|
241
114
|
end
|
242
115
|
|
243
|
-
# Detect if browser is BlackBerry
|
244
|
-
def blackberry?
|
245
|
-
!!(ua =~ /BlackBerry/)
|
246
|
-
end
|
247
|
-
|
248
|
-
# Detect if browser is Android.
|
249
|
-
def android?
|
250
|
-
!!(ua =~ /Android/ && !opera?)
|
251
|
-
end
|
252
|
-
|
253
116
|
# Detect if browser is Apple CoreMedia.
|
254
117
|
def core_media?
|
255
118
|
!!(ua =~ /CoreMedia/)
|
256
119
|
end
|
257
120
|
|
258
|
-
# Detect if browser is
|
259
|
-
def
|
260
|
-
!!(ua =~ /
|
261
|
-
end
|
262
|
-
|
263
|
-
# Detect if browser is iPad.
|
264
|
-
def ipad?
|
265
|
-
!!(ua =~ /iPad/)
|
266
|
-
end
|
267
|
-
|
268
|
-
# Detect if browser is iPod.
|
269
|
-
def ipod?
|
270
|
-
!!(ua =~ /iPod/)
|
121
|
+
# Detect if browser is PhantomJS
|
122
|
+
def phantom_js?
|
123
|
+
!!(ua =~ /PhantomJS/)
|
271
124
|
end
|
272
125
|
|
273
126
|
# Detect if browser is Safari.
|
274
127
|
def safari?
|
275
|
-
ua =~ /Safari/ && ua !~ /Chrome|CriOS/
|
128
|
+
ua =~ /Safari/ && ua !~ /Chrome|CriOS|PhantomJS/
|
276
129
|
end
|
277
130
|
|
278
131
|
# Detect if browser is Firefox.
|
@@ -282,99 +135,20 @@ class Browser
|
|
282
135
|
|
283
136
|
# Detect if browser is Chrome.
|
284
137
|
def chrome?
|
285
|
-
!!(ua =~ /Chrome|CriOS/)
|
286
|
-
end
|
287
|
-
|
288
|
-
# Detect if browser is Internet Explorer.
|
289
|
-
def ie?
|
290
|
-
!!(ua =~ /MSIE/ && ua !~ /Opera/)
|
291
|
-
end
|
292
|
-
|
293
|
-
# Detect if browser is Internet Explorer 6.
|
294
|
-
def ie6?
|
295
|
-
ie? && version == "6"
|
296
|
-
end
|
297
|
-
|
298
|
-
# Detect if browser is Internet Explorer 7.
|
299
|
-
def ie7?
|
300
|
-
ie? && version == "7"
|
301
|
-
end
|
302
|
-
|
303
|
-
# Detect if browser is Internet Explorer 8.
|
304
|
-
def ie8?
|
305
|
-
ie? && version == "8"
|
306
|
-
end
|
307
|
-
|
308
|
-
# Detect if browser is Internet Explorer 9.
|
309
|
-
def ie9?
|
310
|
-
ie? && version == "9"
|
311
|
-
end
|
312
|
-
|
313
|
-
# Detect if browser is running from PSP.
|
314
|
-
def psp?
|
315
|
-
!!(ua =~ /PSP/)
|
138
|
+
!!(ua =~ /Chrome|CriOS/) && !opera?
|
316
139
|
end
|
317
140
|
|
318
141
|
# Detect if browser is Opera.
|
319
142
|
def opera?
|
320
|
-
!!(ua =~ /Opera/)
|
321
|
-
end
|
322
|
-
|
323
|
-
# Detect if browser is Opera Mini.
|
324
|
-
def opera_mini?
|
325
|
-
!!(ua =~ /Opera Mini/)
|
326
|
-
end
|
327
|
-
|
328
|
-
# Detect if current platform is Macintosh.
|
329
|
-
def mac?
|
330
|
-
!!(ua =~ /Mac OS X/)
|
331
|
-
end
|
332
|
-
|
333
|
-
# Detect if current platform is Windows.
|
334
|
-
def windows?
|
335
|
-
!!(ua =~ /Windows/)
|
336
|
-
end
|
337
|
-
|
338
|
-
# Detect if current platform is Linux flavor.
|
339
|
-
def linux?
|
340
|
-
!!(ua =~ /Linux/)
|
341
|
-
end
|
342
|
-
|
343
|
-
# Detect if browser is tablet (currently just iPad or Android).
|
344
|
-
def tablet?
|
345
|
-
!!(ipad? || (android? && !mobile?))
|
346
|
-
end
|
347
|
-
|
348
|
-
# Detect if browser is Kindle.
|
349
|
-
def kindle?
|
350
|
-
!!(ua =~ /Kindle/)
|
351
|
-
end
|
352
|
-
|
353
|
-
# Return the platform.
|
354
|
-
def platform
|
355
|
-
case
|
356
|
-
when linux? then :linux
|
357
|
-
when mac? then :mac
|
358
|
-
when windows? then :windows
|
359
|
-
else
|
360
|
-
:other
|
361
|
-
end
|
143
|
+
!!(ua =~ /(Opera|OPR)/)
|
362
144
|
end
|
363
145
|
|
364
146
|
# Return a meta info about this browser.
|
365
147
|
def meta
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
m.merge(%W[safari safari#{version}]) if safari?
|
371
|
-
m << "#{id}#{version}" unless safari? || chrome?
|
372
|
-
m << platform.to_s
|
373
|
-
m << "capable" if capable?
|
374
|
-
m << "mobile" if mobile?
|
375
|
-
end
|
376
|
-
|
377
|
-
set.to_a
|
148
|
+
Meta.constants.each_with_object(Set.new) do |meta_name, meta|
|
149
|
+
meta_class = Meta.const_get(meta_name)
|
150
|
+
meta.merge(meta_class.new(self).to_a)
|
151
|
+
end.to_a
|
378
152
|
end
|
379
153
|
|
380
154
|
alias_method :to_a, :meta
|
@@ -1,17 +1,19 @@
|
|
1
|
+
require "action_controller/railtie"
|
2
|
+
|
1
3
|
class Browser
|
2
|
-
module ActionController
|
3
|
-
|
4
|
-
|
4
|
+
module ActionController
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
helper_method :browser
|
5
9
|
end
|
6
10
|
|
7
11
|
private
|
8
12
|
def browser
|
9
13
|
@browser ||= Browser.new(
|
10
|
-
:
|
11
|
-
:
|
14
|
+
accept_language: request.headers["Accept-Language"],
|
15
|
+
ua: request.headers["User-Agent"]
|
12
16
|
)
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
16
|
-
|
17
|
-
ActionController::Base.send :include, Browser::ActionController
|