diff --git a/CHANGELOG.md b/CHANGELOG.md index a894856d1598..26a6042efa37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Don't rewrite source maps for `@layer` rules ([#8971](https://github.com/tailwindlabs/tailwindcss/pull/8971)) + ### Added - Added types for `resolveConfig` ([#8924](https://github.com/tailwindlabs/tailwindcss/pull/8924)) diff --git a/src/lib/generateRules.js b/src/lib/generateRules.js index e1cad8f7d9b2..b7843258108b 100644 --- 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 index 46ad6745ac7e..b0552b05d50c 100644 --- 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 index 05f9ae534f4a..299dd63b3e2e 100644 --- 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) { diff --git a/tests/__snapshots__/source-maps.test.js.snap b/tests/__snapshots__/source-maps.test.js.snap index 18a93a82bf1e..6bab9007d240 100644 --- 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 index bc5d63b7f216..04892c5ce066 100644 --- 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('') 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('') 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('') 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('') 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('') + + // 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 index d14b398af5b5..2d458942e2b2 100644 --- 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: [],