mono/packages/tasks/src/library-images.ts
2026-01-29 15:31:09 +01:00

222 lines
7.6 KiB
TypeScript

import * as path from 'path'
import * as sharp from 'sharp'
import { sync as dir } from '@plastichub/fs/dir'
import { sync as exists } from '@plastichub/fs/exists'
import { files as _glob } from '@plastichub/osr-commons'
import { logger } from '../src'
const fg = require('fast-glob')
export const getFormats = (product, folder) => {
return [{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/webp`,
format: 'webp',
}];
}
/*
const updateImages = async (root, product_root, content) => {
// Feed the content into JSDOM
const dom = new JSDOM(content);
const document = dom.window.document;
// Find the image elements via `querySelectorAll`, replace this selector with your own custom one
const imageElems = document.querySelectorAll('img');
// If there are no matching elements, just return the original content :)
if (imageElems.length === 0) {
return content;
}
for (const imgElem of imageElems) {
// Get the `src` of the image element
const imgSrc = imgElem.getAttribute('src');
// Only add this transform for internal images
if (imgSrc.startsWith('https') || imgSrc.startsWith('http')) {
let srcSet = [];
// Replace all of the image sources with a new one that matches the results of the Sharp build
if (imgSrc.indexOf('.png') !== -1) {
continue;
}
if (imgSrc.indexOf('.png') !== -1) {
continue;
}
const parsed = URI.parse(decodeURIComponent(imgSrc));
const pParsed = path.parse(parsed.path);
const imageName = (url) => {
return decodeURIComponent(pParsed.base);
}
// const parts = url.parse(imgSrc);
// Get the metadata for the file and add it as the `${width}w` needed in defining a `srcset` in HTML for `<img>`
const name = imageName(imgSrc);
const _path = decodeURIComponent(parsed.path).replace('//', '');
const imageSrcPath = `${root}/${_path}`;
if (!exists(imageSrcPath)) {
console.log('image doesnt exists : ' + imageSrcPath + ' \n\t' + imgSrc);
return;
}
const imageSrcPathParts = path.parse(imageSrcPath);
const imgSrc80 = imgSrc.replace(name, '80/' + name);
const imgSrc60 = imgSrc.replace(name, '60/' + name);
const imgSrc40 = imgSrc.replace(name, '40/' + name);
const imgSrc20 = imgSrc.replace(name, '20/' + name);
const _set = (res) => {
return path.resolve(imageSrcPathParts.dir + '/' + res + '/' + name);
}
if (!exists(_set(80))) {
console.error('doesnt exists ', _set(80), imgSrc);
continue;
}
if (!exists(_set(60))) {
console.error('doesnt exists ', _set(60), imgSrc);
continue;
}
if (!exists(_set(40))) {
console.error('doesnt exists ', _set(40), imgSrc);
continue;
}
if (!exists(_set(20))) {
console.error('doesnt exists ', _set(20), imgSrc);
continue;
}
const img80 = await sharp(_set(80));
const md80 = await img80.metadata();
srcSet.push(`${imgSrc80.replace(/\s/g,'%20')} ${md80.width}w`);
// Repeat
const img60 = await sharp(_set(60));
const md60 = await img60.metadata();
srcSet.push(`${imgSrc60.replace(/\s/g,'%20')} ${md60.width}w`);
// Repeat
const img40 = await sharp(_set(40));
const md40 = await img40.metadata();
srcSet.push(`${imgSrc40.replace(/\s/g,'%20')} ${md40.width}w`);
// Repeat
const img20 = await sharp(_set(20));
const md20 = await img20.metadata();
srcSet.push(`${imgSrc20.replace(/\s/g,'%20')} ${md20.width}w`);
// Join the `srcset` into a string. that can be added to the `<img>` tag
srcSet = srcSet.join(', ');
// Set the `srcset` attribute
imgElem.setAttribute('srcset', srcSet);
// Find the new `src` for the WebP image
let webpSrc = imgSrc.replace(name, 'webp/' + encodeURIComponent(name)).replace('.png', '.webp').replace('.jpg', '.webp');
// const webpSrc = imgSrc
// .replace('/images/', '/images/webp/')
// .replace('.png', '.webp');
// Create a separate `source` element for the WebP with feature detection via `type`
const webpElement = document.createElement('source');
webpElement.setAttribute('srcset', webpSrc);
webpElement.setAttribute('type', 'image/webp');
// Wrap the `<img>` and the `<source>` into one `<picture>` tag in order for it to work
const pictureElement = document.createElement('picture');
pictureElement.appendChild(webpElement);
pictureElement.appendChild(imgElem.cloneNode());
// Replace the `<img>` with the `<picture>`
imgElem.replaceWith(pictureElement);
}
}
return document.documentElement.outerHTML;
}
*/
export const format = (formats) => {
return formats.forEach((format) => {
if (!exists(format.dist)) {
dir(format.dist)
}
// Find all files matching the glob patterns specified in `src`
let _files = fg.sync(format.src)
_files.forEach((file) => {
let filename = path.basename(file);
if (exists(path.resolve(`${format.dist}/${filename.replace('jpg', format.format)}`))) {
return;
}
const image = sharp(file);
// Convert to WebP via Sharp's inferencing automatically of extensions
image
.toFile(`${format.dist}/${filename.replace('jpg', format.format)}`)
.catch((err) => {
console.log(err);
});
});
});
}
export const getResizePatterns = (product, folder) => {
return [{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/80`,
percent: 80,
},
{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/60`,
percent: 60,
},
{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/40`,
percent: 40,
},
{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/20`,
percent: 20,
},
];
}
const resize = (patterns) => {
return patterns.forEach((resize) => {
if (!exists(resize.dist)) {
dir(resize.dist)
}
let _files = fg.sync(resize.src)
_files.forEach((file) => {
let filename = path.basename(file)
const image = sharp(file)
if (exists(`${resize.dist}/${filename}`)) {
return
}
image
.metadata()
.then((metadata) => {
return image
.resize(Math.round(metadata.width * (resize.percent / 100)))
.png()
.toFile(`${resize.dist}/${filename}`)
.catch(logger.error);
})
.catch(logger.error)
})
})
}