From bd0a7c0e5012ece8fcb8d49f40b756cd6f95fc97 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Wed, 23 Dec 2020 13:07:21 -0600 Subject: [PATCH 1/4] feat: automatically init and resolve tailwind.config.cjs files --- __tests__/cli.test.js | 22 ++++++++++++++++++++++ __tests__/fixtures/esm-package.json | 3 +++ src/cli/commands/init.js | 12 ++++++++---- src/cli/utils.js | 16 ++++++++++++++++ src/constants.js | 5 +++++ src/index.js | 16 +++++++++------- src/index.postcss7.js | 16 +++++++++------- 7 files changed, 72 insertions(+), 18 deletions(-) create mode 100644 __tests__/fixtures/esm-package.json diff --git a/__tests__/cli.test.js b/__tests__/cli.test.js index 00b05d98a4ed..e86ebae1ec43 100644 --- a/__tests__/cli.test.js +++ b/__tests__/cli.test.js @@ -8,6 +8,7 @@ import runInTempDirectory from '../jest/runInTempDirectory' describe('cli', () => { const inputCssPath = path.resolve(__dirname, 'fixtures/tailwind-input.css') const customConfigPath = path.resolve(__dirname, 'fixtures/custom-config.js') + const esmPackageJsonPath = path.resolve(__dirname, 'fixtures/esm-package.json') const defaultConfigFixture = utils.readFile(constants.defaultConfigStubFile) const simpleConfigFixture = utils.readFile(constants.simpleConfigStubFile) const defaultPostCssConfigFixture = utils.readFile(constants.defaultPostCssConfigStubFile) @@ -47,6 +48,27 @@ describe('cli', () => { }) }) + it('creates a .cjs Tailwind config file inside of an ESM project', () => { + return runInTempDirectory(() => { + utils.writeFile('package.json', utils.readFile(esmPackageJsonPath)) + return cli(['init']).then(() => { + expect(utils.readFile(constants.cjsConfigFile)).toEqual(simpleConfigFixture) + }) + }) + }) + + it('creates a .cjs Tailwind config file and a postcss.config.cjs file inside of an ESM project', () => { + return runInTempDirectory(() => { + utils.writeFile('package.json', utils.readFile(esmPackageJsonPath)) + return cli(['init', '-p']).then(() => { + expect(utils.readFile(constants.cjsConfigFile)).toEqual(simpleConfigFixture) + expect(utils.readFile(constants.cjsPostCssConfigFile)).toEqual( + defaultPostCssConfigFixture + ) + }) + }) + }) + it('creates a Tailwind config file in a custom location', () => { return runInTempDirectory(() => { return cli(['init', 'custom.js']).then(() => { diff --git a/__tests__/fixtures/esm-package.json b/__tests__/fixtures/esm-package.json new file mode 100644 index 000000000000..3dbc1ca591c0 --- /dev/null +++ b/__tests__/fixtures/esm-package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/src/cli/commands/init.js b/src/cli/commands/init.js index 543381c94ec5..157523ee566b 100644 --- a/src/cli/commands/init.js +++ b/src/cli/commands/init.js @@ -15,7 +15,7 @@ export const options = [ }, { usage: '-p', - description: 'Generate postcss.config.js file.', + description: 'Generate PostCSS config file.', }, ] @@ -35,8 +35,9 @@ export function run(cliParams, cliOptions) { return new Promise((resolve) => { utils.header() + const isModule = utils.isModule() const full = cliOptions.full - const file = cliParams[0] || constants.defaultConfigFile + const file = cliParams[0] || (isModule ? constants.cjsConfigFile : constants.defaultConfigFile) const simplePath = utils.getSimplePath(file) utils.exists(file) && utils.die(colors.file(simplePath), 'already exists.') @@ -52,10 +53,13 @@ export function run(cliParams, cliOptions) { utils.log(emoji.yes, 'Created Tailwind config file:', colors.file(simplePath)) if (cliOptions.postcss) { - const path = utils.getSimplePath(constants.defaultPostCssConfigFile) + const postCssConfigFile = isModule + ? constants.cjsPostCssConfigFile + : constants.defaultPostCssConfigFile + const path = utils.getSimplePath(postCssConfigFile) utils.exists(constants.defaultPostCssConfigFile) && utils.die(colors.file(path), 'already exists.') - utils.copyFile(constants.defaultPostCssConfigStubFile, constants.defaultPostCssConfigFile) + utils.copyFile(constants.defaultPostCssConfigStubFile, postCssConfigFile) utils.log(emoji.yes, 'Created PostCSS config file:', colors.file(path)) } diff --git a/src/cli/utils.js b/src/cli/utils.js index e62faf264d64..219a8d5977ed 100644 --- a/src/cli/utils.js +++ b/src/cli/utils.js @@ -1,5 +1,6 @@ import { copyFileSync, ensureFileSync, existsSync, outputFileSync, readFileSync } from 'fs-extra' import { findKey, mapValues, startsWith, trimStart } from 'lodash' +import path from 'path' import * as colors from './colors' import * as emoji from './emoji' @@ -119,6 +120,21 @@ export function readFile(path) { return readFileSync(path, 'utf-8') } +/** + * Checks if current package.json uses type "module" + * + * @param {string} path + * @return {string} + */ +export function isModule() { + const pkgPath = path.resolve('./package.json') + if (exists(pkgPath)) { + const pkg = JSON.parse(readFile(pkgPath)) + return pkg.type && pkg.type === 'module' + } + return false +} + /** * Writes content to file. * diff --git a/src/constants.js b/src/constants.js index f72fcdafad2c..790fcc265d46 100644 --- a/src/constants.js +++ b/src/constants.js @@ -3,6 +3,11 @@ import path from 'path' export const cli = 'tailwind' export const defaultConfigFile = './tailwind.config.js' export const defaultPostCssConfigFile = './postcss.config.js' +export const cjsConfigFile = './tailwind.config.js' +export const cjsPostCssConfigFile = './postcss.config.cjs' + +export const supportedConfigFiles = [cjsConfigFile, defaultConfigFile] +export const supportedPostCssConfigFile = [cjsPostCssConfigFile, defaultPostCssConfigFile] export const defaultConfigStubFile = path.resolve(__dirname, '../stubs/defaultConfig.stub.js') export const simpleConfigStubFile = path.resolve(__dirname, '../stubs/simpleConfig.stub.js') diff --git a/src/index.js b/src/index.js index 1393f8af708d..e516e9a31c60 100644 --- a/src/index.js +++ b/src/index.js @@ -9,7 +9,7 @@ import processTailwindFeatures from './processTailwindFeatures' import formatCSS from './lib/formatCSS' import resolveConfig from './util/resolveConfig' import getAllConfigs from './util/getAllConfigs' -import { defaultConfigFile } from './constants' +import { supportedConfigFiles } from './constants' import defaultConfig from '../stubs/defaultConfig.stub.js' function resolveConfigPath(filePath) { @@ -34,13 +34,15 @@ function resolveConfigPath(filePath) { } // require('tailwindcss') - try { - const defaultConfigPath = path.resolve(defaultConfigFile) - fs.accessSync(defaultConfigPath) - return defaultConfigPath - } catch (err) { - return undefined + for (const configFile of supportedConfigFiles) { + try { + const configPath = path.resolve(configFile) + fs.accessSync(configPath) + return configPath + } catch (err) {} } + + return undefined } const getConfigFunction = (config) => () => { diff --git a/src/index.postcss7.js b/src/index.postcss7.js index 98fd13c4b762..5e5b38dcf1cf 100644 --- a/src/index.postcss7.js +++ b/src/index.postcss7.js @@ -10,7 +10,7 @@ import processTailwindFeatures from './processTailwindFeatures' import formatCSS from './lib/formatCSS' import resolveConfig from './util/resolveConfig' import getAllConfigs from './util/getAllConfigs' -import { defaultConfigFile } from './constants' +import { supportedConfigFiles } from './constants' import defaultConfig from '../stubs/defaultConfig.stub.js' function resolveConfigPath(filePath) { @@ -35,13 +35,15 @@ function resolveConfigPath(filePath) { } // require('tailwindcss') - try { - const defaultConfigPath = path.resolve(defaultConfigFile) - fs.accessSync(defaultConfigPath) - return defaultConfigPath - } catch (err) { - return undefined + for (const configFile of supportedConfigFiles) { + try { + const configPath = path.resolve(configFile) + fs.accessSync(configPath) + return configPath + } catch (err) {} } + + return undefined } const getConfigFunction = (config) => () => { From afccfe85204f94d1e777e518453f04ee2bddcea3 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Wed, 23 Dec 2020 13:13:40 -0600 Subject: [PATCH 2/4] test: add tests for default tailwind.config.cjs resolution --- __tests__/customConfig.test.js | 80 +++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/__tests__/customConfig.test.js b/__tests__/customConfig.test.js index e2f746ccccc9..cc6d2ef0df01 100644 --- a/__tests__/customConfig.test.js +++ b/__tests__/customConfig.test.js @@ -2,7 +2,7 @@ import fs from 'fs' import path from 'path' import postcss from 'postcss' import tailwind from '../src/index' -import { defaultConfigFile } from '../src/constants' +import { cjsConfigFile, defaultConfigFile } from '../src/constants' import inTempDirectory from '../jest/runInTempDirectory' test('it uses the values from the custom config file', () => { @@ -133,6 +133,45 @@ test('custom config can be passed under the `config` property', () => { }) }) +test('tailwind.config.cjs is picked up by default', () => { + return inTempDirectory(() => { + fs.writeFileSync( + path.resolve(cjsConfigFile), + `module.exports = { + theme: { + screens: { + mobile: '400px', + }, + }, + }` + ) + + return postcss([tailwind]) + .process( + ` + @responsive { + .foo { + color: blue; + } + } + `, + { from: undefined } + ) + .then((result) => { + expect(result.css).toMatchCss(` + .foo { + color: blue; + } + @media (min-width: 400px) { + .mobile\\:foo { + color: blue; + } + } + `) + }) + }) +}) + test('tailwind.config.js is picked up by default', () => { return inTempDirectory(() => { fs.writeFileSync( @@ -172,6 +211,45 @@ test('tailwind.config.js is picked up by default', () => { }) }) +test('tailwind.config.cjs is picked up by default when passing an empty object', () => { + return inTempDirectory(() => { + fs.writeFileSync( + path.resolve(cjsConfigFile), + `module.exports = { + theme: { + screens: { + mobile: '400px', + }, + }, + }` + ) + + return postcss([tailwind({})]) + .process( + ` + @responsive { + .foo { + color: blue; + } + } + `, + { from: undefined } + ) + .then((result) => { + expect(result.css).toMatchCss(` + .foo { + color: blue; + } + @media (min-width: 400px) { + .mobile\\:foo { + color: blue; + } + } + `) + }) + }) +}) + test('tailwind.config.js is picked up by default when passing an empty object', () => { return inTempDirectory(() => { fs.writeFileSync( From 4157d52aaf8aeb8f7715e3ef7386dd1826b18247 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Wed, 23 Dec 2020 21:05:18 -0600 Subject: [PATCH 3/4] fix `cjsConfigFile` constant --- src/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants.js b/src/constants.js index 790fcc265d46..4d6e08c07616 100644 --- a/src/constants.js +++ b/src/constants.js @@ -3,7 +3,7 @@ import path from 'path' export const cli = 'tailwind' export const defaultConfigFile = './tailwind.config.js' export const defaultPostCssConfigFile = './postcss.config.js' -export const cjsConfigFile = './tailwind.config.js' +export const cjsConfigFile = './tailwind.config.cjs' export const cjsPostCssConfigFile = './postcss.config.cjs' export const supportedConfigFiles = [cjsConfigFile, defaultConfigFile] From 80b393bdcdceb351af86ba232019bb3f3f249756 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Wed, 23 Dec 2020 21:10:01 -0600 Subject: [PATCH 4/4] Fix JSDoc type of isModule --- src/cli/utils.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cli/utils.js b/src/cli/utils.js index 219a8d5977ed..cc80768aac9b 100644 --- a/src/cli/utils.js +++ b/src/cli/utils.js @@ -123,8 +123,7 @@ export function readFile(path) { /** * Checks if current package.json uses type "module" * - * @param {string} path - * @return {string} + * @return {boolean} */ export function isModule() { const pkgPath = path.resolve('./package.json')