brauser 3.2.6 → 3.3.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 +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +29 -0
- data/.travis-gemfile +1 -1
- data/.travis.yml +2 -1
- data/Gemfile +3 -3
- data/README.md +6 -6
- data/brauser.gemspec +1 -1
- data/doc/Brauser.html +7 -7
- data/doc/Brauser/Browseable.html +127 -0
- data/doc/Brauser/{BrowserMethods → Browseable}/Attributes.html +34 -30
- data/doc/Brauser/Browseable/DefaultDefinitions.html +387 -0
- data/doc/Brauser/{BrowserMethods → Browseable}/General.html +9 -9
- data/doc/Brauser/{BrowserMethods → Browseable}/General/ClassMethods.html +33 -33
- data/doc/Brauser/{BrowserMethods → Browseable}/Parsing.html +23 -23
- data/doc/Brauser/{BrowserMethods → Browseable}/PartialQuerying.html +59 -53
- data/doc/Brauser/{BrowserMethods → Browseable}/Querying.html +43 -37
- data/doc/Brauser/{BrowserMethods → Browseable}/Register.html +9 -9
- data/doc/Brauser/Browseable/Register/ClassMethods.html +516 -0
- data/doc/Brauser/Browser.html +787 -1362
- data/doc/Brauser/Definition.html +230 -40
- data/doc/Brauser/Hooks.html +4 -4
- data/doc/Brauser/Hooks/RubyOnRails.html +4 -4
- data/doc/Brauser/Query.html +53 -53
- data/doc/Brauser/{BrowserMethods.html → Queryable.html} +13 -11
- data/doc/Brauser/{Chainers.html → Queryable/Chainers.html} +51 -45
- data/doc/Brauser/{Queries.html → Queryable/Queries.html} +47 -41
- data/doc/Brauser/Version.html +6 -6
- data/doc/_index.html +41 -27
- data/doc/class_list.html +1 -1
- data/doc/css/style.css +1 -0
- data/doc/file.README.html +10 -10
- data/doc/frames.html +1 -1
- data/doc/index.html +10 -10
- data/doc/method_list.html +68 -74
- data/doc/top-level-namespace.html +4 -4
- data/lib/brauser.rb +14 -3
- data/lib/brauser/browseable/attributes.rb +95 -0
- data/lib/brauser/browseable/general.rb +104 -0
- data/lib/brauser/browseable/parsing.rb +127 -0
- data/lib/brauser/browseable/partial_querying.rb +116 -0
- data/lib/brauser/browseable/querying.rb +63 -0
- data/lib/brauser/browseable/register.rb +73 -0
- data/lib/brauser/browser.rb +34 -741
- data/lib/brauser/definition.rb +30 -5
- data/lib/brauser/definitions/browsers.rb +66 -0
- data/lib/brauser/definitions/languages.rb +130 -0
- data/lib/brauser/definitions/platforms.rb +30 -0
- data/lib/brauser/query.rb +4 -99
- data/lib/brauser/queryable/chainers.rb +56 -0
- data/lib/brauser/queryable/queries.rb +60 -0
- data/lib/brauser/version.rb +3 -2
- data/spec/brauser/browser_spec.rb +26 -29
- data/spec/brauser/query_spec.rb +15 -13
- metadata +30 -17
- data/.bundle/install.log +0 -106
- data/doc/Brauser/BrowserMethods/Register/ClassMethods.html +0 -770
@@ -0,0 +1,63 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the brauser gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Brauser
|
8
|
+
# The interface of brauser browsers.
|
9
|
+
module Browseable
|
10
|
+
# Methods to end querying.
|
11
|
+
module Querying
|
12
|
+
# Checks if the browser is a specific name and optionally of a specific version and platform.
|
13
|
+
#
|
14
|
+
# @see #v?
|
15
|
+
# @see #on?
|
16
|
+
#
|
17
|
+
# @param names [Symbol|Array] A list of specific names to match. Also, this meta-names are supported: `:capable` and `:tablet`.
|
18
|
+
# @param versions [Hash] An hash with specific version to match against. Need to be in form `{:operator => version}`, where operator
|
19
|
+
# is one of `:lt, :lte, :eq, :gt, :gte`.
|
20
|
+
# @param platforms [Symbol|Array] A list of specific platform to match. Valid values are all those possible for the platform attribute.
|
21
|
+
# @return [Boolean] `true` if current browser matches, `false` otherwise.
|
22
|
+
def is?(names = [], versions = {}, platforms = [])
|
23
|
+
is(names, versions, platforms).result
|
24
|
+
end
|
25
|
+
|
26
|
+
# Checks if the browser is a specific version.
|
27
|
+
#
|
28
|
+
# @param versions [String|Hash] A string in the form `operator version && ...` (example: `>= 7 && < 4`) or an hash with specific version to match against,
|
29
|
+
# in form `{:operator => version}`, where operator is one of `:lt, :lte, :eq, :gt, :gte`.
|
30
|
+
# @return [Boolean] `true` if current browser matches, `false` otherwise.
|
31
|
+
def version?(versions = {})
|
32
|
+
version(versions).result
|
33
|
+
end
|
34
|
+
alias_method :v?, :version?
|
35
|
+
|
36
|
+
# Check if the browser is on a specific platform.
|
37
|
+
#
|
38
|
+
# @param platforms [Symbol|Array] A list of specific platform to match.
|
39
|
+
# @return [Boolean] `true` if current browser matches, `false` otherwise.
|
40
|
+
def on?(platforms = [])
|
41
|
+
on(platforms).result
|
42
|
+
end
|
43
|
+
|
44
|
+
# Check if the browser accepts the specified languages.
|
45
|
+
#
|
46
|
+
# @param langs [String|Array] A list of languages to match against.
|
47
|
+
# @return [Boolean] `true` if current browser matches, `false` otherwise.
|
48
|
+
def accepts?(langs = [])
|
49
|
+
accepts(langs).result
|
50
|
+
end
|
51
|
+
|
52
|
+
# Check if the browser is supported.
|
53
|
+
#
|
54
|
+
# @param supported [Hash|String] A map of engines and minimum supported major version, or a path to YAML file containing the map.
|
55
|
+
# @return [Boolean] `true` if current browser is supported, `false` otherwise.
|
56
|
+
def supported?(supported)
|
57
|
+
supported = YAML.load_file(supported).symbolize_keys if supported.is_a?(String)
|
58
|
+
minimum = supported[name]
|
59
|
+
(minimum && v?(gte: minimum)).to_boolean
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the brauser gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Brauser
|
8
|
+
# The interface of brauser browsers.
|
9
|
+
module Browseable
|
10
|
+
# Methods for register recognized browsers, versions and platforms.
|
11
|
+
module Register
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
# Class methods.
|
15
|
+
module ClassMethods
|
16
|
+
# Adds a definitions for recognition.
|
17
|
+
#
|
18
|
+
# @param type [Symbol] The type of the definition. Can be `:browsers`, `:platforms` or `:languages`.
|
19
|
+
# @param definition [Definition|Array] The definition to add. Can be also an array of definitions.
|
20
|
+
# @return [Boolean] `true` if at least one definition has been added, `false` otherwise.
|
21
|
+
def add(type, definition)
|
22
|
+
rv = false
|
23
|
+
|
24
|
+
if [:browsers, :platforms, :languages].include?(type)
|
25
|
+
prepare_definitions_for(type)
|
26
|
+
|
27
|
+
definition.ensure_array.each do |d|
|
28
|
+
next unless d.is_a?(::Brauser::Definition)
|
29
|
+
@definitions[type][d.tag] = d
|
30
|
+
rv = true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
rv
|
35
|
+
end
|
36
|
+
|
37
|
+
# Adds definitions for a default list of browsers that can be recognized.
|
38
|
+
#
|
39
|
+
# @return [Boolean] `true` if at least one browser has been added, `false` otherwise.
|
40
|
+
def add_default_browsers
|
41
|
+
add(:browsers, (
|
42
|
+
::Brauser::Browseable::DefaultDefinitions::MOBILE_BROWSERS + ::Brauser::Browseable::DefaultDefinitions::MAJOR_DESKTOP_BROWSERS +
|
43
|
+
::Brauser::Browseable::DefaultDefinitions::MSIE_BROWSERS + ::Brauser::Browseable::DefaultDefinitions::MINOR_DESKTOP_BROWSERS
|
44
|
+
).map { |browser| ::Brauser::Definition.send(:new, *browser) })
|
45
|
+
end
|
46
|
+
|
47
|
+
# Adds a default list of platforms that can be recognized.
|
48
|
+
#
|
49
|
+
# @return [Boolean] `true` if at least one platform has been added, `false` otherwise.
|
50
|
+
def add_default_platforms
|
51
|
+
add(:platforms, ::Brauser::Browseable::DefaultDefinitions::PLATFORMS.map { |platform| ::Brauser::Definition.send(:new, *platform) })
|
52
|
+
end
|
53
|
+
|
54
|
+
# Adds a default list of languages that can be recognized.
|
55
|
+
#
|
56
|
+
# @return [Boolean] `true` if at least one language has been added, `false` otherwise.
|
57
|
+
def add_default_languages
|
58
|
+
add(:languages, ::Brauser::Browseable::DefaultDefinitions::LANGUAGES.map { |code, name| ::Brauser::Definition.new(code, name, code) })
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
# Prepares definition for a specific type.
|
64
|
+
#
|
65
|
+
# @param type [Symbol] The type to prepare.
|
66
|
+
def prepare_definitions_for(type)
|
67
|
+
@definitions ||= {}
|
68
|
+
@definitions[type] ||= {}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/brauser/browser.rb
CHANGED
@@ -6,670 +6,6 @@
|
|
6
6
|
|
7
7
|
# A framework agnostic browser detection and querying helper.
|
8
8
|
module Brauser
|
9
|
-
# Methods of the {Browser Browser} class.
|
10
|
-
module BrowserMethods
|
11
|
-
# Methods for register recognized browsers, versions and platforms.
|
12
|
-
module Register
|
13
|
-
extend ActiveSupport::Concern
|
14
|
-
|
15
|
-
# Class methods.
|
16
|
-
module ClassMethods
|
17
|
-
# Adds a definitions for recognition.
|
18
|
-
#
|
19
|
-
# @param type [Symbol] The type of the definition. Can be `:browsers`, `:platforms` or `:languages`.
|
20
|
-
# @param definition [Definition|Array] The definition to add. Can be also an array of definitions.
|
21
|
-
# @return [Boolean] `true` if at least one definition has been added, `false` otherwise.
|
22
|
-
def add(type, definition)
|
23
|
-
rv = false
|
24
|
-
|
25
|
-
if [:browsers, :platforms, :languages].include?(type) then
|
26
|
-
@definitions ||= {}
|
27
|
-
@definitions[type] ||= {}
|
28
|
-
|
29
|
-
definition.ensure_array.each do |d|
|
30
|
-
if d.is_a?(::Brauser::Definition) then
|
31
|
-
@definitions[type][d.tag] = d
|
32
|
-
rv = true
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
rv
|
38
|
-
end
|
39
|
-
|
40
|
-
# Adds definitions for a default list of browsers that can be recognized.
|
41
|
-
#
|
42
|
-
# @return [Boolean] `true` if at least one browser has been added, `false` otherwise.
|
43
|
-
def add_default_browsers
|
44
|
-
add_mobile_browsers && add_major_desktop_browsers && add_msie_browsers && add_minor_desktop_browsers
|
45
|
-
end
|
46
|
-
|
47
|
-
# Adds a default list of platforms that can be recognized.
|
48
|
-
#
|
49
|
-
# @return [Boolean] `true` if at least one platform has been added, `false` otherwise.
|
50
|
-
def add_default_platforms
|
51
|
-
add(:platforms, [
|
52
|
-
[:symbian, "Symbian", /s60|symb/i],
|
53
|
-
[:windows_phone, "Microsoft Windows Phone", /windows phone/i],
|
54
|
-
[:kindle, "Nokia Symbian", /kindle|silk/i, ],
|
55
|
-
[:ios, "Apple iOS", Proc.new { |_, agent| [:iphone, :ipad, :ipod, :chrome_ios].include?(name) || agent =~ /ipad|iphone|ipod|crios/i }],
|
56
|
-
[:android, "Android", /android/i],
|
57
|
-
[:blackberry, "RIM BlackBerry", /blackberry/i],
|
58
|
-
[:psp, "Sony Playstation Portable", /psp/i],
|
59
|
-
[:ps3, "Sony Playstation 3", /playstation 3/i],
|
60
|
-
[:wii, "Nintendo Wii", /wii/i],
|
61
|
-
|
62
|
-
[:linux, "Linux", /linux/i],
|
63
|
-
[:osx, "Apple MacOS X", /mac|macintosh|mac os x/i],
|
64
|
-
[:windows, "Microsoft Windows", /windows/i]
|
65
|
-
].map { |platform| ::Brauser::Definition.send(:new, *platform) })
|
66
|
-
end
|
67
|
-
|
68
|
-
# Adds a default list of languages that can be recognized.
|
69
|
-
#
|
70
|
-
# @return [Boolean] `true` if at least one language has been added, `false` otherwise.
|
71
|
-
def add_default_languages
|
72
|
-
add(:languages, {
|
73
|
-
"af" => "Afrikaans",
|
74
|
-
"sq" => "Albanian",
|
75
|
-
"eu" => "Basque",
|
76
|
-
"bg" => "Bulgarian",
|
77
|
-
"be" => "Byelorussian",
|
78
|
-
"ca" => "Catalan",
|
79
|
-
"zh" => "Chinese",
|
80
|
-
"zh-cn" => "Chinese/China",
|
81
|
-
"zh-tw" => "Chinese/Taiwan",
|
82
|
-
"zh-hk" => "Chinese/Hong Kong",
|
83
|
-
"zh-sg" => "Chinese/singapore",
|
84
|
-
"hr" => "Croatian",
|
85
|
-
"cs" => "Czech",
|
86
|
-
"da" => "Danish",
|
87
|
-
"nl" => "Dutch",
|
88
|
-
"nl-nl" => "Dutch/Netherlands",
|
89
|
-
"nl-be" => "Dutch/Belgium",
|
90
|
-
"en" => "English",
|
91
|
-
"en-gb" => "English/United Kingdom",
|
92
|
-
"en-us" => "English/United States",
|
93
|
-
"en-au" => "English/Australian",
|
94
|
-
"en-ca" => "English/Canada",
|
95
|
-
"en-nz" => "English/New Zealand",
|
96
|
-
"en-ie" => "English/Ireland",
|
97
|
-
"en-za" => "English/South Africa",
|
98
|
-
"en-jm" => "English/Jamaica",
|
99
|
-
"en-bz" => "English/Belize",
|
100
|
-
"en-tt" => "English/Trinidad",
|
101
|
-
"et" => "Estonian",
|
102
|
-
"fo" => "Faeroese",
|
103
|
-
"fa" => "Farsi",
|
104
|
-
"fi" => "Finnish",
|
105
|
-
"fr" => "French",
|
106
|
-
"fr-be" => "French/Belgium",
|
107
|
-
"fr-fr" => "French/France",
|
108
|
-
"fr-ch" => "French/Switzerland",
|
109
|
-
"fr-ca" => "French/Canada",
|
110
|
-
"fr-lu" => "French/Luxembourg",
|
111
|
-
"gd" => "Gaelic",
|
112
|
-
"gl" => "Galician",
|
113
|
-
"de" => "German",
|
114
|
-
"de-at" => "German/Austria",
|
115
|
-
"de-de" => "German/Germany",
|
116
|
-
"de-ch" => "German/Switzerland",
|
117
|
-
"de-lu" => "German/Luxembourg",
|
118
|
-
"de-li" => "German/Liechtenstein",
|
119
|
-
"el" => "Greek",
|
120
|
-
"he" => "Hebrew",
|
121
|
-
"he-il" => "Hebrew/Israel",
|
122
|
-
"hi" => "Hindi",
|
123
|
-
"hu" => "Hungarian",
|
124
|
-
"ie-ee" => "Internet Explorer/Easter Egg",
|
125
|
-
"is" => "Icelandic",
|
126
|
-
"id" => "Indonesian",
|
127
|
-
"in" => "Indonesian",
|
128
|
-
"ga" => "Irish",
|
129
|
-
"it" => "Italian",
|
130
|
-
"it-ch" => "Italian/ Switzerland",
|
131
|
-
"ja" => "Japanese",
|
132
|
-
"km" => "Khmer",
|
133
|
-
"km-kh" => "Khmer/Cambodia",
|
134
|
-
"ko" => "Korean",
|
135
|
-
"lv" => "Latvian",
|
136
|
-
"lt" => "Lithuanian",
|
137
|
-
"mk" => "Macedonian",
|
138
|
-
"ms" => "Malaysian",
|
139
|
-
"mt" => "Maltese",
|
140
|
-
"no" => "Norwegian",
|
141
|
-
"pl" => "Polish",
|
142
|
-
"pt" => "Portuguese",
|
143
|
-
"pt-br" => "Portuguese/Brazil",
|
144
|
-
"rm" => "Rhaeto-Romanic",
|
145
|
-
"ro" => "Romanian",
|
146
|
-
"ro-mo" => "Romanian/Moldavia",
|
147
|
-
"ru" => "Russian",
|
148
|
-
"ru-mo" => "Russian /Moldavia",
|
149
|
-
"sr" => "Serbian",
|
150
|
-
"sk" => "Slovack",
|
151
|
-
"sl" => "Slovenian",
|
152
|
-
"sb" => "Sorbian",
|
153
|
-
"es" => "Spanish",
|
154
|
-
"es-do" => "Spanish",
|
155
|
-
"es-ar" => "Spanish/Argentina",
|
156
|
-
"es-co" => "Spanish/Colombia",
|
157
|
-
"es-mx" => "Spanish/Mexico",
|
158
|
-
"es-es" => "Spanish/Spain",
|
159
|
-
"es-gt" => "Spanish/Guatemala",
|
160
|
-
"es-cr" => "Spanish/Costa Rica",
|
161
|
-
"es-pa" => "Spanish/Panama",
|
162
|
-
"es-ve" => "Spanish/Venezuela",
|
163
|
-
"es-pe" => "Spanish/Peru",
|
164
|
-
"es-ec" => "Spanish/Ecuador",
|
165
|
-
"es-cl" => "Spanish/Chile",
|
166
|
-
"es-uy" => "Spanish/Uruguay",
|
167
|
-
"es-py" => "Spanish/Paraguay",
|
168
|
-
"es-bo" => "Spanish/Bolivia",
|
169
|
-
"es-sv" => "Spanish/El salvador",
|
170
|
-
"es-hn" => "Spanish/Honduras",
|
171
|
-
"es-ni" => "Spanish/Nicaragua",
|
172
|
-
"es-pr" => "Spanish/Puerto Rico",
|
173
|
-
"sx" => "Sutu",
|
174
|
-
"sv" => "Swedish",
|
175
|
-
"sv-se" => "Swedish/Sweden",
|
176
|
-
"sv-fi" => "Swedish/Finland",
|
177
|
-
"ts" => "Thai",
|
178
|
-
"tn" => "Tswana",
|
179
|
-
"tr" => "Turkish",
|
180
|
-
"uk" => "Ukrainian",
|
181
|
-
"ur" => "Urdu",
|
182
|
-
"vi" => "Vietnamese",
|
183
|
-
"xh" => "Xshosa",
|
184
|
-
"ji" => "Yiddish",
|
185
|
-
"zu" => "Zulu"
|
186
|
-
}.map { |code, name| ::Brauser::Definition.new(code, name, code) })
|
187
|
-
end
|
188
|
-
|
189
|
-
private
|
190
|
-
# Registers the most common desktop browsers.
|
191
|
-
#
|
192
|
-
# @return [Boolean] `true` if at least one browser has been added, `false` otherwise.
|
193
|
-
def add_major_desktop_browsers
|
194
|
-
add(:browsers, [
|
195
|
-
[:chrome, "Google Chrome", /((chrome)|(chromium))/i, /(.+Chrom[a-z]+\/)([a-z0-9.]+)/i],
|
196
|
-
[:netscape, "Netscape Navigator", /(netscape|navigator)\//i, /((Netscape|Navigator)\/)([a-z0-9.]+)/i],
|
197
|
-
[:firefox, "Mozilla Firefox", /firefox/i, /(.+Firefox\/)([a-z0-9.]+)/i],
|
198
|
-
[:safari, "Apple Safari", Proc.new{ |_, agent| disambiguate_browser(agent, /safari/i, /((chrome)|(chromium)|(crios))/i) }, /(.+Version\/)([a-z0-9.]+)/i],
|
199
|
-
].map { |browser| ::Brauser::Definition.send(:new, *browser) })
|
200
|
-
end
|
201
|
-
|
202
|
-
# Registers definitions for MSIE browsers.
|
203
|
-
#
|
204
|
-
# @return [Boolean] `true` if at least one browser has been added, `false` otherwise.
|
205
|
-
def add_msie_browsers
|
206
|
-
add(:browsers, [
|
207
|
-
[:msie_compatibility, "Microsoft Internet Explorer (Compatibility View)", /(msie 7\.0).+(trident)/i, Proc.new { |_, agent|
|
208
|
-
version = /(.+trident\/)(?<version>[a-z0-9.]+)/i.match(agent)["version"].split(".")
|
209
|
-
version[0] = version[0].to_integer + 4
|
210
|
-
version.join(".")
|
211
|
-
}],
|
212
|
-
[:msie, "Microsoft Internet Explorer", Proc.new{ |_, agent| disambiguate_browser(agent, /msie/i, /opera/i) }, /(.+MSIE )([a-z0-9.]+)/i],
|
213
|
-
].map { |browser| ::Brauser::Definition.send(:new, *browser) })
|
214
|
-
end
|
215
|
-
|
216
|
-
# Registers the least common desktop browsers.
|
217
|
-
#
|
218
|
-
# @return [Boolean] `true` if at least one browser has been added, `false` otherwise.
|
219
|
-
def add_minor_desktop_browsers
|
220
|
-
add(:browsers, [
|
221
|
-
[:quicktime, "Apple QuickTime", /quicktime/i, /(.+((QuickTime\/)|(qtver=)))([a-z0-9.]+)/i],
|
222
|
-
[:webkit, "WebKit Browser", /webkit/i, /(.+WebKit\/)([a-z0-9.]+)/i],
|
223
|
-
[:gecko, "Gecko Browser", /gecko/i, /(.+rv:|Gecko\/)([a-z0-9.]+)/i],
|
224
|
-
].map { |browser| ::Brauser::Definition.send(:new, *browser) })
|
225
|
-
end
|
226
|
-
|
227
|
-
# Register the most common mobile and console browsers.
|
228
|
-
#
|
229
|
-
# @return [Boolean] `true` if at least one browser has been added, `false` otherwise.
|
230
|
-
def add_mobile_browsers
|
231
|
-
add(:browsers, [
|
232
|
-
[:coremedia, "Apple CoreMedia", /coremedia/i, /.+CoreMedia v([a-z0-9.]+)/i],
|
233
|
-
|
234
|
-
[:opera_mobile, "Opera Mobile", /opera mobi/i, /.+Opera Mobi.+((.+Opera )|(Version\/))([a-z0-9.]+)/i],
|
235
|
-
[:opera, "Opera", /opera/i, Proc.new{ |_, a|
|
236
|
-
version = ((a !~ /wii/i) ? /((.+Opera )|(Version\/))(?<version>[a-z0-9.]+)/i : /(.+Nintendo Wii; U; ; )(?<version>[a-z0-9.]+)/i).match(a)
|
237
|
-
version ? version["version"] : nil
|
238
|
-
}],
|
239
|
-
|
240
|
-
[:android, "Android", /android/i, /(.+Android )([a-z0-9.]+)/i],
|
241
|
-
[:blackberry, "RIM BlackBerry", /blackberry/i, /(.+Version\/)([a-z0-9.]+)/i],
|
242
|
-
[:kindle, "Amazon Kindle", /(kindle)/i, /(.+(Kindle|Silk)\/)([a-z0-9.]+)/i],
|
243
|
-
[:psp, "Sony Playstation Portable", /psp/i, /(.+PlayStation Portable\); )([a-z0-9.]+)/i],
|
244
|
-
[:ps3, "Sony Playstation 3", /playstation 3/i, /(.+PLAYSTATION 3; )([a-z0-9.]+)/i],
|
245
|
-
[:windows_phone, "Microsoft Windows Phone", /windows phone/i, /(.+IEMobile\/)([a-z0-9.]+)/i],
|
246
|
-
[:wii, "Nintendo Wii", /nintendo wii/, /(.+Nintendo Wii; U; ; )([a-z0-9.]+)/i],
|
247
|
-
|
248
|
-
[:chrome_ios, "Chrome iOS", /crios/i, /(.+CriOS\/)([a-z0-9.]+)/i],
|
249
|
-
[:ipod, "Apple iPod", /ipod/i, /(.+Version\/)([a-z0-9.]+)/i],
|
250
|
-
[:iphone, "Apple iPhone", /iphone/i, /(.+Version\/)([a-z0-9.]+)/i],
|
251
|
-
[:ipad, "Apple iPad", /ipad/i, /(.+Version\/)([a-z0-9.]+)/i],
|
252
|
-
|
253
|
-
[:mobile, "Other Mobile Browser", /(mobile|symbian|midp|windows ce)/i, /.+\/([a-z0-9.]+)/i],
|
254
|
-
].map { |browser| ::Brauser::Definition.send(:new, *browser) })
|
255
|
-
end
|
256
|
-
|
257
|
-
# Recognizes a browser disambiguating against another.
|
258
|
-
#
|
259
|
-
# @param agent [String] The agent to match.
|
260
|
-
# @param positive_matcher [Regexp] The expression to match.
|
261
|
-
# @param negative_matcher [Regexp] The expression NOT to match.
|
262
|
-
# @return [Boolean] `true` if matching succeeded, `false otherwise`.
|
263
|
-
def disambiguate_browser(agent, positive_matcher, negative_matcher)
|
264
|
-
agent =~ positive_matcher && agent !~ negative_matcher
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
# General methods.
|
270
|
-
module General
|
271
|
-
extend ActiveSupport::Concern
|
272
|
-
|
273
|
-
# Class methods.
|
274
|
-
module ClassMethods
|
275
|
-
# Returns the list of browser that can be recognized.
|
276
|
-
#
|
277
|
-
# The keys are the browser name, the values are arrays of the name matcher, the version match and the label.
|
278
|
-
#
|
279
|
-
# @return [Hash] The list of browser that can be recognized.
|
280
|
-
def browsers
|
281
|
-
@definitions[:browsers]
|
282
|
-
end
|
283
|
-
|
284
|
-
# Returns the list of platforms that can be recognized.
|
285
|
-
#
|
286
|
-
# The keys are the platform name, values are arrays of the matcher and the label.
|
287
|
-
#
|
288
|
-
# @return [Hash] The list of platform that can be recognized.
|
289
|
-
def platforms
|
290
|
-
@definitions[:platforms]
|
291
|
-
end
|
292
|
-
|
293
|
-
# Returns the list of languages that can be recognized.
|
294
|
-
#
|
295
|
-
# The keys are the languages code, the values the labels.
|
296
|
-
#
|
297
|
-
# @return [Hash] The list of languages that can be recognized.
|
298
|
-
def languages
|
299
|
-
@definitions[:languages]
|
300
|
-
end
|
301
|
-
|
302
|
-
# Compares two versions.
|
303
|
-
#
|
304
|
-
# @param v1 [String] The first versions to compare.
|
305
|
-
# @param operator [Symbol] The operator to use for comparison, can be one of `[:lt, :lte, :eq, :gte, :gt]`.
|
306
|
-
# @param v2 [Symbol] The second version to compare.
|
307
|
-
# @return [Boolean] true if comparison is valid, `false` otherwise.
|
308
|
-
def compare_versions(v1 = "", operator = :eq, v2 = "")
|
309
|
-
valid_results = {lt: [-1], lte: [-1, 0], eq: [0], gte: [0, 1], gt: [1]}.fetch(operator, [])
|
310
|
-
|
311
|
-
if valid_results.present? && v1.ensure_string.present? then
|
312
|
-
p1, p2 = find_relevant_tokens(v1, v2)
|
313
|
-
p1, p2 = normalize_tokens(p1, p2)
|
314
|
-
valid_results.include?(p1 <=> p2)
|
315
|
-
else
|
316
|
-
false
|
317
|
-
end
|
318
|
-
end
|
319
|
-
|
320
|
-
private
|
321
|
-
# Find relevant tokens (that is, the first two which are not equals) in a string for comparison.
|
322
|
-
#
|
323
|
-
# @param v1 [String] The first versions to compare.
|
324
|
-
# @param v2 [String] The second version to compare.
|
325
|
-
# @return [Array] The tokens to compare.
|
326
|
-
def find_relevant_tokens(v1, v2)
|
327
|
-
v1 = v1.ensure_string.strip.split(".")
|
328
|
-
v2 = v2.ensure_string.strip.split(".")
|
329
|
-
|
330
|
-
p1 = nil
|
331
|
-
p2 = nil
|
332
|
-
[v1.length, v2.length].max.times do |i|
|
333
|
-
p1 = v1[i]
|
334
|
-
p2 = v2[i]
|
335
|
-
break if !p1 && !p2 || p1 != p2
|
336
|
-
end
|
337
|
-
|
338
|
-
[p1 || "0", p2 || "0"]
|
339
|
-
end
|
340
|
-
|
341
|
-
# Normalizes token for comparison.
|
342
|
-
#
|
343
|
-
# @param p1 [String] The first token to normalize.
|
344
|
-
# @param p2 [String] The second token to normalize.
|
345
|
-
# @return [Array] The tokens to compare.
|
346
|
-
def normalize_tokens(p1, p2)
|
347
|
-
if !p1.is_integer? then
|
348
|
-
ll = p1.length
|
349
|
-
p1 = p2 + p1
|
350
|
-
p2 = p2 + ("z" * ll)
|
351
|
-
else
|
352
|
-
ll = [p1.length, p2.length].max
|
353
|
-
p1 = p1.rjust(ll, "0")
|
354
|
-
p2 = p2.rjust(ll, "0")
|
355
|
-
end
|
356
|
-
|
357
|
-
[p1, p2]
|
358
|
-
end
|
359
|
-
end
|
360
|
-
end
|
361
|
-
|
362
|
-
# Methods to handle attributes
|
363
|
-
module Attributes
|
364
|
-
# Gets a human-readable browser name.
|
365
|
-
#
|
366
|
-
# @return [String] A human-readable browser name.
|
367
|
-
def readable_name
|
368
|
-
parse_agent(@agent) if !@name
|
369
|
-
::Brauser::Browser.browsers.fetch(@name).label rescue "Unknown Browser"
|
370
|
-
end
|
371
|
-
|
372
|
-
# Gets a human-readable platform name.
|
373
|
-
#
|
374
|
-
# @return [String] A readable platform name.
|
375
|
-
def platform_name
|
376
|
-
parse_agent(@agent) if !@platform
|
377
|
-
::Brauser::Browser.platforms[@platform].try(:label) || "Unknown Platform"
|
378
|
-
end
|
379
|
-
|
380
|
-
# Returns an array of information about the browser. Information are strings which are suitable to use as CSS classes.
|
381
|
-
#
|
382
|
-
# For version, it will be included a class for every token of the version. For example, version `7.0.1.2` will return this:
|
383
|
-
#
|
384
|
-
# ```ruby
|
385
|
-
# ["version-7", "version-7_0", "version-7_0_1", "version-7_0_1_2"]
|
386
|
-
# ```
|
387
|
-
#
|
388
|
-
# If you provide a block (with accepts name, version and platform as arguments), it will be used for translating the name.
|
389
|
-
#
|
390
|
-
# @param join [String|NilClass] If non falsy, the separator to use to join information. If falsy, informations will be returned as array.
|
391
|
-
# @param name [Boolean] If non falsy, the string to prepend to the name. If falsy, the name information will not be included.
|
392
|
-
# @param version [String|NilClass] If non falsy, the string to prepend to the version. If falsy, the version information will not be included.
|
393
|
-
# @param platform [String|NilClass] If non falsy, the string to prepend to the platform. If falsy, the platform information will not be included.
|
394
|
-
# @param block [Proc] A block to translate browser name.
|
395
|
-
# @return [String|Array] CSS ready information of the current browser.
|
396
|
-
def classes(join = " ", name = "", version = "version-", platform = "platform-", &block)
|
397
|
-
platform = "platform-" if platform.is_a?(TrueClass)
|
398
|
-
rv = [stringify_name(name, &block), stringify_version(version), !platform ? nil : (platform + @platform.to_s)].compact.flatten
|
399
|
-
join ? rv.join(join) : rv
|
400
|
-
end
|
401
|
-
alias :meta :classes
|
402
|
-
|
403
|
-
private
|
404
|
-
# Stringifies a browser name(s).
|
405
|
-
#
|
406
|
-
# @param name [Boolean] If non falsy, the string to prepend to the name. If falsy, the name information will not be included.
|
407
|
-
# @param block [Proc] A block to translate browser name.
|
408
|
-
# @return [String|Array|nil] The browser name(s) or `nil`, if it was set to be skipped.
|
409
|
-
def stringify_name(name, &block)
|
410
|
-
if name then
|
411
|
-
name, block = prepare_name_stringification(name, block)
|
412
|
-
names = block.call(@name, @version, @platform).ensure_array {|n| "#{name}#{n}" }
|
413
|
-
names.length > 1 ? names : names.first
|
414
|
-
else
|
415
|
-
nil
|
416
|
-
end
|
417
|
-
end
|
418
|
-
|
419
|
-
# Prepare a name stringification
|
420
|
-
#
|
421
|
-
# @param name [Boolean] If non falsy, the string to prepend to the name. If falsy, the name information will not be included.
|
422
|
-
# @param block [Proc] A block to translate browser name.
|
423
|
-
# @return [Array] A name and a translator ready to use.
|
424
|
-
def prepare_name_stringification(name, block)
|
425
|
-
self.parse_agent(@agent) if !@name
|
426
|
-
[(name.is_a?(TrueClass) ? "" : name), block || Proc.new {|n, *| n == :msie_compatibility ? [:msie_compatibility, :msie] : n }]
|
427
|
-
end
|
428
|
-
|
429
|
-
# Stringifies a browser version.
|
430
|
-
#
|
431
|
-
# @param version [String|NilClass] If non falsy, the string to prepend to the version. If falsy, the version information will not be included.
|
432
|
-
# @return [Array] The version strings or `nil`, if it was set to be skipped.
|
433
|
-
def stringify_version(version)
|
434
|
-
version = "version-" if version.is_a?(TrueClass)
|
435
|
-
tokens = @version.split(".")
|
436
|
-
|
437
|
-
!version ? nil : tokens.reduce([version + tokens.shift]) {|prev, current|
|
438
|
-
prev + [prev.last + "_" + current]
|
439
|
-
}.flatten
|
440
|
-
end
|
441
|
-
end
|
442
|
-
|
443
|
-
# Methods to parse the user agent.
|
444
|
-
module Parsing
|
445
|
-
# Parses the User-Agent header.
|
446
|
-
# @param agent [String] The User-Agent header.
|
447
|
-
# @return [Boolean] `true` if the browser was detected, `false` otherwise.
|
448
|
-
def parse_agent(agent = nil)
|
449
|
-
agent = agent.ensure_string
|
450
|
-
|
451
|
-
@name, _ = match_name_and_version(agent)
|
452
|
-
@version = adjust_version(@version)
|
453
|
-
@platform = match_platform(agent)
|
454
|
-
|
455
|
-
(@name != :unknown) ? true : false
|
456
|
-
end
|
457
|
-
|
458
|
-
# Parses the Accept-Language header.
|
459
|
-
#
|
460
|
-
# @param accept_language [String] The Accept-Language header.
|
461
|
-
# @return [Array] The list of accepted languages.
|
462
|
-
def parse_accept_language(accept_language = nil)
|
463
|
-
accept_language.ensure_string.gsub(/;q=[\d.]+/, "").split(",").map {|l| l.downcase.strip }.select{|l| l.present? }
|
464
|
-
end
|
465
|
-
|
466
|
-
private
|
467
|
-
# Matches a browser name and version.
|
468
|
-
#
|
469
|
-
# @param agent [String] The User-Agent header.
|
470
|
-
# @return [String|Symbol] The browser name or `:unknown`, if no match was found.
|
471
|
-
def match_name_and_version(agent)
|
472
|
-
catch(:name) do
|
473
|
-
::Brauser::Browser.browsers.each do |tag, definition|
|
474
|
-
matched = definition.match(:primary, definition, agent)
|
475
|
-
|
476
|
-
if matched then
|
477
|
-
@version = definition.match(:secondary, definition, agent)
|
478
|
-
throw(:name, tag)
|
479
|
-
end
|
480
|
-
end
|
481
|
-
|
482
|
-
:unknown
|
483
|
-
end
|
484
|
-
end
|
485
|
-
|
486
|
-
# Adjusts a browser version.
|
487
|
-
#
|
488
|
-
# @param version [String] The version to adjust.
|
489
|
-
# @return [String] The adjusted version.
|
490
|
-
def adjust_version(version)
|
491
|
-
# Adjust version
|
492
|
-
if version.blank? then
|
493
|
-
"0.0"
|
494
|
-
elsif version.is_a?(::MatchData) then
|
495
|
-
version.to_a.last
|
496
|
-
else
|
497
|
-
version
|
498
|
-
end
|
499
|
-
end
|
500
|
-
|
501
|
-
# Matches a browser platform.
|
502
|
-
#
|
503
|
-
# @param agent [String] The User-Agent header.
|
504
|
-
# @return [String|Symbol] The browser platform or `:unknown`, if no match was found.
|
505
|
-
def match_platform(agent)
|
506
|
-
catch(:platform) do
|
507
|
-
::Brauser::Browser.platforms.each do |tag, definition|
|
508
|
-
throw(:platform, tag) if definition.match(:primary, definition, agent)
|
509
|
-
end
|
510
|
-
|
511
|
-
:unknown
|
512
|
-
end
|
513
|
-
end
|
514
|
-
end
|
515
|
-
|
516
|
-
# Methods to query with chaining.
|
517
|
-
module PartialQuerying
|
518
|
-
# Checks if the browser is a specific name and optionally of a specific version and platform.
|
519
|
-
#
|
520
|
-
# @see #v?
|
521
|
-
# @see #on?
|
522
|
-
#
|
523
|
-
# @param names [Symbol|Array] A list of specific names to match. Also, this meta-names are supported: `:capable` and `:tablet`.
|
524
|
-
# @param versions [String|Hash] A string in the form `operator version && ...` (example: `>= 7 && < 4`) or an hash with specific version to match against,
|
525
|
-
# in form `{:operator => version}`, where operator is one of `:lt, :lte, :eq, :gt, :gte`.
|
526
|
-
# @param platforms [Symbol|Array] A list of specific platform to match. Valid values are all those possible for the platform attribute.
|
527
|
-
# @return [Query] A query which can evaluated for concatenation or result.
|
528
|
-
def is(names = [], versions = {}, platforms = [])
|
529
|
-
parse_agent(@agent) if !@name
|
530
|
-
|
531
|
-
names = adjust_names(names)
|
532
|
-
versions = parse_versions_query(versions)
|
533
|
-
platforms = platforms.ensure_array
|
534
|
-
|
535
|
-
::Brauser::Query.new(self,
|
536
|
-
(names.blank? || (names.include?(@name) && check_capable(names))) &&
|
537
|
-
(versions.blank? || v?(versions)) &&
|
538
|
-
(platforms.blank? || on?(platforms))
|
539
|
-
)
|
540
|
-
end
|
541
|
-
|
542
|
-
# Checks if the browser is a specific version.
|
543
|
-
#
|
544
|
-
# @param versions [String|Hash] A string in the form `operator version && ...` (example: `>= 7 && < 4`) or an hash with specific version to match against,
|
545
|
-
# in form `{:operator => version}`, where operator is one of `:lt, :lte, :eq, :gt, :gte`.
|
546
|
-
# @return [Query] A query which can evaluated for concatenation or result.
|
547
|
-
def v(versions = {})
|
548
|
-
parse_agent(@agent) if !@version
|
549
|
-
versions = versions.is_a?(String) ? parse_versions_query(versions) : versions.ensure_hash
|
550
|
-
|
551
|
-
::Brauser::Query.new(self, versions.all? { |operator, value| Brauser::Browser.compare_versions(@version, operator, value) })
|
552
|
-
end
|
553
|
-
|
554
|
-
# Check if the browser is on a specific platform.
|
555
|
-
#
|
556
|
-
# @param platforms [Symbol|Array] A list of specific platform to match.
|
557
|
-
# @return [Query] A query which can evaluated for concatenation or result.
|
558
|
-
def on(platforms = [])
|
559
|
-
parse_agent(@agent) if !@platform
|
560
|
-
|
561
|
-
::Brauser::Query.new(self, platforms.blank? || platforms.ensure_array(nil, true, true, true, :to_sym).include?(@platform))
|
562
|
-
end
|
563
|
-
|
564
|
-
# Check if the browser accepts the specified languages.
|
565
|
-
#
|
566
|
-
# @param langs [String|Array] A list of languages to match against.
|
567
|
-
# @return [Query] A query which can evaluated for concatenation or result.
|
568
|
-
def accepts(langs = [])
|
569
|
-
parse_accept_language(@accept_language) if !@languages
|
570
|
-
|
571
|
-
::Brauser::Query.new(self, (@languages & langs.ensure_array(nil, true, true, true, :to_s)).present?)
|
572
|
-
end
|
573
|
-
|
574
|
-
private
|
575
|
-
# Adjusts names for correct matching.
|
576
|
-
#
|
577
|
-
# @param names [Array] A list of names.
|
578
|
-
# @return [Array] The adjusted list of names.
|
579
|
-
def adjust_names(names)
|
580
|
-
# Adjust names
|
581
|
-
names = names.ensure_array(nil, true, true, true, :to_sym)
|
582
|
-
names << [:msie, :msie_compatibility] if names.include?(:ie) || names.include?(:msie)
|
583
|
-
names << [:chromium] if names.include?(:chrome)
|
584
|
-
names << [:chrome, :firefox, :safari, :opera, :msie] if names.include?(:capable)
|
585
|
-
names << [:ipad, :android, :kindle] if names.include?(:tablet)
|
586
|
-
names.flatten.compact.uniq
|
587
|
-
end
|
588
|
-
|
589
|
-
# Checks if the browser is capable.
|
590
|
-
#
|
591
|
-
# @param names [Array] A list of names.
|
592
|
-
# @return [Boolean] `true` if the browser is capable, `false` otherwise.
|
593
|
-
def check_capable(names)
|
594
|
-
!names.include?(:capable) || @name != :msie || Brauser::Browser.compare_versions(@version, :gte, 9)
|
595
|
-
end
|
596
|
-
|
597
|
-
# Parses a version query.
|
598
|
-
#
|
599
|
-
# @param versions [String|Hash] A string in the form `operator version && ...` (example: `>= 7 && < 4`) or an hash with specific version to match
|
600
|
-
# against, in form `{:operator => version}`, where operator is one of `:lt, :lte, :eq, :gt, :gte`.
|
601
|
-
# @return [Hash] The hash representation of the query.
|
602
|
-
def parse_versions_query(versions)
|
603
|
-
versions.is_a?(::Hash) ? versions : versions.ensure_string.split(/\s*&&\s*/).reduce({}) do |prev, token|
|
604
|
-
operator, version = parse_versions_query_component(token)
|
605
|
-
prev[operator] = version if operator.present? && version.present?
|
606
|
-
prev
|
607
|
-
end
|
608
|
-
end
|
609
|
-
|
610
|
-
# Parses a token of a version query.
|
611
|
-
#
|
612
|
-
# @param token [String] The token to parse.
|
613
|
-
# @return [Array] An operator and an argument.
|
614
|
-
def parse_versions_query_component(token)
|
615
|
-
operator, version = token.strip.split(/\s+/, 2).map(&:strip)
|
616
|
-
[{"<" => :lt, "<=" => :lte, "=" => :eq, "==" => :eq, ">" => :gt, ">=" => :gte}.fetch(operator, nil), version]
|
617
|
-
end
|
618
|
-
end
|
619
|
-
|
620
|
-
# Methods to end querying.
|
621
|
-
module Querying
|
622
|
-
# Checks if the browser is a specific name and optionally of a specific version and platform.
|
623
|
-
#
|
624
|
-
# @see #v?
|
625
|
-
# @see #on?
|
626
|
-
#
|
627
|
-
# @param names [Symbol|Array] A list of specific names to match. Also, this meta-names are supported: `:capable` and `:tablet`.
|
628
|
-
# @param versions [Hash] An hash with specific version to match against. Need to be in form `{:operator => version}`, where operator
|
629
|
-
# is one of `:lt, :lte, :eq, :gt, :gte`.
|
630
|
-
# @param platforms [Symbol|Array] A list of specific platform to match. Valid values are all those possible for the platform attribute.
|
631
|
-
# @return [Boolean] `true` if current browser matches, `false` otherwise.
|
632
|
-
def is?(names = [], versions = {}, platforms = [])
|
633
|
-
is(names, versions, platforms).result
|
634
|
-
end
|
635
|
-
|
636
|
-
# Checks if the browser is a specific version.
|
637
|
-
#
|
638
|
-
# @param versions [String|Hash] A string in the form `operator version && ...` (example: `>= 7 && < 4`) or an hash with specific version to match against,
|
639
|
-
# in form `{:operator => version}`, where operator is one of `:lt, :lte, :eq, :gt, :gte`.
|
640
|
-
# @return [Boolean] `true` if current browser matches, `false` otherwise.
|
641
|
-
def v?(versions = {})
|
642
|
-
v(versions).result
|
643
|
-
end
|
644
|
-
|
645
|
-
# Check if the browser is on a specific platform.
|
646
|
-
#
|
647
|
-
# @param platforms [Symbol|Array] A list of specific platform to match.
|
648
|
-
# @return [Boolean] `true` if current browser matches, `false` otherwise.
|
649
|
-
def on?(platforms = [])
|
650
|
-
on(platforms).result
|
651
|
-
end
|
652
|
-
|
653
|
-
# Check if the browser accepts the specified languages.
|
654
|
-
#
|
655
|
-
# @param langs [String|Array] A list of languages to match against.
|
656
|
-
# @return [Boolean] `true` if current browser matches, `false` otherwise.
|
657
|
-
def accepts?(langs = [])
|
658
|
-
accepts(langs).result
|
659
|
-
end
|
660
|
-
|
661
|
-
# Check if the browser is supported.
|
662
|
-
#
|
663
|
-
# @param supported [Hash|String] A map of engines and minimum supported major version, or a path to YAML file containing the map.
|
664
|
-
# @return [Boolean] `true` if current browser is supported, `false` otherwise.
|
665
|
-
def supported?(supported)
|
666
|
-
supported = YAML.load_file(supported).symbolize_keys if supported.is_a?(String)
|
667
|
-
minimum = supported[name]
|
668
|
-
(minimum && v?(gte: minimum)).to_boolean
|
669
|
-
end
|
670
|
-
end
|
671
|
-
end
|
672
|
-
|
673
9
|
# This class represents a detection of the current user browser.
|
674
10
|
#
|
675
11
|
# @attribute agent
|
@@ -693,15 +29,15 @@ module Brauser
|
|
693
29
|
attr_accessor :platform
|
694
30
|
|
695
31
|
# Aliases
|
696
|
-
|
697
|
-
alias :ua= :agent=
|
32
|
+
alias_attribute :ua, :agent
|
698
33
|
|
699
|
-
include ::Brauser::
|
700
|
-
include ::Brauser::
|
701
|
-
include ::Brauser::
|
702
|
-
include ::Brauser::
|
703
|
-
include ::Brauser::
|
704
|
-
include ::Brauser::
|
34
|
+
include ::Brauser::Browseable::General
|
35
|
+
include ::Brauser::Browseable::Attributes
|
36
|
+
include ::Brauser::Browseable::DefaultDefinitions
|
37
|
+
include ::Brauser::Browseable::Register
|
38
|
+
include ::Brauser::Browseable::Parsing
|
39
|
+
include ::Brauser::Browseable::PartialQuerying
|
40
|
+
include ::Brauser::Browseable::Querying
|
705
41
|
|
706
42
|
# Creates a new browser.
|
707
43
|
#
|
@@ -719,6 +55,16 @@ module Brauser
|
|
719
55
|
parse_agent(@agent) if @agent
|
720
56
|
end
|
721
57
|
|
58
|
+
# Get the current browser version (if called without arguments) or checks if the browser is a specific version.
|
59
|
+
#
|
60
|
+
# @see #is_version
|
61
|
+
# @param versions [String|Hash] A string in the form `operator version && ...` (example: `>= 7 && < 4`) or an hash with specific version to match against,
|
62
|
+
# in form `{:operator => version}`, where operator is one of `:lt, :lte, :eq, :gt, :gte`.
|
63
|
+
# @return [String|Query] The browser version or a query which can evaluated for concatenation or result.
|
64
|
+
def version(versions = nil)
|
65
|
+
!versions ? @version : version_equals_to(versions)
|
66
|
+
end
|
67
|
+
|
722
68
|
# This method enables the use of dynamic queries in just one method.
|
723
69
|
#
|
724
70
|
# For example:
|
@@ -737,77 +83,24 @@ module Brauser
|
|
737
83
|
# @param block [Proc] A block to pass to the method. Unused from the query.
|
738
84
|
# @return [Boolean|Query|nil] A query or a boolean value (if `method` ends with `?`). If the query is not valid, `NoMethodError` will be raised.
|
739
85
|
def method_missing(query, *arguments, &block)
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
super(query, *arguments, &block)
|
746
|
-
end
|
747
|
-
end
|
748
|
-
|
749
|
-
# Returns the current browser as a string.
|
750
|
-
#
|
751
|
-
# @see #classes
|
752
|
-
#
|
753
|
-
# @return [String] A string representation of the current browser.
|
754
|
-
def to_s
|
755
|
-
self.classes
|
86
|
+
query_s = query.ensure_string
|
87
|
+
rv = execute_query(parse_query(query_s)) || Brauser::Query.new(self, false)
|
88
|
+
query_s =~ /\?$/ ? rv.result : rv
|
89
|
+
rescue NoMethodError
|
90
|
+
super(query, *arguments, &block)
|
756
91
|
end
|
757
92
|
|
758
93
|
private
|
759
|
-
# Parse query, getting all arguments.
|
760
|
-
#
|
761
|
-
# @param query [String] The query to issue. Use `__` to separate query and `_` in place of `.` in the version.
|
762
|
-
# @return [Array] And array of `[method, arguments]` entries.
|
763
|
-
def parse_query(query)
|
764
|
-
query.gsub(/\?$/, "").gsub(/(_(v|on|is))/, " \\2").split(" ").map do |part|
|
765
|
-
parse_query_part(part)
|
766
|
-
end
|
767
|
-
end
|
768
|
-
|
769
|
-
# Handles a part of a query.
|
770
|
-
#
|
771
|
-
# @param part [String] A part of a query.
|
772
|
-
# @return [Boolean|Query|nil] A query or a boolean value (if `method` ends with `?`). If the query is not valid, `NoMethodError` will be raised.
|
773
|
-
def parse_query_part(part)
|
774
|
-
method, arguments = part.split("_", 2)
|
775
94
|
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
#
|
787
|
-
# @param version [String] The version to parse.
|
788
|
-
# @return [String] The parsed version.
|
789
|
-
def parse_query_version(version)
|
790
|
-
[
|
791
|
-
[/_?eq_?/, " == "], # Parse ==
|
792
|
-
[/_?lte_?/, " <= "], # Parse <=
|
793
|
-
[/_?gte_?/, " >= "], # Parse >=
|
794
|
-
[/_?lt_?/, " < "], # Parse <
|
795
|
-
[/_?gt_?/, " > "], # Parse >
|
796
|
-
[/_?and_?/, " && "], # Parse &&
|
797
|
-
["_", "."], # Dot notation
|
798
|
-
[/\s+/, " "]
|
799
|
-
].reduce(version) { |current, parse| current.gsub(parse[0], parse[1])}.strip
|
800
|
-
end
|
801
|
-
|
802
|
-
# Executes a parsed query
|
803
|
-
#
|
804
|
-
# @param query [Array] And array of `[method, arguments]` entries.
|
805
|
-
# @return [Brauser::Query] The result of the query.
|
806
|
-
def execute_query(query)
|
807
|
-
query.reduce(Brauser::Query.new(self, true)) { |rv, call|
|
808
|
-
break if !rv.result
|
809
|
-
rv.send(call[0], *call[1])
|
810
|
-
}
|
811
|
-
end
|
95
|
+
# Executes a parsed query
|
96
|
+
#
|
97
|
+
# @param query [Array] And array of `[method, arguments]` entries.
|
98
|
+
# @return [Brauser::Query] The result of the query.
|
99
|
+
def execute_query(query)
|
100
|
+
query.reduce(Brauser::Query.new(self, true)) { |rv, call|
|
101
|
+
break unless rv.result
|
102
|
+
rv.send(call[0], *call[1])
|
103
|
+
}
|
104
|
+
end
|
812
105
|
end
|
813
|
-
end
|
106
|
+
end
|