Repository: stylelint-scss/stylelint-scss
Pull request #860 (2023-09-27 19:58:05)

Add `--fix` to `at-root-no-redundant`.
Add fix to `at-root-no-redundant` by removing the redundant `@at-root` rule from the node string and parsing / appending the new node.


Patch:
diff --git a/src/rules/at-root-no-redundant/index.js b/src/rules/at-root-no-redundant/index.js
index 86a9232..695f659 100644
--- a/src/rules/at-root-no-redundant/index.js
+++ b/src/rules/at-root-no-redundant/index.js
@@ -25,7 +25,7 @@ const meta = {
   url: ruleUrl(ruleName)
 };
 
-function rule(actual) {
+function rule(actual, _, context) {
   return (root, result) => {
     const validOptions = utils.validateOptions(result, ruleName, {
       actual
@@ -41,6 +41,12 @@ function rule(actual) {
         node.params.replace(/#{.*}/g, "").includes("&") ||
         isWithinKeyframes(node)
       ) {
+        if (context.fix) {
+          node.after(node.toString().replace(/@at-root\s/, ""));
+          node.next().raws = node.raws;
+          node.remove();
+          return;
+        }
         utils.report({
           message: messages.rejected,
           node,


Test patch:
diff --git a/src/rules/at-root-no-redundant/__tests__/index.js b/src/rules/at-root-no-redundant/__tests__/index.js
index 0985db3..c1c9a7a 100644
--- a/src/rules/at-root-no-redundant/__tests__/index.js
+++ b/src/rules/at-root-no-redundant/__tests__/index.js
@@ -38,7 +38,7 @@ testRule({
             from {
               transform: translateX(0%);
             }
-          
+
             to {
               transform: translateX(100%);
             }
@@ -50,13 +50,13 @@ testRule({
     {
       code: `
       @mixin foo {}
-      
+
       @keyframes slidein {
         from {
           @include foo;
           transform: translateX(0%);
         }
-      
+
         to {
           transform: translateX(100%);
         }
@@ -100,7 +100,7 @@ testRule({
         @at-root from {
           transform: translateX(0%);
         }
-      
+
         to {
           transform: translateX(100%);
         }
@@ -122,7 +122,7 @@ testRule({
                 transform: translateX(0%);
               }
         }
-      
+
         to {
           transform: translateX(100%);
         }
@@ -134,3 +134,71 @@ testRule({
     }
   ]
 });
+
+// Test with fix
+testRule({
+  ruleName,
+  config: [true],
+  customSyntax: "postcss-scss",
+  fix: true,
+  only: true,
+
+  accept: [
+    {
+      code: `
+      .a { @at-root .b { c: d } }
+      `,
+      description: "@at-root rule is nested."
+    }
+  ],
+  reject: [
+    {
+      code: `
+      .a { @at-root .b { c: d } }
+      @at-root .a { b: c; }`,
+      fixed: `
+      .a { @at-root .b { c: d } }
+      .a { b: c; }`,
+      line: 3,
+      column: 7,
+      message: messages.rejected,
+      description: "@at-root rule is already in the root."
+    },
+    {
+      code: `
+      .a { @at-root .b & { c: d; } }`,
+      fixed: `
+      .a { .b & { c: d; } }`,
+      line: 2,
+      column: 12,
+      message: messages.rejected,
+      description: "@at-root is followed by a `&` outside an interpolation."
+    },
+    {
+      code: `
+      @keyframes slidein {
+        @at-root from {
+          transform: translateX(0%);
+        }
+
+        to {
+          transform: translateX(100%);
+        }
+      }`,
+      fixed: `
+      @keyframes slidein {
+        from {
+          transform: translateX(0%);
+        }
+
+        to {
+          transform: translateX(100%);
+        }
+      }`,
+      line: 3,
+      column: 9,
+      message: messages.rejected,
+      description: "@at-root inside a @keyframes block, nested."
+    }
+  ]
+});