Skip to content

Commit

Permalink
Convert Sass to Dart 3 style
Browse files Browse the repository at this point in the history
  • Loading branch information
nex3 committed Jul 19, 2023
1 parent fe7f9a1 commit 51b4e5c
Show file tree
Hide file tree
Showing 227 changed files with 4,283 additions and 5,384 deletions.
25 changes: 9 additions & 16 deletions bin/sass.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import 'dart:isolate';

import 'package:collection/collection.dart';
import 'package:path/path.dart' as p;
import 'package:stack_trace/stack_trace.dart';
import 'package:term_glyph/term_glyph.dart' as term_glyph;
Expand All @@ -19,6 +18,7 @@ import 'package:sass/src/io.dart';
import 'package:sass/src/io.dart' as io;
import 'package:sass/src/logger/deprecation_handling.dart';
import 'package:sass/src/stylesheet_graph.dart';
import 'package:sass/src/util/map.dart';
import 'package:sass/src/utils.dart';
import 'package:sass/src/embedded/executable.dart'
// Never load the embedded protocol when compiling to JS.
Expand Down Expand Up @@ -47,8 +47,8 @@ Future<void> main(List<String> args) async {
io.printError(buffer);
}

if (args.firstOrNull == '--embedded') {
embedded.main(args.sublist(1));
if (args case ['--embedded', ...var rest]) {
embedded.main(rest);
return;
}

Expand Down Expand Up @@ -84,25 +84,18 @@ Future<void> main(List<String> args) async {
return;
}

for (var source in options.sourcesToDestinations.keys) {
var destination = options.sourcesToDestinations[source];
for (var (source, destination) in options.sourcesToDestinations.pairs) {
try {
await compileStylesheet(options, graph, source, destination,
ifModified: options.update);
} on SassException catch (error, stackTrace) {
// This is an immediately-invoked function expression to work around
// dart-lang/sdk#33400.
() {
if (destination != null && !options.emitErrorCss) {
try {
if (destination != null &&
// dart-lang/sdk#45348
!options!.emitErrorCss) {
deleteFile(destination);
}
deleteFile(destination);
} on FileSystemException {
// If the file doesn't exist, that's fine.
}
}();
}

printError(error.toString(color: options.color),
options.trace ? getTrace(error) ?? stackTrace : null);
Expand Down Expand Up @@ -134,9 +127,9 @@ Future<void> main(List<String> args) async {
exitCode = 64;
} catch (error, stackTrace) {
var buffer = StringBuffer();
if (options != null && options.color) buffer.write('\u001b[31m\u001b[1m');
if (options?.color ?? false) buffer.write('\u001b[31m\u001b[1m');
buffer.write('Unexpected exception:');
if (options != null && options.color) buffer.write('\u001b[0m');
if (options?.color ?? false) buffer.write('\u001b[0m');
buffer.writeln();
buffer.writeln(error);

Expand Down
5 changes: 1 addition & 4 deletions lib/src/ast/css/at_rule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import '../../visitor/interface/css.dart';
import 'node.dart';
import 'value.dart';

/// An unknown plain CSS at-rule.
abstract class CssAtRule extends CssParentNode {
abstract interface class CssAtRule implements CssParentNode {
/// The name of this rule.
CssValue<String> get name;

Expand All @@ -19,6 +18,4 @@ abstract class CssAtRule extends CssParentNode {
/// This implies `children.isEmpty`, but the reverse is not true—for a rule
/// like `@foo {}`, [children] is empty but [isChildless] is `false`.
bool get isChildless;

T accept<T>(CssVisitor<T> visitor) => visitor.visitCssAtRule(this);
}
5 changes: 1 addition & 4 deletions lib/src/ast/css/comment.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import '../../visitor/interface/css.dart';
import 'node.dart';

/// A plain CSS comment.
///
/// This is always a multi-line comment.
abstract class CssComment extends CssNode {
abstract interface class CssComment implements CssNode {
/// The contents of this comment, including `/*` and `*/`.
String get text;

/// Whether this comment starts with `/*!` and so should be preserved even in
/// compressed mode.
bool get isPreserved;

T accept<T>(CssVisitor<T> visitor) => visitor.visitCssComment(this);
}
5 changes: 1 addition & 4 deletions lib/src/ast/css/declaration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
import 'package:source_span/source_span.dart';

import '../../value.dart';
import '../../visitor/interface/css.dart';
import 'node.dart';
import 'value.dart';

/// A plain CSS declaration (that is, a `name: value` pair).
abstract class CssDeclaration extends CssNode {
abstract interface class CssDeclaration implements CssNode {
/// The name of this declaration.
CssValue<String> get name;

Expand All @@ -34,6 +33,4 @@ abstract class CssDeclaration extends CssNode {
/// If this is `true`, [isCustomProperty] will also be `true` and [value] will
/// contain a [SassString].
bool get parsedAsCustomProperty;

T accept<T>(CssVisitor<T> visitor);
}
5 changes: 1 addition & 4 deletions lib/src/ast/css/import.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import '../../visitor/interface/css.dart';
import 'node.dart';
import 'value.dart';

/// A plain CSS `@import`.
abstract class CssImport extends CssNode {
abstract interface class CssImport implements CssNode {
/// The URL being imported.
///
/// This includes quotes.
CssValue<String> get url;

/// The modifiers (such as media or supports queries) attached to this import.
CssValue<String>? get modifiers;

T accept<T>(CssVisitor<T> visitor) => visitor.visitCssImport(this);
}
5 changes: 1 addition & 4 deletions lib/src/ast/css/keyframe_block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import '../../visitor/interface/css.dart';
import 'node.dart';
import 'value.dart';

/// A block within a `@keyframes` rule.
///
/// For example, `10% {opacity: 0.5}`.
abstract class CssKeyframeBlock extends CssParentNode {
abstract interface class CssKeyframeBlock implements CssParentNode {
/// The selector for this block.
CssValue<List<String>> get selector;

T accept<T>(CssVisitor<T> visitor) => visitor.visitCssKeyframeBlock(this);
}
18 changes: 7 additions & 11 deletions lib/src/ast/css/media_query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import '../../parse/media_query.dart';
import '../../utils.dart';

/// A plain CSS media query, as used in `@media` and `@import`.
class CssMediaQuery {
final class CssMediaQuery {
/// The modifier, probably either "not" or "only".
///
/// This may be `null` if no modifier is in use.
Expand Down Expand Up @@ -197,25 +197,21 @@ class CssMediaQuery {
///
/// This is either the singleton values [empty] or [unrepresentable], or an
/// instance of [MediaQuerySuccessfulMergeResult].
abstract class MediaQueryMergeResult {
sealed class MediaQueryMergeResult {
/// A singleton value indicating that there are no contexts that match both
/// input queries.
static const empty = _SingletonCssMediaQueryMergeResult("empty");
static const empty = _SingletonCssMediaQueryMergeResult.empty;

/// A singleton value indicating that the contexts that match both input
/// queries can't be represented by a Level 3 media query.
static const unrepresentable =
_SingletonCssMediaQueryMergeResult("unrepresentable");
_SingletonCssMediaQueryMergeResult.unrepresentable;
}

/// The subclass [MediaQueryMergeResult] that represents singleton enum values.
class _SingletonCssMediaQueryMergeResult implements MediaQueryMergeResult {
/// The name of the result type.
final String _name;

const _SingletonCssMediaQueryMergeResult(this._name);

String toString() => _name;
enum _SingletonCssMediaQueryMergeResult implements MediaQueryMergeResult {
empty,
unrepresentable;
}

/// A successful result of [CssMediaQuery.merge].
Expand Down
5 changes: 1 addition & 4 deletions lib/src/ast/css/media_rule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import '../../visitor/interface/css.dart';
import 'media_query.dart';
import 'node.dart';

/// A plain CSS `@media` rule.
abstract class CssMediaRule extends CssParentNode {
abstract interface class CssMediaRule implements CssParentNode {
/// The queries for this rule.
///
/// This is never empty.
List<CssMediaQuery> get queries;

T accept<T>(CssVisitor<T> visitor) => visitor.visitCssMediaRule(this);
}
3 changes: 2 additions & 1 deletion lib/src/ast/css/modifiable/at_rule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import '../value.dart';
import 'node.dart';

/// A modifiable version of [CssAtRule] for use in the evaluation step.
class ModifiableCssAtRule extends ModifiableCssParentNode implements CssAtRule {
final class ModifiableCssAtRule extends ModifiableCssParentNode
implements CssAtRule {
final CssValue<String> name;
final CssValue<String>? value;
final bool isChildless;
Expand Down
3 changes: 2 additions & 1 deletion lib/src/ast/css/modifiable/comment.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import '../comment.dart';
import 'node.dart';

/// A modifiable version of [CssComment] for use in the evaluation step.
class ModifiableCssComment extends ModifiableCssNode implements CssComment {
final class ModifiableCssComment extends ModifiableCssNode
implements CssComment {
final String text;
final FileSpan span;

Expand Down
2 changes: 1 addition & 1 deletion lib/src/ast/css/modifiable/declaration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import '../value.dart';
import 'node.dart';

/// A modifiable version of [CssDeclaration] for use in the evaluation step.
class ModifiableCssDeclaration extends ModifiableCssNode
final class ModifiableCssDeclaration extends ModifiableCssNode
implements CssDeclaration {
final CssValue<String> name;
final CssValue<Value> value;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/ast/css/modifiable/import.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import '../value.dart';
import 'node.dart';

/// A modifiable version of [CssImport] for use in the evaluation step.
class ModifiableCssImport extends ModifiableCssNode implements CssImport {
final class ModifiableCssImport extends ModifiableCssNode implements CssImport {
/// The URL being imported.
///
/// This includes quotes.
Expand Down
2 changes: 1 addition & 1 deletion lib/src/ast/css/modifiable/keyframe_block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import '../value.dart';
import 'node.dart';

/// A modifiable version of [CssKeyframeBlock] for use in the evaluation step.
class ModifiableCssKeyframeBlock extends ModifiableCssParentNode
final class ModifiableCssKeyframeBlock extends ModifiableCssParentNode
implements CssKeyframeBlock {
final CssValue<List<String>> selector;
final FileSpan span;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/ast/css/modifiable/media_rule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import '../media_rule.dart';
import 'node.dart';

/// A modifiable version of [CssMediaRule] for use in the evaluation step.
class ModifiableCssMediaRule extends ModifiableCssParentNode
final class ModifiableCssMediaRule extends ModifiableCssParentNode
implements CssMediaRule {
final List<CssMediaQuery> queries;
final FileSpan span;
Expand Down
7 changes: 3 additions & 4 deletions lib/src/ast/css/modifiable/node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import '../node.dart';
/// Almost all CSS nodes are the modifiable classes under the covers. However,
/// modification should only be done within the evaluation step, so the
/// unmodifiable types are used elsewhere to enforce that constraint.
abstract class ModifiableCssNode extends CssNode {
abstract base class ModifiableCssNode extends CssNode {
/// The node that contains this, or `null` for the root [CssStylesheet] node.
ModifiableCssParentNode? get parent => _parent;
ModifiableCssParentNode? _parent;
Expand Down Expand Up @@ -43,16 +43,15 @@ abstract class ModifiableCssNode extends CssNode {
}

parent._children.removeAt(_indexInParent!);
for (var i = _indexInParent!; i < parent._children.length; i++) {
var child = parent._children[i];
for (var child in parent._children.skip(_indexInParent!)) {
child._indexInParent = child._indexInParent! - 1;
}
_parent = null;
}
}

/// A modifiable version of [CssParentNode] for use in the evaluation step.
abstract class ModifiableCssParentNode extends ModifiableCssNode
abstract base class ModifiableCssParentNode extends ModifiableCssNode
implements CssParentNode {
final List<ModifiableCssNode> children;
final List<ModifiableCssNode> _children;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/ast/css/modifiable/style_rule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import '../style_rule.dart';
import 'node.dart';

/// A modifiable version of [CssStyleRule] for use in the evaluation step.
class ModifiableCssStyleRule extends ModifiableCssParentNode
final class ModifiableCssStyleRule extends ModifiableCssParentNode
implements CssStyleRule {
SelectorList get selector => _selector.value;

Expand Down
2 changes: 1 addition & 1 deletion lib/src/ast/css/modifiable/stylesheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import '../stylesheet.dart';
import 'node.dart';

/// A modifiable version of [CssStylesheet] for use in the evaluation step.
class ModifiableCssStylesheet extends ModifiableCssParentNode
final class ModifiableCssStylesheet extends ModifiableCssParentNode
implements CssStylesheet {
final FileSpan span;

Expand Down
2 changes: 1 addition & 1 deletion lib/src/ast/css/modifiable/supports_rule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import '../value.dart';
import 'node.dart';

/// A modifiable version of [CssSupportsRule] for use in the evaluation step.
class ModifiableCssSupportsRule extends ModifiableCssParentNode
final class ModifiableCssSupportsRule extends ModifiableCssParentNode
implements CssSupportsRule {
final CssValue<String> condition;
final FileSpan span;
Expand Down
6 changes: 4 additions & 2 deletions lib/src/ast/css/node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import 'comment.dart';
import 'style_rule.dart';

/// A statement in a plain CSS syntax tree.
abstract class CssNode extends AstNode {
@sealed
abstract class CssNode implements AstNode {
/// Whether this was generated from the last node in a nested Sass tree that
/// got flattened during evaluation.
bool get isGroupEnd;
Expand Down Expand Up @@ -43,12 +44,13 @@ abstract class CssNode extends AstNode {
bool get isInvisibleHidingComments => accept(
const _IsInvisibleVisitor(includeBogus: true, includeComments: true));

String toString() => serialize(this, inspect: true).css;
String toString() => serialize(this, inspect: true).$1;
}

// NOTE: New at-rule implementations should add themselves to [AtRootRule]'s
// exclude logic.
/// A [CssNode] that can have child statements.
@sealed
abstract class CssParentNode extends CssNode {
/// The child statements of this node.
List<CssNode> get children;
Expand Down
5 changes: 1 addition & 4 deletions lib/src/ast/css/style_rule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import '../../visitor/interface/css.dart';
import '../selector.dart';
import 'node.dart';

Expand All @@ -11,12 +10,10 @@ import 'node.dart';
/// This applies style declarations to elements that match a given selector.
/// Note that this isn't *strictly* plain CSS, since [selector] may still
/// contain placeholder selectors.
abstract class CssStyleRule extends CssParentNode {
abstract interface class CssStyleRule implements CssParentNode {
/// The selector for this rule.
SelectorList get selector;

/// The selector for this rule, before any extensions were applied.
SelectorList get originalSelector;

T accept<T>(CssVisitor<T> visitor) => visitor.visitCssStyleRule(this);
}
Loading

0 comments on commit 51b4e5c

Please sign in to comment.