From bca9300bbe1a8e2eef9b8c222b92f0cc8a7c885f Mon Sep 17 00:00:00 2001 From: imgix-git-robot Date: Thu, 24 Feb 2022 18:12:14 +0000 Subject: [PATCH] chore(release): 3.5.0 # [3.5.0](https://github.com/imgix/js-core/compare/v3.4.0...v3.5.0) (2022-02-24) ### Bug Fixes * ensure slash always between domain and path when sanitizing ([929e878](https://github.com/imgix/js-core/commit/929e878a513d9d6e755e691c7caadb8eb16e2ce0)) ### Features * allow path encoding to be disabled ([1413800](https://github.com/imgix/js-core/commit/1413800f2eb87e4f08dde0890aef1f078a6471b5)) [skip ci] --- dist/imgix-js-core.umd.js | 2 +- dist/index.cjs.js | 115 +++++++++++++++++++++----------------- dist/index.d.ts | 7 ++- dist/index.esm.js | 113 +++++++++++++++++++++---------------- package.json | 2 +- src/constants.js | 2 +- 6 files changed, 138 insertions(+), 103 deletions(-) diff --git a/dist/imgix-js-core.umd.js b/dist/imgix-js-core.umd.js index 4e91f545..193fff9f 100644 --- a/dist/imgix-js-core.umd.js +++ b/dist/imgix-js-core.umd.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).ImgixClient=e()}(this,function(){"use strict";function e(e,t){var r,n=Object.keys(e);return Object.getOwnPropertySymbols&&(r=Object.getOwnPropertySymbols(e),t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)),n}function s(n){for(var t=1;tt.length)&&(e=t.length);for(var r=0,n=new Array(e);r>>32-e},rotr:function(t,e){return t<<32-e|t>>>e},endian:function(t){if(t.constructor==Number)return 16711935&r.rotl(t,8)|4278255360&r.rotl(t,24);for(var e=0;e>>5]|=t[r]<<24-n%32;return e},wordsToBytes:function(t){for(var e=[],r=0;r<32*t.length;r+=8)e.push(t[r>>>5]>>>24-r%32&255);return e},bytesToHex:function(t){for(var e=[],r=0;r>>4).toString(16)),e.push((15&t[r]).toString(16));return e.join("")},hexToBytes:function(t){for(var e=[],r=0;r>>6*(3-o)&63)):e.push("=");return e.join("")},base64ToBytes:function(t){t=t.replace(/[^A-Z0-9+\/]/gi,"");for(var e=[],r=0,n=0;r>>6-2*n);return e}},t.exports=r}),u={utf8:{stringToBytes:function(t){return u.bin.stringToBytes(unescape(encodeURIComponent(t)))},bytesToString:function(t){return decodeURIComponent(escape(u.bin.bytesToString(t)))}},bin:{stringToBytes:function(t){for(var e=[],r=0;r>>24)|4278255360&(r[u]<<24|r[u]>>>8);r[t>>>5]|=128<>>9<<4)]=t;for(var s=p._ff,c=p._gg,l=p._hh,f=p._ii,u=0;u>>0,o=o+d>>>0,i=i+y>>>0,a=a+b>>>0}return g.endian([n,o,i,a])}var g,m,v,w;g=a,m=h.utf8,v=i,w=h.bin,p._ff=function(t,e,r,n,o,i,a){a=t+(e&r|~e&n)+(o>>>0)+a;return(a<>>32-i)+e},p._gg=function(t,e,r,n,o,i,a){a=t+(e&n|r&~n)+(o>>>0)+a;return(a<>>32-i)+e},p._hh=function(t,e,r,n,o,i,a){a=t+(e^r^n)+(o>>>0)+a;return(a<>>32-i)+e},p._ii=function(t,e,r,n,o,i,a){a=t+(r^(e|~n))+(o>>>0)+a;return(a<>>32-i)+e},p._blocksize=16,p._digestsize=16,t.exports=function(t,e){if(null==t)throw new Error("Illegal argument "+t);t=g.wordsToBytes(p(t,e));return e&&e.asBytes?t:e&&e.asString?w.bytesToString(t):g.bytesToHex(t)}}),b="3.7.2",p="function"==typeof atob,g="function"==typeof btoa,m="function"==typeof Buffer;const v="function"==typeof TextDecoder?new TextDecoder:void 0,w="function"==typeof TextEncoder?new TextEncoder:void 0;const A=Array.prototype.slice.call("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="),x=(t=>{let r={};return t.forEach((t,e)=>r[t]=e),r})(A),S=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,T=String.fromCharCode.bind(String),P="function"==typeof Uint8Array.from?Uint8Array.from.bind(Uint8Array):(t,e=t=>t)=>new Uint8Array(Array.prototype.slice.call(t,0).map(e)),B=t=>t.replace(/=/g,"").replace(/[+\/]/g,t=>"+"==t?"-":"_"),C=t=>t.replace(/[^A-Za-z0-9\+\/]/g,"");var j=e=>{let r,n,o,i,a="";var t=e.length%3;for(let t=0;t>18&63]+A[r>>12&63]+A[r>>6&63]+A[63&r]}return t?a.slice(0,t-3)+"===".substring(t):a};const U=g?t=>btoa(t):m?t=>Buffer.from(t,"binary").toString("base64"):j,R=m?t=>Buffer.from(t).toString("base64"):r=>{let n=[];for(let t=0,e=r.length;te?B(R(t)):R(t),E=t=>{if(t.length<2)return(e=t.charCodeAt(0))<128?t:e<2048?T(192|e>>>6)+T(128|63&e):T(224|e>>>12&15)+T(128|e>>>6&63)+T(128|63&e);var e=65536+1024*(t.charCodeAt(0)-55296)+(t.charCodeAt(1)-56320);return T(240|e>>>18&7)+T(128|e>>>12&63)+T(128|e>>>6&63)+T(128|63&e)},I=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,_=t=>t.replace(I,E),F=m?t=>Buffer.from(t,"utf8").toString("base64"):w?t=>R(w.encode(t)):t=>U(_(t)),k=(t,e=!1)=>e?B(F(t)):F(t);var z=t=>k(t,!0);const D=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,L=t=>{switch(t.length){case 4:var e=((7&t.charCodeAt(0))<<18|(63&t.charCodeAt(1))<<12|(63&t.charCodeAt(2))<<6|63&t.charCodeAt(3))-65536;return T(55296+(e>>>10))+T(56320+(1023&e));case 3:return T((15&t.charCodeAt(0))<<12|(63&t.charCodeAt(1))<<6|63&t.charCodeAt(2));default:return T((31&t.charCodeAt(0))<<6|63&t.charCodeAt(1))}},W=t=>t.replace(D,L);g=e=>{if(e=e.replace(/\s+/g,""),!S.test(e))throw new TypeError("malformed base64.");e+="==".slice(2-(3&e.length));let r,n="",o,i;for(let t=0;t>16&255):64===i?T(r>>16&255,r>>8&255):T(r>>16&255,r>>8&255,255&r);return n};const M=p?t=>atob(C(t)):m?t=>Buffer.from(t,"base64").toString("binary"):g,Z=m?t=>P(Buffer.from(t,"base64")):t=>P(M(t),t=>t.charCodeAt(0)),N=t=>Z(q(t)),Q=m?t=>Buffer.from(t,"base64").toString("utf8"):v?t=>v.decode(Z(t)):t=>W(M(t)),q=t=>C(t.replace(/[-_]/g,t=>"-"==t?"+":"/")),H=t=>Q(q(t));function V(){var t=(t,e)=>Object.defineProperty(String.prototype,t,G(e));t("fromBase64",function(){return H(this)}),t("toBase64",function(t){return k(this,t)}),t("toBase64URI",function(){return k(this,!0)}),t("toBase64URL",function(){return k(this,!0)}),t("toUint8Array",function(){return N(this)})}function $(){var t=(t,e)=>Object.defineProperty(Uint8Array.prototype,t,G(e));t("toBase64",function(t){return O(this,t)}),t("toBase64URI",function(){return O(this,!0)}),t("toBase64URL",function(){return O(this,!0)})}const G=t=>({value:t,enumerable:!1,writable:!0,configurable:!0});const J={version:b,VERSION:"3.7.2",atob:M,atobPolyfill:g,btoa:U,btoaPolyfill:j,fromBase64:H,toBase64:k,encode:k,encodeURI:z,encodeURL:z,utob:_,btou:W,decode:H,isValid:t=>{if("string"!=typeof t)return!1;t=t.replace(/\s+/g,"").replace(/={0,2}$/,"");return!/[^\s0-9a-zA-Z\+/]/.test(t)||!/[^\s0-9a-zA-Z\-_]/.test(t)},fromUint8Array:O,toUint8Array:N,extendString:V,extendUint8Array:$,extendBuiltins:()=>{V(),$()}};var K=/^(?:[a-z\d\-_]{1,62}\.){0,125}(?:[a-z\d](?:\-(?=\-*[a-z\d])|[a-z]|\d){0,62}\.)[a-z\d]{1,63}$/i,X={1:75,2:50,3:35,4:23,5:20},Y=[1,2,3,4,5],tt={domain:null,useHTTPS:!0,includeLibraryParam:!0,urlPrefix:"https://",secureURLToken:null};function et(t,e){if(!Number.isInteger(t)||!Number.isInteger(e)||t<=0||e<=0||et.length)&&(e=t.length);for(var r=0,n=new Array(e);r>>32-e},rotr:function(t,e){return t<<32-e|t>>>e},endian:function(t){if(t.constructor==Number)return 16711935&r.rotl(t,8)|4278255360&r.rotl(t,24);for(var e=0;e>>5]|=t[r]<<24-n%32;return e},wordsToBytes:function(t){for(var e=[],r=0;r<32*t.length;r+=8)e.push(t[r>>>5]>>>24-r%32&255);return e},bytesToHex:function(t){for(var e=[],r=0;r>>4).toString(16)),e.push((15&t[r]).toString(16));return e.join("")},hexToBytes:function(t){for(var e=[],r=0;r>>6*(3-o)&63)):e.push("=");return e.join("")},base64ToBytes:function(t){t=t.replace(/[^A-Z0-9+\/]/gi,"");for(var e=[],r=0,n=0;r>>6-2*n);return e}},t.exports=r}),g={utf8:{stringToBytes:function(t){return g.bin.stringToBytes(unescape(encodeURIComponent(t)))},bytesToString:function(t){return decodeURIComponent(escape(g.bin.bytesToString(t)))}},bin:{stringToBytes:function(t){for(var e=[],r=0;r>>24)|4278255360&(t[i]<<24|t[i]>>>8);t[f>>>5]|=128<>>9<<4)]=f;for(var a=g._ff,u=g._gg,s=g._hh,c=g._ii,i=0;i>>0,r=r+h>>>0,n=n+y>>>0,o=o+b>>>0}return p.endian([e,r,n,o])}var p,v,m,w;p=x,v=P.utf8,m=A,w=P.bin,g._ff=function(t,e,r,n,o,i,a){t=t+(e&r|~e&n)+(o>>>0)+a;return(t<>>32-i)+e},g._gg=function(t,e,r,n,o,i,a){t=t+(e&n|r&~n)+(o>>>0)+a;return(t<>>32-i)+e},g._hh=function(t,e,r,n,o,i,a){t=t+(e^r^n)+(o>>>0)+a;return(t<>>32-i)+e},g._ii=function(t,e,r,n,o,i,a){t=t+(r^(e|~n))+(o>>>0)+a;return(t<>>32-i)+e},g._blocksize=16,g._digestsize=16,t.exports=function(t,e){if(null==t)throw new Error("Illegal argument "+t);t=p.wordsToBytes(g(t,e));return e&&e.asBytes?t:e&&e.asString?w.bytesToString(t):p.bytesToHex(t)}}),m="3.7.2",w="function"==typeof atob,t="function"==typeof btoa,e="function"==typeof Buffer;const S="function"==typeof TextDecoder?new TextDecoder:void 0,T="function"==typeof TextEncoder?new TextEncoder:void 0;const u=Array.prototype.slice.call("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="),a=(t=>{let r={};return t.forEach((t,e)=>r[t]=e),r})(u),B=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,s=String.fromCharCode.bind(String),C="function"==typeof Uint8Array.from?Uint8Array.from.bind(Uint8Array):(t,e=t=>t)=>new Uint8Array(Array.prototype.slice.call(t,0).map(e)),j=t=>t.replace(/=/g,"").replace(/[+\/]/g,t=>"+"==t?"-":"_"),E=t=>t.replace(/[^A-Za-z0-9\+\/]/g,"");var U=e=>{let r,n,o,i,a="";var t=e.length%3;for(let t=0;t>18&63]+u[r>>12&63]+u[r>>6&63]+u[63&r]}return t?a.slice(0,t-3)+"===".substring(t):a};const R=t?t=>btoa(t):e?t=>Buffer.from(t,"binary").toString("base64"):U,O=e?t=>Buffer.from(t).toString("base64"):r=>{let n=[];for(let t=0,e=r.length;te?j(O(t)):O(t),I=t=>{var e;return t.length<2?(e=t.charCodeAt(0))<128?t:e<2048?s(192|e>>>6)+s(128|63&e):s(224|e>>>12&15)+s(128|e>>>6&63)+s(128|63&e):(e=65536+1024*(t.charCodeAt(0)-55296)+(t.charCodeAt(1)-56320),s(240|e>>>18&7)+s(128|e>>>12&63)+s(128|e>>>6&63)+s(128|63&e))},_=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,F=t=>t.replace(_,I),k=e?t=>Buffer.from(t,"utf8").toString("base64"):T?t=>O(T.encode(t)):t=>R(F(t)),o=(t,e=!1)=>e?j(k(t)):k(t);t=t=>o(t,!0);const z=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,D=t=>{switch(t.length){case 4:var e=((7&t.charCodeAt(0))<<18|(63&t.charCodeAt(1))<<12|(63&t.charCodeAt(2))<<6|63&t.charCodeAt(3))-65536;return s(55296+(e>>>10))+s(56320+(1023&e));case 3:return s((15&t.charCodeAt(0))<<12|(63&t.charCodeAt(1))<<6|63&t.charCodeAt(2));default:return s((31&t.charCodeAt(0))<<6|63&t.charCodeAt(1))}},L=t=>t.replace(z,D);var W=e=>{if(e=e.replace(/\s+/g,""),!B.test(e))throw new TypeError("malformed base64.");e+="==".slice(2-(3&e.length));let r,n="",o,i;for(let t=0;t>16&255):64===i?s(r>>16&255,r>>8&255):s(r>>16&255,r>>8&255,255&r);return n};const M=w?t=>atob(E(t)):e?t=>Buffer.from(t,"base64").toString("binary"):W,Z=e?t=>C(Buffer.from(t,"base64")):t=>C(M(t),t=>t.charCodeAt(0)),N=t=>Z(q(t)),Q=e?t=>Buffer.from(t,"base64").toString("utf8"):S?t=>S.decode(Z(t)):t=>L(M(t)),q=t=>E(t.replace(/[-_]/g,t=>"-"==t?"+":"/")),H=t=>Q(q(t));function V(){var t=(t,e)=>Object.defineProperty(String.prototype,t,G(e));t("fromBase64",function(){return H(this)}),t("toBase64",function(t){return o(this,t)}),t("toBase64URI",function(){return o(this,!0)}),t("toBase64URL",function(){return o(this,!0)}),t("toUint8Array",function(){return N(this)})}function $(){var t=(t,e)=>Object.defineProperty(Uint8Array.prototype,t,G(e));t("toBase64",function(t){return r(this,t)}),t("toBase64URI",function(){return r(this,!0)}),t("toBase64URL",function(){return r(this,!0)})}const G=t=>({value:t,enumerable:!1,writable:!0,configurable:!0});const J={version:m,VERSION:"3.7.2",atob:M,atobPolyfill:W,btoa:R,btoaPolyfill:U,fromBase64:H,toBase64:o,encode:o,encodeURI:t,encodeURL:t,utob:F,btou:L,decode:H,isValid:t=>{if("string"!=typeof t)return!1;t=t.replace(/\s+/g,"").replace(/={0,2}$/,"");return!/[^\s0-9a-zA-Z\+/]/.test(t)||!/[^\s0-9a-zA-Z\-_]/.test(t)},fromUint8Array:r,toUint8Array:N,extendString:V,extendUint8Array:$,extendBuiltins:()=>{V(),$()}};var K=/^(?:[a-z\d\-_]{1,62}\.){0,125}(?:[a-z\d](?:\-(?=\-*[a-z\d])|[a-z]|\d){0,62}\.)[a-z\d]{1,63}$/i,X={1:75,2:50,3:35,4:23,5:20},Y=[1,2,3,4,5],tt={domain:null,useHTTPS:!0,includeLibraryParam:!0,urlPrefix:"https://",secureURLToken:null};function et(t,e){if(!Number.isInteger(t)||!Number.isInteger(e)||t<=0||e<=0||e 0 && arguments[0] !== undefined ? arguments[0] : ''; + var rawPath = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - var sanitizedPath = this._sanitizePath(path); + var path = this._sanitizePath(rawPath, { + encode: !options.disablePathEncoding + }); var finalParams = this._buildParams(params); if (!!this.settings.secureURLToken) { - finalParams = this._signParams(sanitizedPath, finalParams); + finalParams = this._signParams(path, finalParams); } - return this.settings.urlPrefix + this.settings.domain + sanitizedPath + finalParams; + return this.settings.urlPrefix + this.settings.domain + path + finalParams; } }, { key: "_buildParams", @@ -331,23 +319,38 @@ var ImgixClient = /*#__PURE__*/function () { key: "_signParams", value: function _signParams(path, queryParams) { var signatureBase = this.settings.secureURLToken + path + queryParams; - var signature = md5__default['default'](signatureBase); + var signature = md5__default["default"](signatureBase); return queryParams.length > 0 ? queryParams + '&s=' + signature : '?s=' + signature; } + /** + * "Sanitize" the path of the image URL. + * Ensures that the path has a leading slash, and that the path is correctly + * encoded. If it's a proxy path (begins with http/https), then encode the + * whole path as a URI component, otherwise only encode specific characters. + * @param {string} path The URL path of the image + * @param {Object} options Sanitization options + * @param {boolean} options.encode Whether to encode the path, default true + * @returns {string} The sanitized path + */ + }, { key: "_sanitizePath", value: function _sanitizePath(path) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + // Strip leading slash first (we'll re-add after encoding) var _path = path.replace(/^\//, ''); - if (/^https?:\/\//.test(_path)) { - // Use de/encodeURIComponent to ensure *all* characters are handled, - // since it's being used as a path - _path = encodeURIComponent(_path); - } else { - // Use de/encodeURI if we think the path is just a path, - // so it leaves legal characters like '/' and '@' alone - _path = encodeURI(_path).replace(/[#?:+]/g, encodeURIComponent); + if (!(options.encode === false)) { + if (/^https?:\/\//.test(_path)) { + // Use de/encodeURIComponent to ensure *all* characters are handled, + // since it's being used as a path + _path = encodeURIComponent(_path); + } else { + // Use de/encodeURI if we think the path is just a path, + // so it leaves legal characters like '/' and '@' alone + _path = encodeURI(_path).replace(/[#?:+]/g, encodeURIComponent); + } } return '/' + _path; @@ -369,9 +372,12 @@ var ImgixClient = /*#__PURE__*/function () { }, { key: "_buildSrcSetPairs", - value: function _buildSrcSetPairs(path, params, options) { + value: function _buildSrcSetPairs(path) { var _this = this; + var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var _validateAndDestructu = validateAndDestructureOptions(options), _validateAndDestructu2 = _slicedToArray(_validateAndDestructu, 3), widthTolerance = _validateAndDestructu2[0], @@ -390,15 +396,20 @@ var ImgixClient = /*#__PURE__*/function () { var srcset = targetWidthValues.map(function (w) { return "".concat(_this.buildURL(path, _objectSpread2(_objectSpread2({}, params), {}, { w: w - })), " ").concat(w, "w"); + }), { + disablePathEncoding: options.disablePathEncoding + }), " ").concat(w, "w"); }); return srcset.join(',\n'); } }, { key: "_buildDPRSrcSet", - value: function _buildDPRSrcSet(path, params, options) { + value: function _buildDPRSrcSet(path) { var _this2 = this; + var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + if (options.devicePixelRatios) { validateDevicePixelRatios(options.devicePixelRatios); } @@ -420,13 +431,17 @@ var ImgixClient = /*#__PURE__*/function () { return "".concat(_this2.buildURL(path, _objectSpread2(_objectSpread2({}, params), {}, { dpr: dpr, q: params.q || qualities[dpr] || qualities[Math.floor(dpr)] - })), " ").concat(dpr, "x"); + }), { + disablePathEncoding: options.disablePathEncoding + }), " ").concat(dpr, "x"); }; var srcset = disableVariableQuality ? targetRatios.map(function (dpr) { return "".concat(_this2.buildURL(path, _objectSpread2(_objectSpread2({}, params), {}, { dpr: dpr - })), " ").concat(dpr, "x"); + }), { + disablePathEncoding: options.disablePathEncoding + }), " ").concat(dpr, "x"); }) : targetRatios.map(function (dpr) { return withQuality(path, params, dpr); }); diff --git a/dist/index.d.ts b/dist/index.d.ts index 91365eae..7806b7f8 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -11,7 +11,11 @@ declare class ImgixClient { includeLibraryParam?: boolean; }); - buildURL(path: string, params?: {}): string; + buildURL( + path: string, + params?: {}, + options?: { disablePathEncoding?: boolean }, + ): string; _sanitizePath(path: string): string; _buildParams(params: {}): string; _signParams(path: string, queryParams?: {}): string; @@ -38,6 +42,7 @@ export interface SrcSetOptions { disableVariableQuality?: boolean; devicePixelRatios?: DevicePixelRatio[]; variableQualities?: VariableQualities; + disablePathEncoding?: boolean; } export default ImgixClient; diff --git a/dist/index.esm.js b/dist/index.esm.js index 53d276c2..b1562678 100644 --- a/dist/index.esm.js +++ b/dist/index.esm.js @@ -6,14 +6,9 @@ function ownKeys(object, enumerableOnly) { if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); - - if (enumerableOnly) { - symbols = symbols.filter(function (sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable; - }); - } - - keys.push.apply(keys, symbols); + enumerableOnly && (symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + })), keys.push.apply(keys, symbols); } return keys; @@ -21,19 +16,12 @@ function ownKeys(object, enumerableOnly) { function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { - var source = arguments[i] != null ? arguments[i] : {}; - - if (i % 2) { - ownKeys(Object(source), true).forEach(function (key) { - _defineProperty(target, key, source[key]); - }); - } else if (Object.getOwnPropertyDescriptors) { - Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); - } else { - ownKeys(Object(source)).forEach(function (key) { - Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); - }); - } + var source = null != arguments[i] ? arguments[i] : {}; + i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { + _defineProperty(target, key, source[key]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); } return target; @@ -42,17 +30,11 @@ function _objectSpread2(target) { 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); + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { + return typeof obj; + } : function (obj) { + return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }, _typeof(obj); } function _classCallCheck(instance, Constructor) { @@ -74,6 +56,9 @@ function _defineProperties(target, props) { function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); + Object.defineProperty(Constructor, "prototype", { + writable: false + }); return Constructor; } @@ -288,18 +273,21 @@ var ImgixClient = /*#__PURE__*/function () { _createClass(ImgixClient, [{ key: "buildURL", value: function buildURL() { - var path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var rawPath = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - var sanitizedPath = this._sanitizePath(path); + var path = this._sanitizePath(rawPath, { + encode: !options.disablePathEncoding + }); var finalParams = this._buildParams(params); if (!!this.settings.secureURLToken) { - finalParams = this._signParams(sanitizedPath, finalParams); + finalParams = this._signParams(path, finalParams); } - return this.settings.urlPrefix + this.settings.domain + sanitizedPath + finalParams; + return this.settings.urlPrefix + this.settings.domain + path + finalParams; } }, { key: "_buildParams", @@ -328,20 +316,35 @@ var ImgixClient = /*#__PURE__*/function () { var signature = md5(signatureBase); return queryParams.length > 0 ? queryParams + '&s=' + signature : '?s=' + signature; } + /** + * "Sanitize" the path of the image URL. + * Ensures that the path has a leading slash, and that the path is correctly + * encoded. If it's a proxy path (begins with http/https), then encode the + * whole path as a URI component, otherwise only encode specific characters. + * @param {string} path The URL path of the image + * @param {Object} options Sanitization options + * @param {boolean} options.encode Whether to encode the path, default true + * @returns {string} The sanitized path + */ + }, { key: "_sanitizePath", value: function _sanitizePath(path) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + // Strip leading slash first (we'll re-add after encoding) var _path = path.replace(/^\//, ''); - if (/^https?:\/\//.test(_path)) { - // Use de/encodeURIComponent to ensure *all* characters are handled, - // since it's being used as a path - _path = encodeURIComponent(_path); - } else { - // Use de/encodeURI if we think the path is just a path, - // so it leaves legal characters like '/' and '@' alone - _path = encodeURI(_path).replace(/[#?:+]/g, encodeURIComponent); + if (!(options.encode === false)) { + if (/^https?:\/\//.test(_path)) { + // Use de/encodeURIComponent to ensure *all* characters are handled, + // since it's being used as a path + _path = encodeURIComponent(_path); + } else { + // Use de/encodeURI if we think the path is just a path, + // so it leaves legal characters like '/' and '@' alone + _path = encodeURI(_path).replace(/[#?:+]/g, encodeURIComponent); + } } return '/' + _path; @@ -363,9 +366,12 @@ var ImgixClient = /*#__PURE__*/function () { }, { key: "_buildSrcSetPairs", - value: function _buildSrcSetPairs(path, params, options) { + value: function _buildSrcSetPairs(path) { var _this = this; + var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var _validateAndDestructu = validateAndDestructureOptions(options), _validateAndDestructu2 = _slicedToArray(_validateAndDestructu, 3), widthTolerance = _validateAndDestructu2[0], @@ -384,15 +390,20 @@ var ImgixClient = /*#__PURE__*/function () { var srcset = targetWidthValues.map(function (w) { return "".concat(_this.buildURL(path, _objectSpread2(_objectSpread2({}, params), {}, { w: w - })), " ").concat(w, "w"); + }), { + disablePathEncoding: options.disablePathEncoding + }), " ").concat(w, "w"); }); return srcset.join(',\n'); } }, { key: "_buildDPRSrcSet", - value: function _buildDPRSrcSet(path, params, options) { + value: function _buildDPRSrcSet(path) { var _this2 = this; + var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + if (options.devicePixelRatios) { validateDevicePixelRatios(options.devicePixelRatios); } @@ -414,13 +425,17 @@ var ImgixClient = /*#__PURE__*/function () { return "".concat(_this2.buildURL(path, _objectSpread2(_objectSpread2({}, params), {}, { dpr: dpr, q: params.q || qualities[dpr] || qualities[Math.floor(dpr)] - })), " ").concat(dpr, "x"); + }), { + disablePathEncoding: options.disablePathEncoding + }), " ").concat(dpr, "x"); }; var srcset = disableVariableQuality ? targetRatios.map(function (dpr) { return "".concat(_this2.buildURL(path, _objectSpread2(_objectSpread2({}, params), {}, { dpr: dpr - })), " ").concat(dpr, "x"); + }), { + disablePathEncoding: options.disablePathEncoding + }), " ").concat(dpr, "x"); }) : targetRatios.map(function (dpr) { return withQuality(path, params, dpr); }); diff --git a/package.json b/package.json index a085a6af..1887fb95 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@imgix/js-core", "description": "A JavaScript client library for generating image URLs with imgix", - "version": "3.4.0", + "version": "3.5.0", "repository": "https://github.com/imgix/js-core", "license": "BSD-2-Clause", "main": "dist/index.cjs.js", diff --git a/src/constants.js b/src/constants.js index 30eb00ab..fb4e41a9 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,5 +1,5 @@ // package version used in the ix-lib parameter -export const VERSION = '3.4.0'; +export const VERSION = '3.5.0'; // regex pattern used to determine if a domain is valid export const DOMAIN_REGEX = /^(?:[a-z\d\-_]{1,62}\.){0,125}(?:[a-z\d](?:\-(?=\-*[a-z\d])|[a-z]|\d){0,62}\.)[a-z\d]{1,63}$/i; // minimum generated srcset width