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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix usage of special-character prefixes #8772

Merged
merged 4 commits into from Jul 4, 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
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

- Allows fallback values in plugin API helpers ([#8762](https://github.com/tailwindlabs/tailwindcss/pull/8762))
- Fix usage of postcss.config.js in standalone CLI ([#8769](https://github.com/tailwindlabs/tailwindcss/pull/8769))
- Fix usage of special-character prefixes ([#8772](https://github.com/tailwindlabs/tailwindcss/pull/8772))

## [3.1.4] - 2022-06-21

Expand Down
8 changes: 7 additions & 1 deletion src/lib/defaultExtractor.js
@@ -1,4 +1,4 @@
import { flagEnabled } from '../featureFlags.js'
import { flagEnabled } from '../featureFlags'
import * as regex from './regex'

export function defaultExtractor(context) {
Expand All @@ -22,6 +22,10 @@ export function defaultExtractor(context) {
function* buildRegExps(context) {
let separator = context.tailwindConfig.separator
let variantGroupingEnabled = flagEnabled(context.tailwindConfig, 'variantGrouping')
let prefix =
context.tailwindConfig.prefix !== ''
? regex.optional(regex.pattern([/-?/, regex.escape(context.tailwindConfig.prefix)]))
: ''

let utility = regex.any([
// Arbitrary properties
Expand Down Expand Up @@ -88,6 +92,8 @@ function* buildRegExps(context) {
// Important (optional)
/!?/,

prefix,

variantGroupingEnabled
? regex.any([
// Or any of those things but grouped separated by commas
Expand Down
117 changes: 117 additions & 0 deletions tests/prefix.test.js
Expand Up @@ -400,3 +400,120 @@ it('supports prefixed utilities using arbitrary values', async () => {
}
`)
})

it('supports non-word prefixes (1)', async () => {
let config = {
prefix: '@',
content: [
{
raw: html`
<div class="@underline"></div>
<div class="@bg-black"></div>
<div class="@[color:red]"></div>
<div class="hover:before:@content-['Hovering']"></div>
<div class="my-utility"></div>
<div class="foo"></div>

<!-- these won't be detected -->
<div class="overline"></div>
`,
},
],
corePlugins: { preflight: false },
}

let input = css`
@tailwind utilities;
@layer utilities {
.my-utility {
color: orange;
}
}
.foo {
@apply @text-white;
@apply [background-color:red];
}
`

const result = await run(input, config)

expect(result.css).toMatchFormattedCss(css`
.\@bg-black {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
}
.\@underline {
text-decoration-line: underline;
}
.my-utility {
color: orange;
}
.foo {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
background-color: red;
}
.hover\:before\:\@content-\[\'Hovering\'\]:hover::before {
--tw-content: 'Hovering';
content: var(--tw-content);
}
`)
})

it('supports non-word prefixes (2)', async () => {
let config = {
prefix: '@]$',
content: [
{
raw: html`
<div class="@]$underline"></div>
<div class="@]$bg-black"></div>
<div class="@]$[color:red]"></div>
<div class="hover:before:@]$content-['Hovering']"></div>
<div class="my-utility"></div>
<div class="foo"></div>

<!-- these won't be detected -->
<div class="overline"></div>
`,
},
],
corePlugins: { preflight: false },
}

let input = css`
@tailwind utilities;
@layer utilities {
.my-utility {
color: orange;
}
}
.foo {
@apply @]$text-white;
@apply [background-color:red];
}
`

const result = await run(input, config)

// TODO: The class `.hover\:before\:\@\]\$content-\[\'Hovering\'\]:hover::before` is not generated
// This happens because of the parenthesis/brace/bracket clipping performed on candidates

expect(result.css).toMatchFormattedCss(css`
.\@\]\$bg-black {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
}
.\@\]\$underline {
text-decoration-line: underline;
}
.my-utility {
color: orange;
}
.foo {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
background-color: red;
}
`)
})