@sanity/image-url
Version:
Tools to generate image urls from Sanity content
180 lines • 7.08 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var parseAssetId_1 = __importDefault(require("./parseAssetId"));
var parseSource_1 = __importDefault(require("./parseSource"));
exports.parseSource = parseSource_1.default;
exports.SPEC_NAME_TO_URL_NAME_MAPPINGS = [
['width', 'w'],
['height', 'h'],
['format', 'fm'],
['download', 'dl'],
['blur', 'blur'],
['sharpen', 'sharp'],
['invert', 'invert'],
['orientation', 'or'],
['minHeight', 'min-h'],
['maxHeight', 'max-h'],
['minWidth', 'min-w'],
['maxWidth', 'max-w'],
['quality', 'q'],
['fit', 'fit'],
['crop', 'crop'],
['auto', 'auto'],
['dpr', 'dpr']
];
function urlForImage(options) {
var spec = __assign({}, (options || {}));
var source = spec.source;
delete spec.source;
var image = parseSource_1.default(source);
if (!image) {
return null;
}
var id = image.asset._ref || image.asset._id || '';
var asset = parseAssetId_1.default(id);
// Compute crop rect in terms of pixel coordinates in the raw source image
var cropLeft = Math.round(image.crop.left * asset.width);
var cropTop = Math.round(image.crop.top * asset.height);
var crop = {
left: cropLeft,
top: cropTop,
width: Math.round(asset.width - image.crop.right * asset.width - cropLeft),
height: Math.round(asset.height - image.crop.bottom * asset.height - cropTop)
};
// Compute hot spot rect in terms of pixel coordinates
var hotSpotVerticalRadius = (image.hotspot.height * asset.height) / 2;
var hotSpotHorizontalRadius = (image.hotspot.width * asset.width) / 2;
var hotSpotCenterX = image.hotspot.x * asset.width;
var hotSpotCenterY = image.hotspot.y * asset.height;
var hotspot = {
left: hotSpotCenterX - hotSpotHorizontalRadius,
top: hotSpotCenterY - hotSpotVerticalRadius,
right: hotSpotCenterX + hotSpotHorizontalRadius,
bottom: hotSpotCenterY + hotSpotVerticalRadius
};
// If irrelevant, or if we are requested to: don't perform crop/fit based on
// the crop/hotspot.
if (!(spec.rect || spec.focalPoint || spec.ignoreImageParams || spec.crop)) {
spec = __assign({}, spec, fit({ crop: crop, hotspot: hotspot }, spec));
}
return specToImageUrl(__assign({}, spec, { asset: asset }));
}
exports.default = urlForImage;
// eslint-disable-next-line complexity
function specToImageUrl(spec) {
var cdnUrl = spec.baseUrl || 'https://cdn.sanity.io';
var filename = spec.asset.id + "-" + spec.asset.width + "x" + spec.asset.height + "." + spec.asset.format;
var baseUrl = cdnUrl + "/images/" + spec.projectId + "/" + spec.dataset + "/" + filename;
var params = [];
if (spec.rect) {
// Only bother url with a crop if it actually crops anything
var _a = spec.rect, left = _a.left, top_1 = _a.top, width = _a.width, height = _a.height;
var isEffectiveCrop = left !== 0 || top_1 !== 0 || height !== spec.asset.height || width !== spec.asset.width;
if (isEffectiveCrop) {
params.push("rect=" + left + "," + top_1 + "," + width + "," + height);
}
}
if (spec.bg) {
params.push("bg=" + spec.bg);
}
if (spec.focalPoint) {
params.push("fp-x=" + spec.focalPoint.x);
params.push("fp-x=" + spec.focalPoint.y);
}
var flip = [spec.flipHorizontal && 'h', spec.flipVertical && 'v'].filter(Boolean).join('');
if (flip) {
params.push("flip=" + flip);
}
// Map from spec name to url param name, and allow using the actual param name as an alternative
exports.SPEC_NAME_TO_URL_NAME_MAPPINGS.forEach(function (mapping) {
var specName = mapping[0], param = mapping[1];
if (typeof spec[specName] !== 'undefined') {
params.push(param + "=" + encodeURIComponent(spec[specName]));
}
else if (typeof spec[param] !== 'undefined') {
params.push(param + "=" + encodeURIComponent(spec[param]));
}
});
if (params.length === 0) {
return baseUrl;
}
return baseUrl + "?" + params.join('&');
}
function fit(source, spec) {
var cropRect;
var imgWidth = spec.width;
var imgHeight = spec.height;
// If we are not constraining the aspect ratio, we'll just use the whole crop
if (!(imgWidth && imgHeight)) {
return { width: imgWidth, height: imgHeight, rect: source.crop };
}
var crop = source.crop;
var hotspot = source.hotspot;
// If we are here, that means aspect ratio is locked and fitting will be a bit harder
var desiredAspectRatio = imgWidth / imgHeight;
var cropAspectRatio = crop.width / crop.height;
if (cropAspectRatio > desiredAspectRatio) {
// The crop is wider than the desired aspect ratio. That means we are cutting from the sides
var height = crop.height;
var width = height * desiredAspectRatio;
var top_2 = crop.top;
// Center output horizontally over hotspot
var hotspotXCenter = (hotspot.right - hotspot.left) / 2 + hotspot.left;
var left = hotspotXCenter - width / 2;
// Keep output within crop
if (left < crop.left) {
left = crop.left;
}
else if (left + width > crop.left + crop.width) {
left = crop.left + crop.width - width;
}
cropRect = {
left: Math.round(left),
top: Math.round(top_2),
width: Math.round(width),
height: Math.round(height)
};
}
else {
// The crop is taller than the desired ratio, we are cutting from top and bottom
var width = crop.width;
var height = width / desiredAspectRatio;
var left = crop.left;
// Center output vertically over hotspot
var hotspotYCenter = (hotspot.bottom - hotspot.top) / 2 + hotspot.top;
var top_3 = hotspotYCenter - height / 2;
// Keep output rect within crop
if (top_3 < crop.top) {
top_3 = crop.top;
}
else if (top_3 + height > crop.top + crop.height) {
top_3 = crop.top + crop.height - height;
}
cropRect = {
left: Math.max(0, Math.floor(left)),
top: Math.max(0, Math.floor(top_3)),
width: Math.round(width),
height: Math.round(height)
};
}
return {
width: imgWidth,
height: imgHeight,
rect: cropRect
};
}
//# sourceMappingURL=urlForImage.js.map