Module: Colors::CSS
- Defined in:
- lib/colors/css.rb
Class Method Summary collapse
-
.parse(css_string) ⇒ Object
Factory method for generating RGB/RGBA/HSL/HSLA Objects.
Class Method Details
.parse(css_string) ⇒ Object
Factory method for generating RGB/RGBA/HSL/HSLA Objects. Parsing based on spec https://www.w3.org/TR/css-color-3 ; section 4.2
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/colors/css.rb', line 5 def self.parse(css_string) = "must be a string of `rgb(rr,gg,bb)`, `rgba(rr,gg,bb,aa)`, `hsl(hh,ss,ll)`, or `hsla(hh,ss,ll,aa)` form" unless css_string.respond_to?(:to_str) raise ArgumentError, "#{}: #{css_string.inspect}" end css_string = css_string.to_str.strip matcher = /\A((?:rgb|hsl)a?)\(([^)]+)\)\z/.match(css_string) unless matcher raise ArgumentError, "#{}: #{css_string.inspect}" end color_space, args_string = matcher[1..2] args = args_string.strip.split(/\s*,\s*/) has_alpha = color_space.end_with?("a") # rgba/hsla if has_alpha && args.length != 4 raise ArgumentError, "Expecting 4 fields for #{color_space}(): #{css_string.inspect}" elsif !has_alpha && args.length != 3 raise ArgumentError, "Expecting 3 fields for #{color_space}(): #{css_string.inspect}" end case color_space when "rgb", "rgba" rgb, alpha = args[0, 3], args[3] num_percent_vals = rgb.count {|v| v.end_with?("%") } # CSS3 allows RGB values to be specified with all 3 as a percentage "##%" # or all as integer values without '%' sign. if num_percent_vals.zero? # interpret as integer values in range of 0..255 r, g, b = rgb.map {|strval| strval.to_i.clamp(0, 255) } # Note, RGBA.new expects all values to be integers or floats. # For this case, we also turn the alpha-value into an int range 0..255 # to match the r,g,b values. a = has_alpha && (alpha.to_r.clamp(0r, 1r) * 255).to_i elsif num_percent_vals == 3 r, g, b = rgb.map {|strval| (strval.to_r / 100).clamp(0r, 1r) } a = has_alpha && alpha.to_r.clamp(0r, 1r) else raise ArgumentError, "Invalid mix of percent and integer values: #{css_string.inspect}" end return has_alpha ? RGBA.new(r, g, b, a) : RGB.new(r, g, b) when "hsl", "hsla" hue, sat, light, alpha = *args # CSS3 Hue values are an angle, unclear if we should convert to Integer or Rational here. h = hue.to_r s, l = [sat, light].map {|strval| (strval.to_r / 100).clamp(0r, 1r) } if has_alpha a = alpha.to_r.clamp(0r, 1r) return HSLA.new(h, s, l, a) else return HSL.new(h, s, l) end else raise ArgumentError, "Unknown color space: #{css_string.inspect}" end end |