11import ConfigureCommand from '@adonisjs/core/commands/configure'
22import { mkdir , writeFile } from 'node:fs/promises'
3- import { SourceFile , Symbol } from 'ts-morph'
4- import { SyntaxKind } from 'typescript'
5- import { stubsRoot } from '../../stubs/main.js'
63import { readFileOrDefault } from '../utils/file_helper.js'
74import BaseScaffold from './base_scaffold.js'
85
9- type Import = {
10- name : string
11- module : string
12- }
13-
146export default class TailwindScaffold extends BaseScaffold {
15- #imports = new Map < string , Import > ( [
16- [
17- 'tailwind' ,
18- {
19- name : 'tailwind' ,
20- module : 'tailwindcss' ,
21- } ,
22- ] ,
23- [
24- 'autoprefixer' ,
25- {
26- name : 'autoprefixer' ,
27- module : 'autoprefixer' ,
28- } ,
29- ] ,
30- ] )
31-
327 constructor ( protected command : ConfigureCommand ) {
338 super ( command )
349 }
3510
3611 static installs : { name : string ; isDevDependency : boolean } [ ] = [
3712 { name : 'tailwindcss' , isDevDependency : true } ,
38- { name : 'autoprefixer ' , isDevDependency : true } ,
13+ { name : '@tailwindcss/vite ' , isDevDependency : true } ,
3914 ]
4015
4116 async run ( ) {
4217 await this . boot ( )
4318
4419 const cssPath = this . app . makePath ( 'resources/css' )
4520 const cssFile = this . app . makePath ( 'resources/css/app.css' )
46- const cssContents = '@tailwind base;\n@tailwind components;\n@tailwind utilities;\n'
47-
48- await this . codemods . makeUsingStub ( stubsRoot , 'configs/tailwind.config.stub' , { } )
21+ const cssContents = '@import "tailwindcss";\n@source "../views";\n'
22+ const defaultReset = '* {\n margin: 0;\n padding: 0;\n}'
4923
5024 let css = await readFileOrDefault ( cssFile , '' )
5125 let wasChanged = false
@@ -56,127 +30,33 @@ export default class TailwindScaffold extends BaseScaffold {
5630 wasChanged = true
5731 }
5832
59- if ( ! css . includes ( '@tailwind ' ) ) {
33+ if ( ! css . includes ( '@import tailwindcss ' ) ) {
6034 css = css ? `${ cssContents } \n${ css } ` : cssContents
6135 wasChanged = true
6236 }
6337
38+ if ( css . includes ( defaultReset ) ) {
39+ css = css . replace ( defaultReset , '' )
40+ wasChanged = true
41+ }
42+
6443 if ( wasChanged ) {
6544 await mkdir ( cssPath , { recursive : true } )
6645 await writeFile ( cssFile , css )
6746
6847 this . logger . action ( 'update resources/css/app.css' )
6948 }
7049
71- await this . #addViteConfig( )
72- }
73-
74- async #addViteConfig( ) {
75- const project = await this . codemods . getTsMorphProject ( )
76- const file = project ?. getSourceFile ( this . app . makePath ( 'vite.config.ts' ) )
77- const defaultExport = file ?. getDefaultExportSymbol ( )
78-
79- if ( ! file ) {
80- throw new Error ( 'Cannot find the vite.config.ts file' )
81- }
82-
83- if ( ! defaultExport ) {
84- throw new Error ( 'Cannot find the default export in vite.config.ts' )
85- }
86-
87- const imports = await this . #addVitePostcssPlugins( defaultExport )
88-
89- this . #addMissingImports( file , imports )
90-
91- if ( imports . length ) {
92- file . formatText ( { indentSize : 2 } )
93-
94- this . logger . action ( 'create tailwind.config.ts' )
95- }
96-
97- await file . save ( )
50+ await this . #addVitePlugin( )
9851 }
9952
100- async #addVitePostcssPlugins( defaultExport : Symbol ) {
101- // get the object contents of `defineConfig`
102- const declaration = defaultExport . getDeclarations ( ) [ 0 ]
103- const options =
104- declaration . getChildrenOfKind ( SyntaxKind . ObjectLiteralExpression ) [ 0 ] ||
105- declaration . getChildrenOfKind ( SyntaxKind . CallExpression ) [ 0 ] . getArguments ( ) [ 0 ]
106-
107- // 1. if there isn't already a `css` property, we can add the whole thing
108- const cssProperty = options
109- . getProperty ( 'css' )
110- ?. getFirstChildByKind ( SyntaxKind . ObjectLiteralExpression )
111-
112- if ( ! cssProperty ?. getFullText ( ) ) {
113- options . addPropertyAssignment ( {
114- name : 'css' ,
115- initializer : `{ postcss: { plugins: [tailwind(), autoprefixer()] } }` ,
116- } )
117- return [ ...this . #imports. values ( ) ]
118- }
119-
120- // 2. if there is a `css` property but not a `postcss` property,
121- // we can add the whole `postcss` config
122- const postcssProperty = cssProperty
123- . getProperty ( 'postcss' )
124- ?. getFirstChildByKind ( SyntaxKind . ObjectLiteralExpression )
125-
126- if ( ! postcssProperty ?. getFullText ( ) ) {
127- cssProperty . addPropertyAssignment ( {
128- name : 'postcss' ,
129- initializer : '{ plugins: [tailwind(), autoprefixer()] }' ,
130- } )
131- return [ ...this . #imports. values ( ) ]
132- }
133-
134- // 3. if there is a `css.postcss` property, but it doesn't contain `plugins`,
135- // we can add the plugins
136- const plugins = postcssProperty
137- ?. getProperty ( 'plugins' )
138- ?. getFirstChildByKind ( SyntaxKind . ArrayLiteralExpression )
139-
140- if ( ! plugins ?. getFullText ( ) ) {
141- postcssProperty . addPropertyAssignment ( {
142- name : 'plugins' ,
143- initializer : '[tailwind(), autoprefixer()]' ,
144- } )
145- return [ ...this . #imports. values ( ) ]
146- }
147-
148- // 4. if there is a `css.postcss.plugins` property,
149- // determine if either the tailwind or autoprefixer plugis are missing
150- const pluginItems = plugins
151- ?. getElements ( )
152- . filter ( ( element ) => [ 'tailwind()' , 'autoprefixer()' ] . includes ( element . getText ( ) ) )
153- . map ( ( element ) => element . getText ( ) )
154-
155- const imports : Import [ ] = [ ]
156-
157- if ( ! pluginItems ?. includes ( 'tailwind()' ) ) {
158- plugins . insertElement ( 0 , 'tailwind()' )
159- imports . push ( this . #imports. get ( 'tailwind' ) ! )
160- }
161-
162- if ( ! pluginItems . includes ( 'autoprefixer()' ) ) {
163- plugins . addElement ( 'autoprefixer()' )
164- imports . push ( this . #imports. get ( 'autoprefixer' ) ! )
165- }
166-
167- return imports
168- }
169-
170- #addMissingImports( file : SourceFile , imports : Import [ ] ) {
171- const defaultImports = file . getImportDeclarations ( ) . map ( ( r ) => r . getDefaultImport ( ) ?. getText ( ) )
172-
173- imports ?. forEach ( ( imp ) => {
174- if ( defaultImports ?. includes ( imp . name ) ) return
175-
176- file . addImportDeclaration ( {
177- defaultImport : imp . name ,
178- moduleSpecifier : imp . module ,
179- } )
180- } )
53+ async #addVitePlugin( ) {
54+ this . codemods . registerVitePlugin ( 'tailwindcss()' , [
55+ {
56+ isNamed : false ,
57+ module : '@tailwindcss/vite' ,
58+ identifier : 'tailwindcss' ,
59+ } ,
60+ ] )
18161 }
18262}
0 commit comments