feat: Show "Did you mean?" message when users @apply errant class (#2590)

* feat: suggest alternate classes if @apply value not found

* fix: remove only from test

* feat: move logic to applyComplexClasses

* fix: remove whitespace

* remove unused files

* did you mean suggestion
This commit is contained in:
Matt Rothenberg 2020-10-19 09:35:22 -04:00 committed by GitHub
parent 3141425c29
commit 7572b0256c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 1 deletions

View File

@ -887,6 +887,50 @@ describe('using apply with the prefix option', () => {
})
})
test('a "Did You Mean" suggestion is recommended if a similar class can be identified.', () => {
const input = `
.foo { @apply anti-aliased; }
`
const config = resolveConfig([
{
...defaultConfig,
},
])
expect.assertions(1)
return run(input, config).catch((e) => {
expect(e).toMatchObject({
name: 'CssSyntaxError',
reason:
"The `anti-aliased` class does not exist, but `antialiased` does. If you're sure that `anti-aliased` exists, make sure that any `@import` statements are being properly processed before Tailwind CSS sees your CSS, as `@apply` can only be used for classes in the same CSS tree.",
})
})
})
test('a "Did You Mean" suggestion is omitted if a similar class cannot be identified.', () => {
const input = `
.foo { @apply anteater; }
`
const config = resolveConfig([
{
...defaultConfig,
},
])
expect.assertions(1)
return run(input, config).catch((e) => {
expect(e).toMatchObject({
name: 'CssSyntaxError',
reason:
"The `anteater` class does not exist. If you're sure that `anteater` exists, make sure that any `@import` statements are being properly processed before Tailwind CSS sees your CSS, as `@apply` can only be used for classes in the same CSS tree.",
})
})
})
test('you can apply classes with important and a prefix enabled', () => {
const input = `
.foo { @apply tw-mt-4; }

View File

@ -1,6 +1,7 @@
import _ from 'lodash'
import selectorParser from 'postcss-selector-parser'
import postcss from 'postcss'
import didYouMean from 'didyoumean'
import substituteTailwindAtRules from './substituteTailwindAtRules'
import evaluateTailwindFunctions from './evaluateTailwindFunctions'
import substituteVariantsAtRules from './substituteVariantsAtRules'
@ -166,6 +167,8 @@ function makeExtractUtilityRules(css, lookupTree, config) {
if (utilityMap[utilityName] === undefined) {
// Look for prefixed utility in case the user has goofed
const prefixedUtility = prefixSelector(config.prefix, `.${utilityName}`).slice(1)
const suggestedClass = didYouMean(utilityName, Object.keys(utilityMap))
const suggestionMessage = suggestedClass ? `, but \`${suggestedClass}\` does` : ''
if (utilityMap[prefixedUtility] !== undefined) {
throw rule.error(
@ -174,7 +177,7 @@ function makeExtractUtilityRules(css, lookupTree, config) {
}
throw rule.error(
`The \`${utilityName}\` class does not exist. If you're sure that \`${utilityName}\` exists, make sure that any \`@import\` statements are being properly processed before Tailwind CSS sees your CSS, as \`@apply\` can only be used for classes in the same CSS tree.`,
`The \`${utilityName}\` class does not exist${suggestionMessage}. If you're sure that \`${utilityName}\` exists, make sure that any \`@import\` statements are being properly processed before Tailwind CSS sees your CSS, as \`@apply\` can only be used for classes in the same CSS tree.`,
{ word: utilityName }
)
}