def __init__(self, scss_vars=None, scss_opts=None, scss_files=None, super_selector='', live_errors=False, library=None, func_registry=None, search_paths=None): self.super_selector = super_selector self._scss_vars = {} if scss_vars: calculator = Calculator() for var_name, value in scss_vars.items(): if isinstance(value, six.string_types): scss_value = calculator.evaluate_expression(value) if scss_value is None: # TODO warning? scss_value = String.unquoted(value) else: scss_value = value self._scss_vars[var_name] = scss_value self._scss_opts = scss_opts or {} self._scss_files = scss_files self._library = func_registry or library self._search_paths = search_paths # If true, swallow compile errors and embed them in the output instead self.live_errors = live_errors
def test_reference_operations(): """Test the example expressions in the reference document: http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#operations """ # TODO: break this into its own file and add the entire reference guide # Need to build the calculator manually to get at its namespace, and need # to use calculate() instead of evaluate_expression() so interpolation # works ns = CoreExtension.namespace.derive() calc = Calculator(ns).calculate # Simple example assert calc('1in + 8pt') == Number(1.1111111111111112, "in") # Division ns.set_variable('$width', Number(1000, "px")) ns.set_variable('$font-size', Number(12, "px")) ns.set_variable('$line-height', Number(30, "px")) assert calc('10px/8px') == String('10px / 8px') # plain CSS; no division assert calc('$width/2') == Number(500, "px") # uses a variable; does division assert calc('(500px/2)') == Number(250, "px") # uses parens; does division assert calc('5px + 8px/2px') == Number(9, "px") # uses +; does division # TODO, again: Ruby Sass correctly renders this without spaces assert calc('#{$font-size}/#{$line-height}') == String('12px / 30px') # uses #{}; does no division # Color operations ns.set_variable('$translucent-red', Color.from_rgb(1, 0, 0, 0.5)) ns.set_variable('$green', Color.from_name('lime')) assert calc('#010203 + #040506') == Color.from_hex('#050709') assert calc('#010203 * 2') == Color.from_hex('#020406') assert calc( 'rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75)') == Color.from_rgb( 1, 1, 0, 0.75) assert calc('opacify($translucent-red, 0.3)') == Color.from_rgb( 1, 0, 0, 0.8) assert calc('transparentize($translucent-red, 0.25)') == Color.from_rgb( 1, 0, 0, 0.25) assert calc( "progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#{ie-hex-str($green)}', endColorstr='#{ie-hex-str($translucent-red)}')" ).render( ) == "progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#FF00FF00', endColorstr='#80FF0000')" # String operations ns.set_variable('$value', Null()) assert_strict_string_eq(calc('e + -resize'), String('e-resize', quotes=None)) assert_strict_string_eq(calc('"Foo " + Bar'), String('Foo Bar', quotes='"')) assert_strict_string_eq(calc('sans- + "serif"'), String('sans-serif', quotes=None)) assert calc('3px + 4px auto') == List( [Number(7, "px"), String('auto', quotes=None)]) assert_strict_string_eq(calc('"I ate #{5 + 10} pies!"'), String('I ate 15 pies!', quotes='"')) assert_strict_string_eq(calc('"I ate #{$value} pies!"'), String('I ate pies!', quotes='"'))
def __init__(self, is_sass=False): # TODO it would be lovely to get these out of here, somehow self.namespace = Namespace(variables=_default_scss_vars) self.compiler = Compiler(namespace=self.namespace) self.compilation = self.compiler.make_compilation() self.legacy_compiler_options = {} self.source_file = SourceFile.from_string('', '<shell>', is_sass=is_sass) self.calculator = Calculator(self.namespace)
def test_functions(calc): calc = Calculator(CoreExtension.namespace).calculate assert calc('grayscale(red)') == Color.from_rgb(0.5, 0.5, 0.5) assert calc('grayscale(1)') == String( 'grayscale(1)', quotes=None) # Misusing css built-in functions (with scss counterpart) assert calc('skew(1)') == String( 'skew(1)', quotes=None) # Missing css-only built-in functions with pytest.raises(SassEvaluationError): calc('unitless("X")') # Misusing non-css built-in scss funtions
def test_parse_special_functions(): ns = CoreExtension.namespace.derive() calc = Calculator(ns).calculate # expression() allows absolutely any old garbage inside # TODO we can't deal with an unmatched { due to the block locator, but ruby # can for gnarly_expression in ( "not ~* remotely *~ valid {syntax}", "expression( ( -0 - floater.offsetHeight + ( document" ".documentElement.clientHeight ? document.documentElement" ".clientHeight : document.body.clientHeight ) + ( ignoreMe" " = document.documentElement.scrollTop ? document" ".documentElement.scrollTop : document.body.scrollTop ) ) +" " 'px' )"): expr = 'expression(' + gnarly_expression + ')' assert calc(expr).render() == expr # alpha() doubles as a special function if it contains opacity=n, the IE # filter syntax assert calc('alpha(black)') == Number(1) assert calc('alpha(opacity = 5)') == Function('opacity=5', 'alpha') assert calc('alpha(opacity = 5)').render() == 'alpha(opacity=5)' # url() allows both an opaque URL and a Sass expression, based on some # heuristics ns.set_variable('$foo', String.unquoted('foo')) assert calc('url($foo)').render() == "url(foo)" assert calc('url(#{$foo}foo)').render() == "url(foofoo)" assert calc('url($foo + $foo)').render() == "url(foofoo)" # TODO this one doesn't work if $foo has quotes; Url.render() tries to # escape them. which i'm not sure is wrong, but we're getting into # territory where it's obvious bad output... assert calc('url($foo + #{$foo})').render() == "url(foo + foo)" assert calc('url(foo #{$foo} foo)').render() == "url(foo foo foo)" with pytest.raises(SassSyntaxError): # Starting with #{} means it's a url, which can't contain spaces calc('url(#{$foo} foo)') with pytest.raises(SassSyntaxError): # Or variables calc('url(#{$foo}$foo)') with pytest.raises(SassSyntaxError): # This looks like a URL too calc('url(foo#{$foo} foo)')
def calc(expression): return Calculator(CoreExtension.namespace).evaluate_expression(expression)
def calc(): return Calculator(CompassExtension.namespace).evaluate_expression
def calc(): return Calculator().evaluate_expression