From bef383855297b36eeaa7683eed1e16d4b2439fd6 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 14 Jan 2022 09:47:39 -0500 Subject: [PATCH] Show warnings for invalid content config (#7065) --- CHANGELOG.md | 4 +- src/lib/expandTailwindAtRules.js | 9 ++++ src/util/normalizeConfig.js | 6 +++ tests/warnings.test.js | 74 ++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 tests/warnings.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d29a640b15c..c1bccab5db77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Nothing yet! +### Added + +- Show warnings for invalid content config ([#7065](https://github.com/tailwindlabs/tailwindcss/pull/7065)) ## [3.0.13] - 2022-01-11 diff --git a/src/lib/expandTailwindAtRules.js b/src/lib/expandTailwindAtRules.js index 2c9469f3099a..b24fe527b10c 100644 --- a/src/lib/expandTailwindAtRules.js +++ b/src/lib/expandTailwindAtRules.js @@ -2,6 +2,7 @@ import LRU from 'quick-lru' import * as sharedState from './sharedState' import { generateRules } from './generateRules' import bigSign from '../util/bigSign' +import log from '../util/log' import cloneNodes from '../util/cloneNodes' import { defaultExtractor } from './defaultExtractor' @@ -227,6 +228,14 @@ export default function expandTailwindAtRules(context) { root.append(cloneNodes([...screenNodes], root.source)) } + // If we've got a utility layer and no utilities are generated there's likely something wrong + // TODO: Detect utility variants only + if (layerNodes.utilities && utilityNodes.size === 0 && screenNodes.size === 0) { + log.warn('content-problems', [ + 'No utilities were generated there is likely a problem with the `content` key in the tailwind config. For more information see the documentation: https://tailwindcss.com/docs/content-configuration', + ]) + } + // --- if (env.DEBUG) { diff --git a/src/util/normalizeConfig.js b/src/util/normalizeConfig.js index 31eee90f49cd..ebc313d87010 100644 --- a/src/util/normalizeConfig.js +++ b/src/util/normalizeConfig.js @@ -258,5 +258,11 @@ export function normalizeConfig(config) { } } + if (config.content.files.length === 0) { + log.warn('content-problems', [ + 'The `content` key is missing or empty. Please populate the content key as Tailwind generates utilities on-demand based on the files that use them. For more information see the documentation: https://tailwindcss.com/docs/content-configuration', + ]) + } + return config } diff --git a/tests/warnings.test.js b/tests/warnings.test.js new file mode 100644 index 000000000000..9ff1a98afd0d --- /dev/null +++ b/tests/warnings.test.js @@ -0,0 +1,74 @@ +import { html, run, css } from './util/run' + +let warn + +beforeEach(() => { + let log = require('../src/util/log') + warn = jest.spyOn(log.default, 'warn') +}) + +afterEach(() => { + warn.mockClear() +}) + +test('it warns when there is no content key', async () => { + let config = { + corePlugins: { preflight: false }, + } + + let input = css` + @tailwind base; + ` + + await run(input, config) + + expect(warn).toHaveBeenCalledTimes(1) + expect(warn.mock.calls.map((x) => x[0])).toEqual(['content-problems']) +}) + +test('it warns when there is an empty content key', async () => { + let config = { + content: [], + corePlugins: { preflight: false }, + } + + let input = css` + @tailwind base; + ` + + await run(input, config) + + expect(warn).toHaveBeenCalledTimes(1) + expect(warn.mock.calls.map((x) => x[0])).toEqual(['content-problems']) +}) + +test('it warns when there are no utilities generated', async () => { + let config = { + content: [{ raw: html`nothing here matching a utility` }], + corePlugins: { preflight: false }, + } + + let input = css` + @tailwind utilities; + ` + + await run(input, config) + + expect(warn).toHaveBeenCalledTimes(1) + expect(warn.mock.calls.map((x) => x[0])).toEqual(['content-problems']) +}) + +it('warnings are not thrown when only variant utilities are generated', async () => { + let config = { + content: [{ raw: html`
` }], + corePlugins: { preflight: false }, + } + + let input = css` + @tailwind utilities; + ` + + await run(input, config) + + expect(warn).toHaveBeenCalledTimes(0) +})