@@ -11,6 +11,7 @@ import '../deprecation.dart';
11
11
import '../evaluation_context.dart' ;
12
12
import '../exception.dart' ;
13
13
import '../module/built_in.dart' ;
14
+ import '../util/map.dart' ;
14
15
import '../util/nullable.dart' ;
15
16
import '../util/number.dart' ;
16
17
import '../utils.dart' ;
@@ -589,40 +590,30 @@ Value _invert(List<Value> arguments, {bool global = false}) {
589
590
if (fuzzyEquals (weight, 0 )) return color;
590
591
591
592
var inSpace = color.toSpace (space);
592
- SassColor inverted;
593
- switch (space) {
594
- case ColorSpace .hwb:
595
- inverted = SassColor .hwb ((inSpace.channel0 + 180 ) % 360 , inSpace.channel2,
596
- inSpace.channel1, inSpace.alpha);
597
- break ;
598
-
599
- case ColorSpace .hsl:
600
- inverted = SassColor .hsl ((inSpace.channel0 + 180 ) % 360 , inSpace.channel1,
601
- 100 - inSpace.channel2, inSpace.alpha);
602
- break ;
603
-
604
- case ColorSpace .lch:
605
- inverted = SassColor .lch (100 - inSpace.channel0, inSpace.channel1,
606
- (inSpace.channel2 + 180 ) % 360 , inSpace.alpha);
607
- break ;
608
-
609
- case ColorSpace .oklch:
610
- inverted = SassColor .oklch (1 - inSpace.channel0, inSpace.channel1,
611
- (inSpace.channel2 + 180 ) % 360 , inSpace.alpha);
612
- break ;
613
-
614
- default :
615
- var channel0 = space.channels[0 ] as LinearChannel ;
616
- var channel1 = space.channels[1 ] as LinearChannel ;
617
- var channel2 = space.channels[2 ] as LinearChannel ;
618
- inverted = SassColor .forSpaceInternal (
593
+ var inverted = switch (space) {
594
+ ColorSpace .hwb => SassColor .hwb ((inSpace.channel0 + 180 ) % 360 ,
595
+ inSpace.channel2, inSpace.channel1, inSpace.alpha),
596
+ ColorSpace .hsl => SassColor .hsl ((inSpace.channel0 + 180 ) % 360 ,
597
+ inSpace.channel1, 100 - inSpace.channel2, inSpace.alpha),
598
+ ColorSpace .lch => SassColor .lch (100 - inSpace.channel0, inSpace.channel1,
599
+ (inSpace.channel2 + 180 ) % 360 , inSpace.alpha),
600
+ ColorSpace .oklch => SassColor .oklch (1 - inSpace.channel0, inSpace.channel1,
601
+ (inSpace.channel2 + 180 ) % 360 , inSpace.alpha),
602
+ ColorSpace (
603
+ channels: [
604
+ LinearChannel channel0,
605
+ LinearChannel channel1,
606
+ LinearChannel channel2
607
+ ]
608
+ ) =>
609
+ SassColor .forSpaceInternal (
619
610
space,
620
611
_invertChannel (channel0, inSpace.channel0),
621
612
_invertChannel (channel1, inSpace.channel1),
622
613
_invertChannel (channel2, inSpace.channel2),
623
- inSpace.alpha);
624
- break ;
625
- }
614
+ inSpace.alpha),
615
+ _ => throw UnsupportedError ( "Unknown color space $ space ." )
616
+ };
626
617
627
618
if (fuzzyEquals (weight, 1 )) return inverted;
628
619
return color.interpolate (inverted, InterpolationMethod (space),
@@ -704,15 +695,15 @@ SassColor _updateComponents(List<Value> arguments,
704
695
var oldChannels = color.channels;
705
696
var channelArgs = List <SassNumber ?>.filled (oldChannels.length, null );
706
697
var channelInfo = color.space.channels;
707
- for (var entry in keywords.entries ) {
708
- var channelIndex = channelInfo.indexWhere ((info) => entry.key == info.name);
698
+ for (var (name, value) in keywords.pairs ) {
699
+ var channelIndex = channelInfo.indexWhere ((info) => name == info.name);
709
700
if (channelIndex == - 1 ) {
710
701
throw SassScriptException (
711
702
"Color space ${color .space } doesn't have a channel with this name." ,
712
- entry.key );
703
+ name );
713
704
}
714
705
715
- channelArgs[channelIndex] = entry. value.assertNumber (entry.key );
706
+ channelArgs[channelIndex] = value.assertNumber (name );
716
707
}
717
708
718
709
var result = change
@@ -765,17 +756,15 @@ double _scaleChannel(
765
756
var factor = (factorArg..assertUnit ('%' , channel.name))
766
757
.valueInRangeWithUnit (- 100 , 100 , channel.name, '%' ) /
767
758
100 ;
768
- if (factor == 0 ) {
769
- return oldValue;
770
- } else if (factor > 0 ) {
771
- return oldValue >= channel.max
759
+ return switch (factor) {
760
+ 0 => oldValue,
761
+ > 0 => oldValue >= channel.max
772
762
? oldValue
773
- : oldValue + (channel.max - oldValue) * factor;
774
- } else {
775
- return oldValue <= channel.min
763
+ : oldValue + (channel.max - oldValue) * factor,
764
+ _ => oldValue <= channel.min
776
765
? oldValue
777
- : oldValue + (oldValue - channel.min) * factor;
778
- }
766
+ : oldValue + (oldValue - channel.min) * factor
767
+ };
779
768
}
780
769
781
770
/// Returns a copy of [color] with its channel values adjusted by the values in
@@ -804,32 +793,34 @@ double _adjustChannel(ColorSpace space, ColorChannel channel, double oldValue,
804
793
SassNumber ? adjustmentArg) {
805
794
if (adjustmentArg == null ) return oldValue;
806
795
807
- if ((space == ColorSpace .hsl || space == ColorSpace .hwb) &&
808
- channel is ! LinearChannel ) {
809
- // `_channelFromValue` expects all hue values to be compatible with `deg`,
810
- // but we're still in the deprecation period where we allow non-`deg` values
811
- // for HSL and HWB so we have to handle that ahead-of-time.
812
- adjustmentArg = SassNumber (_angleValue (adjustmentArg, 'hue' ));
813
- } else if (space == ColorSpace .hsl && channel is LinearChannel ) {
814
- // `_channelFromValue` expects lightness/saturation to be `%`, but we're
815
- // still in the deprecation period where we allow non-`%` values so we have
816
- // to handle that ahead-of-time.
817
- _checkPercent (adjustmentArg, channel.name);
818
- adjustmentArg = SassNumber (adjustmentArg.value, '%' );
819
- } else if (channel == ColorChannel .alpha && adjustmentArg.hasUnits) {
820
- // `_channelFromValue` expects alpha to be unitless or `%`, but we're still
821
- // in the deprecation period where we allow other values (and interpret `%`
822
- // as unitless) so we have to handle that ahead-of-time.
823
- warnForDeprecation (
824
- "\$ alpha: Passing a number with unit ${adjustmentArg .unitString } is "
825
- "deprecated.\n "
826
- "\n "
827
- "To preserve current behavior: "
828
- "${adjustmentArg .unitSuggestion ('alpha' )}\n "
829
- "\n "
830
- "More info: https://sass-lang.com/d/function-units" ,
831
- Deprecation .functionUnits);
832
- adjustmentArg = SassNumber (adjustmentArg.value);
796
+ switch ((space, channel)) {
797
+ case (ColorSpace .hsl || ColorSpace .hwb, _) when channel is ! LinearChannel :
798
+ // `_channelFromValue` expects all hue values to be compatible with `deg`,
799
+ // but we're still in the deprecation period where we allow non-`deg`
800
+ // values for HSL and HWB so we have to handle that ahead-of-time.
801
+ adjustmentArg = SassNumber (_angleValue (adjustmentArg, 'hue' ));
802
+
803
+ case (ColorSpace .hsl, LinearChannel ()):
804
+ // `_channelFromValue` expects lightness/saturation to be `%`, but we're
805
+ // still in the deprecation period where we allow non-`%` values so we
806
+ // have to handle that ahead-of-time.
807
+ _checkPercent (adjustmentArg, channel.name);
808
+ adjustmentArg = SassNumber (adjustmentArg.value, '%' );
809
+
810
+ case (_, ColorChannel .alpha) when adjustmentArg.hasUnits:
811
+ // `_channelFromValue` expects alpha to be unitless or `%`, but we're
812
+ // still in the deprecation period where we allow other values (and
813
+ // interpret `%` as unitless) so we have to handle that ahead-of-time.
814
+ warnForDeprecation (
815
+ "\$ alpha: Passing a number with unit ${adjustmentArg .unitString } is "
816
+ "deprecated.\n "
817
+ "\n "
818
+ "To preserve current behavior: "
819
+ "${adjustmentArg .unitSuggestion ('alpha' )}\n "
820
+ "\n "
821
+ "More info: https://sass-lang.com/d/function-units" ,
822
+ Deprecation .functionUnits);
823
+ adjustmentArg = SassNumber (adjustmentArg.value);
833
824
}
834
825
835
826
var result = oldValue + _channelFromValue (channel, adjustmentArg)! ;
@@ -846,17 +837,13 @@ double _adjustChannel(ColorSpace space, ColorChannel channel, double oldValue,
846
837
ColorSpace ? _sniffLegacyColorSpace (Map <String , Value > keywords) {
847
838
for (var key in keywords.keys) {
848
839
switch (key) {
849
- case "red" :
850
- case "green" :
851
- case "blue" :
840
+ case "red" || "green" || "blue" :
852
841
return ColorSpace .rgb;
853
842
854
- case "saturation" :
855
- case "lightness" :
843
+ case "saturation" || "lightness" :
856
844
return ColorSpace .hsl;
857
845
858
- case "whiteness" :
859
- case "blackness" :
846
+ case "whiteness" || "blackness" :
860
847
return ColorSpace .hwb;
861
848
}
862
849
}
@@ -1138,24 +1125,20 @@ ColorSpace _spaceOrDefault(SassColor color, Value space, [String? name]) =>
1138
1125
Value _parseChannels (String functionName, Value input,
1139
1126
{ColorSpace ? space, String ? name}) {
1140
1127
if (input.isVar) return _functionString (functionName, [input]);
1141
- var inputList = input.assertCommonListStyle (name, allowSlash: true );
1142
1128
1143
1129
Value components;
1144
1130
Value ? alphaValue;
1145
- switch (inputList ) {
1131
+ switch (input. assertCommonListStyle (name, allowSlash : true ) ) {
1146
1132
case [var components_, var alphaValue_]
1147
1133
when input.separator == ListSeparator .slash:
1148
1134
components = components_;
1149
1135
alphaValue = alphaValue_;
1150
1136
1151
- case _ when input.separator == ListSeparator .slash:
1137
+ case var inputList when input.separator == ListSeparator .slash:
1152
1138
throw SassScriptException (
1153
1139
"Only 2 slash-separated elements allowed, but ${inputList .length } "
1154
1140
"${pluralize ('was' , inputList .length , plural : 'were' )} passed." );
1155
1141
1156
- case []:
1157
- components = input;
1158
-
1159
1142
case [..., SassString (hasQuotes: false , : var text)] when text.contains ('/' ):
1160
1143
return _functionString (functionName, [input]);
1161
1144
@@ -1169,46 +1152,51 @@ Value _parseChannels(String functionName, Value input,
1169
1152
1170
1153
List <Value > channels;
1171
1154
SassString ? spaceName;
1172
- var componentList = components.assertCommonListStyle (name, allowSlash: false );
1173
- if (componentList.isEmpty) {
1174
- throw SassScriptException ('Color component list may not be empty.' , name);
1175
- } else if (components.isVar) {
1176
- channels = [components];
1177
- } else {
1178
- if (space == null ) {
1179
- spaceName = componentList.first.assertString (name)..assertUnquoted (name);
1180
- space =
1181
- spaceName.isVar ? null : ColorSpace .fromName (spaceName.text, name);
1182
- channels = [...componentList.skip (1 )];
1183
-
1184
- if (const {
1185
- ColorSpace .rgb,
1186
- ColorSpace .hsl,
1187
- ColorSpace .hwb,
1188
- ColorSpace .lab,
1189
- ColorSpace .lch,
1190
- ColorSpace .oklab,
1191
- ColorSpace .oklch
1192
- }.contains (space)) {
1193
- throw SassScriptException (
1194
- "The color() function doesn't support the color space $space . Use "
1195
- "the $space () function instead." ,
1196
- name);
1155
+ switch (components.assertCommonListStyle (name, allowSlash: false )) {
1156
+ case []:
1157
+ throw SassScriptException ('Color component list may not be empty.' , name);
1158
+
1159
+ case _ when components.isVar:
1160
+ channels = [components];
1161
+
1162
+ case [var first, ...var rest] && var componentList:
1163
+ if (space == null ) {
1164
+ spaceName = first.assertString (name)..assertUnquoted (name);
1165
+ space =
1166
+ spaceName.isVar ? null : ColorSpace .fromName (spaceName.text, name);
1167
+ channels = rest;
1168
+
1169
+ if (space
1170
+ case ColorSpace .rgb ||
1171
+ ColorSpace .hsl ||
1172
+ ColorSpace .hwb ||
1173
+ ColorSpace .lab ||
1174
+ ColorSpace .lch ||
1175
+ ColorSpace .oklab ||
1176
+ ColorSpace .oklch) {
1177
+ throw SassScriptException (
1178
+ "The color() function doesn't support the color space $space . Use "
1179
+ "the $space () function instead." ,
1180
+ name);
1181
+ }
1182
+ } else {
1183
+ channels = componentList;
1197
1184
}
1198
- } else {
1199
- channels = componentList;
1200
- }
1201
1185
1202
- for (var channel in channels) {
1203
- if (! channel.isSpecialNumber &&
1204
- channel is ! SassNumber &&
1205
- ! _isNone (channel)) {
1206
- var channelName =
1207
- space? .channels[channels.indexOf (channel)].name ?? 'channel' ;
1208
- throw SassScriptException (
1209
- 'Expected $channelName $channel to be a number.' , name);
1186
+ for (var channel in channels) {
1187
+ if (! channel.isSpecialNumber &&
1188
+ channel is ! SassNumber &&
1189
+ ! _isNone (channel)) {
1190
+ var channelName =
1191
+ space? .channels[channels.indexOf (channel)].name ?? 'channel' ;
1192
+ throw SassScriptException (
1193
+ 'Expected $channelName $channel to be a number.' , name);
1194
+ }
1210
1195
}
1211
- }
1196
+
1197
+ // dart-lang/sdk#51926
1198
+ case _:
1199
+ throw "unreachable" ;
1212
1200
}
1213
1201
1214
1202
if (alphaValue? .isSpecialNumber ?? false ) {
@@ -1319,16 +1307,14 @@ SassColor _colorFromChannels(ColorSpace space, SassNumber? channel0,
1319
1307
/// Converts a channel value from a [SassNumber] into a [double] according to
1320
1308
/// [channel] .
1321
1309
double ? _channelFromValue (ColorChannel channel, SassNumber ? value) =>
1322
- value.andThen ((value) {
1323
- if (channel is ! LinearChannel ) {
1324
- return value.coerceValueToUnit ('deg' , channel.name);
1325
- } else if (channel.requiresPercent && ! value.hasUnit ('%' )) {
1326
- throw SassScriptException (
1327
- 'Expected $value to have unit "%".' , channel.name);
1328
- } else {
1329
- return _percentageOrUnitless (value, channel.max, channel.name);
1330
- }
1331
- });
1310
+ value.andThen ((value) => switch (channel) {
1311
+ LinearChannel (requiresPercent: true ) when ! value.hasUnit ('%' ) =>
1312
+ throw SassScriptException (
1313
+ 'Expected $value to have unit "%".' , channel.name),
1314
+ LinearChannel () =>
1315
+ _percentageOrUnitless (value, channel.max, channel.name),
1316
+ _ => value.coerceValueToUnit ('deg' , channel.name)
1317
+ });
1332
1318
1333
1319
/// Returns whether [value] is an unquoted string case-insensitively equal to
1334
1320
/// "none".
0 commit comments