const fs = require('fs') const path = require('path') const cp = require('child_process') const process = require('process') //const exec = cp.execSync const exec = (cmd) => { console.log(`Exec: ${cmd}`) return cp.execSync(cmd) } const CleanCSS = require('clean-css') const html = require('html-minifier') const red = '\033[1;31m' const green = '\033[1;32m' const yellow = '\033[1;33m' const blue = '\033[1;34m' const bold = '\033[1m' const reset = '\033[0m' const minjs = 'script.min.js' const mincss = 'style.min.css' main() function main() { switch (process.argv[2]) { case 'build': const dir = process.argv[3] if (dir) buildOne(dir) else buildAll() break case 'archive': archive() break case 'clean': clean() break default: print('Available actions:', true) printList([ 'build', 'build ', 'archive', 'clean', ]) break } } function buildAll() { const dirs = fs.readdirSync('.', { withFileTypes: true }) .filter(file => file.isDirectory()) .map(file => file.name) const pages = [ '.', ...dirs, ] for (let page of pages) buildOne(page) print('Completed', true, 'V', green) } function buildOne(dir) { print(`${bold}Building:${reset} ${dir}`) const config = `${dir}/webpage.json` let files if (fs.existsSync(config)) { files = JSON.parse(fs.readFileSync(config)) } else { print( 'Unable to find webpage.json, skipping', false, '!', yellow, ) return } fs.mkdirSync(`dist/${dir}`, { recursive: true }) print('Minifying JS') minifyJs(dir, files) print('Rendering LESS') renderLess(dir, files) print('Minifying CSS') minifyCss(dir, files) print('Converting paths in HTML') convertPathsHtml(dir, files) print('Minifying HTML') minifyHtml(dir, files) print('Copying other files') copyOther(dir, files) } function minifyJs(dir, files) { files.js = files.js || [] if (files.js.length == 0) return; exec( 'node_modules/.bin/terser --compress --mangle ' + `-o "dist/${dir}/${minjs}" ` + files.js.map(js => `"${dir}/${js}"`).join(' ') ) } function renderLess(dir, files) { files.less = files.less || [] if (files.less.length == 0) return; rendered = path.resolve(`dist/${dir}/${mincss}`) exec( 'node_modules/.bin/lessc ' + files.less.map(less => `"${dir}/${less}"`).join(' ') + ` "${rendered}"` ) files.css = [ ...(files.css || []), rendered, ] } function minifyCss(dir, files) { files.css = files.css || [] if (files.css.length == 0) return; const content = new CleanCSS().minify(files.css).styles fs.writeFileSync(`dist/${dir}/${mincss}`, content) } function convertPathsHtml(dir, files) { const scriptRegex = /(?:', '' ) .replace( '', `` ) .replace( scriptRegex, `` ) const built = path.resolve(`dist/${dir}/${file}`) fs.writeFileSync(built, content) converted.push(built) } files.html = converted } function minifyHtml(dir, files) { files.html = files.html || [] for (let file of files.html) { const isAbs = path.isAbsolute(file) const name = (isAbs ? file : `${dir}/${file}`) const built = (isAbs ? file : `dist/${dir}/${file}`) const content = html.minify( fs.readFileSync(name).toString(), { collapseBooleanAttributes: true, collapseInlineTagWhitespace: true, collapseWhitespace: true, removeAttributeQuotes: true, removeComments: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, useShortDoctype: true, keepClosingSlash: false, minifyCSS: true, minifyJS: true, } ) fs.writeFileSync(built, content) } } function copyOther(dir, files) { files.other = files.other || [] for (let file of files.other) { const isAbs = path.isAbsolute(file) const name = (isAbs ? file : `${dir}/${file}`) const built = (isAbs ? file : `dist/${dir}/${file}`) fs.cpSync(name, built, { recursive: true, errorOnExist: false, }) } } function archive() { exec('7z a dist.zip dist/*') } function clean() { fs.rmSync('dist/', { recursive: true, force: true, }) fs.rmSync('dist.zip', { force: true, }) } function print( str, title = false, symbol = '*', color = blue, ) { console.log( `${color}[${symbol}]${reset} ` + `${title ? bold : ""}${str}${reset}` ) } function printList(arr) { for (let item of arr) console.log(` ${item}`) }