Skip to content

Commit 5f48365

Browse files
committed
feat(tailwindcss): updated tailwindcss integration from v3 to v4. closes #1
1 parent 45ff162 commit 5f48365

File tree

2 files changed

+21
-140
lines changed

2 files changed

+21
-140
lines changed

src/scaffolds/tailwind_scaffold.ts

Lines changed: 18 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,25 @@
11
import ConfigureCommand from '@adonisjs/core/commands/configure'
22
import { 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'
63
import { readFileOrDefault } from '../utils/file_helper.js'
74
import BaseScaffold from './base_scaffold.js'
85

9-
type Import = {
10-
name: string
11-
module: string
12-
}
13-
146
export 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
}

stubs/views/components/layout/index.edge

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
</a>
2525
<nav class="flex flex-wrap items-center mb-5 text-sm md:mb-0 md:pl-8 md:ml-8 md:border-l md:border-gray-200">
2626
<a href="{{ route('jumpstart') }}" class="mr-5 font-medium leading-6 text-gray-600 hover:text-gray-900">Home</a>
27-
<a href="#_" class="mr-5 font-medium leading-6 text-gray-600 hover:text-gray-900">Documentation</a>
2827
<a href="https://adonisjs.com" target="_blank" class="mr-5 font-medium leading-6 text-gray-600 hover:text-gray-900">AdonisJS</a>
2928
<a href="https://adocasts.com" target="_blank" class="mr-5 font-medium leading-6 text-gray-600 hover:text-gray-900">Adocasts</a>
3029
</nav>
@@ -79,7 +78,9 @@
7978
<!-- End Navigation -->
8079

8180
<main class="px-8">
82-
{{{ await $slots.main() }}}
81+
<div class="max-w-7xl mx-auto">
82+
{{{ await $slots.main() }}}
83+
</div>
8384
</main>
8485

8586
@!toast.flash()

0 commit comments

Comments
 (0)