-
Notifications
You must be signed in to change notification settings - Fork 221
/
Copy pathsrcsetUtils.js
149 lines (134 loc) · 4.94 KB
/
srcsetUtils.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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;