browserx 1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +29 -0
- data/LICENSE.md +21 -0
- data/README.md +438 -0
- data/bot_exceptions.yml +5 -0
- data/bots.yml +327 -0
- data/languages.yml +113 -0
- data/lib/browser/accept_language.rb +55 -0
- data/lib/browser/action_controller.rb +20 -0
- data/lib/browser/aliases.rb +33 -0
- data/lib/browser/alipay.rb +21 -0
- data/lib/browser/base.rb +292 -0
- data/lib/browser/blackberry.rb +23 -0
- data/lib/browser/bot/empty_user_agent_matcher.rb +11 -0
- data/lib/browser/bot/keyword_matcher.rb +11 -0
- data/lib/browser/bot/known_bots_matcher.rb +11 -0
- data/lib/browser/bot.rb +119 -0
- data/lib/browser/browser.rb +116 -0
- data/lib/browser/chrome.rb +43 -0
- data/lib/browser/detect_version.rb +22 -0
- data/lib/browser/device/android.rb +20 -0
- data/lib/browser/device/base.rb +13 -0
- data/lib/browser/device/blackberry_playbook.rb +19 -0
- data/lib/browser/device/ipad.rb +19 -0
- data/lib/browser/device/iphone.rb +19 -0
- data/lib/browser/device/ipod_touch.rb +19 -0
- data/lib/browser/device/kindle.rb +19 -0
- data/lib/browser/device/kindle_fire.rb +19 -0
- data/lib/browser/device/playstation3.rb +19 -0
- data/lib/browser/device/playstation4.rb +19 -0
- data/lib/browser/device/psp.rb +19 -0
- data/lib/browser/device/psvita.rb +19 -0
- data/lib/browser/device/samsung.rb +33 -0
- data/lib/browser/device/surface.rb +23 -0
- data/lib/browser/device/switch.rb +19 -0
- data/lib/browser/device/tv.rb +19 -0
- data/lib/browser/device/unknown.rb +19 -0
- data/lib/browser/device/wii.rb +19 -0
- data/lib/browser/device/wiiu.rb +19 -0
- data/lib/browser/device/xbox_360.rb +19 -0
- data/lib/browser/device/xbox_one.rb +19 -0
- data/lib/browser/device.rb +222 -0
- data/lib/browser/duck_duck_go.rb +22 -0
- data/lib/browser/edge.rb +25 -0
- data/lib/browser/electron.rb +22 -0
- data/lib/browser/epiphany.rb +21 -0
- data/lib/browser/facebook.rb +23 -0
- data/lib/browser/firefox.rb +21 -0
- data/lib/browser/google_search_app.rb +21 -0
- data/lib/browser/huawei_browser.rb +21 -0
- data/lib/browser/instagram.rb +21 -0
- data/lib/browser/internet_explorer.rb +63 -0
- data/lib/browser/maxthon.rb +21 -0
- data/lib/browser/meta/base.rb +42 -0
- data/lib/browser/meta/device.rb +11 -0
- data/lib/browser/meta/generic_browser.rb +15 -0
- data/lib/browser/meta/id.rb +11 -0
- data/lib/browser/meta/ie.rb +20 -0
- data/lib/browser/meta/ios.rb +11 -0
- data/lib/browser/meta/mobile.rb +11 -0
- data/lib/browser/meta/platform.rb +11 -0
- data/lib/browser/meta/proxy.rb +11 -0
- data/lib/browser/meta/safari.rb +11 -0
- data/lib/browser/meta/tablet.rb +11 -0
- data/lib/browser/meta/webkit.rb +11 -0
- data/lib/browser/meta.rb +14 -0
- data/lib/browser/micro_messenger.rb +21 -0
- data/lib/browser/middleware/context/additions.rb +18 -0
- data/lib/browser/middleware/context/url_methods.rb +15 -0
- data/lib/browser/middleware/context.rb +22 -0
- data/lib/browser/middleware.rb +70 -0
- data/lib/browser/miui_browser.rb +21 -0
- data/lib/browser/nokia.rb +21 -0
- data/lib/browser/opera.rb +21 -0
- data/lib/browser/otter.rb +21 -0
- data/lib/browser/phantom_js.rb +21 -0
- data/lib/browser/platform/adobe_air.rb +23 -0
- data/lib/browser/platform/android.rb +23 -0
- data/lib/browser/platform/base.rb +18 -0
- data/lib/browser/platform/blackberry.rb +23 -0
- data/lib/browser/platform/chrome_os.rb +23 -0
- data/lib/browser/platform/firefox_os.rb +23 -0
- data/lib/browser/platform/ios.rb +36 -0
- data/lib/browser/platform/kai_os.rb +23 -0
- data/lib/browser/platform/linux.rb +23 -0
- data/lib/browser/platform/mac.rb +25 -0
- data/lib/browser/platform/unknown.rb +23 -0
- data/lib/browser/platform/windows.rb +23 -0
- data/lib/browser/platform/windows_mobile.rb +23 -0
- data/lib/browser/platform/windows_phone.rb +23 -0
- data/lib/browser/platform.rb +193 -0
- data/lib/browser/qq.rb +25 -0
- data/lib/browser/rails.rb +23 -0
- data/lib/browser/safari.rb +40 -0
- data/lib/browser/samsung_browser.rb +21 -0
- data/lib/browser/snapchat.rb +21 -0
- data/lib/browser/sougou_browser.rb +24 -0
- data/lib/browser/sputnik.rb +21 -0
- data/lib/browser/testing.rb +27 -0
- data/lib/browser/uc_browser.rb +21 -0
- data/lib/browser/unknown.rb +32 -0
- data/lib/browser/version.rb +5 -0
- data/lib/browser/weibo.rb +21 -0
- data/lib/browser/yandex.rb +21 -0
- data/lib/browser.rb +4 -0
- data/lib/browserx.rb +3 -0
- data/samsung.yml +138 -0
- data/search_engines.yml +7 -0
- data/test/ua.yml +181 -0
- data/test/ua_bots.yml +121 -0
- data/test/ua_search_engines.yml +7 -0
- metadata +267 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Browser
|
|
4
|
+
class Device
|
|
5
|
+
class Samsung < Base
|
|
6
|
+
REGEX = /\(Linux.*?; Android.*?; (SAMSUNG )?(SM-[A-Z0-9]+).*?\)/i
|
|
7
|
+
|
|
8
|
+
def self.names
|
|
9
|
+
@names ||= YAML.load_file(Browser.root.join("samsung.yml").to_s)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def id
|
|
13
|
+
:samsung
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def name
|
|
17
|
+
"Samsung #{self.class.names[code] || code}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def code
|
|
21
|
+
matches && matches[2]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def matches
|
|
25
|
+
@matches ||= ua.match(REGEX)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def match?
|
|
29
|
+
!!matches
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Browser
|
|
4
|
+
class Device
|
|
5
|
+
class Surface < Base
|
|
6
|
+
def id
|
|
7
|
+
:surface
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def name
|
|
11
|
+
"Microsoft Surface"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def match?
|
|
15
|
+
platform.windows_rt? && ua.include?("Touch")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private def platform
|
|
19
|
+
@platform ||= Platform.new(ua)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,222 @@
|
|
|
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)
|
|
57
|
+
@ua = ua
|
|
58
|
+
@platform = platform
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def subject
|
|
62
|
+
@subject ||= self.class.matchers.each do |matcher|
|
|
63
|
+
candidate = matcher.new(ua)
|
|
64
|
+
break candidate if candidate.match?
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def id
|
|
69
|
+
subject.id
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def name
|
|
73
|
+
subject.name
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Detect if browser is tablet (currently iPad, Android, Surface or
|
|
77
|
+
# Playbook).
|
|
78
|
+
def tablet?
|
|
79
|
+
ipad? ||
|
|
80
|
+
(platform.android? && !detect_mobile?) ||
|
|
81
|
+
surface? ||
|
|
82
|
+
playbook?
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Detect if browser is mobile.
|
|
86
|
+
def mobile?
|
|
87
|
+
detect_mobile? && !tablet?
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def ipad?
|
|
91
|
+
id == :ipad
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def unknown?
|
|
95
|
+
id == :unknown_device
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def ipod_touch?
|
|
99
|
+
id == :ipod_touch
|
|
100
|
+
end
|
|
101
|
+
alias_method :ipod?, :ipod_touch?
|
|
102
|
+
|
|
103
|
+
def iphone?
|
|
104
|
+
id == :iphone
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def ps3?
|
|
108
|
+
id == :ps3
|
|
109
|
+
end
|
|
110
|
+
alias_method :playstation3?, :ps3?
|
|
111
|
+
|
|
112
|
+
def ps4?
|
|
113
|
+
id == :ps4
|
|
114
|
+
end
|
|
115
|
+
alias_method :playstation4?, :ps4?
|
|
116
|
+
|
|
117
|
+
def psp?
|
|
118
|
+
id == :psp
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def playstation_vita?
|
|
122
|
+
id == :psvita
|
|
123
|
+
end
|
|
124
|
+
alias_method :vita?, :playstation_vita?
|
|
125
|
+
alias_method :psp_vita?, :playstation_vita?
|
|
126
|
+
|
|
127
|
+
def kindle?
|
|
128
|
+
id == :kindle || kindle_fire?
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def kindle_fire?
|
|
132
|
+
id == :kindle_fire
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def nintendo_wii?
|
|
136
|
+
id == :wii
|
|
137
|
+
end
|
|
138
|
+
alias_method :wii?, :nintendo_wii?
|
|
139
|
+
|
|
140
|
+
def nintendo_wiiu?
|
|
141
|
+
id == :wiiu
|
|
142
|
+
end
|
|
143
|
+
alias_method :wiiu?, :nintendo_wiiu?
|
|
144
|
+
|
|
145
|
+
def nintendo_switch?
|
|
146
|
+
id == :switch
|
|
147
|
+
end
|
|
148
|
+
alias_method :switch?, :nintendo_switch?
|
|
149
|
+
|
|
150
|
+
def blackberry_playbook?
|
|
151
|
+
id == :playbook
|
|
152
|
+
end
|
|
153
|
+
alias_method :playbook?, :blackberry_playbook?
|
|
154
|
+
|
|
155
|
+
def surface?
|
|
156
|
+
id == :surface
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def tv?
|
|
160
|
+
id == :tv
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Detect if browser is Silk.
|
|
164
|
+
def silk?
|
|
165
|
+
ua.include?("Silk")
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Detect if browser is running under Xbox.
|
|
169
|
+
def xbox?
|
|
170
|
+
ua.include?("Xbox")
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Detect if browser is running under Xbox 360.
|
|
174
|
+
def xbox_360?
|
|
175
|
+
id == :xbox_360
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Detect if browser is running under Xbox One.
|
|
179
|
+
def xbox_one?
|
|
180
|
+
id == :xbox_one
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Detect if browser is running under PlayStation.
|
|
184
|
+
def playstation?
|
|
185
|
+
ps3? || ps4?
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Detect if browser is Nintendo.
|
|
189
|
+
def nintendo?
|
|
190
|
+
wii? || wiiu? || switch?
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Detect if browser is console (currently Xbox, PlayStation, or Nintendo).
|
|
194
|
+
def console?
|
|
195
|
+
xbox? || playstation? || nintendo?
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Detect if device is a Samsung.
|
|
199
|
+
def samsung?
|
|
200
|
+
id == :samsung
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Regex taken from http://detectmobilebrowsers.com
|
|
204
|
+
# rubocop:disable-next Layout/LineLength
|
|
205
|
+
private def detect_mobile?
|
|
206
|
+
return @detect_mobile if defined?(@detect_mobile)
|
|
207
|
+
|
|
208
|
+
@detect_mobile =
|
|
209
|
+
psp? ||
|
|
210
|
+
/zunewp7|crios/i.match?(ua) ||
|
|
211
|
+
%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.match?(ua) ||
|
|
212
|
+
%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.match?(ua[0..3])
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
private def platform
|
|
216
|
+
@platform ||= Platform.new(ua)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
private :subject
|
|
220
|
+
private :ua
|
|
221
|
+
end
|
|
222
|
+
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
|
data/lib/browser/edge.rb
ADDED
|
@@ -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
|