Skip to content

Commit

Permalink
Deprecated mixed declarations (#2267)
Browse files Browse the repository at this point in the history
  • Loading branch information
nex3 authored Jul 9, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 1edc247 commit 7203d65
Showing 8 changed files with 81 additions and 24 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## 1.77.7

* Declarations that appear after nested rules are deprecated, because the
semantics Sass has historically used are different from the semantics
specified by CSS. In the future, Sass will adopt the standard CSS semantics.

See [the Sass website](https://sass-lang.com/d/mixed-decls) for details.

* **Potentially breaking bug fix:** `//` in certain places such as unknown
at-rule values was being preserved in the CSS output, leading to potentially
invalid CSS. It's now properly parsed as a silent comment and omitted from the
7 changes: 6 additions & 1 deletion lib/src/deprecation.dart
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ enum Deprecation {
// DO NOT EDIT. This section was generated from the language repo.
// See tool/grind/generate_deprecations.dart for details.
//
// Checksum: 22d9bdbe92eb39b3c0d6d64ebe1879a431c0037e
// Checksum: 309e4f1f008f08379b824ab6094e13df2e18e187

/// Deprecation for passing a string directly to meta.call().
callString('call-string',
@@ -90,6 +90,11 @@ enum Deprecation {
deprecatedIn: '1.76.0',
description: 'Function and mixin names beginning with --.'),

/// Deprecation for declarations after or between nested rules.
mixedDecls('mixed-decls',
deprecatedIn: '1.77.7',
description: 'Declarations after or between nested rules.'),

/// Deprecation for @import rules.
import.future('import', description: '@import rules.'),

6 changes: 3 additions & 3 deletions lib/src/parse/css.dart
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ class CssParser extends ScssParser {
}

Statement atRule(Statement child(), {bool root = false}) {
// NOTE: this logic is largely duplicated in CssParser.atRule. Most changes
// NOTE: this logic is largely duplicated in StylesheetParser.atRule. Most changes
// here should be mirrored there.

var start = scanner.state;
@@ -65,7 +65,7 @@ class CssParser extends ScssParser {
"return" ||
"warn" ||
"while" =>
_forbiddenAtRoot(start),
_forbiddenAtRule(start),
"import" => _cssImportRule(start),
"media" => mediaRule(start),
"-moz-document" => mozDocumentRule(start, name),
@@ -75,7 +75,7 @@ class CssParser extends ScssParser {
}

/// Throws an error for a forbidden at-rule.
Never _forbiddenAtRoot(LineScannerState start) {
Never _forbiddenAtRule(LineScannerState start) {
almostAnyValue();
error("This at-rule isn't allowed in plain CSS.", scanner.spanFrom(start));
}
37 changes: 29 additions & 8 deletions lib/src/visitor/async_evaluate.dart
Original file line number Diff line number Diff line change
@@ -1189,6 +1189,22 @@ final class _EvaluateVisitor
node.span);
}

if (_parent.parent!.children.last case var sibling
when _parent != sibling) {
_warn(
"Sass's behavior for declarations that appear after nested\n"
"rules will be changing to match the behavior specified by CSS in an "
"upcoming\n"
"version. To keep the existing behavior, move the declaration above "
"the nested\n"
"rule. To opt into the new behavior, wrap the declaration in `& "
"{}`.\n"
"\n"
"More info: https://sass-lang.com/d/mixed-decls",
MultiSpan(node.span, 'declaration', {sibling.span: 'nested rule'}),
Deprecation.mixedDecls);
}

var name = await _interpolationToValue(node.name, warnForColor: true);
if (_declarationName case var declarationName?) {
name = CssValue("$declarationName-${name.value}", name.span);
@@ -2065,8 +2081,20 @@ final class _EvaluateVisitor
scopeWhen: node.hasDeclarations);
_atRootExcludingStyleRule = oldAtRootExcludingStyleRule;

_warnForBogusCombinators(rule);

if (_styleRule == null && _parent.children.isNotEmpty) {
var lastChild = _parent.children.last;
lastChild.isGroupEnd = true;
}

return null;
}

/// Emits deprecation warnings for any bogus combinators in [rule].
void _warnForBogusCombinators(CssStyleRule rule) {
if (!rule.isInvisibleOtherThanBogusCombinators) {
for (var complex in parsedSelector.components) {
for (var complex in rule.selector.components) {
if (!complex.isBogus) continue;

if (complex.isUseless) {
@@ -2110,13 +2138,6 @@ final class _EvaluateVisitor
}
}
}

if (_styleRule == null && _parent.children.isNotEmpty) {
var lastChild = _parent.children.last;
lastChild.isGroupEnd = true;
}

return null;
}

Future<Value?> visitSupportsRule(SupportsRule node) async {
39 changes: 30 additions & 9 deletions lib/src/visitor/evaluate.dart
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_evaluate.dart.
// See tool/grind/synchronize.dart for details.
//
// Checksum: 116b8079719577ac6e4dad4aebe403282136e611
// Checksum: ebf292c26dcfdd7f61fd70ce3dc9e0be2b6708b3
//
// ignore_for_file: unused_import

@@ -1187,6 +1187,22 @@ final class _EvaluateVisitor
node.span);
}

if (_parent.parent!.children.last case var sibling
when _parent != sibling) {
_warn(
"Sass's behavior for declarations that appear after nested\n"
"rules will be changing to match the behavior specified by CSS in an "
"upcoming\n"
"version. To keep the existing behavior, move the declaration above "
"the nested\n"
"rule. To opt into the new behavior, wrap the declaration in `& "
"{}`.\n"
"\n"
"More info: https://sass-lang.com/d/mixed-decls",
MultiSpan(node.span, 'declaration', {sibling.span: 'nested rule'}),
Deprecation.mixedDecls);
}

var name = _interpolationToValue(node.name, warnForColor: true);
if (_declarationName case var declarationName?) {
name = CssValue("$declarationName-${name.value}", name.span);
@@ -2055,8 +2071,20 @@ final class _EvaluateVisitor
scopeWhen: node.hasDeclarations);
_atRootExcludingStyleRule = oldAtRootExcludingStyleRule;

_warnForBogusCombinators(rule);

if (_styleRule == null && _parent.children.isNotEmpty) {
var lastChild = _parent.children.last;
lastChild.isGroupEnd = true;
}

return null;
}

/// Emits deprecation warnings for any bogus combinators in [rule].
void _warnForBogusCombinators(CssStyleRule rule) {
if (!rule.isInvisibleOtherThanBogusCombinators) {
for (var complex in parsedSelector.components) {
for (var complex in rule.selector.components) {
if (!complex.isBogus) continue;

if (complex.isUseless) {
@@ -2100,13 +2128,6 @@ final class _EvaluateVisitor
}
}
}

if (_styleRule == null && _parent.children.isNotEmpty) {
var lastChild = _parent.children.last;
lastChild.isGroupEnd = true;
}

return null;
}

Value? visitSupportsRule(SupportsRule node) {
4 changes: 4 additions & 0 deletions pkg/sass_api/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 10.4.7

* No user-visible changes.

## 10.4.6

* No user-visible changes.
4 changes: 2 additions & 2 deletions pkg/sass_api/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -2,15 +2,15 @@ name: sass_api
# Note: Every time we add a new Sass AST node, we need to bump the *major*
# version because it's a breaking change for anyone who's implementing the
# visitor interface(s).
version: 10.4.6
version: 10.4.7
description: Additional APIs for Dart Sass.
homepage: https://github.com/sass/dart-sass

environment:
sdk: ">=3.0.0 <4.0.0"

dependencies:
sass: 1.77.6
sass: 1.77.7

dev_dependencies:
dartdoc: ">=6.0.0 <9.0.0"
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: sass
version: 1.77.7-dev
version: 1.77.7
description: A Sass implementation in Dart.
homepage: https://github.com/sass/dart-sass

0 comments on commit 7203d65

Please sign in to comment.