Skip to content

Commit

Permalink
Deprecate /-as-division and add replacements
Browse files Browse the repository at this point in the history
Partially addresses #663
  • Loading branch information
nex3 committed May 12, 2021
1 parent 742023a commit be1a414
Show file tree
Hide file tree
Showing 13 changed files with 338 additions and 105 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,12 @@
## 1.33.0

* Deprecate the use of `/` for division. The new `math.div()` function should be
used instead. See [this page][] for details.

[this page]: https://sass-lang.com/documentation/breaking-changes/slash-div

* Add a `list.slash()` function that returns a slash-separated list.

## 1.32.13

* Use the proper parameter names in error messages about `string.slice`
Expand Down
27 changes: 24 additions & 3 deletions lib/src/functions/color.dart
Expand Up @@ -705,6 +705,25 @@ Object /* SassString | List<Value> */ _parseChannels(
String name, List<String> argumentNames, Value channels) {
if (channels.isVar) return _functionString(name, [channels]);

var originalChannels = channels;
Value? alphaFromSlashList;
if (channels.separator == ListSeparator.slash) {
var list = channels.asList;
if (list.length != 2) {
throw SassScriptException(
"Only 2 slash-separated elements allowed, but ${list.length} "
"${pluralize('was', list.length, plural: 'were')} passed.");
}

channels = list[0];

alphaFromSlashList = list[1];
if (!alphaFromSlashList.isSpecialNumber) {
alphaFromSlashList.assertNumber("alpha");
}
if (list[0].isVar) return _functionString(name, [originalChannels]);
}

var isCommaSeparated = channels.separator == ListSeparator.comma;
var isBracketed = channels.hasBrackets;
if (isCommaSeparated || isBracketed) {
Expand All @@ -720,18 +739,20 @@ Object /* SassString | List<Value> */ _parseChannels(

var list = channels.asList;
if (list.length > 3) {
throw SassScriptException(
"Only 3 elements allowed, but ${list.length} were passed.");
throw SassScriptException("Only 3 elements allowed, but ${list.length} "
"${pluralize('was', list.length, plural: 'were')} passed.");
} else if (list.length < 3) {
if (list.any((value) => value.isVar) ||
(list.isNotEmpty && _isVarSlash(list.last))) {
return _functionString(name, [channels]);
return _functionString(name, [originalChannels]);
} else {
var argument = argumentNames[list.length];
throw SassScriptException("Missing element $argument.");
}
}

if (alphaFromSlashList != null) return [...list, alphaFromSlashList];

var maybeSlashSeparated = list[2];
if (maybeSlashSeparated is SassNumber) {
var slash = maybeSlashSeparated.asSlash;
Expand Down
35 changes: 26 additions & 9 deletions lib/src/functions/list.dart
Expand Up @@ -20,7 +20,7 @@ final global = UnmodifiableListView([
/// The Sass list module.
final module = BuiltInModule("list", functions: [
_length, _nth, _setNth, _join, _append, _zip, _index, _isBracketed, //
_separator
_separator, _slash
]);

final _length = _function(
Expand Down Expand Up @@ -61,9 +61,11 @@ final _join = _function(
separator = ListSeparator.space;
} else if (separatorParam.text == "comma") {
separator = ListSeparator.comma;
} else if (separatorParam.text == "slash") {
separator = ListSeparator.slash;
} else {
throw SassScriptException(
'\$separator: Must be "space", "comma", or "auto".');
'\$separator: Must be "space", "comma", "slash", or "auto".');
}

var bracketed = bracketedParam is SassString && bracketedParam.text == 'auto'
Expand All @@ -89,9 +91,11 @@ final _append =
separator = ListSeparator.space;
} else if (separatorParam.text == "comma") {
separator = ListSeparator.comma;
} else if (separatorParam.text == "slash") {
separator = ListSeparator.slash;
} else {
throw SassScriptException(
'\$separator: Must be "space", "comma", or "auto".');
'\$separator: Must be "space", "comma", "slash", or "auto".');
}

var newList = [...list.asList, value];
Expand Down Expand Up @@ -121,16 +125,29 @@ final _index = _function("index", r"$list, $value", (arguments) {
return index == -1 ? sassNull : SassNumber(index + 1);
});

final _separator = _function(
"separator",
r"$list",
(arguments) => arguments[0].separator == ListSeparator.comma
? SassString("comma", quotes: false)
: SassString("space", quotes: false));
final _separator = _function("separator", r"$list", (arguments) {
switch (arguments[0].separator) {
case ListSeparator.comma:
return SassString("comma", quotes: false);
case ListSeparator.slash:
return SassString("slash", quotes: false);
default:
return SassString("space", quotes: false);
}
});

final _isBracketed = _function("is-bracketed", r"$list",
(arguments) => SassBoolean(arguments[0].hasBrackets));

final _slash = _function("slash", r"$elements...", (arguments) {
var list = arguments[0].asList;
if (list.length < 2) {
throw SassScriptException("At least two elements are required.");
}

return SassList(list, ListSeparator.slash);
});

/// Like [new BuiltInCallable.function], but always sets the URL to `sass:list`.
BuiltInCallable _function(
String name, String arguments, Value callback(List<Value> arguments)) =>
Expand Down
15 changes: 14 additions & 1 deletion 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';

/// The global definitions of Sass math functions.
final global = UnmodifiableListView([
Expand All @@ -25,7 +26,7 @@ final global = UnmodifiableListView([
final module = BuiltInModule("math", functions: [
_abs, _acos, _asin, _atan, _atan2, _ceil, _clamp, _cos, _compatible, //
_floor, _hypot, _isUnitless, _log, _max, _min, _percentage, _pow, //
_randomFunction, _round, _sin, _sqrt, _tan, _unit,
_randomFunction, _round, _sin, _sqrt, _tan, _unit, _div
], variables: {
"e": SassNumber(math.e),
"pi": SassNumber(math.pi),
Expand Down Expand Up @@ -295,6 +296,18 @@ final _randomFunction = _function("random", r"$limit: null", (arguments) {
return SassNumber(_random.nextInt(limit) + 1);
});

final _div = _function("div", r"$number1, $number2", (arguments) {
var number1 = arguments[0];
var number2 = arguments[1];

if (number1 is! SassNumber || number2 is! SassNumber) {
warn("math.div() will only support number arguments in a future release.\n"
"Use list.slash() instead for a slash separator.");
}

return number1.dividedBy(number2);
});

///
/// Helpers
///
Expand Down
43 changes: 24 additions & 19 deletions lib/src/value.dart
Expand Up @@ -195,27 +195,32 @@ abstract class Value implements ext.Value {
if (list.asList.isEmpty) return null;

var result = <String>[];
if (list.separator == ListSeparator.comma) {
for (var complex in list.asList) {
if (complex is SassString) {
result.add(complex.text);
} else if (complex is SassList &&
complex.separator == ListSeparator.space) {
var string = complex._selectorStringOrNull();
if (string == null) return null;
result.add(string);
} else {
return null;
switch (list.separator) {
case ListSeparator.comma:
for (var complex in list.asList) {
if (complex is SassString) {
result.add(complex.text);
} else if (complex is SassList &&
complex.separator == ListSeparator.space) {
var string = complex._selectorStringOrNull();
if (string == null) return null;
result.add(string);
} else {
return null;
}
}
}
} else {
for (var compound in list.asList) {
if (compound is SassString) {
result.add(compound.text);
} else {
return null;
break;
case ListSeparator.slash:
return null;
default:
for (var compound in list.asList) {
if (compound is SassString) {
result.add(compound.text);
} else {
return null;
}
}
}
break;
}
return result.join(list.separator == ListSeparator.comma ? ', ' : ' ');
}
Expand Down
3 changes: 3 additions & 0 deletions lib/src/value/list.dart
Expand Up @@ -67,6 +67,9 @@ class ListSeparator {
/// A comma-separated list.
static const comma = ListSeparator._("comma", ",");

/// A slash-separated list.
static const slash = ListSeparator._("slash", "/");

/// A separator that hasn't yet been determined.
///
/// Singleton lists and empty lists don't have separators defined. This means
Expand Down

0 comments on commit be1a414

Please sign in to comment.