core/client/uikit/build/util.js
2022-03-02 14:36:17 +06:00

247 lines
6.3 KiB
JavaScript

import less from 'less';
import fs from 'fs-extra';
import pLimit from 'p-limit';
import globImport from 'glob';
import {optimize} from 'svgo';
import {promisify} from 'util';
import minimist from 'minimist';
import CleanCSS from 'clean-css';
import html from 'rollup-plugin-html';
import buble from '@rollup/plugin-buble';
import alias from '@rollup/plugin-alias';
import modify from 'rollup-plugin-modify';
import replace from '@rollup/plugin-replace';
import {basename, dirname, join} from 'path';
import {exec as execImport} from 'child_process';
import {rollup, watch as rollupWatch} from 'rollup';
import {minify as rollupMinify} from 'rollup-plugin-esbuild';
const limit = pLimit(Number(process.env.cpus || 2));
export const exec = promisify(execImport);
export const glob = promisify(globImport);
export const {pathExists, readJson} = fs;
export const banner = `/*! UIkit ${await getVersion()} | https://www.getuikit.com | (c) 2014 - ${new Date().getFullYear()} YOOtheme | MIT License */\n`;
export const validClassName = /[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/;
const argv = minimist(process.argv.slice(2));
argv._.forEach(arg => {
const tokens = arg.split('=');
argv[tokens[0]] = tokens[1] || true;
});
export const args = argv;
export function read(file) {
return fs.readFile(file, 'utf8');
}
export async function write(dest, data) {
const err = await fs.writeFile(dest, data);
if (err) {
console.log(err);
throw err;
}
await logFile(dest);
return dest;
}
export async function logFile(file) {
const data = await read(file);
console.log(`${cyan(file)} ${getSize(data)}`);
}
export async function minify(file) {
const {styles} = await limit(() => new CleanCSS({
advanced: false,
keepSpecialComments: 0,
rebase: false,
returnPromise: true
}).minify([file]));
await write(`${join(dirname(file), basename(file, '.css'))}.min.css`, styles);
return styles;
}
export function renderLess(data, options) {
return limit(async () => (await less.render(data, options)).css);
}
export async function compile(file, dest, {external, globals, name, aliases, replaces} = {}) {
const minify = !args.nominify;
const debug = args.d || args.debug;
const watch = args.w || args.watch;
name = (name || '').replace(/[^\w]/g, '_');
const inputOptions = {
external,
input: file,
plugins: [
replace({
preventAssignment: true,
values: {
VERSION: `'${await getVersion()}'`,
...replaces
}
}),
alias({
entries: {
'uikit-util': './src/js/util/index.js',
...aliases
}
}),
html({
include: '**/*.svg',
htmlMinifierOptions: {
collapseWhitespace: true
}
}),
buble({namedFunctionExpressions: false}),
modify({
find: /(>)\\n\s+|\\n\s+(<)/,
replace: (m, m1, m2) => `${m1 || ''} ${m2 || ''}`
})
]
};
const outputOptions = {
globals,
banner,
format: 'umd',
amd: {id: `UIkit${name}`.toLowerCase()},
name: `UIkit${ucfirst(name)}`,
sourcemap: debug ? 'inline' : false
};
const output = [{
...outputOptions,
file: `${dest}.js`
}];
if (minify) {
output.push({
...outputOptions,
file: `${dest}.min.js`,
plugins: [minify ? rollupMinify() : undefined]
});
}
if (!watch) {
const bundle = await rollup(inputOptions);
for (const options of output) {
await limit(() => bundle.write(options));
logFile(options.file);
}
await bundle.close();
} else {
console.log('UIkit is watching the files...');
const watcher = rollupWatch({
...inputOptions,
output
});
watcher.on('event', ({code, result, output, error}) => {
if (result) {
result.close();
}
if (code === 'BUNDLE_END' && output) {
output.map(logFile);
}
if (error) {
console.error(error);
}
});
watcher.close();
}
}
export async function icons(src) {
const options = {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
cleanupNumericValues: {
floatPrecision: 3
},
convertPathData: false,
convertShapeToPath: false,
mergePaths: false,
removeDimensions: false,
removeStyleElement: false,
removeScriptElement: false,
removeUnknownsAndDefaults: false,
removeUselessStrokeAndFill: false
}
}
}
]
};
const files = await glob(src, {nosort: true});
const icons = await Promise.all(
files.map(file =>
limit(async () =>
(await optimize(await read(file), options)).data
)
)
);
return JSON.stringify(files.reduce((result, file, i) => {
result[basename(file, '.svg')] = icons[i];
return result;
}, {}), null, ' ');
}
export async function run(cmd, options) {
const {stdout, stderr} = await limit(() => exec(cmd, options));
stdout && console.log(stdout.trim());
stderr && console.log(stderr.trim());
return stdout;
}
export function ucfirst(str) {
return str.length ? str.charAt(0).toUpperCase() + str.slice(1) : '';
}
export async function getVersion() {
return (await readJson('package.json')).version;
}
export async function replaceInFile(file, fn) {
await write(file, await fn(await read(file)));
}
function cyan(str) {
return `\x1b[1m\x1b[36m${str}\x1b[39m\x1b[22m`;
}
function getSize(data) {
return `${(data.length / 1024).toFixed(2)}kb`;
}