mirror of
https://github.com/danog/dart-sass.git
synced 2024-12-02 09:37:49 +01:00
Support import clauses.
This commit is contained in:
parent
80055653d9
commit
be8b26191d
@ -5,6 +5,7 @@
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../../visitor/interface/css.dart';
|
||||
import 'media_query.dart';
|
||||
import 'node.dart';
|
||||
import 'value.dart';
|
||||
|
||||
@ -15,9 +16,16 @@ class CssImport extends CssNode {
|
||||
/// This includes quotes.
|
||||
final CssValue<String> url;
|
||||
|
||||
/// The supports condition attached to this import.
|
||||
final CssValue<String> supports;
|
||||
|
||||
/// The media query attached to this import.
|
||||
final List<CssMediaQuery> media;
|
||||
|
||||
final FileSpan span;
|
||||
|
||||
CssImport(this.url, this.span);
|
||||
CssImport(this.url, this.span, {this.supports, Iterable<CssMediaQuery> media})
|
||||
: media = media == null ? null : new List.unmodifiable(media);
|
||||
|
||||
/*=T*/ accept/*<T>*/(CssVisitor/*<T>*/ visitor) => visitor.visitImport(this);
|
||||
}
|
||||
|
@ -2,11 +2,14 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'package:charcode/charcode.dart';
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../../../visitor/interface/statement.dart';
|
||||
import '../interpolation.dart';
|
||||
import '../media_query.dart';
|
||||
import '../statement.dart';
|
||||
import '../supports_condition.dart';
|
||||
|
||||
/// A rule that produces a plain CSS `@import` rule.
|
||||
class PlainImportRule implements Statement {
|
||||
@ -15,12 +18,28 @@ class PlainImportRule implements Statement {
|
||||
/// This already contains quotes.
|
||||
final Interpolation url;
|
||||
|
||||
/// The supports condition attached to this import, or `null` if no condition
|
||||
/// is attached.
|
||||
final SupportsCondition supports;
|
||||
|
||||
/// The media query attached to this import, or `null` if no condition is
|
||||
/// attached.
|
||||
final List<MediaQuery> media;
|
||||
|
||||
final FileSpan span;
|
||||
|
||||
PlainImportRule(this.url, this.span);
|
||||
PlainImportRule(this.url, this.span,
|
||||
{this.supports, Iterable<MediaQuery> media})
|
||||
: media = media == null ? null : new List.unmodifiable(media);
|
||||
|
||||
/*=T*/ accept/*<T>*/(StatementVisitor/*<T>*/ visitor) =>
|
||||
visitor.visitPlainImportRule(this);
|
||||
|
||||
String toString() => "@import $url;";
|
||||
String toString() {
|
||||
var buffer = new StringBuffer("@import $url");
|
||||
if (supports != null) buffer.write(" supports($supports)");
|
||||
if (media != null) buffer.write(" $media");
|
||||
buffer.writeCharCode($semicolon);
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
@ -625,23 +625,29 @@ abstract class StylesheetParser extends Parser {
|
||||
///
|
||||
/// [start] should point before the `@`.
|
||||
Statement _importRule(LineScannerState start) {
|
||||
// TODO: parse supports clauses, url(), and query lists
|
||||
var urlStart = scanner.state;
|
||||
var next = scanner.peekChar();
|
||||
if (next == $u || next == $U) {
|
||||
var url = _dynamicUrl();
|
||||
whitespace();
|
||||
var queries = _tryImportQueries();
|
||||
_expectStatementSeparator();
|
||||
return new PlainImportRule(
|
||||
new Interpolation([url], scanner.spanFrom(urlStart)),
|
||||
scanner.spanFrom(start));
|
||||
scanner.spanFrom(start),
|
||||
supports: queries?.item1,
|
||||
media: queries?.item2);
|
||||
}
|
||||
|
||||
var url = string();
|
||||
whitespace();
|
||||
var queries = _tryImportQueries();
|
||||
if (_isPlainImportUrl(url)) {
|
||||
var interpolation = new Interpolation(
|
||||
[scanner.substring(urlStart.position)], scanner.spanFrom(urlStart));
|
||||
_expectStatementSeparator();
|
||||
return new PlainImportRule(interpolation, scanner.spanFrom(start));
|
||||
return new PlainImportRule(interpolation, scanner.spanFrom(start),
|
||||
supports: queries?.item1, media: queries?.item2);
|
||||
} else if (_inControlDirective || _inMixin) {
|
||||
_disallowedAtRule(start);
|
||||
return null;
|
||||
@ -666,6 +672,38 @@ abstract class StylesheetParser extends Parser {
|
||||
return url.startsWith("http://") || url.startsWith("https://");
|
||||
}
|
||||
|
||||
/// Consumes a supports condition and/or a media query after an `@import`.
|
||||
///
|
||||
/// Returns `null` if neither type of query can be found.
|
||||
Tuple2<SupportsCondition, List<MediaQuery>> _tryImportQueries() {
|
||||
SupportsCondition supports;
|
||||
if (scanIdentifier("supports", ignoreCase: true)) {
|
||||
scanner.expectChar($lparen);
|
||||
var start = scanner.state;
|
||||
if (scanIdentifier("not", ignoreCase: true)) {
|
||||
whitespace();
|
||||
supports = new SupportsNegation(
|
||||
_supportsConditionInParens(), scanner.spanFrom(start));
|
||||
} else {
|
||||
var name = _expression();
|
||||
scanner.expectChar($colon);
|
||||
whitespace();
|
||||
var value = _expression();
|
||||
supports =
|
||||
new SupportsDeclaration(name, value, scanner.spanFrom(start));
|
||||
}
|
||||
scanner.expectChar($rparen);
|
||||
whitespace();
|
||||
}
|
||||
|
||||
var media =
|
||||
_lookingAtInterpolatedIdentifier() || scanner.peekChar() == $lparen
|
||||
? _mediaQueryList()
|
||||
: null;
|
||||
if (supports == null && media == null) return null;
|
||||
return new Tuple2(supports, media);
|
||||
}
|
||||
|
||||
/// Consumes an `@include` rule.
|
||||
///
|
||||
/// [start] should point before the `@`.
|
||||
|
@ -609,7 +609,17 @@ class _PerformVisitor
|
||||
}
|
||||
|
||||
Value visitPlainImportRule(PlainImportRule node) {
|
||||
_parent.addChild(new CssImport(_interpolationToValue(node.url), node.span));
|
||||
var url = _interpolationToValue(node.url);
|
||||
var supports = node.supports;
|
||||
var resolvedSupports = supports is SupportsDeclaration
|
||||
? "${supports.name.accept(this).toCssString()}: "
|
||||
"${supports.value.accept(this).toCssString()})"
|
||||
: (supports == null ? null : _visitSupportsCondition(supports));
|
||||
_parent.addChild(new CssImport(url, node.span,
|
||||
supports: resolvedSupports == null
|
||||
? null
|
||||
: new CssValue(resolvedSupports, node.supports.span),
|
||||
media: node?.media?.map(_visitMediaQuery)));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -141,6 +141,17 @@ class _SerializeCssVisitor
|
||||
_writeIndentation();
|
||||
_buffer.write("@import ");
|
||||
_buffer.write(node.url.value);
|
||||
|
||||
if (node.supports != null) {
|
||||
_buffer.writeCharCode($space);
|
||||
_buffer.write(node.supports.value);
|
||||
}
|
||||
|
||||
if (node.media != null) {
|
||||
_buffer.writeCharCode($space);
|
||||
_writeBetween(node.media, ', ', visitMediaQuery);
|
||||
}
|
||||
|
||||
_buffer.writeCharCode($semicolon);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user