Class: Browsable::Target

Inherits:
Object
  • Object
show all
Defined in:
lib/browsable/target.rb

Overview

A browser-support target: the browsers and minimum versions the project intends to support, expressed as a browserslist query.

Target resolves a query into concrete minimum versions. It prefers the ‘browserslist` CLI (installed alongside node) and falls back to a small built-in table when node is not available.

Constant Summary collapse

MODERN =

Rails 8’s ‘allow_browser versions: :modern` resolves to roughly this set. Mirrors ActionController’s modern-browser baseline so browsable can read the policy without booting Rails.

{
  "chrome" => "120", "edge" => "120", "firefox" => "121",
  "safari" => "17.2", "opera" => "106"
}.freeze
DEFAULTS =

browsable’s built-in approximation of the browserslist ‘defaults` query —a frozen snapshot, used only as a last resort when the `browserslist` CLI is not installed (so live caniuse data cannot be queried) and there is no policy or explicit target. #note flags whenever this fallback is in play.

{
  "chrome" => "109", "edge" => "109", "firefox" => "115", "safari" => "15.6"
}.freeze
BROWSERSLIST_ALIASES =

Maps browserslist’s browser codes onto the names browsable reports with.

{
  "ios_saf" => "safari", "and_chr" => "chrome", "and_ff" => "firefox",
  "samsung" => "samsung", "op_mob" => "opera"
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(query, resolved: nil) ⇒ Target

Returns a new instance of Target.



61
62
63
64
65
66
67
# File 'lib/browsable/target.rb', line 61

def initialize(query, resolved: nil)
  @query = query
  @resolved = resolved
  # How #browsers was obtained: :explicit (a caller supplied it, e.g. a
  # Rails policy), :browserslist (the CLI), or :builtin (the frozen table).
  @resolved_via = resolved ? :explicit : nil
end

Instance Attribute Details

#queryObject (readonly)

Returns the value of attribute query.



35
36
37
# File 'lib/browsable/target.rb', line 35

def query
  @query
end

Class Method Details

.from_rails_policy(versions) ⇒ Object

Build a Target from a Rails ‘allow_browser versions:` argument.



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/browsable/target.rb', line 43

def self.from_rails_policy(versions)
  case versions
  when :modern, "modern", nil
    modern
  when Hash
    new("custom allow_browser policy", resolved: normalize_hash(versions))
  else
    # A named policy we don't special-case — treat the name as a query.
    new(versions.to_s)
  end
end

.modernObject

The Rails ‘:modern` baseline, fully resolved.



38
39
40
# File 'lib/browsable/target.rb', line 38

def self.modern
  new("modern", resolved: MODERN)
end

.normalize_hash(hash) ⇒ Object



55
56
57
58
59
# File 'lib/browsable/target.rb', line 55

def self.normalize_hash(hash)
  hash.each_with_object({}) do |(browser, version), out|
    out[browser.to_s] = version.to_s
  end
end

Instance Method Details

#as_jsonObject



115
116
117
# File 'lib/browsable/target.rb', line 115

def as_json
  { query: query.to_s, browsers: browsers, resolved_via: resolved_via }
end

#browsersObject

The resolved minimum versions, e.g. { “chrome” => “120”, … }.



70
71
72
# File 'lib/browsable/target.rb', line 70

def browsers
  @resolved ||= resolve
end

#includes?(browser, version) ⇒ Boolean

True when ‘version` of `browser` falls within the target.

Returns:

  • (Boolean)


80
81
82
83
84
85
86
87
# File 'lib/browsable/target.rb', line 80

def includes?(browser, version)
  min = minimum_version(browser)
  return false unless min && version

  Gem::Version.new(version.to_s) >= Gem::Version.new(min.to_s)
rescue ArgumentError
  false
end

#minimum_version(browser) ⇒ Object

The minimum supported version of a browser, or nil if untargeted.



75
76
77
# File 'lib/browsable/target.rb', line 75

def minimum_version(browser)
  browsers[browser.to_s]
end

#noteObject

A caveat about this target’s accuracy, or nil. Set when browsable had to fall back to its built-in table instead of querying live browserslist data.



105
106
107
108
109
110
111
112
113
# File 'lib/browsable/target.rb', line 105

def note
  return nil unless resolved_via == :builtin
  return nil if query.to_s.strip.downcase == "modern" # the builtin :modern set is exact

  "The versions above are browsable's built-in approximation — the `browserslist` " \
    "CLI is not installed, so live browser-share data could not be queried. Install " \
    "it (npm install -g browserslist) or set an explicit `target:` in " \
    "config/browsable.yml for accurate, stable versions."
end

#resolved_viaObject

How #browsers was resolved: :explicit, :browserslist, or :builtin.



98
99
100
101
# File 'lib/browsable/target.rb', line 98

def resolved_via
  browsers # force resolution
  @resolved_via
end

#to_browserslistObject

Format the target as browserslist query fragments, e.g. [“chrome >= 120”, “safari >= 17.2”]. Used to configure stylelint/eslint.



91
92
93
# File 'lib/browsable/target.rb', line 91

def to_browserslist
  browsers.map { |browser, version| "#{browser} >= #{version}" }
end

#to_sObject



95
# File 'lib/browsable/target.rb', line 95

def to_s = query.to_s