diff --git a/CHANGELOG.md b/CHANGELOG.md index e0adec123e17..21dbfb319d16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Rewrite default class extractor ([#8204](https://github.com/tailwindlabs/tailwindcss/pull/8204)) - Move `important` selector to the front when `@apply`-ing selector-modifying variants in custom utilities ([#8313](https://github.com/tailwindlabs/tailwindcss/pull/8313)) - Error when registering an invalid custom variant ([#8345](https://github.com/tailwindlabs/tailwindcss/pull/8345)) +- Create tailwind.config.cjs file in ESM package when running init ([#8363](https://github.com/tailwindlabs/tailwindcss/pull/8363)) ### Changed diff --git a/integrations/tailwindcss-cli/tests/cli.test.js b/integrations/tailwindcss-cli/tests/cli.test.js index 553097ce0208..e812500582af 100644 --- a/integrations/tailwindcss-cli/tests/cli.test.js +++ b/integrations/tailwindcss-cli/tests/cli.test.js @@ -464,4 +464,68 @@ describe('Init command', () => { `) ) }) + + test('--help in ESM package', async () => { + let pkg = await readOutputFile('../package.json') + + await writeInputFile( + '../package.json', + JSON.stringify({ + ...JSON.parse(pkg), + type: 'module', + }) + ) + + let { combined } = await $(`${EXECUTABLE} init --help`) + + expect(dedent(combined)).toEqual( + dedent(` + tailwindcss v${version} + + Usage: + tailwindcss init [options] + + Options: + -f, --full Initialize a full \`tailwind.config.cjs\` file + -p, --postcss Initialize a \`postcss.config.cjs\` file + --types Add TypeScript types for the \`tailwind.config.cjs\` file + -h, --help Display usage information + `) + ) + + await writeInputFile('../package.json', pkg) + }) + + test('cjs config created when in ESM package', async () => { + cleanupFile('tailwind.config.cjs') + + let pkg = await readOutputFile('../package.json') + + await writeInputFile( + '../package.json', + JSON.stringify({ + ...JSON.parse(pkg), + type: 'module', + }) + ) + + let { combined } = await $(`${EXECUTABLE} init`) + + expect(combined).toMatchInlineSnapshot(` + " + Created Tailwind CSS config file: tailwind.config.cjs + " + `) + + expect(await fileExists('./tailwind.config.cjs')).toBe(true) + + // Not a clean way to test this. + expect(await readOutputFile('../tailwind.config.cjs')).toContain('module.exports =') + + expect(await readOutputFile('../tailwind.config.cjs')).not.toContain( + `/** @type {import('tailwindcss/types').Config} */` + ) + + await writeInputFile('../package.json', pkg) + }) }) diff --git a/src/cli.js b/src/cli.js index 92de66a77c0d..7d184aa45537 100644 --- a/src/cli.js +++ b/src/cli.js @@ -23,6 +23,27 @@ let env = { DEBUG: process.env.DEBUG !== undefined && process.env.DEBUG !== '0', } +function isESM() { + const pkgPath = path.resolve('./package.json') + + try { + let pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')) + return pkg.type && pkg.type === 'module' + } catch (err) { + return false + } +} + +let configs = isESM() + ? { + tailwind: 'tailwind.config.cjs', + postcss: 'postcss.config.cjs', + } + : { + tailwind: 'tailwind.config.js', + postcss: 'postcss.config.js', + } + // --- function indentRecursive(node, indent = 0) { @@ -160,11 +181,11 @@ let commands = { init: { run: init, args: { - '--full': { type: Boolean, description: 'Initialize a full `tailwind.config.js` file' }, - '--postcss': { type: Boolean, description: 'Initialize a `postcss.config.js` file' }, + '--full': { type: Boolean, description: `Initialize a full \`${configs.tailwind}\` file` }, + '--postcss': { type: Boolean, description: `Initialize a \`${configs.postcss}\` file` }, '--types': { type: Boolean, - description: 'Add TypeScript types for the `tailwind.config.js` file', + description: `Add TypeScript types for the \`${configs.tailwind}\` file`, }, '-f': '--full', '-p': '--postcss', @@ -340,7 +361,7 @@ run() function init() { let messages = [] - let tailwindConfigLocation = path.resolve(args['_'][1] ?? './tailwind.config.js') + let tailwindConfigLocation = path.resolve(args['_'][1] ?? `./${configs.tailwind}`) if (fs.existsSync(tailwindConfigLocation)) { messages.push(`${path.basename(tailwindConfigLocation)} already exists.`) } else { @@ -367,7 +388,7 @@ function init() { } if (args['--postcss']) { - let postcssConfigLocation = path.resolve('./postcss.config.js') + let postcssConfigLocation = path.resolve(`./${configs.postcss}`) if (fs.existsSync(postcssConfigLocation)) { messages.push(`${path.basename(postcssConfigLocation)} already exists.`) } else { @@ -421,7 +442,7 @@ async function build() { let configPath = args['--config'] ? args['--config'] : ((defaultPath) => (fs.existsSync(defaultPath) ? defaultPath : null))( - path.resolve('./tailwind.config.js') + path.resolve(`./${configs.tailwind}`) ) async function loadPostCssPlugins() {