@@ -8,9 +8,11 @@ import { fileURLToPath } from 'url';
8
8
const __filename = fileURLToPath ( import . meta. url ) ;
9
9
const __dirname = path . dirname ( __filename ) ;
10
10
11
-
12
11
function toKebabCase ( str ) {
13
- return str . replace ( / ( [ a - z 0 - 9 ] ) ( [ A - Z ] ) / g, '$1-$2' ) . toLowerCase ( ) . replace ( / \s + / g, '-' ) ;
12
+ return str
13
+ . replace ( / ( [ a - z 0 - 9 ] ) ( [ A - Z ] ) / g, '$1-$2' )
14
+ . toLowerCase ( )
15
+ . replace ( / \s + / g, '-' ) ;
14
16
}
15
17
16
18
export default class extends Generator {
@@ -68,7 +70,7 @@ export default class extends Generator {
68
70
default : false ,
69
71
} ) ;
70
72
71
- this . installNextJS = async function ( ) {
73
+ this . installNextJS = async function ( ) {
72
74
// Clone Next.js template with Tailwind if specified, using the project name
73
75
const createNextAppCommand = [ '-y' , '[email protected] ' ] ;
74
76
createNextAppCommand . push ( toKebabCase ( this . options . project ) ) ; // Use the project name for the directory
@@ -80,52 +82,71 @@ export default class extends Generator {
80
82
createNextAppCommand . push ( '@/*' ) ;
81
83
createNextAppCommand . push ( '--use-npm' ) ;
82
84
createNextAppCommand . push ( '--eslint' ) ;
83
-
85
+
84
86
if ( this . options . typescript ) {
85
87
createNextAppCommand . push ( '--typescript' ) ; // This will avoid the TypeScript prompt
86
88
} else {
87
89
createNextAppCommand . push ( '--js' ) ;
88
90
}
89
-
91
+
90
92
if ( this . options . tailwind ) {
91
93
createNextAppCommand . push ( '--tailwind' ) ;
92
94
}
93
-
94
- this . log ( " Installing Next.js..." ) ;
95
- const patchPackages = '' ; //'next@14 react@18 react-dom@18';
95
+
96
+ this . log ( ' Installing Next.js...' ) ;
97
+ const patchPackages = '' ; //'next@14 react@18 react-dom@18';
96
98
const additionalPackages = `react-tooltip ${ patchPackages } ` ;
97
- await new Promise ( ( resolve , error ) => { exec ( `npx ${ createNextAppCommand . join ( ' ' ) } && cd ${ toKebabCase ( this . options . project ) } && npm install ${ additionalPackages } ` ) . on ( 'exit' , ( code ) => {
98
- this . destinationRoot ( this . destinationPath ( toKebabCase ( this . options . project ) ) ) ;
99
- resolve ( ) ;
100
- } ) ; } ) ;
101
- }
99
+ await new Promise ( ( resolve , error ) => {
100
+ exec (
101
+ `npx ${ createNextAppCommand . join ( ' ' ) } && cd ${ toKebabCase (
102
+ this . options . project
103
+ ) } && npm install ${ additionalPackages } `
104
+ ) . on ( 'exit' , ( code ) => {
105
+ this . destinationRoot (
106
+ this . destinationPath ( toKebabCase ( this . options . project ) )
107
+ ) ;
108
+ resolve ( ) ;
109
+ } ) ;
110
+ } ) ;
111
+ } ;
102
112
103
- this . installStorybook = function ( ) {
113
+ this . installStorybook = function ( ) {
104
114
// Conditionally initialize Storybook
105
115
if ( this . options . storybook ) {
106
116
this . log ( 'Installing Storybook...' ) ;
107
- this . spawnCommandSync ( 'npx' , [ '-y' , 'storybook@^8.4' , 'init' , '--no-dev' ] ) ;
117
+ this . spawnCommandSync ( 'npx' , [
118
+ '-y' ,
119
+ 'storybook@^8.4' ,
120
+ 'init' ,
121
+ '--no-dev' ,
122
+ ] ) ;
108
123
this . log ( 'Storybook installed!' ) ;
109
124
// if (this.options.tailwind && this.options.storybook) {
110
125
// Tailwind CSS specific setup for older versions of Storybook
111
126
// this.spawnCommandSync('npx', ['storybook@latest', 'add', '@storybook/addon-styling-webpack']);
112
127
// }
113
128
}
114
- }
115
-
116
- this . installCypress = function ( ) {
129
+ } ;
130
+
131
+ this . installCypress = function ( ) {
117
132
// Conditionally add Cypress
118
133
if ( this . options . cypress ) {
119
134
this . log ( 'Installing Cypress...' ) ;
120
135
this . spawnCommandSync ( 'npm' , [ 'install' , '--save-dev' , 'cypress' ] ) ;
121
136
this . log ( 'Cypress installed!' ) ;
122
137
if ( this . options . bitloops ) {
123
- this . spawnCommandSync ( 'npm' , [ 'install' , '--save-dev' , 'mochawesome' , 'mochawesome-merge' , 'mochawesome-report-generator' ] ) ;
138
+ this . spawnCommandSync ( 'npm' , [
139
+ 'install' ,
140
+ '--save-dev' ,
141
+ 'mochawesome' ,
142
+ 'mochawesome-merge' ,
143
+ 'mochawesome-report-generator' ,
144
+ ] ) ;
124
145
}
125
146
}
126
- }
127
-
128
- this . patchFiles = async function ( ) {
147
+ } ;
148
+
149
+ this . patchFiles = async function ( ) {
129
150
// Conditionally initialize Storybook
130
151
if ( this . options . storybook ) {
131
152
this . log ( 'Making Storybook changes...' ) ;
@@ -134,102 +155,134 @@ export default class extends Generator {
134
155
this . log ( 'Setting up Tailwind CSS with Storybook...' ) ;
135
156
this . fs . copyTpl (
136
157
this . templatePath ( 'storybook.preview.ts' ) ,
137
- this . destinationPath ( '.storybook/preview.ts' ) ,
138
- ) ;
158
+ this . destinationPath ( '.storybook/preview.ts' )
159
+ ) ;
139
160
}
140
161
this . log ( 'Removing default Storybook stories...' ) ;
141
162
try {
142
- fs . rmSync ( this . destinationPath ( 'src/stories' ) , { recursive : true , force : true } ) ;
163
+ fs . rmSync ( this . destinationPath ( 'src/stories' ) , {
164
+ recursive : true ,
165
+ force : true ,
166
+ } ) ;
143
167
console . log ( 'Sample stories directory deleted successfully!' ) ;
144
168
} catch ( err ) {
145
- console . error ( 'Error deleting sample stories directory:' , err ) ;
169
+ console . error ( 'Error deleting sample stories directory:' , err ) ;
146
170
}
147
171
fs . unlinkSync ( this . destinationPath ( 'tailwind.config.ts' ) ) ;
148
172
this . fs . copyTpl (
149
173
this . templatePath ( 'tailwind.config.ts' ) ,
150
- this . destinationPath ( 'tailwind.config.ts' ) ,
174
+ this . destinationPath ( 'tailwind.config.ts' )
151
175
) ;
152
176
}
153
-
177
+
154
178
if ( this . options . cypress ) {
155
179
this . log ( 'Adding Cypress config...' ) ;
156
180
this . fs . copyTpl (
157
181
this . templatePath ( 'cypress.config.ts' ) ,
158
- this . destinationPath ( 'cypress.config.ts' ) ,
159
- ) ;
182
+ this . destinationPath ( 'cypress.config.ts' )
183
+ ) ;
160
184
}
161
-
185
+
162
186
fs . unlinkSync ( this . destinationPath ( 'src/app/page.tsx' ) ) ;
163
187
this . fs . copyTpl (
164
188
this . templatePath ( 'next.app.page.tsx' ) ,
165
- this . destinationPath ( 'src/app/page.tsx' ) ,
166
- ) ;
167
-
189
+ this . destinationPath ( 'src/app/page.tsx' )
190
+ ) ;
191
+
168
192
fs . unlinkSync ( this . destinationPath ( 'src/app/layout.tsx' ) ) ;
169
193
this . fs . copyTpl (
170
194
this . templatePath ( 'next.app.layout.tsx' ) ,
171
195
this . destinationPath ( 'src/app/layout.tsx' ) ,
172
- { projectName : this . options . project } ,
196
+ { projectName : this . options . project }
173
197
) ;
174
-
198
+
175
199
this . log ( 'Adding Meyer reset in global.css...' ) ;
176
200
fs . unlinkSync ( this . destinationPath ( 'src/app/globals.css' ) ) ;
177
201
this . fs . copyTpl (
178
202
this . templatePath ( 'globals.css' ) ,
179
- this . destinationPath ( 'src/app/globals.css' ) ,
180
- ) ;
203
+ this . destinationPath ( 'src/app/globals.css' )
204
+ ) ;
181
205
182
206
if ( this . options . bitloops ) {
183
207
this . log ( 'Adding Bitloops support components...' ) ;
184
- const path = 'src/components/bitloops/Unsupported.tsx' ;
208
+ const unsupportedPath =
209
+ 'src/components/bitloops/unsupported/Unsupported.tsx' ;
210
+ this . fs . copyTpl (
211
+ this . templatePath ( unsupportedPath ) ,
212
+ this . destinationPath ( unsupportedPath )
213
+ ) ;
214
+ const buttonPath = 'src/components/bitloops/button/Button.tsx' ;
185
215
this . fs . copyTpl (
186
- this . templatePath ( path ) ,
187
- this . destinationPath ( path ) ,
188
- ) ;
216
+ this . templatePath ( buttonPath ) ,
217
+ this . destinationPath ( buttonPath )
218
+ ) ;
189
219
if ( this . options . storybook ) {
190
- const path = 'src/components/bitloops/Unsupported.stories.tsx' ;
220
+ const unsupportedPath =
221
+ 'src/components/bitloops/unsupported/Unsupported.stories.tsx' ;
191
222
this . fs . copyTpl (
192
- this . templatePath ( path ) ,
193
- this . destinationPath ( path ) ,
194
- ) ;
223
+ this . templatePath ( unsupportedPath ) ,
224
+ this . destinationPath ( unsupportedPath )
225
+ ) ;
226
+ const buttonPath =
227
+ 'src/components/bitloops/button/Button.stories.tsx' ;
228
+ this . fs . copyTpl (
229
+ this . templatePath ( buttonPath ) ,
230
+ this . destinationPath ( buttonPath )
231
+ ) ;
195
232
}
196
233
if ( this . options . cypress ) {
197
234
const path = 'cypress/helpers/index.ts' ;
198
- this . fs . copyTpl (
199
- this . templatePath ( path ) ,
200
- this . destinationPath ( path ) ,
201
- ) ;
235
+ this . fs . copyTpl ( this . templatePath ( path ) , this . destinationPath ( path ) ) ;
202
236
}
237
+ this . spawnCommandSync ( 'npm' , [
238
+ 'install' ,
239
+ '--save-dev' ,
240
+ 'react-aria-components' ,
241
+ ] ) ;
203
242
}
204
- }
243
+ } ;
205
244
206
- this . commitChanges = async function ( ) {
245
+ this . commitChanges = async function ( ) {
207
246
this . log ( 'Committing changes to git...' ) ;
208
- await new Promise ( ( resolve ) => { exec ( `cd ${ toKebabCase ( this . options . project ) } && git add . && git commit -m "Initial setup"` ) . on ( 'exit' , ( code ) => {
209
- if ( code !== 0 ) {
210
- this . log ( 'Error committing changes to git! ' , code ) ;
247
+ await new Promise ( ( resolve ) => {
248
+ exec (
249
+ `cd ${ toKebabCase (
250
+ this . options . project
251
+ ) } && git add . && git commit -m "Initial setup"`
252
+ ) . on ( 'exit' , ( code ) => {
253
+ if ( code !== 0 ) {
254
+ this . log ( 'Error committing changes to git! ' , code ) ;
255
+ resolve ( ) ;
256
+ }
257
+ this . log ( 'Git changes committed!' ) ;
211
258
resolve ( ) ;
212
- }
213
- this . log ( 'Git changes committed!' ) ;
214
- resolve ( ) ;
215
- } ) ; } ) ;
216
- }
259
+ } ) ;
260
+ } ) ;
261
+ } ;
217
262
}
218
263
219
264
initializing ( ) {
220
265
// Check if the project name and --nextjs flag are provided
221
266
if ( ! this . options . project ) {
222
- this . log ( "Error: --project option is required to specify the project name." ) ;
267
+ this . log (
268
+ 'Error: --project option is required to specify the project name.'
269
+ ) ;
223
270
process . exit ( 1 ) ;
224
271
}
225
272
226
273
if ( ! this . options . nextjs ) {
227
- this . log ( "Error: --nextjs option is currently required to scaffold a project." ) ;
274
+ this . log (
275
+ 'Error: --nextjs option is currently required to scaffold a project.'
276
+ ) ;
228
277
process . exit ( 1 ) ;
229
278
}
230
279
231
- this . log ( `Initializing project ${ toKebabCase ( this . options . project ) } with the selected options...` ) ;
232
- }
280
+ this . log (
281
+ `Initializing project ${ toKebabCase (
282
+ this . options . project
283
+ ) } with the selected options...`
284
+ ) ;
285
+ }
233
286
234
287
async main ( ) {
235
288
await this . installNextJS ( ) ;
@@ -242,12 +295,21 @@ export default class extends Generator {
242
295
}
243
296
244
297
end ( ) {
245
- this . log ( `Your Bitloops project '${ toKebabCase ( this . options . project ) } ' setup is complete! 🎉🎉🎉` ) ;
298
+ this . log (
299
+ `Your Bitloops project '${ toKebabCase (
300
+ this . options . project
301
+ ) } ' setup is complete! 🎉🎉🎉`
302
+ ) ;
246
303
this . log ( '' ) ;
247
304
this . log ( 'Use the following commands to start:' ) ;
248
- this . log ( "- `npm run dev` to start the Next.js app." ) ;
249
- if ( this . options . storybook ) this . log ( "- `npm run storybook` to start Storybook." ) ;
250
- if ( this . options . cypress ) this . log ( "- `npx cypress open --e2e --browser chrome` to open Cypress." ) ;
251
- if ( this . options . cypress ) this . log ( "- `npx cypress run --e2e --browser chrome` to run Cypress on the terminal." ) ;
305
+ this . log ( '- `npm run dev` to start the Next.js app.' ) ;
306
+ if ( this . options . storybook )
307
+ this . log ( '- `npm run storybook` to start Storybook.' ) ;
308
+ if ( this . options . cypress )
309
+ this . log ( '- `npx cypress open --e2e --browser chrome` to open Cypress.' ) ;
310
+ if ( this . options . cypress )
311
+ this . log (
312
+ '- `npx cypress run --e2e --browser chrome` to run Cypress on the terminal.'
313
+ ) ;
252
314
}
253
- } ;
315
+ }
0 commit comments