Skip to content

Commit dd9e3cc

Browse files
authoredOct 28, 2022
Implement deprecations for strict function units (#1817)
See #1776 See sass/sass#3374
1 parent 655b55c commit dd9e3cc

File tree

5 files changed

+89
-25
lines changed

5 files changed

+89
-25
lines changed
 

‎CHANGELOG.md

+22
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,28 @@
22

33
* Fix indentation for selectors that span multiple lines in a `@media` query.
44

5+
* Emit a deprecation warning when passing `$alpha` values with units to
6+
`color.adjust()` or `color.change()`. This will be an error in Dart Sass
7+
2.0.0.
8+
9+
* Emit a deprecation warning when passing a `$weight` value with no units or
10+
with units other than `%` to `color.mix()`. This will be an error in Dart Sass
11+
2.0.0.
12+
13+
* Emit a deprecation warning when passing `$n` values with units to `list.nth()`
14+
or `list.set-nth()`. This will be an error in Dart Sass 2.0.0.
15+
16+
* Improve existing deprecation warnings to wrap `/`-as-division suggestions in
17+
`calc()` expressions.
18+
19+
* Properly mark the warning for passing numbers with units to `random()` as a
20+
deprecation warning.
21+
22+
### Dart API
23+
24+
* Emit a deprecation warning when passing a `sassIndex` with units to
25+
`Value.sassIndexToListIndex()`. This will be an error in Dart Sass 2.0.0.
26+
527
## 1.55.0
628

729
* **Potentially breaking bug fix:** Sass numbers are now universally stored as

‎lib/src/functions/color.dart

+24-13
Original file line numberDiff line numberDiff line change
@@ -453,9 +453,23 @@ SassColor _updateComponents(List<Value> arguments,
453453
/// [max] should be 255 for RGB channels, 1 for the alpha channel, and 100
454454
/// for saturation, lightness, whiteness, and blackness.
455455
double? getParam(String name, num max,
456-
{bool checkPercent = false, bool assertPercent = false}) {
456+
{bool checkPercent = false,
457+
bool assertPercent = false,
458+
bool checkUnitless = false}) {
457459
var number = keywords.remove(name)?.assertNumber(name);
458460
if (number == null) return null;
461+
if (!scale && checkUnitless) {
462+
if (number.hasUnits) {
463+
warn(
464+
"\$$name: Passing a number with unit ${number.unitString} is "
465+
"deprecated.\n"
466+
"\n"
467+
"To preserve current behavior: ${number.unitSuggestion(name)}\n"
468+
"\n"
469+
"More info: https://sass-lang.com/d/function-units",
470+
deprecation: true);
471+
}
472+
}
459473
if (!scale && checkPercent) _checkPercent(number, name);
460474
if (scale || assertPercent) number.assertUnit("%", name);
461475
if (scale) max = 100;
@@ -465,7 +479,7 @@ SassColor _updateComponents(List<Value> arguments,
465479
change ? 0 : -max, max, name, checkPercent ? '%' : '');
466480
}
467481

468-
var alpha = getParam("alpha", 1);
482+
var alpha = getParam("alpha", 1, checkUnitless: true);
469483
var red = getParam("red", 255);
470484
var green = getParam("green", 255);
471485
var blue = getParam("blue", 255);
@@ -656,12 +670,13 @@ void _checkAngle(SassNumber angle, String name) {
656670

657671
var actualUnit = angle.numeratorUnits.first;
658672
message
659-
..writeln("To preserve current behavior: \$$name * 1deg/1$actualUnit")
673+
..writeln(
674+
"To preserve current behavior: calc(\$$name * 1deg/1$actualUnit)")
660675
..writeln("To migrate to new behavior: 0deg + \$$name")
661676
..writeln();
662677
} else {
663678
message
664-
..writeln("To preserve current behavior: \$$name${_removeUnits(angle)}")
679+
..writeln("To preserve current behavior: ${angle.unitSuggestion(name)}")
665680
..writeln();
666681
}
667682

@@ -676,18 +691,12 @@ void _checkPercent(SassNumber number, String name) {
676691
warn(
677692
"\$$name: Passing a number without unit % ($number) is deprecated.\n"
678693
"\n"
679-
"To preserve current behavior: \$$name${_removeUnits(number)} * 1%",
694+
"To preserve current behavior: ${number.unitSuggestion(name, '%')}\n"
695+
"\n"
696+
"More info: https://sass-lang.com/d/function-units",
680697
deprecation: true);
681698
}
682699

683-
/// Returns the right-hand side of an expression that would remove all units
684-
/// from `$number` but leaves the value the same.
685-
///
686-
/// Used for constructing deprecation messages.
687-
String _removeUnits(SassNumber number) =>
688-
number.denominatorUnits.map((unit) => " * 1$unit").join() +
689-
number.numeratorUnits.map((unit) => " / 1$unit").join();
690-
691700
/// Create an HWB color from the given [arguments].
692701
Value _hwb(List<Value> arguments) {
693702
var alpha = arguments.length > 3 ? arguments[3] : null;
@@ -805,6 +814,8 @@ double _percentageOrUnitless(SassNumber number, num max, String name) {
805814

806815
/// Returns [color1] and [color2], mixed together and weighted by [weight].
807816
SassColor _mixColors(SassColor color1, SassColor color2, SassNumber weight) {
817+
_checkPercent(weight, 'weight');
818+
808819
// This algorithm factors in both the user-provided weight (w) and the
809820
// difference between the alpha values of the two colors (a) to decide how
810821
// to perform the weighted average of the two RGB values.

‎lib/src/functions/math.dart

+11-11
Original file line numberDiff line numberDiff line change
@@ -251,17 +251,17 @@ final _randomFunction = _function("random", r"$limit: null", (arguments) {
251251

252252
if (limit.hasUnits) {
253253
warn(
254-
"math.random() will no longer ignore \$limit units ($limit) in a "
255-
"future release.\n"
256-
"\n"
257-
"Recommendation: "
258-
"math.random(math.div(\$limit, 1${limit.unitString})) * 1${limit.unitString}\n"
259-
"\n"
260-
"To preserve current behavior: "
261-
"math.random(math.div(\$limit, 1${limit.unitString}))\n"
262-
"\n"
263-
"More info: https://sass-lang.com/d/random-with-units",
264-
);
254+
"math.random() will no longer ignore \$limit units ($limit) in a "
255+
"future release.\n"
256+
"\n"
257+
"Recommendation: "
258+
"math.random(math.div(\$limit, 1${limit.unitString})) * 1${limit.unitString}\n"
259+
"\n"
260+
"To preserve current behavior: "
261+
"math.random(math.div(\$limit, 1${limit.unitString}))\n"
262+
"\n"
263+
"More info: https://sass-lang.com/d/function-units",
264+
deprecation: true);
265265
}
266266

267267
var limitScalar = limit.assertInt("limit");

‎lib/src/value.dart

+15-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:meta/meta.dart';
66

77
import 'ast/selector.dart';
8+
import 'evaluation_context.dart';
89
import 'exception.dart';
910
import 'utils.dart';
1011
import 'value/boolean.dart';
@@ -120,7 +121,20 @@ abstract class Value {
120121
/// [asList]. If [sassIndex] came from a function argument, [name] is the
121122
/// argument name (without the `$`). It's used for error reporting.
122123
int sassIndexToListIndex(Value sassIndex, [String? name]) {
123-
var index = sassIndex.assertNumber(name).assertInt(name);
124+
var indexValue = sassIndex.assertNumber(name);
125+
if (indexValue.hasUnits) {
126+
warn(
127+
"\$$name: Passing a number with unit ${indexValue.unitString} is "
128+
"deprecated.\n"
129+
"\n"
130+
"To preserve current behavior: "
131+
"${indexValue.unitSuggestion(name ?? 'index')}\n"
132+
"\n"
133+
"More info: https://sass-lang.com/d/function-units",
134+
deprecation: true);
135+
}
136+
137+
var index = indexValue.assertInt(name);
124138
if (index == 0) throw SassScriptException("List index may not be 0.", name);
125139
if (index.abs() > lengthAsList) {
126140
throw SassScriptException(

‎lib/src/value/number.dart

+17
Original file line numberDiff line numberDiff line change
@@ -933,4 +933,21 @@ abstract class SassNumber extends Value {
933933
var innerMap = _conversions[unit];
934934
return innerMap == null ? 1 : 1 / innerMap.values.first;
935935
}
936+
937+
/// Returns a suggested Sass snippet for converting a variable named [name]
938+
/// (without `%`) containing this number into a number with the same value and
939+
/// the given [unit].
940+
///
941+
/// If [unit] is null, this forces the number to be unitless.
942+
///
943+
/// This is used for deprecation warnings when restricting which units are
944+
/// allowed for a given function.
945+
@internal
946+
String unitSuggestion(String name, [String? unit]) {
947+
var result = "\$$name" +
948+
denominatorUnits.map((unit) => " * 1$unit").join() +
949+
numeratorUnits.map((unit) => " / 1$unit").join() +
950+
(unit == null ? "" : " * 1$unit");
951+
return numeratorUnits.isEmpty ? result : "calc($result)";
952+
}
936953
}

0 commit comments

Comments
 (0)
Please sign in to comment.