agentry 3.0.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.
Files changed (119) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +93 -0
  3. data/LICENSE.md +21 -0
  4. data/README.md +552 -0
  5. data/data/bot_categories.json +1 -0
  6. data/data/bot_exceptions.json +1 -0
  7. data/data/bot_ip_ranges.json +1 -0
  8. data/data/bots.json +1 -0
  9. data/data/languages.json +1 -0
  10. data/data/samsung.json +1 -0
  11. data/data/search_engines.json +1 -0
  12. data/lib/agentry.rb +3 -0
  13. data/lib/browser/accept_language.rb +55 -0
  14. data/lib/browser/action_controller.rb +21 -0
  15. data/lib/browser/aliases.rb +33 -0
  16. data/lib/browser/alipay.rb +21 -0
  17. data/lib/browser/base.rb +307 -0
  18. data/lib/browser/blackberry.rb +23 -0
  19. data/lib/browser/bot/empty_user_agent_matcher.rb +11 -0
  20. data/lib/browser/bot/ip_ranges.rb +194 -0
  21. data/lib/browser/bot/keyword_matcher.rb +11 -0
  22. data/lib/browser/bot/known_bots_matcher.rb +11 -0
  23. data/lib/browser/bot.rb +221 -0
  24. data/lib/browser/browser.rb +200 -0
  25. data/lib/browser/cache.rb +92 -0
  26. data/lib/browser/chrome.rb +43 -0
  27. data/lib/browser/client_hints.rb +73 -0
  28. data/lib/browser/cloudflare.rb +65 -0
  29. data/lib/browser/detect_version.rb +22 -0
  30. data/lib/browser/detection.rb +25 -0
  31. data/lib/browser/device/android.rb +20 -0
  32. data/lib/browser/device/base.rb +13 -0
  33. data/lib/browser/device/blackberry_playbook.rb +19 -0
  34. data/lib/browser/device/ipad.rb +19 -0
  35. data/lib/browser/device/iphone.rb +19 -0
  36. data/lib/browser/device/ipod_touch.rb +19 -0
  37. data/lib/browser/device/kindle.rb +19 -0
  38. data/lib/browser/device/kindle_fire.rb +19 -0
  39. data/lib/browser/device/playstation3.rb +19 -0
  40. data/lib/browser/device/playstation4.rb +19 -0
  41. data/lib/browser/device/psp.rb +19 -0
  42. data/lib/browser/device/psvita.rb +19 -0
  43. data/lib/browser/device/samsung.rb +33 -0
  44. data/lib/browser/device/surface.rb +23 -0
  45. data/lib/browser/device/switch.rb +19 -0
  46. data/lib/browser/device/tv.rb +19 -0
  47. data/lib/browser/device/unknown.rb +19 -0
  48. data/lib/browser/device/wii.rb +19 -0
  49. data/lib/browser/device/wiiu.rb +19 -0
  50. data/lib/browser/device/xbox_360.rb +19 -0
  51. data/lib/browser/device/xbox_one.rb +19 -0
  52. data/lib/browser/device.rb +246 -0
  53. data/lib/browser/duck_duck_go.rb +22 -0
  54. data/lib/browser/edge.rb +25 -0
  55. data/lib/browser/electron.rb +22 -0
  56. data/lib/browser/epiphany.rb +21 -0
  57. data/lib/browser/facebook.rb +23 -0
  58. data/lib/browser/firefox.rb +21 -0
  59. data/lib/browser/google_search_app.rb +21 -0
  60. data/lib/browser/huawei_browser.rb +21 -0
  61. data/lib/browser/instagram.rb +21 -0
  62. data/lib/browser/internet_explorer.rb +63 -0
  63. data/lib/browser/maxthon.rb +21 -0
  64. data/lib/browser/meta/base.rb +42 -0
  65. data/lib/browser/meta/device.rb +11 -0
  66. data/lib/browser/meta/generic_browser.rb +15 -0
  67. data/lib/browser/meta/id.rb +11 -0
  68. data/lib/browser/meta/ie.rb +20 -0
  69. data/lib/browser/meta/ios.rb +11 -0
  70. data/lib/browser/meta/mobile.rb +11 -0
  71. data/lib/browser/meta/platform.rb +11 -0
  72. data/lib/browser/meta/proxy.rb +11 -0
  73. data/lib/browser/meta/safari.rb +11 -0
  74. data/lib/browser/meta/tablet.rb +11 -0
  75. data/lib/browser/meta/webkit.rb +11 -0
  76. data/lib/browser/meta.rb +14 -0
  77. data/lib/browser/micro_messenger.rb +21 -0
  78. data/lib/browser/middleware/context/additions.rb +18 -0
  79. data/lib/browser/middleware/context/url_methods.rb +15 -0
  80. data/lib/browser/middleware/context.rb +23 -0
  81. data/lib/browser/middleware.rb +70 -0
  82. data/lib/browser/miui_browser.rb +21 -0
  83. data/lib/browser/nokia.rb +21 -0
  84. data/lib/browser/opera.rb +21 -0
  85. data/lib/browser/otter.rb +21 -0
  86. data/lib/browser/phantom_js.rb +21 -0
  87. data/lib/browser/platform/adobe_air.rb +23 -0
  88. data/lib/browser/platform/android.rb +23 -0
  89. data/lib/browser/platform/base.rb +18 -0
  90. data/lib/browser/platform/blackberry.rb +23 -0
  91. data/lib/browser/platform/chrome_os.rb +23 -0
  92. data/lib/browser/platform/firefox_os.rb +23 -0
  93. data/lib/browser/platform/ios.rb +36 -0
  94. data/lib/browser/platform/kai_os.rb +23 -0
  95. data/lib/browser/platform/linux.rb +23 -0
  96. data/lib/browser/platform/mac.rb +25 -0
  97. data/lib/browser/platform/unknown.rb +23 -0
  98. data/lib/browser/platform/windows.rb +23 -0
  99. data/lib/browser/platform/windows_mobile.rb +23 -0
  100. data/lib/browser/platform/windows_phone.rb +23 -0
  101. data/lib/browser/platform.rb +220 -0
  102. data/lib/browser/qq.rb +25 -0
  103. data/lib/browser/rails.rb +24 -0
  104. data/lib/browser/safari.rb +40 -0
  105. data/lib/browser/samsung_browser.rb +21 -0
  106. data/lib/browser/snapchat.rb +21 -0
  107. data/lib/browser/sougou_browser.rb +24 -0
  108. data/lib/browser/sputnik.rb +21 -0
  109. data/lib/browser/testing.rb +29 -0
  110. data/lib/browser/uc_browser.rb +21 -0
  111. data/lib/browser/unknown.rb +32 -0
  112. data/lib/browser/version.rb +5 -0
  113. data/lib/browser/weibo.rb +21 -0
  114. data/lib/browser/yandex.rb +21 -0
  115. data/lib/browser.rb +4 -0
  116. data/test/ua.yml +181 -0
  117. data/test/ua_bots.yml +121 -0
  118. data/test/ua_search_engines.yml +7 -0
  119. metadata +274 -0
@@ -0,0 +1,246 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "device/base"
4
+ require_relative "device/android"
5
+ require_relative "device/unknown"
6
+ require_relative "device/ipad"
7
+ require_relative "device/ipod_touch"
8
+ require_relative "device/iphone"
9
+ require_relative "device/playstation3"
10
+ require_relative "device/playstation4"
11
+ require_relative "device/psp"
12
+ require_relative "device/psvita"
13
+ require_relative "device/kindle"
14
+ require_relative "device/kindle_fire"
15
+ require_relative "device/wii"
16
+ require_relative "device/wiiu"
17
+ require_relative "device/blackberry_playbook"
18
+ require_relative "device/surface"
19
+ require_relative "device/switch"
20
+ require_relative "device/tv"
21
+ require_relative "device/xbox_one"
22
+ require_relative "device/xbox_360"
23
+ require_relative "device/samsung"
24
+
25
+ module Browser
26
+ class Device
27
+ attr_reader :ua
28
+
29
+ # Hold the list of device matchers.
30
+ # Order is important.
31
+ def self.matchers
32
+ @matchers ||= [
33
+ Samsung,
34
+ XboxOne,
35
+ Xbox360,
36
+ Surface,
37
+ TV,
38
+ BlackBerryPlaybook,
39
+ WiiU,
40
+ Wii,
41
+ Switch,
42
+ KindleFire,
43
+ Kindle,
44
+ PlayStation4,
45
+ PlayStation3,
46
+ PSVita,
47
+ PSP,
48
+ Ipad,
49
+ Iphone,
50
+ IpodTouch,
51
+ Android,
52
+ Unknown
53
+ ]
54
+ end
55
+
56
+ def initialize(ua, platform: nil, client_hints: nil)
57
+ @ua = ua
58
+ @platform = platform
59
+ @client_hints = client_hints
60
+ end
61
+
62
+ # This device, or one built with the client hints when Sec-CH-UA-Mobile or
63
+ # the platform they gave change its answers.
64
+ def with_client_hints(client_hints, platform:)
65
+ mobile = client_hints.mobile?
66
+ return self if platform.equal?(self.platform) && (mobile.nil? || mobile == detect_mobile?)
67
+
68
+ self.class.new(ua, platform:, client_hints:)
69
+ end
70
+
71
+ def subject
72
+ @subject ||= self.class.matchers.each do |matcher|
73
+ candidate = matcher.new(ua)
74
+ break candidate if candidate.match?
75
+ end
76
+ end
77
+
78
+ def id
79
+ subject.id
80
+ end
81
+
82
+ def name
83
+ subject.name
84
+ end
85
+
86
+ # Detect if browser is tablet (currently iPad, Android, Surface or
87
+ # Playbook).
88
+ def tablet?
89
+ ipad? ||
90
+ (platform.android? && !detect_mobile?) ||
91
+ surface? ||
92
+ playbook?
93
+ end
94
+
95
+ # Detect if browser is mobile.
96
+ def mobile?
97
+ detect_mobile? && !tablet?
98
+ end
99
+
100
+ def ipad?
101
+ id == :ipad
102
+ end
103
+
104
+ def unknown?
105
+ id == :unknown_device
106
+ end
107
+
108
+ def ipod_touch?
109
+ id == :ipod_touch
110
+ end
111
+ alias_method :ipod?, :ipod_touch?
112
+
113
+ def iphone?
114
+ id == :iphone
115
+ end
116
+
117
+ def ps3?
118
+ id == :ps3
119
+ end
120
+ alias_method :playstation3?, :ps3?
121
+
122
+ def ps4?
123
+ id == :ps4
124
+ end
125
+ alias_method :playstation4?, :ps4?
126
+
127
+ def psp?
128
+ id == :psp
129
+ end
130
+
131
+ def playstation_vita?
132
+ id == :psvita
133
+ end
134
+ alias_method :vita?, :playstation_vita?
135
+ alias_method :psp_vita?, :playstation_vita?
136
+
137
+ def kindle?
138
+ id == :kindle || kindle_fire?
139
+ end
140
+
141
+ def kindle_fire?
142
+ id == :kindle_fire
143
+ end
144
+
145
+ def nintendo_wii?
146
+ id == :wii
147
+ end
148
+ alias_method :wii?, :nintendo_wii?
149
+
150
+ def nintendo_wiiu?
151
+ id == :wiiu
152
+ end
153
+ alias_method :wiiu?, :nintendo_wiiu?
154
+
155
+ def nintendo_switch?
156
+ id == :switch
157
+ end
158
+ alias_method :switch?, :nintendo_switch?
159
+
160
+ def blackberry_playbook?
161
+ id == :playbook
162
+ end
163
+ alias_method :playbook?, :blackberry_playbook?
164
+
165
+ def surface?
166
+ id == :surface
167
+ end
168
+
169
+ def tv?
170
+ id == :tv
171
+ end
172
+
173
+ # Detect if browser is Silk.
174
+ def silk?
175
+ ua.include?("Silk")
176
+ end
177
+
178
+ # Detect if browser is running under Xbox.
179
+ def xbox?
180
+ ua.include?("Xbox")
181
+ end
182
+
183
+ # Detect if browser is running under Xbox 360.
184
+ def xbox_360?
185
+ id == :xbox_360
186
+ end
187
+
188
+ # Detect if browser is running under Xbox One.
189
+ def xbox_one?
190
+ id == :xbox_one
191
+ end
192
+
193
+ # Detect if browser is running under PlayStation.
194
+ def playstation?
195
+ ps3? || ps4?
196
+ end
197
+
198
+ # Detect if browser is Nintendo.
199
+ def nintendo?
200
+ wii? || wiiu? || switch?
201
+ end
202
+
203
+ # Detect if browser is console (currently Xbox, PlayStation, or Nintendo).
204
+ def console?
205
+ xbox? || playstation? || nintendo?
206
+ end
207
+
208
+ # Detect if device is a Samsung.
209
+ def samsung?
210
+ id == :samsung
211
+ end
212
+
213
+ # Regex taken from http://detectmobilebrowsers.com
214
+ MOBILE_REGEX = %r{(android|bb\d+|meego).+mobile|avantgo|bada/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino}i
215
+ MOBILE_PREFIX_REGEX = %r{1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-}i
216
+ # Both are lowercase: on an ASCII user agent, matching its downcased copy
217
+ # without /i gives the same answer several times faster. Every prefix is 4
218
+ # characters long, so anchoring it tests the first 4 without copying them.
219
+ MOBILE_LOWERCASE_REGEX = Regexp.new(MOBILE_REGEX.source)
220
+ MOBILE_PREFIX_LOWERCASE_REGEX = Regexp.new("\\A(?:#{MOBILE_PREFIX_REGEX.source})")
221
+ private_constant :MOBILE_REGEX, :MOBILE_PREFIX_REGEX, :MOBILE_LOWERCASE_REGEX,
222
+ :MOBILE_PREFIX_LOWERCASE_REGEX
223
+
224
+ private def detect_mobile?
225
+ return @detect_mobile if defined?(@detect_mobile)
226
+
227
+ mobile = @client_hints&.mobile?
228
+ @detect_mobile = mobile.nil? ? psp? || /zunewp7|crios/i.match?(ua) || mobile_user_agent? : mobile
229
+ end
230
+
231
+ private def mobile_user_agent?
232
+ return MOBILE_REGEX.match?(ua) || MOBILE_PREFIX_REGEX.match?(ua[0..3]) unless ua.ascii_only?
233
+
234
+ lowercase_ua = ua.downcase
235
+ MOBILE_LOWERCASE_REGEX.match?(lowercase_ua) ||
236
+ MOBILE_PREFIX_LOWERCASE_REGEX.match?(lowercase_ua)
237
+ end
238
+
239
+ private def platform
240
+ @platform ||= Platform.new(ua)
241
+ end
242
+
243
+ private :subject
244
+ private :ua
245
+ end
246
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ class DuckDuckGo < Base
5
+ def id
6
+ :duckduckgo
7
+ end
8
+
9
+ def name
10
+ "DuckDuckGo"
11
+ end
12
+
13
+ def full_version
14
+ ua[%r{DuckDuckGo/([\d.]+)}, 1] ||
15
+ "0.0"
16
+ end
17
+
18
+ def match?
19
+ ua.include?("DuckDuckGo")
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ class Edge < InternetExplorer
5
+ def id
6
+ :edge
7
+ end
8
+
9
+ def name
10
+ "Microsoft Edge"
11
+ end
12
+
13
+ def full_version
14
+ ua[%r{(?:Edge|Edg|EdgiOS|EdgA)/([\d.]+)}, 1] || super
15
+ end
16
+
17
+ def match?
18
+ ua.match?(%r{((?:Edge|Edg|EdgiOS|EdgA)/[\d.]+|Trident/8)})
19
+ end
20
+
21
+ def chromium_based?
22
+ match? && ua.match?(/\bEdg\b/)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ class Electron < Base
5
+ def id
6
+ :electron
7
+ end
8
+
9
+ def name
10
+ "Electron"
11
+ end
12
+
13
+ def full_version
14
+ ua[%r{Electron/([\d.]+)}, 1] ||
15
+ "0.0"
16
+ end
17
+
18
+ def match?
19
+ ua.include?("Electron")
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ class Epiphany < Base
5
+ def id
6
+ :epiphany
7
+ end
8
+
9
+ def name
10
+ "Epiphany"
11
+ end
12
+
13
+ def full_version
14
+ ua[%r{Epiphany/([\d.]+)}, 1] || "0.0"
15
+ end
16
+
17
+ def match?
18
+ ua.include?("Epiphany")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ class Facebook < Base
5
+ def id
6
+ :facebook
7
+ end
8
+
9
+ def name
10
+ "Facebook"
11
+ end
12
+
13
+ def full_version
14
+ ua[%r{FBAV/([\d.]+)}, 1] ||
15
+ ua[%r{AppleWebKit/([\d.]+)}, 0] ||
16
+ "0.0"
17
+ end
18
+
19
+ def match?
20
+ ua.match?(/FBAV|FBAN/)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ class Firefox < Base
5
+ def id
6
+ :firefox
7
+ end
8
+
9
+ def name
10
+ "Firefox"
11
+ end
12
+
13
+ def full_version
14
+ ua[%r{(?:Firefox|FxiOS)/([\d.]+)}, 1] || "0.0"
15
+ end
16
+
17
+ def match?
18
+ ua.match?(/Firefox|FxiOS/)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ class GoogleSearchApp < Chrome
5
+ def id
6
+ :google_search_app
7
+ end
8
+
9
+ def name
10
+ "Google Search App"
11
+ end
12
+
13
+ def full_version
14
+ ua[%r{GSA/([\d.]+\d)}, 1] || super
15
+ end
16
+
17
+ def match?
18
+ ua.include?("GSA")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ class HuaweiBrowser < Base
5
+ def id
6
+ :huawei_browser
7
+ end
8
+
9
+ def name
10
+ "Huawei Browser"
11
+ end
12
+
13
+ def full_version
14
+ ua[%r{(?:HuaweiBrowser)/([\d.]+)}i, 1] || "0.0"
15
+ end
16
+
17
+ def match?
18
+ ua.match?(/HuaweiBrowser/i)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ class Instagram < Base
5
+ def id
6
+ :instagram
7
+ end
8
+
9
+ def name
10
+ "Instagram"
11
+ end
12
+
13
+ def full_version
14
+ ua[%r{Instagram[ /]([\d.]+)}, 1] || "0.0"
15
+ end
16
+
17
+ def match?
18
+ ua.include?("Instagram")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ class InternetExplorer < Base
5
+ # https://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx#TriToken
6
+ TRIDENT_MAPPING = {
7
+ "4.0" => "8",
8
+ "5.0" => "9",
9
+ "6.0" => "10",
10
+ "7.0" => "11",
11
+ "8.0" => "12"
12
+ }.freeze
13
+
14
+ def id
15
+ :ie
16
+ end
17
+
18
+ def name
19
+ "Internet Explorer"
20
+ end
21
+
22
+ def full_version
23
+ "#{ie_version}.0"
24
+ end
25
+
26
+ def msie_full_version
27
+ case ua.match(%r{MSIE ([\d.]+)|Trident/.*?; rv:([\d.]+)})
28
+ in [msie, trident_rv] then msie || trident_rv
29
+ else "0.0"
30
+ end
31
+ end
32
+
33
+ def msie_version
34
+ msie_full_version.split(".").first
35
+ end
36
+
37
+ def match?
38
+ msie? || modern_ie?
39
+ end
40
+
41
+ # Detect if IE is running in compatibility mode.
42
+ def compatibility_view?
43
+ trident_version && msie_version.to_i < (trident_version.to_i + 4)
44
+ end
45
+
46
+ private def ie_version
47
+ TRIDENT_MAPPING[trident_version] || msie_version
48
+ end
49
+
50
+ # Return the trident version.
51
+ private def trident_version
52
+ ua[%r{Trident/([0-9.]+)}, 1]
53
+ end
54
+
55
+ private def msie?
56
+ ua.include?("MSIE") && !ua.include?("Opera")
57
+ end
58
+
59
+ private def modern_ie?
60
+ ua.match?(%r{Trident/.*?; rv:(.*?)})
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ class Maxthon < Base
5
+ def id
6
+ :maxthon
7
+ end
8
+
9
+ def name
10
+ "Maxthon"
11
+ end
12
+
13
+ def full_version
14
+ ua[%r{(?:Maxthon)/([\d.]+)}i, 1] || "0.0"
15
+ end
16
+
17
+ def match?
18
+ ua.match?(/Maxthon/i)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ module Meta
5
+ def self.rules
6
+ @rules ||= [
7
+ Device,
8
+ GenericBrowser,
9
+ Id,
10
+ IE,
11
+ IOS,
12
+ Mobile,
13
+ Platform,
14
+ Proxy,
15
+ Safari,
16
+ Tablet,
17
+ Webkit
18
+ ]
19
+ end
20
+
21
+ def self.get(browser)
22
+ rules.flat_map { |rule| rule.new(browser).to_a }.uniq
23
+ end
24
+
25
+ class Base
26
+ # Set the browser instance.
27
+ attr_reader :browser
28
+
29
+ def initialize(browser)
30
+ @browser = browser
31
+ end
32
+
33
+ def meta
34
+ nil
35
+ end
36
+
37
+ def to_a
38
+ meta.to_s.squeeze(" ").split
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ module Meta
5
+ class Device < Base
6
+ def meta
7
+ browser.device.id
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ module Meta
5
+ class GenericBrowser < Base
6
+ def meta
7
+ "#{browser.id} #{browser.id}#{browser.version}" if generic?
8
+ end
9
+
10
+ private def generic?
11
+ !browser.safari? && !browser.chrome?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ module Meta
5
+ class Id < Base
6
+ def meta
7
+ browser.id
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ module Meta
5
+ class IE < Base
6
+ def version
7
+ @version ||= browser.version.to_i
8
+ end
9
+
10
+ def meta
11
+ return unless browser.ie?
12
+
13
+ meta = []
14
+ meta << "oldie lt-ie8 lt-ie9" if version < 8
15
+ meta << "lt-ie9" if version == 8
16
+ meta.join(" ")
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ module Meta
5
+ class IOS < Base
6
+ def meta
7
+ "ios" if browser.platform.ios?
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ module Meta
5
+ class Mobile < Base
6
+ def meta
7
+ "mobile" if browser.device.mobile?
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ module Meta
5
+ class Platform < Base
6
+ def meta
7
+ browser.platform.id
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Browser
4
+ module Meta
5
+ class Proxy < Base
6
+ def meta
7
+ "proxy" if browser.proxy?
8
+ end
9
+ end
10
+ end
11
+ end