mirror of
https://github.com/danog/dart-sass.git
synced 2024-12-02 09:37:49 +01:00
Merge pull request #2067 from sass/revert-calc
Revert new calculation functions
This commit is contained in:
commit
e70cd5a0a0
12
CHANGELOG.md
12
CHANGELOG.md
@ -1,3 +1,15 @@
|
|||||||
|
## 1.66.0
|
||||||
|
|
||||||
|
* **Breaking change:** Drop support for the additional CSS calculations defined
|
||||||
|
in CSS Values and Units 4. Custom Sass functions whose names overlapped with
|
||||||
|
these new CSS functions were being parsed as CSS calculations instead, causing
|
||||||
|
an unintentional breaking change outside our normal [compatibility policy] for
|
||||||
|
CSS compatibility changes.
|
||||||
|
|
||||||
|
Support will be added again in a future version, but only after Sass has
|
||||||
|
emitted a deprecation warning for all functions that will break for at least
|
||||||
|
three months prior to the breakage.
|
||||||
|
|
||||||
## 1.65.1
|
## 1.65.1
|
||||||
|
|
||||||
* Update abs-percent deprecatedIn version to `1.65.0`.
|
* Update abs-percent deprecatedIn version to `1.65.0`.
|
||||||
|
@ -40,10 +40,6 @@ final class CalculationExpression implements Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a `hypot()` calculation expression.
|
|
||||||
CalculationExpression.hypot(Iterable<Expression> arguments, FileSpan span)
|
|
||||||
: this("hypot", arguments, span);
|
|
||||||
|
|
||||||
/// Returns a `max()` calculation expression.
|
/// Returns a `max()` calculation expression.
|
||||||
CalculationExpression.max(Iterable<Expression> arguments, this.span)
|
CalculationExpression.max(Iterable<Expression> arguments, this.span)
|
||||||
: name = "max",
|
: name = "max",
|
||||||
@ -53,76 +49,11 @@ final class CalculationExpression implements Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a `sqrt()` calculation expression.
|
|
||||||
CalculationExpression.sqrt(Expression argument, FileSpan span)
|
|
||||||
: this("sqrt", [argument], span);
|
|
||||||
|
|
||||||
/// Returns a `sin()` calculation expression.
|
|
||||||
CalculationExpression.sin(Expression argument, FileSpan span)
|
|
||||||
: this("sin", [argument], span);
|
|
||||||
|
|
||||||
/// Returns a `cos()` calculation expression.
|
|
||||||
CalculationExpression.cos(Expression argument, FileSpan span)
|
|
||||||
: this("cos", [argument], span);
|
|
||||||
|
|
||||||
/// Returns a `tan()` calculation expression.
|
|
||||||
CalculationExpression.tan(Expression argument, FileSpan span)
|
|
||||||
: this("tan", [argument], span);
|
|
||||||
|
|
||||||
/// Returns a `asin()` calculation expression.
|
|
||||||
CalculationExpression.asin(Expression argument, FileSpan span)
|
|
||||||
: this("asin", [argument], span);
|
|
||||||
|
|
||||||
/// Returns a `acos()` calculation expression.
|
|
||||||
CalculationExpression.acos(Expression argument, FileSpan span)
|
|
||||||
: this("acos", [argument], span);
|
|
||||||
|
|
||||||
/// Returns a `atan()` calculation expression.
|
|
||||||
CalculationExpression.atan(Expression argument, FileSpan span)
|
|
||||||
: this("atan", [argument], span);
|
|
||||||
|
|
||||||
/// Returns a `abs()` calculation expression.
|
|
||||||
CalculationExpression.abs(Expression argument, FileSpan span)
|
|
||||||
: this("abs", [argument], span);
|
|
||||||
|
|
||||||
/// Returns a `sign()` calculation expression.
|
|
||||||
CalculationExpression.sign(Expression argument, FileSpan span)
|
|
||||||
: this("sign", [argument], span);
|
|
||||||
|
|
||||||
/// Returns a `exp()` calculation expression.
|
|
||||||
CalculationExpression.exp(Expression argument, FileSpan span)
|
|
||||||
: this("exp", [argument], span);
|
|
||||||
|
|
||||||
/// Returns a `clamp()` calculation expression.
|
/// Returns a `clamp()` calculation expression.
|
||||||
CalculationExpression.clamp(
|
CalculationExpression.clamp(
|
||||||
Expression min, Expression value, Expression max, FileSpan span)
|
Expression min, Expression value, Expression max, FileSpan span)
|
||||||
: this("clamp", [min, max, value], span);
|
: this("clamp", [min, max, value], span);
|
||||||
|
|
||||||
/// Returns a `pow()` calculation expression.
|
|
||||||
CalculationExpression.pow(Expression base, Expression exponent, FileSpan span)
|
|
||||||
: this("pow", [base, exponent], span);
|
|
||||||
|
|
||||||
/// Returns a `log()` calculation expression.
|
|
||||||
CalculationExpression.log(Expression number, Expression base, FileSpan span)
|
|
||||||
: this("log", [number, base], span);
|
|
||||||
|
|
||||||
/// Returns a `round()` calculation expression.
|
|
||||||
CalculationExpression.round(
|
|
||||||
Expression strategy, Expression number, Expression step, FileSpan span)
|
|
||||||
: this("round", [strategy, number, step], span);
|
|
||||||
|
|
||||||
/// Returns a `atan2()` calculation expression.
|
|
||||||
CalculationExpression.atan2(Expression y, Expression x, FileSpan span)
|
|
||||||
: this("atan2", [y, x], span);
|
|
||||||
|
|
||||||
/// Returns a `mod()` calculation expression.
|
|
||||||
CalculationExpression.mod(Expression y, Expression x, FileSpan span)
|
|
||||||
: this("mod", [y, x], span);
|
|
||||||
|
|
||||||
/// Returns a `rem()` calculation expression.
|
|
||||||
CalculationExpression.rem(Expression y, Expression x, FileSpan span)
|
|
||||||
: this("rem", [y, x], span);
|
|
||||||
|
|
||||||
/// Returns a calculation expression with the given name and arguments.
|
/// Returns a calculation expression with the given name and arguments.
|
||||||
///
|
///
|
||||||
/// Unlike the other constructors, this doesn't verify that the arguments are
|
/// Unlike the other constructors, this doesn't verify that the arguments are
|
||||||
|
@ -12,22 +12,40 @@ import '../deprecation.dart';
|
|||||||
import '../evaluation_context.dart';
|
import '../evaluation_context.dart';
|
||||||
import '../exception.dart';
|
import '../exception.dart';
|
||||||
import '../module/built_in.dart';
|
import '../module/built_in.dart';
|
||||||
import '../util/number.dart';
|
|
||||||
import '../value.dart';
|
import '../value.dart';
|
||||||
|
|
||||||
/// The global definitions of Sass math functions.
|
/// The global definitions of Sass math functions.
|
||||||
final global = UnmodifiableListView([
|
final global = UnmodifiableListView([
|
||||||
_abs, _ceil, _floor, _max, _min, _percentage, _randomFunction, _round,
|
_function("abs", r"$number", (arguments) {
|
||||||
_unit, //
|
var number = arguments[0].assertNumber("number");
|
||||||
|
if (number.hasUnit("%")) {
|
||||||
|
warnForDeprecation(
|
||||||
|
"Passing percentage units to the global abs() function is "
|
||||||
|
"deprecated.\n"
|
||||||
|
"In the future, this will emit a CSS abs() function to be resolved "
|
||||||
|
"by the browser.\n"
|
||||||
|
"To preserve current behavior: math.abs($number)"
|
||||||
|
"\n"
|
||||||
|
"To emit a CSS abs() now: abs(#{$number})\n"
|
||||||
|
"More info: https://sass-lang.com/d/abs-percent",
|
||||||
|
Deprecation.absPercent);
|
||||||
|
}
|
||||||
|
return SassNumber.withUnits(number.value.abs(),
|
||||||
|
numeratorUnits: number.numeratorUnits,
|
||||||
|
denominatorUnits: number.denominatorUnits);
|
||||||
|
}),
|
||||||
|
|
||||||
|
_ceil, _floor, _max, _min, _percentage, _randomFunction, _round, _unit, //
|
||||||
_compatible.withName("comparable"),
|
_compatible.withName("comparable"),
|
||||||
_isUnitless.withName("unitless"),
|
_isUnitless.withName("unitless"),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/// The Sass math module.
|
/// The Sass math module.
|
||||||
final module = BuiltInModule("math", functions: <Callable>[
|
final module = BuiltInModule("math", functions: <Callable>[
|
||||||
_abs, _acos, _asin, _atan, _atan2, _ceil, _clamp, _cos, _compatible, //
|
_numberFunction("abs", (value) => value.abs()),
|
||||||
_floor, _hypot, _isUnitless, _log, _max, _min, _percentage, _pow, //
|
_acos, _asin, _atan, _atan2, _ceil, _clamp, _cos, _compatible, _floor, //
|
||||||
_randomFunction, _round, _sin, _sqrt, _tan, _unit, _div
|
_hypot, _isUnitless, _log, _max, _min, _percentage, _pow, _randomFunction,
|
||||||
|
_round, _sin, _sqrt, _tan, _unit, _div
|
||||||
], variables: {
|
], variables: {
|
||||||
"e": SassNumber(math.e),
|
"e": SassNumber(math.e),
|
||||||
"pi": SassNumber(math.pi),
|
"pi": SassNumber(math.pi),
|
||||||
@ -89,8 +107,6 @@ final _round = _numberFunction("round", (number) => number.round().toDouble());
|
|||||||
/// Distance functions
|
/// Distance functions
|
||||||
///
|
///
|
||||||
|
|
||||||
final _abs = _numberFunction("abs", (value) => value.abs());
|
|
||||||
|
|
||||||
final _hypot = _function("hypot", r"$numbers...", (arguments) {
|
final _hypot = _function("hypot", r"$numbers...", (arguments) {
|
||||||
var numbers =
|
var numbers =
|
||||||
arguments[0].asList.map((argument) => argument.assertNumber()).toList();
|
arguments[0].asList.map((argument) => argument.assertNumber()).toList();
|
||||||
@ -133,32 +149,87 @@ final _log = _function("log", r"$number, $base: null", (arguments) {
|
|||||||
final _pow = _function("pow", r"$base, $exponent", (arguments) {
|
final _pow = _function("pow", r"$base, $exponent", (arguments) {
|
||||||
var base = arguments[0].assertNumber("base");
|
var base = arguments[0].assertNumber("base");
|
||||||
var exponent = arguments[1].assertNumber("exponent");
|
var exponent = arguments[1].assertNumber("exponent");
|
||||||
return pow(base, exponent);
|
if (base.hasUnits) {
|
||||||
|
throw SassScriptException("\$base: Expected $base to have no units.");
|
||||||
|
} else if (exponent.hasUnits) {
|
||||||
|
throw SassScriptException(
|
||||||
|
"\$exponent: Expected $exponent to have no units.");
|
||||||
|
} else {
|
||||||
|
return SassNumber(math.pow(base.value, exponent.value));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
final _sqrt = _singleArgumentMathFunc("sqrt", sqrt);
|
final _sqrt = _function("sqrt", r"$number", (arguments) {
|
||||||
|
var number = arguments[0].assertNumber("number");
|
||||||
|
if (number.hasUnits) {
|
||||||
|
throw SassScriptException("\$number: Expected $number to have no units.");
|
||||||
|
} else {
|
||||||
|
return SassNumber(math.sqrt(number.value));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Trigonometric functions
|
/// Trigonometric functions
|
||||||
///
|
///
|
||||||
|
|
||||||
final _acos = _singleArgumentMathFunc("acos", acos);
|
final _acos = _function("acos", r"$number", (arguments) {
|
||||||
|
var number = arguments[0].assertNumber("number");
|
||||||
|
if (number.hasUnits) {
|
||||||
|
throw SassScriptException("\$number: Expected $number to have no units.");
|
||||||
|
} else {
|
||||||
|
return SassNumber.withUnits(math.acos(number.value) * 180 / math.pi,
|
||||||
|
numeratorUnits: ['deg']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
final _asin = _singleArgumentMathFunc("asin", asin);
|
final _asin = _function("asin", r"$number", (arguments) {
|
||||||
|
var number = arguments[0].assertNumber("number");
|
||||||
|
if (number.hasUnits) {
|
||||||
|
throw SassScriptException("\$number: Expected $number to have no units.");
|
||||||
|
} else {
|
||||||
|
return SassNumber.withUnits(math.asin(number.value) * 180 / math.pi,
|
||||||
|
numeratorUnits: ['deg']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
final _atan = _singleArgumentMathFunc("atan", atan);
|
final _atan = _function("atan", r"$number", (arguments) {
|
||||||
|
var number = arguments[0].assertNumber("number");
|
||||||
|
if (number.hasUnits) {
|
||||||
|
throw SassScriptException("\$number: Expected $number to have no units.");
|
||||||
|
} else {
|
||||||
|
return SassNumber.withUnits(math.atan(number.value) * 180 / math.pi,
|
||||||
|
numeratorUnits: ['deg']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
final _atan2 = _function("atan2", r"$y, $x", (arguments) {
|
final _atan2 = _function("atan2", r"$y, $x", (arguments) {
|
||||||
var y = arguments[0].assertNumber("y");
|
var y = arguments[0].assertNumber("y");
|
||||||
var x = arguments[1].assertNumber("x");
|
var x = arguments[1].assertNumber("x");
|
||||||
return atan2(y, x);
|
return SassNumber.withUnits(
|
||||||
|
math.atan2(y.value, x.convertValueToMatch(y, 'x', 'y')) * 180 / math.pi,
|
||||||
|
numeratorUnits: ['deg']);
|
||||||
});
|
});
|
||||||
|
|
||||||
final _cos = _singleArgumentMathFunc("cos", cos);
|
final _cos = _function(
|
||||||
|
"cos",
|
||||||
|
r"$number",
|
||||||
|
(arguments) => SassNumber(math.cos(arguments[0]
|
||||||
|
.assertNumber("number")
|
||||||
|
.coerceValueToUnit("rad", "number"))));
|
||||||
|
|
||||||
final _sin = _singleArgumentMathFunc("sin", sin);
|
final _sin = _function(
|
||||||
|
"sin",
|
||||||
|
r"$number",
|
||||||
|
(arguments) => SassNumber(math.sin(arguments[0]
|
||||||
|
.assertNumber("number")
|
||||||
|
.coerceValueToUnit("rad", "number"))));
|
||||||
|
|
||||||
final _tan = _singleArgumentMathFunc("tan", tan);
|
final _tan = _function(
|
||||||
|
"tan",
|
||||||
|
r"$number",
|
||||||
|
(arguments) => SassNumber(math.tan(arguments[0]
|
||||||
|
.assertNumber("number")
|
||||||
|
.coerceValueToUnit("rad", "number"))));
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Unit functions
|
/// Unit functions
|
||||||
@ -234,16 +305,6 @@ final _div = _function("div", r"$number1, $number2", (arguments) {
|
|||||||
/// Helpers
|
/// Helpers
|
||||||
///
|
///
|
||||||
|
|
||||||
/// Returns a [Callable] named [name] that calls a single argument
|
|
||||||
/// math function.
|
|
||||||
BuiltInCallable _singleArgumentMathFunc(
|
|
||||||
String name, SassNumber mathFunc(SassNumber value)) {
|
|
||||||
return _function(name, r"$number", (arguments) {
|
|
||||||
var number = arguments[0].assertNumber("number");
|
|
||||||
return mathFunc(number);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a [Callable] named [name] that transforms a number's value
|
/// Returns a [Callable] named [name] that transforms a number's value
|
||||||
/// using [transform] and preserves its units.
|
/// using [transform] and preserves its units.
|
||||||
BuiltInCallable _numberFunction(String name, double transform(double value)) {
|
BuiltInCallable _numberFunction(String name, double transform(double value)) {
|
||||||
|
@ -93,7 +93,7 @@ final JSClass calculationOperationClass = () {
|
|||||||
_assertCalculationValue(left);
|
_assertCalculationValue(left);
|
||||||
_assertCalculationValue(right);
|
_assertCalculationValue(right);
|
||||||
return SassCalculation.operateInternal(operator, left, right,
|
return SassCalculation.operateInternal(operator, left, right,
|
||||||
inLegacySassFunction: false, simplify: false);
|
inMinMax: false, simplify: false);
|
||||||
});
|
});
|
||||||
|
|
||||||
jsClass.defineMethods({
|
jsClass.defineMethods({
|
||||||
@ -109,7 +109,7 @@ final JSClass calculationOperationClass = () {
|
|||||||
|
|
||||||
getJSClass(SassCalculation.operateInternal(
|
getJSClass(SassCalculation.operateInternal(
|
||||||
CalculationOperator.plus, SassNumber(1), SassNumber(1),
|
CalculationOperator.plus, SassNumber(1), SassNumber(1),
|
||||||
inLegacySassFunction: false, simplify: false))
|
inMinMax: false, simplify: false))
|
||||||
.injectSuperclass(jsClass);
|
.injectSuperclass(jsClass);
|
||||||
return jsClass;
|
return jsClass;
|
||||||
}();
|
}();
|
||||||
|
@ -2065,8 +2065,7 @@ abstract class StylesheetParser extends Parser {
|
|||||||
/// produces a potentially slash-separated number.
|
/// produces a potentially slash-separated number.
|
||||||
bool _isSlashOperand(Expression expression) =>
|
bool _isSlashOperand(Expression expression) =>
|
||||||
expression is NumberExpression ||
|
expression is NumberExpression ||
|
||||||
(expression is CalculationExpression &&
|
expression is CalculationExpression ||
|
||||||
!{'min', 'max', 'round', 'abs'}.contains(expression.name)) ||
|
|
||||||
(expression is BinaryOperationExpression && expression.allowsSlash);
|
(expression is BinaryOperationExpression && expression.allowsSlash);
|
||||||
|
|
||||||
/// Consumes an expression that doesn't contain any top-level whitespace.
|
/// Consumes an expression that doesn't contain any top-level whitespace.
|
||||||
@ -2653,64 +2652,32 @@ abstract class StylesheetParser extends Parser {
|
|||||||
assert(scanner.peekChar() == $lparen);
|
assert(scanner.peekChar() == $lparen);
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "calc":
|
case "calc":
|
||||||
case "sqrt":
|
|
||||||
case "sin":
|
|
||||||
case "cos":
|
|
||||||
case "tan":
|
|
||||||
case "asin":
|
|
||||||
case "acos":
|
|
||||||
case "atan":
|
|
||||||
case "exp":
|
|
||||||
case "sign":
|
|
||||||
var arguments = _calculationArguments(1);
|
var arguments = _calculationArguments(1);
|
||||||
return CalculationExpression(name, arguments, scanner.spanFrom(start));
|
return CalculationExpression(name, arguments, scanner.spanFrom(start));
|
||||||
|
|
||||||
case "abs":
|
|
||||||
return _tryArgumentsCalculation(name, start, 1);
|
|
||||||
|
|
||||||
case "hypot":
|
|
||||||
var arguments = _calculationArguments();
|
|
||||||
return CalculationExpression(name, arguments, scanner.spanFrom(start));
|
|
||||||
|
|
||||||
case "min" || "max":
|
case "min" || "max":
|
||||||
// min() and max() are parsed as calculations if possible, and otherwise
|
// min() and max() are parsed as calculations if possible, and otherwise
|
||||||
// are parsed as normal Sass functions.
|
// are parsed as normal Sass functions.
|
||||||
return _tryArgumentsCalculation(name, start, null);
|
var beforeArguments = scanner.state;
|
||||||
|
List<Expression> arguments;
|
||||||
|
try {
|
||||||
|
arguments = _calculationArguments();
|
||||||
|
} on FormatException catch (_) {
|
||||||
|
scanner.state = beforeArguments;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
case "pow":
|
|
||||||
case "log":
|
|
||||||
case "atan2":
|
|
||||||
case "mod":
|
|
||||||
case "rem":
|
|
||||||
var arguments = _calculationArguments(2);
|
|
||||||
return CalculationExpression(name, arguments, scanner.spanFrom(start));
|
return CalculationExpression(name, arguments, scanner.spanFrom(start));
|
||||||
|
|
||||||
case "clamp":
|
case "clamp":
|
||||||
var arguments = _calculationArguments(3);
|
var arguments = _calculationArguments(3);
|
||||||
return CalculationExpression(name, arguments, scanner.spanFrom(start));
|
return CalculationExpression(name, arguments, scanner.spanFrom(start));
|
||||||
|
|
||||||
case "round":
|
|
||||||
return _tryArgumentsCalculation(name, start, 3);
|
|
||||||
|
|
||||||
case _:
|
case _:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a CalculationExpression if the function can be parsed as a calculation,
|
|
||||||
// otherwise, returns null and the function is parsed as a normal Sass function.
|
|
||||||
CalculationExpression? _tryArgumentsCalculation(
|
|
||||||
String name, LineScannerState start, int? maxArgs) {
|
|
||||||
var beforeArguments = scanner.state;
|
|
||||||
try {
|
|
||||||
var arguments = _calculationArguments(maxArgs);
|
|
||||||
return CalculationExpression(name, arguments, scanner.spanFrom(start));
|
|
||||||
} on FormatException catch (_) {
|
|
||||||
scanner.state = beforeArguments;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Consumes and returns arguments for a calculation expression, including the
|
/// Consumes and returns arguments for a calculation expression, including the
|
||||||
/// opening and closing parentheses.
|
/// opening and closing parentheses.
|
||||||
///
|
///
|
||||||
|
@ -110,7 +110,6 @@ double fuzzyAssertRange(double number, int min, int max, [String? name]) {
|
|||||||
///
|
///
|
||||||
/// [floored division]: https://en.wikipedia.org/wiki/Modulo_operation#Variants_of_the_definition
|
/// [floored division]: https://en.wikipedia.org/wiki/Modulo_operation#Variants_of_the_definition
|
||||||
double moduloLikeSass(double num1, double num2) {
|
double moduloLikeSass(double num1, double num2) {
|
||||||
if (num2.isInfinite && num1.sign != num2.sign) return double.nan;
|
|
||||||
if (num2 > 0) return num1 % num2;
|
if (num2 > 0) return num1 % num2;
|
||||||
if (num2 == 0) return double.nan;
|
if (num2 == 0) return double.nan;
|
||||||
|
|
||||||
@ -119,78 +118,3 @@ double moduloLikeSass(double num1, double num2) {
|
|||||||
var result = num1 % num2;
|
var result = num1 % num2;
|
||||||
return result == 0 ? 0 : result + num2;
|
return result == 0 ? 0 : result + num2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the square root of [number].
|
|
||||||
SassNumber sqrt(SassNumber number) {
|
|
||||||
number.assertNoUnits("number");
|
|
||||||
return SassNumber(math.sqrt(number.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the sine of [number].
|
|
||||||
SassNumber sin(SassNumber number) =>
|
|
||||||
SassNumber(math.sin(number.coerceValueToUnit("rad", "number")));
|
|
||||||
|
|
||||||
/// Returns the cosine of [number].
|
|
||||||
SassNumber cos(SassNumber number) =>
|
|
||||||
SassNumber(math.cos(number.coerceValueToUnit("rad", "number")));
|
|
||||||
|
|
||||||
/// Returns the tangent of [number].
|
|
||||||
SassNumber tan(SassNumber number) =>
|
|
||||||
SassNumber(math.tan(number.coerceValueToUnit("rad", "number")));
|
|
||||||
|
|
||||||
/// Returns the arctangent of [number].
|
|
||||||
SassNumber atan(SassNumber number) {
|
|
||||||
number.assertNoUnits("number");
|
|
||||||
return SassNumber.withUnits(math.atan(number.value) * 180 / math.pi,
|
|
||||||
numeratorUnits: ['deg']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the arcsine of [number].
|
|
||||||
SassNumber asin(SassNumber number) {
|
|
||||||
number.assertNoUnits("number");
|
|
||||||
return SassNumber.withUnits(math.asin(number.value) * 180 / math.pi,
|
|
||||||
numeratorUnits: ['deg']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the arccosine of [number]
|
|
||||||
SassNumber acos(SassNumber number) {
|
|
||||||
number.assertNoUnits("number");
|
|
||||||
return SassNumber.withUnits(math.acos(number.value) * 180 / math.pi,
|
|
||||||
numeratorUnits: ['deg']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the absolute value of [number].
|
|
||||||
SassNumber abs(SassNumber number) =>
|
|
||||||
SassNumber(number.value.abs()).coerceToMatch(number);
|
|
||||||
|
|
||||||
/// Returns the logarithm of [number] with respect to [base].
|
|
||||||
SassNumber log(SassNumber number, SassNumber? base) {
|
|
||||||
if (base != null) {
|
|
||||||
return SassNumber(math.log(number.value) / math.log(base.value));
|
|
||||||
}
|
|
||||||
return SassNumber(math.log(number.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the value of [base] raised to the power of [exponent].
|
|
||||||
SassNumber pow(SassNumber base, SassNumber exponent) {
|
|
||||||
base.assertNoUnits("base");
|
|
||||||
exponent.assertNoUnits("exponent");
|
|
||||||
return SassNumber(math.pow(base.value, exponent.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the arctangent for [y] and [x].
|
|
||||||
SassNumber atan2(SassNumber y, SassNumber x) {
|
|
||||||
return SassNumber.withUnits(
|
|
||||||
math.atan2(y.value, x.convertValueToMatch(y, 'x', 'y')) * 180 / math.pi,
|
|
||||||
numeratorUnits: ['deg']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extension methods to get the sign of the double's numerical value,
|
|
||||||
/// including positive and negative zero.
|
|
||||||
extension DoubleWithSignedZero on double {
|
|
||||||
double get signIncludingZero {
|
|
||||||
if (identical(this, -0.0)) return -1.0;
|
|
||||||
if (this == 0) return 1.0;
|
|
||||||
return sign;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -2,16 +2,11 @@
|
|||||||
// MIT-style license that can be found in the LICENSE file or at
|
// MIT-style license that can be found in the LICENSE file or at
|
||||||
// https://opensource.org/licenses/MIT.
|
// https://opensource.org/licenses/MIT.
|
||||||
|
|
||||||
import 'dart:math' as math;
|
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
import '../deprecation.dart';
|
|
||||||
import '../evaluation_context.dart';
|
|
||||||
import '../exception.dart';
|
import '../exception.dart';
|
||||||
import '../callable.dart';
|
|
||||||
import '../util/nullable.dart';
|
import '../util/nullable.dart';
|
||||||
import '../util/number.dart' as number_lib;
|
import '../util/number.dart';
|
||||||
import '../utils.dart';
|
import '../utils.dart';
|
||||||
import '../value.dart';
|
import '../value.dart';
|
||||||
import '../visitor/interface/value.dart';
|
import '../visitor/interface/value.dart';
|
||||||
@ -124,187 +119,6 @@ final class SassCalculation extends Value {
|
|||||||
return SassCalculation._("max", args);
|
return SassCalculation._("max", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `hypot()` calculation with the given [arguments].
|
|
||||||
///
|
|
||||||
/// 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 hypot(Iterable<Object> arguments) {
|
|
||||||
var args = _simplifyArguments(arguments);
|
|
||||||
if (args.isEmpty) {
|
|
||||||
throw ArgumentError("hypot() must have at least one argument.");
|
|
||||||
}
|
|
||||||
_verifyCompatibleNumbers(args);
|
|
||||||
|
|
||||||
var subtotal = 0.0;
|
|
||||||
var first = args.first;
|
|
||||||
if (first is! SassNumber || first.hasUnit('%')) {
|
|
||||||
return SassCalculation._("hypot", args);
|
|
||||||
}
|
|
||||||
for (var i = 0; i < args.length; i++) {
|
|
||||||
var number = args.elementAt(i);
|
|
||||||
if (number is! SassNumber || !number.hasCompatibleUnits(first)) {
|
|
||||||
return SassCalculation._("hypot", args);
|
|
||||||
}
|
|
||||||
var value =
|
|
||||||
number.convertValueToMatch(first, "numbers[${i + 1}]", "numbers[1]");
|
|
||||||
subtotal += value * value;
|
|
||||||
}
|
|
||||||
return SassNumber.withUnits(math.sqrt(subtotal),
|
|
||||||
numeratorUnits: first.numeratorUnits,
|
|
||||||
denominatorUnits: first.denominatorUnits);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a `sqrt()` calculation with the given [argument].
|
|
||||||
///
|
|
||||||
/// The [argument] must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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) =>
|
|
||||||
_singleArgument("sqrt", argument, number_lib.sqrt, forbidUnits: true);
|
|
||||||
|
|
||||||
/// Creates a `sin()` calculation with the given [argument].
|
|
||||||
///
|
|
||||||
/// The [argument] must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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 sin(Object argument) =>
|
|
||||||
_singleArgument("sin", argument, number_lib.sin);
|
|
||||||
|
|
||||||
/// Creates a `cos()` calculation with the given [argument].
|
|
||||||
///
|
|
||||||
/// The [argument] must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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 cos(Object argument) =>
|
|
||||||
_singleArgument("cos", argument, number_lib.cos);
|
|
||||||
|
|
||||||
/// Creates a `tan()` calculation with the given [argument].
|
|
||||||
///
|
|
||||||
/// The [argument] must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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 tan(Object argument) =>
|
|
||||||
_singleArgument("tan", argument, number_lib.tan);
|
|
||||||
|
|
||||||
/// Creates an `atan()` calculation with the given [argument].
|
|
||||||
///
|
|
||||||
/// The [argument] must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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 atan(Object argument) =>
|
|
||||||
_singleArgument("atan", argument, number_lib.atan, forbidUnits: true);
|
|
||||||
|
|
||||||
/// Creates an `asin()` calculation with the given [argument].
|
|
||||||
///
|
|
||||||
/// The [argument] must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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 asin(Object argument) =>
|
|
||||||
_singleArgument("asin", argument, number_lib.asin, forbidUnits: true);
|
|
||||||
|
|
||||||
/// Creates an `acos()` calculation with the given [argument].
|
|
||||||
///
|
|
||||||
/// The [argument] must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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 acos(Object argument) =>
|
|
||||||
_singleArgument("acos", argument, number_lib.acos, forbidUnits: true);
|
|
||||||
|
|
||||||
/// Creates an `abs()` calculation with the given [argument].
|
|
||||||
///
|
|
||||||
/// The [argument] must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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 abs(Object argument) {
|
|
||||||
argument = _simplify(argument);
|
|
||||||
if (argument is! SassNumber) return SassCalculation._("abs", [argument]);
|
|
||||||
if (argument.hasUnit("%")) {
|
|
||||||
warnForDeprecation(
|
|
||||||
"Passing percentage units to the global abs() function is deprecated.\n"
|
|
||||||
"In the future, this will emit a CSS abs() function to be resolved by the browser.\n"
|
|
||||||
"To preserve current behavior: math.abs($argument)"
|
|
||||||
"\n"
|
|
||||||
"To emit a CSS abs() now: abs(#{$argument})\n"
|
|
||||||
"More info: https://sass-lang.com/d/abs-percent",
|
|
||||||
Deprecation.absPercent);
|
|
||||||
}
|
|
||||||
return number_lib.abs(argument);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an `exp()` calculation with the given [argument].
|
|
||||||
///
|
|
||||||
/// The [argument] must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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 exp(Object argument) {
|
|
||||||
argument = _simplify(argument);
|
|
||||||
if (argument is! SassNumber) {
|
|
||||||
return SassCalculation._("exp", [argument]);
|
|
||||||
}
|
|
||||||
argument.assertNoUnits();
|
|
||||||
return number_lib.pow(SassNumber(math.e), argument);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a `sign()` calculation with the given [argument].
|
|
||||||
///
|
|
||||||
/// The [argument] must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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 sign(Object argument) {
|
|
||||||
argument = _simplify(argument);
|
|
||||||
return switch (argument) {
|
|
||||||
SassNumber(value: double(isNaN: true) || 0) => argument,
|
|
||||||
SassNumber arg when !arg.hasUnit('%') =>
|
|
||||||
SassNumber(arg.value.sign).coerceToMatch(argument),
|
|
||||||
_ => SassCalculation._("sign", [argument]),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a `clamp()` calculation with the given [min], [value], and [max].
|
/// Creates a `clamp()` calculation with the given [min], [value], and [max].
|
||||||
///
|
///
|
||||||
/// Each argument must be either a [SassNumber], a [SassCalculation], an
|
/// Each argument must be either a [SassNumber], a [SassCalculation], an
|
||||||
@ -343,255 +157,6 @@ final class SassCalculation extends Value {
|
|||||||
return SassCalculation._("clamp", args);
|
return SassCalculation._("clamp", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `pow()` calculation with the given [base] and [exponent].
|
|
||||||
///
|
|
||||||
/// Each argument must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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.
|
|
||||||
///
|
|
||||||
/// This may be passed fewer than two arguments, but only if one of the
|
|
||||||
/// arguments is an unquoted `var()` string.
|
|
||||||
static Value pow(Object base, Object? exponent) {
|
|
||||||
var args = [base, if (exponent != null) exponent];
|
|
||||||
_verifyLength(args, 2);
|
|
||||||
base = _simplify(base);
|
|
||||||
exponent = exponent.andThen(_simplify);
|
|
||||||
if (base is! SassNumber || exponent is! SassNumber) {
|
|
||||||
return SassCalculation._("pow", args);
|
|
||||||
}
|
|
||||||
base.assertNoUnits();
|
|
||||||
exponent.assertNoUnits();
|
|
||||||
return number_lib.pow(base, exponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a `log()` calculation with the given [number] and [base].
|
|
||||||
///
|
|
||||||
/// Each argument must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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.
|
|
||||||
///
|
|
||||||
/// If arguments contains exactly a single argument,
|
|
||||||
/// the base is set to `math.e` by default.
|
|
||||||
static Value log(Object number, Object? base) {
|
|
||||||
number = _simplify(number);
|
|
||||||
base = base.andThen(_simplify);
|
|
||||||
var args = [number, if (base != null) base];
|
|
||||||
if (number is! SassNumber || (base != null && base is! SassNumber)) {
|
|
||||||
return SassCalculation._("log", args);
|
|
||||||
}
|
|
||||||
number.assertNoUnits();
|
|
||||||
if (base is SassNumber) {
|
|
||||||
base.assertNoUnits();
|
|
||||||
return number_lib.log(number, base);
|
|
||||||
}
|
|
||||||
return number_lib.log(number, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a `atan2()` calculation for [y] and [x].
|
|
||||||
///
|
|
||||||
/// Each argument must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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.
|
|
||||||
///
|
|
||||||
/// This may be passed fewer than two arguments, but only if one of the
|
|
||||||
/// arguments is an unquoted `var()` string.
|
|
||||||
static Value atan2(Object y, Object? x) {
|
|
||||||
y = _simplify(y);
|
|
||||||
x = x.andThen(_simplify);
|
|
||||||
var args = [y, if (x != null) x];
|
|
||||||
_verifyLength(args, 2);
|
|
||||||
_verifyCompatibleNumbers(args);
|
|
||||||
if (y is! SassNumber ||
|
|
||||||
x is! SassNumber ||
|
|
||||||
y.hasUnit('%') ||
|
|
||||||
x.hasUnit('%') ||
|
|
||||||
!y.hasCompatibleUnits(x)) {
|
|
||||||
return SassCalculation._("atan2", args);
|
|
||||||
}
|
|
||||||
return number_lib.atan2(y, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a `rem()` calculation with the given [dividend] and [modulus].
|
|
||||||
///
|
|
||||||
/// Each argument must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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.
|
|
||||||
///
|
|
||||||
/// This may be passed fewer than two arguments, but only if one of the
|
|
||||||
/// arguments is an unquoted `var()` string.
|
|
||||||
static Value rem(Object dividend, Object? modulus) {
|
|
||||||
dividend = _simplify(dividend);
|
|
||||||
modulus = modulus.andThen(_simplify);
|
|
||||||
var args = [dividend, if (modulus != null) modulus];
|
|
||||||
_verifyLength(args, 2);
|
|
||||||
_verifyCompatibleNumbers(args);
|
|
||||||
if (dividend is! SassNumber ||
|
|
||||||
modulus is! SassNumber ||
|
|
||||||
!dividend.hasCompatibleUnits(modulus)) {
|
|
||||||
return SassCalculation._("rem", args);
|
|
||||||
}
|
|
||||||
var result = dividend.modulo(modulus);
|
|
||||||
if (modulus.value.signIncludingZero != dividend.value.signIncludingZero) {
|
|
||||||
if (modulus.value.isInfinite) return dividend;
|
|
||||||
if (result.value == 0) {
|
|
||||||
return result.unaryMinus();
|
|
||||||
}
|
|
||||||
return result.minus(modulus);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a `mod()` calculation with the given [dividend] and [modulus].
|
|
||||||
///
|
|
||||||
/// Each argument must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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.
|
|
||||||
///
|
|
||||||
/// This may be passed fewer than two arguments, but only if one of the
|
|
||||||
/// arguments is an unquoted `var()` string.
|
|
||||||
static Value mod(Object dividend, Object? modulus) {
|
|
||||||
dividend = _simplify(dividend);
|
|
||||||
modulus = modulus.andThen(_simplify);
|
|
||||||
var args = [dividend, if (modulus != null) modulus];
|
|
||||||
_verifyLength(args, 2);
|
|
||||||
_verifyCompatibleNumbers(args);
|
|
||||||
if (dividend is! SassNumber ||
|
|
||||||
modulus is! SassNumber ||
|
|
||||||
!dividend.hasCompatibleUnits(modulus)) {
|
|
||||||
return SassCalculation._("mod", args);
|
|
||||||
}
|
|
||||||
return dividend.modulo(modulus);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a `round()` calculation with the given [strategyOrNumber], [numberOrStep], and [step].
|
|
||||||
/// Strategy must be either nearest, up, down or to-zero.
|
|
||||||
///
|
|
||||||
/// Number and step must be either a [SassNumber], a [SassCalculation], an
|
|
||||||
/// unquoted [SassString], a [CalculationOperation], or a
|
|
||||||
/// [CalculationInterpolation].
|
|
||||||
///
|
|
||||||
/// 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.
|
|
||||||
///
|
|
||||||
/// This may be passed fewer than two arguments, but only if one of the
|
|
||||||
/// arguments is an unquoted `var()` string.
|
|
||||||
static Value round(Object strategyOrNumber,
|
|
||||||
[Object? numberOrStep, Object? step]) {
|
|
||||||
switch ((
|
|
||||||
_simplify(strategyOrNumber),
|
|
||||||
numberOrStep.andThen(_simplify),
|
|
||||||
step.andThen(_simplify)
|
|
||||||
)) {
|
|
||||||
case (SassNumber number, null, null):
|
|
||||||
return _matchUnits(number.value.round().toDouble(), number);
|
|
||||||
|
|
||||||
case (SassNumber number, SassNumber step, null)
|
|
||||||
when !number.hasCompatibleUnits(step):
|
|
||||||
_verifyCompatibleNumbers([number, step]);
|
|
||||||
return SassCalculation._("round", [number, step]);
|
|
||||||
|
|
||||||
case (SassNumber number, SassNumber step, null):
|
|
||||||
_verifyCompatibleNumbers([number, step]);
|
|
||||||
return _roundWithStep('nearest', number, step);
|
|
||||||
|
|
||||||
case (
|
|
||||||
SassString(text: 'nearest' || 'up' || 'down' || 'to-zero') &&
|
|
||||||
var strategy,
|
|
||||||
SassNumber number,
|
|
||||||
SassNumber step
|
|
||||||
)
|
|
||||||
when !number.hasCompatibleUnits(step):
|
|
||||||
_verifyCompatibleNumbers([number, step]);
|
|
||||||
return SassCalculation._("round", [strategy, number, step]);
|
|
||||||
|
|
||||||
case (
|
|
||||||
SassString(text: 'nearest' || 'up' || 'down' || 'to-zero') &&
|
|
||||||
var strategy,
|
|
||||||
SassNumber number,
|
|
||||||
SassNumber step
|
|
||||||
):
|
|
||||||
_verifyCompatibleNumbers([number, step]);
|
|
||||||
return _roundWithStep(strategy.text, number, step);
|
|
||||||
|
|
||||||
case (
|
|
||||||
SassString(text: 'nearest' || 'up' || 'down' || 'to-zero') &&
|
|
||||||
var strategy,
|
|
||||||
(SassString() || CalculationInterpolation()) && var rest?,
|
|
||||||
null
|
|
||||||
):
|
|
||||||
return SassCalculation._("round", [strategy, rest]);
|
|
||||||
|
|
||||||
case (
|
|
||||||
SassString(text: 'nearest' || 'up' || 'down' || 'to-zero'),
|
|
||||||
_?,
|
|
||||||
null
|
|
||||||
):
|
|
||||||
throw SassScriptException("If strategy is not null, step is required.");
|
|
||||||
|
|
||||||
case (
|
|
||||||
SassString(text: 'nearest' || 'up' || 'down' || 'to-zero'),
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
):
|
|
||||||
throw SassScriptException(
|
|
||||||
"Number to round and step arguments are required.");
|
|
||||||
|
|
||||||
case (
|
|
||||||
(SassString() || CalculationInterpolation()) && var rest,
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
):
|
|
||||||
return SassCalculation._("round", [rest]);
|
|
||||||
|
|
||||||
case (var number, null, null):
|
|
||||||
throw SassScriptException(
|
|
||||||
"Single argument $number expected to be simplifiable.");
|
|
||||||
|
|
||||||
case (var number, var step?, null):
|
|
||||||
return SassCalculation._("round", [number, step]);
|
|
||||||
|
|
||||||
case (
|
|
||||||
(SassString(text: 'nearest' || 'up' || 'down' || 'to-zero') ||
|
|
||||||
SassString(isVar: true)) &&
|
|
||||||
var strategy,
|
|
||||||
var number?,
|
|
||||||
var step?
|
|
||||||
):
|
|
||||||
return SassCalculation._("round", [strategy, number, step]);
|
|
||||||
|
|
||||||
case (_, _?, _?):
|
|
||||||
throw SassScriptException(
|
|
||||||
"$strategyOrNumber must be either nearest, up, down or to-zero.");
|
|
||||||
|
|
||||||
case (_, null, _?):
|
|
||||||
// TODO(pamelalozano): Get rid of this case once dart-lang/sdk#52908 is solved.
|
|
||||||
// ignore: unreachable_switch_case
|
|
||||||
case (_, _, _):
|
|
||||||
throw SassScriptException("Invalid parameters.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates and simplifies a [CalculationOperation] with the given [operator],
|
/// Creates and simplifies a [CalculationOperation] with the given [operator],
|
||||||
/// [left], and [right].
|
/// [left], and [right].
|
||||||
///
|
///
|
||||||
@ -603,12 +168,11 @@ final class SassCalculation extends Value {
|
|||||||
/// a [CalculationInterpolation].
|
/// a [CalculationInterpolation].
|
||||||
static Object operate(
|
static Object operate(
|
||||||
CalculationOperator operator, Object left, Object right) =>
|
CalculationOperator operator, Object left, Object right) =>
|
||||||
operateInternal(operator, left, right,
|
operateInternal(operator, left, right, inMinMax: false, simplify: true);
|
||||||
inLegacySassFunction: false, simplify: true);
|
|
||||||
|
|
||||||
/// Like [operate], but with the internal-only [inLegacySassFunction] parameter.
|
/// Like [operate], but with the internal-only [inMinMax] parameter.
|
||||||
///
|
///
|
||||||
/// If [inLegacySassFunction] is `true`, this allows unitless numbers to be added and
|
/// If [inMinMax] is `true`, this allows unitless numbers to be added and
|
||||||
/// subtracted with numbers with units, for backwards-compatibility with the
|
/// subtracted with numbers with units, for backwards-compatibility with the
|
||||||
/// old global `min()` and `max()` functions.
|
/// old global `min()` and `max()` functions.
|
||||||
///
|
///
|
||||||
@ -616,7 +180,7 @@ final class SassCalculation extends Value {
|
|||||||
@internal
|
@internal
|
||||||
static Object operateInternal(
|
static Object operateInternal(
|
||||||
CalculationOperator operator, Object left, Object right,
|
CalculationOperator operator, Object left, Object right,
|
||||||
{required bool inLegacySassFunction, required bool simplify}) {
|
{required bool inMinMax, required bool simplify}) {
|
||||||
if (!simplify) return CalculationOperation._(operator, left, right);
|
if (!simplify) return CalculationOperation._(operator, left, right);
|
||||||
left = _simplify(left);
|
left = _simplify(left);
|
||||||
right = _simplify(right);
|
right = _simplify(right);
|
||||||
@ -624,7 +188,7 @@ final class SassCalculation extends Value {
|
|||||||
if (operator case CalculationOperator.plus || CalculationOperator.minus) {
|
if (operator case CalculationOperator.plus || CalculationOperator.minus) {
|
||||||
if (left is SassNumber &&
|
if (left is SassNumber &&
|
||||||
right is SassNumber &&
|
right is SassNumber &&
|
||||||
(inLegacySassFunction
|
(inMinMax
|
||||||
? left.isComparableTo(right)
|
? left.isComparableTo(right)
|
||||||
: left.hasCompatibleUnits(right))) {
|
: left.hasCompatibleUnits(right))) {
|
||||||
return operator == CalculationOperator.plus
|
return operator == CalculationOperator.plus
|
||||||
@ -634,7 +198,7 @@ final class SassCalculation extends Value {
|
|||||||
|
|
||||||
_verifyCompatibleNumbers([left, right]);
|
_verifyCompatibleNumbers([left, right]);
|
||||||
|
|
||||||
if (right is SassNumber && number_lib.fuzzyLessThan(right.value, 0)) {
|
if (right is SassNumber && fuzzyLessThan(right.value, 0)) {
|
||||||
right = right.times(SassNumber(-1));
|
right = right.times(SassNumber(-1));
|
||||||
operator = operator == CalculationOperator.plus
|
operator = operator == CalculationOperator.plus
|
||||||
? CalculationOperator.minus
|
? CalculationOperator.minus
|
||||||
@ -655,70 +219,6 @@ final class SassCalculation extends Value {
|
|||||||
/// simplification.
|
/// simplification.
|
||||||
SassCalculation._(this.name, this.arguments);
|
SassCalculation._(this.name, this.arguments);
|
||||||
|
|
||||||
// Returns [value] coerced to [number]'s units.
|
|
||||||
static SassNumber _matchUnits(double value, SassNumber number) =>
|
|
||||||
SassNumber.withUnits(value,
|
|
||||||
numeratorUnits: number.numeratorUnits,
|
|
||||||
denominatorUnits: number.denominatorUnits);
|
|
||||||
|
|
||||||
/// Returns a rounded [number] based on a selected rounding [strategy],
|
|
||||||
/// to the nearest integer multiple of [step].
|
|
||||||
static SassNumber _roundWithStep(
|
|
||||||
String strategy, SassNumber number, SassNumber step) {
|
|
||||||
if (!{'nearest', 'up', 'down', 'to-zero'}.contains(strategy)) {
|
|
||||||
throw ArgumentError(
|
|
||||||
"$strategy must be either nearest, up, down or to-zero.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (number.value.isInfinite && step.value.isInfinite ||
|
|
||||||
step.value == 0 ||
|
|
||||||
number.value.isNaN ||
|
|
||||||
step.value.isNaN) {
|
|
||||||
return _matchUnits(double.nan, number);
|
|
||||||
}
|
|
||||||
if (number.value.isInfinite) return number;
|
|
||||||
|
|
||||||
if (step.value.isInfinite) {
|
|
||||||
return switch ((strategy, number.value)) {
|
|
||||||
(_, 0) => number,
|
|
||||||
('nearest' || 'to-zero', > 0) => _matchUnits(0.0, number),
|
|
||||||
('nearest' || 'to-zero', _) => _matchUnits(-0.0, number),
|
|
||||||
('up', > 0) => _matchUnits(double.infinity, number),
|
|
||||||
('up', _) => _matchUnits(-0.0, number),
|
|
||||||
('down', < 0) => _matchUnits(-double.infinity, number),
|
|
||||||
('down', _) => _matchUnits(0, number),
|
|
||||||
(_, _) => throw UnsupportedError("Invalid argument: $strategy.")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var stepWithNumberUnit = step.convertValueToMatch(number);
|
|
||||||
return switch (strategy) {
|
|
||||||
'nearest' => _matchUnits(
|
|
||||||
(number.value / stepWithNumberUnit).round() * stepWithNumberUnit,
|
|
||||||
number),
|
|
||||||
'up' => _matchUnits(
|
|
||||||
(step.value < 0
|
|
||||||
? (number.value / stepWithNumberUnit).floor()
|
|
||||||
: (number.value / stepWithNumberUnit).ceil()) *
|
|
||||||
stepWithNumberUnit,
|
|
||||||
number),
|
|
||||||
'down' => _matchUnits(
|
|
||||||
(step.value < 0
|
|
||||||
? (number.value / stepWithNumberUnit).ceil()
|
|
||||||
: (number.value / stepWithNumberUnit).floor()) *
|
|
||||||
stepWithNumberUnit,
|
|
||||||
number),
|
|
||||||
'to-zero' => number.value < 0
|
|
||||||
? _matchUnits(
|
|
||||||
(number.value / stepWithNumberUnit).ceil() * stepWithNumberUnit,
|
|
||||||
number)
|
|
||||||
: _matchUnits(
|
|
||||||
(number.value / stepWithNumberUnit).floor() * stepWithNumberUnit,
|
|
||||||
number),
|
|
||||||
_ => _matchUnits(double.nan, number)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an unmodifiable list of [args], with each argument simplified.
|
/// Returns an unmodifiable list of [args], with each argument simplified.
|
||||||
static List<Object> _simplifyArguments(Iterable<Object> args) =>
|
static List<Object> _simplifyArguments(Iterable<Object> args) =>
|
||||||
List.unmodifiable(args.map(_simplify));
|
List.unmodifiable(args.map(_simplify));
|
||||||
@ -779,21 +279,6 @@ final class SassCalculation extends Value {
|
|||||||
"${pluralize('was', args.length, plural: 'were')} passed.");
|
"${pluralize('was', args.length, plural: 'were')} passed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a [Callable] named [name] that calls a single argument
|
|
||||||
/// math function.
|
|
||||||
///
|
|
||||||
/// If [forbidUnits] is `true` it will throw an error if [argument] has units.
|
|
||||||
static Value _singleArgument(
|
|
||||||
String name, Object argument, SassNumber mathFunc(SassNumber value),
|
|
||||||
{bool forbidUnits = false}) {
|
|
||||||
argument = _simplify(argument);
|
|
||||||
if (argument is! SassNumber) {
|
|
||||||
return SassCalculation._(name, [argument]);
|
|
||||||
}
|
|
||||||
if (forbidUnits) argument.assertNoUnits();
|
|
||||||
return mathFunc(argument);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@internal
|
@internal
|
||||||
T accept<T>(ValueVisitor<T> visitor) => visitor.visitCalculation(this);
|
T accept<T>(ValueVisitor<T> visitor) => visitor.visitCalculation(this);
|
||||||
|
@ -710,7 +710,7 @@ abstract class SassNumber extends Value {
|
|||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@internal
|
@internal
|
||||||
SassNumber modulo(Value other) {
|
Value modulo(Value other) {
|
||||||
if (other is SassNumber) {
|
if (other is SassNumber) {
|
||||||
return withValue(_coerceUnits(other, moduloLikeSass));
|
return withValue(_coerceUnits(other, moduloLikeSass));
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ class UnitlessSassNumber extends SassNumber {
|
|||||||
return super.lessThanOrEquals(other);
|
return super.lessThanOrEquals(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
SassNumber modulo(Value other) {
|
Value modulo(Value other) {
|
||||||
if (other is SassNumber) {
|
if (other is SassNumber) {
|
||||||
return other.withValue(moduloLikeSass(value, other.value));
|
return other.withValue(moduloLikeSass(value, other.value));
|
||||||
}
|
}
|
||||||
|
@ -2300,8 +2300,7 @@ final class _EvaluateVisitor
|
|||||||
var arguments = [
|
var arguments = [
|
||||||
for (var argument in node.arguments)
|
for (var argument in node.arguments)
|
||||||
await _visitCalculationValue(argument,
|
await _visitCalculationValue(argument,
|
||||||
inLegacySassFunction:
|
inMinMax: node.name == 'min' || node.name == 'max')
|
||||||
{'min', 'max', 'round', 'abs'}.contains(node.name))
|
|
||||||
];
|
];
|
||||||
if (_inSupportsDeclaration) {
|
if (_inSupportsDeclaration) {
|
||||||
return SassCalculation.unsimplified(node.name, arguments);
|
return SassCalculation.unsimplified(node.name, arguments);
|
||||||
@ -2310,31 +2309,8 @@ final class _EvaluateVisitor
|
|||||||
try {
|
try {
|
||||||
return switch (node.name) {
|
return switch (node.name) {
|
||||||
"calc" => SassCalculation.calc(arguments[0]),
|
"calc" => SassCalculation.calc(arguments[0]),
|
||||||
"sqrt" => SassCalculation.sqrt(arguments[0]),
|
|
||||||
"sin" => SassCalculation.sin(arguments[0]),
|
|
||||||
"cos" => SassCalculation.cos(arguments[0]),
|
|
||||||
"tan" => SassCalculation.tan(arguments[0]),
|
|
||||||
"asin" => SassCalculation.asin(arguments[0]),
|
|
||||||
"acos" => SassCalculation.acos(arguments[0]),
|
|
||||||
"atan" => SassCalculation.atan(arguments[0]),
|
|
||||||
"abs" => SassCalculation.abs(arguments[0]),
|
|
||||||
"exp" => SassCalculation.exp(arguments[0]),
|
|
||||||
"sign" => SassCalculation.sign(arguments[0]),
|
|
||||||
"min" => SassCalculation.min(arguments),
|
"min" => SassCalculation.min(arguments),
|
||||||
"max" => SassCalculation.max(arguments),
|
"max" => SassCalculation.max(arguments),
|
||||||
"hypot" => SassCalculation.hypot(arguments),
|
|
||||||
"pow" =>
|
|
||||||
SassCalculation.pow(arguments[0], arguments.elementAtOrNull(1)),
|
|
||||||
"atan2" =>
|
|
||||||
SassCalculation.atan2(arguments[0], arguments.elementAtOrNull(1)),
|
|
||||||
"log" =>
|
|
||||||
SassCalculation.log(arguments[0], arguments.elementAtOrNull(1)),
|
|
||||||
"mod" =>
|
|
||||||
SassCalculation.mod(arguments[0], arguments.elementAtOrNull(1)),
|
|
||||||
"rem" =>
|
|
||||||
SassCalculation.rem(arguments[0], arguments.elementAtOrNull(1)),
|
|
||||||
"round" => SassCalculation.round(arguments[0],
|
|
||||||
arguments.elementAtOrNull(1), arguments.elementAtOrNull(2)),
|
|
||||||
"clamp" => SassCalculation.clamp(arguments[0],
|
"clamp" => SassCalculation.clamp(arguments[0],
|
||||||
arguments.elementAtOrNull(1), arguments.elementAtOrNull(2)),
|
arguments.elementAtOrNull(1), arguments.elementAtOrNull(2)),
|
||||||
_ => throw UnsupportedError('Unknown calculation name "${node.name}".')
|
_ => throw UnsupportedError('Unknown calculation name "${node.name}".')
|
||||||
@ -2343,9 +2319,7 @@ final class _EvaluateVisitor
|
|||||||
// The simplification logic in the [SassCalculation] static methods will
|
// The simplification logic in the [SassCalculation] static methods will
|
||||||
// throw an error if the arguments aren't compatible, but we have access
|
// throw an error if the arguments aren't compatible, but we have access
|
||||||
// to the original spans so we can throw a more informative error.
|
// to the original spans so we can throw a more informative error.
|
||||||
if (error.message.contains("compatible")) {
|
_verifyCompatibleNumbers(arguments, node.arguments);
|
||||||
_verifyCompatibleNumbers(arguments, node.arguments);
|
|
||||||
}
|
|
||||||
throwWithTrace(_exception(error.message, node.span), error, stackTrace);
|
throwWithTrace(_exception(error.message, node.span), error, stackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2387,15 +2361,14 @@ final class _EvaluateVisitor
|
|||||||
|
|
||||||
/// Evaluates [node] as a component of a calculation.
|
/// Evaluates [node] as a component of a calculation.
|
||||||
///
|
///
|
||||||
/// If [inLegacySassFunction] is `true`, this allows unitless numbers to be added and
|
/// If [inMinMax] is `true`, this allows unitless numbers to be added and
|
||||||
/// subtracted with numbers with units, for backwards-compatibility with the
|
/// subtracted with numbers with units, for backwards-compatibility with the
|
||||||
/// old global `min()`, `max()`, `round()`, and `abs()` functions.
|
/// old global `min()` and `max()` functions.
|
||||||
Future<Object> _visitCalculationValue(Expression node,
|
Future<Object> _visitCalculationValue(Expression node,
|
||||||
{required bool inLegacySassFunction}) async {
|
{required bool inMinMax}) async {
|
||||||
switch (node) {
|
switch (node) {
|
||||||
case ParenthesizedExpression(expression: var inner):
|
case ParenthesizedExpression(expression: var inner):
|
||||||
var result = await _visitCalculationValue(inner,
|
var result = await _visitCalculationValue(inner, inMinMax: inMinMax);
|
||||||
inLegacySassFunction: inLegacySassFunction);
|
|
||||||
return inner is FunctionExpression &&
|
return inner is FunctionExpression &&
|
||||||
inner.name.toLowerCase() == 'var' &&
|
inner.name.toLowerCase() == 'var' &&
|
||||||
result is SassString &&
|
result is SassString &&
|
||||||
@ -2426,11 +2399,9 @@ final class _EvaluateVisitor
|
|||||||
node,
|
node,
|
||||||
() async => SassCalculation.operateInternal(
|
() async => SassCalculation.operateInternal(
|
||||||
_binaryOperatorToCalculationOperator(operator),
|
_binaryOperatorToCalculationOperator(operator),
|
||||||
await _visitCalculationValue(left,
|
await _visitCalculationValue(left, inMinMax: inMinMax),
|
||||||
inLegacySassFunction: inLegacySassFunction),
|
await _visitCalculationValue(right, inMinMax: inMinMax),
|
||||||
await _visitCalculationValue(right,
|
inMinMax: inMinMax,
|
||||||
inLegacySassFunction: inLegacySassFunction),
|
|
||||||
inLegacySassFunction: inLegacySassFunction,
|
|
||||||
simplify: !_inSupportsDeclaration));
|
simplify: !_inSupportsDeclaration));
|
||||||
|
|
||||||
case _:
|
case _:
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// DO NOT EDIT. This file was generated from async_evaluate.dart.
|
// DO NOT EDIT. This file was generated from async_evaluate.dart.
|
||||||
// See tool/grind/synchronize.dart for details.
|
// See tool/grind/synchronize.dart for details.
|
||||||
//
|
//
|
||||||
// Checksum: e4d8cd913b88b73d11417b5ccda03a6313a5bb78
|
// Checksum: 6eb7f76735562eba91e9460af796b269b3b0aaf7
|
||||||
//
|
//
|
||||||
// ignore_for_file: unused_import
|
// ignore_for_file: unused_import
|
||||||
|
|
||||||
@ -2282,8 +2282,7 @@ final class _EvaluateVisitor
|
|||||||
var arguments = [
|
var arguments = [
|
||||||
for (var argument in node.arguments)
|
for (var argument in node.arguments)
|
||||||
_visitCalculationValue(argument,
|
_visitCalculationValue(argument,
|
||||||
inLegacySassFunction:
|
inMinMax: node.name == 'min' || node.name == 'max')
|
||||||
{'min', 'max', 'round', 'abs'}.contains(node.name))
|
|
||||||
];
|
];
|
||||||
if (_inSupportsDeclaration) {
|
if (_inSupportsDeclaration) {
|
||||||
return SassCalculation.unsimplified(node.name, arguments);
|
return SassCalculation.unsimplified(node.name, arguments);
|
||||||
@ -2292,31 +2291,8 @@ final class _EvaluateVisitor
|
|||||||
try {
|
try {
|
||||||
return switch (node.name) {
|
return switch (node.name) {
|
||||||
"calc" => SassCalculation.calc(arguments[0]),
|
"calc" => SassCalculation.calc(arguments[0]),
|
||||||
"sqrt" => SassCalculation.sqrt(arguments[0]),
|
|
||||||
"sin" => SassCalculation.sin(arguments[0]),
|
|
||||||
"cos" => SassCalculation.cos(arguments[0]),
|
|
||||||
"tan" => SassCalculation.tan(arguments[0]),
|
|
||||||
"asin" => SassCalculation.asin(arguments[0]),
|
|
||||||
"acos" => SassCalculation.acos(arguments[0]),
|
|
||||||
"atan" => SassCalculation.atan(arguments[0]),
|
|
||||||
"abs" => SassCalculation.abs(arguments[0]),
|
|
||||||
"exp" => SassCalculation.exp(arguments[0]),
|
|
||||||
"sign" => SassCalculation.sign(arguments[0]),
|
|
||||||
"min" => SassCalculation.min(arguments),
|
"min" => SassCalculation.min(arguments),
|
||||||
"max" => SassCalculation.max(arguments),
|
"max" => SassCalculation.max(arguments),
|
||||||
"hypot" => SassCalculation.hypot(arguments),
|
|
||||||
"pow" =>
|
|
||||||
SassCalculation.pow(arguments[0], arguments.elementAtOrNull(1)),
|
|
||||||
"atan2" =>
|
|
||||||
SassCalculation.atan2(arguments[0], arguments.elementAtOrNull(1)),
|
|
||||||
"log" =>
|
|
||||||
SassCalculation.log(arguments[0], arguments.elementAtOrNull(1)),
|
|
||||||
"mod" =>
|
|
||||||
SassCalculation.mod(arguments[0], arguments.elementAtOrNull(1)),
|
|
||||||
"rem" =>
|
|
||||||
SassCalculation.rem(arguments[0], arguments.elementAtOrNull(1)),
|
|
||||||
"round" => SassCalculation.round(arguments[0],
|
|
||||||
arguments.elementAtOrNull(1), arguments.elementAtOrNull(2)),
|
|
||||||
"clamp" => SassCalculation.clamp(arguments[0],
|
"clamp" => SassCalculation.clamp(arguments[0],
|
||||||
arguments.elementAtOrNull(1), arguments.elementAtOrNull(2)),
|
arguments.elementAtOrNull(1), arguments.elementAtOrNull(2)),
|
||||||
_ => throw UnsupportedError('Unknown calculation name "${node.name}".')
|
_ => throw UnsupportedError('Unknown calculation name "${node.name}".')
|
||||||
@ -2325,9 +2301,7 @@ final class _EvaluateVisitor
|
|||||||
// The simplification logic in the [SassCalculation] static methods will
|
// The simplification logic in the [SassCalculation] static methods will
|
||||||
// throw an error if the arguments aren't compatible, but we have access
|
// throw an error if the arguments aren't compatible, but we have access
|
||||||
// to the original spans so we can throw a more informative error.
|
// to the original spans so we can throw a more informative error.
|
||||||
if (error.message.contains("compatible")) {
|
_verifyCompatibleNumbers(arguments, node.arguments);
|
||||||
_verifyCompatibleNumbers(arguments, node.arguments);
|
|
||||||
}
|
|
||||||
throwWithTrace(_exception(error.message, node.span), error, stackTrace);
|
throwWithTrace(_exception(error.message, node.span), error, stackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2369,15 +2343,13 @@ final class _EvaluateVisitor
|
|||||||
|
|
||||||
/// Evaluates [node] as a component of a calculation.
|
/// Evaluates [node] as a component of a calculation.
|
||||||
///
|
///
|
||||||
/// If [inLegacySassFunction] is `true`, this allows unitless numbers to be added and
|
/// If [inMinMax] is `true`, this allows unitless numbers to be added and
|
||||||
/// subtracted with numbers with units, for backwards-compatibility with the
|
/// subtracted with numbers with units, for backwards-compatibility with the
|
||||||
/// old global `min()`, `max()`, `round()`, and `abs()` functions.
|
/// old global `min()` and `max()` functions.
|
||||||
Object _visitCalculationValue(Expression node,
|
Object _visitCalculationValue(Expression node, {required bool inMinMax}) {
|
||||||
{required bool inLegacySassFunction}) {
|
|
||||||
switch (node) {
|
switch (node) {
|
||||||
case ParenthesizedExpression(expression: var inner):
|
case ParenthesizedExpression(expression: var inner):
|
||||||
var result = _visitCalculationValue(inner,
|
var result = _visitCalculationValue(inner, inMinMax: inMinMax);
|
||||||
inLegacySassFunction: inLegacySassFunction);
|
|
||||||
return inner is FunctionExpression &&
|
return inner is FunctionExpression &&
|
||||||
inner.name.toLowerCase() == 'var' &&
|
inner.name.toLowerCase() == 'var' &&
|
||||||
result is SassString &&
|
result is SassString &&
|
||||||
@ -2408,11 +2380,9 @@ final class _EvaluateVisitor
|
|||||||
node,
|
node,
|
||||||
() => SassCalculation.operateInternal(
|
() => SassCalculation.operateInternal(
|
||||||
_binaryOperatorToCalculationOperator(operator),
|
_binaryOperatorToCalculationOperator(operator),
|
||||||
_visitCalculationValue(left,
|
_visitCalculationValue(left, inMinMax: inMinMax),
|
||||||
inLegacySassFunction: inLegacySassFunction),
|
_visitCalculationValue(right, inMinMax: inMinMax),
|
||||||
_visitCalculationValue(right,
|
inMinMax: inMinMax,
|
||||||
inLegacySassFunction: inLegacySassFunction),
|
|
||||||
inLegacySassFunction: inLegacySassFunction,
|
|
||||||
simplify: !_inSupportsDeclaration));
|
simplify: !_inSupportsDeclaration));
|
||||||
|
|
||||||
case _:
|
case _:
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
## 8.2.0
|
||||||
|
|
||||||
|
* No user-visible changes.
|
||||||
|
|
||||||
## 8.1.1
|
## 8.1.1
|
||||||
|
|
||||||
* No user-visible changes.
|
* No user-visible changes.
|
||||||
|
@ -2,7 +2,7 @@ name: sass_api
|
|||||||
# Note: Every time we add a new Sass AST node, we need to bump the *major*
|
# Note: Every time we add a new Sass AST node, we need to bump the *major*
|
||||||
# version because it's a breaking change for anyone who's implementing the
|
# version because it's a breaking change for anyone who's implementing the
|
||||||
# visitor interface(s).
|
# visitor interface(s).
|
||||||
version: 8.1.1
|
version: 8.2.0
|
||||||
description: Additional APIs for Dart Sass.
|
description: Additional APIs for Dart Sass.
|
||||||
homepage: https://github.com/sass/dart-sass
|
homepage: https://github.com/sass/dart-sass
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ environment:
|
|||||||
sdk: ">=3.0.0 <4.0.0"
|
sdk: ">=3.0.0 <4.0.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
sass: 1.65.1
|
sass: 1.66.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
dartdoc: ^5.0.0
|
dartdoc: ^5.0.0
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name: sass
|
name: sass
|
||||||
version: 1.65.1
|
version: 1.66.0
|
||||||
description: A Sass implementation in Dart.
|
description: A Sass implementation in Dart.
|
||||||
homepage: https://github.com/sass/dart-sass
|
homepage: https://github.com/sass/dart-sass
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user