module Browserino
Public Class Methods
analyze(uas, matcher = nil, headers = nil)
click to toggle source
# File lib/browserino/methods.rb, line 4 def self.analyze(uas, matcher = nil, headers = nil) @defaults ||= config.global_matchers.map(&:properties).reduce(&:merge) props = @defaults.merge(matcher && matcher.properties || {}) like = props.delete :like props = mass_collect props, uas if headers.is_a? Hash headers = normalize_header_keys headers props = fill_missing_with_headers headers, props end props = fix_inconsistent_props props like = Client.new props.merge(like_attrs(props, like, uas)) if like Client.new props, like end
collect(properties, uas)
click to toggle source
# File lib/browserino/methods.rb, line 129 def self.collect(properties, uas) properties.each_with_object({}) do |(n, v), r| r[n] = convert (v.is_a?(Regexp) ? v.match(uas).to_a[1] : v), format: n end end
collect_with_smart_watchers(properties, user_agent)
click to toggle source
# File lib/browserino/methods.rb, line 102 def self.collect_with_smart_watchers(properties, user_agent) properties.merge collect(smart_matchers(properties), user_agent) end
config()
click to toggle source
# File lib/browserino/methods.rb, line 66 def self.config @config ||= Config.new before_parse: [], global_matchers: [], properties: [], types: [:unknown], names: [], smart_matchers: {}, missing_props: {}, matchers: [], labels: Hash.new { |h, k| h[k] = [] }, filters: Hash.new { |h, k| h[k] = [] }, aliasses: Hash.new { |h, k| h[k] = [] } end
convert(val, **opts)
click to toggle source
# File lib/browserino/methods.rb, line 135 def self.convert(val, **opts) filters = config.filters[:global] + config.filters[opts[:format]] filters.each do |fmt| val = fmt.call val end val end
fill_missing_with_headers(headers, props)
click to toggle source
# File lib/browserino/methods.rb, line 47 def self.fill_missing_with_headers(headers, props) config.missing_props.each_with_object props do |(prop, blk), res| if props.key?(prop) && (!props[prop] || (props[prop].respond_to?(:empty?) && props[prop].empty?)) res[prop] = convert blk.call(headers, res), format: prop end end end
fix_inconsistent_props(hsh)
click to toggle source
# File lib/browserino/methods.rb, line 23 def self.fix_inconsistent_props(hsh) # patch locale and locales props if hsh[:locales].any? # when locale is not present in locales, append it hsh[:locales] << hsh[:locale] unless hsh[:locales].include? hsh[:locale] # ensure locales.first == locale when locale present in locales hsh[:locale] = hsh[:locales].first elsif hsh[:locale] # no locales from header but locale is found in UA, append locale # to locales to ensure expected output hsh[:locales] << hsh[:locale] end hsh end
get_flags(*flags)
click to toggle source
# File lib/browserino/methods.rb, line 144 def self.get_flags(*flags) flags.reduce(0) do |val, flag| case flag.to_sym when :m then val | Regexp::MULTILINE when :i then val | Regexp::IGNORECASE when :x then val | Regexp::EXTENDED end end end
label_for(target_name, version = nil)
click to toggle source
# File lib/browserino/methods.rb, line 80 def self.label_for(target_name, version = nil) return unless config.labels.key?(target_name) && version version = Version.new version unless version.is_a? Version return unless version > 0 config.labels[target_name].each do |candidate| return candidate[:name] if version.between? candidate[:range] end nil end
like_attrs(props, like, user_agent)
click to toggle source
# File lib/browserino/methods.rb, line 56 def self.like_attrs(props, like, user_agent) version = config.matchers.select { |m| m == like } .first.properties[:version] fattrs = { name: like } fattrs[:version] = version if version.is_a? Regexp fattrs[:version] ||= smart_matchers(fattrs)[:version] props.dup.merge collect(fattrs, user_agent) end
mass_collect(props, uas)
click to toggle source
# File lib/browserino/methods.rb, line 123 def self.mass_collect(props, uas) props = collect props, uas props = collect_with_smart_watchers props, uas with_labels props end
normalize_header_keys(headers)
click to toggle source
# File lib/browserino/methods.rb, line 40 def self.normalize_header_keys(headers) headers.each_with_object({}) do |(header, value), normalized| header = header.gsub(/^HTTP_/i, '').tr('-', '_').downcase.to_sym normalized[header] = value end end
parse(uas, headers = nil)
click to toggle source
# File lib/browserino.rb, line 19 def self.parse(uas, headers = nil) uas = '' unless uas #stringify user agent before usage when nil or false uas = config.before_parse.reduce(uas) { |u, b| b.call u } config.matchers.each do |matcher| return analyze uas, matcher, headers if matcher.matches? uas end analyze uas, nil, headers end
parse_detector(detect, properties)
click to toggle source
# File lib/browserino/methods.rb, line 114 def self.parse_detector(detect, properties) pat = properties.each_with_object(detect[:with].dup) do |(key, val), str| replacement = val.to_s.strip.gsub '_', '[_\s-]' str.gsub! ":#{key}", replacement unless replacement.empty? end Regexp.new pat, get_flags(*detect[:flags].to_a) end
smart_matchers(properties)
click to toggle source
# File lib/browserino/methods.rb, line 106 def self.smart_matchers(properties) config.smart_matchers.each_with_object({}) do |(prop, detector), props| next if properties.key? prop props[prop] = parse_detector detector, properties end end
version(current = '4.5.0')
click to toggle source
# File lib/browserino/version.rb, line 4 def self.version(current = '4.5.0') @version ||= Version.new current end
with_labels(properties)
click to toggle source
# File lib/browserino/methods.rb, line 92 def self.with_labels(properties) %i[name engine platform].each do |prop| lbl_prop = (prop == :name) && :label || "#{prop}_label".to_sym ver_prop = (prop == :name) && :version || "#{prop}_version".to_sym properties[lbl_prop] ||= label_for properties[prop], properties[ver_prop] end properties end