const fs = require('fs') const path = require('path') const Jimp = require('jimp') const imagemin = require('imagemin') const rimraf = require('rimraf') const zopfli = require('node-zopfli') const brotli = require('iltorb') const filewalker = require('filewalker') const chalk = require('chalk') const log = console.log; // clear dist path const clear_dist = config => new Promise((resolve, reject) => rimraf(path.join(config.basepath, config.dist_path, config.image_path), err => err ? reject(err) : resolve())) // webp conversion const convertToWebp = config => { return new Promise((resolve, reject) => { let cbw_counter = 0 const webp_plug = [require('imagemin-webp')({method: 6})] const wcb = () => cbw_counter++ === config.images.length - 1 ? resolve() : false config.images.forEach(orig => { let folder = path.basename(path.dirname(orig)) let destination = path.join(config.basepath, config.dist_path, config.image_path, folder) let original_path = path.join(destination, path.basename(orig)).replace(',svg', '') imagemin([original_path], destination, {plugins: webp_plug}).then(wcb) }) }) } // losslessly optimize images const lossless_optimize = config => { return new Promise((resolve, reject) => { let cb_counter = 0 const plugins = [ require('imagemin-jpegtran')(), require('imagemin-jpegoptim')(), require('imagemin-mozjpeg')(), require('imagemin-zopfli')({more: true}), require('imagemin-pngcrush')(), require('imagemin-advpng')(), require('imagemin-optipng')(), require('imagemin-svgo')(), ] const cb = () => cb_counter++ === config.images.length - 1 ? resolve() : false config.images.forEach(orig => { const folder = path.basename(path.dirname(orig)) const destination = path.join(config.basepath, config.dist_path, config.image_path, folder) const source = path.join(config.basepath, config.image_path, orig) imagemin([source], destination, {plugins: plugins}).then(cb) }) }) } // compress svg with zopfli & brotli const compress_svg = config => { return new Promise((resolve, reject) => { const find_images = () => { let images = [] filewalker(path.join(config.basepath, config.dist_path, config.image_path)) .on('file', file => images.push(path.join(config.basepath, config.dist_path, config.image_path, file))) .on('done', filter_svgs.bind(null, images)) .walk() } const filter_svgs = images => compress_items(images.filter(image => image.substr(-4) === '.svg')) const compress_items = images => { const iterations = images.length * 2 let scb_counter = 0 const scb = () => scb_counter++ === iterations ? resolve() : false images.forEach(image => { // read original file contents fs.readFile(image, 'utf-8', (err, contents) => { // write zopfli compressed file zopfli.gzip(Buffer.from(contents), (err, output) => fs.writeFile(image + '.gz', output, err => err ? reject(err) : scb())) // write brotli compressed file brotli.compress(Buffer.from(contents), (err, output) => fs.writeFile(image + '.br', output, err => err ? reject(err) : scb())) }) }) } find_images() }) } module.exports = (config, result) => { return new Promise(async (resolve, reject) => { try { log(' ', chalk.green('>>'), 'Deleting old destination folder') const cleared = await clear_dist(config) log(' ', chalk.green('>>'), 'Optimize images') const optimized = await lossless_optimize(config) log(' ', chalk.green('>>'), 'Convert to WebP') const webp = await convertToWebp(config) log(' ', chalk.green('>>'), 'Static compress SVG') const compressedSvg = compress_svg(config) resolve({cleared, optimized, webp, compressedSvg}) } catch (err) { reject(err) } }) } /* Jimp.read('../img/content/article.jpg', (err, image) => { if (err) throw err image.resize(Jimp.AUTO, 400).quality(100).write('../dist/article-home.jpg') }) */