device_detector 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c4c30ed187479291cfd7f71cff4db8bffd0c69b4
4
+ data.tar.gz: 3e2af5d2b3b5cfb9f7ee9d30b47c976d3a2230d8
5
+ SHA512:
6
+ metadata.gz: 28cc68b8699240a8fa4f099792c25ed73bc2dade2fecc30d2c9c678c88043816cde9667f80735fb15b9811d001f06fa19ec2f27cee03e54e23b31b90f3436d74
7
+ data.tar.gz: 2f9fc0bbde16054f926247af64027d63a91ee6601d2e4c8459cbba94cb07636e07c83d13a000a8329d297a4c2f6afb4c18e8d62b30220f42edcd9ddaed00149b
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in device_detector.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Mati Sójka
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,44 @@
1
+ # DeviceDetector
2
+
3
+ This is a Ruby port of the Universal Device Detection library. You can find the original code here: [https://github.com/piwik/device-detector].
4
+
5
+ The Universal Device Detection library will parse any User Agent and detect the browser, operating system, device used (desktop, tablet, mobile, tv, cars, console, etc.), brand and model.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'device_detector'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install device_detector
22
+
23
+ ## Usage
24
+
25
+ ```ruby
26
+ user_agent = 'foo'
27
+ detector = DeviceDetector.new(user_agent)
28
+
29
+ os = detector.os # extract the operating system details
30
+ os.name # => Mac
31
+ os.full_version # => '10_8_5'
32
+
33
+ client = detector.client # extract the client (browser, device, feed reader) details
34
+ client.name # => Chrome
35
+ client.full_version # => '30.0.1599.69'
36
+ ```
37
+
38
+ ## Contributing
39
+
40
+ 1. Fork it ( https://github.com/[my-github-username]/device_detector/fork )
41
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
42
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
43
+ 4. Push to the branch (`git push origin my-new-feature`)
44
+ 5. Create a new Pull Request
@@ -0,0 +1,11 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ task default: :spec
11
+
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'device_detector/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'device_detector'
8
+ spec.version = DeviceDetector::VERSION
9
+ spec.authors = ['Mati Sójka', 'Ben Zimmer']
10
+ spec.email = ['yagooar@gmail.com']
11
+ spec.summary = %q{Universal Device Detection}
12
+ spec.description = %q{The Universal Device Detection library will parse any User Agent and detect the browser, operating system, device, brand and model.}
13
+ spec.homepage = 'https://github.com/podigee/device_detector'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = []
18
+ spec.test_files = spec.files.grep(%r{^(spec)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'rspec' ,'~> 3.1', '>= 3.1.0'
22
+ spec.add_development_dependency 'pry', '~> 0.10'
23
+ end
@@ -0,0 +1,31 @@
1
+ require 'yaml'
2
+
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+
6
+ require 'device_detector/version'
7
+ require 'device_detector/version_extractor'
8
+ require 'device_detector/os'
9
+ require 'device_detector/client'
10
+ require 'device_detector/os_detector'
11
+ require 'device_detector/client_detector'
12
+
13
+ class DeviceDetector
14
+
15
+ ROOT = Pathname.new(File.expand_path('../..', __FILE__))
16
+
17
+ attr_reader :user_agent
18
+
19
+ def initialize(user_agent)
20
+ @user_agent = user_agent
21
+ end
22
+
23
+ def os
24
+ OSDetector.new(user_agent).call
25
+ end
26
+
27
+ def client
28
+ ClientDetector.new(user_agent).call
29
+ end
30
+
31
+ end
@@ -0,0 +1,18 @@
1
+ class DeviceDetector
2
+ class Client
3
+
4
+ def initialize(user_agent, regex_meta)
5
+ @user_agent = user_agent
6
+ @regex_meta = regex_meta
7
+ end
8
+
9
+ def name
10
+ @regex_meta['name']
11
+ end
12
+
13
+ def full_version
14
+ VersionExtractor.new(@user_agent, @regex_meta).call
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,41 @@
1
+ class DeviceDetector
2
+ class ClientDetector
3
+
4
+ attr_reader :user_agent
5
+
6
+ def initialize(user_agent)
7
+ @user_agent = user_agent
8
+ end
9
+
10
+ def call
11
+ DeviceDetector::Client.new(user_agent, matching_regex)
12
+ end
13
+
14
+ private
15
+
16
+ def matching_regex
17
+ regexes.find { |r| user_agent =~ Regexp.new(r['regex']) }
18
+ end
19
+
20
+ def regexes
21
+ YAML.load(filepaths.map { |filepath| File.read(filepath) }.join)
22
+ end
23
+
24
+ def filepaths
25
+ filenames.map do |filename|
26
+ File.join(DeviceDetector::ROOT, 'regexes', filename)
27
+ end
28
+ end
29
+
30
+ def filenames
31
+ [
32
+ 'browsers.yml',
33
+ 'feed_readers.yml',
34
+ 'libraries.yml',
35
+ 'mediaplayers.yml',
36
+ 'mobile_apps.yml',
37
+ 'pim.yml'
38
+ ]
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,19 @@
1
+ class DeviceDetector
2
+ class OS
3
+
4
+ def initialize(user_agent, regex_meta)
5
+ @user_agent = user_agent
6
+ @regex_meta = regex_meta
7
+ end
8
+
9
+ def name
10
+ @regex_meta['name']
11
+ end
12
+
13
+ def full_version
14
+ VersionExtractor.new(@user_agent, @regex_meta).call
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,29 @@
1
+ class DeviceDetector
2
+ class OSDetector
3
+
4
+ attr_reader :user_agent
5
+
6
+ def initialize(user_agent)
7
+ @user_agent = user_agent
8
+ end
9
+
10
+ def call
11
+ DeviceDetector::OS.new(user_agent, matching_regex)
12
+ end
13
+
14
+ private
15
+
16
+ def matching_regex
17
+ regexes.find { |r| user_agent =~ Regexp.new(r['regex']) }
18
+ end
19
+
20
+ def regexes
21
+ @regexes ||= YAML.load(File.read(filepath))
22
+ end
23
+
24
+ def filepath
25
+ File.join(DeviceDetector::ROOT, 'regexes', 'oss.yml')
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ class DeviceDetector
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,36 @@
1
+ class DeviceDetector
2
+ class VersionExtractor < Struct.new(:user_agent, :regex_meta)
3
+
4
+ def call
5
+ extract_version
6
+ end
7
+
8
+ private
9
+
10
+ def version_string
11
+ regex_meta['version']
12
+ end
13
+
14
+ def extract_version
15
+ user_agent.match(regex) do |match_data|
16
+ replace_version_string_with(match_data)
17
+ end
18
+ end
19
+
20
+ def replace_version_string_with(match_data)
21
+ string = version_string
22
+
23
+ 1.upto(9) do |index|
24
+ string = string.gsub(/\$#{index}/, match_data[index]) if match_data[index]
25
+ end
26
+
27
+ string
28
+ end
29
+
30
+ def regex
31
+ Regexp.new(regex_meta['regex'])
32
+ end
33
+
34
+ end
35
+ end
36
+
@@ -0,0 +1,27 @@
1
+ ###############
2
+ # Device Detector - The Universal Device Detection library for parsing User Agents
3
+ #
4
+ # @link http://piwik.org
5
+ # @license http://www.gnu.org/licenses/lgpl.html LGPL v3 or later
6
+ ###############
7
+
8
+ - regex: 'NetFront'
9
+ name: 'NetFront'
10
+
11
+ - regex: 'Trident'
12
+ name: 'Trident'
13
+
14
+ - regex: 'Blink'
15
+ name: 'Blink'
16
+
17
+ - regex: '(?:Apple)?WebKit'
18
+ name: 'WebKit'
19
+
20
+ - regex: 'Presto'
21
+ name: 'Presto'
22
+
23
+ - regex: '(?<!like )Gecko'
24
+ name: 'Gecko'
25
+
26
+ - regex: 'KHTML'
27
+ name: 'KHTML'
@@ -0,0 +1,742 @@
1
+ ###############
2
+ # Device Detector - The Universal Device Detection library for parsing User Agents
3
+ #
4
+ # @link http://piwik.org
5
+ # @license http://www.gnu.org/licenses/lgpl.html LGPL v3 or later
6
+ ###############
7
+
8
+ #SailfishBrowser
9
+ - regex: 'SailfishBrowser(?:/(\d+[\.\d]+))?'
10
+ name: 'Sailfish Browser'
11
+ version: '$1'
12
+ engine:
13
+ default: 'Gecko'
14
+
15
+ # SeaMonkey
16
+ - regex: '(Iceape|SeaMonkey|gnuzilla)(?:/(\d+[\.\d]+))?'
17
+ name: '$1'
18
+ version: '$2'
19
+ engine:
20
+ default: 'Gecko'
21
+
22
+ # Camino
23
+ - regex: 'Camino(?:/(\d+[\.\d]+))?'
24
+ name: 'Camino'
25
+ version: '$1'
26
+ engine:
27
+ default: 'Gecko'
28
+
29
+ #Fennec (Firefox for mobile)
30
+ - regex: 'Fennec(?:/(\d+[\.\d]+))?'
31
+ name: 'Fennec'
32
+ version: '$1'
33
+ engine:
34
+ default: 'Gecko'
35
+
36
+ #MicroB
37
+ - regex: 'Firefox.*Tablet browser (\d+[\.\d]+)'
38
+ name: 'MicroB'
39
+ version: '$1'
40
+ engine:
41
+ default: 'Gecko'
42
+
43
+ #Avant Browser
44
+ - regex: 'Avant Browser'
45
+ name: 'Avant Browser'
46
+ version: ''
47
+ engine:
48
+ default: '' # multiple
49
+
50
+ #Bunjalloo
51
+ - regex: 'Bunjalloo(?:/(\d+[\.\d]+))?'
52
+ name: 'Bunjalloo'
53
+ version: '$1'
54
+
55
+ #Iceweasel
56
+ - regex: 'Iceweasel(?:/(\d+[\.\d]+))?'
57
+ name: 'Iceweasel'
58
+ version: '$1'
59
+ engine:
60
+ default: 'Gecko'
61
+
62
+ #WebPositive
63
+ - regex: 'WebPositive'
64
+ name: 'WebPositive'
65
+ version: ''
66
+ engine:
67
+ default: 'WebKit'
68
+
69
+
70
+ #Pale Moon
71
+ - regex: 'PaleMoon(?:/(\d+[\.\d]+))?'
72
+ name: 'Pale Moon'
73
+ version: '$1'
74
+ engine:
75
+ default: 'Gecko'
76
+
77
+ #CometBird
78
+ - regex: 'CometBird(?:/(\d+[\.\d]+))?'
79
+ name: 'CometBird'
80
+ version: '$1'
81
+ engine:
82
+ default: 'Gecko'
83
+
84
+ #IceDragon
85
+ - regex: 'IceDragon(?:/(\d+[\.\d]+))?'
86
+ name: 'IceDragon'
87
+ version: '$1'
88
+ engine:
89
+ default: 'Gecko'
90
+
91
+ #Flock
92
+ - regex: 'Flock(?:/(\d+[\.\d]+))?'
93
+ name: 'Flock'
94
+ version: '$1'
95
+ engine:
96
+ default: 'Gecko'
97
+ versions:
98
+ 3: 'WebKit'
99
+
100
+ #Kapiko
101
+ - regex: 'Kapiko(?:/(\d+[\.\d]+))?'
102
+ name: 'Kapiko'
103
+ version: '$1'
104
+ engine:
105
+ default: 'Gecko'
106
+
107
+ #Swiftfox
108
+ - regex: 'Firefox/(\d+[\.\d]+).*\(Swiftfox\)'
109
+ name: 'Swiftfox'
110
+ version: '$1'
111
+ engine:
112
+ default: 'Gecko'
113
+
114
+ #Firefox
115
+ - regex: 'Firefox(?:/(\d+[\.\d]+))?'
116
+ name: 'Firefox'
117
+ version: '$1'
118
+ engine:
119
+ default: 'Gecko'
120
+ - regex: '(BonEcho|GranParadiso|Lorentz|Minefield|Namoroka|Shiretoko)/(\d+[\.\d]+)'
121
+ name: 'Firefox'
122
+ version: '$1 ($2)'
123
+ engine:
124
+ default: 'Gecko'
125
+
126
+ #ANTGalio
127
+ - regex: 'ANTGalio(?:/(\d+[\.\d]+))?'
128
+ name: 'ANTGalio'
129
+ version: '$1'
130
+
131
+ #Espial TV Browser
132
+ - regex: '(?:Espial|Escape)(?:[/ ](\d+[\.\d]+))?'
133
+ name: 'Espial TV Browser'
134
+ version: '$1'
135
+
136
+ #RockMelt
137
+ - regex: 'RockMelt(?:/(\d+[\.\d]+))?'
138
+ name: 'RockMelt'
139
+ version: '$1'
140
+ engine:
141
+ default: 'WebKit'
142
+
143
+ #Fireweb Navigator
144
+ - regex: 'Fireweb Navigator(?:/(\d+[\.\d]+))?'
145
+ name: 'Fireweb Navigator'
146
+ version: '$1'
147
+
148
+ #Netscape
149
+ - regex: '(?:Navigator|Netscape6)(?:/(\d+[\.\d]+))?'
150
+ name: 'Netscape'
151
+ version: '$1'
152
+ engine:
153
+ default: '' # Mosaic in the first versions, then Gecko
154
+
155
+ #Opera
156
+ - regex: '(?:Opera Tablet.*Version|Opera/.+Opera Mobi.+Version|Mobile.+OPR)/(\d+[\.\d]+)'
157
+ name: 'Opera Mobile'
158
+ version: '$1'
159
+ engine:
160
+ default: 'Presto'
161
+ versions:
162
+ 15: 'Blink'
163
+ - regex: 'Opera Mini/(?:att/)?(\d+[\.\d]+)'
164
+ name: 'Opera Mini'
165
+ version: '$1'
166
+ engine:
167
+ default: 'Presto'
168
+ - regex: 'Opera.+Edition Next.+Version/(\d+[\.\d]+)'
169
+ name: 'Opera Next'
170
+ version: '$1'
171
+ engine:
172
+ default: 'Presto'
173
+ versions:
174
+ 15: 'Blink'
175
+ - regex: '(?:Opera|OPR)[/ ](?:9.80.*Version/)?(\d+[\.\d]+).+Edition Next'
176
+ name: 'Opera Next'
177
+ version: '$1'
178
+ engine:
179
+ default: 'Presto'
180
+ versions:
181
+ 15: 'Blink'
182
+ - regex: '(?:Opera|OPR)[/ ](?:9.80.*Version/)?(\d+[\.\d]+)'
183
+ name: 'Opera'
184
+ version: '$1'
185
+ engine:
186
+ default: 'Presto'
187
+ versions:
188
+ 15: 'Blink'
189
+
190
+ #Rekonq
191
+ - regex: 'rekonq(?:/(\d+[\.\d]+))?'
192
+ name: 'Rekonq'
193
+ version: '$1'
194
+ engine:
195
+ default: 'WebKit'
196
+
197
+ #CoolNovo (former ChromePlus)
198
+ - regex: 'CoolNovo(?:/(\d+[\.\d]+))?'
199
+ name: 'CoolNovo'
200
+ version: '$1'
201
+ engine:
202
+ default: '' # multi engine
203
+
204
+ #Comodo Dragon
205
+ - regex: 'Comodo[ _]Dragon(?:/(\d+[\.\d]+))?'
206
+ name: 'Comodo Dragon'
207
+ version: '$1'
208
+ engine:
209
+ default: 'WebKit'
210
+ versions:
211
+ 28: 'Blink'
212
+
213
+ #ChromePlus
214
+ - regex: 'ChromePlus(?:/(\d+[\.\d]+))?'
215
+ name: 'ChromePlus'
216
+ version: '$1'
217
+ engine:
218
+ default: '' # multi engine
219
+
220
+ #Conkeror
221
+ - regex: 'Conkeror(?:/(\d+[\.\d]+))?'
222
+ name: 'Conkeror'
223
+ version: '$1'
224
+ engine:
225
+ default: 'Gecko'
226
+
227
+ #Konqueror
228
+ - regex: 'Konqueror(?:/(\d+[\.\d]+))?'
229
+ name: 'Konqueror'
230
+ version: '$1'
231
+ engine:
232
+ default: 'KHTML'
233
+ versions:
234
+ 4: '' # multiple (KHTML or WebKit)
235
+
236
+ #Baidu Browser
237
+ - regex: 'baidubrowser(?:[/ ](\d+[\.\d]*))?'
238
+ name: 'Baidu Browser'
239
+ version: '$1'
240
+
241
+ #Baidu Spark
242
+ - regex: '(?:(?:BD)?Spark|BIDUBrowser)[/ ](\d+[\.\d]*)'
243
+ name: 'Baidu Spark'
244
+ version: '$1'
245
+
246
+ #Yandex Browser
247
+ - regex: 'YaBrowser(?:/(\d+[\.\d]*))?'
248
+ name: 'Yandex Browser'
249
+ version: '$1'
250
+ engine:
251
+ default: 'Blink'
252
+
253
+ #Midori
254
+ - regex: 'Midori(?:/(\d+[\.\d]+))?'
255
+ name: 'Midori'
256
+ version: '$1'
257
+ engine:
258
+ default: 'WebKit'
259
+
260
+ #Mercury
261
+ - regex: 'Mercury(?:/(\d+[\.\d]+))?'
262
+ name: 'Mercury'
263
+ version: '$1'
264
+
265
+ #Maxthon
266
+ - regex: 'Maxthon[ /](\d+[\.\d]+)'
267
+ name: 'Maxthon'
268
+ version: '$1'
269
+ engine:
270
+ default: '' # Trident and WebKit
271
+ versions:
272
+ 3: 'WebKit'
273
+
274
+ - regex: '(?:Maxthon|MyIE2|Uzbl)'
275
+ name: 'Maxthon'
276
+ version: ''
277
+ engine:
278
+ default: '' # Trident and WebKit
279
+
280
+ #Puffin
281
+ - regex: 'Puffin(?:/(\d+[\.\d]+))?'
282
+ name: 'Puffin'
283
+ version: '$1'
284
+
285
+ #Iron
286
+ - regex: 'Iron(?:/(\d+[\.\d]+))?'
287
+ name: 'Iron'
288
+ version: '$1'
289
+ engine:
290
+ default: 'WebKit'
291
+ versions:
292
+ 28: 'Blink'
293
+
294
+ #Epiphany
295
+ - regex: 'Epiphany(?:/(\d+[\.\d]+))?'
296
+ name: 'Epiphany'
297
+ version: '$1'
298
+ engine:
299
+ default: 'Gecko'
300
+ versions:
301
+ 2.9.16: '' # multi engine
302
+ 2.28: 'WebKit'
303
+
304
+ # Liebao
305
+ - regex: 'LBBrowser(?:[ /](\d+[\.\d]+))?'
306
+ name: 'Liebao'
307
+ version: '$1'
308
+
309
+ # Sogou Explorer
310
+ - regex: 'SE (\d+[\.\d]+)'
311
+ name: 'Sogou Explorer'
312
+ version: '$1'
313
+
314
+ #Chrome
315
+ - regex: 'CrMo(?:/(\d+[\.\d]+))?'
316
+ name: 'Chrome Mobile'
317
+ version: '$1'
318
+ engine:
319
+ default: 'WebKit'
320
+ versions:
321
+ 28: 'Blink'
322
+ - regex: 'CriOS(?:/(\d+[\.\d]+))?'
323
+ name: 'Chrome Mobile iOS'
324
+ version: '$1'
325
+ engine:
326
+ default: 'WebKit'
327
+ - regex: 'Chrome(?:/(\d+[\.\d]+))?.*Mobile'
328
+ name: 'Chrome Mobile'
329
+ version: '$1'
330
+ engine:
331
+ default: 'WebKit'
332
+ versions:
333
+ 28: 'Blink'
334
+ - regex: 'chromeframe(?:/(\d+[\.\d]+))?'
335
+ name: 'Chrome Frame'
336
+ version: '$1'
337
+ engine:
338
+ default: 'WebKit'
339
+ - regex: 'Chromium(?:/(\d+[\.\d]+))?'
340
+ name: 'Chromium'
341
+ version: '$1'
342
+ engine:
343
+ default: 'WebKit'
344
+ versions:
345
+ 28: 'Blink'
346
+ - regex: 'Chrome(?:/(\d+[\.\d]+))?'
347
+ name: 'Chrome'
348
+ version: '$1'
349
+ engine:
350
+ default: 'WebKit'
351
+ versions:
352
+ 28: 'Blink'
353
+
354
+ #UC Browser
355
+ - regex: 'UC[ ]?Browser(?:[ /]?(\d+[\.\d]+))?'
356
+ name: 'UC Browser'
357
+ version: '$1'
358
+ - regex: 'UCWEB(?:[ /]?(\d+[\.\d]+))?'
359
+ name: 'UC Browser'
360
+ version: '$1'
361
+
362
+ #Tizen Browser
363
+ - regex: '(?:Tizen|SLP) Browser(?:/(\d+[\.\d]+))?'
364
+ name: 'Tizen Browser'
365
+ version: '$1'
366
+
367
+ #Palm Blazer
368
+ - regex: 'Blazer(?:/(\d+[\.\d]+))?'
369
+ name: 'Palm Blazer'
370
+ version: '$1'
371
+ - regex: 'Pre/(\d+[\.\d]+)'
372
+ name: 'Palm Pre'
373
+ version: '$1'
374
+
375
+ #wOSBrowser
376
+ - regex: '(?:hpw|web)OS/(\d+[\.\d]+)'
377
+ name: 'wOSBrowser'
378
+ version: '$1'
379
+
380
+ #Palm WebPro
381
+ - regex: 'WebPro(?:[ /](\d+[\.\d]+))?'
382
+ name: 'Palm WebPro'
383
+ version: '$1'
384
+
385
+ #Jasmine
386
+ - regex: 'Jasmine(?:[ /](\d+[\.\d]+))?'
387
+ name: 'Jasmine'
388
+ version: '$1'
389
+
390
+ #Lynx
391
+ - regex: 'Lynx(?:/(\d+[\.\d]+))?'
392
+ name: 'Lynx'
393
+ version: '$1'
394
+ engine:
395
+ default: 'Text-based'
396
+
397
+ #NCSA Mosaic
398
+ - regex: 'NCSA_Mosaic(?:/(\d+[\.\d]+))?'
399
+ name: 'NCSA Mosaic'
400
+ version: '$1'
401
+
402
+ #ABrowse
403
+ - regex: 'ABrowse(?: (\d+[\.\d]+))?'
404
+ name: 'ABrowse'
405
+ version: '$1'
406
+
407
+ #Amaya
408
+ - regex: 'amaya(?:/(\d+[\.\d]+))?'
409
+ name: 'Amaya'
410
+ version: '$1'
411
+
412
+ #Amiga Voyager
413
+ - regex: 'AmigaVoyager(?:/(\d+[\.\d]+))?'
414
+ name: 'Amiga Voyager'
415
+ version: '$1'
416
+
417
+ #Amiga Aweb
418
+ - regex: 'Amiga-Aweb(?:/(\d+[\.\d]+))?'
419
+ name: 'Amiga Aweb'
420
+ version: '$1'
421
+
422
+ #Arora
423
+ - regex: 'Arora(?:/(\d+[\.\d]+))?'
424
+ name: 'Arora'
425
+ version: '$1'
426
+ engine:
427
+ default: 'WebKit'
428
+
429
+ #Beonex
430
+ - regex: 'Beonex(?:/(\d+[\.\d]+))?'
431
+ name: 'Beonex'
432
+ version: '$1'
433
+ engine:
434
+ default: 'Gecko'
435
+
436
+ #BlackBerry Browser
437
+ - regex: 'BlackBerry|PlayBook|BB10'
438
+ name: 'BlackBerry Browser'
439
+ version: ''
440
+
441
+ #BrowseX
442
+ - regex: 'BrowseX \((\d+[\.\d]+)'
443
+ name: 'BrowseX'
444
+ version: '$1'
445
+
446
+ #Charon
447
+ - regex: 'Charon(?:[/ ](\d+[\.\d]+))?'
448
+ name: 'Charon'
449
+ version: '$1'
450
+
451
+ #Cheshire
452
+ - regex: 'Cheshire(?:/(\d+[\.\d]+))?'
453
+ name: 'Cheshire'
454
+ version: '$1'
455
+
456
+ #Dillo
457
+ - regex: 'Dillo(?:/(\d+[\.\d]+))?'
458
+ name: 'Dillo'
459
+ version: '$1'
460
+ engine:
461
+ default: 'Dillo'
462
+
463
+ #Dolphin
464
+ - regex: 'Dolfin(?:/(\d+[\.\d]+))?|dolphin'
465
+ name: 'Dolphin'
466
+ version: '$1'
467
+ engine:
468
+ default: 'WebKit'
469
+
470
+ #Elinks
471
+ - regex: 'Elinks(?:/(\d+[\.\d]+))?'
472
+ name: 'Elinks'
473
+ version: '$1'
474
+ engine:
475
+ default: 'Text-based'
476
+
477
+ #Firebird
478
+ - regex: 'Firebird(?:/(\d+[\.\d]+))?'
479
+ name: 'Firebird'
480
+ version: '$1'
481
+ engine:
482
+ default: 'Gecko'
483
+
484
+ #Fluid
485
+ - regex: 'Fluid(?:/(\d+[\.\d]+))?'
486
+ name: 'Fluid'
487
+ version: '$1'
488
+ engine:
489
+ default: 'WebKit'
490
+
491
+ #Galeon
492
+ - regex: 'Galeon(?:/(\d+[\.\d]+))?'
493
+ name: 'Galeon'
494
+ version: '$1'
495
+ engine:
496
+ default: 'Gecko'
497
+
498
+ #Google Earth
499
+ - regex: 'Google Earth(?:/(\d+[\.\d]+))?'
500
+ name: 'Google Earth'
501
+ version: '$1'
502
+ engine:
503
+ default: 'WebKit'
504
+
505
+ #HotJava
506
+ - regex: 'HotJava(?:/(\d+[\.\d]+))?'
507
+ name: 'HotJava'
508
+ version: '$1'
509
+
510
+ #IBrowse
511
+ - regex: 'IBrowse(?:[ /](\d+[\.\d]+))?'
512
+ name: 'IBrowse'
513
+ version: '$1'
514
+
515
+ #iCab
516
+ - regex: 'iCab(?:[ /](\d+[\.\d]+))?'
517
+ name: 'iCab'
518
+ version: '$1'
519
+ engine:
520
+ default: 'iCab'
521
+ versions:
522
+ 4: 'WebKit'
523
+
524
+ #Sleipnir
525
+ - regex: 'Sleipnir(?:[ /](\d+[\.\d]+))?'
526
+ name: 'Sleipnir'
527
+ version: '$1'
528
+ engine:
529
+ default: '' # multi engine
530
+
531
+ #Lunascape
532
+ - regex: 'Lunascape(?:[/ ](\d+[\.\d]+))?'
533
+ name: 'Lunascape'
534
+ version: '$1'
535
+ engine:
536
+ default: '' # multi engine
537
+
538
+ #Internet Explorer
539
+ - regex: 'IEMobile[ /](\d+[\.\d]+)'
540
+ name: 'IE Mobile'
541
+ version: '$1'
542
+ engine:
543
+ default: 'Trident'
544
+ - regex: 'MSIE (\d+[\.\d]+).*XBLWP7'
545
+ name: 'IE Mobile'
546
+ version: '$1'
547
+ engine:
548
+ default: 'Trident'
549
+ - regex: 'MSIE.*Trident/4.0'
550
+ name: 'Internet Explorer'
551
+ version: 8.0
552
+ engine:
553
+ default: 'Trident'
554
+ - regex: 'MSIE.*Trident/5.0'
555
+ name: 'Internet Explorer'
556
+ version: 9.0
557
+ engine:
558
+ default: 'Trident'
559
+ - regex: 'MSIE.*Trident/6.0'
560
+ name: 'Internet Explorer'
561
+ version: 10.0
562
+ engine:
563
+ default: 'Trident'
564
+ - regex: 'Trident/7.0'
565
+ name: 'Internet Explorer'
566
+ version: 11.0
567
+ engine:
568
+ default: 'Trident'
569
+ - regex: 'MSIE (\d+[\.\d]+)'
570
+ name: 'Internet Explorer'
571
+ version: '$1'
572
+ engine:
573
+ default: 'Trident'
574
+ - regex: 'IE[ /](\d+[\.\d]++)'
575
+ name: 'Internet Explorer'
576
+ version: '$1'
577
+ engine:
578
+ default: 'Trident'
579
+
580
+ #Kazehakase
581
+ - regex: 'Kazehakase(?:/(\d+[\.\d]+))?'
582
+ name: 'Kazehakase'
583
+ version: '$1'
584
+ engine:
585
+ default: '' # multi engine
586
+
587
+ #Kindle Browser
588
+ - regex: 'Kindle/(\d+[\.\d]+)'
589
+ name: 'Kindle Browser'
590
+ version: '$1'
591
+
592
+ #K-meleon
593
+ - regex: 'K-meleon(?:/(\d+[\.\d]+))?'
594
+ name: 'K-meleon'
595
+ version: '$1'
596
+ engine:
597
+ default: 'Gecko'
598
+
599
+ #Links
600
+ - regex: 'Links(?: \((\d+[\.\d]+))?'
601
+ name: 'Links'
602
+ version: '$1'
603
+ engine:
604
+ default: 'Text-based'
605
+
606
+ #Openwave Mobile Browser
607
+ - regex: 'UP.Browser(?:/(\d+[\.\d]+))?'
608
+ name: 'Openwave Mobile Browser'
609
+ version: '$1'
610
+
611
+ #OmniWeb
612
+ - regex: 'OmniWeb(?:/[v]?(\d+[\.\d]+))?'
613
+ name: 'OmniWeb'
614
+ version: '$1'
615
+ engine:
616
+ default: 'WebKit'
617
+
618
+ #Phoenix
619
+ - regex: 'Phoenix(?:/(\d+[\.\d]+))?'
620
+ name: 'Phoenix'
621
+ version: '$1'
622
+
623
+ #Mobile Silk
624
+ - regex: 'Silk(?:/(\d+[\.\d]+))?'
625
+ name: 'Mobile Silk'
626
+ version: '$1'
627
+ engine:
628
+ default: 'Blink'
629
+
630
+ #Nokia Browser
631
+ - regex: '(?:NokiaBrowser|BrowserNG)(?:/(\d+[\.\d]+))?'
632
+ name: 'Nokia Browser'
633
+ version: '$1'
634
+ - regex: 'Series60/5\.0'
635
+ name: 'Nokia Browser'
636
+ version: '7.0'
637
+ - regex: 'Series60/(\d+[\.\d]+)'
638
+ name: 'Nokia OSS Browser'
639
+ version: '$1'
640
+ - regex: 'S40OviBrowser/(\d+[\.\d]+)'
641
+ name: 'Nokia Ovi Browser'
642
+ version: '$1'
643
+ - regex: '^Nokia|Nokia[EN]?\d+'
644
+ name: 'Nokia Browser'
645
+ version: ''
646
+
647
+ #NetFront
648
+ - regex: 'NetFrontLifeBrowser(?:/(\d+[\.\d]+))?'
649
+ name: 'NetFront Life'
650
+ version: '$1'
651
+ engine:
652
+ default: 'NetFront'
653
+ - regex: 'NetFront(?:/(\d+[\.\d]+))?'
654
+ name: 'NetFront'
655
+ version: '$1'
656
+ engine:
657
+ default: 'NetFront'
658
+ - regex: 'PLAYSTATION|NINTENDO 3|AppleWebKit.+ NX/\d+\.\d+\.\d+'
659
+ name: 'NetFront'
660
+ version: ''
661
+
662
+ #NetPositive
663
+ - regex: 'NetPositive(?:/(\d+[\.\d]+))?'
664
+ name: 'NetPositive'
665
+ version: '$1'
666
+
667
+ #Obigo
668
+ - regex: 'Obigo[ ]?(?:InternetBrowser|Browser)?(?:[ /]([a-z0-9]*))?'
669
+ name: 'Obigo'
670
+ version: '$1'
671
+ - regex: 'Obigo|Teleca'
672
+ name: 'Obigo'
673
+ version: ''
674
+
675
+ #Oregano
676
+ - regex: 'Oregano(?:[ /](\d+[\.\d]+))?'
677
+ name: 'Oregano'
678
+ version: '$1'
679
+
680
+ #Polaris
681
+ - regex: '(?:Polaris|Embider)(?:[/ ](\d+[\.\d]+))?'
682
+ name: 'Polaris'
683
+ version: '$1'
684
+
685
+ #SEMC Browser
686
+ - regex: 'SEMC-Browser(?:[/ ](\d+[\.\d]+))?'
687
+ name: 'SEMC-Browser'
688
+ version: '$1'
689
+
690
+ #Shiira
691
+ - regex: 'Shiira(?:[/ ](\d+[\.\d]+))?'
692
+ name: 'Shiira'
693
+ version: '$1'
694
+ engine:
695
+ default: 'WebKit'
696
+
697
+ #Snowshoe
698
+ - regex: 'Snowshoe(?:/(\d+[\.\d]+))?'
699
+ name: 'Snowshoe'
700
+ version: '$1'
701
+ engine:
702
+ default: 'WebKit'
703
+
704
+ #Sunrise
705
+ - regex: 'Sunrise(?:Browser)?(?:/(\d+[\.\d]+))?'
706
+ name: 'Sunrise'
707
+ version: '$1'
708
+
709
+ #Xiino
710
+ - regex: 'Xiino(?:/(\d+[\.\d]+))?'
711
+ name: 'Xiino'
712
+ version: '$1'
713
+
714
+ #Android Browser
715
+ - regex: 'Android'
716
+ name: 'Android Browser'
717
+ version: ''
718
+ engine:
719
+ default: 'WebKit'
720
+
721
+ #Safari
722
+ - regex: '(?:iPod|iPad|iPhone).+Version/(\d+[\.\d]+)'
723
+ name: 'Mobile Safari'
724
+ version: '$1'
725
+ engine:
726
+ default: 'WebKit'
727
+ - regex: 'Version/(\d+[\.\d]+).*Mobile.*Safari/'
728
+ name: 'Mobile Safari'
729
+ version: '$1'
730
+ engine:
731
+ default: 'WebKit'
732
+ - regex: '(?:iPod|iPhone|iPad)'
733
+ name: 'Mobile Safari'
734
+ version: ''
735
+ engine:
736
+ default: 'WebKit'
737
+ - regex: 'Version/(\d+[\.\d]+).*Safari/|Safari/\d+'
738
+ name: 'Safari'
739
+ version: '$1'
740
+ engine:
741
+ default: 'WebKit'
742
+