webpack-image-resize-loader
Version:
Webpack loader to resize imported images
148 lines • 6.22 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultFileLoaderOptionsGenerator = exports.raw = void 0;
const loader_utils_1 = require("loader-utils");
const schema_utils_1 = require("schema-utils");
const sharp_1 = __importDefault(require("sharp"));
const webpack_loader_util_1 = require("@calvin-l/webpack-loader-util");
const getFormat_1 = __importDefault(require("./helpers/getFormat"));
const options_json_1 = __importDefault(require("./options.json"));
exports.raw = true;
function default_1(content) {
const callback = this.async();
const defaultOptions = {
format: (0, getFormat_1.default)(this.resourcePath),
scaleUp: false,
sharpOptions: {
png: { compressionLevel: 9, adaptiveFiltering: true },
jpeg: { mozjpeg: true },
webp: { reductionEffort: 6 },
avif: { speed: 0 },
},
fileLoader: "file-loader",
fileLoaderOptionsGenerator: defaultFileLoaderOptionsGenerator,
};
const rawOptions = (0, webpack_loader_util_1.getOptions)(this, true, true);
const options = {
...defaultOptions,
sharpOptions: {
...defaultOptions.sharpOptions,
...rawOptions.sharpOptions,
},
...rawOptions,
};
(0, schema_utils_1.validate)(options_json_1.default, options, {
name: "Image Resize Loader",
baseDataPath: "options",
});
processImage(content, options)
.then((result) => replaceFileLoaderOptions(this, options, rawOptions).then(() => {
callback(null, result);
}))
.catch((error) => {
callback(error, undefined);
});
}
exports.default = default_1;
function defaultFileLoaderOptionsGenerator({ format }, existingOptions) {
let name = existingOptions === null || existingOptions === void 0 ? void 0 : existingOptions.name;
if (name === undefined) {
name = `[contenthash].${format}`;
}
else if (typeof name === "string") {
name = name.replace("[ext]", format);
}
else if (typeof name === "function") {
name = (file) => {
const nameFn = existingOptions.name;
return nameFn(file).replace("[ext]", format);
};
}
return {
...existingOptions,
name,
};
}
exports.defaultFileLoaderOptionsGenerator = defaultFileLoaderOptionsGenerator;
function resolveLoader(context, path) {
return new Promise((resolve, reject) => {
// get internal `enhanced-resolve` resolver
const resolver = context._compilation.resolverFactory.get("loader");
resolver.resolve({}, context.rootContext, path, {}, (err, resolvedResource) => {
if (err)
reject(err);
else
resolve(resolvedResource);
});
});
}
async function replaceFileLoaderOptions(context, options, rawOptions) {
const { fileLoader: fileLoaderName, fileLoaderOptionsGenerator } = options;
const loaders = context.loaders;
let fileLoaderNameOrPath = fileLoaderName;
// try to resolve path, if path not found, try to find by
// fileLoaderName directly
try {
fileLoaderNameOrPath = await resolveLoader(context, fileLoaderNameOrPath);
// eslint-disable-next-line no-empty
}
catch (e) { }
const fileLoader = loaders.find(({ path }, index) => index < context.loaderIndex && path === fileLoaderNameOrPath);
if (fileLoader === undefined) {
if (rawOptions.fileLoader !== undefined ||
rawOptions.fileLoaderOptionsGenerator !== undefined) {
// only throw when either fileLoader or fileLoaderOptionsGenerator is set
// don't want to throw if using url-loader for example
throw new Error(`Can't find "${fileLoaderName}" in the list of loaders before webpack-image-resize-loader`);
}
else {
return;
}
}
const fileLoaderOptions = typeof fileLoader.options === "string"
? (0, loader_utils_1.parseQuery)("?" + fileLoader.options)
: fileLoader.options;
if (typeof fileLoaderOptionsGenerator === "string")
fileLoader.options = eval(fileLoaderOptionsGenerator)(options, fileLoaderOptions);
else
fileLoader.options = fileLoaderOptionsGenerator(options, fileLoaderOptions);
}
async function processImage(content, { width, height, fit, position, background, scale, format, quality, scaleUp, sharpOptions, }) {
let sharpImage = (0, sharp_1.default)(Buffer.from(content));
const { height: imageHeight, width: imageWidth } = await sharpImage.metadata();
const normalizedImageHeight = imageHeight !== null && imageHeight !== void 0 ? imageHeight : Number.MAX_VALUE;
const normalizedImageWidth = imageWidth !== null && imageWidth !== void 0 ? imageWidth : Number.MAX_VALUE;
const normalizedResultHeight = height !== null && height !== void 0 ? height : 0;
const normalizedResultWidth = width !== null && width !== void 0 ? width : 0;
if ((width || height) &&
(scaleUp ||
(normalizedResultHeight <= normalizedImageHeight &&
normalizedResultWidth <= normalizedImageWidth)))
sharpImage = sharpImage.resize({
width,
height,
fit,
position,
background,
...sharpOptions === null || sharpOptions === void 0 ? void 0 : sharpOptions.resize,
});
else if (scale && (scaleUp || scale <= 1)) {
sharpImage = sharpImage.resize({
width: Math.round(normalizedImageWidth * scale),
fit,
position,
background,
...sharpOptions === null || sharpOptions === void 0 ? void 0 : sharpOptions.resize,
});
}
sharpImage = sharpImage[format]({
...(quality ? { quality } : {}),
...sharpOptions === null || sharpOptions === void 0 ? void 0 : sharpOptions[format],
});
const sharpImageOutput = await sharpImage.toBuffer();
return sharpImageOutput;
}
//# sourceMappingURL=index.js.map