Repository: tailwindlabs/tailwindcss (TypeScript)

Issue:
Incorrect work of url() in css file when using vite.js
<!-- Please provide all of the information requested below. We're a small team and without all of this information it's not possible for us to help and your bug report will be closed. -->

**What version of Tailwind CSS are you using?**

"tailwindcss": "3.1.6"

**What build tool (or framework if it abstracts the build tool) are you using?**

"vite": "3.0.3"

**What version of Node.js are you using?**

v16.16.0

**What browser are you using?**

Any

**What operating system are you using?**

Windows (WSL2)

**Reproduction URL**
https://codesandbox.io/s/vite-tailwind-bug-jm7w9h

**Describe your issue**

If vite.config.js entry point is a style file, for example, for a classic backend, then the url() in css files are not processed.
But if I comment out the tilewindcss plugin in the postcss.config.js file, then everything works fine.

Result with tailwindcss: (not processed)
```
.test{background-image:url(img.svg)}
```
Result without tailwindcss: (processed)
```
.test{background-image:url(/img-8dac5379.svg)}
```


Hints:

Patch:
diff --git a/src/lib/generateRules.js b/src/lib/generateRules.js
--- a/src/lib/generateRules.js
+++ b/src/lib/generateRules.js
@@ -471,7 +471,11 @@ function splitWithSeparator(input, separator) {
 
 function* recordCandidates(matches, classCandidate) {
   for (const match of matches) {
-    match[1].raws.tailwind = { ...match[1].raws.tailwind, classCandidate }
+    match[1].raws.tailwind = {
+      ...match[1].raws.tailwind,
+      classCandidate,
+      preserveSource: match[0].options?.preserveSource ?? false,
+    }
 
     yield match
   }
diff --git a/src/lib/setupContextUtils.js b/src/lib/setupContextUtils.js
--- a/src/lib/setupContextUtils.js
+++ b/src/lib/setupContextUtils.js
@@ -289,6 +289,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
     },
     addComponents(components, options) {
       let defaultOptions = {
+        preserveSource: false,
         respectPrefix: true,
         respectImportant: false,
       }
@@ -311,6 +312,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
     },
     addUtilities(utilities, options) {
       let defaultOptions = {
+        preserveSource: false,
         respectPrefix: true,
         respectImportant: true,
       }
@@ -579,14 +581,14 @@ function collectLayerPlugins(root) {
     } else if (layerRule.params === 'components') {
       for (let node of layerRule.nodes) {
         layerPlugins.push(function ({ addComponents }) {
-          addComponents(node, { respectPrefix: false })
+          addComponents(node, { respectPrefix: false, preserveSource: true })
         })
       }
       layerRule.remove()
     } else if (layerRule.params === 'utilities') {
       for (let node of layerRule.nodes) {
         layerPlugins.push(function ({ addUtilities }) {
-          addUtilities(node, { respectPrefix: false })
+          addUtilities(node, { respectPrefix: false, preserveSource: true })
         })
       }
       layerRule.remove()
diff --git a/src/util/cloneNodes.js b/src/util/cloneNodes.js
--- a/src/util/cloneNodes.js
+++ b/src/util/cloneNodes.js
@@ -2,7 +2,11 @@ export default function cloneNodes(nodes, source = undefined, raws = undefined)
   return nodes.map((node) => {
     let cloned = node.clone()
 
-    if (source !== undefined) {
+    // We always want override the source map
+    // except when explicitly told not to
+    let shouldOverwriteSource = node.raws.tailwind?.preserveSource !== true || !cloned.source
+
+    if (source !== undefined && shouldOverwriteSource) {
       cloned.source = source
 
       if ('walk' in cloned) {


Test patch:
diff --git a/tests/__snapshots__/source-maps.test.js.snap b/tests/__snapshots__/source-maps.test.js.snap
--- a/tests/__snapshots__/source-maps.test.js.snap
+++ b/tests/__snapshots__/source-maps.test.js.snap
@@ -347,3 +347,17 @@ Array [
   "2:18 -> 440:0",
 ]
 `;
+
+exports[`source maps for layer rules are not rewritten to point to @tailwind directives 1`] = `
+Array [
+  "2:6 -> 1:0",
+  "2:6 -> 2:10",
+  "2:25 -> 3:0",
+  "3:8 -> 4:8",
+  "4:10-31 -> 5:10-31",
+  "5:8 -> 6:8",
+  "3:8 -> 7:8",
+  "4:10-31 -> 8:10-31",
+  "5:8 -> 9:8",
+]
+`;
diff --git a/tests/source-maps.test.js b/tests/source-maps.test.js
--- a/tests/source-maps.test.js
+++ b/tests/source-maps.test.js
@@ -1,4 +1,5 @@
-import { runWithSourceMaps as run, html, css } from './util/run'
+import postcss from 'postcss'
+import { runWithSourceMaps as run, html, css, map } from './util/run'
 import { parseSourceMaps } from './util/source-maps'
 
 it('apply generates source maps', async () => {
@@ -39,7 +40,6 @@ it('apply generates source maps', async () => {
   expect(sources).not.toContain('<no source>')
   expect(sources.length).toBe(1)
 
-  // It would make the tests nicer to read and write
   expect(annotations).toMatchSnapshot()
 })
 
@@ -60,7 +60,6 @@ it('preflight + base have source maps', async () => {
   expect(sources).not.toContain('<no source>')
   expect(sources.length).toBe(1)
 
-  // It would make the tests nicer to read and write
   expect(annotations).toMatchSnapshot()
 })
 
@@ -81,7 +80,6 @@ it('utilities have source maps', async () => {
   expect(sources).not.toContain('<no source>')
   expect(sources.length).toBe(1)
 
-  // It would make the tests nicer to read and write
   expect(annotations).toStrictEqual(['2:4 -> 1:0', '2:4-23 -> 2:4-24', '2:4 -> 3:4', '2:23 -> 4:0'])
 })
 
@@ -102,6 +100,50 @@ it('components have source maps', async () => {
   expect(sources).not.toContain('<no source>')
   expect(sources.length).toBe(1)
 
-  // It would make the tests nicer to read and write
+  expect(annotations).toMatchSnapshot()
+})
+
+it('source maps for layer rules are not rewritten to point to @tailwind directives', async () => {
+  let config = {
+    content: [{ raw: `font-normal foo hover:foo` }],
+  }
+
+  let utilitiesFile = postcss.parse(
+    css`
+      @tailwind utilities;
+    `,
+    { from: 'components.css', map: { prev: map } }
+  )
+
+  let mainCssFile = postcss.parse(
+    css`
+      @layer utilities {
+        .foo {
+          background-color: red;
+        }
+      }
+    `,
+    { from: 'input.css', map: { prev: map } }
+  )
+
+  // Just pretend that there's an @import in `mainCssFile` that imports the nodes from `utilitiesFile`
+  let input = postcss.root({
+    nodes: [...utilitiesFile.nodes, ...mainCssFile.nodes],
+    source: mainCssFile.source,
+  })
+
+  let result = await run(input, config)
+
+  let { sources, annotations } = parseSourceMaps(result)
+
+  // All CSS generated by Tailwind CSS should be annotated with source maps
+  // And always be able to point to the original source file
+  expect(sources).not.toContain('<no source>')
+
+  // And we should see that the source map for the layer rule is not rewritten
+  // to point to the @tailwind directive but instead points to the original
+  expect(sources.length).toBe(2)
+  expect(sources).toEqual(['components.css', 'input.css'])
+
   expect(annotations).toMatchSnapshot()
 })
diff --git a/tests/util/run.js b/tests/util/run.js
--- a/tests/util/run.js
+++ b/tests/util/run.js
@@ -5,7 +5,7 @@ import tailwind from '../../src'
 export * from './strings'
 export * from './defaults'
 
-let map = JSON.stringify({
+export let map = JSON.stringify({
   version: 3,
   file: null,
   sources: [],