Skip to content

Commit a1346c9

Browse files
Don't rewrite source maps for @layer rules (#8971)
* Cleanup * Don’t rewrite source maps for `@layer` rules * Update changelog
1 parent da268f6 commit a1346c9

File tree

7 files changed

+80
-10
lines changed

7 files changed

+80
-10
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- Don't rewrite source maps for `@layer` rules ([#8971](https://github.com/tailwindlabs/tailwindcss/pull/8971))
13+
1014
### Added
1115

1216
- Added types for `resolveConfig` ([#8924](https://github.com/tailwindlabs/tailwindcss/pull/8924))

src/lib/generateRules.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,11 @@ function splitWithSeparator(input, separator) {
471471

472472
function* recordCandidates(matches, classCandidate) {
473473
for (const match of matches) {
474-
match[1].raws.tailwind = { ...match[1].raws.tailwind, classCandidate }
474+
match[1].raws.tailwind = {
475+
...match[1].raws.tailwind,
476+
classCandidate,
477+
preserveSource: match[0].options?.preserveSource ?? false,
478+
}
475479

476480
yield match
477481
}

src/lib/setupContextUtils.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
289289
},
290290
addComponents(components, options) {
291291
let defaultOptions = {
292+
preserveSource: false,
292293
respectPrefix: true,
293294
respectImportant: false,
294295
}
@@ -311,6 +312,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
311312
},
312313
addUtilities(utilities, options) {
313314
let defaultOptions = {
315+
preserveSource: false,
314316
respectPrefix: true,
315317
respectImportant: true,
316318
}
@@ -579,14 +581,14 @@ function collectLayerPlugins(root) {
579581
} else if (layerRule.params === 'components') {
580582
for (let node of layerRule.nodes) {
581583
layerPlugins.push(function ({ addComponents }) {
582-
addComponents(node, { respectPrefix: false })
584+
addComponents(node, { respectPrefix: false, preserveSource: true })
583585
})
584586
}
585587
layerRule.remove()
586588
} else if (layerRule.params === 'utilities') {
587589
for (let node of layerRule.nodes) {
588590
layerPlugins.push(function ({ addUtilities }) {
589-
addUtilities(node, { respectPrefix: false })
591+
addUtilities(node, { respectPrefix: false, preserveSource: true })
590592
})
591593
}
592594
layerRule.remove()

src/util/cloneNodes.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ export default function cloneNodes(nodes, source = undefined, raws = undefined)
22
return nodes.map((node) => {
33
let cloned = node.clone()
44

5-
if (source !== undefined) {
5+
// We always want override the source map
6+
// except when explicitly told not to
7+
let shouldOverwriteSource = node.raws.tailwind?.preserveSource !== true || !cloned.source
8+
9+
if (source !== undefined && shouldOverwriteSource) {
610
cloned.source = source
711

812
if ('walk' in cloned) {

tests/__snapshots__/source-maps.test.js.snap

+14
Original file line numberDiff line numberDiff line change
@@ -347,3 +347,17 @@ Array [
347347
"2:18 -> 440:0",
348348
]
349349
`;
350+
351+
exports[`source maps for layer rules are not rewritten to point to @tailwind directives 1`] = `
352+
Array [
353+
"2:6 -> 1:0",
354+
"2:6 -> 2:10",
355+
"2:25 -> 3:0",
356+
"3:8 -> 4:8",
357+
"4:10-31 -> 5:10-31",
358+
"5:8 -> 6:8",
359+
"3:8 -> 7:8",
360+
"4:10-31 -> 8:10-31",
361+
"5:8 -> 9:8",
362+
]
363+
`;

tests/source-maps.test.js

+47-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { runWithSourceMaps as run, html, css } from './util/run'
1+
import postcss from 'postcss'
2+
import { runWithSourceMaps as run, html, css, map } from './util/run'
23
import { parseSourceMaps } from './util/source-maps'
34

45
it('apply generates source maps', async () => {
@@ -39,7 +40,6 @@ it('apply generates source maps', async () => {
3940
expect(sources).not.toContain('<no source>')
4041
expect(sources.length).toBe(1)
4142

42-
// It would make the tests nicer to read and write
4343
expect(annotations).toMatchSnapshot()
4444
})
4545

@@ -60,7 +60,6 @@ it('preflight + base have source maps', async () => {
6060
expect(sources).not.toContain('<no source>')
6161
expect(sources.length).toBe(1)
6262

63-
// It would make the tests nicer to read and write
6463
expect(annotations).toMatchSnapshot()
6564
})
6665

@@ -81,7 +80,6 @@ it('utilities have source maps', async () => {
8180
expect(sources).not.toContain('<no source>')
8281
expect(sources.length).toBe(1)
8382

84-
// It would make the tests nicer to read and write
8583
expect(annotations).toStrictEqual(['2:4 -> 1:0', '2:4-23 -> 2:4-24', '2:4 -> 3:4', '2:23 -> 4:0'])
8684
})
8785

@@ -102,6 +100,50 @@ it('components have source maps', async () => {
102100
expect(sources).not.toContain('<no source>')
103101
expect(sources.length).toBe(1)
104102

105-
// It would make the tests nicer to read and write
103+
expect(annotations).toMatchSnapshot()
104+
})
105+
106+
it('source maps for layer rules are not rewritten to point to @tailwind directives', async () => {
107+
let config = {
108+
content: [{ raw: `font-normal foo hover:foo` }],
109+
}
110+
111+
let utilitiesFile = postcss.parse(
112+
css`
113+
@tailwind utilities;
114+
`,
115+
{ from: 'components.css', map: { prev: map } }
116+
)
117+
118+
let mainCssFile = postcss.parse(
119+
css`
120+
@layer utilities {
121+
.foo {
122+
background-color: red;
123+
}
124+
}
125+
`,
126+
{ from: 'input.css', map: { prev: map } }
127+
)
128+
129+
// Just pretend that there's an @import in `mainCssFile` that imports the nodes from `utilitiesFile`
130+
let input = postcss.root({
131+
nodes: [...utilitiesFile.nodes, ...mainCssFile.nodes],
132+
source: mainCssFile.source,
133+
})
134+
135+
let result = await run(input, config)
136+
137+
let { sources, annotations } = parseSourceMaps(result)
138+
139+
// All CSS generated by Tailwind CSS should be annotated with source maps
140+
// And always be able to point to the original source file
141+
expect(sources).not.toContain('<no source>')
142+
143+
// And we should see that the source map for the layer rule is not rewritten
144+
// to point to the @tailwind directive but instead points to the original
145+
expect(sources.length).toBe(2)
146+
expect(sources).toEqual(['components.css', 'input.css'])
147+
106148
expect(annotations).toMatchSnapshot()
107149
})

tests/util/run.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import tailwind from '../../src'
55
export * from './strings'
66
export * from './defaults'
77

8-
let map = JSON.stringify({
8+
export let map = JSON.stringify({
99
version: 3,
1010
file: null,
1111
sources: [],

0 commit comments

Comments
 (0)