flash.moe/build.js

156 lines
4.5 KiB
JavaScript
Raw Normal View History

const fs = require('fs');
const swc = require('@swc/core');
const path = require('path');
const util = require('util');
2023-10-14 23:05:49 +00:00
const exec = util.promisify(require('child_process').exec);
const postcss = require('postcss');
2023-10-14 23:05:49 +00:00
const htmlminify = require('html-minifier-terser').minify;
const utils = require('./assets/utils.js');
const assproc = require('./assets/assproc.js');
const rootDir = __dirname;
const assetsDir = path.join(rootDir, 'assets');
const assetsInfo = path.join(assetsDir, 'current.json');
const pubDir = path.join(rootDir, 'public');
const pubAssets = '/assets';
const pubAssetsFull = path.join(pubDir, pubAssets);
const pubAssetCSSFormat = '%s-%s.css';
const pubAssetJSFormat = '%s-%s.js';
const isDebugBuild = fs.existsSync(path.join(rootDir, '.debug'));
2023-10-14 23:05:49 +00:00
const renderTemplates = [
{ in: 'errors/401', out: '/error-401.html' },
{ in: 'errors/403', out: '/error-403.html' },
{ in: 'errors/404', out: '/error-404.html' },
{ in: 'errors/500', out: '/error-500.html' },
{ in: 'errors/503', out: '/error-503.html' },
];
const swcJscOptions = {
target: 'es2016',
loose: false,
externalHelpers: false,
keepClassNames: true,
preserveAllComments: false,
transform: {},
parser: {
syntax: 'ecmascript',
jsx: true,
dynamicImport: false,
privateMethod: false,
functionBind: false,
exportDefaultFrom: false,
exportNamespaceFrom: false,
decorators: false,
decoratorsBeforeExport: false,
topLevelAwait: true,
importMeta: false,
},
transform: {
react: {
runtime: 'classic',
pragma: '$er',
},
},
};
2023-10-14 23:05:49 +00:00
const htmlMinifyOptions = {
collapseBooleanAttributes: true,
collapseWhitespace: true,
conservativeCollapse: false,
decodeEntities: false,
quoteCharacter: '"',
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeOptionalTags: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
sortAttributes: true,
sortClassName: true,
};
const postcssPlugins = [];
if(!isDebugBuild) postcssPlugins.push(require('cssnano'));
postcssPlugins.push(require('autoprefixer')({
remove: false,
}));
fs.mkdirSync(pubAssetsFull, { recursive: true });
(async () => {
2023-10-13 19:33:34 +00:00
console.log('Building assets...');
const dirs = fs.readdirSync(assetsDir);
const assets = {};
const _postcss = postcss(postcssPlugins);
for(const dir of dirs) {
const dirPath = path.join(assetsDir, dir);
if(!fs.statSync(dirPath).isDirectory())
continue;
const parts = dir.split('.', 2);
if(parts.length < 2)
continue;
console.log();
console.log(dir);
let filePath = '';
let fileBody = '';
if(parts[1] === 'js') {
fileBody = await assproc.process(dirPath, { 'prefix': '#', 'entry': 'main.js' });
fileBody = (await swc.transform(fileBody, {
filename: dir,
sourceMaps: false,
isModule: false,
minify: !isDebugBuild,
jsc: swcJscOptions,
})).code;
filePath = path.join(pubAssets, util.format(pubAssetJSFormat, parts[0], utils.shortHash(fileBody)));
} else if(parts[1] === 'css') {
fileBody = await assproc.process(dirPath, { 'prefix': '@', 'entry': 'main.css' });
fileBody = (await _postcss.process(fileBody, { from: dir })).css;
filePath = path.join(pubAssets, util.format(pubAssetCSSFormat, parts[0], utils.shortHash(fileBody)));
}
if(filePath !== '') {
assets[dir] = filePath;
fs.writeFileSync(path.join(pubDir, filePath), fileBody);
} else console.error(`Unknown type: ${parts[1]}`);
}
console.log('Writing assets info...');
fs.writeFileSync(assetsInfo, JSON.stringify(assets));
2023-10-14 23:05:49 +00:00
console.log('Housekeeping...');
assproc.housekeep(pubAssetsFull);
2023-10-14 23:05:49 +00:00
console.log('Prerendering templates...');
const renderCommand = path.join(rootDir, 'tools/render-tpl');
console.log(renderCommand);
for(const info of renderTemplates) {
console.log();
console.log(info.in);
const { stdout, stderr } = await exec(`${renderCommand} ${info.in}`);
if(stdout.trim() === '') {
console.error(stderr);
continue;
}
let body = await htmlminify(stdout, htmlMinifyOptions);
fs.writeFileSync(path.join(pubDir, info.out), body);
}
})();