poops 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.yml +10 -0
- package/.github/dependabot.yml +9 -0
- package/.github/workflows/npm_publish.yml +17 -0
- package/LICENSE +21 -0
- package/README.md +301 -0
- package/dist/css/styles.css +17659 -0
- package/dist/css/styles.css.map +1 -0
- package/dist/css/styles.min.css +4 -0
- package/dist/js/scripts.js +35 -0
- package/dist/js/scripts.js.map +7 -0
- package/dist/js/scripts.min.js +2 -0
- package/index.html +86 -0
- package/package.json +44 -0
- package/poops.js +452 -0
- package/poops.json +35 -0
- package/src/js/main.ts +29 -0
- package/src/js/scripts/utils.ts +16 -0
- package/src/scss/index.scss +2 -0
- package/src/scss/style/index.scss +27 -0
- package/tsconfig.json +16 -0
package/poops.js
ADDED
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const autoprefixer = require('autoprefixer')
|
|
4
|
+
const { build } = require('esbuild')
|
|
5
|
+
const chokidar = require('chokidar')
|
|
6
|
+
const connect = require('connect')
|
|
7
|
+
const cssnano = require('cssnano')
|
|
8
|
+
const deepmerge = require('deepmerge')
|
|
9
|
+
const fs = require('node:fs')
|
|
10
|
+
const http = require('node:http')
|
|
11
|
+
const livereload = require('livereload')
|
|
12
|
+
const path = require('node:path')
|
|
13
|
+
const { pathToFileURL } = require('node:url')
|
|
14
|
+
const postcss = require('postcss')
|
|
15
|
+
const sass = require('sass')
|
|
16
|
+
const serveStatic = require('serve-static')
|
|
17
|
+
const Terser = require('terser')
|
|
18
|
+
|
|
19
|
+
const cwd = process.cwd() // Current Working Directory
|
|
20
|
+
const pkg = require('./package.json')
|
|
21
|
+
const args = process.argv.slice(2)
|
|
22
|
+
|
|
23
|
+
let defaultConfigPath = 'poop.json'
|
|
24
|
+
|
|
25
|
+
if (args.length) {
|
|
26
|
+
defaultConfigPath = args[0]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Helpers
|
|
30
|
+
|
|
31
|
+
class Style {
|
|
32
|
+
reset = '\x1b[0m'
|
|
33
|
+
bold = '\x1b[1m'
|
|
34
|
+
dim = '\x1b[2m'
|
|
35
|
+
italic = '\x1b[3m'
|
|
36
|
+
underline = '\x1b[4m'
|
|
37
|
+
blink = '\x1b[5m'
|
|
38
|
+
inverse = '\x1b[7m'
|
|
39
|
+
hidden = '\x1b[8m'
|
|
40
|
+
strikethrough = '\x1b[9m'
|
|
41
|
+
black = '\x1b[30m'
|
|
42
|
+
red = '\x1b[31m'
|
|
43
|
+
redBright = '\x1b[91m'
|
|
44
|
+
green = '\x1b[32m'
|
|
45
|
+
greenBright = '\x1b[92m'
|
|
46
|
+
yellow = '\x1b[33m'
|
|
47
|
+
yellowBright = '\x1b[93m'
|
|
48
|
+
blue = '\x1b[34m'
|
|
49
|
+
blueBright = '\x1b[94m'
|
|
50
|
+
magenta = '\x1b[35m'
|
|
51
|
+
magentaBright = '\x1b[95m'
|
|
52
|
+
cyan = '\x1b[36m'
|
|
53
|
+
cyanBright = '\x1b[96m'
|
|
54
|
+
white = '\x1b[37m'
|
|
55
|
+
whiteBright = '\x1b[97m'
|
|
56
|
+
gray = '\x1b[90m'
|
|
57
|
+
bgBlack = '\x1b[40m'
|
|
58
|
+
bgRed = '\x1b[41m'
|
|
59
|
+
bgRedBright = '\x1b[101m'
|
|
60
|
+
bgGreen = '\x1b[42m'
|
|
61
|
+
bgGreenBright = '\x1b[102m'
|
|
62
|
+
bgYellow = '\x1b[43m'
|
|
63
|
+
bgYellowBright = '\x1b[103m'
|
|
64
|
+
bgBlue = '\x1b[44m'
|
|
65
|
+
bgBlueBright = '\x1b[104m'
|
|
66
|
+
bgMagenta = '\x1b[45m'
|
|
67
|
+
bgMagentaBright = '\x1b[105m'
|
|
68
|
+
bgCyan = '\x1b[46m'
|
|
69
|
+
bgCyanBright = '\x1b[106m'
|
|
70
|
+
bgWhite = '\x1b[47m'
|
|
71
|
+
bgWhiteBright = '\x1b[107m'
|
|
72
|
+
bgGray = '\x1b[100m'
|
|
73
|
+
bell = '\x07'
|
|
74
|
+
|
|
75
|
+
hexToRgb(hex) {
|
|
76
|
+
const sanitizedHex = hex.replace('#', '')
|
|
77
|
+
const red = parseInt(sanitizedHex.substring(0, 2), 16)
|
|
78
|
+
const green = parseInt(sanitizedHex.substring(2, 4), 16)
|
|
79
|
+
const blue = parseInt(sanitizedHex.substring(4, 6), 16)
|
|
80
|
+
|
|
81
|
+
return [red, green, blue]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
terminalColorIndex(red, green, blue) {
|
|
85
|
+
return 16 +
|
|
86
|
+
Math.round(red / 255 * 5) * 36 +
|
|
87
|
+
Math.round(green / 255 * 5) * 6 +
|
|
88
|
+
Math.round(blue / 255 * 5)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
color(hex) {
|
|
92
|
+
const [red, green, blue] = this.hexToRgb(hex)
|
|
93
|
+
|
|
94
|
+
return `\x1b[38;5;${this.terminalColorIndex(red, green, blue)}m`
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
background(hex) {
|
|
98
|
+
const [red, green, blue] = this.hexToRgb(hex)
|
|
99
|
+
|
|
100
|
+
return `\x1b[48;5;${this.terminalColorIndex(red, green, blue)}m`
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function pathExists() {
|
|
105
|
+
return fs.existsSync(path.join(...arguments))
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function pathIsDirectory() {
|
|
109
|
+
return fs.lstatSync(path.join(...arguments)).isDirectory()
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function mkPath(filePath) {
|
|
113
|
+
const dirPath = path.dirname(filePath)
|
|
114
|
+
if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true })
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function pathForFile(filePath) {
|
|
118
|
+
return /\./.test(path.basename(filePath))
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function insertMinSuffix(filePath) {
|
|
122
|
+
const { name, ext } = path.parse(filePath)
|
|
123
|
+
return path.join(path.dirname(filePath), `${name}.min${ext}`)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function buildStyleOutputFilePath(inputPath, outputPath) {
|
|
127
|
+
if (pathForFile(outputPath)) return outputPath
|
|
128
|
+
const { name } = path.parse(inputPath)
|
|
129
|
+
return path.join(path.join(outputPath, `${name}.css`))
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function buildScriptOutputFilePath(inputPath, outputPath) {
|
|
133
|
+
if (pathForFile(outputPath)) return outputPath
|
|
134
|
+
const { name, ext } = path.parse(inputPath)
|
|
135
|
+
return path.join(path.join(outputPath, `${name}${ext.replace('t', 'j')}`))
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function fillBannerTemplate(template, packagesPath) {
|
|
139
|
+
packagesPath = packagesPath || cwd
|
|
140
|
+
const packagesFilePath = path.join(packagesPath, 'package.json')
|
|
141
|
+
if (!pathExists(packagesFilePath)) return template
|
|
142
|
+
const pkg = require(packagesFilePath)
|
|
143
|
+
const { name, version, homepage, description, license, author } = pkg
|
|
144
|
+
const year = new Date().getFullYear()
|
|
145
|
+
|
|
146
|
+
return template
|
|
147
|
+
.replace(/{{\s?name\s?}}/g, name)
|
|
148
|
+
.replace(/{{\s?version\s?}}/g, version)
|
|
149
|
+
.replace(/{{\s?homepage\s?}}/g, homepage)
|
|
150
|
+
.replace(/{{\s?description\s?}}/g, description)
|
|
151
|
+
.replace(/{{\s?author\s?}}/g, author)
|
|
152
|
+
.replace(/{{\s?license\s?}}/g, license)
|
|
153
|
+
.replace(/{{\s?year\s?}}/g, year)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function buildTime(start, end) {
|
|
157
|
+
const time = Math.round(end - start)
|
|
158
|
+
if (time < 1000) return `${time}ms`
|
|
159
|
+
if (time < 60 * 1000) return `${(time / 1000).toFixed(0)}s ${time % 1000}ms`
|
|
160
|
+
return `${(time / 1000 / 60).toFixed(0)}m ${((time / 1000) % 60).toFixed(0)}s ${time % 1000}ms`
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const style = new Style()
|
|
164
|
+
|
|
165
|
+
// CLI Header
|
|
166
|
+
console.log(`\n${style.color('#8b4513')}💩 Poop — v${pkg.version}
|
|
167
|
+
----------------${style.reset + style.bell}\n`)
|
|
168
|
+
|
|
169
|
+
const configPath = path.join(cwd, defaultConfigPath)
|
|
170
|
+
|
|
171
|
+
// Check if poop.json exists
|
|
172
|
+
if (!pathExists(configPath)) {
|
|
173
|
+
console.log(`${style.redBright + style.bold}[error]${style.reset} \`${style.underline}${defaultConfigPath}${style.reset}\` not found.
|
|
174
|
+
${style.dim}Configuration file \`${style.underline}${defaultConfigPath}${style.reset}${style.dim}\` not found in your working directory: ${style.underline}${cwd}${style.reset}\n
|
|
175
|
+
${style.dim}Please specify another file path or create a \`poop.js\` file in your working directory and try again.\n
|
|
176
|
+
${style.dim}For information on the structure of the configuration file, please visit: \n${style.underline}https://stamat.github.io/poop${style.reset}\n`)
|
|
177
|
+
process.exit(1)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Load poop.json
|
|
181
|
+
const config = require(configPath)
|
|
182
|
+
const banner = config.banner ? fillBannerTemplate(config.banner) : null
|
|
183
|
+
|
|
184
|
+
if (config.watch) {
|
|
185
|
+
config.watch = Array.isArray(config.watch) ? config.watch : [config.watch]
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (config.includePaths) {
|
|
189
|
+
config.includePaths = Array.isArray(config.includePaths) ? config.includePaths : [config.includePaths]
|
|
190
|
+
} else {
|
|
191
|
+
config.includePaths = ['node_modules']
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Start the webserver
|
|
195
|
+
if (config.serve) {
|
|
196
|
+
const app = connect()
|
|
197
|
+
|
|
198
|
+
if (config.serve.base && pathExists(cwd, config.serve.base)) {
|
|
199
|
+
app.use(serveStatic(path.join(cwd, config.serve.base)))
|
|
200
|
+
} else {
|
|
201
|
+
app.use(serveStatic(cwd))
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const port = config.serve.port ? parseInt(config.serve.port, 10) : 4040
|
|
205
|
+
http.createServer(app).listen(port, () => {
|
|
206
|
+
console.log(`${style.cyanBright + style.bold}[info]${style.reset} ${style.dim}🌍 Local server:${style.reset} ${style.italic + style.underline}http://localhost:${port}${style.reset}`)
|
|
207
|
+
poop()
|
|
208
|
+
})
|
|
209
|
+
} else {
|
|
210
|
+
poop()
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// SCSS/SASS Compiler
|
|
214
|
+
function tryToFindFile(filePath, extensions) {
|
|
215
|
+
const fileExt = extensions.find(ext => fs.existsSync(`${filePath}.${ext}`))
|
|
216
|
+
if (fileExt) {
|
|
217
|
+
return `${filePath}.${fileExt}`
|
|
218
|
+
}
|
|
219
|
+
return null
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function sassPathResolver(url, resolvePath) {
|
|
223
|
+
if (fs.existsSync(url)) return new URL(url)
|
|
224
|
+
const resolvedPath = pathToFileURL(resolvePath)
|
|
225
|
+
if (!fs.existsSync(resolvedPath.pathname)) return null
|
|
226
|
+
const importPath = path.relative(cwd, path.join(resolvedPath.pathname, url))
|
|
227
|
+
|
|
228
|
+
if (!fs.existsSync(importPath)) {
|
|
229
|
+
const correctFile = tryToFindFile(importPath, ['sass', 'scss', 'css'])
|
|
230
|
+
if (correctFile) return new URL(correctFile, resolvedPath)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (pathIsDirectory(importPath) && !pathExists(importPath, 'index.sass') && !pathExists(importPath, 'index.scss')) {
|
|
234
|
+
const correctFile = tryToFindFile(importPath, ['sass', 'scss', 'css'])
|
|
235
|
+
if (correctFile) return new URL(correctFile, resolvedPath)
|
|
236
|
+
|
|
237
|
+
if (!pathExists(importPath, 'package.json')) return null
|
|
238
|
+
|
|
239
|
+
const pkg = require(path.join(importPath, 'package.json'))
|
|
240
|
+
|
|
241
|
+
if (pkg.sass) return new URL(path.join(importPath, pkg.sass), resolvedPath)
|
|
242
|
+
if (pkg.css) return new URL(path.join(importPath, pkg.css), resolvedPath)
|
|
243
|
+
|
|
244
|
+
const basename = path.basename(pkg.main)
|
|
245
|
+
if (pkg.main && /(\.sass|\.scss|\.css)$/i.test(basename)) return new URL(path.join(importPath, pkg.main), resolvedPath)
|
|
246
|
+
return null
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return new URL(importPath, resolvedPath)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function compileStyles() {
|
|
253
|
+
if (!config.styles) return
|
|
254
|
+
config.styles = Array.isArray(config.styles) ? config.styles : [config.styles]
|
|
255
|
+
for (const styleEntry of config.styles) {
|
|
256
|
+
if (styleEntry.in && styleEntry.out && pathExists(styleEntry.in)) {
|
|
257
|
+
mkPath(styleEntry.out)
|
|
258
|
+
compileStylesEntry(styleEntry.in, styleEntry.out, styleEntry.options)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function compileStylesEntry(infilePath, outfilePath, options = {}) {
|
|
264
|
+
const opts = {
|
|
265
|
+
sourceMap: false,
|
|
266
|
+
sourceMapIncludeSources: false,
|
|
267
|
+
importers: [{
|
|
268
|
+
// Resolve `includePaths`.
|
|
269
|
+
findFileUrl(url) {
|
|
270
|
+
for (const includePath of config.includePaths) {
|
|
271
|
+
const resolvedPath = sassPathResolver(url, includePath)
|
|
272
|
+
if (resolvedPath) return resolvedPath
|
|
273
|
+
}
|
|
274
|
+
return null
|
|
275
|
+
}
|
|
276
|
+
}]
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (options.sourcemap) {
|
|
280
|
+
opts.sourceMap = options.sourcemap
|
|
281
|
+
opts.sourceMapIncludeSources = options.sourcemap
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
outfilePath = buildStyleOutputFilePath(infilePath, outfilePath, options)
|
|
285
|
+
|
|
286
|
+
const cssStart = performance.now()
|
|
287
|
+
const compiledSass = sass.compile(infilePath, opts)
|
|
288
|
+
const mapsrc = options.sourcemap ? `\n/*# sourceMappingURL=${path.basename(outfilePath)}.map */` : ''
|
|
289
|
+
if (banner) compiledSass.css = banner + '\n' + compiledSass.css
|
|
290
|
+
fs.writeFileSync(outfilePath, compiledSass.css + mapsrc)
|
|
291
|
+
const cssEnd = performance.now()
|
|
292
|
+
if (!options.justMinified) console.log(`${style.magentaBright + style.bold}[style]${style.reset} ${style.dim}Compiled:${style.reset} ${style.italic + style.underline}${outfilePath}${style.reset} ${style.greenBright}(${buildTime(cssStart, cssEnd)})${style.reset}`)
|
|
293
|
+
|
|
294
|
+
if (compiledSass.sourceMap) {
|
|
295
|
+
if (banner) compiledSass.sourceMap.mappings = ';' + compiledSass.sourceMap.mappings
|
|
296
|
+
fs.writeFileSync(`${outfilePath}.map`, JSON.stringify(compiledSass.sourceMap))
|
|
297
|
+
console.log(`${style.magentaBright + style.bold}[style]${style.reset} ${style.dim}Compiled:${style.reset} ${style.italic + style.underline}${outfilePath}.map${style.reset}`)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const cssMinStart = performance.now()
|
|
301
|
+
const minPath = insertMinSuffix(outfilePath)
|
|
302
|
+
if (options.minify) {
|
|
303
|
+
postcss([autoprefixer, cssnano]).process(compiledSass.css, {
|
|
304
|
+
from: outfilePath,
|
|
305
|
+
to: minPath
|
|
306
|
+
}).then(result => {
|
|
307
|
+
if (banner) result.css = banner + '\n' + result.css
|
|
308
|
+
fs.writeFileSync(minPath, result.css)
|
|
309
|
+
const cssMinEnd = performance.now()
|
|
310
|
+
console.log(`${style.magentaBright + style.bold}[style]${style.reset} ${style.dim}Compiled:${style.reset} ${style.italic + style.underline}${minPath}${style.reset} ${style.greenBright}(${buildTime(cssMinStart, cssMinEnd)})${style.reset}`)
|
|
311
|
+
}).catch((error) => {
|
|
312
|
+
console.log(`${style.redBright + style.bold}[error]${style.reset} Error occurred during CSS minification: ${style.dim}${error}${style.reset}`)
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
if (options.justMinified) {
|
|
316
|
+
fs.unlinkSync(outfilePath)
|
|
317
|
+
}
|
|
318
|
+
} else {
|
|
319
|
+
fs.unlinkSync(minPath)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// JS/TS Compiler
|
|
324
|
+
function compileScripts() {
|
|
325
|
+
if (!config.scripts) return
|
|
326
|
+
config.scripts = Array.isArray(config.scripts) ? config.scripts : [config.scripts]
|
|
327
|
+
for (const scriptEntry of config.scripts) {
|
|
328
|
+
if (scriptEntry.in && scriptEntry.out && pathExists(scriptEntry.in)) {
|
|
329
|
+
mkPath(scriptEntry.out)
|
|
330
|
+
compileScriptsEntry(scriptEntry.in, scriptEntry.out, scriptEntry.options)
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function compileScriptsEntry(infilePath, outfilePath, options = {}) {
|
|
336
|
+
if (!Array.isArray(infilePath)) infilePath = [infilePath]
|
|
337
|
+
|
|
338
|
+
const opts = {
|
|
339
|
+
logLevel: 'error',
|
|
340
|
+
entryPoints: infilePath,
|
|
341
|
+
bundle: true,
|
|
342
|
+
sourcemap: false,
|
|
343
|
+
minify: false,
|
|
344
|
+
format: 'iife',
|
|
345
|
+
target: 'es2019',
|
|
346
|
+
nodePaths: config.includePaths // Resolve `includePaths`
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const terserOpts = {
|
|
350
|
+
mangle: false
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (banner) {
|
|
354
|
+
opts.banner = {
|
|
355
|
+
js: banner,
|
|
356
|
+
css: banner
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (!pathForFile(outfilePath)) {
|
|
361
|
+
opts.outdir = outfilePath
|
|
362
|
+
} else {
|
|
363
|
+
if (infilePath.length > 1) {
|
|
364
|
+
console.log(`${style.redBright + style.bold}[error]${style.reset} Cannot output multiple ${style.bold + style.underline}script${style.reset} files to a single file. Please specify an output directory path instead.`)
|
|
365
|
+
process.exit(1)
|
|
366
|
+
}
|
|
367
|
+
opts.outfile = outfilePath
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (options.format) opts.format = options.format
|
|
371
|
+
if (options.target) opts.target = options.target
|
|
372
|
+
if (options.nodePaths) opts.nodePaths = [...new Set([...opts.nodePaths, ...options.nodePaths])]
|
|
373
|
+
if (options.sourcemap) opts.sourcemap = options.sourcemap
|
|
374
|
+
|
|
375
|
+
if (options.mangle) terserOpts.mangle = options.mangle
|
|
376
|
+
|
|
377
|
+
delete options.mangle
|
|
378
|
+
deepmerge(opts, options) // ability to pass other esbuild options `node_modules/esbuild/lib/main.d.ts`
|
|
379
|
+
|
|
380
|
+
// TODO: Actually loop the build process for each entry point!!!
|
|
381
|
+
const esbuildStart = performance.now()
|
|
382
|
+
build(opts).then(() => {
|
|
383
|
+
const esbuildEnd = performance.now()
|
|
384
|
+
for (const entry of infilePath) {
|
|
385
|
+
const newOutFilePath = buildScriptOutputFilePath(entry, outfilePath)
|
|
386
|
+
const minPath = insertMinSuffix(newOutFilePath)
|
|
387
|
+
|
|
388
|
+
if (!options.justMinified) console.log(`${style.yellowBright + style.bold}[script]${style.reset} ${style.dim}Compiled:${style.reset} ${style.italic + style.underline}${newOutFilePath}${style.reset} ${style.greenBright}(${buildTime(esbuildStart, esbuildEnd)})${style.reset}`)
|
|
389
|
+
if (options.sourcemap) console.log(`${style.yellowBright + style.bold}[script]${style.reset} ${style.dim}Compiled:${style.reset} ${style.italic + style.underline}${newOutFilePath}.map${style.reset}`)
|
|
390
|
+
|
|
391
|
+
if (options.minify) {
|
|
392
|
+
const terserStart = performance.now()
|
|
393
|
+
Terser.minify(fs.readFileSync(newOutFilePath, 'utf-8'), { mangle: terserOpts.mangle }).then((result) => {
|
|
394
|
+
if (result.error) {
|
|
395
|
+
console.log(`${style.redBright + style.bold}[error]${style.reset} Error occurred during JS minification: ${style.dim}${result.error}${style.reset}`)
|
|
396
|
+
} else {
|
|
397
|
+
if (banner) result.code = banner + '\n' + result.code
|
|
398
|
+
fs.writeFileSync(minPath, result.code)
|
|
399
|
+
const terserEnd = performance.now()
|
|
400
|
+
console.log(`${style.yellowBright + style.bold}[script]${style.reset} ${style.dim}Compiled:${style.reset} ${style.italic + style.underline}${minPath}${style.reset} ${style.greenBright}(${buildTime(terserStart, terserEnd)})${style.reset}`)
|
|
401
|
+
}
|
|
402
|
+
})
|
|
403
|
+
|
|
404
|
+
if (options.justMinified) {
|
|
405
|
+
fs.unlinkSync(newOutFilePath)
|
|
406
|
+
}
|
|
407
|
+
} else {
|
|
408
|
+
fs.unlinkSync(minPath)
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
})
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Main function 💩
|
|
415
|
+
function poop() {
|
|
416
|
+
if (config.livereload) {
|
|
417
|
+
const lrExcludes = ['.git', '.svn', '.hg']
|
|
418
|
+
|
|
419
|
+
if (config.watch) {
|
|
420
|
+
lrExcludes.push(...config.watch)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (config.includePaths) {
|
|
424
|
+
lrExcludes.push(...config.includePaths)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (config.livereload.exclude) {
|
|
428
|
+
lrExcludes.push(...config.livereload.exclude)
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const lrserver = livereload.createServer({
|
|
432
|
+
exclusions: [...new Set(lrExcludes)],
|
|
433
|
+
port: config.livereload.port || 35729
|
|
434
|
+
})
|
|
435
|
+
console.log(`${style.cyanBright + style.bold}[info]${style.reset} ${style.dim}🔃 LiveReload server:${style.reset} ${style.italic + style.underline}http://localhost:${lrserver.config.port}${style.reset}`)
|
|
436
|
+
lrserver.watch(cwd)
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
compileStyles()
|
|
440
|
+
compileScripts()
|
|
441
|
+
|
|
442
|
+
if (config.watch) {
|
|
443
|
+
chokidar.watch(config.watch).on('change', (file) => {
|
|
444
|
+
if (/(\.js|\.ts)$/i.test(file)) compileScripts()
|
|
445
|
+
if (/(\.sass|\.scss|\.css)$/i.test(file)) compileStyles()
|
|
446
|
+
})
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (!config.watch && !config.livereload && !config.serve) {
|
|
450
|
+
process.exit(1)
|
|
451
|
+
}
|
|
452
|
+
}
|
package/poops.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scripts": [{
|
|
3
|
+
"in": "src/js/main.ts",
|
|
4
|
+
"out": "dist/js/scripts.js",
|
|
5
|
+
"options": {
|
|
6
|
+
"sourcemap": true,
|
|
7
|
+
"minify": true,
|
|
8
|
+
"justMinified": false,
|
|
9
|
+
"format": "iife",
|
|
10
|
+
"target": "es2019",
|
|
11
|
+
"mangle": true
|
|
12
|
+
}
|
|
13
|
+
}],
|
|
14
|
+
"styles": [{
|
|
15
|
+
"in": "src/scss/index.scss",
|
|
16
|
+
"out": "dist/css/styles.css",
|
|
17
|
+
"options": {
|
|
18
|
+
"sourcemap": true,
|
|
19
|
+
"minify": true,
|
|
20
|
+
"justMinified": false
|
|
21
|
+
}
|
|
22
|
+
}],
|
|
23
|
+
"banner": "/* {{ name }} v{{ version }} | {{ homepage }} | {{ license }} License */",
|
|
24
|
+
"serve" : {
|
|
25
|
+
"port": 4040,
|
|
26
|
+
"base": "/"
|
|
27
|
+
},
|
|
28
|
+
"livereload": true,
|
|
29
|
+
"watch": [
|
|
30
|
+
"src"
|
|
31
|
+
],
|
|
32
|
+
"includePaths": [
|
|
33
|
+
"node_modules"
|
|
34
|
+
]
|
|
35
|
+
}
|
package/src/js/main.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { capitalize, calculateSum, formatDate } from './scripts/utils'
|
|
2
|
+
|
|
3
|
+
// Sample TypeScript code rendered by ChatGPT-3
|
|
4
|
+
|
|
5
|
+
class Person {
|
|
6
|
+
private name: string;
|
|
7
|
+
private age: number;
|
|
8
|
+
|
|
9
|
+
constructor(name: string, age: number) {
|
|
10
|
+
this.name = name;
|
|
11
|
+
this.age = age;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
greet(): void {
|
|
15
|
+
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Creating an instance of the Person class
|
|
20
|
+
const person = new Person("Stamat", new Date().getFullYear() - 1988);
|
|
21
|
+
|
|
22
|
+
// Accessing properties and calling methods
|
|
23
|
+
person.greet();
|
|
24
|
+
|
|
25
|
+
console.log(capitalize('hello')); // Output: Hello
|
|
26
|
+
console.log(calculateSum([1, 2, 3, 4, 5])); // Output: 15
|
|
27
|
+
|
|
28
|
+
const today = new Date();
|
|
29
|
+
console.log(formatDate(today)); // Output: YYYY-MM-DD
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Sample TypeScript code rendered by ChatGPT-3
|
|
2
|
+
|
|
3
|
+
export function capitalize(str: string): string {
|
|
4
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function calculateSum(numbers: number[]): number {
|
|
8
|
+
return numbers.reduce((acc, num) => acc + num, 0);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function formatDate(date: Date): string {
|
|
12
|
+
const year = date.getFullYear();
|
|
13
|
+
const month = `${date.getMonth() + 1}`.padStart(2, '0');
|
|
14
|
+
const day = `${date.getDate()}`.padStart(2, '0');
|
|
15
|
+
return `${year}-${month}-${day}`;
|
|
16
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
body {
|
|
2
|
+
background-color: #DCC8AC;
|
|
3
|
+
margin: 0;
|
|
4
|
+
padding: 0;
|
|
5
|
+
font-family: 'DM Sans', Helvetica, Arial, sans-serif !important;
|
|
6
|
+
font-size: 24px !important;
|
|
7
|
+
line-height: 1.5;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
header {
|
|
11
|
+
text-align: center;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
header h1 {
|
|
15
|
+
font-family: 'Poppins', Helvetica, Arial, sans-serif !important;
|
|
16
|
+
font-weight: 700 !important;
|
|
17
|
+
font-size: 94px;
|
|
18
|
+
line-height: 1;
|
|
19
|
+
margin: 0;
|
|
20
|
+
color: #824F2D;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#poop {
|
|
24
|
+
font-size: 10rem;
|
|
25
|
+
display: inline-block;
|
|
26
|
+
margin-bottom: 24px;
|
|
27
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"experimentalDecorators": true,
|
|
4
|
+
"target": "es2019",
|
|
5
|
+
"module": "es2020",
|
|
6
|
+
"lib": ["es2019", "dom", "dom.iterable"],
|
|
7
|
+
"moduleResolution": "node",
|
|
8
|
+
"allowSyntheticDefaultImports": true,
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
"checkJs": false,
|
|
11
|
+
"noEmit": true,
|
|
12
|
+
"strict": true,
|
|
13
|
+
"strictPropertyInitialization": false,
|
|
14
|
+
"resolveJsonModule": true
|
|
15
|
+
}
|
|
16
|
+
}
|