diff --git a/lib/src/ast/sass/expression/calculation.dart b/lib/src/ast/sass/expression/calculation.dart index ac17dc0aa..55c5b969a 100644 --- a/lib/src/ast/sass/expression/calculation.dart +++ b/lib/src/ast/sass/expression/calculation.dart @@ -50,6 +50,10 @@ class CalculationExpression implements Expression { } } + /// Returns a `sqrt()` calculation expression. + CalculationExpression.sqrt(Expression argument, FileSpan span) + : this("sqrt", [argument], span); + /// Returns a `clamp()` calculation expression. CalculationExpression.clamp( Expression min, Expression value, Expression max, FileSpan span) diff --git a/lib/src/parse/stylesheet.dart b/lib/src/parse/stylesheet.dart index 0a4286687..04edf310e 100644 --- a/lib/src/parse/stylesheet.dart +++ b/lib/src/parse/stylesheet.dart @@ -2894,6 +2894,7 @@ abstract class StylesheetParser extends Parser { assert(scanner.peekChar() == $lparen); switch (name) { case "calc": + case "sqrt": var arguments = _calculationArguments(1); return CalculationExpression(name, arguments, scanner.spanFrom(start)); diff --git a/lib/src/value/calculation.dart b/lib/src/value/calculation.dart index 74375b280..d7c4aec31 100644 --- a/lib/src/value/calculation.dart +++ b/lib/src/value/calculation.dart @@ -11,6 +11,7 @@ import '../utils.dart'; import '../value.dart'; import '../visitor/interface/value.dart'; import '../visitor/serialize.dart'; +import 'dart:math' as math; /// A SassScript calculation. /// @@ -120,6 +121,25 @@ class SassCalculation extends Value { return SassCalculation._("max", args); } + /// Creates a `sqrt()` calculation with the given [argument]. + /// + /// Each argument must be either a [SassNumber], a [SassCalculation], an + /// unquoted [SassString], a [CalculationOperation], or a + /// [CalculationInterpolation]. It must be passed at least one argument. + /// + /// This automatically simplifies the calculation, so it may return a + /// [SassNumber] rather than a [SassCalculation]. It throws an exception if it + /// can determine that the calculation will definitely produce invalid CSS. + static Value sqrt(Object argument) { + argument = _simplify(argument); + if (argument is! SassNumber) { + return SassCalculation.sqrt(argument); + } + argument.assertNoUnits(); + + return SassNumber(math.sqrt(argument.value)); + } + /// Creates a `clamp()` calculation with the given [min], [value], and [max]. /// /// Each argument must be either a [SassNumber], a [SassCalculation], an diff --git a/lib/src/visitor/async_evaluate.dart b/lib/src/visitor/async_evaluate.dart index 30c72ff49..02de29a98 100644 --- a/lib/src/visitor/async_evaluate.dart +++ b/lib/src/visitor/async_evaluate.dart @@ -2292,7 +2292,7 @@ class _EvaluateVisitor var arguments = [ for (var argument in node.arguments) await _visitCalculationValue(argument, - inMinMax: node.name == 'min' || node.name == 'max') + inMinMax: {'min', 'max', 'sqrt'}.contains(node.name)) ]; if (_inSupportsDeclaration) { return SassCalculation.unsimplified(node.name, arguments); @@ -2303,10 +2303,13 @@ class _EvaluateVisitor case "calc": assert(arguments.length == 1); return SassCalculation.calc(arguments[0]); + case "sqrt": + assert(arguments.length == 1); + return SassCalculation.sqrt(arguments[0]); case "min": return SassCalculation.min(arguments); case "max": - return SassCalculation.max(arguments); + return SassCalculation.min(arguments); case "clamp": return SassCalculation.clamp( arguments[0],