browser 1.1.0 → 2.0.0.rc1

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.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/.bundle/config +2 -0
  3. data/.hound.yml +26 -6
  4. data/.rubocop.yml +26 -6
  5. data/CHANGELOG.md +10 -0
  6. data/README.md +177 -41
  7. data/Rakefile +1 -1
  8. data/bin/rake +16 -0
  9. data/bot_exceptions.yml +1 -0
  10. data/bots.yml +188 -192
  11. data/browser.gemspec +14 -28
  12. data/languages.yml +54 -54
  13. data/lib/browser.rb +82 -202
  14. data/lib/browser/accept_language.rb +47 -0
  15. data/lib/browser/action_controller.rb +1 -1
  16. data/lib/browser/base.rb +159 -0
  17. data/lib/browser/blackberry.rb +21 -0
  18. data/lib/browser/bot.rb +63 -0
  19. data/lib/browser/chrome.rb +23 -0
  20. data/lib/browser/detect_version.rb +19 -0
  21. data/lib/browser/device.rb +175 -0
  22. data/lib/browser/device/base.rb +11 -0
  23. data/lib/browser/device/blackberry_playbook.rb +17 -0
  24. data/lib/browser/device/ipad.rb +17 -0
  25. data/lib/browser/device/iphone.rb +17 -0
  26. data/lib/browser/device/ipod_touch.rb +17 -0
  27. data/lib/browser/device/kindle.rb +17 -0
  28. data/lib/browser/device/kindle_fire.rb +17 -0
  29. data/lib/browser/device/playstation3.rb +17 -0
  30. data/lib/browser/device/playstation4.rb +17 -0
  31. data/lib/browser/device/psp.rb +17 -0
  32. data/lib/browser/device/psvita.rb +17 -0
  33. data/lib/browser/device/surface.rb +23 -0
  34. data/lib/browser/device/tv.rb +17 -0
  35. data/lib/browser/device/unknown.rb +17 -0
  36. data/lib/browser/device/wii.rb +17 -0
  37. data/lib/browser/device/wiiu.rb +17 -0
  38. data/lib/browser/device/xbox_360.rb +17 -0
  39. data/lib/browser/device/xbox_one.rb +17 -0
  40. data/lib/browser/edge.rb +19 -0
  41. data/lib/browser/firefox.rb +19 -0
  42. data/lib/browser/generic.rb +32 -0
  43. data/lib/browser/internet_explorer.rb +61 -0
  44. data/lib/browser/meta/base.rb +1 -1
  45. data/lib/browser/meta/device.rb +9 -0
  46. data/lib/browser/meta/generic_browser.rb +1 -1
  47. data/lib/browser/meta/id.rb +1 -1
  48. data/lib/browser/meta/ie.rb +1 -1
  49. data/lib/browser/meta/ios.rb +2 -2
  50. data/lib/browser/meta/mobile.rb +2 -2
  51. data/lib/browser/meta/modern.rb +1 -1
  52. data/lib/browser/meta/platform.rb +2 -2
  53. data/lib/browser/meta/proxy.rb +1 -1
  54. data/lib/browser/meta/safari.rb +1 -1
  55. data/lib/browser/meta/tablet.rb +9 -0
  56. data/lib/browser/meta/webkit.rb +1 -1
  57. data/lib/browser/middleware.rb +1 -1
  58. data/lib/browser/middleware/context.rb +2 -2
  59. data/lib/browser/middleware/context/additions.rb +1 -1
  60. data/lib/browser/middleware/context/url_methods.rb +3 -3
  61. data/lib/browser/nokia.rb +19 -0
  62. data/lib/browser/opera.rb +19 -0
  63. data/lib/browser/phantom_js.rb +19 -0
  64. data/lib/browser/platform.rb +152 -0
  65. data/lib/browser/platform/adobe_air.rb +21 -0
  66. data/lib/browser/platform/android.rb +21 -0
  67. data/lib/browser/platform/base.rb +15 -0
  68. data/lib/browser/platform/blackberry.rb +21 -0
  69. data/lib/browser/platform/chrome_os.rb +21 -0
  70. data/lib/browser/platform/firefox_os.rb +21 -0
  71. data/lib/browser/platform/ios.rb +28 -0
  72. data/lib/browser/platform/linux.rb +21 -0
  73. data/lib/browser/platform/mac.rb +21 -0
  74. data/lib/browser/platform/other.rb +21 -0
  75. data/lib/browser/platform/windows.rb +21 -0
  76. data/lib/browser/platform/windows_mobile.rb +21 -0
  77. data/lib/browser/platform/windows_phone.rb +21 -0
  78. data/lib/browser/rails.rb +3 -2
  79. data/lib/browser/safari.rb +22 -0
  80. data/lib/browser/testing.rb +23 -0
  81. data/lib/browser/uc_browser.rb +19 -0
  82. data/lib/browser/version.rb +2 -7
  83. data/search_engines.yml +5 -5
  84. data/test/browser_test.rb +71 -172
  85. data/test/middleware_test.rb +7 -7
  86. data/test/sample_app.rb +3 -3
  87. data/test/test_helper.rb +11 -10
  88. data/test/ua.yml +15 -26
  89. data/test/ua_bots.yml +27 -0
  90. data/test/ua_search_engines.yml +6 -0
  91. data/test/unit/accept_language_test.rb +92 -0
  92. data/test/unit/adobe_air_test.rb +5 -10
  93. data/test/unit/android_test.rb +44 -49
  94. data/test/unit/blackberry_test.rb +55 -77
  95. data/test/unit/bots_test.rb +52 -84
  96. data/test/unit/chrome_test.rb +48 -42
  97. data/test/unit/console_test.rb +4 -62
  98. data/test/unit/device_test.rb +193 -0
  99. data/test/unit/firefox_test.rb +32 -27
  100. data/test/unit/ie_test.rb +223 -238
  101. data/test/unit/ios_app_test.rb +3 -3
  102. data/test/unit/ios_test.rb +87 -94
  103. data/test/unit/kindle_test.rb +10 -24
  104. data/test/unit/nokia_test.rb +3 -7
  105. data/test/unit/opera_test.rb +20 -30
  106. data/test/unit/platform_test.rb +161 -0
  107. data/test/unit/proxy_test.rb +3 -3
  108. data/test/unit/safari_test.rb +66 -0
  109. data/test/unit/uc_browser_test.rb +3 -7
  110. data/test/unit/windows_phone_test.rb +19 -40
  111. data/test/unit/windows_test.rb +32 -34
  112. metadata +73 -28
  113. data/lib/browser/methods/blackberry.rb +0 -51
  114. data/lib/browser/methods/bots.rb +0 -35
  115. data/lib/browser/methods/consoles.rb +0 -43
  116. data/lib/browser/methods/devices.rb +0 -41
  117. data/lib/browser/methods/ie.rb +0 -99
  118. data/lib/browser/methods/language.rb +0 -16
  119. data/lib/browser/methods/mobile.rb +0 -35
  120. data/lib/browser/methods/platform.rb +0 -152
  121. data/lib/browser/methods/proxy.rb +0 -8
  122. data/lib/browser/methods/tv.rb +0 -8
@@ -1,38 +1,24 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "browser/version"
1
+ require "./lib/browser/version"
4
2
 
5
3
  Gem::Specification.new do |s|
6
- s.name = "browser"
7
- s.version = Browser::Version::STRING
8
- s.platform = Gem::Platform::RUBY
9
- s.authors = ["Nando Vieira"]
10
- s.email = ["fnando.vieira@gmail.com"]
11
- s.homepage = "http://github.com/fnando/browser"
12
- s.summary = "Do some browser detection with Ruby."
13
- s.description = s.summary
14
- s.license = 'MIT'
4
+ s.required_ruby_version = ">= 2.0"
5
+ s.name = "browser"
6
+ s.version = Browser::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Nando Vieira"]
9
+ s.email = ["fnando.vieira@gmail.com"]
10
+ s.homepage = "http://github.com/fnando/browser"
11
+ s.summary = "Do some browser detection with Ruby."
12
+ s.description = s.summary
13
+ s.license = "MIT"
15
14
 
16
15
  s.files = `git ls-files`.split("\n")
17
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.executables = `git ls-files -- exe/*`
18
+ .split("\n")
19
+ .map {|f| File.basename(f) }
19
20
  s.require_paths = ["lib"]
20
21
 
21
- s.post_install_message = [
22
- "",
23
- "#################### WARNING ##############################" ,
24
- "# #" ,
25
- "# Internet Explorer detection has changed on v1.0.0+. #" ,
26
- "# If this is important for you, please read #" ,
27
- "# https://github.com/fnando/browser#internet-explorer #" ,
28
- "# #" ,
29
- "# iOS webviews and web apps aren't detect as Safari #" ,
30
- "# anymore, so be aware of that if that's your case. #" ,
31
- "# #" ,
32
- "###########################################################" ,
33
- "\n"
34
- ].join("\n")
35
-
36
22
  s.add_development_dependency "bundler", ">= 0"
37
23
  s.add_development_dependency "rake"
38
24
  s.add_development_dependency "rails"
@@ -5,59 +5,59 @@
5
5
  "be": "Byelorussian"
6
6
  "ca": "Catalan"
7
7
  "zh": "Chinese"
8
- "zh-cn": "Chinese/China"
9
- "zh-tw": "Chinese/Taiwan"
10
- "zh-hk": "Chinese/Hong Kong"
11
- "zh-sg": "Chinese/singapore"
8
+ "zh-CN": "Chinese/China"
9
+ "zh-TW": "Chinese/Taiwan"
10
+ "zh-HK": "Chinese/Hong Kong"
11
+ "zh-SG": "Chinese/singapore"
12
12
  "hr": "Croatian"
13
13
  "cs": "Czech"
14
14
  "da": "Danish"
15
15
  "nl": "Dutch"
16
- "nl-nl": "Dutch/Netherlands"
17
- "nl-be": "Dutch/Belgium"
16
+ "nl-NL": "Dutch/Netherlands"
17
+ "nl-BE": "Dutch/Belgium"
18
18
  "en": "English"
19
- "en-gb": "English/United Kingdom"
20
- "en-us": "English/United States"
21
- "en-au": "English/Australian"
22
- "en-ca": "English/Canada"
23
- "en-nz": "English/New Zealand"
24
- "en-ie": "English/Ireland"
25
- "en-za": "English/South Africa"
26
- "en-jm": "English/Jamaica"
27
- "en-bz": "English/Belize"
28
- "en-tt": "English/Trinidad"
19
+ "en-GB": "English/United Kingdom"
20
+ "en-US": "English/United States"
21
+ "en-AU": "English/Australian"
22
+ "en-CA": "English/Canada"
23
+ "en-NZ": "English/New Zealand"
24
+ "en-IE": "English/Ireland"
25
+ "en-ZA": "English/South Africa"
26
+ "en-JM": "English/Jamaica"
27
+ "en-BZ": "English/Belize"
28
+ "en-TT": "English/Trinidad"
29
29
  "et": "Estonian"
30
30
  "fo": "Faeroese"
31
31
  "fa": "Farsi"
32
32
  "fi": "Finnish"
33
33
  "fr": "French"
34
- "fr-be": "French/Belgium"
35
- "fr-fr": "French/France"
36
- "fr-ch": "French/Switzerland"
37
- "fr-ca": "French/Canada"
38
- "fr-lu": "French/Luxembourg"
34
+ "fr-BE": "French/Belgium"
35
+ "fr-FR": "French/France"
36
+ "fr-CH": "French/Switzerland"
37
+ "fr-CA": "French/Canada"
38
+ "fr-LU": "French/Luxembourg"
39
39
  "gl": "Galician"
40
40
  "de": "German"
41
- "de-at": "German/Austria"
42
- "de-de": "German/Germany"
43
- "de-ch": "German/Switzerland"
44
- "de-lu": "German/Luxembourg"
45
- "de-li": "German/Liechtenstein"
41
+ "de-AT": "German/Austria"
42
+ "de-DE": "German/Germany"
43
+ "de-CH": "German/Switzerland"
44
+ "de-LU": "German/Luxembourg"
45
+ "de-LI": "German/Liechtenstein"
46
46
  "el": "Greek"
47
47
  "he": "Hebrew"
48
- "he-il": "Hebrew/Israel"
48
+ "he-IL": "Hebrew/Israel"
49
49
  "hi": "Hindi"
50
50
  "hu": "Hungarian"
51
- "ie-ee": "Internet Explorer/Easter Egg"
51
+ "ie-EE": "Internet Explorer/Easter Egg"
52
52
  "is": "Icelandic"
53
53
  "id": "Indonesian"
54
54
  "in": "Indonesian"
55
55
  "ga": "Irish"
56
56
  "it": "Italian"
57
- "it-ch": "Italian/ Switzerland"
57
+ "it-CH": "Italian/ Switzerland"
58
58
  "ja": "Japanese"
59
59
  "km": "Khmer"
60
- "km-kh": "Khmer/Cambodia"
60
+ "km-KH": "Khmer/Cambodia"
61
61
  "ko": "Korean"
62
62
  "lv": "Latvian"
63
63
  "lt": "Lithuanian"
@@ -67,41 +67,41 @@
67
67
  "no": "Norwegian"
68
68
  "pl": "Polish"
69
69
  "pt": "Portuguese"
70
- "pt-br": "Portuguese/Brazil"
70
+ "pt-BR": "Portuguese/Brazil"
71
71
  "rm": "Rhaeto-Romanic"
72
72
  "ro": "Romanian"
73
- "ro-mo": "Romanian/Moldavia"
73
+ "ro-MO": "Romanian/Moldavia"
74
74
  "ru": "Russian"
75
- "ru-mo": "Russian /Moldavia"
75
+ "ru-MO": "Russian /Moldavia"
76
76
  "gd": "Scots Gaelic"
77
77
  "sr": "Serbian"
78
78
  "sk": "Slovack"
79
79
  "sl": "Slovenian"
80
80
  "sb": "Sorbian"
81
81
  "es": "Spanish"
82
- "es-do": "Spanish"
83
- "es-ar": "Spanish/Argentina"
84
- "es-co": "Spanish/Colombia"
85
- "es-mx": "Spanish/Mexico"
86
- "es-es": "Spanish/Spain"
87
- "es-gt": "Spanish/Guatemala"
88
- "es-cr": "Spanish/Costa Rica"
89
- "es-pa": "Spanish/Panama"
90
- "es-ve": "Spanish/Venezuela"
91
- "es-pe": "Spanish/Peru"
92
- "es-ec": "Spanish/Ecuador"
93
- "es-cl": "Spanish/Chile"
94
- "es-uy": "Spanish/Uruguay"
95
- "es-py": "Spanish/Paraguay"
96
- "es-bo": "Spanish/Bolivia"
97
- "es-sv": "Spanish/El salvador"
98
- "es-hn": "Spanish/Honduras"
99
- "es-ni": "Spanish/Nicaragua"
100
- "es-pr": "Spanish/Puerto Rico"
82
+ "es-DO": "Spanish"
83
+ "es-AR": "Spanish/Argentina"
84
+ "es-CO": "Spanish/Colombia"
85
+ "es-MX": "Spanish/Mexico"
86
+ "es-ES": "Spanish/Spain"
87
+ "es-GT": "Spanish/Guatemala"
88
+ "es-CR": "Spanish/Costa Rica"
89
+ "es-PA": "Spanish/Panama"
90
+ "es-VE": "Spanish/Venezuela"
91
+ "es-PE": "Spanish/Peru"
92
+ "es-EC": "Spanish/Ecuador"
93
+ "es-CL": "Spanish/Chile"
94
+ "es-UY": "Spanish/Uruguay"
95
+ "es-PY": "Spanish/Paraguay"
96
+ "es-BO": "Spanish/Bolivia"
97
+ "es-SV": "Spanish/El salvador"
98
+ "es-HN": "Spanish/Honduras"
99
+ "es-NI": "Spanish/Nicaragua"
100
+ "es-PR": "Spanish/Puerto Rico"
101
101
  "sx": "Sutu"
102
102
  "sv": "Swedish"
103
- "sv-se": "Swedish/Sweden"
104
- "sv-fi": "Swedish/Finland"
103
+ "sv-SE": "Swedish/Sweden"
104
+ "sv-FI": "Swedish/Finland"
105
105
  "ts": "Thai"
106
106
  "tn": "Tswana"
107
107
  "tr": "Turkish"
@@ -2,20 +2,60 @@ require "set"
2
2
  require "yaml"
3
3
  require "pathname"
4
4
 
5
+ require "browser/detect_version"
6
+ require "browser/accept_language"
7
+ require "browser/base"
8
+ require "browser/safari"
9
+ require "browser/chrome"
10
+ require "browser/internet_explorer"
11
+ require "browser/firefox"
12
+ require "browser/edge"
13
+ require "browser/opera"
14
+ require "browser/blackberry"
15
+ require "browser/generic"
16
+ require "browser/phantom_js"
17
+ require "browser/uc_browser"
18
+ require "browser/nokia"
19
+
20
+ require "browser/bot"
5
21
  require "browser/middleware"
6
22
  require "browser/middleware/context"
7
23
  require "browser/rails" if defined?(::Rails)
8
24
 
9
- require "browser/methods/ie"
10
- require "browser/methods/blackberry"
11
- require "browser/methods/platform"
12
- require "browser/methods/mobile"
13
- require "browser/methods/devices"
14
- require "browser/methods/consoles"
15
- require "browser/methods/language"
16
- require "browser/methods/bots"
17
- require "browser/methods/tv"
18
- require "browser/methods/proxy"
25
+ require "browser/platform"
26
+ require "browser/platform/base"
27
+ require "browser/platform/ios"
28
+ require "browser/platform/linux"
29
+ require "browser/platform/windows"
30
+ require "browser/platform/mac"
31
+ require "browser/platform/windows_phone"
32
+ require "browser/platform/windows_mobile"
33
+ require "browser/platform/firefox_os"
34
+ require "browser/platform/blackberry"
35
+ require "browser/platform/android"
36
+ require "browser/platform/other"
37
+ require "browser/platform/chrome_os"
38
+ require "browser/platform/adobe_air"
39
+
40
+ require "browser/device"
41
+ require "browser/device/base"
42
+ require "browser/device/unknown"
43
+ require "browser/device/ipad"
44
+ require "browser/device/ipod_touch"
45
+ require "browser/device/iphone"
46
+ require "browser/device/playstation3"
47
+ require "browser/device/playstation4"
48
+ require "browser/device/psp"
49
+ require "browser/device/psvita"
50
+ require "browser/device/kindle"
51
+ require "browser/device/kindle_fire"
52
+ require "browser/device/wii"
53
+ require "browser/device/wiiu"
54
+ require "browser/device/blackberry_playbook"
55
+ require "browser/device/surface"
56
+ require "browser/device/tv"
57
+ require "browser/device/xbox_one"
58
+ require "browser/device/xbox_360"
19
59
 
20
60
  require "browser/meta/base"
21
61
  require "browser/meta/generic_browser"
@@ -28,58 +68,13 @@ require "browser/meta/platform"
28
68
  require "browser/meta/proxy"
29
69
  require "browser/meta/safari"
30
70
  require "browser/meta/webkit"
71
+ require "browser/meta/tablet"
72
+ require "browser/meta/device"
31
73
 
32
- class Browser
33
- include IE
34
- include BlackBerry
35
- include Platform
36
- include Mobile
37
- include Devices
38
- include Consoles
39
- include Language
40
- include Bots
41
- include Tv
42
- include Proxy
43
-
44
- # Set browser's UA string.
45
- attr_accessor :user_agent
46
- alias_method :ua, :user_agent
47
- alias_method :ua=, :user_agent=
48
-
49
- NAMES = {
50
- edge: "Microsoft Edge", # Must come before everything
51
- ie: "Internet Explorer", # Must come before android
52
- chrome: "Chrome", # Must come before android
53
- firefox: "Firefox", # Must come before android
54
- uc_browser: "UC Browser", # Must come before android
55
- android: "Android",
56
- blackberry_running_safari: "Safari",
57
- blackberry: "BlackBerry",
58
- core_media: "Apple CoreMedia",
59
- ipad: "iPad", # Must come before safari
60
- iphone: "iPhone", # Must come before safari
61
- ipod: "iPod Touch", # Must come before safari
62
- nintendo: "Nintendo",
63
- opera: "Opera",
64
- phantom_js: "PhantomJS",
65
- psp: "PlayStation Portable",
66
- playstation: "PlayStation",
67
- quicktime: "QuickTime",
68
- safari: "Safari",
69
- xbox: "Xbox",
70
- nokia: "Nokia S40 Ovi Browser",
71
-
72
- # This must be last item, since Ruby 1.9+ has ordered keys.
73
- other: "Other",
74
- }
75
-
76
- VERSIONS = {
77
- edge: %r[Edge/([\d.]+)],
78
- chrome: %r[(?:Chrome|CriOS)/([\d.]+)],
79
- default: %r[(?:Version|MSIE|Firefox|QuickTime|BlackBerry[^/]+|CoreMedia v|PhantomJS|AdobeAIR)[/ ]?([a-z0-9.]+)]i,
80
- opera: %r[(?:Opera/.*? Version/([\d.]+)|Chrome/.*?OPR/([\d.]+))],
81
- ie: %r[(?:MSIE |Trident/.*?; rv:)([\d.]+)]
82
- }
74
+ module Browser
75
+ def self.root
76
+ @root ||= Pathname.new(File.expand_path("../..", __FILE__))
77
+ end
83
78
 
84
79
  # Define the rules which define a modern browser.
85
80
  # A rule must be a proc/lambda or any object that implements the method
@@ -89,156 +84,41 @@ class Browser
89
84
  #
90
85
  # # Only Chrome Canary is considered modern.
91
86
  # Browser.modern_rules.clear
92
- # Browser.modern_rules << -> b { b.chrome? && b.version >= '37' }
87
+ # Browser.modern_rules << -> b { b.chrome? && b.version >= "37" }
93
88
  #
94
89
  def self.modern_rules
95
90
  @modern_rules ||= []
96
91
  end
97
92
 
98
- self.modern_rules.tap do |rules|
99
- rules << -> b { b.webkit? }
100
- rules << -> b { b.firefox? && b.version.to_i >= 17 }
101
- rules << -> b { b.ie? && b.version.to_i >= 9 && !b.compatibility_view? }
102
- rules << -> b { b.edge? && !b.compatibility_view? }
103
- rules << -> b { b.opera? && b.version.to_i >= 12 }
104
- rules << -> b { b.firefox? && b.tablet? && b.android? && b.version.to_i >= 14 }
105
- end
106
-
107
- # Create a new browser instance and set
108
- # the UA and Accept-Language headers.
109
- #
110
- # browser = Browser.new({
111
- # :ua => "Safari",
112
- # :accept_language => "pt-br"
113
- # })
114
- #
115
- def initialize(options = {}, &block)
116
- self.user_agent = (options[:user_agent] || options[:ua]).to_s
117
- self.accept_language = options[:accept_language].to_s
118
-
119
- yield self if block
120
- end
121
-
122
- # Get readable browser name.
123
- def name
124
- NAMES[id]
125
- end
126
-
127
- # Get the browser identifier.
128
- def id
129
- NAMES.keys
130
- .find {|id| respond_to?("#{id}?", true) ? send("#{id}?") : id }
131
- end
132
-
133
- # Return major version.
134
- def version
135
- if ie?
136
- ie_version
137
- else
138
- full_version.to_s.split(".").first
139
- end
140
- end
141
-
142
- # Return the full version.
143
- def full_version
144
- if ie?
145
- ie_full_version
146
- else
147
- _, *v = *ua.match(VERSIONS.fetch(id, VERSIONS[:default]))
148
- v.compact.first || "0.0"
149
- end
150
- end
151
-
152
- # Return true if browser is modern (Webkit, Firefox 17+, IE9+, Opera 12+).
153
- def modern?
154
- self.class.modern_rules.any? {|rule| rule === self }
155
- end
156
-
157
- # Detect if browser is WebKit-based.
158
- def webkit?
159
- ua =~ /AppleWebKit/i && !edge?
160
- end
161
-
162
- # Detect if browser is QuickTime
163
- def quicktime?
164
- !!(ua =~ /QuickTime/i)
165
- end
166
-
167
- # Detect if browser is Apple CoreMedia.
168
- def core_media?
169
- !!(ua =~ /CoreMedia/)
170
- end
171
-
172
- # Detect if browser is PhantomJS
173
- def phantom_js?
174
- !!(ua =~ /PhantomJS/)
175
- end
176
-
177
- # Detect if browser is Safari.
178
- def safari?
179
- !!((ua =~ /Safari/) && ua !~ /Android|Chrome|CriOS|PhantomJS/)
180
- end
181
-
182
- def safari_webapp_mode?
183
- !!((ipad? || iphone?) && ua =~ /AppleWebKit/)
184
- end
185
-
186
- # Detect if browser is Firefox.
187
- def firefox?
188
- !!(ua =~ /Firefox/)
189
- end
190
-
191
- # Detect if browser is Chrome.
192
- def chrome?
193
- !!(ua =~ /Chrome|CriOS/ && !opera? && !edge?)
194
- end
195
-
196
- # Detect if browser is Opera.
197
- def opera?
198
- !!(ua =~ /(Opera|OPR)/)
199
- end
200
-
201
- # Detect if browser is Silk.
202
- def silk?
203
- !!(ua =~ /Silk/)
204
- end
205
-
206
- # Detect if browser is Yandex.
207
- def yandex?
208
- !!(ua =~ /YaBrowser/)
209
- end
210
-
211
- # Detect if browser is UCBrowser.
212
- def uc_browser?
213
- !!(ua =~ /UCBrowser/)
214
- end
215
-
216
- def known?
217
- id != :other
218
- end
219
-
220
- # Return a meta info about this browser.
221
- def meta
222
- Meta.constants.each_with_object(Set.new) do |meta_name, meta|
223
- meta_class = Meta.const_get(meta_name)
224
- meta.merge(meta_class.new(self).to_a)
225
- end.to_a
226
- end
227
-
228
- alias_method :to_a, :meta
229
-
230
- # Return meta representation as string.
231
- def to_s
232
- meta.to_a.join(" ")
93
+ modern_rules.tap do |rules|
94
+ rules << -> (b) { b.webkit? }
95
+ rules << -> (b) { b.firefox? && b.version.to_i >= 17 }
96
+ rules << -> (b) { b.ie? && b.version.to_i >= 9 && !b.compatibility_view? }
97
+ rules << -> (b) { b.edge? && !b.compatibility_view? }
98
+ rules << -> (b) { b.opera? && b.version.to_i >= 12 }
99
+ rules << -> (b) { b.firefox? && b.device.tablet? && b.platform.android? && b.version.to_i >= 14 } # rubocop:disable Metrics/LineLength
100
+ end
101
+
102
+ def self.new(user_agent, **kwargs)
103
+ [
104
+ Nokia,
105
+ UCBrowser,
106
+ PhantomJS,
107
+ BlackBerry,
108
+ Opera,
109
+ Edge,
110
+ InternetExplorer,
111
+ Firefox,
112
+ Chrome,
113
+ Safari,
114
+ Generic,
115
+ ]
116
+ .map {|klass| klass.new(user_agent, **kwargs) }
117
+ .find(&:match?)
233
118
  end
234
119
 
235
120
  private
236
121
 
237
- def detect_version?(actual_version, expected_version)
238
- return true unless expected_version
239
- actual_version.to_s.start_with?(expected_version.to_s)
240
- end
241
-
242
122
  def deprecate(message)
243
123
  offender = caller[1].to_s[/^(.*?\.rb:\d+).*?$/, 1]
244
124
  $stderr << "\n#{message} (called from #{offender})\n"