Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't rewrite source maps for @layer rules #8971

Merged
merged 3 commits into from Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -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))
Expand Down
6 changes: 5 additions & 1 deletion src/lib/generateRules.js
Expand Up @@ -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
}
Expand Down
6 changes: 4 additions & 2 deletions src/lib/setupContextUtils.js
Expand Up @@ -289,6 +289,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
},
addComponents(components, options) {
let defaultOptions = {
preserveSource: false,
respectPrefix: true,
respectImportant: false,
}
Expand All @@ -311,6 +312,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
},
addUtilities(utilities, options) {
let defaultOptions = {
preserveSource: false,
respectPrefix: true,
respectImportant: true,
}
Expand Down Expand Up @@ -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()
Expand Down
6 changes: 5 additions & 1 deletion src/util/cloneNodes.js
Expand Up @@ -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) {
Expand Down
14 changes: 14 additions & 0 deletions tests/__snapshots__/source-maps.test.js.snap
Expand Up @@ -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",
]
`;
52 changes: 47 additions & 5 deletions 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 () => {
Expand Down Expand Up @@ -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()
})

Expand All @@ -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()
})

Expand All @@ -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'])
})

Expand All @@ -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()
})
2 changes: 1 addition & 1 deletion tests/util/run.js
Expand Up @@ -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: [],
Expand Down