Files
asciidisco.com/build/tasks/images.js
2023-08-01 13:49:46 +02:00

111 lines
4.0 KiB
JavaScript

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')
})
*/