browserino 4.0.0 → 4.1.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 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