Repository: tailwindlabs/tailwindcss (TypeScript)

Issue:
Duplicate @import CSS rules cause undefined behaviour
**What version of Tailwind CSS are you using?**

v3.0.24

**What build tool (or framework if it abstracts the build tool) are you using?**

vite 2.9.1

**What version of Node.js are you using?**

v16.11.0

**What browser are you using?**

N/A

**What operating system are you using?**

Linux

**Reproduction URL**

https://github.com/jordimarimon/tailwindcss-duplicate-imports

**Describe your issue**

Hi!

First of all, thanks for this amazing library!

I am using a third party library that I can't modify and this library has duplicate `@import` CSS rules.

Because of this duplicate `@import` CSS rules I get the following error from the Tailwind PostCSS plugin:

```
TypeError: Cannot read properties of undefined (reading 'type')
    at AtRule.normalize (<path-to-project>/tailwindcss-duplicate-imports/node_modules/postcss/lib/container.js:294:22)
    at AtRule.append (<path-to-project>/tailwindcss-duplicate-imports/node_modules/postcss/lib/container.js:147:24)
    at AtRule.append (<path-to-project>/tailwindcss-duplicate-imports/node_modules/postcss/lib/at-rule.js:13:18)
    at <path-to-project>/tailwindcss-duplicate-imports/node_modules/tailwindcss/lib/lib/collapseAdjacentRules.js:24:29
    at Root.each (<path-to-project>/tailwindcss-duplicate-imports/node_modules/postcss/lib/container.js:41:16)
    at collapseRulesIn (<path-to-project>/tailwindcss-duplicate-imports/node_modules/tailwindcss/lib/lib/collapseAdjacentRules.js:9:14)
    at <path-to-project>/tailwindcss-duplicate-imports/node_modules/tailwindcss/lib/lib/collapseAdjacentRules.js:42:9
    at <path-to-project>/tailwindcss-duplicate-imports/node_modules/tailwindcss/lib/processTailwindFeatures.js:51:53
    at plugins (<path-to-project>/tailwindcss-duplicate-imports/node_modules/tailwindcss/lib/index.js:33:58)
    at LazyResult.runOnRoot (<path-to-project>/tailwindcss-duplicate-imports/node_modules/postcss/lib/lazy-result.js:339:16)
```

In the repository that I have shared, after running `npm install`, there are three types of builds (see the NPM scripts in the package.json):

- Build with TailwindCSS CLI -> works because the `@import` rule is not being resolved
- Build with PostCSS CLI -> works until I add the `postcss-import` plugin
- Build with [Vite](https://vitejs.dev/) -> Fails with the error above

If you look at the `src/input.css` file you will see that I import two files that have the same `@import` rule.

If I remove or change one of the duplicate rules, the build works fine.

The problem I have, in my real project, is that the duplicate `@import` rules are from a third party library... and I can't modify it.

I have cloned the TailwindCSS repository and link it locally to debug it and the line where I have found the problem is here:

https://github.com/tailwindlabs/tailwindcss/blob/master/src/lib/collapseAdjacentRules.js#L32

It seems like `node.nodes` is undefined.

Also, in my real project I'm not using Vite, I'm using the Angular CLI. The error also happens there.

The problem is solved if, in the TailwindCSS plugin, I check if `node.nodes` exist before calling `currentRule.append(node.nodes)`. 

But I'm not sure if this is the correct solution. I'm not even sure if this is a problem of the TailwindCSS plugin.




Hints:

Patch:
diff --git a/src/lib/collapseAdjacentRules.js b/src/lib/collapseAdjacentRules.js
--- a/src/lib/collapseAdjacentRules.js
+++ b/src/lib/collapseAdjacentRules.js
@@ -29,7 +29,11 @@ export default function collapseAdjacentRules() {
             (currentRule[property] ?? '').replace(/\s+/g, ' ')
         )
       ) {
-        currentRule.append(node.nodes)
+        // An AtRule may not have children (for example if we encounter duplicate @import url(…) rules)
+        if (node.nodes) {
+          currentRule.append(node.nodes)
+        }
+
         node.remove()
       } else {
         currentRule = node


Test patch:
diff --git a/tests/collapse-adjacent-rules.test.js b/tests/collapse-adjacent-rules.test.js
--- a/tests/collapse-adjacent-rules.test.js
+++ b/tests/collapse-adjacent-rules.test.js
@@ -1,7 +1,7 @@
 import fs from 'fs'
 import path from 'path'
 
-import { run, css } from './util/run'
+import { run, html, css } from './util/run'
 
 test('collapse adjacent rules', () => {
   let config = {
@@ -61,3 +61,21 @@ test('collapse adjacent rules', () => {
     expect(result.css).toMatchFormattedCss(expected)
   })
 })
+
+test('duplicate url imports does not break rule collapsing', () => {
+  let config = {
+    content: [{ raw: html`` }],
+    corePlugins: { preflight: false },
+  }
+
+  let input = css`
+    @import url('https://example.com');
+    @import url('https://example.com');
+  `
+
+  return run(input, config).then((result) => {
+    expect(result.css).toMatchFormattedCss(css`
+      @import url('https://example.com');
+    `)
+  })
+})