browserino 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1bdd2af440a3b1476900a3cdd36d2905660053c6
4
- data.tar.gz: 0c7a2151e6ec79341ba5dda81eceddef2e8128ed
3
+ metadata.gz: b85dfc764ad259ee956ed4fd456d2a3d157f0e17
4
+ data.tar.gz: b8f96ecc2cc453dada5c1ca5df9dbd3216c0d6a9
5
5
  SHA512:
6
- metadata.gz: fb4d367fb7cfd3bd9cf637998de4a41549e18f20aaa0f14e007cb28883aff70b66e4beb75f757d99fe299b61a77db0c4322b90da74691e30677c524428a1c3eb
7
- data.tar.gz: c13adf9ce004e08c5504b07367c5f362446ca06dbc6abe372872f703cca9694e8b3dd6f8fd7900970dea265a917e5d37ca9e951aef94176f241afaa4eba3f82c
6
+ metadata.gz: 66997f7437d4108c2779f2a1c2d07b0b41b6d95772435e4616ebde8567936bd87545d775db05fc6c81602bbf79a6693e22b938bae2724f130e0c660fddb54c18
7
+ data.tar.gz: a6f8eed6eedd79d2621a6982f1aa52d37302e7bc0577880f30cbcd8bea4f6864811703ac72e48fa6960f4a48f7bafb3ff5a78e5f9faf7b4765ac11b3183bc402
data/.rubocop.yml CHANGED
@@ -4,6 +4,8 @@ AllCops:
4
4
  - 'Guardfile'
5
5
  - '*.gemspec'
6
6
  - 'Rakefile'
7
+ - 'tmp/**/*'
8
+ - 'vendor/**/*'
7
9
 
8
10
  Documentation:
9
11
  Enabled: false
@@ -11,9 +13,25 @@ Documentation:
11
13
  Lint/AmbiguousRegexpLiteral:
12
14
  Enabled: false
13
15
 
16
+ Style/CaseEquality:
17
+ Enabled: false
18
+
14
19
  Style/RegexpLiteral:
15
20
  Enabled: false
16
21
 
22
+ Style/MethodMissing:
23
+ Enabled: false
24
+
25
+ Metrics/BlockLength:
26
+ Enabled: false
27
+
28
+ Metrics/AbcSize:
29
+ Max: 20
30
+
31
+ Metrics/ClassLength:
32
+ CountComments: false
33
+ Max: 175
34
+
17
35
  Metrics/MethodLength:
18
36
  CountComments: false
19
37
  Max: 15
data/.travis.yml CHANGED
@@ -1,3 +1,5 @@
1
+ sudo: false
2
+ cache: bundler
1
3
  language: ruby
2
4
  rvm:
3
5
  - 2.0.0
@@ -6,4 +8,6 @@ rvm:
6
8
  - 2.3.0
7
9
  - 2.4.0
8
10
  before_install: gem install bundler
9
- script: bundle exec rspec spec
11
+ script:
12
+ - bundle exec rspec spec
13
+ - bundle exec rubocop
data/bin/browserino CHANGED
@@ -25,4 +25,4 @@ row = '+' * (out.map(&:size).max - 1) + "\n"
25
25
 
26
26
  out[0] = "#{row}#{out[0]}"
27
27
  out[-1] = "#{out[-1]}#{row}"
28
- puts out.join("#{row}")
28
+ puts out.join row
data/bin/console CHANGED
@@ -4,9 +4,8 @@ require 'bundler/setup'
4
4
  require 'pry'
5
5
  require 'browserino'
6
6
 
7
- @client = Browserino.parse ARGV[0].dup || 'Mozilla/5.0 (Macintosh; Intel Mac\
8
- OS X 10_11_2) AppleWebKit/601.3.9\
9
- (KHTML, l ike Gecko) Version/9.0.\
10
- 2 Safari/601.3.9'
7
+ smpl = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9' \
8
+ ' (KHTML, l ike Gecko) Version/9.0.2 Safari/601.3.9'
11
9
 
10
+ @client = Browserino.parse(ARGV[0].dup || smpl)
12
11
  Pry.start
data/browserino.gemspec CHANGED
@@ -5,7 +5,7 @@ require 'browserino/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "browserino"
8
- spec.version = Browserino::VERSION
8
+ spec.version = Browserino.version.full
9
9
  spec.authors = ["Sidney Liebrand"]
10
10
  spec.email = ["sidneyliebrand@gmail.com"]
11
11
  spec.summary = %q{A browser identification gem with command line and Rails (>= 3.2.0) integration}
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.add_development_dependency "bundler", "~> 1.14"
21
21
  spec.add_development_dependency "rake", "~> 12.0"
22
22
  spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "rubocop"
23
24
  spec.add_development_dependency "coveralls"
24
25
  spec.add_development_dependency "pry"
25
26
  end
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Browserino
3
4
  class Client
4
5
  attr_reader :property_names
5
6
 
6
7
  def initialize(props = {}, like = nil)
7
- @property_names = props.is_a?(Hash) && props.keys || []
8
- @like = like if like
8
+ @property_names = props.keys
9
+ @like = like
10
+
9
11
  # properties are added as methods that will each be defined in a specific
10
12
  # order below. First, seperate static value methods from procs,
11
13
  # procs will be able to call methods in this instances' context
@@ -61,10 +63,8 @@ module Browserino
61
63
  @x32_cache ||= architecture == :x32
62
64
  end
63
65
 
64
- # check the type of a Client
65
- def type?(sym)
66
- return type == sym if sym.is_a? Symbol
67
- type == sym.to_sym
66
+ def arm?
67
+ @arm_cache ||= architecture == :arm
68
68
  end
69
69
 
70
70
  # the catch all method, anything it can ask as question will respond
@@ -105,12 +105,13 @@ module Browserino
105
105
  end
106
106
 
107
107
  def to_s
108
- @str_cache ||= [:name, :engine, :platform].map do |prop|
109
- name = send prop
110
- ver = version if prop == :name
111
- ver = send "#{prop}_version" if ver.nil?
108
+ @str_cache ||= %i[name engine platform].map do |prop|
109
+ n = properties[prop]
110
+ v = version_for prop
111
+ l = label_for prop
112
+ a = l ? l : [n, (v.major if v > '0.0.0')].join.to_sym
112
113
 
113
- [[name], [name, (ver.major if ver > '0.0.0')].compact.join.to_sym]
114
+ [n, a].uniq
114
115
  end.flatten.uniq.join(' ').gsub(/\s{2,}/, ' ').strip
115
116
  end
116
117
 
@@ -139,19 +140,39 @@ module Browserino
139
140
 
140
141
  private
141
142
 
143
+ def name_for(sym)
144
+ mtd = %i[version label].include?(sym) ? :name : "#{sym}_name".to_sym
145
+ properties[mtd]
146
+ end
147
+
148
+ def label_for(sym)
149
+ mtd = %i[version name].include?(sym) ? :label : "#{sym}_label".to_sym
150
+ properties[mtd]
151
+ end
152
+
153
+ def version_for(sym)
154
+ mtd = %i[label name].include?(sym) ? :version : "#{sym}_version".to_sym
155
+ properties[mtd]
156
+ end
157
+
158
+ def get_answer(mtd, res, ver = nil, val = nil)
159
+ incl = [res, *Browserino.config.aliasses[res]].include? val
160
+ return res.is_a?(Version) ? res > 0 : res && true unless val
161
+ ver && incl ? version_for(mtd) == ver : incl
162
+ end
163
+
142
164
  def define_simple_methods!(props)
143
- props.reject { |val| val.respond_to? :call }.each do |name, value|
165
+ props.each do |name, value|
144
166
  define_singleton_method(name) { value }
145
- define_singleton_method("#{name}?") do |val = nil, **opts|
146
- values = [value, *Browserino.config.aliasses[value]]
147
- return values.include? val if val && !opts[:version]
148
- if val && opts[:version]
149
- ver_res = send(name == :name ? :version : "#{name}_version")
150
- return (ver_res == opts[:version]) && values.include?(val)
151
- end
152
- return value > 0 if value.is_a? Version
153
- value && true
154
- end
167
+ define_question_method! name, value
168
+ end
169
+ end
170
+
171
+ def define_question_method!(name, value)
172
+ define_singleton_method("#{name}?") do |val = nil, opts = {}|
173
+ ver = opts.delete :version
174
+ val = val.to_sym if ver
175
+ get_answer name, value, ver, val
155
176
  end
156
177
  end
157
178
 
@@ -163,10 +184,9 @@ module Browserino
163
184
  end
164
185
 
165
186
  def define_name_result_methods!
166
- [:name, :engine, :platform].each do |prop|
167
- result = send prop
168
- ver_res = version if prop == :name
169
- ver_res = send("#{prop}_version") if ver_res.nil?
187
+ %i[name engine platform].each do |prop|
188
+ result = properties[prop]
189
+ ver_res = version_for(prop)
170
190
 
171
191
  # for each of the props:
172
192
  # -- define a question method using the value of prop
@@ -193,11 +213,8 @@ module Browserino
193
213
 
194
214
  def define_label_methods!
195
215
  property_names.select { |name| name =~ /label/i }.each do |prop|
196
- next unless (result = send(prop))
197
-
198
- ver_type = prop.to_s.gsub /_?label/, ''
199
- ver_res = version if ver_type.empty?
200
- ver_res = send("#{ver_type}_version") unless prop == :label
216
+ next unless (result = properties[prop])
217
+ ver_res = version_for(prop.to_s.split('_').first)
201
218
 
202
219
  define_singleton_method("#{result}?") do |value = nil|
203
220
  return ver_res == value if value
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Browserino
3
4
  class Config < Options
4
5
  def define(&block)
5
6
  instance_eval(&block)
6
- return unless identities.any? && identities.all?
7
7
 
8
- identities.each do |identity|
9
- properties << identity.properties.keys
10
- types << identity.type
11
- names << identity.name
8
+ matchers.each do |matcher|
9
+ properties << matcher.properties.keys
10
+ types << matcher.type
11
+ names << matcher.name
12
12
  end
13
13
 
14
14
  properties.flatten!.uniq!
@@ -32,15 +32,19 @@ module Browserino
32
32
  end
33
33
 
34
34
  def match(rgxp = nil, **opts, &block)
35
- rgxp, opts = [nil, rgxp] if rgxp.is_a? Hash
35
+ if rgxp.is_a? Hash
36
+ opts = rgxp.dup
37
+ rgxp = nil
38
+ end
39
+
36
40
  opts = @tmp_defaults.merge opts if @tmp_defaults.is_a? Hash
37
41
 
38
42
  if rgxp && opts[:like]
39
- identities.unshift with_alias(rgxp, opts, &block)
43
+ matchers.unshift with_alias(rgxp, opts, &block)
40
44
  elsif rgxp
41
- identities << Identity.new(rgxp, opts, &block)
45
+ matchers << Matcher.new(rgxp, opts, &block).freeze
42
46
  else
43
- global_identities.unshift Identity.new(&block)
47
+ global_matchers.unshift Matcher.new(&block).freeze
44
48
  end
45
49
  end
46
50
 
@@ -54,37 +58,52 @@ module Browserino
54
58
  end
55
59
 
56
60
  def preset(props, &block)
57
- @tmp_defaults = props
61
+ @preset_store ||= []
62
+ @preset_store << props if @preset_store.empty?
63
+ @preset_store << @tmp_defaults.merge(props) if @tmp_defaults
64
+ @tmp_defaults = @preset_store.last
65
+
58
66
  instance_eval(&block)
59
- @tmp_defaults = nil
67
+
68
+ @preset_store.pop
69
+ @tmp_defaults = @preset_store.last
60
70
  end
61
71
 
62
- def like(tmp, &block)
63
- preset like: tmp.to_sym, &block
72
+ def like(tmp, opts = {}, &block)
73
+ preset opts.merge(like: tmp.to_sym), &block
64
74
  end
65
75
 
66
- def validators(&block)
67
- preset type: :validator, &block
76
+ def emails(opts = {}, &block)
77
+ preset opts.merge(type: :email), &block
68
78
  end
69
79
 
70
- def browsers(&block)
71
- preset type: :browser, &block
80
+ def validators(opts = {}, &block)
81
+ preset opts.merge(type: :validator), &block
72
82
  end
73
83
 
74
- def bots(&block)
75
- preset type: :bot, &block
84
+ def browsers(opts = {}, &block)
85
+ preset opts.merge(type: :browser), &block
76
86
  end
77
87
 
78
- def libraries(&block)
79
- preset type: :library, &block
88
+ def bots(opts = {}, &block)
89
+ preset opts.merge(type: :bot), &block
90
+ end
91
+
92
+ def libraries(opts = {}, &block)
93
+ preset opts.merge(type: :library), &block
80
94
  end
81
95
 
82
96
  def with_alias(pattern, **opts, &block)
83
- id = identities.select { |id| id == opts[:like] }.first
97
+ alt = matchers.select { |id| id == opts[:like] }.first
84
98
 
85
- raise "No alias found for: #{opts[:like] || 'nil'}" unless id
99
+ raise "No alias found for: #{opts[:like] || 'nil'}" unless alt
100
+
101
+ base = alt.properties
102
+ if (excl = opts.delete(:except))
103
+ base = base.reject { |k| excl.include? k }
104
+ end
86
105
 
87
- Identity.new pattern, id.properties.merge(opts), &block
106
+ Matcher.new(pattern, base.merge(opts), &block).freeze
88
107
  end
89
108
  end
90
109
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Browserino.config.define do
3
4
  # aliasses will be defined after a Client has been initialized
4
5
  # only the aliasses matching the Client will be defined
@@ -9,4 +10,5 @@ Browserino.config.define do
9
10
  alias_for :ie, :internet_explorer
10
11
  alias_for :facebook, :fb
11
12
  alias_for :duckduckgo, :ddg
13
+ alias_for :chromeos, :cros
12
14
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Browserino.config.define do
3
4
  # executes before parsing the user agent, 's' in this case is the actual
4
5
  # user agent string in full glory. Do manipulations as you wish, I'm
@@ -12,7 +13,7 @@ Browserino.config.define do
12
13
  ua = ua.gsub(%r{chrome|safari}i, '').gsub('OPR', 'opera') if ua =~ %r{OPR}
13
14
  ua = ua.gsub %r{9\.80}, '' if ua =~ %r{opera}i
14
15
  ua = ua.gsub %r{webkit/}i, '' if ua =~ %r{presto}i
15
- ua = ua.gsub %r{(?:ms)?ie}i, '' if ua =~ %r{rv:}i
16
+ ua = ua.gsub %r{(?:ms)?ie\b}i, '' if ua =~ %r{rv:}i
16
17
  ua = ua.gsub %r{android|linux}i, '' if ua =~ %r{tizen}i
17
18
  ua = ua.gsub %r{linux}i, '' if ua =~ %r{android|s(unos|olaris)|w(eb)?os}i
18
19
  ua = ua.gsub %r{x11}i, '' if ua =~ %r{bsd|s(unos|olaris)}i
@@ -20,10 +21,18 @@ Browserino.config.define do
20
21
  ua = ua.gsub %r{rv:}i, '' if ua =~ %r{servo}i
21
22
  ua = ua.gsub %r{mac\sos\sx}i, '' if ua =~ %r{ip(?:[ao]d|hone)}i
22
23
  ua = ua.gsub %r{msie}i, '' if ua =~ %r{huaweisymantecspider}i
24
+ ua = ua.gsub %r{risc\sos}i, 'risc' if ua =~ %r{risc\sos}i
25
+ ua = ua.gsub %r{msie}i, '' if ua =~ %r{surf|\w*bot}i
26
+ ua = ua.gsub %r{safari}i, 'chrome' if ua =~ %r{bluechrome}i
27
+ ua = ua.gsub %r{msie|windows}i, '' if ua =~ %r{dts\sagent}i
28
+ ua = ua.gsub %r{blade\sos}i, 'blade-os' if ua =~ %r{future\sstar}i
29
+ ua = ua.gsub %r{safari}i, '' if ua =~ %r{obigo}i
30
+ ua = ua.gsub %r{awesomium}i, '' if ua =~ %r{flashfire}i
31
+ ua = ua.gsub %r{version}i, '' if ua =~ %r{kindle/\d}i
23
32
  ua
24
33
  end
25
34
 
26
- # after an identity is found, it's values are filtered in two stages
35
+ # after a matcher is found, it's values are filtered in two stages
27
36
  # first, filters will parse all statically defined values (e.g.) no regexp
28
37
  # or block within matchers, after that, smart matcher patterns will be
29
38
  # conditionally added and parsed with the previously collected values and
@@ -31,34 +40,37 @@ Browserino.config.define do
31
40
 
32
41
  # this is a global filter, multiple can be defined and they will all run
33
42
  # before any named filters
34
- filter do |value|
35
- case value
36
- when TrueClass, FalseClass, NilClass, Proc then value
37
- when %r{\A[\d_\.]+\z}i then value.to_s.strip.tr('_', '.')
38
- else value.to_s.downcase.strip.gsub(%r{[\s-]+}i, '_').to_sym
43
+ filter do |val|
44
+ case val
45
+ when TrueClass, FalseClass, NilClass, Proc then val
46
+ when %r{\A[\d_\.]+\z}i then val.to_s.strip.tr('_', '.')
47
+ else val.to_s.downcase.strip.gsub(%r{[\s-]+}i, '_').to_sym
39
48
  end
40
49
  end
41
50
 
42
51
  # this is a named filter, it defines the same filter for 3 properties
43
52
  # multiple name filters for the same property can be created, they will be
44
53
  # executed in order of addition
45
- filter :version, :engine_version, :platform_version do |value|
46
- Browserino::Version.new value
54
+ filter :version, :engine_version, :platform_version do |val|
55
+ Browserino::Version.new val
47
56
  end
48
57
 
49
- filter :platform do |value|
50
- value = :ios if value =~ %r{ip(?:[ao]d|hone)}i
51
- value = :webos if value =~ %r{w(?:eb)?os}i
52
- value = :linux if value =~ %r{ubuntu|x11}i
53
- value = :solaris if value =~ %r{s(?:unos|olaris)}i
54
- value = :macintosh if value =~ %r{mac_os_x}i
55
- value
58
+ filter :platform do |val|
59
+ if %r{ip(?:[ao]d|hone)}i =~ val then :ios
60
+ elsif %r{w(?:eb)?os}i =~ val then :webos
61
+ elsif %r{ubuntu|x11}i =~ val then :linux
62
+ elsif %r{mac_os_x}i =~ val then :macintosh
63
+ elsif %r{s(?:unos|olaris)}i =~ val then :solaris
64
+ elsif %r{cros}i =~ val then :chromeos
65
+ elsif %r{kindle|kf\w+}i =~ val then :fire_os
66
+ else val
67
+ end
56
68
  end
57
69
 
58
- filter :architecture do |value|
59
- value = :x64 if value && value =~ %r{(?:x86_|amd|wow)?64|i686}i
60
- value = :x32 if value && value != :x64
61
- value
70
+ filter :architecture do |val|
71
+ val = :x64 if val && val != :arm && val =~ %r{(?:x86_|amd|wow)?64|i686}i
72
+ val = :x32 if val && !%i[arm x64].include?(val)
73
+ val
62
74
  end
63
75
 
64
76
  filter :mobile do |value|
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Browserino.config.define do
3
4
  # labels will be defined before a client has been initialized
4
5
  # they will not be filtered before being injected into the Client
@@ -7,7 +8,9 @@ Browserino.config.define do
7
8
  # will create #label, #engine_label and #platform_label properties
8
9
  # respectively. These enjoy all the features that regular defined properties
9
10
  # in for instance methods enjoy, such as automatic question methods like
10
- # client.platform_label? :mavericks
11
+ # client.platform_label? :mavericks and they can also be used in
12
+ # the method this alias is for, e.g. client.platform? :mavericks or
13
+ # client.is? :mavericks
11
14
  label :android, for: :android, range: '1'..'1.4.9'
12
15
  label :cupcake, for: :android, range: '1.5'..'1.9.9'
13
16
  label :eclair, for: :android, range: '2'..'2.1'
@@ -35,11 +38,14 @@ Browserino.config.define do
35
38
  label :el_capitan, for: :macintosh, range: '10.11'..'10.11.9'
36
39
  label :sierra, for: :macintosh, range: '10.12'..'10.12.9'
37
40
 
38
- label :windows_dos, for: :windows, range: '3.1'..'4.0'
39
- label :windows_2000, for: :windows, range: '5.0'..'5.0.9'
40
- label :windows_xp, for: :windows, range: '5.1'..'5.2.9'
41
- label :windows_vista, for: :windows, range: '6.0'..'6.0.9'
42
- label :windows_7, for: :windows, range: '6.1'..'6.1.9'
43
- label :windows_8, for: :windows, range: '6.2'..'6.3'
44
- label :windows_10, for: :windows, range: '10.0'..'10.0.9'
41
+ label :dos, for: :windows, range: '3.1'..'4.0'
42
+ label :windows98, for: :windows, range: '98'..'98.9.9'
43
+ label :windows2000, for: :windows, range: '5.0'..'5.0.9'
44
+ label :xp, for: :windows, range: '5.1'..'5.2.9'
45
+ label :vista, for: :windows, range: '6.0'..'6.0.9'
46
+ label :windows7, for: :windows, range: '6.1'..'6.1.9'
47
+ label :windows8, for: :windows, range: '6.2'..'6.3'
48
+ label :windows10, for: :windows, range: '10.0'..'10.9.9'
49
+
50
+ label :outlook2016, for: :outlook, range: '16.0'..'16.9.9'
45
51
  end