diff --git a/doc-src/SASS_CHANGELOG.md b/doc-src/SASS_CHANGELOG.md index cdadf57a9c..f39e877c2e 100644 --- a/doc-src/SASS_CHANGELOG.md +++ b/doc-src/SASS_CHANGELOG.md @@ -13,6 +13,9 @@ * 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 9b80308794..f9547fc0ff 100644 --- a/lib/sass/script/functions.rb +++ b/lib/sass/script/functions.rb @@ -101,21 +101,30 @@ def assert_type(value, type) # 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) assert_type red, :Number assert_type green, :Number assert_type blue, :Number - [red.value, green.value, blue.value].each do |v| - next unless v < 0 || v > 255 - 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 - Color.new([red.value, green.value, blue.value]) + Color.new(rgb) 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 a5b96de763..ef45ad9411 100644 --- a/test/sass/functions_test.rb +++ b/test/sass/functions_test.rb @@ -103,6 +103,13 @@ def test_rgb 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)") @@ -116,6 +123,15 @@ def test_rgb_tests_bounds "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)");