1
1
#!/usr/bin/env zx
2
+ /* global $, fs, path, argv, echo, spinner */
2
3
3
- $ . verbose = false
4
+ const name = argv . _ [ 0 ]
5
+ if ( ! name ) {
6
+ echo `Error: please specify the app name`
7
+ process . exit ( 1 )
8
+ }
9
+
10
+ function p ( ...args ) {
11
+ return path . join ( name , ...args )
12
+ }
4
13
5
14
async function patchFiles ( files , ...replacers ) {
6
15
for ( const file of [ files ] . flat ( ) ) {
@@ -12,9 +21,9 @@ async function patchFiles(files, ...replacers) {
12
21
}
13
22
}
14
23
15
- async function patchPackage ( name , ...dependencies ) {
24
+ async function patchPackage ( ...dependencies ) {
16
25
const version = async ( dep ) => ( await $ `npm show ${ dep } version` ) . stdout . trim ( )
17
- const file = path . join ( name , 'package.json' )
26
+ const file = p ( 'package.json' )
18
27
let pkg = await fs . readJson ( file )
19
28
for ( const dep of dependencies ) {
20
29
pkg . devDependencies [ dep . slice ( 1 ) ] =
@@ -23,31 +32,83 @@ async function patchPackage(name, ...dependencies) {
23
32
await fs . writeJson ( file , pkg , { spaces : 2 } )
24
33
}
25
34
26
- const name = argv . _ [ 0 ]
27
- if ( ! name ) {
28
- echo `Error: please specify the app name`
29
- process . exit ( 1 )
30
- }
31
-
32
35
await spinner ( 'replace favicon' , async ( ) => {
33
- await fetch ( 'https://raw.githubusercontent.com/zerodevx/sveltekit-starter/main/favicon.png' ) . then (
34
- ( r ) => r . body . pipe ( fs . createWriteStream ( path . join ( name , 'static' , 'favicon.png' ) ) )
35
- )
36
+ const req = await fetch ( 'https://cdn.jsdelivr.net/gh/zerodevx/sveltekit-starter/favicon.png' )
37
+ const blob = await req . blob ( )
38
+ const buf = await blob . arrayBuffer ( )
39
+ await fs . writeFile ( p ( 'static' , 'favicon.png' ) , Buffer . from ( buf ) )
36
40
} )
37
41
38
- await spinner ( 'add tailwindcss' , async ( ) => {
39
- await $ `cd ${ name } && npx -y svelte-add@latest tailwindcss`
40
- await patchPackage ( name , '+@tailwindcss/typography' )
41
- await patchFiles ( path . join ( name , 'tailwind.config.cjs' ) , [
42
- `plugins: [` ,
43
- `plugins: [require('@tailwindcss/typography'),`
42
+ await spinner ( 'add tailwindcss, iconify and fontsource' , async ( ) => {
43
+ await patchPackage (
44
+ '+tailwindcss' ,
45
+ '+@tailwindcss/typography' ,
46
+ '+@fontsource-variable/inter' ,
47
+ '+@iconify/tailwind' ,
48
+ '+@iconify-json/mdi' ,
49
+ '+prettier-plugin-tailwindcss'
50
+ )
51
+ await fs . writeFile (
52
+ p ( 'tailwind.config.js' ) ,
53
+ `import { addIconSelectors } from '@iconify/tailwind'
54
+ import typography from '@tailwindcss/typography'
55
+ import dt from 'tailwindcss/defaultTheme'
56
+
57
+ /** @type {import('tailwindcss').Config} */
58
+ export default {
59
+ content: ['./src/**/*.{html,js,svelte,ts}'],
60
+ theme: {
61
+ extend: {
62
+ fontFamily: {
63
+ sans: ['Inter Variable', ...dt.fontFamily.sans]
64
+ }
65
+ }
66
+ },
67
+ plugins: [addIconSelectors(['mdi']), typography]
68
+ }`
69
+ )
70
+ await fs . writeFile (
71
+ p ( 'postcss.config.js' ) ,
72
+ `/** @type {import('postcss-load-config').Config} */
73
+ export default {
74
+ plugins: {
75
+ tailwindcss: {},
76
+ autoprefixer: {}
77
+ }
78
+ }`
79
+ )
80
+ await fs . writeFile (
81
+ p ( 'src' , 'app.pcss' ) ,
82
+ `/* Write your global styles here, in PostCSS syntax */
83
+ @tailwind base;
84
+ @tailwind components;
85
+ @tailwind utilities;`
86
+ )
87
+ await fs . writeFile (
88
+ p ( 'src' , 'routes' , '+layout.svelte' ) ,
89
+ `<script>
90
+ import '@fontsource-variable/inter'
91
+ import '../app.pcss'
92
+ </script>
93
+
94
+ <slot />`
95
+ )
96
+ await patchFiles ( p ( 'src' , 'routes' , '+page.svelte' ) , [
97
+ `</h1>` ,
98
+ `</h1>\n<span class="iconify mdi--heart text-red-600 animate-pulse" />\n`
44
99
] )
100
+ await patchFiles (
101
+ p ( 'svelte.config.js' ) ,
102
+ [ `import` , `import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';\nimport` ] ,
103
+ [ `\n};` , `, preprocess: [vitePreprocess()]\n};` ]
104
+ )
45
105
} )
46
106
47
107
await spinner ( 'patch prettier' , async ( ) => {
48
- const file = path . join ( name , '.prettierrc' )
49
- await fs . writeJson ( file , {
50
- ...( await fs . readJson ( file ) ) ,
108
+ let config = await fs . readJson ( p ( '.prettierrc' ) )
109
+ config . plugins = [ ...config . plugins , 'prettier-plugin-tailwindcss' ]
110
+ await fs . writeJson ( p ( '.prettierrc' ) , {
111
+ ...config ,
51
112
printWidth : 100 ,
52
113
useTabs : false ,
53
114
semi : false ,
@@ -60,24 +121,21 @@ await spinner('patch prettier', async () => {
60
121
} )
61
122
62
123
await spinner ( 'patch eslint' , async ( ) => {
63
- await patchFiles ( path . join ( name , '.eslintrc.cjs ') , [
64
- `}\n}; ` ,
65
- `},\n\trules : { 'no-tabs': 'error', 'no-unexpected-multiline': 'error' }\n}; `
124
+ await patchFiles ( p ( 'eslint.config.js ') , [
125
+ `languageOptions ` ,
126
+ `rules : { 'no-tabs': 'error', 'no-unexpected-multiline': 'error' }, languageOptions `
66
127
] )
67
128
} )
68
129
69
130
await spinner ( 'add adapter-static' , async ( ) => {
70
- await patchFiles ( path . join ( name , 'svelte.config.js' ) , [ `adapter-auto` , `adapter-static` ] )
131
+ await patchFiles ( p ( 'svelte.config.js' ) , [ `adapter-auto` , `adapter-static` ] )
71
132
await patchPackage ( name , '-@sveltejs/adapter-auto' , '+@sveltejs/adapter-static' )
72
- await fs . outputFile (
73
- path . join ( name , 'src' , 'routes' , '+layout.js' ) ,
74
- `export const prerender = true\n`
75
- )
133
+ await fs . writeFile ( p ( 'src' , 'routes' , '+layout.js' ) , `export const prerender = true\n` )
76
134
} )
77
135
78
136
await spinner ( 'add versioning' , async ( ) => {
79
137
await patchFiles (
80
- path . join ( name , 'svelte.config.js' ) ,
138
+ p ( 'svelte.config.js' ) ,
81
139
[
82
140
`static';` ,
83
141
`static';\nimport { readFileSync } from 'node:fs'\n\nconst { version: name } = JSON.parse(readFileSync(new URL('package.json', import.meta.url), 'utf8'))\n`
@@ -86,32 +144,6 @@ await spinner('add versioning', async () => {
86
144
)
87
145
} )
88
146
89
- await spinner ( 'add fontsource' , async ( ) => {
90
- await patchPackage ( name , '+@fontsource-variable/inter' )
91
- await patchFiles ( path . join ( name , 'src' , 'routes' , '+layout.svelte' ) , [
92
- `<script>` ,
93
- `<script>import '@fontsource-variable/inter';`
94
- ] )
95
- await patchFiles (
96
- path . join ( name , 'tailwind.config.cjs' ) ,
97
- [ `/**` , `const dt = require('tailwindcss/defaultTheme');\n\n/**` ] ,
98
- [ `extend: {}` , `extend: { fontFamily: { sans: ['Inter Variable', ...dt.fontFamily.sans] } }` ]
99
- )
100
- } )
101
-
102
- await spinner ( 'add iconify' , async ( ) => {
103
- await patchPackage ( name , '+@iconify/tailwind' , '+@iconify-json/mdi' )
104
- await patchFiles (
105
- path . join ( name , 'tailwind.config.cjs' ) ,
106
- [ `const dt` , `const { addDynamicIconSelectors } = require('@iconify/tailwind');\nconst dt` ] ,
107
- [ `plugins: [` , `plugins: [addDynamicIconSelectors({ scale: 0 }),` ]
108
- )
109
- await patchFiles ( path . join ( name , 'src' , 'routes' , '+page.svelte' ) , [
110
- `</h1>` ,
111
- `</h1>\n<span class="icon-[mdi--heart] w-8 h-8 text-red-600 animate-pulse" />\n`
112
- ] )
113
- } )
114
-
115
147
echo `
116
148
All done! Complete the setup with:
117
149
0 commit comments