Skip to content

Commit

Permalink
Fix wildcard duplication issue (#7478)
Browse files Browse the repository at this point in the history
This would be better as a symbol but the stringy-ness of class candidates is fairly well baked into assumptions across the codebase. Using `new String` with a well placed check seems to solve the problem.
  • Loading branch information
thecrypticace committed Feb 15, 2022
1 parent db475be commit be5d5c9
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Remove opacity variables from `:visited` pseudo class ([#7458](https://github.com/tailwindlabs/tailwindcss/pull/7458))
- Support arbitrary values + calc + theme with quotes ([#7462](https://github.com/tailwindlabs/tailwindcss/pull/7462))
- Don't duplicate layer output when scanning content with variants + wildcards ([#7478](https://github.com/tailwindlabs/tailwindcss/pull/7478))

## [3.0.22] - 2022-02-11

Expand Down
2 changes: 1 addition & 1 deletion src/lib/expandTailwindAtRules.js
Expand Up @@ -158,7 +158,7 @@ export default function expandTailwindAtRules(context) {
// ---

// Find potential rules in changed files
let candidates = new Set(['*'])
let candidates = new Set([sharedState.NOT_ON_DEMAND])
let seen = new Set()

env.DEBUG && console.time('Reading changed files')
Expand Down
5 changes: 5 additions & 0 deletions src/lib/generateRules.js
Expand Up @@ -5,6 +5,7 @@ import isPlainObject from '../util/isPlainObject'
import prefixSelector from '../util/prefixSelector'
import { updateAllClasses } from '../util/pluginUtils'
import log from '../util/log'
import * as sharedState from './sharedState'
import { formatVariantSelector, finalizeSelector } from '../util/formatVariantSelector'
import { asClass } from '../util/nameClass'
import { normalize } from '../util/dataTypes'
Expand Down Expand Up @@ -382,6 +383,10 @@ function* resolveMatchedPlugins(classCandidate, context) {
}

function splitWithSeparator(input, separator) {
if (input === sharedState.NOT_ON_DEMAND) {
return [sharedState.NOT_ON_DEMAND]
}

return input.split(new RegExp(`\\${separator}(?![^[]*\\])`, 'g'))
}

Expand Down
6 changes: 3 additions & 3 deletions src/lib/setupContextUtils.js
Expand Up @@ -138,7 +138,7 @@ function withIdentifiers(styles) {

// If this isn't "on-demandable", assign it a universal candidate to always include it.
if (containsNonOnDemandableSelectors) {
candidates.unshift('*')
candidates.unshift(sharedState.NOT_ON_DEMAND)
}

// However, it could be that it also contains "on-demandable" candidates.
Expand All @@ -163,8 +163,8 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
}

function prefixIdentifier(identifier, options) {
if (identifier === '*') {
return '*'
if (identifier === sharedState.NOT_ON_DEMAND) {
return sharedState.NOT_ON_DEMAND
}

if (!options.respectPrefix) {
Expand Down
1 change: 1 addition & 0 deletions src/lib/sharedState.js
Expand Up @@ -5,6 +5,7 @@ export const env = {
export const contextMap = new Map()
export const configContextMap = new Map()
export const contextSourcesMap = new Map()
export const NOT_ON_DEMAND = new String('*')

export function resolveDebug(debug) {
if (debug === undefined) {
Expand Down
63 changes: 62 additions & 1 deletion tests/basic-usage.test.js
@@ -1,7 +1,7 @@
import fs from 'fs'
import path from 'path'

import { html, run, css } from './util/run'
import { html, run, css, defaults } from './util/run'

test('basic usage', () => {
let config = {
Expand Down Expand Up @@ -188,3 +188,64 @@ it('can scan extremely long classes without crashing', () => {
expect(result.css).toMatchFormattedCss(css``)
})
})

it('does not produce duplicate output when seeing variants preceding a wildcard (*)', () => {
let config = {
content: [{ raw: html`underline focus:*` }],
corePlugins: { preflight: false },
}

let input = css`
@tailwind base;
@tailwind components;
@tailwind utilities;
* {
color: red;
}
.combined,
* {
text-align: center;
}
@layer base {
* {
color: blue;
}
.combined,
* {
color: red;
}
}
`

return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
* {
color: blue;
}
.combined,
* {
color: red;
}
${defaults}
.underline {
text-decoration-line: underline;
}
* {
color: red;
}
.combined,
* {
text-align: center;
}
`)
})
})

0 comments on commit be5d5c9

Please sign in to comment.