Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds built-in clamp() and hypot() #906

Merged
merged 4 commits into from Dec 26, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,7 @@
## 1.25.0

* Add functions to the built-in "sass:math" module.
Awjin marked this conversation as resolved.
Show resolved Hide resolved

## 1.24.0

* Add an optional `with` clause to the `@forward` rule. This works like the
Expand Down
61 changes: 59 additions & 2 deletions lib/src/functions/math.dart
Expand Up @@ -12,6 +12,7 @@ import '../exception.dart';
import '../module/built_in.dart';
import '../util/number.dart';
import '../value.dart';
import '../warn.dart';

/// A random number generator.
final _random = math.Random();
Expand All @@ -21,14 +22,16 @@ final global = UnmodifiableListView([
_round, _ceil, _floor, _abs, _max, _min, _randomFunction, _unit, //
_percentage,
_isUnitless.withName("unitless"),
_compatible.withName("comparable")
_compatible.withName("comparable"),
_div.withName("divide")
Awjin marked this conversation as resolved.
Show resolved Hide resolved
]);

/// The Sass math module.
final module = BuiltInModule("math", functions: [
_round, _ceil, _floor, _abs, _max, _min, _randomFunction, _unit,
_isUnitless, //
_percentage, _compatible
_percentage, _compatible,
_clamp, _div, _hypot
Awjin marked this conversation as resolved.
Show resolved Hide resolved
]);

final _percentage = BuiltInCallable("percentage", r"$number", (arguments) {
Expand Down Expand Up @@ -98,3 +101,57 @@ BuiltInCallable _numberFunction(String name, num transform(num value)) {
denominatorUnits: number.denominatorUnits);
});
}

final _clamp = BuiltInCallable("clamp", r"$min, $preferred, $max", (arguments) {
Awjin marked this conversation as resolved.
Show resolved Hide resolved
var min = arguments[0].assertNumber("min");
var preferred = arguments[1].assertNumber("preferred");
var max = arguments[2].assertNumber("max");

if (min.hasUnits != preferred.hasUnits ||
preferred.hasUnits != max.hasUnits) {
throw SassScriptException(
"Mixing unitless arguments with arguments that have units is not allowed.");
Awjin marked this conversation as resolved.
Show resolved Hide resolved
}

if (min.greaterThanOrEquals(max).isTruthy) return min;
if (preferred.lessThanOrEquals(min).isTruthy) return min;
if (preferred.greaterThanOrEquals(max).isTruthy) return max;
return preferred;
});

final _div = BuiltInCallable("div", r"$dividend, $divisor", (arguments) {
var dividend = arguments[0];
var divisor = arguments[1];

if (dividend is SassString || divisor is SassString) {
warn("Passing a string is deprecated.");
}

return dividend.dividedBy(divisor);
});

final _hypot = BuiltInCallable("hypot", r"$numbers...", (arguments) {
var numbers =
arguments[0].asList.map((argument) => argument.assertNumber()).toList();

if (numbers.isEmpty) {
throw SassScriptException("At least one argument must be passed.");
}

var unitRequirement = numbers[0].hasUnits;
var numeratorUnits = numbers[0].numeratorUnits;
var denominatorUnits = numbers[0].denominatorUnits;
var subtotal = 0.0;

for (var number in numbers) {
if (number.hasUnits != unitRequirement) {
throw SassScriptException(
"Mixing unitless arguments with arguments that have units is not allowed.");
}
number = number.coerce(numeratorUnits, denominatorUnits);
subtotal += math.pow(number.value, 2);
}

return SassNumber.withUnits(math.sqrt(subtotal),
numeratorUnits: numeratorUnits, denominatorUnits: denominatorUnits);
});
5 changes: 4 additions & 1 deletion lib/src/parse/stylesheet.dart
Expand Up @@ -2367,6 +2367,9 @@ relase. For details, see http://bit.ly/moz-document.
number += _tryDecimal(allowTrailingDot: scanner.position != start.position);
number *= _tryExponent();

// Preserve the sign of -0 by representing it as a double.
number = (sign.isNegative && number == 0) ? -0.0 : sign * number;
Awjin marked this conversation as resolved.
Show resolved Hide resolved

String unit;
if (scanner.scanChar($percent)) {
unit = "%";
Expand All @@ -2376,7 +2379,7 @@ relase. For details, see http://bit.ly/moz-document.
unit = identifier(unit: true);
}

return NumberExpression(sign * number, scanner.spanFrom(start), unit: unit);
return NumberExpression(number, scanner.spanFrom(start), unit: unit);
}

/// Consumes the decimal component of a number and returns its value, or 0 if
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
@@ -1,5 +1,5 @@
name: sass
version: 1.24.0
version: 1.25.0-dev
description: A Sass implementation in Dart.
author: Sass Team
homepage: https://github.com/sass/dart-sass
Expand Down