From 5f48365d09cfeb24f2691e0ab0176a2b2d51a260 Mon Sep 17 00:00:00 2001 From: Tom Gobich Date: Fri, 31 Jan 2025 17:27:18 -0500 Subject: [PATCH] feat(tailwindcss): updated tailwindcss integration from v3 to v4. closes #1 --- src/scaffolds/tailwind_scaffold.ts | 156 +++-------------------- stubs/views/components/layout/index.edge | 5 +- 2 files changed, 21 insertions(+), 140 deletions(-) diff --git a/src/scaffolds/tailwind_scaffold.ts b/src/scaffolds/tailwind_scaffold.ts index c82110a..4ac82ba 100644 --- a/src/scaffolds/tailwind_scaffold.ts +++ b/src/scaffolds/tailwind_scaffold.ts @@ -1,41 +1,16 @@ import ConfigureCommand from '@adonisjs/core/commands/configure' import { mkdir, writeFile } from 'node:fs/promises' -import { SourceFile, Symbol } from 'ts-morph' -import { SyntaxKind } from 'typescript' -import { stubsRoot } from '../../stubs/main.js' import { readFileOrDefault } from '../utils/file_helper.js' import BaseScaffold from './base_scaffold.js' -type Import = { - name: string - module: string -} - export default class TailwindScaffold extends BaseScaffold { - #imports = new Map([ - [ - 'tailwind', - { - name: 'tailwind', - module: 'tailwindcss', - }, - ], - [ - 'autoprefixer', - { - name: 'autoprefixer', - module: 'autoprefixer', - }, - ], - ]) - constructor(protected command: ConfigureCommand) { super(command) } static installs: { name: string; isDevDependency: boolean }[] = [ { name: 'tailwindcss', isDevDependency: true }, - { name: 'autoprefixer', isDevDependency: true }, + { name: '@tailwindcss/vite', isDevDependency: true }, ] async run() { @@ -43,9 +18,8 @@ export default class TailwindScaffold extends BaseScaffold { const cssPath = this.app.makePath('resources/css') const cssFile = this.app.makePath('resources/css/app.css') - const cssContents = '@tailwind base;\n@tailwind components;\n@tailwind utilities;\n' - - await this.codemods.makeUsingStub(stubsRoot, 'configs/tailwind.config.stub', {}) + const cssContents = '@import "tailwindcss";\n@source "../views";\n' + const defaultReset = '* {\n margin: 0;\n padding: 0;\n}' let css = await readFileOrDefault(cssFile, '') let wasChanged = false @@ -56,11 +30,16 @@ export default class TailwindScaffold extends BaseScaffold { wasChanged = true } - if (!css.includes('@tailwind')) { + if (!css.includes('@import tailwindcss')) { css = css ? `${cssContents}\n${css}` : cssContents wasChanged = true } + if (css.includes(defaultReset)) { + css = css.replace(defaultReset, '') + wasChanged = true + } + if (wasChanged) { await mkdir(cssPath, { recursive: true }) await writeFile(cssFile, css) @@ -68,115 +47,16 @@ export default class TailwindScaffold extends BaseScaffold { this.logger.action('update resources/css/app.css') } - await this.#addViteConfig() - } - - async #addViteConfig() { - const project = await this.codemods.getTsMorphProject() - const file = project?.getSourceFile(this.app.makePath('vite.config.ts')) - const defaultExport = file?.getDefaultExportSymbol() - - if (!file) { - throw new Error('Cannot find the vite.config.ts file') - } - - if (!defaultExport) { - throw new Error('Cannot find the default export in vite.config.ts') - } - - const imports = await this.#addVitePostcssPlugins(defaultExport) - - this.#addMissingImports(file, imports) - - if (imports.length) { - file.formatText({ indentSize: 2 }) - - this.logger.action('create tailwind.config.ts') - } - - await file.save() + await this.#addVitePlugin() } - async #addVitePostcssPlugins(defaultExport: Symbol) { - // get the object contents of `defineConfig` - const declaration = defaultExport.getDeclarations()[0] - const options = - declaration.getChildrenOfKind(SyntaxKind.ObjectLiteralExpression)[0] || - declaration.getChildrenOfKind(SyntaxKind.CallExpression)[0].getArguments()[0] - - // 1. if there isn't already a `css` property, we can add the whole thing - const cssProperty = options - .getProperty('css') - ?.getFirstChildByKind(SyntaxKind.ObjectLiteralExpression) - - if (!cssProperty?.getFullText()) { - options.addPropertyAssignment({ - name: 'css', - initializer: `{ postcss: { plugins: [tailwind(), autoprefixer()] } }`, - }) - return [...this.#imports.values()] - } - - // 2. if there is a `css` property but not a `postcss` property, - // we can add the whole `postcss` config - const postcssProperty = cssProperty - .getProperty('postcss') - ?.getFirstChildByKind(SyntaxKind.ObjectLiteralExpression) - - if (!postcssProperty?.getFullText()) { - cssProperty.addPropertyAssignment({ - name: 'postcss', - initializer: '{ plugins: [tailwind(), autoprefixer()] }', - }) - return [...this.#imports.values()] - } - - // 3. if there is a `css.postcss` property, but it doesn't contain `plugins`, - // we can add the plugins - const plugins = postcssProperty - ?.getProperty('plugins') - ?.getFirstChildByKind(SyntaxKind.ArrayLiteralExpression) - - if (!plugins?.getFullText()) { - postcssProperty.addPropertyAssignment({ - name: 'plugins', - initializer: '[tailwind(), autoprefixer()]', - }) - return [...this.#imports.values()] - } - - // 4. if there is a `css.postcss.plugins` property, - // determine if either the tailwind or autoprefixer plugis are missing - const pluginItems = plugins - ?.getElements() - .filter((element) => ['tailwind()', 'autoprefixer()'].includes(element.getText())) - .map((element) => element.getText()) - - const imports: Import[] = [] - - if (!pluginItems?.includes('tailwind()')) { - plugins.insertElement(0, 'tailwind()') - imports.push(this.#imports.get('tailwind')!) - } - - if (!pluginItems.includes('autoprefixer()')) { - plugins.addElement('autoprefixer()') - imports.push(this.#imports.get('autoprefixer')!) - } - - return imports - } - - #addMissingImports(file: SourceFile, imports: Import[]) { - const defaultImports = file.getImportDeclarations().map((r) => r.getDefaultImport()?.getText()) - - imports?.forEach((imp) => { - if (defaultImports?.includes(imp.name)) return - - file.addImportDeclaration({ - defaultImport: imp.name, - moduleSpecifier: imp.module, - }) - }) + async #addVitePlugin() { + this.codemods.registerVitePlugin('tailwindcss()', [ + { + isNamed: false, + module: '@tailwindcss/vite', + identifier: 'tailwindcss', + }, + ]) } } diff --git a/stubs/views/components/layout/index.edge b/stubs/views/components/layout/index.edge index d561772..f135964 100644 --- a/stubs/views/components/layout/index.edge +++ b/stubs/views/components/layout/index.edge @@ -24,7 +24,6 @@ @@ -79,7 +78,9 @@
- {{{ await $slots.main() }}} +
+ {{{ await $slots.main() }}} +
@!toast.flash()