+101
.gitignore
+101
.gitignore
···
1
+
# Logs
2
+
logs
3
+
*.log
4
+
npm-debug.log*
5
+
yarn-debug.log*
6
+
yarn-error.log*
7
+
lerna-debug.log*
8
+
9
+
# Diagnostic reports (https://nodejs.org/api/report.html)
10
+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11
+
12
+
# Runtime data
13
+
pids
14
+
*.pid
15
+
*.seed
16
+
*.pid.lock
17
+
18
+
# Directory for instrumented libs generated by jscoverage/JSCover
19
+
lib-cov
20
+
21
+
# Coverage directory used by tools like istanbul
22
+
coverage
23
+
*.lcov
24
+
25
+
# nyc test coverage
26
+
.nyc_output
27
+
28
+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29
+
.grunt
30
+
31
+
# Bower dependency directory (https://bower.io/)
32
+
bower_components
33
+
34
+
# node-waf configuration
35
+
.lock-wscript
36
+
37
+
# Compiled binary addons (https://nodejs.org/api/addons.html)
38
+
build/Release
39
+
40
+
# Dependency directories
41
+
node_modules/
42
+
jspm_packages/
43
+
44
+
# TypeScript v1 declaration files
45
+
typings/
46
+
47
+
# TypeScript cache
48
+
*.tsbuildinfo
49
+
50
+
# Optional npm cache directory
51
+
.npm
52
+
53
+
# Optional eslint cache
54
+
.eslintcache
55
+
56
+
# Microbundle cache
57
+
.rpt2_cache/
58
+
.rts2_cache_cjs/
59
+
.rts2_cache_es/
60
+
.rts2_cache_umd/
61
+
62
+
# Optional REPL history
63
+
.node_repl_history
64
+
65
+
# Output of 'npm pack'
66
+
*.tgz
67
+
68
+
# Yarn Integrity file
69
+
.yarn-integrity
70
+
71
+
# dotenv environment variables file
72
+
.env
73
+
.env.test
74
+
75
+
# parcel-bundler cache (https://parceljs.org/)
76
+
.cache
77
+
78
+
# next.js build output
79
+
.next
80
+
81
+
# nuxt.js build output
82
+
.nuxt
83
+
84
+
# gatsby files
85
+
.cache/
86
+
public
87
+
88
+
# vuepress build output
89
+
.vuepress/dist
90
+
91
+
# Serverless directories
92
+
.serverless/
93
+
94
+
# FuseBox cache
95
+
.fusebox/
96
+
97
+
# DynamoDB Local files
98
+
.dynamodb/
99
+
100
+
distribution/*
101
+
bin/*
+21
LICENSE
+21
LICENSE
···
1
+
MIT License
2
+
3
+
Copyright (c) 2020 Cory Sanin
4
+
5
+
Permission is hereby granted, free of charge, to any person obtaining a copy
6
+
of this software and associated documentation files (the "Software"), to deal
7
+
in the Software without restriction, including without limitation the rights
8
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+
copies of the Software, and to permit persons to whom the Software is
10
+
furnished to do so, subject to the following conditions:
11
+
12
+
The above copyright notice and this permission notice shall be included in all
13
+
copies or substantial portions of the Software.
14
+
15
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+
SOFTWARE.
+20
README.md
+20
README.md
···
1
+
# build-shit
2
+
A build script for preparing files for production. It handles CSS and JavaScript minification, Sass compilation, and image conversion to WebP.
3
+
4
+
WebP conversion requires libwebp.
5
+
6
+
## Installation
7
+
8
+
```
9
+
npm install --save-dev build-shit
10
+
```
11
+
12
+
## Usage
13
+
14
+
build-shit processes files from the following relative directories:
15
+
16
+
- `styles/` - Contains SCSS files
17
+
- `scripts/` - Contains JavaScript files
18
+
- `assets/images/original/` - Contains image files
19
+
20
+
After populating these directories, run the build script with `npx build-shit`.
+632
package-lock.json
+632
package-lock.json
···
1
+
{
2
+
"name": "build-shit",
3
+
"version": "0.0.1",
4
+
"lockfileVersion": 3,
5
+
"requires": true,
6
+
"packages": {
7
+
"": {
8
+
"name": "build-shit",
9
+
"version": "0.0.1",
10
+
"license": "MIT",
11
+
"dependencies": {
12
+
"csso": "5.0.5",
13
+
"sass": "1.86.0",
14
+
"uglify-js": "3.19.3"
15
+
},
16
+
"bin": {
17
+
"build-shit": "bin/build-shit.js"
18
+
},
19
+
"devDependencies": {
20
+
"@sindresorhus/tsconfig": "7.0.0",
21
+
"@types/csso": "^5.0.4",
22
+
"@types/node": "^22.13.10",
23
+
"@types/uglify-js": "^3.17.5",
24
+
"typescript": "5.8.2"
25
+
}
26
+
},
27
+
"node_modules/@parcel/watcher": {
28
+
"version": "2.5.1",
29
+
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
30
+
"integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
31
+
"hasInstallScript": true,
32
+
"license": "MIT",
33
+
"optional": true,
34
+
"dependencies": {
35
+
"detect-libc": "^1.0.3",
36
+
"is-glob": "^4.0.3",
37
+
"micromatch": "^4.0.5",
38
+
"node-addon-api": "^7.0.0"
39
+
},
40
+
"engines": {
41
+
"node": ">= 10.0.0"
42
+
},
43
+
"funding": {
44
+
"type": "opencollective",
45
+
"url": "https://opencollective.com/parcel"
46
+
},
47
+
"optionalDependencies": {
48
+
"@parcel/watcher-android-arm64": "2.5.1",
49
+
"@parcel/watcher-darwin-arm64": "2.5.1",
50
+
"@parcel/watcher-darwin-x64": "2.5.1",
51
+
"@parcel/watcher-freebsd-x64": "2.5.1",
52
+
"@parcel/watcher-linux-arm-glibc": "2.5.1",
53
+
"@parcel/watcher-linux-arm-musl": "2.5.1",
54
+
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
55
+
"@parcel/watcher-linux-arm64-musl": "2.5.1",
56
+
"@parcel/watcher-linux-x64-glibc": "2.5.1",
57
+
"@parcel/watcher-linux-x64-musl": "2.5.1",
58
+
"@parcel/watcher-win32-arm64": "2.5.1",
59
+
"@parcel/watcher-win32-ia32": "2.5.1",
60
+
"@parcel/watcher-win32-x64": "2.5.1"
61
+
}
62
+
},
63
+
"node_modules/@parcel/watcher-android-arm64": {
64
+
"version": "2.5.1",
65
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
66
+
"integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
67
+
"cpu": [
68
+
"arm64"
69
+
],
70
+
"license": "MIT",
71
+
"optional": true,
72
+
"os": [
73
+
"android"
74
+
],
75
+
"engines": {
76
+
"node": ">= 10.0.0"
77
+
},
78
+
"funding": {
79
+
"type": "opencollective",
80
+
"url": "https://opencollective.com/parcel"
81
+
}
82
+
},
83
+
"node_modules/@parcel/watcher-darwin-arm64": {
84
+
"version": "2.5.1",
85
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
86
+
"integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
87
+
"cpu": [
88
+
"arm64"
89
+
],
90
+
"license": "MIT",
91
+
"optional": true,
92
+
"os": [
93
+
"darwin"
94
+
],
95
+
"engines": {
96
+
"node": ">= 10.0.0"
97
+
},
98
+
"funding": {
99
+
"type": "opencollective",
100
+
"url": "https://opencollective.com/parcel"
101
+
}
102
+
},
103
+
"node_modules/@parcel/watcher-darwin-x64": {
104
+
"version": "2.5.1",
105
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
106
+
"integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
107
+
"cpu": [
108
+
"x64"
109
+
],
110
+
"license": "MIT",
111
+
"optional": true,
112
+
"os": [
113
+
"darwin"
114
+
],
115
+
"engines": {
116
+
"node": ">= 10.0.0"
117
+
},
118
+
"funding": {
119
+
"type": "opencollective",
120
+
"url": "https://opencollective.com/parcel"
121
+
}
122
+
},
123
+
"node_modules/@parcel/watcher-freebsd-x64": {
124
+
"version": "2.5.1",
125
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
126
+
"integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
127
+
"cpu": [
128
+
"x64"
129
+
],
130
+
"license": "MIT",
131
+
"optional": true,
132
+
"os": [
133
+
"freebsd"
134
+
],
135
+
"engines": {
136
+
"node": ">= 10.0.0"
137
+
},
138
+
"funding": {
139
+
"type": "opencollective",
140
+
"url": "https://opencollective.com/parcel"
141
+
}
142
+
},
143
+
"node_modules/@parcel/watcher-linux-arm-glibc": {
144
+
"version": "2.5.1",
145
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
146
+
"integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
147
+
"cpu": [
148
+
"arm"
149
+
],
150
+
"license": "MIT",
151
+
"optional": true,
152
+
"os": [
153
+
"linux"
154
+
],
155
+
"engines": {
156
+
"node": ">= 10.0.0"
157
+
},
158
+
"funding": {
159
+
"type": "opencollective",
160
+
"url": "https://opencollective.com/parcel"
161
+
}
162
+
},
163
+
"node_modules/@parcel/watcher-linux-arm-musl": {
164
+
"version": "2.5.1",
165
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
166
+
"integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
167
+
"cpu": [
168
+
"arm"
169
+
],
170
+
"license": "MIT",
171
+
"optional": true,
172
+
"os": [
173
+
"linux"
174
+
],
175
+
"engines": {
176
+
"node": ">= 10.0.0"
177
+
},
178
+
"funding": {
179
+
"type": "opencollective",
180
+
"url": "https://opencollective.com/parcel"
181
+
}
182
+
},
183
+
"node_modules/@parcel/watcher-linux-arm64-glibc": {
184
+
"version": "2.5.1",
185
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
186
+
"integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
187
+
"cpu": [
188
+
"arm64"
189
+
],
190
+
"license": "MIT",
191
+
"optional": true,
192
+
"os": [
193
+
"linux"
194
+
],
195
+
"engines": {
196
+
"node": ">= 10.0.0"
197
+
},
198
+
"funding": {
199
+
"type": "opencollective",
200
+
"url": "https://opencollective.com/parcel"
201
+
}
202
+
},
203
+
"node_modules/@parcel/watcher-linux-arm64-musl": {
204
+
"version": "2.5.1",
205
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
206
+
"integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
207
+
"cpu": [
208
+
"arm64"
209
+
],
210
+
"license": "MIT",
211
+
"optional": true,
212
+
"os": [
213
+
"linux"
214
+
],
215
+
"engines": {
216
+
"node": ">= 10.0.0"
217
+
},
218
+
"funding": {
219
+
"type": "opencollective",
220
+
"url": "https://opencollective.com/parcel"
221
+
}
222
+
},
223
+
"node_modules/@parcel/watcher-linux-x64-glibc": {
224
+
"version": "2.5.1",
225
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
226
+
"integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
227
+
"cpu": [
228
+
"x64"
229
+
],
230
+
"license": "MIT",
231
+
"optional": true,
232
+
"os": [
233
+
"linux"
234
+
],
235
+
"engines": {
236
+
"node": ">= 10.0.0"
237
+
},
238
+
"funding": {
239
+
"type": "opencollective",
240
+
"url": "https://opencollective.com/parcel"
241
+
}
242
+
},
243
+
"node_modules/@parcel/watcher-linux-x64-musl": {
244
+
"version": "2.5.1",
245
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
246
+
"integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
247
+
"cpu": [
248
+
"x64"
249
+
],
250
+
"license": "MIT",
251
+
"optional": true,
252
+
"os": [
253
+
"linux"
254
+
],
255
+
"engines": {
256
+
"node": ">= 10.0.0"
257
+
},
258
+
"funding": {
259
+
"type": "opencollective",
260
+
"url": "https://opencollective.com/parcel"
261
+
}
262
+
},
263
+
"node_modules/@parcel/watcher-win32-arm64": {
264
+
"version": "2.5.1",
265
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
266
+
"integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
267
+
"cpu": [
268
+
"arm64"
269
+
],
270
+
"license": "MIT",
271
+
"optional": true,
272
+
"os": [
273
+
"win32"
274
+
],
275
+
"engines": {
276
+
"node": ">= 10.0.0"
277
+
},
278
+
"funding": {
279
+
"type": "opencollective",
280
+
"url": "https://opencollective.com/parcel"
281
+
}
282
+
},
283
+
"node_modules/@parcel/watcher-win32-ia32": {
284
+
"version": "2.5.1",
285
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
286
+
"integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
287
+
"cpu": [
288
+
"ia32"
289
+
],
290
+
"license": "MIT",
291
+
"optional": true,
292
+
"os": [
293
+
"win32"
294
+
],
295
+
"engines": {
296
+
"node": ">= 10.0.0"
297
+
},
298
+
"funding": {
299
+
"type": "opencollective",
300
+
"url": "https://opencollective.com/parcel"
301
+
}
302
+
},
303
+
"node_modules/@parcel/watcher-win32-x64": {
304
+
"version": "2.5.1",
305
+
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
306
+
"integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
307
+
"cpu": [
308
+
"x64"
309
+
],
310
+
"license": "MIT",
311
+
"optional": true,
312
+
"os": [
313
+
"win32"
314
+
],
315
+
"engines": {
316
+
"node": ">= 10.0.0"
317
+
},
318
+
"funding": {
319
+
"type": "opencollective",
320
+
"url": "https://opencollective.com/parcel"
321
+
}
322
+
},
323
+
"node_modules/@sindresorhus/tsconfig": {
324
+
"version": "7.0.0",
325
+
"resolved": "https://registry.npmjs.org/@sindresorhus/tsconfig/-/tsconfig-7.0.0.tgz",
326
+
"integrity": "sha512-i5K04hLAP44Af16zmDjG07E1NHuDgCM07SJAT4gY0LZSRrWYzwt4qkLem6TIbIVh0k51RkN2bF+lP+lM5eC9fw==",
327
+
"dev": true,
328
+
"license": "MIT",
329
+
"engines": {
330
+
"node": ">=18"
331
+
},
332
+
"funding": {
333
+
"url": "https://github.com/sponsors/sindresorhus"
334
+
}
335
+
},
336
+
"node_modules/@types/css-tree": {
337
+
"version": "2.3.10",
338
+
"resolved": "https://registry.npmjs.org/@types/css-tree/-/css-tree-2.3.10.tgz",
339
+
"integrity": "sha512-WcaBazJ84RxABvRttQjjFWgTcHvZR9jGr0Y3hccPkHjFyk/a3N8EuxjKr+QfrwjoM5b1yI1Uj1i7EzOAAwBwag==",
340
+
"dev": true,
341
+
"license": "MIT"
342
+
},
343
+
"node_modules/@types/csso": {
344
+
"version": "5.0.4",
345
+
"resolved": "https://registry.npmjs.org/@types/csso/-/csso-5.0.4.tgz",
346
+
"integrity": "sha512-W/FsRkm/9c04x9ON+bj+HQ0cSgNkG1LvcfuBCpkP7cpikM7+RkrNFLGtiofb++xBG6KGMUycLoDbi9/K621ZCw==",
347
+
"dev": true,
348
+
"license": "MIT",
349
+
"dependencies": {
350
+
"@types/css-tree": "*"
351
+
}
352
+
},
353
+
"node_modules/@types/node": {
354
+
"version": "22.13.10",
355
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz",
356
+
"integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
357
+
"dev": true,
358
+
"license": "MIT",
359
+
"dependencies": {
360
+
"undici-types": "~6.20.0"
361
+
}
362
+
},
363
+
"node_modules/@types/uglify-js": {
364
+
"version": "3.17.5",
365
+
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.17.5.tgz",
366
+
"integrity": "sha512-TU+fZFBTBcXj/GpDpDaBmgWk/gn96kMZ+uocaFUlV2f8a6WdMzzI44QBCmGcCiYR0Y6ZlNRiyUyKKt5nl/lbzQ==",
367
+
"dev": true,
368
+
"license": "MIT",
369
+
"dependencies": {
370
+
"source-map": "^0.6.1"
371
+
}
372
+
},
373
+
"node_modules/braces": {
374
+
"version": "3.0.3",
375
+
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
376
+
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
377
+
"license": "MIT",
378
+
"optional": true,
379
+
"dependencies": {
380
+
"fill-range": "^7.1.1"
381
+
},
382
+
"engines": {
383
+
"node": ">=8"
384
+
}
385
+
},
386
+
"node_modules/chokidar": {
387
+
"version": "4.0.3",
388
+
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
389
+
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
390
+
"license": "MIT",
391
+
"dependencies": {
392
+
"readdirp": "^4.0.1"
393
+
},
394
+
"engines": {
395
+
"node": ">= 14.16.0"
396
+
},
397
+
"funding": {
398
+
"url": "https://paulmillr.com/funding/"
399
+
}
400
+
},
401
+
"node_modules/css-tree": {
402
+
"version": "2.2.1",
403
+
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
404
+
"integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
405
+
"license": "MIT",
406
+
"dependencies": {
407
+
"mdn-data": "2.0.28",
408
+
"source-map-js": "^1.0.1"
409
+
},
410
+
"engines": {
411
+
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
412
+
"npm": ">=7.0.0"
413
+
}
414
+
},
415
+
"node_modules/csso": {
416
+
"version": "5.0.5",
417
+
"resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
418
+
"integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
419
+
"license": "MIT",
420
+
"dependencies": {
421
+
"css-tree": "~2.2.0"
422
+
},
423
+
"engines": {
424
+
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
425
+
"npm": ">=7.0.0"
426
+
}
427
+
},
428
+
"node_modules/detect-libc": {
429
+
"version": "1.0.3",
430
+
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
431
+
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
432
+
"license": "Apache-2.0",
433
+
"optional": true,
434
+
"bin": {
435
+
"detect-libc": "bin/detect-libc.js"
436
+
},
437
+
"engines": {
438
+
"node": ">=0.10"
439
+
}
440
+
},
441
+
"node_modules/fill-range": {
442
+
"version": "7.1.1",
443
+
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
444
+
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
445
+
"license": "MIT",
446
+
"optional": true,
447
+
"dependencies": {
448
+
"to-regex-range": "^5.0.1"
449
+
},
450
+
"engines": {
451
+
"node": ">=8"
452
+
}
453
+
},
454
+
"node_modules/immutable": {
455
+
"version": "5.0.3",
456
+
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz",
457
+
"integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==",
458
+
"license": "MIT"
459
+
},
460
+
"node_modules/is-extglob": {
461
+
"version": "2.1.1",
462
+
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
463
+
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
464
+
"license": "MIT",
465
+
"optional": true,
466
+
"engines": {
467
+
"node": ">=0.10.0"
468
+
}
469
+
},
470
+
"node_modules/is-glob": {
471
+
"version": "4.0.3",
472
+
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
473
+
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
474
+
"license": "MIT",
475
+
"optional": true,
476
+
"dependencies": {
477
+
"is-extglob": "^2.1.1"
478
+
},
479
+
"engines": {
480
+
"node": ">=0.10.0"
481
+
}
482
+
},
483
+
"node_modules/is-number": {
484
+
"version": "7.0.0",
485
+
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
486
+
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
487
+
"license": "MIT",
488
+
"optional": true,
489
+
"engines": {
490
+
"node": ">=0.12.0"
491
+
}
492
+
},
493
+
"node_modules/mdn-data": {
494
+
"version": "2.0.28",
495
+
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
496
+
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
497
+
"license": "CC0-1.0"
498
+
},
499
+
"node_modules/micromatch": {
500
+
"version": "4.0.8",
501
+
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
502
+
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
503
+
"license": "MIT",
504
+
"optional": true,
505
+
"dependencies": {
506
+
"braces": "^3.0.3",
507
+
"picomatch": "^2.3.1"
508
+
},
509
+
"engines": {
510
+
"node": ">=8.6"
511
+
}
512
+
},
513
+
"node_modules/node-addon-api": {
514
+
"version": "7.1.1",
515
+
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
516
+
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
517
+
"license": "MIT",
518
+
"optional": true
519
+
},
520
+
"node_modules/picomatch": {
521
+
"version": "2.3.1",
522
+
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
523
+
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
524
+
"license": "MIT",
525
+
"optional": true,
526
+
"engines": {
527
+
"node": ">=8.6"
528
+
},
529
+
"funding": {
530
+
"url": "https://github.com/sponsors/jonschlinkert"
531
+
}
532
+
},
533
+
"node_modules/readdirp": {
534
+
"version": "4.1.2",
535
+
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
536
+
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
537
+
"license": "MIT",
538
+
"engines": {
539
+
"node": ">= 14.18.0"
540
+
},
541
+
"funding": {
542
+
"type": "individual",
543
+
"url": "https://paulmillr.com/funding/"
544
+
}
545
+
},
546
+
"node_modules/sass": {
547
+
"version": "1.86.0",
548
+
"resolved": "https://registry.npmjs.org/sass/-/sass-1.86.0.tgz",
549
+
"integrity": "sha512-zV8vGUld/+mP4KbMLJMX7TyGCuUp7hnkOScgCMsWuHtns8CWBoz+vmEhoGMXsaJrbUP8gj+F1dLvVe79sK8UdA==",
550
+
"license": "MIT",
551
+
"dependencies": {
552
+
"chokidar": "^4.0.0",
553
+
"immutable": "^5.0.2",
554
+
"source-map-js": ">=0.6.2 <2.0.0"
555
+
},
556
+
"bin": {
557
+
"sass": "sass.js"
558
+
},
559
+
"engines": {
560
+
"node": ">=14.0.0"
561
+
},
562
+
"optionalDependencies": {
563
+
"@parcel/watcher": "^2.4.1"
564
+
}
565
+
},
566
+
"node_modules/source-map": {
567
+
"version": "0.6.1",
568
+
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
569
+
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
570
+
"dev": true,
571
+
"license": "BSD-3-Clause",
572
+
"engines": {
573
+
"node": ">=0.10.0"
574
+
}
575
+
},
576
+
"node_modules/source-map-js": {
577
+
"version": "1.2.1",
578
+
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
579
+
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
580
+
"license": "BSD-3-Clause",
581
+
"engines": {
582
+
"node": ">=0.10.0"
583
+
}
584
+
},
585
+
"node_modules/to-regex-range": {
586
+
"version": "5.0.1",
587
+
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
588
+
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
589
+
"license": "MIT",
590
+
"optional": true,
591
+
"dependencies": {
592
+
"is-number": "^7.0.0"
593
+
},
594
+
"engines": {
595
+
"node": ">=8.0"
596
+
}
597
+
},
598
+
"node_modules/typescript": {
599
+
"version": "5.8.2",
600
+
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
601
+
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
602
+
"dev": true,
603
+
"license": "Apache-2.0",
604
+
"bin": {
605
+
"tsc": "bin/tsc",
606
+
"tsserver": "bin/tsserver"
607
+
},
608
+
"engines": {
609
+
"node": ">=14.17"
610
+
}
611
+
},
612
+
"node_modules/uglify-js": {
613
+
"version": "3.19.3",
614
+
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
615
+
"integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
616
+
"license": "BSD-2-Clause",
617
+
"bin": {
618
+
"uglifyjs": "bin/uglifyjs"
619
+
},
620
+
"engines": {
621
+
"node": ">=0.8.0"
622
+
}
623
+
},
624
+
"node_modules/undici-types": {
625
+
"version": "6.20.0",
626
+
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
627
+
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
628
+
"dev": true,
629
+
"license": "MIT"
630
+
}
631
+
}
632
+
}
+39
package.json
+39
package.json
···
1
+
{
2
+
"name": "build-shit",
3
+
"version": "0.0.1",
4
+
"description": "Tiny script for preparing web assets for deployment",
5
+
"homepage": "https://github.com/CorySanin/build-shit#readme",
6
+
"bugs": {
7
+
"url": "https://github.com/CorySanin/build-shit/issues"
8
+
},
9
+
"dependencies": {
10
+
"csso": "5.0.5",
11
+
"sass": "1.86.0",
12
+
"uglify-js": "3.19.3"
13
+
},
14
+
"devDependencies": {
15
+
"@sindresorhus/tsconfig": "7.0.0",
16
+
"@types/csso": "^5.0.4",
17
+
"@types/node": "^22.13.10",
18
+
"@types/uglify-js": "^3.17.5",
19
+
"typescript": "5.8.2"
20
+
},
21
+
"repository": {
22
+
"type": "git",
23
+
"url": "git+https://github.com/CorySanin/build-shit.git"
24
+
},
25
+
"license": "MIT",
26
+
"author": {
27
+
"name": "Cory Sanin",
28
+
"email": "corysanin@artixlinux.org",
29
+
"url": "https://sanin.dev"
30
+
},
31
+
"type": "module",
32
+
"main": "bin/build-shit.js",
33
+
"bin": {
34
+
"build-shit": "./bin/build-shit.js"
35
+
},
36
+
"scripts": {
37
+
"build": "tsc"
38
+
}
39
+
}
+173
src/build-shit.ts
+173
src/build-shit.ts
···
1
+
#!/usr/bin/env node
2
+
3
+
import fs from 'fs';
4
+
import path from 'path';
5
+
import child_process from 'child_process';
6
+
import uglifyjs from "uglify-js";
7
+
import * as sass from 'sass';
8
+
import * as csso from 'csso';
9
+
10
+
const spawn = child_process.spawn;
11
+
const fsp = fs.promises;
12
+
const STYLESDIR = 'styles';
13
+
const SCRIPTSDIR = 'scripts';
14
+
const IMAGESDIR = path.join('assets', 'images', 'original');
15
+
const STYLEOUTDIR = process.env.STYLEOUTDIR || path.join(import.meta.dirname, 'assets', 'css');
16
+
const SCRIPTSOUTDIR = process.env.SCRIPTSOUTDIR || path.join(import.meta.dirname, 'assets', 'js');
17
+
const IMAGESOUTDIR = process.env.IMAGESOUTDIR || path.join(import.meta.dirname, 'assets', 'images', 'webp');
18
+
const STYLEOUTFILE = process.env.STYLEOUTFILE || 'styles.css';
19
+
const SQUASH = new RegExp('^[0-9]+-');
20
+
21
+
async function emptyDir(dir: string) {
22
+
await Promise.all((await fsp.readdir(dir, { withFileTypes: true })).map(f => path.join(dir, f.name)).map(p => fsp.rm(p, {
23
+
recursive: true,
24
+
force: true
25
+
})));
26
+
}
27
+
28
+
async function mkdir(dir: string | string[]) {
29
+
if (typeof dir === 'string') {
30
+
await fsp.mkdir(dir, { recursive: true });
31
+
}
32
+
else {
33
+
await Promise.all(dir.map(mkdir));
34
+
}
35
+
}
36
+
37
+
// Process styles
38
+
async function styles() {
39
+
await mkdir([STYLEOUTDIR, STYLESDIR]);
40
+
await emptyDir(STYLEOUTDIR);
41
+
let styles: string[] = [];
42
+
let files = await fsp.readdir(STYLESDIR);
43
+
await Promise.all(files.map(f => new Promise(async (res, reject) => {
44
+
let p = path.join(STYLESDIR, f);
45
+
console.log(`Processing style ${p}`);
46
+
let style = sass.compile(p).css;
47
+
if (f.charAt(0) !== '_') {
48
+
if (SQUASH.test(f)) {
49
+
styles.push(style);
50
+
}
51
+
else {
52
+
let o = path.join(STYLEOUTDIR, f.substring(0, f.lastIndexOf('.')) + '.css');
53
+
await fsp.writeFile(o, csso.minify(style).css);
54
+
console.log(`Wrote ${o}`);
55
+
}
56
+
}
57
+
res(0);
58
+
})));
59
+
let out = csso.minify(styles.join('\n')).css;
60
+
let outpath = path.join(STYLEOUTDIR, STYLEOUTFILE);
61
+
await fsp.writeFile(outpath, out);
62
+
console.log(`Wrote ${outpath}`);
63
+
}
64
+
65
+
// Process scripts
66
+
async function scripts() {
67
+
await mkdir([SCRIPTSOUTDIR, SCRIPTSDIR]);
68
+
await emptyDir(SCRIPTSOUTDIR);
69
+
let files = await fsp.readdir(SCRIPTSDIR);
70
+
await Promise.all(files.map(f => new Promise(async (res, reject) => {
71
+
let p = path.join(SCRIPTSDIR, f);
72
+
let o = path.join(SCRIPTSOUTDIR, f);
73
+
console.log(`Processing script ${p}`);
74
+
try {
75
+
await fsp.writeFile(o, uglifyjs.minify((await fsp.readFile(p)).toString()).code);
76
+
console.log(`Wrote ${o}`);
77
+
}
78
+
catch (ex) {
79
+
console.log(`error writing ${o}: ${ex}`);
80
+
}
81
+
res(0);
82
+
})));
83
+
}
84
+
85
+
// Process images
86
+
async function images(dir = '') {
87
+
let p = path.join(IMAGESDIR, dir);
88
+
await mkdir(p);
89
+
if (dir.length === 0) {
90
+
await mkdir(IMAGESOUTDIR)
91
+
await emptyDir(IMAGESOUTDIR);
92
+
}
93
+
let files = await fsp.readdir(p, {
94
+
withFileTypes: true
95
+
});
96
+
if (files.length) {
97
+
await Promise.all(files.map(f => new Promise(async (res, reject) => {
98
+
if (f.isFile()) {
99
+
let outDir = path.join(IMAGESOUTDIR, dir);
100
+
let infile = path.join(p, f.name);
101
+
let outfile = path.join(outDir, f.name.substring(0, f.name.lastIndexOf('.')) + '.webp');
102
+
await mkdir(outDir);
103
+
console.log(`Processing image ${infile}`)
104
+
let process = spawn('cwebp', ['-mt', '-q', '50', infile, '-o', outfile]);
105
+
let timeout = setTimeout(() => {
106
+
reject('Timed out');
107
+
process.kill();
108
+
}, 30000);
109
+
process.on('exit', async (code) => {
110
+
clearTimeout(timeout);
111
+
if (code === 0) {
112
+
console.log(`Wrote ${outfile}`);
113
+
res(null);
114
+
}
115
+
else {
116
+
reject(code);
117
+
}
118
+
});
119
+
}
120
+
else if (f.isDirectory()) {
121
+
images(path.join(dir, f.name)).then(res).catch(reject);
122
+
}
123
+
})));
124
+
}
125
+
}
126
+
127
+
function isAbortError(err: unknown): boolean {
128
+
return typeof err === 'object' && err !== null && 'name' in err && err.name === 'AbortError';
129
+
}
130
+
131
+
(async function () {
132
+
await Promise.all([styles(), scripts(), images()]);
133
+
if (process.argv.indexOf('--watch') >= 0) {
134
+
console.log('watching for changes...');
135
+
(async () => {
136
+
try {
137
+
const watcher = fsp.watch(STYLESDIR);
138
+
for await (const _ of watcher)
139
+
await styles();
140
+
} catch (err) {
141
+
if (isAbortError(err))
142
+
return;
143
+
throw err;
144
+
}
145
+
})();
146
+
147
+
(async () => {
148
+
try {
149
+
const watcher = fsp.watch(SCRIPTSDIR);
150
+
for await (const _ of watcher)
151
+
await scripts();
152
+
} catch (err) {
153
+
if (isAbortError(err))
154
+
return;
155
+
throw err;
156
+
}
157
+
})();
158
+
159
+
(async () => {
160
+
try {
161
+
const watcher = fsp.watch(IMAGESDIR, {
162
+
recursive: true // no Linux ☹️
163
+
});
164
+
for await (const _ of watcher)
165
+
await images();
166
+
} catch (err) {
167
+
if (isAbortError(err))
168
+
return;
169
+
throw err;
170
+
}
171
+
})();
172
+
}
173
+
})();
+19
tsconfig.json
+19
tsconfig.json
···
1
+
{
2
+
"compilerOptions": {
3
+
"lib": [
4
+
"ESNext"
5
+
],
6
+
"module": "NodeNext",
7
+
"target": "ESNext",
8
+
"esModuleInterop": true,
9
+
"skipLibCheck": true,
10
+
"moduleResolution": "node16",
11
+
"outDir": "./bin"
12
+
},
13
+
"include": [
14
+
"src/**/*"
15
+
],
16
+
"exclude": [
17
+
"**/*.spec.ts"
18
+
]
19
+
}