cloudinary-core
Version:
Cloudinary Client Side JS library. Cloudinary streamlines your web application’s image manipulation needs. Cloudinary's cloud-based servers automate image uploading, resizing, cropping, optimizing, sprite generation and more.
150 lines (134 loc) • 5.06 kB
JavaScript
import * as utils from '../util';
const isEmpty = utils.isEmpty;
import generateBreakpoints from './generateBreakpoints';
import Transformation from '../transformation';
import url from '../url';
/**
* Options used to generate the srcset attribute.
* @typedef {object} srcset
* @property {(number[]|string[])} [breakpoints] An array of breakpoints.
* @property {number} [min_width] Minimal width of the srcset images.
* @property {number} [max_width] Maximal width of the srcset images.
* @property {number} [max_images] Number of srcset images to generate.
* @property {object|string} [transformation] The transformation to use in the srcset urls.
* @property {boolean} [sizes] Whether to calculate and add the sizes attribute.
*/
/**
* Helper function. Generates a single srcset item url
*
* @private
* @param {string} public_id Public ID of the resource.
* @param {number} width Width in pixels of the srcset item.
* @param {object|string} transformation
* @param {object} options Additional options.
*
* @return {string} Resulting URL of the item
*/
export function scaledUrl(public_id, width, transformation, options = {}) {
let configParams = utils.extractUrlParams(options);
transformation = transformation || options;
configParams.raw_transformation = new Transformation([utils.merge({}, transformation), {
crop: 'scale',
width: width
}]).toString();
return url(public_id, configParams);
}
/**
* If cache is enabled, get the breakpoints from the cache. If the values were not found in the cache,
* or cache is not enabled, generate the values.
* @param {srcset} srcset The srcset configuration parameters
* @param {string} public_id
* @param {object} options
* @return {*|Array}
*/
export function getOrGenerateBreakpoints(public_id, srcset = {}, options = {}) {
return generateBreakpoints(srcset);
}
/**
* Helper function. Generates srcset attribute value of the HTML img tag
* @private
*
* @param {string} public_id Public ID of the resource
* @param {number[]} breakpoints An array of breakpoints (in pixels)
* @param {object} transformation The transformation
* @param {object} options Includes html tag options, transformation options
* @return {string} Resulting srcset attribute value
*/
export function generateSrcsetAttribute(public_id, breakpoints, transformation, options) {
options = utils.cloneDeep(options);
utils.patchFetchFormat(options);
return breakpoints.map(width => `${scaledUrl(public_id, width, transformation, options)} ${width}w`).join(', ');
}
/**
* Helper function. Generates sizes attribute value of the HTML img tag
* @private
* @param {number[]} breakpoints An array of breakpoints.
* @return {string} Resulting sizes attribute value
*/
export function generateSizesAttribute(breakpoints) {
if (breakpoints == null) {
return '';
}
return breakpoints.map(width => `(max-width: ${width}px) ${width}px`).join(', ');
}
/**
* Helper function. Generates srcset and sizes attributes of the image tag
*
* Generated attributes are added to attributes argument
*
* @private
* @param {string} publicId The public ID of the resource
* @param {object} attributes Existing HTML attributes.
* @param {srcset} srcsetData
* @param {object} options Additional options.
*
* @return array The responsive attributes
*/
export function generateImageResponsiveAttributes(publicId, attributes = {}, srcsetData = {}, options = {}) {
// Create both srcset and sizes here to avoid fetching breakpoints twice
let responsiveAttributes = {};
if (isEmpty(srcsetData)) {
return responsiveAttributes;
}
const generateSizes = (!attributes.sizes && srcsetData.sizes === true);
const generateSrcset = !attributes.srcset;
if (generateSrcset || generateSizes) {
let breakpoints = getOrGenerateBreakpoints(publicId, srcsetData, options);
if (generateSrcset) {
let transformation = srcsetData.transformation;
let srcsetAttr = generateSrcsetAttribute(publicId, breakpoints, transformation, options);
if (!isEmpty(srcsetAttr)) {
responsiveAttributes.srcset = srcsetAttr;
}
}
if (generateSizes) {
let sizesAttr = generateSizesAttribute(breakpoints);
if (!isEmpty(sizesAttr)) {
responsiveAttributes.sizes = sizesAttr;
}
}
}
return responsiveAttributes;
}
/**
* Generate a media query
*
* @private
* @param {object} options configuration options
* @param {number|string} options.min_width
* @param {number|string} options.max_width
* @return {string} a media query string
*/
export function generateMediaAttr(options) {
let mediaQuery = [];
if (options != null) {
if (options.min_width != null) {
mediaQuery.push(`(min-width: ${options.min_width}px)`);
}
if (options.max_width != null) {
mediaQuery.push(`(max-width: ${options.max_width}px)`);
}
}
return mediaQuery.join(' and ');
}
export const srcsetUrl = scaledUrl;