diff --git a/assets/conf-img/sizes/square-native.json b/assets/conf-img/sizes/square-native.json new file mode 100644 index 00000000..957b72d7 --- /dev/null +++ b/assets/conf-img/sizes/square-native.json @@ -0,0 +1,12 @@ +[ + { + "width": 500, + "height": 500, + "crop": true + }, + { + "width": 1000, + "height": 1000, + "crop": true + } +] diff --git a/assets/conf-img/tpl/default-native-caption.tpl b/assets/conf-img/tpl/default-native-caption.tpl new file mode 100644 index 00000000..daf9c71e --- /dev/null +++ b/assets/conf-img/tpl/default-native-caption.tpl @@ -0,0 +1,5 @@ +%%data-location%% +
+ +
%%caption%%
+
diff --git a/assets/conf-img/tpl/default-native.tpl b/assets/conf-img/tpl/default-native.tpl new file mode 100644 index 00000000..baf82163 --- /dev/null +++ b/assets/conf-img/tpl/default-native.tpl @@ -0,0 +1,2 @@ +%%data-location%% + diff --git a/config/WebpackImageSizesPlugin.js b/config/WebpackImageSizesPlugin.js deleted file mode 100644 index e718dbd6..00000000 --- a/config/WebpackImageSizesPlugin.js +++ /dev/null @@ -1,266 +0,0 @@ -const chalk = require('chalk') -const path = require('path') -const fs = require('fs') -const sharp = require('sharp') - -const logId = '[' + chalk.blue('WebpackImageSizesPlugin') + ']' - -class WebpackImageSizesPlugin { - constructor(options) { - // folders - this._confImgFolder = path.resolve(__dirname, '../assets/conf-img') + '/' - this._tplFolder = this._confImgFolder + 'tpl/' - this._defaultImagesFolder = path.resolve(__dirname, '../dist/images') + '/' - - // files - this._imageSisesJson = this._confImgFolder + 'image-sizes.json' - this._imageLocationsJson = this._confImgFolder + 'image-locations.json' - this._imageDefault = path.resolve(__dirname, '../src/img/static') + '/default.jpg' - - // list of [filnename]: sizes - this._defaultImages = {} - - if (options.watch) { - fs.watch(this._tplFolder, () => { - this.generateImageJsonFiles() - this.generateDefaultImages() - }) - } - - this.generateImageJsonFiles() - } - - /** - * apply - */ - apply(compiler) { - compiler.hooks.afterEmit.tapAsync('WebpackImageSizesPlugin', (compilation, callback) => { - this.generateDefaultImages() - callback() - }) - } - - /** - * Generate image-sises.json and image-location.json - */ - generateImageJsonFiles() { - const that = this - const regex = { - srcset: /srcset="(.[^"]*)"/gm, - crop: /data-crop="(.[^"]*)"/gm, - img: /img-\d*-\d*/gm, - } - - const locations = {} - const sizes = {} - - let nbLocations = 0 - let nbSizes = 0 - - /** - * reset defaultImages - */ - this._defaultImages = {} - - /** - * Return an array of names of tpl files - * @return {array} - */ - function getTemplateFileNames() { - return fs.readdirSync(that._tplFolder).filter((tpl) => { - if ( - tpl !== 'default-picture.tpl' && - tpl !== 'default-picture-caption.tpl' && - tpl !== 'default-picture-nolazyload.tpl' && - tpl !== 'default-picture-nolazyload-caption.tpl' - ) { - return tpl - } - }) - } - - /** - * Return content of tpl file - * @param {string} templateFileName - * @return {string} - */ - function getTemplateFileContent(templateFileName) { - return fs.readFileSync(that._tplFolder + templateFileName, 'utf8') - } - - /** - * Create a json file - * @param {string} destPath - * @param data - * @return undefined - */ - function createJsonFile(destPath, data) { - createFile(destPath, JSON.stringify(data, null, 2)) - } - - /** - * Remove extension template name - * @param {string} name - * @return {String} - */ - function removeFileExtension(name) { - return name.split('.')[0] - } - - /** - * Generate default location name based on image size - * @param {String} size - * @return {String} - */ - function getDefaultImgName(str) { - return `${str.replace('img', 'default')}.jpg` - } - - /** - * Check if srcset is retina - * @param {String} src - * @return {Array} - */ - function isRetina(src) { - const retina = [] - src.split(',').forEach((val) => { - if (val.includes('2x')) { - retina.push('2x') - } else { - retina.push('') - } - }) - return retina - } - - /** - * Create file if he does not exist - * @param {String} filename - * @param {String} json - */ - function createFile(filename, json) { - fs.open(filename, 'r', () => { - fs.writeFileSync(filename, json) - }) - } - - /** - * Get image locations informations from tpl files - */ - function imageLocationsFromTpl() { - const templateFileNames = getTemplateFileNames() - - templateFileNames.forEach((tplName) => { - nbLocations += 1 - const tplContent = getTemplateFileContent(tplName) - const srcsetArr = tplContent.match(regex.srcset) || [] - const cropArr = tplContent.match(regex.crop) - const storage = { - srcsets: [], - default_img: '', - img_base: '', - } - - srcsetArr.forEach((src) => { - const dimensions = src.match(regex.img) - const retina = isRetina(src) - const crop = !(cropArr && cropArr[0] === 'data-crop="false"') - - dimensions.forEach((size, index) => { - const splitSize = size.split('-') - const srcsetObj = { - srcset: retina[index], - size, - } - - if (sizes[size] && sizes[size].crop !== crop) { - console.log(logId, '\nSize already exists but crop is not equal :', size) - } - - if (!sizes[size]) { - sizes[size] = { - width: splitSize[1], - height: splitSize[2], - crop, - } - - nbSizes += 1 - } - - storage.srcsets.push(srcsetObj) - storage.default_img = getDefaultImgName(size) - storage.img_base = size - - that._defaultImages[getDefaultImgName(size)] = sizes[size] - }) - - locations[removeFileExtension(tplName)] = [storage] - }) - }) - } - - /** - * Init - */ - console.log(logId, 'Generate image locations and sizes JSON files') - - imageLocationsFromTpl() - - createJsonFile(this._imageLocationsJson, [locations]) - createJsonFile(this._imageSisesJson, [sizes]) - - console.log(logId, 'JSON files successfully generated !') - console.log(logId, 'Number of locations:', nbLocations) - console.log(logId, 'Number of sizes:', nbSizes) - - return this - } - - /** - * generate default images - */ - generateDefaultImages() { - if (!fs.existsSync(this._defaultImagesFolder)) { - fs.mkdirSync(this._defaultImagesFolder, { recursive: true }) - } - - for (const filename in this._defaultImages) { - const sizes = this._defaultImages[filename] - const outputFile = this._defaultImagesFolder + filename - - try { - if (fs.existsSync(outputFile)) { - continue - } - - const width = parseInt(sizes.width, 10) - const height = parseInt(sizes.height, 10) - - if (width >= 9999 || height >= 9999) { - continue - } - - sharp(this._imageDefault) - .resize(width, height, { - fit: 'cover', - position: 'center', - }) - .jpeg({ quality: 70, chromaSubsampling: '4:4:4' }) - .toFile(outputFile, (err, info) => { - if (err) { - console.error(logId, err) - } else { - console.log(logId, `Created ${info.width}x${info.height} image`) - console.log(logId, 'at', outputFile.split('/themes/')[1] || '') - } - }) - } catch (err) { - console.error(logId, err) - } - } - - return this - } -} - -module.exports = WebpackImageSizesPlugin diff --git a/config/plugins.js b/config/plugins.js index be971bb1..866ecb12 100644 --- a/config/plugins.js +++ b/config/plugins.js @@ -9,7 +9,7 @@ const WebpackBar = require('webpackbar') const DependencyExtractionWebpackPlugin = require('@wordpress/dependency-extraction-webpack-plugin') const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin -const WebpackImageSizesPlugin = require('./WebpackImageSizesPlugin') +const WebpackImageSizesPlugin = require('./webpack-image-sizes-plugin') module.exports = { get: function (mode) { @@ -33,7 +33,15 @@ module.exports = { }), new DependencyExtractionWebpackPlugin(), new WebpackImageSizesPlugin({ - watch: mode !== 'production', + confImgPath: 'assets/conf-img', // Path to the conf-img folder + sizesSubdir: 'sizes', // Subdirectory containing the sizes JSON files + tplSubdir: 'tpl', // Subdirectory containing TPL templates + outputImageLocations: 'image-locations.json', // Output locations file name + outputImageSizes: 'image-sizes.json', // Output sizes file name + generateDefaultImages: true, // Generate default images + defaultImageSource: 'src/img/static/default.jpg', // Source image for generation + defaultImagesOutputDir: 'dist/images', // Default images output directory + defaultImageFormat: 'jpg', // Generated image format (jpg, png, webp, avif) }), ] diff --git a/config/webpack-image-sizes-plugin.js b/config/webpack-image-sizes-plugin.js new file mode 100644 index 00000000..f8cac011 --- /dev/null +++ b/config/webpack-image-sizes-plugin.js @@ -0,0 +1,509 @@ +const fs = require('fs') +const path = require('path') + +// Try to require sharp, fallback gracefully if not available +let sharp +try { + sharp = require('sharp') +} catch (error) { + console.warn('⚠️ Sharp not available. Default image generation will be disabled.') +} + +/** + * Webpack plugin that generates image-locations.json and image-sizes.json files + * by parsing JSON files in sizes/ subdirectory and TPL files in tpl/ subdirectory. + * + * @class WebpackImageSizesPlugin + */ +class WebpackImageSizesPlugin { + /** + * Creates an instance of WebpackImageSizesPlugin. + * + * @param {Object} [options={}] - Plugin configuration options + * @param {string} [options.confImgPath='assets/conf-img'] - Path to the conf-img directory + * @param {string} [options.sizesSubdir='sizes'] - Subdirectory containing JSON size files + * @param {string} [options.tplSubdir='tpl'] - Subdirectory containing TPL template files + * @param {string} [options.outputImageLocations='image-locations.json'] - Output filename for image locations + * @param {string} [options.outputImageSizes='image-sizes.json'] - Output filename for image sizes + * @param {boolean} [options.generateDefaultImages=false] - Whether to generate default images + * @param {string} [options.defaultImageSource='src/img/static/default.jpg'] - Path to the source image for generating defaults + * @param {string} [options.defaultImagesOutputDir='dist/images'] - Directory where default images will be generated + * @param {string} [options.defaultImageFormat='jpg'] - Format for generated images (jpg, png, webp, avif) + * @memberof WebpackImageSizesPlugin + */ + constructor(options = {}) { + this.options = { + confImgPath: options.confImgPath || 'assets/conf-img', + sizesSubdir: options.sizesSubdir || 'sizes', + tplSubdir: options.tplSubdir || 'tpl', + outputImageLocations: options.outputImageLocations || 'image-locations.json', + outputImageSizes: options.outputImageSizes || 'image-sizes.json', + generateDefaultImages: options.generateDefaultImages || false, + defaultImageSource: options.defaultImageSource || 'src/img/static/default.jpg', + defaultImagesOutputDir: options.defaultImagesOutputDir || 'dist/images', + defaultImageFormat: options.defaultImageFormat || 'jpg', + ...options, + } + } + + /** + * Applies the plugin to the webpack compiler. + * Sets up hooks for initial build and watch mode rebuilds. + * + * @param {Object} compiler - The webpack compiler instance + * @memberof WebpackImageSizesPlugin + */ + apply(compiler) { + // Execute on first build and each rebuild + const runGeneration = async (compilation, callback) => { + try { + const confImgPath = path.resolve(compiler.context, this.options.confImgPath) + const sizesPath = path.join(confImgPath, this.options.sizesSubdir) + const tplPath = path.join(confImgPath, this.options.tplSubdir) + + console.log('🔧 Starting WebpackImageSizesPlugin generation...') + + // Check for deleted/renamed files if output files already exist + this.checkForDeletedFiles(confImgPath, sizesPath, tplPath) + + // Generate image-locations.json from JSON and TPL files + const imageLocations = this.generateImageLocations(sizesPath, tplPath) + + // Generate image-sizes.json from JSON files and TPL files + const imageSizes = this.generateImageSizes(sizesPath, tplPath, imageLocations) + + // Write output files + const imageLocationsPath = path.join(confImgPath, this.options.outputImageLocations) + const imageSizesPath = path.join(confImgPath, this.options.outputImageSizes) + + fs.writeFileSync(imageLocationsPath, JSON.stringify(imageLocations, null, 2)) + fs.writeFileSync(imageSizesPath, JSON.stringify(imageSizes, null, 2)) + + console.log(`✅ Generated ${this.options.outputImageLocations} and ${this.options.outputImageSizes}`) + + // Generate default images if option is enabled + if (this.options.generateDefaultImages) { + await this.generateDefaultImages(compiler.context, imageSizes) + } + + if (callback) { + callback() + } + } catch (error) { + console.error('❌ Error in WebpackImageSizesPlugin:', error) + if (callback) { + callback(error) + } + } + } + + // Hook for initial build + compiler.hooks.emit.tapAsync('WebpackImageSizesPlugin', runGeneration) + + // Hook for rebuilds in watch mode + compiler.hooks.watchRun.tapAsync('WebpackImageSizesPlugin', (compiler, callback) => { + console.log('👀 Watch mode: checking for conf-img changes...') + runGeneration(null, callback) + }) + + // Add directories to watch + compiler.hooks.afterEnvironment.tap('WebpackImageSizesPlugin', () => { + const confImgPath = path.resolve(compiler.context, this.options.confImgPath) + const sizesPath = path.join(confImgPath, this.options.sizesSubdir) + const tplPath = path.join(confImgPath, this.options.tplSubdir) + + // Add directories to watched dependencies + compiler.hooks.compilation.tap('WebpackImageSizesPlugin', (compilation) => { + // Watch configuration directories + if (fs.existsSync(sizesPath)) { + compilation.contextDependencies.add(sizesPath) + console.log('📁 Added sizes directory to watch dependencies') + } + if (fs.existsSync(tplPath)) { + compilation.contextDependencies.add(tplPath) + console.log('📁 Added tpl directory to watch dependencies') + } + }) + }) + } + + /** + * Generates image sizes configuration by parsing JSON files in the sizes directory + * and extracting sizes from TPL files. + * + * @param {string} sizesPath - Path to the sizes directory containing JSON files + * @param {string} tplPath - Path to the tpl directory containing template files + * @param {Array} imageLocations - Generated image locations to extract additional sizes + * @returns {Array} Array containing image sizes configuration object + * @memberof WebpackImageSizesPlugin + */ + generateImageSizes(sizesPath, tplPath, imageLocations) { + // Completely reset image sizes + const imageSizes = [{}] + const allSizes = new Set() // To avoid duplicates + + if (!fs.existsSync(sizesPath)) { + console.warn(`⚠️ Sizes directory not found: ${sizesPath}`) + return imageSizes + } + + const sizeFiles = fs.readdirSync(sizesPath).filter((file) => file.endsWith('.json')) + console.log(`📋 Processing ${sizeFiles.length} size files: ${sizeFiles.join(', ')}`) + + sizeFiles.forEach((file) => { + try { + const filePath = path.join(sizesPath, file) + const sizesData = JSON.parse(fs.readFileSync(filePath, 'utf8')) + + // Convert sizes to image-sizes.json format + sizesData.forEach((size) => { + const sizeKey = `img-${size.width}-${size.height}` + + // Avoid duplicates between files + if (!allSizes.has(sizeKey)) { + allSizes.add(sizeKey) + imageSizes[0][sizeKey] = { + width: size.width.toString(), + height: size.height.toString(), + crop: size.crop, + } + } + }) + } catch (error) { + console.error(`❌ Error parsing ${file}:`, error) + } + }) + + // Extract additional sizes from TPL files that are not in JSON files + this.extractSizesFromTPLFiles(tplPath, imageLocations, imageSizes[0], allSizes) + + console.log(`📐 Generated ${Object.keys(imageSizes[0]).length} unique image sizes`) + return imageSizes + } + + /** + * Extracts image sizes from TPL files and adds them to the sizes configuration. + * This method parses image locations to find sizes that are referenced in TPL files + * but not defined in JSON files. + * + * @param {string} tplPath - Path to the tpl directory + * @param {Array} imageLocations - Generated image locations containing srcsets + * @param {Object} imageSizesObj - Image sizes object to populate + * @param {Set} allSizes - Set of already processed sizes to avoid duplicates + * @memberof WebpackImageSizesPlugin + */ + extractSizesFromTPLFiles(tplPath, imageLocations, imageSizesObj, allSizes) { + if (!fs.existsSync(tplPath) || !imageLocations[0]) { + return + } + + // Extract all unique sizes from image locations + const tplSizes = new Set() + + Object.values(imageLocations[0]).forEach((locationArray) => { + locationArray.forEach((location) => { + if (location.srcsets) { + location.srcsets.forEach((srcset) => { + if (srcset.size && srcset.size.startsWith('img-')) { + tplSizes.add(srcset.size) + } + }) + } + }) + }) + + // Add sizes that are not already defined + tplSizes.forEach((sizeKey) => { + if (!allSizes.has(sizeKey)) { + // Extract width and height from size key (e.g., "img-100-100" -> width: 100, height: 100) + const matches = sizeKey.match(/img-(\d+)-(\d+)/) + if (matches) { + const width = matches[1] + const height = matches[2] + + allSizes.add(sizeKey) + imageSizesObj[sizeKey] = { + width: width, + height: height, + crop: true, // Default crop value for TPL-extracted sizes + } + + console.log(`🎨 Added size from TPL: ${sizeKey}`) + } + } + }) + } + + /** + * Generates image locations configuration by parsing JSON and TPL files. + * + * @param {string} sizesPath - Path to the sizes directory containing JSON files + * @param {string} tplPath - Path to the tpl directory containing template files + * @returns {Array} Array containing image locations configuration object + * @memberof WebpackImageSizesPlugin + */ + generateImageLocations(sizesPath, tplPath) { + // Completely reset image locations + const imageLocations = [{}] + const processedFiles = new Set() // For tracking processed files + + if (!fs.existsSync(sizesPath)) { + console.warn(`⚠️ Sizes directory not found: ${sizesPath}`) + return imageLocations + } + + // Process JSON files in sizes/ first + const sizeFiles = fs.readdirSync(sizesPath).filter((file) => file.endsWith('.json')) + console.log(`📋 Processing ${sizeFiles.length} JSON files from sizes/: ${sizeFiles.join(', ')}`) + + sizeFiles.forEach((file) => { + try { + const filename = path.basename(file, '.json') + const filePath = path.join(sizesPath, file) + const sizesData = JSON.parse(fs.readFileSync(filePath, 'utf8')) + + // Generate srcsets from sizes + const srcsets = sizesData.map((size) => ({ + size: `img-${size.width}-${size.height}`, + })) + + imageLocations[0][filename] = [ + { + srcsets: srcsets, + }, + ] + + processedFiles.add(filename) + } catch (error) { + console.error(`❌ Error parsing JSON ${file}:`, error) + } + }) + + // Then process TPL files for unprocessed or missing files + if (fs.existsSync(tplPath)) { + const tplFiles = fs.readdirSync(tplPath).filter((file) => file.endsWith('.tpl')) + console.log(`📋 Processing ${tplFiles.length} TPL files: ${tplFiles.join(', ')}`) + + tplFiles.forEach((file) => { + try { + const filename = path.basename(file, '.tpl') + const filePath = path.join(tplPath, file) + const tplContent = fs.readFileSync(filePath, 'utf8') + + // Extract sizes from templates (pattern %%img-width-height%%) + const sizeMatches = tplContent.match(/%%img-(\d+)-(\d+)%%/g) + + // Process only if not already processed by a JSON file or no JSON match + if (sizeMatches && !processedFiles.has(filename)) { + const srcsets = [...new Set(sizeMatches)].map((match) => { + const size = match.replace(/%%/g, '') + return { size } + }) + + imageLocations[0][filename] = [ + { + srcsets: srcsets, + }, + ] + + processedFiles.add(filename) + console.log(`📝 Added location from TPL: ${filename}`) + } + } catch (error) { + console.error(`❌ Error parsing TPL ${file}:`, error) + } + }) + } + + const totalEntries = Object.keys(imageLocations[0]).length + console.log(`📍 Generated ${totalEntries} image locations (${processedFiles.size} files processed)`) + + // Log processed files for debugging + if (processedFiles.size > 0) { + console.log(`✅ Processed files: ${Array.from(processedFiles).join(', ')}`) + } + + return imageLocations + } + + /** + * Generates default images from the source image based on image sizes configuration. + * + * @param {string} compilerContext - The webpack compiler context path + * @param {Array} imageSizes - Array containing image sizes configuration + * @memberof WebpackImageSizesPlugin + */ + async generateDefaultImages(compilerContext, imageSizes) { + if (!sharp) { + console.warn('⚠️ Sharp not available. Skipping default image generation.') + return + } + + const sourceImagePath = path.resolve(compilerContext, this.options.defaultImageSource) + const outputDir = path.resolve(compilerContext, this.options.defaultImagesOutputDir) + + if (!fs.existsSync(sourceImagePath)) { + console.warn(`⚠️ Source image not found: ${sourceImagePath}`) + return + } + + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }) + } + + const sizesObj = imageSizes[0] || {} + const sizeKeys = Object.keys(sizesObj) + const format = this.options.defaultImageFormat.toLowerCase() + + // Validate format + const supportedFormats = ['jpg', 'jpeg', 'png', 'webp', 'avif'] + if (!supportedFormats.includes(format)) { + console.warn(`⚠️ Unsupported format '${format}'. Using 'jpg' instead.`) + this.options.defaultImageFormat = 'jpg' + } + + console.log( + `🖼️ Generating ${sizeKeys.length} default images (${format.toUpperCase()}) from ${ + this.options.defaultImageSource + }` + ) + + const promises = sizeKeys.map(async (sizeKey) => { + const size = sizesObj[sizeKey] + const width = parseInt(size.width) + const height = parseInt(size.height) + const outputFilename = `default-${width}-${height}.${this.options.defaultImageFormat}` + const outputPath = path.join(outputDir, outputFilename) + + try { + let sharpInstance = sharp(sourceImagePath) + + if (size.crop) { + // Crop and resize to exact dimensions + sharpInstance = sharpInstance.resize(width, height, { + fit: 'cover', + position: 'center', + }) + } else { + // Resize maintaining aspect ratio + sharpInstance = sharpInstance.resize(width, height, { + fit: 'inside', + withoutEnlargement: false, + }) + } + + // Apply format-specific options + const formatOptions = this.getFormatOptions(this.options.defaultImageFormat) + await sharpInstance[formatOptions.method](formatOptions.options).toFile(outputPath) + + console.log(`✨ Generated: ${outputFilename} (${width}x${height}${size.crop ? ', cropped' : ''})`) + } catch (error) { + console.error(`❌ Error generating ${outputFilename}:`, error.message) + } + }) + + await Promise.all(promises) + console.log(`🎉 Default image generation completed!`) + } + + /** + * Gets format-specific Sharp options for different image formats. + * + * @param {string} format - The image format (jpg, png, webp, avif) + * @returns {Object} Object containing Sharp method and options + * @memberof WebpackImageSizesPlugin + */ + getFormatOptions(format) { + const formatLower = format.toLowerCase() + + const formatConfigs = { + jpg: { + method: 'jpeg', + options: { quality: 80, progressive: true }, + }, + jpeg: { + method: 'jpeg', + options: { quality: 80, progressive: true }, + }, + png: { + method: 'png', + options: { quality: 80, progressive: true }, + }, + webp: { + method: 'webp', + options: { quality: 80, effort: 4 }, + }, + avif: { + method: 'avif', + options: { quality: 80, effort: 4 }, + }, + } + + return formatConfigs[formatLower] || formatConfigs.jpg + } + + /** + * Checks for deleted or renamed files by comparing current files with existing configuration. + * + * @param {string} confImgPath - Path to the conf-img directory + * @param {string} sizesPath - Path to the sizes directory + * @param {string} tplPath - Path to the tpl directory + * @memberof WebpackImageSizesPlugin + */ + checkForDeletedFiles(confImgPath, sizesPath, tplPath) { + const imageLocationsPath = path.join(confImgPath, this.options.outputImageLocations) + + // Check if image-locations.json file already exists + if (!fs.existsSync(imageLocationsPath)) { + console.log('📄 No existing image-locations.json found, creating fresh files') + return + } + + try { + // Read existing file + const existingData = JSON.parse(fs.readFileSync(imageLocationsPath, 'utf8')) + const existingEntries = Object.keys(existingData[0] || {}) + + // Get current files + const currentSizeFiles = fs.existsSync(sizesPath) + ? fs + .readdirSync(sizesPath) + .filter((file) => file.endsWith('.json')) + .map((file) => path.basename(file, '.json')) + : [] + + const currentTplFiles = fs.existsSync(tplPath) + ? fs + .readdirSync(tplPath) + .filter((file) => file.endsWith('.tpl')) + .map((file) => path.basename(file, '.tpl')) + : [] + + const currentFiles = [...new Set([...currentSizeFiles, ...currentTplFiles])] + + // Detect deleted files + const deletedFiles = existingEntries.filter((entry) => !currentFiles.includes(entry)) + + if (deletedFiles.length > 0) { + console.log(`🗑️ Detected ${deletedFiles.length} deleted/renamed files: ${deletedFiles.join(', ')}`) + console.log(' → These entries will be removed from generated files') + } + + // Detect new files + const newFiles = currentFiles.filter((file) => !existingEntries.includes(file)) + + if (newFiles.length > 0) { + console.log(`📂 Detected ${newFiles.length} new files: ${newFiles.join(', ')}`) + console.log(' → These entries will be added to generated files') + } + + if (deletedFiles.length === 0 && newFiles.length === 0) { + console.log('📋 No file changes detected') + } + } catch (error) { + console.warn('⚠️ Could not read existing image-locations.json:', error.message) + } + } +} + +module.exports = WebpackImageSizesPlugin diff --git a/package.json b/package.json index d0362d5b..847a0128 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,6 @@ "license": "GPL-2.0", "dependencies": { "@fontsource/poppins": "^5.0.5", - "lazysizes": "^5.3.2", "oneloop.js": "^5.2.1" }, "devDependencies": { @@ -53,7 +52,7 @@ "prettier": "^2.2.1", "sass": "^1.85.1", "sass-loader": "^16.0.5", - "sharp": "^0.32.1", + "sharp": "^0.34.2", "style-loader": "^2.0.0", "stylelint": "^14.13.0", "stylelint-config-recess-order": "^3.0.0", diff --git a/src/js/editor.js b/src/js/editor.js index fbed2e49..771566b5 100644 --- a/src/js/editor.js +++ b/src/js/editor.js @@ -2,21 +2,10 @@ /* Customize BFFEditorSettings in inc/Services/Editor.php or with `bff_editor_custom_settings` filter (see readme). */ -import lazySizes from 'lazysizes' -import 'lazysizes/plugins/native-loading/ls.native-loading' -import 'lazysizes/plugins/object-fit/ls.object-fit' import domReady from '@wordpress/dom-ready' import { addFilter } from '@wordpress/hooks' import { unregisterBlockStyle, getBlockVariations, unregisterBlockVariation } from '@wordpress/blocks' -/** - * LazySizes configuration - * https://github.com/aFarkas/lazysizes/#js-api---options - */ -lazySizes.cfg.nativeLoading = { - setLoadingAttribute: false, -} - // Native Gutenberg domReady(() => { // Disable specific block styles diff --git a/src/js/index.js b/src/js/index.js index 7a6f043e..64b490f0 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -1,5 +1,3 @@ -import 'lazysizes' -import 'lazysizes/plugins/print/ls.print' import './classes/ScrollDirection' import './classes/ButtonSeoClick' import './classes/Header' diff --git a/src/scss/02-tools/_m-placeholder-media.scss b/src/scss/02-tools/_m-placeholder-media.scss index 9ac0b2d2..dc71bb17 100644 --- a/src/scss/02-tools/_m-placeholder-media.scss +++ b/src/scss/02-tools/_m-placeholder-media.scss @@ -28,11 +28,6 @@ content: ""; } - .lazyload, - .lazyloading { - height: 0; - } - #{$targets} { position: absolute; top: 0; diff --git a/src/scss/04-utilities/_lazyload.scss b/src/scss/04-utilities/_lazyload.scss deleted file mode 100644 index c2a4753e..00000000 --- a/src/scss/04-utilities/_lazyload.scss +++ /dev/null @@ -1,77 +0,0 @@ -@use "../01-abstract/variables" as *; -@use "sass:math"; - -.lazyload, -.lazyloading { - background: $color-primary; - opacity: 0; -} - -.lazyloaded { - opacity: 1; - transition: opacity .5s; -} - -// css loading for bgset items -// with basicspinner -$loading-dimensions: 50px; - -[data-bgset] { - position: relative; - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: cover; - opacity: 1; - - &::before { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 2; - content: ""; - background: $color-primary; - transition: opacity .5s, z-index .5s ease .5s; - } - - &::after { - position: absolute; - top: calc(50% - #{math.div($loading-dimensions, 2)}); - left: calc(50% - #{math.div($loading-dimensions, 2)}); - z-index: 3; - width: $loading-dimensions; - height: $loading-dimensions; - content: ""; - border: 5px solid $color-light; - border-top-color: transparent; - border-radius: $loading-dimensions; - opacity: 1; - transition: opacity .5s, z-index .5s ease .5s; - transform: translateX(-50%) translateY(-50%); - animation: loading .5s linear infinite; - } - - &.lazyload { - opacity: 1; - transition: opacity .5s; - } - - &.lazyloaded { - &::after, - &::before { - z-index: -1; - opacity: 0; - } - } -} - -@keyframes loading { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } -} diff --git a/src/scss/editor.scss b/src/scss/editor.scss index 6e86ec30..25207cf4 100644 --- a/src/scss/editor.scss +++ b/src/scss/editor.scss @@ -27,7 +27,6 @@ variables.$entry-file-name: "editor"; @use "04-utilities/wp-admin-bar"; @use "04-utilities/focus"; -@use "04-utilities/lazyload"; @use "04-utilities/seo"; @use "04-utilities/video-wrapper"; @use "04-utilities/palette"; diff --git a/src/scss/style.scss b/src/scss/style.scss index 4ee6e41e..75d19422 100644 --- a/src/scss/style.scss +++ b/src/scss/style.scss @@ -31,7 +31,6 @@ variables.$entry-file-name: "style"; @use "04-utilities/wp-admin-bar"; @use "04-utilities/focus"; -@use "04-utilities/lazyload"; @use "04-utilities/seo"; @use "04-utilities/video-wrapper"; @use "04-utilities/palette"; diff --git a/yarn.lock b/yarn.lock index a313ba09..60bcc8c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -409,6 +409,15 @@ __metadata: languageName: node linkType: hard +"@emnapi/runtime@npm:^1.4.3": + version: 1.4.3 + resolution: "@emnapi/runtime@npm:1.4.3" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/4f90852a1a5912982cc4e176b6420556971bcf6a85ee23e379e2455066d616219751367dcf43e6a6eaf41ea7e95ba9dc830665a52b5d979dfe074237d19578f8 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/android-arm64@npm:0.16.17" @@ -662,6 +671,195 @@ __metadata: languageName: node linkType: hard +"@img/sharp-darwin-arm64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-darwin-arm64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-darwin-arm64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-darwin-arm64": + optional: true + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-darwin-x64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-darwin-x64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-darwin-x64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-darwin-x64": + optional: true + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@img/sharp-libvips-darwin-arm64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-darwin-arm64@npm:1.1.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-libvips-darwin-x64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-darwin-x64@npm:1.1.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-arm64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linux-arm64@npm:1.1.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-arm@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linux-arm@npm:1.1.0" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-ppc64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linux-ppc64@npm:1.1.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-s390x@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linux-s390x@npm:1.1.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-x64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linux-x64@npm:1.1.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linuxmusl-arm64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linuxmusl-arm64@npm:1.1.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-libvips-linuxmusl-x64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linuxmusl-x64@npm:1.1.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-linux-arm64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linux-arm64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linux-arm64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linux-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-arm@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linux-arm@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linux-arm": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linux-arm": + optional: true + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-s390x@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linux-s390x@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linux-s390x": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linux-s390x": + optional: true + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-x64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linux-x64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linux-x64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linux-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linuxmusl-arm64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linuxmusl-arm64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-linuxmusl-x64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linuxmusl-x64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linuxmusl-x64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-wasm32@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-wasm32@npm:0.34.2" + dependencies: + "@emnapi/runtime": "npm:^1.4.3" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@img/sharp-win32-arm64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-win32-arm64@npm:0.34.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-win32-ia32@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-win32-ia32@npm:0.34.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@img/sharp-win32-x64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-win32-x64@npm:0.34.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -2003,13 +2201,6 @@ __metadata: languageName: node linkType: hard -"b4a@npm:^1.6.4": - version: 1.6.7 - resolution: "b4a@npm:1.6.7" - checksum: 10/1ac056e3bce378d4d3e570e57319360a9d3125ab6916a1921b95bea33d9ee646698ebc75467561fd6fcc80ff697612124c89bb9b95e80db94c6dc23fcb977705 - languageName: node - linkType: hard - "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -2024,62 +2215,6 @@ __metadata: languageName: node linkType: hard -"bare-events@npm:^2.2.0, bare-events@npm:^2.5.4": - version: 2.5.4 - resolution: "bare-events@npm:2.5.4" - checksum: 10/135ef380b13f554ca2c6905bdbcfac8edae08fce85b7f953fa01f09a9f5b0da6a25e414111659bc9a6118216f0dd1f732016acd11ce91517f2afb26ebeb4b721 - languageName: node - linkType: hard - -"bare-fs@npm:^4.0.1": - version: 4.1.2 - resolution: "bare-fs@npm:4.1.2" - dependencies: - bare-events: "npm:^2.5.4" - bare-path: "npm:^3.0.0" - bare-stream: "npm:^2.6.4" - peerDependencies: - bare-buffer: "*" - peerDependenciesMeta: - bare-buffer: - optional: true - checksum: 10/e64d22d0311a71a23919e33b8f1c2ea9f5a6260c468c9c70bdd248efdf356b4d5a36754d5f502f526ca5ff5544a780afdd73cd66fcc38ba00003e99287a69f37 - languageName: node - linkType: hard - -"bare-os@npm:^3.0.1": - version: 3.6.1 - resolution: "bare-os@npm:3.6.1" - checksum: 10/285d95c391250166128e64da2947f4a348ae127de680afffec1f6c82445856be0d1f259672b471afe06517e4cd3831183c373a1d63ef7799ed4aaa1321b86b67 - languageName: node - linkType: hard - -"bare-path@npm:^3.0.0": - version: 3.0.0 - resolution: "bare-path@npm:3.0.0" - dependencies: - bare-os: "npm:^3.0.1" - checksum: 10/712d90e9cd8c3263cc11b0e0d386d1531a452706d7840c081ee586b34b00d72544e65df7a40013d47c1b177277495225deeede65cb2984db88a979cb65aaa2ff - languageName: node - linkType: hard - -"bare-stream@npm:^2.6.4": - version: 2.6.5 - resolution: "bare-stream@npm:2.6.5" - dependencies: - streamx: "npm:^2.21.0" - peerDependencies: - bare-buffer: "*" - bare-events: "*" - peerDependenciesMeta: - bare-buffer: - optional: true - bare-events: - optional: true - checksum: 10/0f5ca2167fbbccc118157bce7c53a933e21726268e03d751461211550d72b2d01c296b767ccf96aae8ab28e106b126407c6fe0d29f915734b844ffe6057f0a08 - languageName: node - linkType: hard - "base64-js@npm:^1.3.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -2137,7 +2272,6 @@ __metadata: imagemin-jpegtran: "npm:^7.0.0" imagemin-optipng: "npm:^8.0.0" imagemin-svgo: "npm:^10.0.1" - lazysizes: "npm:^5.3.2" mini-css-extract-plugin: "npm:^1.5.0" oneloop.js: "npm:^5.2.1" postcss: "npm:^8.4.24" @@ -2150,7 +2284,7 @@ __metadata: prettier: "npm:^2.2.1" sass: "npm:^1.85.1" sass-loader: "npm:^16.0.5" - sharp: "npm:^0.32.1" + sharp: "npm:^0.34.2" style-loader: "npm:^2.0.0" stylelint: "npm:^14.13.0" stylelint-config-recess-order: "npm:^3.0.0" @@ -2244,17 +2378,6 @@ __metadata: languageName: node linkType: hard -"bl@npm:^4.0.3": - version: 4.1.0 - resolution: "bl@npm:4.1.0" - dependencies: - buffer: "npm:^5.5.0" - inherits: "npm:^2.0.4" - readable-stream: "npm:^3.4.0" - checksum: 10/b7904e66ed0bdfc813c06ea6c3e35eafecb104369dbf5356d0f416af90c1546de3b74e5b63506f0629acf5e16a6f87c3798f16233dcff086e9129383aa02ab55 - languageName: node - linkType: hard - "bluebird@npm:^3.5.0": version: 3.7.2 resolution: "bluebird@npm:3.7.2" @@ -2367,7 +2490,7 @@ __metadata: languageName: node linkType: hard -"buffer@npm:^5.2.1, buffer@npm:^5.5.0": +"buffer@npm:^5.2.1": version: 5.7.1 resolution: "buffer@npm:5.7.1" dependencies: @@ -2638,13 +2761,6 @@ __metadata: languageName: node linkType: hard -"chownr@npm:^1.1.1": - version: 1.1.4 - resolution: "chownr@npm:1.1.4" - checksum: 10/115648f8eb38bac5e41c3857f3e663f9c39ed6480d1349977c4d96c95a47266fcacc5a5aabf3cb6c481e22d72f41992827db47301851766c4fd77ac21a4f081d - languageName: node - linkType: hard - "chownr@npm:^3.0.0": version: 3.0.0 resolution: "chownr@npm:3.0.0" @@ -3373,15 +3489,6 @@ __metadata: languageName: node linkType: hard -"decompress-response@npm:^6.0.0": - version: 6.0.0 - resolution: "decompress-response@npm:6.0.0" - dependencies: - mimic-response: "npm:^3.1.0" - checksum: 10/d377cf47e02d805e283866c3f50d3d21578b779731e8c5072d6ce8c13cc31493db1c2f6784da9d1d5250822120cefa44f1deab112d5981015f2e17444b763812 - languageName: node - linkType: hard - "decompress-tar@npm:^4.0.0, decompress-tar@npm:^4.1.0, decompress-tar@npm:^4.1.1": version: 4.1.1 resolution: "decompress-tar@npm:4.1.1" @@ -3445,13 +3552,6 @@ __metadata: languageName: node linkType: hard -"deep-extend@npm:^0.6.0": - version: 0.6.0 - resolution: "deep-extend@npm:0.6.0" - checksum: 10/7be7e5a8d468d6b10e6a67c3de828f55001b6eb515d014f7aeb9066ce36bd5717161eb47d6a0f7bed8a9083935b465bc163ee2581c8b128d29bf61092fdf57a7 - languageName: node - linkType: hard - "deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -3547,10 +3647,10 @@ __metadata: languageName: node linkType: hard -"detect-libc@npm:^2.0.0, detect-libc@npm:^2.0.2": - version: 2.0.3 - resolution: "detect-libc@npm:2.0.3" - checksum: 10/b4ea018d623e077bd395f168a9e81db77370dde36a5b01d067f2ad7989924a81d31cb547ff764acb2aa25d50bb7fdde0b0a93bec02212b0cb430621623246d39 +"detect-libc@npm:^2.0.4": + version: 2.0.4 + resolution: "detect-libc@npm:2.0.4" + checksum: 10/136e995f8c5ffbc515955b0175d441b967defd3d5f2268e89fa695e9c7170d8bed17993e31a34b04f0fad33d844a3a598e0fd519a8e9be3cad5f67662d96fee0 languageName: node linkType: hard @@ -3809,7 +3909,7 @@ __metadata: languageName: node linkType: hard -"end-of-stream@npm:^1.0.0, end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": +"end-of-stream@npm:^1.0.0, end-of-stream@npm:^1.1.0": version: 1.4.4 resolution: "end-of-stream@npm:1.4.4" dependencies: @@ -4436,13 +4536,6 @@ __metadata: languageName: node linkType: hard -"expand-template@npm:^2.0.3": - version: 2.0.3 - resolution: "expand-template@npm:2.0.3" - checksum: 10/588c19847216421ed92befb521767b7018dc88f88b0576df98cb242f20961425e96a92cbece525ef28cc5becceae5d544ae0f5b9b5e2aa05acb13716ca5b3099 - languageName: node - linkType: hard - "exponential-backoff@npm:^3.1.1": version: 3.1.2 resolution: "exponential-backoff@npm:3.1.2" @@ -4518,13 +4611,6 @@ __metadata: languageName: node linkType: hard -"fast-fifo@npm:^1.2.0, fast-fifo@npm:^1.3.2": - version: 1.3.2 - resolution: "fast-fifo@npm:1.3.2" - checksum: 10/6bfcba3e4df5af7be3332703b69a7898a8ed7020837ec4395bb341bd96cc3a6d86c3f6071dd98da289618cf2234c70d84b2a6f09a33dd6f988b1ff60d8e54275 - languageName: node - linkType: hard - "fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.7, fast-glob@npm:^3.2.9": version: 3.3.3 resolution: "fast-glob@npm:3.3.3" @@ -5049,13 +5135,6 @@ __metadata: languageName: node linkType: hard -"github-from-package@npm:0.0.0": - version: 0.0.0 - resolution: "github-from-package@npm:0.0.0" - checksum: 10/2a091ba07fbce22205642543b4ea8aaf068397e1433c00ae0f9de36a3607baf5bcc14da97fbb798cfca6393b3c402031fca06d8b491a44206d6efef391c58537 - languageName: node - linkType: hard - "glob-parent@npm:^5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" @@ -5792,14 +5871,14 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10/cd45e923bee15186c07fa4c89db0aace24824c482fb887b528304694b2aa6ff8a898da8657046a5dcf3e46cd6db6c61629551f9215f208d7c3f157cf9b290521 languageName: node linkType: hard -"ini@npm:^1.3.4, ini@npm:^1.3.5, ini@npm:~1.3.0": +"ini@npm:^1.3.4, ini@npm:^1.3.5": version: 1.3.8 resolution: "ini@npm:1.3.8" checksum: 10/314ae176e8d4deb3def56106da8002b462221c174ddb7ce0c49ee72c8cd1f9044f7b10cc555a7d8850982c3b9ca96fc212122749f5234bc2b6fb05fb942ed566 @@ -6624,13 +6703,6 @@ __metadata: languageName: node linkType: hard -"lazysizes@npm:^5.3.2": - version: 5.3.2 - resolution: "lazysizes@npm:5.3.2" - checksum: 10/15dfa1cc8bf8c3a4393014d411f161cb1df96ab0888a0776ba4dc34d45c6ba9c5d2b2eca22683c14dfeee552c67173cb9a512d640d3424d9910c0246e15c4edc - languageName: node - linkType: hard - "levn@npm:^0.4.1": version: 0.4.1 resolution: "levn@npm:0.4.1" @@ -7106,13 +7178,6 @@ __metadata: languageName: node linkType: hard -"mimic-response@npm:^3.1.0": - version: 3.1.0 - resolution: "mimic-response@npm:3.1.0" - checksum: 10/7e719047612411fe071332a7498cf0448bbe43c485c0d780046c76633a771b223ff49bd00267be122cedebb897037fdb527df72335d0d0f74724604ca70b37ad - languageName: node - linkType: hard - "min-indent@npm:^1.0.0": version: 1.0.1 resolution: "min-indent@npm:1.0.1" @@ -7162,7 +7227,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.1.3, minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.6": +"minimist@npm:^1.1.3, minimist@npm:^1.2.0, minimist@npm:^1.2.6": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 10/908491b6cc15a6c440ba5b22780a0ba89b9810e1aea684e253e43c4e3b8d56ec1dcdd7ea96dde119c29df59c936cde16062159eae4225c691e19c70b432b6e6f @@ -7262,13 +7327,6 @@ __metadata: languageName: node linkType: hard -"mkdirp-classic@npm:^0.5.2, mkdirp-classic@npm:^0.5.3": - version: 0.5.3 - resolution: "mkdirp-classic@npm:0.5.3" - checksum: 10/3f4e088208270bbcc148d53b73e9a5bd9eef05ad2cbf3b3d0ff8795278d50dd1d11a8ef1875ff5aea3fa888931f95bfcb2ad5b7c1061cfefd6284d199e6776ac - languageName: node - linkType: hard - "mkdirp@npm:^3.0.1": version: 3.0.1 resolution: "mkdirp@npm:3.0.1" @@ -7341,13 +7399,6 @@ __metadata: languageName: node linkType: hard -"napi-build-utils@npm:^2.0.0": - version: 2.0.0 - resolution: "napi-build-utils@npm:2.0.0" - checksum: 10/69adcdb828481737f1ec64440286013f6479d5b264e24d5439ba795f65293d0bb6d962035de07c65fae525ed7d2fcd0baab6891d8e3734ea792fec43918acf83 - languageName: node - linkType: hard - "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -7386,24 +7437,6 @@ __metadata: languageName: node linkType: hard -"node-abi@npm:^3.3.0": - version: 3.74.0 - resolution: "node-abi@npm:3.74.0" - dependencies: - semver: "npm:^7.3.5" - checksum: 10/314ba5f773690e12a3d87b967d509e9badf16bf2a8ba7619104794f9594545dd268a42f34817d3c81402bf1dc6308545456e2fa9c0200bb6e648cfb75addbe66 - languageName: node - linkType: hard - -"node-addon-api@npm:^6.1.0": - version: 6.1.0 - resolution: "node-addon-api@npm:6.1.0" - dependencies: - node-gyp: "npm:latest" - checksum: 10/8eea1d4d965930a177a0508695beb0d89b4c1d80bf330646a035357a1e8fc31e0d09686e2374996e96e757b947a7ece319f98ede3146683f162597c0bcb4df90 - languageName: node - linkType: hard - "node-addon-api@npm:^7.0.0": version: 7.1.1 resolution: "node-addon-api@npm:7.1.1" @@ -9016,28 +9049,6 @@ __metadata: languageName: node linkType: hard -"prebuild-install@npm:^7.1.1": - version: 7.1.3 - resolution: "prebuild-install@npm:7.1.3" - dependencies: - detect-libc: "npm:^2.0.0" - expand-template: "npm:^2.0.3" - github-from-package: "npm:0.0.0" - minimist: "npm:^1.2.3" - mkdirp-classic: "npm:^0.5.3" - napi-build-utils: "npm:^2.0.0" - node-abi: "npm:^3.3.0" - pump: "npm:^3.0.0" - rc: "npm:^1.2.7" - simple-get: "npm:^4.0.0" - tar-fs: "npm:^2.0.0" - tunnel-agent: "npm:^0.6.0" - bin: - prebuild-install: bin.js - checksum: 10/1b7e4c00d2750b532a4fc2a83ffb0c5fefa1b6f2ad071896ead15eeadc3255f5babd816949991af083cf7429e375ae8c7d1c51f73658559da36f948a020a3a11 - languageName: node - linkType: hard - "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -9199,20 +9210,6 @@ __metadata: languageName: node linkType: hard -"rc@npm:^1.2.7": - version: 1.2.8 - resolution: "rc@npm:1.2.8" - dependencies: - deep-extend: "npm:^0.6.0" - ini: "npm:~1.3.0" - minimist: "npm:^1.2.0" - strip-json-comments: "npm:~2.0.1" - bin: - rc: ./cli.js - checksum: 10/5c4d72ae7eec44357171585938c85ce066da8ca79146b5635baf3d55d74584c92575fa4e2c9eac03efbed3b46a0b2e7c30634c012b4b4fa40d654353d3c163eb - languageName: node - linkType: hard - "react-dom@npm:^17.0.2": version: 17.0.2 resolution: "react-dom@npm:17.0.2" @@ -9315,7 +9312,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0": +"readable-stream@npm:^3.1.1": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -9888,6 +9885,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.2": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: 10/7a24cffcaa13f53c09ce55e05efe25cd41328730b2308678624f8b9f5fc3093fc4d189f47950f0b811ff8f3c3039c24a2c36717ba7961615c682045bf03e1dda + languageName: node + linkType: hard + "sentence-case@npm:^3.0.4": version: 3.0.4 resolution: "sentence-case@npm:3.0.4" @@ -9980,20 +9986,78 @@ __metadata: languageName: node linkType: hard -"sharp@npm:^0.32.1": - version: 0.32.6 - resolution: "sharp@npm:0.32.6" - dependencies: +"sharp@npm:^0.34.2": + version: 0.34.2 + resolution: "sharp@npm:0.34.2" + dependencies: + "@img/sharp-darwin-arm64": "npm:0.34.2" + "@img/sharp-darwin-x64": "npm:0.34.2" + "@img/sharp-libvips-darwin-arm64": "npm:1.1.0" + "@img/sharp-libvips-darwin-x64": "npm:1.1.0" + "@img/sharp-libvips-linux-arm": "npm:1.1.0" + "@img/sharp-libvips-linux-arm64": "npm:1.1.0" + "@img/sharp-libvips-linux-ppc64": "npm:1.1.0" + "@img/sharp-libvips-linux-s390x": "npm:1.1.0" + "@img/sharp-libvips-linux-x64": "npm:1.1.0" + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.1.0" + "@img/sharp-libvips-linuxmusl-x64": "npm:1.1.0" + "@img/sharp-linux-arm": "npm:0.34.2" + "@img/sharp-linux-arm64": "npm:0.34.2" + "@img/sharp-linux-s390x": "npm:0.34.2" + "@img/sharp-linux-x64": "npm:0.34.2" + "@img/sharp-linuxmusl-arm64": "npm:0.34.2" + "@img/sharp-linuxmusl-x64": "npm:0.34.2" + "@img/sharp-wasm32": "npm:0.34.2" + "@img/sharp-win32-arm64": "npm:0.34.2" + "@img/sharp-win32-ia32": "npm:0.34.2" + "@img/sharp-win32-x64": "npm:0.34.2" color: "npm:^4.2.3" - detect-libc: "npm:^2.0.2" - node-addon-api: "npm:^6.1.0" - node-gyp: "npm:latest" - prebuild-install: "npm:^7.1.1" - semver: "npm:^7.5.4" - simple-get: "npm:^4.0.1" - tar-fs: "npm:^3.0.4" - tunnel-agent: "npm:^0.6.0" - checksum: 10/f0e4a86881e590f86b05ea463229f62cd29afc2dca08b3f597889f872f118c2c456f382bf2c3e90e934b7a1d30f109cf5ed584cf5a23e79d6b6403a8dc0ebe32 + detect-libc: "npm:^2.0.4" + semver: "npm:^7.7.2" + dependenciesMeta: + "@img/sharp-darwin-arm64": + optional: true + "@img/sharp-darwin-x64": + optional: true + "@img/sharp-libvips-darwin-arm64": + optional: true + "@img/sharp-libvips-darwin-x64": + optional: true + "@img/sharp-libvips-linux-arm": + optional: true + "@img/sharp-libvips-linux-arm64": + optional: true + "@img/sharp-libvips-linux-ppc64": + optional: true + "@img/sharp-libvips-linux-s390x": + optional: true + "@img/sharp-libvips-linux-x64": + optional: true + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + "@img/sharp-libvips-linuxmusl-x64": + optional: true + "@img/sharp-linux-arm": + optional: true + "@img/sharp-linux-arm64": + optional: true + "@img/sharp-linux-s390x": + optional: true + "@img/sharp-linux-x64": + optional: true + "@img/sharp-linuxmusl-arm64": + optional: true + "@img/sharp-linuxmusl-x64": + optional: true + "@img/sharp-wasm32": + optional: true + "@img/sharp-win32-arm64": + optional: true + "@img/sharp-win32-ia32": + optional: true + "@img/sharp-win32-x64": + optional: true + checksum: 10/8c7a6f20d58849a6e33bc69c4525f471d57eb3dea0072331b55ab12bae4b8bd8b99b65264aeaec38e54d52d692db13e3261f6e7bc29430b39b507c409838cbb0 languageName: node linkType: hard @@ -10109,24 +10173,6 @@ __metadata: languageName: node linkType: hard -"simple-concat@npm:^1.0.0": - version: 1.0.1 - resolution: "simple-concat@npm:1.0.1" - checksum: 10/4d211042cc3d73a718c21ac6c4e7d7a0363e184be6a5ad25c8a1502e49df6d0a0253979e3d50dbdd3f60ef6c6c58d756b5d66ac1e05cda9cacd2e9fc59e3876a - languageName: node - linkType: hard - -"simple-get@npm:^4.0.0, simple-get@npm:^4.0.1": - version: 4.0.1 - resolution: "simple-get@npm:4.0.1" - dependencies: - decompress-response: "npm:^6.0.0" - once: "npm:^1.3.1" - simple-concat: "npm:^1.0.0" - checksum: 10/93f1b32319782f78f2f2234e9ce34891b7ab6b990d19d8afefaa44423f5235ce2676aae42d6743fecac6c8dfff4b808d4c24fe5265be813d04769917a9a44f36 - languageName: node - linkType: hard - "simple-html-tokenizer@npm:^0.5.7": version: 0.5.11 resolution: "simple-html-tokenizer@npm:0.5.11" @@ -10446,20 +10492,6 @@ __metadata: languageName: node linkType: hard -"streamx@npm:^2.15.0, streamx@npm:^2.21.0": - version: 2.22.0 - resolution: "streamx@npm:2.22.0" - dependencies: - bare-events: "npm:^2.2.0" - fast-fifo: "npm:^1.3.2" - text-decoder: "npm:^1.1.0" - dependenciesMeta: - bare-events: - optional: true - checksum: 10/9c329bb316e2085e207e471ecd0da18b4ed5b1cfe5cf10e9e7fad3f8f50c6ca1a6a844bdfd9bc7521560b97f229890de82ca162a0e66115300b91a489b1cbefd - languageName: node - linkType: hard - "strict-uri-encode@npm:^1.0.0": version: 1.1.0 resolution: "strict-uri-encode@npm:1.1.0" @@ -10651,13 +10683,6 @@ __metadata: languageName: node linkType: hard -"strip-json-comments@npm:~2.0.1": - version: 2.0.1 - resolution: "strip-json-comments@npm:2.0.1" - checksum: 10/1074ccb63270d32ca28edfb0a281c96b94dc679077828135141f27d52a5a398ef5e78bcf22809d23cadc2b81dfbe345eb5fd8699b385c8b1128907dec4a7d1e1 - languageName: node - linkType: hard - "strip-outer@npm:^1.0.0": version: 1.0.1 resolution: "strip-outer@npm:1.0.1" @@ -11035,35 +11060,6 @@ __metadata: languageName: node linkType: hard -"tar-fs@npm:^2.0.0": - version: 2.1.2 - resolution: "tar-fs@npm:2.1.2" - dependencies: - chownr: "npm:^1.1.1" - mkdirp-classic: "npm:^0.5.2" - pump: "npm:^3.0.0" - tar-stream: "npm:^2.1.4" - checksum: 10/623f7e8e58a43578ba7368002c3cc7e321f6d170053ac0691d95172dbc7daf5dcf4347eb061277627340870ce6cfda89f5a5d633cc274c41ae6d69f54a2374e7 - languageName: node - linkType: hard - -"tar-fs@npm:^3.0.4": - version: 3.0.8 - resolution: "tar-fs@npm:3.0.8" - dependencies: - bare-fs: "npm:^4.0.1" - bare-path: "npm:^3.0.0" - pump: "npm:^3.0.0" - tar-stream: "npm:^3.1.5" - dependenciesMeta: - bare-fs: - optional: true - bare-path: - optional: true - checksum: 10/fdcd1c66dc5e2cad5544ffe7eab9a470b419290b22300c344688df51bf06127963da07a1e3ae23cae80851cd9f60149e80b38e56485dd7a14aea701241ac2f81 - languageName: node - linkType: hard - "tar-stream@npm:^1.5.2": version: 1.6.2 resolution: "tar-stream@npm:1.6.2" @@ -11079,30 +11075,6 @@ __metadata: languageName: node linkType: hard -"tar-stream@npm:^2.1.4": - version: 2.2.0 - resolution: "tar-stream@npm:2.2.0" - dependencies: - bl: "npm:^4.0.3" - end-of-stream: "npm:^1.4.1" - fs-constants: "npm:^1.0.0" - inherits: "npm:^2.0.3" - readable-stream: "npm:^3.1.1" - checksum: 10/1a52a51d240c118cbcd30f7368ea5e5baef1eac3e6b793fb1a41e6cd7319296c79c0264ccc5859f5294aa80f8f00b9239d519e627b9aade80038de6f966fec6a - languageName: node - linkType: hard - -"tar-stream@npm:^3.1.5": - version: 3.1.7 - resolution: "tar-stream@npm:3.1.7" - dependencies: - b4a: "npm:^1.6.4" - fast-fifo: "npm:^1.2.0" - streamx: "npm:^2.15.0" - checksum: 10/b21a82705a72792544697c410451a4846af1f744176feb0ff11a7c3dd0896961552e3def5e1c9a6bbee4f0ae298b8252a1f4c9381e9f991553b9e4847976f05c - languageName: node - linkType: hard - "tar@npm:^7.4.3": version: 7.4.3 resolution: "tar@npm:7.4.3" @@ -11170,15 +11142,6 @@ __metadata: languageName: node linkType: hard -"text-decoder@npm:^1.1.0": - version: 1.2.3 - resolution: "text-decoder@npm:1.2.3" - dependencies: - b4a: "npm:^1.6.4" - checksum: 10/bcdec33c0f070aeac38e46e4cafdcd567a58473ed308bdf75260bfbd8f7dc76acbc0b13226afaec4a169d0cb44cec2ab89c57b6395ccf02e941eaebbe19e124a - languageName: node - linkType: hard - "text-table@npm:^0.2.0": version: 0.2.0 resolution: "text-table@npm:0.2.0" @@ -11331,7 +11294,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.3, tslib@npm:^2.1.0": +"tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.4.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10/3e2e043d5c2316461cb54e5c7fe02c30ef6dccb3384717ca22ae5c6b5bc95232a6241df19c622d9c73b809bea33b187f6dbc73030963e29950c2141bc32a79f7