sassc-ruby
sassc-ruby copied to clipboard
How to expose more functionality from libsass?
libsass appears to define a lot of colour-related functions that don't get exposed in sassc, such as lighten, darken, etc.
Can we add a way to access these functions? I can't work out how to do it, as I'm not super-familiar with FFI...
I don't exactly follow what you are asking for. Could you please give me a code example of what you'd like to do?
I ended up using an alternative gem (Chroma) to do it, but eh.
The sass gem provided methods to adjust colours, and I can see that the code for libsass provides methods to do it also, in functions.cpp (lighten, darken, etc), but these methods haven't been imported into Ruby. Ideally I wanted to do something like SassC::Util::Native.lighten("#4edd9e", 0.35) and get #e4faf0.
In my case, I need to do custom bootstrap theming on the fly. I see exactly how the colors I need are derived, ultimately using the Sass "mix" function. Our CSS is generated by Webpacker during slug compliation. At run time I need to generate custom themes. Like @sevenseacat, I am forced back to Chroma in order to do this. It is somewhat frustrating because, the Libsass "mix" function is right here, but I don't see how to access it. Chroma does not provide a "mix" function, so I end up needing to fudge it. Oh well, it will work for now.
EDIT: 3 hours later -- this works quite well. It's a funny workaround, but on the other hand I have to weight the tradeoff of incorporating the Chroma gem as a dependency, which is not maintained (even less so than sassc-ruby), and also it does not do the color transformations in the same way that Bootstrap does. Whereas this shim, albeit ugly, is very performant, and does the color transformations in exactly the same way as Bootstrap, allowing for exact matches:
# https://github.com/sass/sassc-ruby/issues/104#issuecomment-1164890694
require "sassc"
module SasscFunctions
# https://github.com/twbs/bootstrap/blob/v5.2.0-beta1/scss/_functions.scss#L206
def self.bootstrap_tint_color(color, weight)
sass_mix("white", color, weight);
end
# https://github.com/twbs/bootstrap/blob/v5.2.0-beta1/scss/_functions.scss#L210
def self.bootstrap_shade_color(color, weight)
sass_mix("black", color, weight);
end
# https://github.com/twbs/bootstrap/blob/v5.2.0-beta1/scss/_functions.scss#L216
def self.bootstrap_shift_color(color, weight)
weight_int = weight.to_i
weight_int > 0 ? bootstrap_shade_color(color, weight) : bootstrap_tint_color(color, weight)
end
# Using mix() is not the same as lighten() and darken()—the former blends the specified color with white or black, while the latter only adjusts the lightness value of each color. The result is a much more complete suite of colors, as shown in this CodePen demo.
# Our tint-color() and shade-color() functions use mix() alongside our $theme-color-interval variable, which specifies a stepped percentage value for each mixed color we produce. See the scss/_functions.scss and scss/_variables.scss files for the full source code.
# https://getbootstrap.com/docs/5.0/customize/color/#notes-on-sass
def self.sass_mix(color1, color2, weight)
self.sass_color_raw("mix(#{color1}, #{color2}, #{weight})")
end
def self.sass_to_rgb(color_string)
red = SasscFunctions.sass_color_raw("red(#{color_string})")
blue = SasscFunctions.sass_color_raw("blue(#{color_string})")
green = SasscFunctions.sass_color_raw("green(#{color_string})")
"#{red}, #{green}, #{blue}"
end
def self.sass_color_raw(color_string_raw)
simple_stylesheet = "p { color: #{color_string_raw}}"
css = SassC::Engine.new(simple_stylesheet, style: :compressed).render
parse_resulting_color_regex = /p{color:(.+)}/
match = parse_resulting_color_regex.match(css)
match[1]
end
end