From ca9bf9149c8feb087de4b5759442d2b13d5efe1a Mon Sep 17 00:00:00 2001 From: Dunqing Date: Sun, 15 Oct 2023 15:40:13 +0800 Subject: [PATCH] feat(cli): support `tailwind.config.mjs` file --- packages/cli/src/commands/init.ts | 10 +- packages/cli/src/utils/templates.ts | 14 +- .../transformers/transform-cjs-to-esm.ts | 8 ++ .../transform-cjs-to-esm.test.ts.snap | 135 ++++++++++++++++++ .../test/utils/transform-cjs-to-esm.test.ts | 8 ++ 5 files changed, 168 insertions(+), 7 deletions(-) create mode 100644 packages/cli/src/utils/transformers/transform-cjs-to-esm.ts create mode 100644 packages/cli/test/utils/__snapshots__/transform-cjs-to-esm.test.ts.snap create mode 100644 packages/cli/test/utils/transform-cjs-to-esm.test.ts diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 052fee3f..334ed213 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -28,6 +28,7 @@ import { rawConfigSchema, resolveConfigPaths, } from '../utils/get-config' +import { transformCJSToESM } from '../utils/transformers/transform-cjs-to-esm' const PROJECT_DEPENDENCIES = { base: [ @@ -235,9 +236,12 @@ export async function runInit(cwd: string, config: Config) { // Write tailwind config. await fs.writeFile( config.resolvedPaths.tailwindConfig, - config.tailwind.cssVariables - ? template(templates.TAILWIND_CONFIG_WITH_VARIABLES)({ extension, framework: config.framework }) - : template(templates.TAILWIND_CONFIG)({ extension, framework: config.framework }), + transformCJSToESM( + config.resolvedPaths.tailwindConfig, + config.tailwind.cssVariables + ? template(templates.TAILWIND_CONFIG_WITH_VARIABLES)({ extension, framework: config.framework }) + : template(templates.TAILWIND_CONFIG)({ extension, framework: config.framework }), + ), 'utf8', ) diff --git a/packages/cli/src/utils/templates.ts b/packages/cli/src/utils/templates.ts index 3ebd2edd..b2adbd55 100644 --- a/packages/cli/src/utils/templates.ts +++ b/packages/cli/src/utils/templates.ts @@ -7,7 +7,10 @@ export function cn(...inputs: ClassValue[]) { } ` -export const TAILWIND_CONFIG = `/** @type {import('tailwindcss').Config} */ +export const TAILWIND_CONFIG = ` +const animate = require("tailwindcss-animate") + +/** @type {import('tailwindcss').Config} */ module.exports = { darkMode: ["class"], content: [ @@ -41,10 +44,13 @@ module.exports = { }, }, }, - plugins: [require("tailwindcss-animate")], + plugins: [animate], }` -export const TAILWIND_CONFIG_WITH_VARIABLES = `/** @type {import('tailwindcss').Config} */ +export const TAILWIND_CONFIG_WITH_VARIABLES = `\n +const animate = require("tailwindcss-animate") + +/** @type {import('tailwindcss').Config} */ module.exports = { darkMode: ["class"], <% if (framework === 'vite') { %> @@ -127,5 +133,5 @@ module.exports = { }, }, }, - plugins: [require("tailwindcss-animate")], + plugins: [], }` diff --git a/packages/cli/src/utils/transformers/transform-cjs-to-esm.ts b/packages/cli/src/utils/transformers/transform-cjs-to-esm.ts new file mode 100644 index 00000000..010b45aa --- /dev/null +++ b/packages/cli/src/utils/transformers/transform-cjs-to-esm.ts @@ -0,0 +1,8 @@ +export function transformCJSToESM(filename: string, code: string) { + if (!filename.endsWith('.mjs')) { + return code + .replace(/const\s([\w\d_]+)\s*=\s*require\((.*)\);?/g, 'import $1 from $2') + .replace(/module\.exports = /g, 'export default ') + } + return code +} diff --git a/packages/cli/test/utils/__snapshots__/transform-cjs-to-esm.test.ts.snap b/packages/cli/test/utils/__snapshots__/transform-cjs-to-esm.test.ts.snap new file mode 100644 index 00000000..be1d0aa6 --- /dev/null +++ b/packages/cli/test/utils/__snapshots__/transform-cjs-to-esm.test.ts.snap @@ -0,0 +1,135 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`handle tailwind config template correctly 1`] = ` +" +import animate from \\"tailwindcss-animate\\" + +/** @type {import('tailwindcss').Config} */ +export default { + darkMode: [\\"class\\"], + content: [ + './pages/**/*.{<%- extension %>,<%- extension %>x,vue}', + './components/**/*.{<%- extension %>,<%- extension %>x,vue}', + './app/**/*.{<%- extension %>,<%- extension %>x,vue}', + './src/**/*.{<%- extension %>,<%- extension %>x,vue}', + ], + theme: { + container: { + center: true, + padding: \\"2rem\\", + screens: { + \\"2xl\\": \\"1400px\\", + }, + }, + extend: { + keyframes: { + \\"accordion-down\\": { + from: { height: 0 }, + to: { height: \\"var(--radix-accordion-content-height)\\" }, + }, + \\"accordion-up\\": { + from: { height: \\"var(--radix-accordion-content-height)\\" }, + to: { height: 0 }, + }, + }, + animation: { + \\"accordion-down\\": \\"accordion-down 0.2s ease-out\\", + \\"accordion-up\\": \\"accordion-up 0.2s ease-out\\", + }, + }, + }, + plugins: [animate], +}" +`; + +exports[`handle tailwind config template correctly 2`] = ` +" + +import animate from \\"tailwindcss-animate\\" + +/** @type {import('tailwindcss').Config} */ +export default { + darkMode: [\\"class\\"], + <% if (framework === 'vite') { %> + content: [ + './pages/**/*.{<%- extension %>,<%- extension %>x,vue}', + './components/**/*.{<%- extension %>,<%- extension %>x,vue}', + './app/**/*.{<%- extension %>,<%- extension %>x,vue}', + './src/**/*.{<%- extension %>,<%- extension %>x,vue}', + ], + <% } else if (framework === 'laravel') { %> + content: [ + \\"./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php\\", + \\"./storage/framework/views/*.php\\", + \\"./resources/views/**/*.blade.php\\", + \\"./resources/js/**/*.{<%- extension %>,<%- extension %>x,vue}\\", + ], + <% } %> + theme: { + container: { + center: true, + padding: \\"2rem\\", + screens: { + \\"2xl\\": \\"1400px\\", + }, + }, + extend: { + colors: { + border: \\"hsl(var(--border))\\", + input: \\"hsl(var(--input))\\", + ring: \\"hsl(var(--ring))\\", + background: \\"hsl(var(--background))\\", + foreground: \\"hsl(var(--foreground))\\", + primary: { + DEFAULT: \\"hsl(var(--primary))\\", + foreground: \\"hsl(var(--primary-foreground))\\", + }, + secondary: { + DEFAULT: \\"hsl(var(--secondary))\\", + foreground: \\"hsl(var(--secondary-foreground))\\", + }, + destructive: { + DEFAULT: \\"hsl(var(--destructive))\\", + foreground: \\"hsl(var(--destructive-foreground))\\", + }, + muted: { + DEFAULT: \\"hsl(var(--muted))\\", + foreground: \\"hsl(var(--muted-foreground))\\", + }, + accent: { + DEFAULT: \\"hsl(var(--accent))\\", + foreground: \\"hsl(var(--accent-foreground))\\", + }, + popover: { + DEFAULT: \\"hsl(var(--popover))\\", + foreground: \\"hsl(var(--popover-foreground))\\", + }, + card: { + DEFAULT: \\"hsl(var(--card))\\", + foreground: \\"hsl(var(--card-foreground))\\", + }, + }, + borderRadius: { + lg: \\"var(--radius)\\", + md: \\"calc(var(--radius) - 2px)\\", + sm: \\"calc(var(--radius) - 4px)\\", + }, + keyframes: { + \\"accordion-down\\": { + from: { height: 0 }, + to: { height: \\"var(--radix-accordion-content-height)\\" }, + }, + \\"accordion-up\\": { + from: { height: \\"var(--radix-accordion-content-height)\\" }, + to: { height: 0 }, + }, + }, + animation: { + \\"accordion-down\\": \\"accordion-down 0.2s ease-out\\", + \\"accordion-up\\": \\"accordion-up 0.2s ease-out\\", + }, + }, + }, + plugins: [], +}" +`; diff --git a/packages/cli/test/utils/transform-cjs-to-esm.test.ts b/packages/cli/test/utils/transform-cjs-to-esm.test.ts new file mode 100644 index 00000000..84c274fc --- /dev/null +++ b/packages/cli/test/utils/transform-cjs-to-esm.test.ts @@ -0,0 +1,8 @@ +import { expect, test } from 'vitest' +import { TAILWIND_CONFIG, TAILWIND_CONFIG_WITH_VARIABLES } from '../../src/utils/templates' +import { transformCJSToESM } from '../../src/utils/transformers/transform-cjs-to-esm' + +test('handle tailwind config template correctly', () => { + expect(transformCJSToESM('.js', TAILWIND_CONFIG)).toMatchSnapshot() + expect(transformCJSToESM('.js', TAILWIND_CONFIG_WITH_VARIABLES)).toMatchSnapshot() +})