Repository: postcss/postcss-import
Pull request #572 (2025-02-09 14:11:58)

Update dependency prettier to ~3.5.0
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [prettier](https://prettier.io) ([source](https://redirect.github.com/prettier/prettier)) | [`~3.4.0` -> `~3.5.0`](https://renovatebot.com/diffs/npm/prettier/3.4.2/3.5.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/3.4.2/3.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/3.4.2/3.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>prettier/prettier (prettier)</summary>

### [`v3.5.0`](https://redirect.github.com/prettier/prettier/blob/HEAD/CHANGELOG.md#350)

[Compare Source](https://redirect.github.com/prettier/prettier/compare/3.4.2...3.5.0)

[diff](https://redirect.github.com/prettier/prettier/compare/3.4.2...3.5.0)

🔗 [Release Notes](https://prettier.io/blog/2025/02/09/3.5.0.html)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/postcss/postcss-import).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjQuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2NC4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbImRlcHMiXX0=-->



Patch:
diff --git a/lib/apply-conditions.js b/lib/apply-conditions.js
index 76a8475..2005c6b 100644
--- a/lib/apply-conditions.js
+++ b/lib/apply-conditions.js
@@ -3,12 +3,38 @@
 const base64EncodedConditionalImport = require("./base64-encoded-import")
 
 module.exports = function applyConditions(bundle, atRule) {
-  bundle.forEach(stmt => {
+  const firstImportStatementIndex = bundle.findIndex(
+    stmt => stmt.type === "import",
+  )
+  const lastImportStatementIndex = bundle.findLastIndex(
+    stmt => stmt.type === "import",
+  )
+
+  bundle.forEach((stmt, index) => {
+    if (stmt.type === "charset" || stmt.type === "warning") {
+      return
+    }
+
     if (
-      stmt.type === "charset" ||
-      stmt.type === "warning" ||
-      !stmt.conditions?.length
+      stmt.type === "layer" &&
+      ((index < lastImportStatementIndex && stmt.conditions?.length) ||
+        (index > firstImportStatementIndex && index < lastImportStatementIndex))
     ) {
+      stmt.type = "import"
+      stmt.node = stmt.node.clone({
+        name: "import",
+        params: base64EncodedConditionalImport(
+          `'data:text/css;base64,${Buffer.from(stmt.node.toString()).toString(
+            "base64",
+          )}'`,
+          stmt.conditions,
+        ),
+      })
+
+      return
+    }
+
+    if (!stmt.conditions?.length) {
       return
     }
 
@@ -20,8 +46,15 @@ module.exports = function applyConditions(bundle, atRule) {
       return
     }
 
-    const { nodes } = stmt
-    const { parent } = nodes[0]
+    let nodes
+    let parent
+    if (stmt.type === "layer") {
+      nodes = [stmt.node]
+      parent = stmt.node.parent
+    } else {
+      nodes = stmt.nodes
+      parent = nodes[0].parent
+    }
 
     const atRules = []
 
diff --git a/lib/apply-styles.js b/lib/apply-styles.js
index ca961b1..a92e7ff 100644
--- a/lib/apply-styles.js
+++ b/lib/apply-styles.js
@@ -5,7 +5,7 @@ module.exports = function applyStyles(bundle, styles) {
 
   // Strip additional statements.
   bundle.forEach(stmt => {
-    if (["charset", "import"].includes(stmt.type)) {
+    if (["charset", "import", "layer"].includes(stmt.type)) {
       stmt.node.parent = undefined
       styles.append(stmt.node)
     } else if (stmt.type === "nodes") {
diff --git a/lib/base64-encoded-import.js b/lib/base64-encoded-import.js
index a928c62..5e49779 100644
--- a/lib/base64-encoded-import.js
+++ b/lib/base64-encoded-import.js
@@ -8,6 +8,8 @@ const formatImportPrelude = require("./format-import-prelude")
 // To achieve this we create a list of base64 encoded imports, where each import contains a stylesheet with another import.
 // Each import can define a single group of conditions and a single cascade layer.
 module.exports = function base64EncodedConditionalImport(prelude, conditions) {
+  if (!conditions?.length) return prelude
+
   conditions.reverse()
   const first = conditions.pop()
   let params = `${prelude} ${formatImportPrelude(
diff --git a/lib/parse-statements.js b/lib/parse-statements.js
index 788193a..3df0bad 100644
--- a/lib/parse-statements.js
+++ b/lib/parse-statements.js
@@ -9,6 +9,7 @@ const { stringify } = valueParser
 module.exports = function parseStatements(result, styles, conditions, from) {
   const statements = []
   let nodes = []
+  let encounteredNonImportNodes = false
 
   styles.each(node => {
     let stmt
@@ -17,6 +18,14 @@ module.exports = function parseStatements(result, styles, conditions, from) {
         stmt = parseImport(result, node, conditions, from)
       else if (node.name === "charset")
         stmt = parseCharset(result, node, conditions, from)
+      else if (
+        node.name === "layer" &&
+        !encounteredNonImportNodes &&
+        !node.nodes
+      )
+        stmt = parseLayer(result, node, conditions, from)
+    } else if (node.type !== "comment") {
+      encounteredNonImportNodes = true
     }
 
     if (stmt) {
@@ -233,3 +242,12 @@ function parseImport(result, atRule, conditions, from) {
 
   return stmt
 }
+
+function parseLayer(result, atRule, conditions, from) {
+  return {
+    type: "layer",
+    node: atRule,
+    conditions: [...conditions],
+    from,
+  }
+}
diff --git a/lib/parse-styles.js b/lib/parse-styles.js
index 9dd43d7..766de9c 100644
--- a/lib/parse-styles.js
+++ b/lib/parse-styles.js
@@ -33,7 +33,7 @@ async function parseStyles(
   }
 
   let charset
-  const imports = []
+  const beforeBundle = []
   const bundle = []
 
   function handleCharset(stmt) {
@@ -56,19 +56,24 @@ async function parseStyles(
     else if (stmt.type === "import") {
       if (stmt.children) {
         stmt.children.forEach((child, index) => {
-          if (child.type === "import") imports.push(child)
+          if (child.type === "import") beforeBundle.push(child)
+          else if (child.type === "layer") beforeBundle.push(child)
           else if (child.type === "charset") handleCharset(child)
           else bundle.push(child)
           // For better output
           if (index === 0) child.parent = stmt
         })
-      } else imports.push(stmt)
+      } else beforeBundle.push(stmt)
+    } else if (stmt.type === "layer") {
+      beforeBundle.push(stmt)
     } else if (stmt.type === "nodes") {
       bundle.push(stmt)
     }
   })
 
-  return charset ? [charset, ...imports.concat(bundle)] : imports.concat(bundle)
+  return charset
+    ? [charset, ...beforeBundle.concat(bundle)]
+    : beforeBundle.concat(bundle)
 }
 
 async function resolveImportId(result, stmt, options, state, postcss) {
diff --git a/package.json b/package.json
index 2203501..6c61d3e 100644
--- a/package.json
+++ b/package.json
@@ -33,7 +33,7 @@
     "eslint-plugin-prettier": "^5.0.0",
     "postcss": "^8.0.0",
     "postcss-scss": "^4.0.0",
-    "prettier": "~3.4.0",
+    "prettier": "~3.5.0",
     "sugarss": "^5.0.0"
   },
   "peerDependencies": {


Test patch:
diff --git a/test/fixtures/imports/layer-followed-by-ignore.css b/test/fixtures/imports/layer-followed-by-ignore.css
new file mode 100644
index 0000000..13f9646
--- /dev/null
+++ b/test/fixtures/imports/layer-followed-by-ignore.css
@@ -0,0 +1,4 @@
+/* a comment */
+
+@layer layer-alpha;
+@import "http://css";
diff --git a/test/fixtures/imports/layer-only.css b/test/fixtures/imports/layer-only.css
new file mode 100644
index 0000000..9dc1acc
--- /dev/null
+++ b/test/fixtures/imports/layer-only.css
@@ -0,0 +1,1 @@
+@layer layer-beta;
diff --git a/test/fixtures/layer-followed-by-ignore-with-conditions.css b/test/fixtures/layer-followed-by-ignore-with-conditions.css
new file mode 100644
index 0000000..e5cf2e5
--- /dev/null
+++ b/test/fixtures/layer-followed-by-ignore-with-conditions.css
@@ -0,0 +1,2 @@
+@import "layer-only.css" print;
+@import "layer-followed-by-ignore.css" screen;
diff --git a/test/fixtures/layer-followed-by-ignore-with-conditions.expected.css b/test/fixtures/layer-followed-by-ignore-with-conditions.expected.css
new file mode 100644
index 0000000..3d1a219
--- /dev/null
+++ b/test/fixtures/layer-followed-by-ignore-with-conditions.expected.css
@@ -0,0 +1,6 @@
+@import 'data:text/css;base64,QGxheWVyIGxheWVyLWJldGE=' print;
+@import 'data:text/css;base64,QGxheWVyIGxheWVyLWFscGhh' screen;
+@import "http://css" screen;
+@media screen{
+/* a comment */
+}
diff --git a/test/fixtures/layer-followed-by-ignore-without-conditions.css b/test/fixtures/layer-followed-by-ignore-without-conditions.css
new file mode 100644
index 0000000..6b48f60
--- /dev/null
+++ b/test/fixtures/layer-followed-by-ignore-without-conditions.css
@@ -0,0 +1,3 @@
+@import "http://css-a";
+@import url("layer-only.css");
+@import "http://css-b";
diff --git a/test/fixtures/layer-followed-by-ignore-without-conditions.expected.css b/test/fixtures/layer-followed-by-ignore-without-conditions.expected.css
new file mode 100644
index 0000000..6e8818a
--- /dev/null
+++ b/test/fixtures/layer-followed-by-ignore-without-conditions.expected.css
@@ -0,0 +1,3 @@
+@import "http://css-a";
+@import 'data:text/css;base64,QGxheWVyIGxheWVyLWJldGE=';
+@import "http://css-b";
diff --git a/test/fixtures/layer-followed-by-ignore.css b/test/fixtures/layer-followed-by-ignore.css
new file mode 100644
index 0000000..1c4c793
--- /dev/null
+++ b/test/fixtures/layer-followed-by-ignore.css
@@ -0,0 +1,2 @@
+@layer layer-alpha;
+@import "http://css";
diff --git a/test/fixtures/layer-followed-by-ignore.expected.css b/test/fixtures/layer-followed-by-ignore.expected.css
new file mode 100644
index 0000000..1c4c793
--- /dev/null
+++ b/test/fixtures/layer-followed-by-ignore.expected.css
@@ -0,0 +1,2 @@
+@layer layer-alpha;
+@import "http://css";
diff --git a/test/fixtures/layer-statement-with-conditions.css b/test/fixtures/layer-statement-with-conditions.css
new file mode 100644
index 0000000..2256df4
--- /dev/null
+++ b/test/fixtures/layer-statement-with-conditions.css
@@ -0,0 +1,1 @@
+@import "layer-only.css" print;
diff --git a/test/fixtures/layer-statement-with-conditions.expected.css b/test/fixtures/layer-statement-with-conditions.expected.css
new file mode 100644
index 0000000..9f57df6
--- /dev/null
+++ b/test/fixtures/layer-statement-with-conditions.expected.css
@@ -0,0 +1,3 @@
+@media print{
+@layer layer-beta
+}
diff --git a/test/layer.js b/test/layer.js
index c80cc32..52236a6 100644
--- a/test/layer.js
+++ b/test/layer.js
@@ -33,3 +33,27 @@ test(
   checkFixture,
   "layer-duplicate-anonymous-imports-skip",
 )
+
+test(
+  "should correctly handle layer statements followed by ignored imports",
+  checkFixture,
+  "layer-followed-by-ignore",
+)
+
+test(
+  "should correctly handle layer statements followed by ignored imports in conditional imports",
+  checkFixture,
+  "layer-followed-by-ignore-with-conditions",
+)
+
+test(
+  "should correctly handle layer statements followed by ignored imports in unconditional imports",
+  checkFixture,
+  "layer-followed-by-ignore-without-conditions",
+)
+
+test(
+  "should correctly handle layer statements in conditional imports",
+  checkFixture,
+  "layer-statement-with-conditions",
+)