@@ -1086,20 +1086,20 @@ abstract class StylesheetParser extends Parser {
1086
1086
if (next == $u || next == $U ) {
1087
1087
var url = dynamicUrl ();
1088
1088
whitespace ();
1089
- var queries = tryImportQueries ();
1089
+ var modifiers = tryImportModifiers ();
1090
1090
return StaticImport (Interpolation ([url], scanner.spanFrom (start)),
1091
1091
scanner.spanFrom (start),
1092
- supports : queries ? .item1, media : queries ? .item2 );
1092
+ modifiers : modifiers );
1093
1093
}
1094
1094
1095
1095
var url = string ();
1096
1096
var urlSpan = scanner.spanFrom (start);
1097
1097
whitespace ();
1098
- var queries = tryImportQueries ();
1099
- if (isPlainImportUrl (url) || queries != null ) {
1098
+ var modifiers = tryImportModifiers ();
1099
+ if (isPlainImportUrl (url) || modifiers != null ) {
1100
1100
return StaticImport (
1101
1101
Interpolation ([urlSpan.text], urlSpan), scanner.spanFrom (start),
1102
- supports : queries ? .item1, media : queries ? .item2 );
1102
+ modifiers : modifiers );
1103
1103
} else {
1104
1104
try {
1105
1105
return DynamicImport (parseImportUrl (url), urlSpan);
@@ -1135,54 +1135,100 @@ abstract class StylesheetParser extends Parser {
1135
1135
return url.startsWith ("http://" ) || url.startsWith ("https://" );
1136
1136
}
1137
1137
1138
- /// Consumes a supports condition and/or a media query after an `@import` .
1138
+ /// Consumes a sequence of modifiers (such as media or supports queries)
1139
+ /// after an import argument.
1139
1140
///
1140
- /// Returns `null` if neither type of query can be found.
1141
- Tuple2 <SupportsCondition ?, Interpolation ?>? tryImportQueries () {
1142
- SupportsCondition ? supports;
1143
- if (scanIdentifier ("supports" )) {
1144
- scanner.expectChar ($lparen);
1145
- var start = scanner.state;
1146
- if (scanIdentifier ("not" )) {
1147
- whitespace ();
1148
- supports = SupportsNegation (
1149
- _supportsConditionInParens (), scanner.spanFrom (start));
1150
- } else if (scanner.peekChar () == $lparen) {
1151
- supports = _supportsCondition ();
1152
- } else {
1153
- if (_lookingAtInterpolatedIdentifier ()) {
1154
- var identifier = interpolatedIdentifier ();
1155
- if (identifier.asPlain? .toLowerCase () == "not" ) {
1156
- error ('"not" is not a valid identifier here.' , identifier.span);
1157
- }
1141
+ /// Returns `null` if there are no modifiers.
1142
+ Interpolation ? tryImportModifiers () {
1143
+ // Exit before allocating anything if we're not looking at any modifiers, as
1144
+ // is the most common case.
1145
+ if (! _lookingAtInterpolatedIdentifier () && scanner.peekChar () != $lparen) {
1146
+ return null ;
1147
+ }
1158
1148
1159
- if (scanner.scanChar ($lparen)) {
1160
- var arguments = _interpolatedDeclarationValue (
1161
- allowEmpty: true , allowSemicolon: true );
1162
- scanner.expectChar ($rparen);
1163
- supports = SupportsFunction (
1164
- identifier, arguments, scanner.spanFrom (start));
1149
+ var start = scanner.state;
1150
+ var buffer = InterpolationBuffer ();
1151
+ while (true ) {
1152
+ if (_lookingAtInterpolatedIdentifier ()) {
1153
+ if (! buffer.isEmpty) buffer.writeCharCode ($space);
1154
+
1155
+ var identifier = interpolatedIdentifier ();
1156
+ buffer.addInterpolation (identifier);
1157
+
1158
+ var name = identifier.asPlain? .toLowerCase ();
1159
+ if (name != "and" && scanner.scanChar ($lparen)) {
1160
+ if (name == "supports" ) {
1161
+ var query = _importSupportsQuery ();
1162
+ if (query is ! SupportsDeclaration ) buffer.writeCharCode ($lparen);
1163
+ buffer.add (SupportsExpression (query));
1164
+ if (query is ! SupportsDeclaration ) buffer.writeCharCode ($rparen);
1165
1165
} else {
1166
- // Backtrack to parse a variable declaration
1167
- scanner.state = start;
1166
+ buffer.writeCharCode ($lparen);
1167
+ buffer.addInterpolation (_interpolatedDeclarationValue (
1168
+ allowEmpty: true , allowSemicolon: true ));
1169
+ buffer.writeCharCode ($rparen);
1170
+ }
1171
+
1172
+ scanner.expectChar ($rparen);
1173
+ whitespace ();
1174
+ } else {
1175
+ whitespace ();
1176
+ if (scanner.scanChar ($comma)) {
1177
+ buffer.write (", " );
1178
+ buffer.addInterpolation (_mediaQueryList ());
1179
+ return buffer.interpolation (scanner.spanFrom (start));
1168
1180
}
1169
1181
}
1170
- if (supports == null ) {
1171
- var name = expression ();
1172
- scanner.expectChar ($colon);
1173
- supports = _supportsDeclarationValue (name, start);
1174
- }
1182
+ } else if (scanner.peekChar () == $lparen) {
1183
+ if (! buffer.isEmpty) buffer.writeCharCode ($space);
1184
+ buffer.addInterpolation (_mediaQueryList ());
1185
+ return buffer.interpolation (scanner.spanFrom (start));
1186
+ } else {
1187
+ return buffer.interpolation (scanner.spanFrom (start));
1175
1188
}
1176
- scanner.expectChar ($rparen);
1189
+ }
1190
+ }
1191
+
1192
+ /// Consumes the contents of a `supports()` function after an `@import` rule
1193
+ /// (but not the function name or parentheses).
1194
+ SupportsCondition _importSupportsQuery () {
1195
+ if (scanIdentifier ("not" )) {
1177
1196
whitespace ();
1197
+ var start = scanner.state;
1198
+ return SupportsNegation (
1199
+ _supportsConditionInParens (), scanner.spanFrom (start));
1200
+ } else if (scanner.peekChar () == $lparen) {
1201
+ return _supportsCondition ();
1202
+ } else {
1203
+ var function = _tryImportSupportsFunction ();
1204
+ if (function != null ) return function;
1205
+
1206
+ var start = scanner.state;
1207
+ var name = expression ();
1208
+ scanner.expectChar ($colon);
1209
+ return _supportsDeclarationValue (name, start);
1210
+ }
1211
+ }
1212
+
1213
+ /// Consumes a function call within a `supports()` function after an
1214
+ /// `@import` if available.
1215
+ SupportsFunction ? _tryImportSupportsFunction () {
1216
+ if (! _lookingAtInterpolatedIdentifier ()) return null ;
1217
+
1218
+ var start = scanner.state;
1219
+ var name = interpolatedIdentifier ();
1220
+ assert (name.asPlain != "not" );
1221
+
1222
+ if (! scanner.scanChar ($lparen)) {
1223
+ scanner.state = start;
1224
+ return null ;
1178
1225
}
1179
1226
1180
- var media =
1181
- _lookingAtInterpolatedIdentifier () || scanner.peekChar () == $lparen
1182
- ? _mediaQueryList ()
1183
- : null ;
1184
- if (supports == null && media == null ) return null ;
1185
- return Tuple2 (supports, media);
1227
+ var value =
1228
+ _interpolatedDeclarationValue (allowEmpty: true , allowSemicolon: true );
1229
+ scanner.expectChar ($rparen);
1230
+
1231
+ return SupportsFunction (name, value, scanner.spanFrom (start));
1186
1232
}
1187
1233
1188
1234
/// Consumes an `@include` rule.
0 commit comments