diff --git a/doc-src/SASS_CHANGELOG.md b/doc-src/SASS_CHANGELOG.md index 06d07176..be570e9a 100644 --- a/doc-src/SASS_CHANGELOG.md +++ b/doc-src/SASS_CHANGELOG.md @@ -97,6 +97,9 @@ Several bug fixes and minor improvements have been made, including: * All Sass functions now raise explicit errors if their inputs are of the incorrect type. +* Allow the SassScript `rgb()` function to take percentages + in addition to numerical values. + * Add an `assert_type` function that's available to {Sass::Script::Functions}. This is useful for typechecking the inputs to functions. diff --git a/lib/sass/script/functions.rb b/lib/sass/script/functions.rb index 62cf85a6..8e3ccf1a 100644 --- a/lib/sass/script/functions.rb +++ b/lib/sass/script/functions.rb @@ -126,11 +126,14 @@ module Sass::Script # Creates a {Color} object from red, green, and blue values. # @param red - # A number between 0 and 255 inclusive + # A number between 0 and 255 inclusive, + # or between 0% and 100% inclusive # @param green - # A number between 0 and 255 inclusive + # A number between 0 and 255 inclusive, + # or between 0% and 100% inclusive # @param blue - # A number between 0 and 255 inclusive + # A number between 0 and 255 inclusive, + # or between 0% and 100% inclusive def rgb(red, green, blue) rgba(red, green, blue, Number.new(1)) end @@ -152,16 +155,22 @@ module Sass::Script assert_type blue, :Number assert_type alpha, :Number - [red.value, green.value, blue.value].each do |v| - next if (0..255).include?(v) - raise ArgumentError.new("Color value #{v} must be between 0 and 255 inclusive") + rgb = [red, green, blue].map do |c| + v = c.value + if c.numerator_units == ["%"] && c.denominator_units.empty? + next v * 255 / 100.0 if (0..100).include?(v) + raise ArgumentError.new("Color value #{c} must be between 0% and 100% inclusive") + else + next v if (0..255).include?(v) + raise ArgumentError.new("Color value #{v} must be between 0 and 255 inclusive") + end end unless (0..1).include?(alpha.value) raise ArgumentError.new("Alpha channel #{alpha.value} must be between 0 and 1 inclusive") end - Color.new([red.value, green.value, blue.value, alpha.value]) + Color.new(rgb + [alpha.value]) end # Creates a {Color} object from hue, saturation, and lightness. diff --git a/test/sass/functions_test.rb b/test/sass/functions_test.rb index 5be24e01..3ae1360a 100644 --- a/test/sass/functions_test.rb +++ b/test/sass/functions_test.rb @@ -96,6 +96,13 @@ class SassFunctionTest < Test::Unit::TestCase assert_equal("#00ff7f", evaluate("rgb(0, 255, 127)")) end + def test_rgb_percent + assert_equal("#123456", evaluate("rgb(7.1%, 20.4%, 34%)")) + assert_equal("#beaded", evaluate("rgb(74.7%, 173, 93%)")) + assert_equal("#beaded", evaluate("rgb(190, 68%, 237)")) + assert_equal("#00ff7f", evaluate("rgb(0%, 100%, 50%)")) + end + def test_rgb_tests_bounds assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgb'", "rgb(256, 1, 1)") @@ -109,6 +116,15 @@ class SassFunctionTest < Test::Unit::TestCase "rgb(-1, 1, 1)") end + def test_rgb_test_percent_bounds + assert_error_message("Color value 100.1% must be between 0% and 100% inclusive for `rgb'", + "rgb(100.1%, 0, 0)") + assert_error_message("Color value -0.1% must be between 0% and 100% inclusive for `rgb'", + "rgb(0, -0.1%, 0)") + assert_error_message("Color value 101% must be between 0% and 100% inclusive for `rgb'", + "rgb(0, 0, 101%)") + end + def test_rgb_tests_types assert_error_message("\"foo\" is not a number for `rgb'", "rgb(\"foo\", 10, 12)"); assert_error_message("\"foo\" is not a number for `rgb'", "rgb(10, \"foo\", 12)");