UNPKG

@sanity/image-url

Version:

Tools to generate image urls from Sanity content

180 lines 7.08 kB
"use strict"; 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