ted-crushinator-helpers
Advanced tools
Comparing version 2.7.0 to 2.8.0
# Changelog | ||
### 2.8.0 | ||
* Add a type definitions for TypeScript | ||
### 2.7.0 | ||
@@ -4,0 +8,0 @@ |
define('crushinator', ['exports'], function (exports) { 'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; | ||
}; | ||
function _typeof(obj) { | ||
"@babel/helpers - typeof"; | ||
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { | ||
_typeof = function (obj) { | ||
return typeof obj; | ||
}; | ||
} else { | ||
_typeof = function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; | ||
}; | ||
} | ||
return _typeof(obj); | ||
} | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
/** | ||
Wrapper methods for logging errors and other notices. | ||
*/ | ||
/** | ||
True if we can send messages to the console. | ||
*/ | ||
var isConsolable = (typeof console === "undefined" ? "undefined" : _typeof(console)) === 'object'; | ||
/** | ||
Throw an honest-to-goodness error. | ||
*/ | ||
function error(message) { | ||
throw new Error(message); | ||
} | ||
/** | ||
Display a warning without throwing a script-halting error. | ||
*/ | ||
function warn(message) { | ||
if (isConsolable && typeof console.warn === 'function') { | ||
console.warn(message); | ||
} | ||
} | ||
/** | ||
Methods used to prepare Crushinator option values for parameterization, | ||
mostly concerning typecasting and type-checking with application of | ||
default values. | ||
*/ | ||
/** | ||
Returns true if the value is undefined, null, or false. | ||
@param {*} value - Value to test for emptiness. | ||
@returns {boolean} | ||
*/ | ||
function isBlank(value) { | ||
return typeof value === 'undefined' || value === null || value === false; | ||
} | ||
/** | ||
Prepare a boolean value. | ||
@param {*} value - Value that should be typecast as a boolean. | ||
@returns {boolean} | ||
*/ | ||
function prepBoolean(value) { | ||
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
return typeof value === 'undefined' ? defaultValue : !!value; | ||
} | ||
/** | ||
Prepare a numerical value. | ||
@param {*} value - Value that should be typecast as a number. | ||
@returns {number} | ||
*/ | ||
function prepNumber(value) { | ||
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | ||
var outgoing = value; // Boolean true evaluates to 1 numerically | ||
if (value === true) { | ||
outgoing = defaultValue || 1; | ||
} | ||
if (isBlank(value)) { | ||
outgoing = defaultValue; | ||
} // Cast values numerically | ||
var _extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
outgoing = Number(outgoing); | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
if (!isFinite(outgoing)) { | ||
error("\"".concat(value, "\" is not a finite number")); | ||
outgoing = defaultValue; | ||
} | ||
} | ||
return target; | ||
}; | ||
/** | ||
Wrapper methods for logging errors and other notices. | ||
*/ | ||
/** | ||
True if we can send messages to the console. | ||
*/ | ||
var isConsolable = (typeof console === 'undefined' ? 'undefined' : _typeof(console)) === 'object'; | ||
/** | ||
Throw an honest-to-goodness error. | ||
*/ | ||
function error$1(message) { | ||
throw new Error(message); | ||
} | ||
/** | ||
Display a warning without throwing a script-halting error. | ||
*/ | ||
function warn(message) { | ||
if (isConsolable && typeof console.warn === 'function') { | ||
console.warn(message); | ||
return outgoing; | ||
} | ||
} | ||
/** | ||
Methods used to prepare Crushinator option values for parameterization, | ||
mostly concerning typecasting and type-checking with application of | ||
default values. | ||
*/ | ||
/** | ||
Default Crushinator helper options. | ||
*/ | ||
/** | ||
Returns true if the value is undefined, null, or false. | ||
var defaultOptions = { | ||
fit: true, | ||
unsharp: true, | ||
quality: 82 | ||
}; | ||
/** | ||
Given a list of options returns those options seeded with the defaults | ||
specified above unless the "defaults" option is set to false. | ||
@param {*} value - Value to test for emptiness. | ||
@returns {boolean} | ||
*/ | ||
function isBlank(value) { | ||
return typeof value === 'undefined' || value === null || value === false; | ||
} | ||
@param {Object} [options] - Incoming Crushinator helper options. | ||
@returns {Object} | ||
*/ | ||
/** | ||
Prepare a boolean value. | ||
@param {*} value - Value that should be typecast as a boolean. | ||
@returns {boolean} | ||
*/ | ||
function prepBoolean(value) { | ||
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
return typeof value === 'undefined' ? defaultValue : !!value; | ||
} | ||
/** | ||
Prepare a numerical value. | ||
@param {*} value - Value that should be typecast as a number. | ||
@returns {number} | ||
*/ | ||
function prepNumber(value) { | ||
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | ||
var outgoing = value; | ||
// Boolean true evaluates to 1 numerically | ||
if (value === true) { | ||
outgoing = defaultValue || 1; | ||
function defaultify() { | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
return _extends({}, prepBoolean(options.defaults, true) ? defaultOptions : {}, options); | ||
} | ||
if (isBlank(value)) { | ||
outgoing = defaultValue; | ||
/** | ||
Given an options object, returns a parameters object with crop | ||
parameters included according to the specified options. | ||
*/ | ||
function param(cropOptions) { | ||
return cropOptions.afterResize ? 'c' : 'precrop'; | ||
} | ||
function filter(cropOptions) { | ||
var data = []; | ||
data.push(prepNumber(cropOptions.width)); | ||
data.push(prepNumber(cropOptions.height)); | ||
// Cast values numerically | ||
outgoing = Number(outgoing); | ||
if (Object.prototype.hasOwnProperty.call(cropOptions, 'x') || Object.prototype.hasOwnProperty.call(cropOptions, 'y')) { | ||
data.push(prepNumber(cropOptions.x)); | ||
data.push(prepNumber(cropOptions.y)); | ||
} | ||
if (!isFinite(outgoing)) { | ||
error$1('"' + value + '" is not a finite number'); | ||
outgoing = defaultValue; | ||
return data.join(','); | ||
} | ||
return outgoing; | ||
} | ||
function fit(options) { | ||
var params = {}; | ||
/** | ||
Add defaults to a Crushinator helper options object, | ||
unless explicitly requested not to do so. | ||
*/ | ||
if (options.fit && options.width && options.height) { | ||
_extends(params, { | ||
op: '^', | ||
c: "".concat(prepNumber(options.width), ",").concat(prepNumber(options.height)) | ||
}); // A custom alignment may be specified with the fit option | ||
/** | ||
Default Crushinator helper options. | ||
*/ | ||
var defaultOptions = { | ||
fit: true, | ||
unsharp: true, | ||
quality: 82 | ||
}; | ||
/** | ||
Given a list of options returns those options seeded with the defaults | ||
specified above unless the "defaults" option is set to false. | ||
if (!options.align) params.gravity = 't'; | ||
} | ||
@param {Object} [options] - Incoming Crushinator helper options. | ||
@returns {Object} | ||
*/ | ||
function defaultify() { | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
return params; | ||
} | ||
return _extends({}, prepBoolean(options.defaults, true) ? defaultOptions : {}, options); | ||
} | ||
function unsharp(options) { | ||
var params = {}; | ||
var value = options.unsharp; | ||
/** | ||
Given an options object, returns a parameters object with crop | ||
parameters included according to the specified options. | ||
*/ | ||
if (value) { | ||
_extends(params, { | ||
u: { | ||
r: prepNumber(value.radius, 2), | ||
s: prepNumber(value.sigma, 0.5), | ||
a: prepNumber(value.amount, 0.8), | ||
t: prepNumber(value.threshold, 0.03) | ||
} | ||
}); | ||
} | ||
function param(cropOptions) { | ||
return cropOptions.afterResize ? 'c' : 'precrop'; | ||
} | ||
function filter(cropOptions) { | ||
var data = []; | ||
data.push(prepNumber(cropOptions.width)); | ||
data.push(prepNumber(cropOptions.height)); | ||
if (Object.prototype.hasOwnProperty.call(cropOptions, 'x') || Object.prototype.hasOwnProperty.call(cropOptions, 'y')) { | ||
data.push(prepNumber(cropOptions.x)); | ||
data.push(prepNumber(cropOptions.y)); | ||
return params; | ||
} | ||
return data.join(','); | ||
} | ||
/** | ||
Convert values from hyphenated form to an object tree, e.g.: | ||
/** | ||
Given an options object, returns the parameters required to | ||
resize the image for best fit if applicable. | ||
*/ | ||
``` | ||
dehyphenate({ | ||
'cat-ears': 'pointy', | ||
'cat-tail': 'whippy', | ||
'dog-ears': 'floppy', | ||
'dog-tail': 'swishy', | ||
}) | ||
// => { | ||
// cat: { ears: 'pointy', tail: 'whippy' }, | ||
// dog: { ears: 'floppy', 'tail: 'swishy' }, | ||
// } | ||
``` | ||
*/ | ||
function dehyphenate(values) { | ||
var dehyphenated = {}; | ||
Object.keys(values).forEach(function (key) { | ||
var value = values[key]; | ||
var splitted = key.match(/([^-]+)-+(.*)/); | ||
function fit(options) { | ||
var params = {}; | ||
if (options.fit && options.width && options.height) { | ||
_extends(params, { | ||
op: '^', | ||
c: prepNumber(options.width) + ',' + prepNumber(options.height) | ||
if (splitted) { | ||
dehyphenated[splitted[1]] = dehyphenated[splitted[1]] || {}; | ||
dehyphenated[splitted[1]][splitted[2]] = value; | ||
} else { | ||
dehyphenated[key] = value; | ||
} | ||
}); | ||
// A custom alignment may be specified with the fit option | ||
if (!options.align) params.gravity = 't'; | ||
return dehyphenated; | ||
} | ||
return params; | ||
} | ||
function parameterize(incoming) { | ||
var params = {}; | ||
var options = dehyphenate(incoming); | ||
Object.keys(options).forEach(function (option) { | ||
var value = options[option]; | ||
/** | ||
Given an options object, returns a parameters object with unsharp | ||
parameters included according to the specified options. | ||
*/ | ||
switch (option) { | ||
case 'width': | ||
params.w = prepNumber(value); | ||
break; | ||
function unsharp(options) { | ||
var params = {}; | ||
var value = options.unsharp; | ||
case 'height': | ||
params.h = prepNumber(value); | ||
break; | ||
if (value) { | ||
_extends(params, { u: { | ||
r: prepNumber(value.radius, 2), | ||
s: prepNumber(value.sigma, 0.5), | ||
a: prepNumber(value.amount, 0.8), | ||
t: prepNumber(value.threshold, 0.03) | ||
} }); | ||
} | ||
case 'quality': | ||
params.quality = prepNumber(value); | ||
break; | ||
return params; | ||
} | ||
case 'fit': | ||
_extends(params, fit(options)); | ||
/** | ||
Convert values from hyphenated form to an object tree, e.g.: | ||
break; | ||
``` | ||
dehyphenate({ | ||
'cat-ears': 'pointy', | ||
'cat-tail': 'whippy', | ||
'dog-ears': 'floppy', | ||
'dog-tail': 'swishy', | ||
}) | ||
// => { | ||
// cat: { ears: 'pointy', tail: 'whippy' }, | ||
// dog: { ears: 'floppy', 'tail: 'swishy' }, | ||
// } | ||
``` | ||
*/ | ||
case 'align': | ||
params.gravity = { | ||
top: 'n', | ||
left: 'w', | ||
center: 'c', | ||
middle: 'c', | ||
right: 'e', | ||
bottom: 's' | ||
}[value] || 'c'; | ||
break; | ||
function dehyphenate(values) { | ||
var dehyphenated = {}; | ||
case 'crop': | ||
params[param(value)] = filter(value); | ||
break; | ||
Object.keys(values).forEach(function (key) { | ||
var value = values[key]; | ||
var splitted = key.match(/([^-]+)-+(.*)/); | ||
case 'blur': | ||
params.blur = _typeof(value) === 'object' ? "".concat(prepNumber(value.radius), ",").concat(prepNumber(value.sigma, 2)) : "0,".concat(prepNumber(value, 2)); | ||
break; | ||
if (splitted) { | ||
dehyphenated[splitted[1]] = dehyphenated[splitted[1]] || {}; | ||
dehyphenated[splitted[1]][splitted[2]] = value; | ||
} else { | ||
dehyphenated[key] = value; | ||
} | ||
}); | ||
case 'gamma': | ||
params.gamma = _typeof(value) === 'object' ? "".concat(prepNumber(value.red, 1), ",").concat(prepNumber(value.green, 1), ",").concat(prepNumber(value.blue, 1)) : prepNumber(value, 1); | ||
break; | ||
return dehyphenated; | ||
} | ||
case 'grayscale': | ||
case 'greyscale': | ||
params.grayscale = prepNumber(value, 1) * 100; | ||
break; | ||
/** | ||
Convert helper options to Crushinator URL parameters. | ||
*/ | ||
case 'unsharp': | ||
_extends(params, unsharp(options)); | ||
function parameterize(incoming) { | ||
var params = {}; | ||
var options = dehyphenate(incoming); | ||
break; | ||
Object.keys(options).forEach(function (option) { | ||
var value = options[option]; | ||
case 'query': | ||
_extends(params, value || {}); | ||
switch (option) { | ||
case 'width': | ||
params.w = prepNumber(value); | ||
break; | ||
break; | ||
} | ||
}); | ||
return params; | ||
} | ||
case 'height': | ||
params.h = prepNumber(value); | ||
break; | ||
/** | ||
Query string helper methods. | ||
*/ | ||
case 'quality': | ||
params.quality = prepNumber(value); | ||
break; | ||
/** | ||
Encode value for use in a URL. | ||
*/ | ||
function encode(value) { | ||
return encodeURIComponent(value); | ||
} | ||
/** | ||
Simple serialization of an object to query parameters. | ||
*/ | ||
case 'fit': | ||
_extends(params, fit(options)); | ||
break; | ||
function serialize(params, prefix) { | ||
var parts = []; | ||
Object.keys(params).forEach(function (key) { | ||
var value = params[key]; | ||
var param = prefix ? "".concat(prefix, "[").concat(key, "]") : key; | ||
parts.push(_typeof(value) === 'object' ? serialize(value, param) : "".concat(encode(param), "=").concat(encode(value))); | ||
}); | ||
return parts.join('&'); | ||
} | ||
case 'align': | ||
params.gravity = { | ||
top: 'n', | ||
left: 'w', | ||
center: 'c', | ||
middle: 'c', | ||
right: 'e', | ||
bottom: 's' | ||
}[value] || 'c'; | ||
break; | ||
/** | ||
Given a URL string, returns a version where parentheses and quotation | ||
marks (single and double) are percent-encoded. | ||
case 'crop': | ||
params[param(value)] = filter(value); | ||
break; | ||
Though these characters are legal in URLs, they can cause problems | ||
in some interpolations. Percent encoding them avoids that pitfall. | ||
*/ | ||
var percentifyChar = function percentifyChar(c) { | ||
return "%".concat(c.charCodeAt(0).toString(16)); | ||
}; | ||
case 'blur': | ||
params.blur = (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' ? prepNumber(value.radius) + ',' + prepNumber(value.sigma, 2) : '0,' + prepNumber(value, 2); | ||
break; | ||
var desnag = function desnag(url) { | ||
return url.replace(/[()'"]/g, percentifyChar); | ||
}; | ||
case 'gamma': | ||
params.gamma = (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' ? prepNumber(value.red, 1) + ',' + prepNumber(value.green, 1) + ',' + prepNumber(value.blue, 1) : prepNumber(value, 1); | ||
break; | ||
/** | ||
A whitelist: Crushinator is capable of optimizing images hosted on | ||
any of these domains. | ||
*/ | ||
case 'grayscale': | ||
case 'greyscale': | ||
params.grayscale = prepNumber(value, 1) * 100; | ||
break; | ||
var imageHosts = ['assets.tedcdn.com', 'assets2.tedcdn.com', 'ems.ted.com', 'ems-staging.ted.com', 'images.ted.com', 'pa.tedcdn.com', 'pb-assets.tedcdn.com', 'pe.tedcdn.com', 'pf.tedcdn.com', 'ph.tedcdn.com', 'pj.tedcdn.com', 'pk.tedcdn.com', 'pl.tedcdn.com', 's3.amazonaws.com', 's3-us-west-2.amazonaws.com', 'staging.ted.com', 'storage.ted.com', 'talkstar-photos.s3.amazonaws.com', 'tedcdnpa-a.akamaihd.net', 'tedcdnpe-a.akamaihd.net', 'tedcdnpf-a.akamaihd.net', 'tedconfblog.files.wordpress.com', 'tedideas.files.wordpress.com', 'tedlive.ted.com', 'tedlive-staging.ted.com', 'ted2017.ted.com', 'ted2017-staging.ted.com', 'userdata.amara.org', 'www.filepicker.io', 'www.ted.com']; | ||
/** | ||
Global configuration options. These can be overridden at the library | ||
level or via the options object by individual helper method calls. | ||
*/ | ||
case 'unsharp': | ||
_extends(params, unsharp(options)); | ||
break; | ||
case 'query': | ||
_extends(params, value || {}); | ||
break; | ||
default: | ||
break; | ||
} | ||
}); | ||
return params; | ||
} | ||
/** | ||
Query string helper methods. | ||
*/ | ||
/** | ||
Encode value for use in a URL. | ||
*/ | ||
function encode(value) { | ||
return encodeURIComponent(value); | ||
} | ||
/** | ||
Simple serialization of an object to query parameters. | ||
*/ | ||
function serialize(params, prefix) { | ||
var parts = []; | ||
Object.keys(params).forEach(function (key) { | ||
var value = params[key]; | ||
var param = prefix ? prefix + '[' + key + ']' : key; | ||
parts.push((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' ? serialize(value, param) : encode(param) + '=' + encode(value)); | ||
}); | ||
return parts.join('&'); | ||
} | ||
/** | ||
Given a URL string, returns a version where parentheses and quotation | ||
marks (single and double) are percent-encoded. | ||
Though these characters are legal in URLs, they can cause problems | ||
in some interpolations. Percent encoding them avoids that pitfall. | ||
*/ | ||
var percentifyChar = function percentifyChar(c) { | ||
return "%" + c.charCodeAt(0).toString(16); | ||
}; | ||
var desnag = function desnag(url) { | ||
return url.replace(/[()'"]/g, percentifyChar); | ||
}; | ||
/** | ||
Crushinator Helpers | ||
Library of simple JS methods to produce crushed image URLs. | ||
http://github.com/tedconf/js-crushinator-helpers | ||
*/ | ||
/** | ||
A whitelist: Crushinator is capable of optimizing images hosted on | ||
any of these domains. | ||
*/ | ||
var imageHosts = ['assets.tedcdn.com', 'assets2.tedcdn.com', 'ems.ted.com', 'ems-staging.ted.com', 'images.ted.com', 'pa.tedcdn.com', 'pb-assets.tedcdn.com', 'pe.tedcdn.com', 'pf.tedcdn.com', 'ph.tedcdn.com', 'pj.tedcdn.com', 'pk.tedcdn.com', 'pl.tedcdn.com', 's3.amazonaws.com', 's3-us-west-2.amazonaws.com', 'staging.ted.com', 'storage.ted.com', 'talkstar-photos.s3.amazonaws.com', 'tedcdnpa-a.akamaihd.net', 'tedcdnpe-a.akamaihd.net', 'tedcdnpf-a.akamaihd.net', 'tedconfblog.files.wordpress.com', 'tedideas.files.wordpress.com', 'tedlive.ted.com', 'tedlive-staging.ted.com', 'ted2017.ted.com', 'ted2017-staging.ted.com', 'userdata.amara.org', 'www.filepicker.io', 'www.ted.com']; | ||
/** | ||
Global configuration options. These can be overridden at the library | ||
level or via the options object by individual helper method calls. | ||
*/ | ||
var config = { | ||
var config = { | ||
defaults: true, | ||
host: 'https://pi.tedcdn.com' | ||
}; | ||
}; | ||
/** | ||
Returns the portion of input URL that corresponds to the host name. | ||
/** | ||
Returns the portion of input URL that corresponds to the host name. | ||
@private | ||
@param {string} url | ||
@returns {string} | ||
*/ | ||
@private | ||
@param {string} url | ||
@returns {string} | ||
*/ | ||
function extractHost(url) { | ||
function extractHost(url) { | ||
return String(url).replace(/.*\/\/([^/]+).*/, '$1'); | ||
} | ||
} | ||
/** | ||
Check to see if a URL passes Crushinator's host whitelist. | ||
/** | ||
Check to see if a URL passes Crushinator's host whitelist. | ||
@param {string} url - URL of image to check. | ||
@returns {boolean} | ||
*/ | ||
@param {string} url - URL of image to check. | ||
@returns {boolean} | ||
*/ | ||
function crushable(url) { | ||
function crushable(url) { | ||
return imageHosts.indexOf(extractHost(url)) !== -1; | ||
} | ||
} | ||
/** | ||
Restore a previously crushed URL to its original form. | ||
/** | ||
Restore a previously crushed URL to its original form. | ||
@param {string} url - Previously optimized image URL. | ||
@returns {string} | ||
*/ | ||
@param {string} url - Previously optimized image URL. | ||
@returns {string} | ||
*/ | ||
function uncrush(url) { | ||
var parts = String(url).match(/(.+)?\/\/(?:(?:img(?:-ssl)?|pi)\.tedcdn\.com|tedcdnpi-a\.akamaihd\.net)\/r\/([^?]+)/); | ||
function uncrush(url) { | ||
var parts = String(url).match(/(.+)?\/\/(?:(?:img(?:-ssl)?|pi)\.tedcdn\.com|tedcdnpi-a\.akamaihd\.net)\/r\/([^?]+)/); // Avoid double-crushing images | ||
// Avoid double-crushing images | ||
if (parts) { | ||
return uncrush(parts[1] + '//' + parts[2]); | ||
return uncrush("".concat(parts[1], "//").concat(parts[2])); | ||
} | ||
return url; | ||
} | ||
} | ||
/** | ||
Returns a Crushinator-optimized version of an image URL, using options | ||
specified in a Plain Old JavaScript Object: | ||
/** | ||
Returns a Crushinator-optimized version of an image URL, using options | ||
specified in a Plain Old JavaScript Object: | ||
crush('http://images.ted.com/image.jpg', { width: 320 }) | ||
=> 'https://pi.tedcdn.com/images.ted.com/image.jpg?w=320' | ||
crush('http://images.ted.com/image.jpg', { width: 320 }) | ||
=> 'https://pi.tedcdn.com/images.ted.com/image.jpg?w=320' | ||
If the input URL cannot be optimized (does not pass the whitelist) it | ||
is returned untampered, making this method safe to use for dynamic | ||
image sources. | ||
If the input URL cannot be optimized (does not pass the whitelist) it | ||
is returned untampered, making this method safe to use for dynamic | ||
image sources. | ||
@public | ||
@param {string} url - URL of image to be optimized. | ||
@param {Object} [options] | ||
@param {number} [options.width] - Target image width in pixels. | ||
@param {number} [options.height] - Target image height in pixels. | ||
@param {number} [options.quality] - Image quality as a percentage | ||
(0-100). Defaults to 82. | ||
@param {boolean} [options.fit] - Will zoom and crop the image | ||
for best fit into the target dimensions (width and height) | ||
if both are provided. Defaults to true. | ||
@param {boolean} [options.defaults] - Default options are excluded | ||
if set to false. Defaults to true. | ||
@param {string} [options.align] - If cropping occurs, the image | ||
can be aligned to the "top", "bottom", "left", "right", or | ||
"middle" of the crop frame. | ||
@param {Object} [options.crop] - Image crop configuration. | ||
@param {number} [options.crop.width] - Width of cropped section | ||
in pixels. | ||
@param {number} [options.crop.height] - Height of cropped section | ||
in pixels. | ||
@param {number} [options.crop.x] - Coordinate at which to start crop | ||
(pixels from left.) | ||
@param {number} [options.crop.y] - Coordinate at which to start crop | ||
(pixels from top.) | ||
@param {boolean} [options.crop.afterResize] - If true, crop will | ||
take place after the image has been resized. | ||
@param {Object|number} [options.blur] - Image blur configuration | ||
(object) or blur spread amount in pixels (number). | ||
@param {number} [options.blur.sigma] - Blur spread amount in pixels. | ||
@param {number} [options.blur.radius] - Radial constraint of blur or | ||
zero if unconstrained. Should be at least 2x sigma if specified. | ||
@param {Object|number} [options.gamma] - Gamma correction, applied | ||
either to the whole image (number) or to individual color | ||
channels (object). | ||
@param {number} [options.gamma.red] - Red channel gamma correction. | ||
@param {number} [options.gamma.green] - Green channel gamma correction. | ||
@param {number} [options.gamma.blue] - Blue channel gamma correction. | ||
@param {boolean|number} [options.grayscale] - Fully desaturates the | ||
image if truthy. Optionally you may also darken the image by | ||
specifying a decimal percentage value of less than 1. | ||
@param {Object|boolean} [options.unsharp] - Applies an unsharp mask | ||
if true. Precise configurations can be specified in object form: | ||
@param {number} [options.unsharp.radius] - Number of pixels to which | ||
sharpening should be applied surrounding each target pixel. | ||
@param {number} [options.unsharp.sigma] - Size of details to sharpen | ||
in pixels. (Pedantically: the standard deviation of the Gaussian.) | ||
@param {number} [options.unsharp.amount] - Decimel percentage | ||
representing the strength of the sharpening in terms of the | ||
difference between the sharpened image and the original. | ||
@param {number} [options.unsharp.threshold] - Decimal percentage | ||
representing a minimum amount of difference in a pixel vs | ||
surrounding colors before it's considered a sharpenable detail. | ||
@param {Object} [options.query] - Additional query parameters to | ||
include in the Crushinator-optimized image URL. | ||
@returns {string} | ||
*/ | ||
@public | ||
@param {string} url - URL of image to be optimized. | ||
@param {Object} [options] | ||
@param {number} [options.width] - Target image width in pixels. | ||
@param {number} [options.height] - Target image height in pixels. | ||
@param {number} [options.quality] - Image quality as a percentage | ||
(0-100). Defaults to 82. | ||
@param {boolean} [options.fit] - Will zoom and crop the image | ||
for best fit into the target dimensions (width and height) | ||
if both are provided. Defaults to true. | ||
@param {boolean} [options.defaults] - Default options are excluded | ||
if set to false. Defaults to true. | ||
@param {string} [options.align] - If cropping occurs, the image | ||
can be aligned to the "top", "bottom", "left", "right", or | ||
"middle" of the crop frame. | ||
@param {Object} [options.crop] - Image crop configuration. | ||
@param {number} [options.crop.width] - Width of cropped section | ||
in pixels. | ||
@param {number} [options.crop.height] - Height of cropped section | ||
in pixels. | ||
@param {number} [options.crop.x] - Coordinate at which to start crop | ||
(pixels from left.) | ||
@param {number} [options.crop.y] - Coordinate at which to start crop | ||
(pixels from top.) | ||
@param {boolean} [options.crop.afterResize] - If true, crop will | ||
take place after the image has been resized. | ||
@param {Object|number} [options.blur] - Image blur configuration | ||
(object) or blur spread amount in pixels (number). | ||
@param {number} [options.blur.sigma] - Blur spread amount in pixels. | ||
@param {number} [options.blur.radius] - Radial constraint of blur or | ||
zero if unconstrained. Should be at least 2x sigma if specified. | ||
@param {Object|number} [options.gamma] - Gamma correction, applied | ||
either to the whole image (number) or to individual color | ||
channels (object). | ||
@param {number} [options.gamma.red] - Red channel gamma correction. | ||
@param {number} [options.gamma.green] - Green channel gamma correction. | ||
@param {number} [options.gamma.blue] - Blue channel gamma correction. | ||
@param {boolean|number} [options.grayscale] - Fully desaturates the | ||
image if truthy. Optionally you may also darken the image by | ||
specifying a decimal percentage value of less than 1. | ||
@param {Object|boolean} [options.unsharp] - Applies an unsharp mask | ||
if true. Precise configurations can be specified in object form: | ||
@param {number} [options.unsharp.radius] - Number of pixels to which | ||
sharpening should be applied surrounding each target pixel. | ||
@param {number} [options.unsharp.sigma] - Size of details to sharpen | ||
in pixels. (Pedantically: the standard deviation of the Gaussian.) | ||
@param {number} [options.unsharp.amount] - Decimel percentage | ||
representing the strength of the sharpening in terms of the | ||
difference between the sharpened image and the original. | ||
@param {number} [options.unsharp.threshold] - Decimal percentage | ||
representing a minimum amount of difference in a pixel vs | ||
surrounding colors before it's considered a sharpenable detail. | ||
@param {Object} [options.query] - Additional query parameters to | ||
include in the Crushinator-optimized image URL. | ||
@returns {string} | ||
*/ | ||
function crush(url) { | ||
function crush(url) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
// Avoid double-crushing images | ||
var uncrushed = uncrush(url); | ||
var uncrushed = uncrush(url); // Apply host whitelist | ||
// Apply host whitelist | ||
if (!crushable(uncrushed)) { | ||
return uncrushed; | ||
return uncrushed; | ||
} | ||
var params = {}; | ||
var params = {}; // Complain about use of the deprecated string API | ||
// Complain about use of the deprecated string API | ||
if (typeof options === 'string') { | ||
warn('Sending Crushinator options as a query string is ' + 'deprecated. Please use the object format.'); | ||
params = options; | ||
} | ||
warn('Sending Crushinator options as a query string is ' + 'deprecated. Please use the object format.'); | ||
params = options; | ||
} // Stringify object options while adding defaults | ||
// Stringify object options while adding defaults | ||
if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') { | ||
params = serialize(parameterize(defaultify(_extends({ defaults: config.defaults }, options)))); | ||
if (_typeof(options) === 'object') { | ||
params = serialize(parameterize(defaultify(_extends({ | ||
defaults: config.defaults | ||
}, options)))); | ||
} | ||
return desnag(config.host + '/r/' + uncrushed.replace(/.*\/\//, '') + (params ? '?' + params : '')); | ||
} | ||
return desnag("".concat(config.host, "/r/").concat(uncrushed.replace(/.*\/\//, '')).concat(params ? "?".concat(params) : '')); | ||
} | ||
exports.imageHosts = imageHosts; | ||
exports.config = config; | ||
exports.crushable = crushable; | ||
exports.uncrush = uncrush; | ||
exports.crush = crush; | ||
exports['default'] = crush; | ||
exports.config = config; | ||
exports.crush = crush; | ||
exports.crushable = crushable; | ||
exports.default = crush; | ||
exports.imageHosts = imageHosts; | ||
exports.uncrush = uncrush; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
}); |
@@ -1,1 +0,1 @@ | ||
define("crushinator",["exports"],function(e){"use strict";function t(e){throw new Error(e)}function n(e){k&&"function"==typeof console.warn&&console.warn(e)}function r(e){return void 0===e||null===e||!1===e}function o(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return void 0===e?t:!!e}function a(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,o=e;return!0===e&&(o=n||1),r(e)&&(o=n),o=Number(o),isFinite(o)||(t('"'+e+'" is not a finite number'),o=n),o}function c(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return w({},o(e.defaults,!0)?j:{},e)}function i(e){return e.afterResize?"c":"precrop"}function s(e){var t=[];return t.push(a(e.width)),t.push(a(e.height)),(Object.prototype.hasOwnProperty.call(e,"x")||Object.prototype.hasOwnProperty.call(e,"y"))&&(t.push(a(e.x)),t.push(a(e.y))),t.join(",")}function d(e){var t={};return e.fit&&e.width&&e.height&&(w(t,{op:"^",c:a(e.width)+","+a(e.height)}),e.align||(t.gravity="t")),t}function u(e){var t={},n=e.unsharp;return n&&w(t,{u:{r:a(n.radius,2),s:a(n.sigma,.5),a:a(n.amount,.8),t:a(n.threshold,.03)}}),t}function f(e){var t={};return Object.keys(e).forEach(function(n){var r=e[n],o=n.match(/([^-]+)-+(.*)/);o?(t[o[1]]=t[o[1]]||{},t[o[1]][o[2]]=r):t[n]=r}),t}function m(e){var t={},n=f(e);return Object.keys(n).forEach(function(e){var r=n[e];switch(e){case"width":t.w=a(r);break;case"height":t.h=a(r);break;case"quality":t.quality=a(r);break;case"fit":w(t,d(n));break;case"align":t.gravity={top:"n",left:"w",center:"c",middle:"c",right:"e",bottom:"s"}[r]||"c";break;case"crop":t[i(r)]=s(r);break;case"blur":t.blur="object"===(void 0===r?"undefined":v(r))?a(r.radius)+","+a(r.sigma,2):"0,"+a(r,2);break;case"gamma":t.gamma="object"===(void 0===r?"undefined":v(r))?a(r.red,1)+","+a(r.green,1)+","+a(r.blue,1):a(r,1);break;case"grayscale":case"greyscale":t.grayscale=100*a(r,1);break;case"unsharp":w(t,u(n));break;case"query":w(t,r||{})}}),t}function l(e){return encodeURIComponent(e)}function p(e,t){var n=[];return Object.keys(e).forEach(function(r){var o=e[r],a=t?t+"["+r+"]":r;n.push("object"===(void 0===o?"undefined":v(o))?p(o,a):l(a)+"="+l(o))}),n.join("&")}function h(e){return String(e).replace(/.*\/\/([^\/]+).*/,"$1")}function g(e){return-1!==q.indexOf(h(e))}function b(e){var t=String(e).match(/(.+)?\/\/(?:(?:img(?:-ssl)?|pi)\.tedcdn\.com|tedcdnpi-a\.akamaihd\.net)\/r\/([^?]+)/);return t?b(t[1]+"//"+t[2]):e}function y(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=b(e);if(!g(r))return r;var o={};return"string"==typeof t&&(n("Sending Crushinator options as a query string is deprecated. Please use the object format."),o=t),"object"===(void 0===t?"undefined":v(t))&&(o=p(m(c(w({defaults:P.defaults},t))))),S(P.host+"/r/"+r.replace(/.*\/\//,"")+(o?"?"+o:""))}var v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},w=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},k="object"===("undefined"==typeof console?"undefined":v(console)),j={fit:!0,unsharp:!0,quality:82},O=function(e){return"%"+e.charCodeAt(0).toString(16)},S=function(e){return e.replace(/[()'"]/g,O)},q=["assets.tedcdn.com","assets2.tedcdn.com","ems.ted.com","ems-staging.ted.com","images.ted.com","pa.tedcdn.com","pb-assets.tedcdn.com","pe.tedcdn.com","pf.tedcdn.com","ph.tedcdn.com","pj.tedcdn.com","pk.tedcdn.com","pl.tedcdn.com","s3.amazonaws.com","s3-us-west-2.amazonaws.com","staging.ted.com","storage.ted.com","talkstar-photos.s3.amazonaws.com","tedcdnpa-a.akamaihd.net","tedcdnpe-a.akamaihd.net","tedcdnpf-a.akamaihd.net","tedconfblog.files.wordpress.com","tedideas.files.wordpress.com","tedlive.ted.com","tedlive-staging.ted.com","ted2017.ted.com","ted2017-staging.ted.com","userdata.amara.org","www.filepicker.io","www.ted.com"],P={defaults:!0,host:"https://pi.tedcdn.com"};e.imageHosts=q,e.config=P,e.crushable=g,e.uncrush=b,e.crush=y,e.default=y,Object.defineProperty(e,"__esModule",{value:!0})}); | ||
define("crushinator",["exports"],function(t){"use strict";function u(t){return(u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function m(){return(m=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var c=arguments[e];for(var n in c)Object.prototype.hasOwnProperty.call(c,n)&&(t[n]=c[n])}return t}).apply(this,arguments)}var a="object"===("undefined"==typeof console?"undefined":u(console));function f(t,e){var c,n=1<arguments.length&&void 0!==e?e:0,o=t;return!0===t&&(o=n||1),null!=(c=t)&&!1!==c||(o=n),o=Number(o),isFinite(o)||(function(t){throw new Error(t)}('"'.concat(t,'" is not a finite number')),o=n),o}var c={fit:!0,unsharp:!0,quality:82};function r(t){var e=0<arguments.length&&void 0!==t?t:{};return m({},function(t,e){return void 0===t?1<arguments.length&&void 0!==e&&e:t}(e.defaults,!0)?c:{},e)}function s(t){var n,o,i={},d=(n=t,o={},Object.keys(n).forEach(function(t){var e=n[t],c=t.match(/([^-]+)-+(.*)/);c?(o[c[1]]=o[c[1]]||{},o[c[1]][c[2]]=e):o[t]=e}),o);return Object.keys(d).forEach(function(t){var e,c,n,o,a,r,s=d[t];switch(t){case"width":i.w=f(s);break;case"height":i.h=f(s);break;case"quality":i.quality=f(s);break;case"fit":m(i,(r={},(a=d).fit&&a.width&&a.height&&(m(r,{op:"^",c:"".concat(f(a.width),",").concat(f(a.height))}),a.align||(r.gravity="t")),r));break;case"align":i.gravity={top:"n",left:"w",center:"c",middle:"c",right:"e",bottom:"s"}[s]||"c";break;case"crop":i[s.afterResize?"c":"precrop"]=((o=[]).push(f((n=s).width)),o.push(f(n.height)),(Object.prototype.hasOwnProperty.call(n,"x")||Object.prototype.hasOwnProperty.call(n,"y"))&&(o.push(f(n.x)),o.push(f(n.y))),o.join(","));break;case"blur":i.blur="object"===u(s)?"".concat(f(s.radius),",").concat(f(s.sigma,2)):"0,".concat(f(s,2));break;case"gamma":i.gamma="object"===u(s)?"".concat(f(s.red,1),",").concat(f(s.green,1),",").concat(f(s.blue,1)):f(s,1);break;case"grayscale":case"greyscale":i.grayscale=100*f(s,1);break;case"unsharp":m(i,(e={},(c=d.unsharp)&&m(e,{u:{r:f(c.radius,2),s:f(c.sigma,.5),a:f(c.amount,.8),t:f(c.threshold,.03)}}),e));break;case"query":m(i,s||{})}}),i}function i(t){return encodeURIComponent(t)}function d(t){return"%".concat(t.charCodeAt(0).toString(16))}var e=["assets.tedcdn.com","assets2.tedcdn.com","ems.ted.com","ems-staging.ted.com","images.ted.com","pa.tedcdn.com","pb-assets.tedcdn.com","pe.tedcdn.com","pf.tedcdn.com","ph.tedcdn.com","pj.tedcdn.com","pk.tedcdn.com","pl.tedcdn.com","s3.amazonaws.com","s3-us-west-2.amazonaws.com","staging.ted.com","storage.ted.com","talkstar-photos.s3.amazonaws.com","tedcdnpa-a.akamaihd.net","tedcdnpe-a.akamaihd.net","tedcdnpf-a.akamaihd.net","tedconfblog.files.wordpress.com","tedideas.files.wordpress.com","tedlive.ted.com","tedlive-staging.ted.com","ted2017.ted.com","ted2017-staging.ted.com","userdata.amara.org","www.filepicker.io","www.ted.com"],p={defaults:!0,host:"https://pi.tedcdn.com"};function l(t){return-1!==e.indexOf(String(t).replace(/.*\/\/([^/]+).*/,"$1"))}function h(t){var e=String(t).match(/(.+)?\/\/(?:(?:img(?:-ssl)?|pi)\.tedcdn\.com|tedcdnpi-a\.akamaihd\.net)\/r\/([^?]+)/);return e?h("".concat(e[1],"//").concat(e[2])):t}function n(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},c=h(t);if(!l(c))return c;var n,o={};return"string"==typeof e&&(n="Sending Crushinator options as a query string is deprecated. Please use the object format.",a&&"function"==typeof console.warn&&console.warn(n),o=e),"object"===u(e)&&(o=function n(o,a){var r=[];return Object.keys(o).forEach(function(t){var e=o[t],c=a?"".concat(a,"[").concat(t,"]"):t;r.push("object"===u(e)?n(e,c):"".concat(i(c),"=").concat(i(e)))}),r.join("&")}(s(r(m({defaults:p.defaults},e))))),"".concat(p.host,"/r/").concat(c.replace(/.*\/\//,"")).concat(o?"?".concat(o):"").replace(/[()'"]/g,d)}t.config=p,t.crush=n,t.crushable=l,t.default=n,t.imageHosts=e,t.uncrush=h,Object.defineProperty(t,"__esModule",{value:!0})}); |
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(factory((global.crushinator = global.crushinator || {}))); | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(global = global || self, factory(global.crushinator = {})); | ||
}(this, (function (exports) { 'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; | ||
}; | ||
function _typeof(obj) { | ||
"@babel/helpers - typeof"; | ||
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { | ||
_typeof = function (obj) { | ||
return typeof obj; | ||
}; | ||
} else { | ||
_typeof = function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; | ||
}; | ||
} | ||
return _typeof(obj); | ||
} | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
/** | ||
Wrapper methods for logging errors and other notices. | ||
*/ | ||
/** | ||
True if we can send messages to the console. | ||
*/ | ||
var isConsolable = (typeof console === "undefined" ? "undefined" : _typeof(console)) === 'object'; | ||
/** | ||
Throw an honest-to-goodness error. | ||
*/ | ||
function error(message) { | ||
throw new Error(message); | ||
} | ||
/** | ||
Display a warning without throwing a script-halting error. | ||
*/ | ||
function warn(message) { | ||
if (isConsolable && typeof console.warn === 'function') { | ||
console.warn(message); | ||
} | ||
} | ||
/** | ||
Methods used to prepare Crushinator option values for parameterization, | ||
mostly concerning typecasting and type-checking with application of | ||
default values. | ||
*/ | ||
/** | ||
Returns true if the value is undefined, null, or false. | ||
@param {*} value - Value to test for emptiness. | ||
@returns {boolean} | ||
*/ | ||
function isBlank(value) { | ||
return typeof value === 'undefined' || value === null || value === false; | ||
} | ||
/** | ||
Prepare a boolean value. | ||
@param {*} value - Value that should be typecast as a boolean. | ||
@returns {boolean} | ||
*/ | ||
function prepBoolean(value) { | ||
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
return typeof value === 'undefined' ? defaultValue : !!value; | ||
} | ||
/** | ||
Prepare a numerical value. | ||
@param {*} value - Value that should be typecast as a number. | ||
@returns {number} | ||
*/ | ||
function prepNumber(value) { | ||
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | ||
var outgoing = value; // Boolean true evaluates to 1 numerically | ||
if (value === true) { | ||
outgoing = defaultValue || 1; | ||
} | ||
if (isBlank(value)) { | ||
outgoing = defaultValue; | ||
} // Cast values numerically | ||
var _extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
outgoing = Number(outgoing); | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
if (!isFinite(outgoing)) { | ||
error("\"".concat(value, "\" is not a finite number")); | ||
outgoing = defaultValue; | ||
} | ||
} | ||
return target; | ||
}; | ||
/** | ||
Wrapper methods for logging errors and other notices. | ||
*/ | ||
/** | ||
True if we can send messages to the console. | ||
*/ | ||
var isConsolable = (typeof console === 'undefined' ? 'undefined' : _typeof(console)) === 'object'; | ||
/** | ||
Throw an honest-to-goodness error. | ||
*/ | ||
function error$1(message) { | ||
throw new Error(message); | ||
} | ||
/** | ||
Display a warning without throwing a script-halting error. | ||
*/ | ||
function warn(message) { | ||
if (isConsolable && typeof console.warn === 'function') { | ||
console.warn(message); | ||
return outgoing; | ||
} | ||
} | ||
/** | ||
Methods used to prepare Crushinator option values for parameterization, | ||
mostly concerning typecasting and type-checking with application of | ||
default values. | ||
*/ | ||
/** | ||
Default Crushinator helper options. | ||
*/ | ||
/** | ||
Returns true if the value is undefined, null, or false. | ||
var defaultOptions = { | ||
fit: true, | ||
unsharp: true, | ||
quality: 82 | ||
}; | ||
/** | ||
Given a list of options returns those options seeded with the defaults | ||
specified above unless the "defaults" option is set to false. | ||
@param {*} value - Value to test for emptiness. | ||
@returns {boolean} | ||
*/ | ||
function isBlank(value) { | ||
return typeof value === 'undefined' || value === null || value === false; | ||
} | ||
@param {Object} [options] - Incoming Crushinator helper options. | ||
@returns {Object} | ||
*/ | ||
/** | ||
Prepare a boolean value. | ||
@param {*} value - Value that should be typecast as a boolean. | ||
@returns {boolean} | ||
*/ | ||
function prepBoolean(value) { | ||
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
return typeof value === 'undefined' ? defaultValue : !!value; | ||
} | ||
/** | ||
Prepare a numerical value. | ||
@param {*} value - Value that should be typecast as a number. | ||
@returns {number} | ||
*/ | ||
function prepNumber(value) { | ||
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | ||
var outgoing = value; | ||
// Boolean true evaluates to 1 numerically | ||
if (value === true) { | ||
outgoing = defaultValue || 1; | ||
function defaultify() { | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
return _extends({}, prepBoolean(options.defaults, true) ? defaultOptions : {}, options); | ||
} | ||
if (isBlank(value)) { | ||
outgoing = defaultValue; | ||
/** | ||
Given an options object, returns a parameters object with crop | ||
parameters included according to the specified options. | ||
*/ | ||
function param(cropOptions) { | ||
return cropOptions.afterResize ? 'c' : 'precrop'; | ||
} | ||
function filter(cropOptions) { | ||
var data = []; | ||
data.push(prepNumber(cropOptions.width)); | ||
data.push(prepNumber(cropOptions.height)); | ||
// Cast values numerically | ||
outgoing = Number(outgoing); | ||
if (Object.prototype.hasOwnProperty.call(cropOptions, 'x') || Object.prototype.hasOwnProperty.call(cropOptions, 'y')) { | ||
data.push(prepNumber(cropOptions.x)); | ||
data.push(prepNumber(cropOptions.y)); | ||
} | ||
if (!isFinite(outgoing)) { | ||
error$1('"' + value + '" is not a finite number'); | ||
outgoing = defaultValue; | ||
return data.join(','); | ||
} | ||
return outgoing; | ||
} | ||
function fit(options) { | ||
var params = {}; | ||
/** | ||
Add defaults to a Crushinator helper options object, | ||
unless explicitly requested not to do so. | ||
*/ | ||
if (options.fit && options.width && options.height) { | ||
_extends(params, { | ||
op: '^', | ||
c: "".concat(prepNumber(options.width), ",").concat(prepNumber(options.height)) | ||
}); // A custom alignment may be specified with the fit option | ||
/** | ||
Default Crushinator helper options. | ||
*/ | ||
var defaultOptions = { | ||
fit: true, | ||
unsharp: true, | ||
quality: 82 | ||
}; | ||
/** | ||
Given a list of options returns those options seeded with the defaults | ||
specified above unless the "defaults" option is set to false. | ||
if (!options.align) params.gravity = 't'; | ||
} | ||
@param {Object} [options] - Incoming Crushinator helper options. | ||
@returns {Object} | ||
*/ | ||
function defaultify() { | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
return params; | ||
} | ||
return _extends({}, prepBoolean(options.defaults, true) ? defaultOptions : {}, options); | ||
} | ||
function unsharp(options) { | ||
var params = {}; | ||
var value = options.unsharp; | ||
/** | ||
Given an options object, returns a parameters object with crop | ||
parameters included according to the specified options. | ||
*/ | ||
if (value) { | ||
_extends(params, { | ||
u: { | ||
r: prepNumber(value.radius, 2), | ||
s: prepNumber(value.sigma, 0.5), | ||
a: prepNumber(value.amount, 0.8), | ||
t: prepNumber(value.threshold, 0.03) | ||
} | ||
}); | ||
} | ||
function param(cropOptions) { | ||
return cropOptions.afterResize ? 'c' : 'precrop'; | ||
} | ||
function filter(cropOptions) { | ||
var data = []; | ||
data.push(prepNumber(cropOptions.width)); | ||
data.push(prepNumber(cropOptions.height)); | ||
if (Object.prototype.hasOwnProperty.call(cropOptions, 'x') || Object.prototype.hasOwnProperty.call(cropOptions, 'y')) { | ||
data.push(prepNumber(cropOptions.x)); | ||
data.push(prepNumber(cropOptions.y)); | ||
return params; | ||
} | ||
return data.join(','); | ||
} | ||
/** | ||
Convert values from hyphenated form to an object tree, e.g.: | ||
/** | ||
Given an options object, returns the parameters required to | ||
resize the image for best fit if applicable. | ||
*/ | ||
``` | ||
dehyphenate({ | ||
'cat-ears': 'pointy', | ||
'cat-tail': 'whippy', | ||
'dog-ears': 'floppy', | ||
'dog-tail': 'swishy', | ||
}) | ||
// => { | ||
// cat: { ears: 'pointy', tail: 'whippy' }, | ||
// dog: { ears: 'floppy', 'tail: 'swishy' }, | ||
// } | ||
``` | ||
*/ | ||
function dehyphenate(values) { | ||
var dehyphenated = {}; | ||
Object.keys(values).forEach(function (key) { | ||
var value = values[key]; | ||
var splitted = key.match(/([^-]+)-+(.*)/); | ||
function fit(options) { | ||
var params = {}; | ||
if (options.fit && options.width && options.height) { | ||
_extends(params, { | ||
op: '^', | ||
c: prepNumber(options.width) + ',' + prepNumber(options.height) | ||
if (splitted) { | ||
dehyphenated[splitted[1]] = dehyphenated[splitted[1]] || {}; | ||
dehyphenated[splitted[1]][splitted[2]] = value; | ||
} else { | ||
dehyphenated[key] = value; | ||
} | ||
}); | ||
// A custom alignment may be specified with the fit option | ||
if (!options.align) params.gravity = 't'; | ||
return dehyphenated; | ||
} | ||
return params; | ||
} | ||
function parameterize(incoming) { | ||
var params = {}; | ||
var options = dehyphenate(incoming); | ||
Object.keys(options).forEach(function (option) { | ||
var value = options[option]; | ||
/** | ||
Given an options object, returns a parameters object with unsharp | ||
parameters included according to the specified options. | ||
*/ | ||
switch (option) { | ||
case 'width': | ||
params.w = prepNumber(value); | ||
break; | ||
function unsharp(options) { | ||
var params = {}; | ||
var value = options.unsharp; | ||
case 'height': | ||
params.h = prepNumber(value); | ||
break; | ||
if (value) { | ||
_extends(params, { u: { | ||
r: prepNumber(value.radius, 2), | ||
s: prepNumber(value.sigma, 0.5), | ||
a: prepNumber(value.amount, 0.8), | ||
t: prepNumber(value.threshold, 0.03) | ||
} }); | ||
} | ||
case 'quality': | ||
params.quality = prepNumber(value); | ||
break; | ||
return params; | ||
} | ||
case 'fit': | ||
_extends(params, fit(options)); | ||
/** | ||
Convert values from hyphenated form to an object tree, e.g.: | ||
break; | ||
``` | ||
dehyphenate({ | ||
'cat-ears': 'pointy', | ||
'cat-tail': 'whippy', | ||
'dog-ears': 'floppy', | ||
'dog-tail': 'swishy', | ||
}) | ||
// => { | ||
// cat: { ears: 'pointy', tail: 'whippy' }, | ||
// dog: { ears: 'floppy', 'tail: 'swishy' }, | ||
// } | ||
``` | ||
*/ | ||
case 'align': | ||
params.gravity = { | ||
top: 'n', | ||
left: 'w', | ||
center: 'c', | ||
middle: 'c', | ||
right: 'e', | ||
bottom: 's' | ||
}[value] || 'c'; | ||
break; | ||
function dehyphenate(values) { | ||
var dehyphenated = {}; | ||
case 'crop': | ||
params[param(value)] = filter(value); | ||
break; | ||
Object.keys(values).forEach(function (key) { | ||
var value = values[key]; | ||
var splitted = key.match(/([^-]+)-+(.*)/); | ||
case 'blur': | ||
params.blur = _typeof(value) === 'object' ? "".concat(prepNumber(value.radius), ",").concat(prepNumber(value.sigma, 2)) : "0,".concat(prepNumber(value, 2)); | ||
break; | ||
if (splitted) { | ||
dehyphenated[splitted[1]] = dehyphenated[splitted[1]] || {}; | ||
dehyphenated[splitted[1]][splitted[2]] = value; | ||
} else { | ||
dehyphenated[key] = value; | ||
} | ||
}); | ||
case 'gamma': | ||
params.gamma = _typeof(value) === 'object' ? "".concat(prepNumber(value.red, 1), ",").concat(prepNumber(value.green, 1), ",").concat(prepNumber(value.blue, 1)) : prepNumber(value, 1); | ||
break; | ||
return dehyphenated; | ||
} | ||
case 'grayscale': | ||
case 'greyscale': | ||
params.grayscale = prepNumber(value, 1) * 100; | ||
break; | ||
/** | ||
Convert helper options to Crushinator URL parameters. | ||
*/ | ||
case 'unsharp': | ||
_extends(params, unsharp(options)); | ||
function parameterize(incoming) { | ||
var params = {}; | ||
var options = dehyphenate(incoming); | ||
break; | ||
Object.keys(options).forEach(function (option) { | ||
var value = options[option]; | ||
case 'query': | ||
_extends(params, value || {}); | ||
switch (option) { | ||
case 'width': | ||
params.w = prepNumber(value); | ||
break; | ||
break; | ||
} | ||
}); | ||
return params; | ||
} | ||
case 'height': | ||
params.h = prepNumber(value); | ||
break; | ||
/** | ||
Query string helper methods. | ||
*/ | ||
case 'quality': | ||
params.quality = prepNumber(value); | ||
break; | ||
/** | ||
Encode value for use in a URL. | ||
*/ | ||
function encode(value) { | ||
return encodeURIComponent(value); | ||
} | ||
/** | ||
Simple serialization of an object to query parameters. | ||
*/ | ||
case 'fit': | ||
_extends(params, fit(options)); | ||
break; | ||
function serialize(params, prefix) { | ||
var parts = []; | ||
Object.keys(params).forEach(function (key) { | ||
var value = params[key]; | ||
var param = prefix ? "".concat(prefix, "[").concat(key, "]") : key; | ||
parts.push(_typeof(value) === 'object' ? serialize(value, param) : "".concat(encode(param), "=").concat(encode(value))); | ||
}); | ||
return parts.join('&'); | ||
} | ||
case 'align': | ||
params.gravity = { | ||
top: 'n', | ||
left: 'w', | ||
center: 'c', | ||
middle: 'c', | ||
right: 'e', | ||
bottom: 's' | ||
}[value] || 'c'; | ||
break; | ||
/** | ||
Given a URL string, returns a version where parentheses and quotation | ||
marks (single and double) are percent-encoded. | ||
case 'crop': | ||
params[param(value)] = filter(value); | ||
break; | ||
Though these characters are legal in URLs, they can cause problems | ||
in some interpolations. Percent encoding them avoids that pitfall. | ||
*/ | ||
var percentifyChar = function percentifyChar(c) { | ||
return "%".concat(c.charCodeAt(0).toString(16)); | ||
}; | ||
case 'blur': | ||
params.blur = (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' ? prepNumber(value.radius) + ',' + prepNumber(value.sigma, 2) : '0,' + prepNumber(value, 2); | ||
break; | ||
var desnag = function desnag(url) { | ||
return url.replace(/[()'"]/g, percentifyChar); | ||
}; | ||
case 'gamma': | ||
params.gamma = (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' ? prepNumber(value.red, 1) + ',' + prepNumber(value.green, 1) + ',' + prepNumber(value.blue, 1) : prepNumber(value, 1); | ||
break; | ||
/** | ||
A whitelist: Crushinator is capable of optimizing images hosted on | ||
any of these domains. | ||
*/ | ||
case 'grayscale': | ||
case 'greyscale': | ||
params.grayscale = prepNumber(value, 1) * 100; | ||
break; | ||
var imageHosts = ['assets.tedcdn.com', 'assets2.tedcdn.com', 'ems.ted.com', 'ems-staging.ted.com', 'images.ted.com', 'pa.tedcdn.com', 'pb-assets.tedcdn.com', 'pe.tedcdn.com', 'pf.tedcdn.com', 'ph.tedcdn.com', 'pj.tedcdn.com', 'pk.tedcdn.com', 'pl.tedcdn.com', 's3.amazonaws.com', 's3-us-west-2.amazonaws.com', 'staging.ted.com', 'storage.ted.com', 'talkstar-photos.s3.amazonaws.com', 'tedcdnpa-a.akamaihd.net', 'tedcdnpe-a.akamaihd.net', 'tedcdnpf-a.akamaihd.net', 'tedconfblog.files.wordpress.com', 'tedideas.files.wordpress.com', 'tedlive.ted.com', 'tedlive-staging.ted.com', 'ted2017.ted.com', 'ted2017-staging.ted.com', 'userdata.amara.org', 'www.filepicker.io', 'www.ted.com']; | ||
/** | ||
Global configuration options. These can be overridden at the library | ||
level or via the options object by individual helper method calls. | ||
*/ | ||
case 'unsharp': | ||
_extends(params, unsharp(options)); | ||
break; | ||
case 'query': | ||
_extends(params, value || {}); | ||
break; | ||
default: | ||
break; | ||
} | ||
}); | ||
return params; | ||
} | ||
/** | ||
Query string helper methods. | ||
*/ | ||
/** | ||
Encode value for use in a URL. | ||
*/ | ||
function encode(value) { | ||
return encodeURIComponent(value); | ||
} | ||
/** | ||
Simple serialization of an object to query parameters. | ||
*/ | ||
function serialize(params, prefix) { | ||
var parts = []; | ||
Object.keys(params).forEach(function (key) { | ||
var value = params[key]; | ||
var param = prefix ? prefix + '[' + key + ']' : key; | ||
parts.push((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' ? serialize(value, param) : encode(param) + '=' + encode(value)); | ||
}); | ||
return parts.join('&'); | ||
} | ||
/** | ||
Given a URL string, returns a version where parentheses and quotation | ||
marks (single and double) are percent-encoded. | ||
Though these characters are legal in URLs, they can cause problems | ||
in some interpolations. Percent encoding them avoids that pitfall. | ||
*/ | ||
var percentifyChar = function percentifyChar(c) { | ||
return "%" + c.charCodeAt(0).toString(16); | ||
}; | ||
var desnag = function desnag(url) { | ||
return url.replace(/[()'"]/g, percentifyChar); | ||
}; | ||
/** | ||
Crushinator Helpers | ||
Library of simple JS methods to produce crushed image URLs. | ||
http://github.com/tedconf/js-crushinator-helpers | ||
*/ | ||
/** | ||
A whitelist: Crushinator is capable of optimizing images hosted on | ||
any of these domains. | ||
*/ | ||
var imageHosts = ['assets.tedcdn.com', 'assets2.tedcdn.com', 'ems.ted.com', 'ems-staging.ted.com', 'images.ted.com', 'pa.tedcdn.com', 'pb-assets.tedcdn.com', 'pe.tedcdn.com', 'pf.tedcdn.com', 'ph.tedcdn.com', 'pj.tedcdn.com', 'pk.tedcdn.com', 'pl.tedcdn.com', 's3.amazonaws.com', 's3-us-west-2.amazonaws.com', 'staging.ted.com', 'storage.ted.com', 'talkstar-photos.s3.amazonaws.com', 'tedcdnpa-a.akamaihd.net', 'tedcdnpe-a.akamaihd.net', 'tedcdnpf-a.akamaihd.net', 'tedconfblog.files.wordpress.com', 'tedideas.files.wordpress.com', 'tedlive.ted.com', 'tedlive-staging.ted.com', 'ted2017.ted.com', 'ted2017-staging.ted.com', 'userdata.amara.org', 'www.filepicker.io', 'www.ted.com']; | ||
/** | ||
Global configuration options. These can be overridden at the library | ||
level or via the options object by individual helper method calls. | ||
*/ | ||
var config = { | ||
var config = { | ||
defaults: true, | ||
host: 'https://pi.tedcdn.com' | ||
}; | ||
}; | ||
/** | ||
Returns the portion of input URL that corresponds to the host name. | ||
/** | ||
Returns the portion of input URL that corresponds to the host name. | ||
@private | ||
@param {string} url | ||
@returns {string} | ||
*/ | ||
@private | ||
@param {string} url | ||
@returns {string} | ||
*/ | ||
function extractHost(url) { | ||
function extractHost(url) { | ||
return String(url).replace(/.*\/\/([^/]+).*/, '$1'); | ||
} | ||
} | ||
/** | ||
Check to see if a URL passes Crushinator's host whitelist. | ||
/** | ||
Check to see if a URL passes Crushinator's host whitelist. | ||
@param {string} url - URL of image to check. | ||
@returns {boolean} | ||
*/ | ||
@param {string} url - URL of image to check. | ||
@returns {boolean} | ||
*/ | ||
function crushable(url) { | ||
function crushable(url) { | ||
return imageHosts.indexOf(extractHost(url)) !== -1; | ||
} | ||
} | ||
/** | ||
Restore a previously crushed URL to its original form. | ||
/** | ||
Restore a previously crushed URL to its original form. | ||
@param {string} url - Previously optimized image URL. | ||
@returns {string} | ||
*/ | ||
@param {string} url - Previously optimized image URL. | ||
@returns {string} | ||
*/ | ||
function uncrush(url) { | ||
var parts = String(url).match(/(.+)?\/\/(?:(?:img(?:-ssl)?|pi)\.tedcdn\.com|tedcdnpi-a\.akamaihd\.net)\/r\/([^?]+)/); | ||
function uncrush(url) { | ||
var parts = String(url).match(/(.+)?\/\/(?:(?:img(?:-ssl)?|pi)\.tedcdn\.com|tedcdnpi-a\.akamaihd\.net)\/r\/([^?]+)/); // Avoid double-crushing images | ||
// Avoid double-crushing images | ||
if (parts) { | ||
return uncrush(parts[1] + '//' + parts[2]); | ||
return uncrush("".concat(parts[1], "//").concat(parts[2])); | ||
} | ||
return url; | ||
} | ||
} | ||
/** | ||
Returns a Crushinator-optimized version of an image URL, using options | ||
specified in a Plain Old JavaScript Object: | ||
/** | ||
Returns a Crushinator-optimized version of an image URL, using options | ||
specified in a Plain Old JavaScript Object: | ||
crush('http://images.ted.com/image.jpg', { width: 320 }) | ||
=> 'https://pi.tedcdn.com/images.ted.com/image.jpg?w=320' | ||
crush('http://images.ted.com/image.jpg', { width: 320 }) | ||
=> 'https://pi.tedcdn.com/images.ted.com/image.jpg?w=320' | ||
If the input URL cannot be optimized (does not pass the whitelist) it | ||
is returned untampered, making this method safe to use for dynamic | ||
image sources. | ||
If the input URL cannot be optimized (does not pass the whitelist) it | ||
is returned untampered, making this method safe to use for dynamic | ||
image sources. | ||
@public | ||
@param {string} url - URL of image to be optimized. | ||
@param {Object} [options] | ||
@param {number} [options.width] - Target image width in pixels. | ||
@param {number} [options.height] - Target image height in pixels. | ||
@param {number} [options.quality] - Image quality as a percentage | ||
(0-100). Defaults to 82. | ||
@param {boolean} [options.fit] - Will zoom and crop the image | ||
for best fit into the target dimensions (width and height) | ||
if both are provided. Defaults to true. | ||
@param {boolean} [options.defaults] - Default options are excluded | ||
if set to false. Defaults to true. | ||
@param {string} [options.align] - If cropping occurs, the image | ||
can be aligned to the "top", "bottom", "left", "right", or | ||
"middle" of the crop frame. | ||
@param {Object} [options.crop] - Image crop configuration. | ||
@param {number} [options.crop.width] - Width of cropped section | ||
in pixels. | ||
@param {number} [options.crop.height] - Height of cropped section | ||
in pixels. | ||
@param {number} [options.crop.x] - Coordinate at which to start crop | ||
(pixels from left.) | ||
@param {number} [options.crop.y] - Coordinate at which to start crop | ||
(pixels from top.) | ||
@param {boolean} [options.crop.afterResize] - If true, crop will | ||
take place after the image has been resized. | ||
@param {Object|number} [options.blur] - Image blur configuration | ||
(object) or blur spread amount in pixels (number). | ||
@param {number} [options.blur.sigma] - Blur spread amount in pixels. | ||
@param {number} [options.blur.radius] - Radial constraint of blur or | ||
zero if unconstrained. Should be at least 2x sigma if specified. | ||
@param {Object|number} [options.gamma] - Gamma correction, applied | ||
either to the whole image (number) or to individual color | ||
channels (object). | ||
@param {number} [options.gamma.red] - Red channel gamma correction. | ||
@param {number} [options.gamma.green] - Green channel gamma correction. | ||
@param {number} [options.gamma.blue] - Blue channel gamma correction. | ||
@param {boolean|number} [options.grayscale] - Fully desaturates the | ||
image if truthy. Optionally you may also darken the image by | ||
specifying a decimal percentage value of less than 1. | ||
@param {Object|boolean} [options.unsharp] - Applies an unsharp mask | ||
if true. Precise configurations can be specified in object form: | ||
@param {number} [options.unsharp.radius] - Number of pixels to which | ||
sharpening should be applied surrounding each target pixel. | ||
@param {number} [options.unsharp.sigma] - Size of details to sharpen | ||
in pixels. (Pedantically: the standard deviation of the Gaussian.) | ||
@param {number} [options.unsharp.amount] - Decimel percentage | ||
representing the strength of the sharpening in terms of the | ||
difference between the sharpened image and the original. | ||
@param {number} [options.unsharp.threshold] - Decimal percentage | ||
representing a minimum amount of difference in a pixel vs | ||
surrounding colors before it's considered a sharpenable detail. | ||
@param {Object} [options.query] - Additional query parameters to | ||
include in the Crushinator-optimized image URL. | ||
@returns {string} | ||
*/ | ||
@public | ||
@param {string} url - URL of image to be optimized. | ||
@param {Object} [options] | ||
@param {number} [options.width] - Target image width in pixels. | ||
@param {number} [options.height] - Target image height in pixels. | ||
@param {number} [options.quality] - Image quality as a percentage | ||
(0-100). Defaults to 82. | ||
@param {boolean} [options.fit] - Will zoom and crop the image | ||
for best fit into the target dimensions (width and height) | ||
if both are provided. Defaults to true. | ||
@param {boolean} [options.defaults] - Default options are excluded | ||
if set to false. Defaults to true. | ||
@param {string} [options.align] - If cropping occurs, the image | ||
can be aligned to the "top", "bottom", "left", "right", or | ||
"middle" of the crop frame. | ||
@param {Object} [options.crop] - Image crop configuration. | ||
@param {number} [options.crop.width] - Width of cropped section | ||
in pixels. | ||
@param {number} [options.crop.height] - Height of cropped section | ||
in pixels. | ||
@param {number} [options.crop.x] - Coordinate at which to start crop | ||
(pixels from left.) | ||
@param {number} [options.crop.y] - Coordinate at which to start crop | ||
(pixels from top.) | ||
@param {boolean} [options.crop.afterResize] - If true, crop will | ||
take place after the image has been resized. | ||
@param {Object|number} [options.blur] - Image blur configuration | ||
(object) or blur spread amount in pixels (number). | ||
@param {number} [options.blur.sigma] - Blur spread amount in pixels. | ||
@param {number} [options.blur.radius] - Radial constraint of blur or | ||
zero if unconstrained. Should be at least 2x sigma if specified. | ||
@param {Object|number} [options.gamma] - Gamma correction, applied | ||
either to the whole image (number) or to individual color | ||
channels (object). | ||
@param {number} [options.gamma.red] - Red channel gamma correction. | ||
@param {number} [options.gamma.green] - Green channel gamma correction. | ||
@param {number} [options.gamma.blue] - Blue channel gamma correction. | ||
@param {boolean|number} [options.grayscale] - Fully desaturates the | ||
image if truthy. Optionally you may also darken the image by | ||
specifying a decimal percentage value of less than 1. | ||
@param {Object|boolean} [options.unsharp] - Applies an unsharp mask | ||
if true. Precise configurations can be specified in object form: | ||
@param {number} [options.unsharp.radius] - Number of pixels to which | ||
sharpening should be applied surrounding each target pixel. | ||
@param {number} [options.unsharp.sigma] - Size of details to sharpen | ||
in pixels. (Pedantically: the standard deviation of the Gaussian.) | ||
@param {number} [options.unsharp.amount] - Decimel percentage | ||
representing the strength of the sharpening in terms of the | ||
difference between the sharpened image and the original. | ||
@param {number} [options.unsharp.threshold] - Decimal percentage | ||
representing a minimum amount of difference in a pixel vs | ||
surrounding colors before it's considered a sharpenable detail. | ||
@param {Object} [options.query] - Additional query parameters to | ||
include in the Crushinator-optimized image URL. | ||
@returns {string} | ||
*/ | ||
function crush(url) { | ||
function crush(url) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
// Avoid double-crushing images | ||
var uncrushed = uncrush(url); | ||
var uncrushed = uncrush(url); // Apply host whitelist | ||
// Apply host whitelist | ||
if (!crushable(uncrushed)) { | ||
return uncrushed; | ||
return uncrushed; | ||
} | ||
var params = {}; | ||
var params = {}; // Complain about use of the deprecated string API | ||
// Complain about use of the deprecated string API | ||
if (typeof options === 'string') { | ||
warn('Sending Crushinator options as a query string is ' + 'deprecated. Please use the object format.'); | ||
params = options; | ||
} | ||
warn('Sending Crushinator options as a query string is ' + 'deprecated. Please use the object format.'); | ||
params = options; | ||
} // Stringify object options while adding defaults | ||
// Stringify object options while adding defaults | ||
if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') { | ||
params = serialize(parameterize(defaultify(_extends({ defaults: config.defaults }, options)))); | ||
if (_typeof(options) === 'object') { | ||
params = serialize(parameterize(defaultify(_extends({ | ||
defaults: config.defaults | ||
}, options)))); | ||
} | ||
return desnag(config.host + '/r/' + uncrushed.replace(/.*\/\//, '') + (params ? '?' + params : '')); | ||
} | ||
return desnag("".concat(config.host, "/r/").concat(uncrushed.replace(/.*\/\//, '')).concat(params ? "?".concat(params) : '')); | ||
} | ||
exports.imageHosts = imageHosts; | ||
exports.config = config; | ||
exports.crushable = crushable; | ||
exports.uncrush = uncrush; | ||
exports.crush = crush; | ||
exports['default'] = crush; | ||
exports.config = config; | ||
exports.crush = crush; | ||
exports.crushable = crushable; | ||
exports.default = crush; | ||
exports.imageHosts = imageHosts; | ||
exports.uncrush = uncrush; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
}))); |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.crushinator=e.crushinator||{})}(this,function(e){"use strict";function t(e){throw new Error(e)}function n(e){k&&"function"==typeof console.warn&&console.warn(e)}function o(e){return void 0===e||null===e||!1===e}function r(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return void 0===e?t:!!e}function a(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r=e;return!0===e&&(r=n||1),o(e)&&(r=n),r=Number(r),isFinite(r)||(t('"'+e+'" is not a finite number'),r=n),r}function c(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return w({},r(e.defaults,!0)?j:{},e)}function i(e){return e.afterResize?"c":"precrop"}function s(e){var t=[];return t.push(a(e.width)),t.push(a(e.height)),(Object.prototype.hasOwnProperty.call(e,"x")||Object.prototype.hasOwnProperty.call(e,"y"))&&(t.push(a(e.x)),t.push(a(e.y))),t.join(",")}function d(e){var t={};return e.fit&&e.width&&e.height&&(w(t,{op:"^",c:a(e.width)+","+a(e.height)}),e.align||(t.gravity="t")),t}function u(e){var t={},n=e.unsharp;return n&&w(t,{u:{r:a(n.radius,2),s:a(n.sigma,.5),a:a(n.amount,.8),t:a(n.threshold,.03)}}),t}function f(e){var t={};return Object.keys(e).forEach(function(n){var o=e[n],r=n.match(/([^-]+)-+(.*)/);r?(t[r[1]]=t[r[1]]||{},t[r[1]][r[2]]=o):t[n]=o}),t}function m(e){var t={},n=f(e);return Object.keys(n).forEach(function(e){var o=n[e];switch(e){case"width":t.w=a(o);break;case"height":t.h=a(o);break;case"quality":t.quality=a(o);break;case"fit":w(t,d(n));break;case"align":t.gravity={top:"n",left:"w",center:"c",middle:"c",right:"e",bottom:"s"}[o]||"c";break;case"crop":t[i(o)]=s(o);break;case"blur":t.blur="object"===(void 0===o?"undefined":v(o))?a(o.radius)+","+a(o.sigma,2):"0,"+a(o,2);break;case"gamma":t.gamma="object"===(void 0===o?"undefined":v(o))?a(o.red,1)+","+a(o.green,1)+","+a(o.blue,1):a(o,1);break;case"grayscale":case"greyscale":t.grayscale=100*a(o,1);break;case"unsharp":w(t,u(n));break;case"query":w(t,o||{})}}),t}function p(e){return encodeURIComponent(e)}function l(e,t){var n=[];return Object.keys(e).forEach(function(o){var r=e[o],a=t?t+"["+o+"]":o;n.push("object"===(void 0===r?"undefined":v(r))?l(r,a):p(a)+"="+p(r))}),n.join("&")}function h(e){return String(e).replace(/.*\/\/([^\/]+).*/,"$1")}function g(e){return-1!==x.indexOf(h(e))}function b(e){var t=String(e).match(/(.+)?\/\/(?:(?:img(?:-ssl)?|pi)\.tedcdn\.com|tedcdnpi-a\.akamaihd\.net)\/r\/([^?]+)/);return t?b(t[1]+"//"+t[2]):e}function y(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=b(e);if(!g(o))return o;var r={};return"string"==typeof t&&(n("Sending Crushinator options as a query string is deprecated. Please use the object format."),r=t),"object"===(void 0===t?"undefined":v(t))&&(r=l(m(c(w({defaults:q.defaults},t))))),S(q.host+"/r/"+o.replace(/.*\/\//,"")+(r?"?"+r:""))}var v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},w=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},k="object"===("undefined"==typeof console?"undefined":v(console)),j={fit:!0,unsharp:!0,quality:82},O=function(e){return"%"+e.charCodeAt(0).toString(16)},S=function(e){return e.replace(/[()'"]/g,O)},x=["assets.tedcdn.com","assets2.tedcdn.com","ems.ted.com","ems-staging.ted.com","images.ted.com","pa.tedcdn.com","pb-assets.tedcdn.com","pe.tedcdn.com","pf.tedcdn.com","ph.tedcdn.com","pj.tedcdn.com","pk.tedcdn.com","pl.tedcdn.com","s3.amazonaws.com","s3-us-west-2.amazonaws.com","staging.ted.com","storage.ted.com","talkstar-photos.s3.amazonaws.com","tedcdnpa-a.akamaihd.net","tedcdnpe-a.akamaihd.net","tedcdnpf-a.akamaihd.net","tedconfblog.files.wordpress.com","tedideas.files.wordpress.com","tedlive.ted.com","tedlive-staging.ted.com","ted2017.ted.com","ted2017-staging.ted.com","userdata.amara.org","www.filepicker.io","www.ted.com"],q={defaults:!0,host:"https://pi.tedcdn.com"};e.imageHosts=x,e.config=q,e.crushable=g,e.uncrush=b,e.crush=y,e.default=y,Object.defineProperty(e,"__esModule",{value:!0})}); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).crushinator={})}(this,function(t){"use strict";function u(t){return(u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function f(){return(f=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var c=arguments[e];for(var n in c)Object.prototype.hasOwnProperty.call(c,n)&&(t[n]=c[n])}return t}).apply(this,arguments)}var a="object"===("undefined"==typeof console?"undefined":u(console));function p(t,e){var c,n=1<arguments.length&&void 0!==e?e:0,o=t;return!0===t&&(o=n||1),null!=(c=t)&&!1!==c||(o=n),o=Number(o),isFinite(o)||(function(t){throw new Error(t)}('"'.concat(t,'" is not a finite number')),o=n),o}var c={fit:!0,unsharp:!0,quality:82};function r(t){var e=0<arguments.length&&void 0!==t?t:{};return f({},function(t,e){return void 0===t?1<arguments.length&&void 0!==e&&e:t}(e.defaults,!0)?c:{},e)}function s(t){var n,o,i={},d=(n=t,o={},Object.keys(n).forEach(function(t){var e=n[t],c=t.match(/([^-]+)-+(.*)/);c?(o[c[1]]=o[c[1]]||{},o[c[1]][c[2]]=e):o[t]=e}),o);return Object.keys(d).forEach(function(t){var e,c,n,o,a,r,s=d[t];switch(t){case"width":i.w=p(s);break;case"height":i.h=p(s);break;case"quality":i.quality=p(s);break;case"fit":f(i,(r={},(a=d).fit&&a.width&&a.height&&(f(r,{op:"^",c:"".concat(p(a.width),",").concat(p(a.height))}),a.align||(r.gravity="t")),r));break;case"align":i.gravity={top:"n",left:"w",center:"c",middle:"c",right:"e",bottom:"s"}[s]||"c";break;case"crop":i[s.afterResize?"c":"precrop"]=((o=[]).push(p((n=s).width)),o.push(p(n.height)),(Object.prototype.hasOwnProperty.call(n,"x")||Object.prototype.hasOwnProperty.call(n,"y"))&&(o.push(p(n.x)),o.push(p(n.y))),o.join(","));break;case"blur":i.blur="object"===u(s)?"".concat(p(s.radius),",").concat(p(s.sigma,2)):"0,".concat(p(s,2));break;case"gamma":i.gamma="object"===u(s)?"".concat(p(s.red,1),",").concat(p(s.green,1),",").concat(p(s.blue,1)):p(s,1);break;case"grayscale":case"greyscale":i.grayscale=100*p(s,1);break;case"unsharp":f(i,(e={},(c=d.unsharp)&&f(e,{u:{r:p(c.radius,2),s:p(c.sigma,.5),a:p(c.amount,.8),t:p(c.threshold,.03)}}),e));break;case"query":f(i,s||{})}}),i}function i(t){return encodeURIComponent(t)}function d(t){return"%".concat(t.charCodeAt(0).toString(16))}var e=["assets.tedcdn.com","assets2.tedcdn.com","ems.ted.com","ems-staging.ted.com","images.ted.com","pa.tedcdn.com","pb-assets.tedcdn.com","pe.tedcdn.com","pf.tedcdn.com","ph.tedcdn.com","pj.tedcdn.com","pk.tedcdn.com","pl.tedcdn.com","s3.amazonaws.com","s3-us-west-2.amazonaws.com","staging.ted.com","storage.ted.com","talkstar-photos.s3.amazonaws.com","tedcdnpa-a.akamaihd.net","tedcdnpe-a.akamaihd.net","tedcdnpf-a.akamaihd.net","tedconfblog.files.wordpress.com","tedideas.files.wordpress.com","tedlive.ted.com","tedlive-staging.ted.com","ted2017.ted.com","ted2017-staging.ted.com","userdata.amara.org","www.filepicker.io","www.ted.com"],m={defaults:!0,host:"https://pi.tedcdn.com"};function l(t){return-1!==e.indexOf(String(t).replace(/.*\/\/([^/]+).*/,"$1"))}function h(t){var e=String(t).match(/(.+)?\/\/(?:(?:img(?:-ssl)?|pi)\.tedcdn\.com|tedcdnpi-a\.akamaihd\.net)\/r\/([^?]+)/);return e?h("".concat(e[1],"//").concat(e[2])):t}function n(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},c=h(t);if(!l(c))return c;var n,o={};return"string"==typeof e&&(n="Sending Crushinator options as a query string is deprecated. Please use the object format.",a&&"function"==typeof console.warn&&console.warn(n),o=e),"object"===u(e)&&(o=function n(o,a){var r=[];return Object.keys(o).forEach(function(t){var e=o[t],c=a?"".concat(a,"[").concat(t,"]"):t;r.push("object"===u(e)?n(e,c):"".concat(i(c),"=").concat(i(e)))}),r.join("&")}(s(r(f({defaults:m.defaults},e))))),"".concat(m.host,"/r/").concat(c.replace(/.*\/\//,"")).concat(o?"?".concat(o):"").replace(/[()'"]/g,d)}t.config=m,t.crush=n,t.crushable=l,t.default=n,t.imageHosts=e,t.uncrush=h,Object.defineProperty(t,"__esModule",{value:!0})}); |
{ | ||
"name": "ted-crushinator-helpers", | ||
"version": "2.7.0", | ||
"version": "2.8.0", | ||
"description": "JS methods to produce crushinator'd image URLs.", | ||
"license": "MIT", | ||
"author": "TED Tech", | ||
"license": "UNLICENSED", | ||
"files": [ | ||
"dist" | ||
], | ||
"main": "dist/crushinator.umd.min.js", | ||
"types": "dist/crushinator.d.ts", | ||
"repository": { | ||
@@ -14,10 +19,10 @@ "type": "git", | ||
"lint": "eslint {src,test}{/*.js,/**/*.js}", | ||
"pretest": "npm run lint", | ||
"test": "yarn test:fast --ci --colors --silent --testResultsProcessor=\"jest-junit\" --coverage", | ||
"pretest": "yarn lint", | ||
"test": "yarn test:fast --ci --silent --coverage --reporters=jest-junit", | ||
"test:fast": "jest --colors", | ||
"test:watch": "jest --watch", | ||
"prepush": "run-p --aggregate-output \"lint\" \"test:fast\"" | ||
"test:watch": "jest --watch" | ||
}, | ||
"jest-junit": { | ||
"output": "./spec/reports/test-results.xml", | ||
"outputDirectory": "./spec/reports", | ||
"outputName": "test-results.xml", | ||
"ancestorSeparator": " › " | ||
@@ -27,19 +32,14 @@ }, | ||
"devDependencies": { | ||
"babel-jest": "22.0.4", | ||
"babel-plugin-external-helpers": "^6.22.0", | ||
"babel-plugin-transform-object-assign": "^6.22.0", | ||
"babel-preset-es2015": "^6.22.0", | ||
"babel-register": "^6.22.0", | ||
"eslint": "^3.13.0", | ||
"eslint-config-airbnb-base": "^11.0.0", | ||
"eslint-plugin-import": "^2.2.0", | ||
"husky": "0.14.3", | ||
"jest": "22.0.5", | ||
"jest-junit": "3.4.1", | ||
"mocha": "^3.2.0", | ||
"npm-run-all": "4.1.2", | ||
"rollup": "^0.41.4", | ||
"rollup-plugin-babel": "^2.7.1", | ||
"rollup-plugin-uglify": "^1.0.1" | ||
"@babel/core": "^7.8.0", | ||
"@babel/plugin-transform-object-assign": "^7.8.0", | ||
"@babel/preset-env": "^7.8.0", | ||
"babel-core": "^7.0.0-bridge.0", | ||
"eslint": "^6.8.0", | ||
"eslint-plugin-import": "^2.20.0", | ||
"jest": "^26.0.1", | ||
"jest-junit": "^10.0.0", | ||
"rollup": "^1.31.0", | ||
"rollup-plugin-babel": "^4.3.0", | ||
"rollup-plugin-uglify": "^6.0.0" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Explicitly Unlicensed Item
License(Experimental) Something was found which is explicitly marked as unlicensed.
Found 1 instance in 1 package
Misc. License Issues
License(Experimental) A package's licensing information has fine-grained problems.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
11
1
0
57828
8
1
1
1
0
907