diff --git a/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js b/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js index aa174459e9b7..3745077d90e0 100644 --- a/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js +++ b/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js @@ -59,7 +59,14 @@ const tailwindImportsAndNotes = [ export const handler = async ({ force, install }) => { const rwPaths = getPaths() - const packages = ['postcss', 'postcss-loader', 'tailwindcss', 'autoprefixer'] + const projectPackages = ['prettier-plugin-tailwindcss'] + + const webWorkspacePackages = [ + 'postcss', + 'postcss-loader', + 'tailwindcss', + 'autoprefixer', + ] const recommendedVSCodeExtensions = [ 'csstools.postcss', @@ -68,19 +75,33 @@ export const handler = async ({ force, install }) => { const tasks = new Listr([ { - title: 'Installing packages...', + title: 'Installing project-wide packages...', + skip: () => !install, + task: () => { + return new Listr([ + { + title: `Install ${projectPackages.join(', ')}`, + task: async () => { + await execa('yarn', ['add', '-D', ...projectPackages]) + }, + }, + ]) + }, + }, + { + title: 'Installing web workspace-wide packages...', skip: () => !install, task: () => { return new Listr([ { - title: `Install ${packages.join(', ')}`, + title: `Install ${webWorkspacePackages.join(', ')}`, task: async () => { await execa('yarn', [ 'workspace', 'web', 'add', '-D', - ...packages, + ...webWorkspacePackages, ]) }, }, @@ -189,6 +210,76 @@ export const handler = async ({ force, install }) => { } }, }, + { + title: 'Adding tailwind config entry in prettier...', + task: async (_ctx) => { + const prettierConfigPath = path.join(rwPaths.base, 'prettier.config.js') + // Add tailwindcss ordering plugin to prettier + const prettierConfig = fs.readFileSync(prettierConfigPath, 'utf-8') + const tailwindConfigPath = path.relative( + rwPaths.base, + path.join(rwPaths.web.config, 'tailwind.config.js') + ) + + let newPrettierConfig = prettierConfig + if (newPrettierConfig.includes('tailwindConfig: ')) { + if (force) { + newPrettierConfig = newPrettierConfig.replace( + /tailwindConfig: .*(,)?/, + `tailwindConfig: './${tailwindConfigPath}',` + ) + } else { + throw new Error( + 'tailwindConfig setting already exists in prettier configuration.\nUse --force to override existing config.' + ) + } + } else { + newPrettierConfig = newPrettierConfig.replace( + /,(\n\s*)(\}\n?)$/, + `,\n tailwindConfig: './${tailwindConfigPath}',$1$2` + ) + } + + fs.writeFileSync(prettierConfigPath, newPrettierConfig) + }, + }, + { + title: 'Adding tailwind prettier plugin...', + task: async (_ctx, task) => { + const prettierConfigPath = path.join(rwPaths.base, 'prettier.config.js') + // Add tailwindcss ordering plugin to prettier + const prettierConfig = fs.readFileSync(prettierConfigPath, 'utf-8') + + let newPrettierConfig = prettierConfig + if (newPrettierConfig.includes('plugins: [')) { + const pluginsMatch = newPrettierConfig.match( + /plugins: \[[\sa-z\(\)'\-,]*]/ + ) + + const matched = pluginsMatch && pluginsMatch[0] + + if ( + matched && + (matched.includes("require('prettier-plugin-tailwindcss')") || + matched.includes('require("prettier-plugin-tailwindcss")')) + ) { + task.skip('tailwindcss-plugin-prettier already required in plugins') + } else { + newPrettierConfig = newPrettierConfig.replace( + /plugins: \[(\n\s+)*/, + `plugins: [$1require('prettier-plugin-tailwindcss'),$1` + ) + } + } else { + newPrettierConfig = newPrettierConfig.replace( + /,(\n\s*)(\}\n?)$/, + `,\n plugins: [require('prettier-plugin-tailwindcss')],$1$2` + ) + } + + fs.writeFileSync(prettierConfigPath, newPrettierConfig) + }, + }, ]) try {