@shopgate/pwa-common 7.20.0-beta.2 → 7.20.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,15 @@
1
1
  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);}import{ACTION_REPLACE}from'@virtuous/conductor';import{navigate}from"../../action-creators/router";import{mutable}from"../../helpers/redux";/**
2
2
  * @mixes {MutableFunction}
3
3
  * @param {Object} params The history params.
4
+ * @param {Object} [options={}] Additional options for the action
5
+ * @param {boolean} [options.remountRoute=true] When set to "true", the target route will be forced
6
+ * to remount.
4
7
  * @return {Function} The dispatched action.
5
- */export var historyReplace=mutable(function(params){return function(dispatch){dispatch(navigate(_extends({},params,{action:ACTION_REPLACE})));};});
8
+ */export var historyReplace=mutable(function(params){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};return function(dispatch){dispatch(navigate(_extends({},params,{},(options===null||options===void 0?void 0:options.remountRoute)!==false&&{state:_extends({},params.state,{/**
9
+ * When a route is "replaced" the router doesn't assign a new route id to the old route
10
+ * stack entry. This can cause issues when a route is replaced by itself, since the content
11
+ * will not remount out of the box.
12
+ *
13
+ * When the "replaceRouteId" state prop is injected, the Route component performs logic
14
+ * to enforce re-remounting routes which where replaced by itself.
15
+ */replaceRouteId:Math.random().toString(36).substring(2,7)})},{action:ACTION_REPLACE})));};});
@@ -1,4 +1,5 @@
1
1
  import fetchUser from"./fetchUser";/**
2
2
  * Get the current user
3
3
  * @return {Function} A redux thunk.
4
+ * @deprecated Will be removed in the near future. Use fetchUser instead.
4
5
  */var getUser=fetchUser;export default getUser;
@@ -1,4 +1,4 @@
1
- function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}/* eslint-disable extra-rules/potential-point-free */ /**
1
+ 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);}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}/* eslint-disable extra-rules/potential-point-free */ /**
2
2
  * Class to maintain embedded media within DOM containers.
3
3
  */var EmbeddedMedia=/*#__PURE__*/function(){/**
4
4
  * Constructor
@@ -16,6 +16,16 @@ function _classCallCheck(instance,Constructor){if(!(instance instanceof Construc
16
16
  * embedded media is unmounted.
17
17
  * @param {ParentNode} container A DOM container.
18
18
  */},{key:"remove",value:function remove(container){this.providers.forEach(function(provider){provider.remove(container);});}/**
19
+ * Searches for embedded media and replaces it with a placeholder element when required cookie
20
+ * consent is not accepted.
21
+ * Should be invoked before container content is added to the DOM to fulfill all regulations.
22
+ * @param {ParentNode} container A DOM container.
23
+ * @param {Object} [cookieConsentSettings] Additional settings related to cookie consent.
24
+ * @param {boolean} [cookieConsentSettings.comfortCookiesAccepted] Whether comfort cookies
25
+ * are accepted.
26
+ * @param {boolean} [cookieConsentSettings.statisticsCookiesAccepted] Whether statistics cookies
27
+ * are accepted.
28
+ */},{key:"handleCookieConsent",value:function handleCookieConsent(container){var cookieConsentSettings=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var cookieConsent=_extends({comfortCookiesAccepted:false,statisticsCookiesAccepted:false},cookieConsentSettings);this.providers.forEach(function(provider){if(provider.handleCookieConsent){provider.handleCookieConsent(container,cookieConsent);}});}/**
19
29
  * Stops all playing media within the DOM containers.
20
30
  */},{key:"stop",value:function stop(){this.providers.forEach(function(provider){provider.stop();});}/**
21
31
  * Check if we have media providers with not-ready SDK
@@ -1,4 +1,4 @@
1
- function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}import{logger}from'@shopgate/pwa-core/helpers';import{isRelativePosition,isAbsolutePosition}from"../../helpers/dom";import styles from"./style";/**
1
+ function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}import{i18n,logger}from'@shopgate/engage/core/helpers';import{PRIVACY_SETTINGS_PATTERN}from'@shopgate/engage/tracking/constants';import{isRelativePosition,isAbsolutePosition}from"../../helpers/dom";import styles from"./style";var consentMessageIcon="\n <svg\n width=\"100%\"\n height=\"100%\"\n viewBox=\"0 0 110 84\"\n version=\"1.1\"\n class=\"".concat(styles.consentIcon,"\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <g transform=\"matrix(1,0,0,1,-24.6099,-41.8178)\">\n <path d=\"M50.303,68.639L104.088,98.668L56.288,125.172C55.039,125.865 53.518,125.845 52.288,125.12C51.058,124.396 50.303,123.075 50.303,121.648L50.303,68.639ZM50.303,54.702L50.303,45.855C50.303,44.425 51.059,43.102 52.292,42.376C53.524,41.651 55.048,41.631 56.298,42.324C71.141,50.554 109.492,71.82 124.676,80.239C125.95,80.945 126.741,82.288 126.741,83.745C126.741,85.203 125.95,86.545 124.676,87.252L116.612,91.724L50.303,54.702Z\" />\n <g transform=\"matrix(0.944597,0.527391,-0.487489,0.873129,45.7069,-42.8282)\">\n <path d=\"M139,89C139,87.344 137.757,86 136.227,86L26.773,86C25.243,86 24,87.344 24,89C24,90.656 25.243,92 26.773,92L136.227,92C137.757,92 139,90.656 139,89Z\" />\n </g>\n </g>\n </svg>");/* eslint-disable class-methods-use-this */ /**
2
2
  * The MediaProvider base class.
3
3
  */var MediaProvider=/*#__PURE__*/function(){/**
4
4
  * Constructor.
@@ -6,16 +6,44 @@ function _classCallCheck(instance,Constructor){if(!(instance instanceof Construc
6
6
  * Callback for when Provider script is loaded
7
7
  * @callback
8
8
  * @abstract
9
- */ /* eslint-disable-next-line class-methods-use-this, require-jsdoc */return _createClass(MediaProvider,[{key:"onScriptLoaded",value:function onScriptLoaded(){logger.error('MediaProvider.onScriptLoaded() needs to be implemented within an inheriting class');}/**
9
+ */return _createClass(MediaProvider,[{key:"onScriptLoaded",value:function onScriptLoaded(){logger.error('MediaProvider.onScriptLoaded() needs to be implemented within an inheriting class');}/**
10
+ * Callback to retrieve a list of media containers
11
+ * @callback
12
+ * @abstract
13
+ */},{key:"getMediaContainers",value:function getMediaContainers(){logger.error('MediaProvider.getMediaContainers() needs to be implemented within an inheriting class');}/**
10
14
  * Optimizes video container to make it responsive.
11
15
  * @param {Element} container A DOM container.
12
16
  * @returns {MediaProvider}
13
17
  */},{key:"responsify",value:function responsify(container){// Remove fixed dimensions from the container.
14
18
  container.removeAttribute('height');container.removeAttribute('width');if(isRelativePosition(container.parentNode)&&isAbsolutePosition(container)){// Assume responsive embed code
15
19
  container.parentNode.removeAttribute('style');}// Create the wrapper and apply styling.
16
- var wrapper=document.createElement('div');wrapper.className=styles;// Add the wrapper right before the container into the DOM.
20
+ var wrapper=document.createElement('div');wrapper.className=styles.responsiveContainer;// Add the wrapper right before the container into the DOM.
17
21
  container.parentNode.insertBefore(wrapper,container);// Move the container into the wrapper.
18
22
  wrapper.appendChild(container);return this;}/**
23
+ * Searches for embedded media and replaces it with a placeholder element when comfort cookie
24
+ * consent is not accepted.
25
+ *
26
+ * Should be called before media container / markup is mounted to the DOM.
27
+ * @param {ParentNode} container A DOM container.
28
+ * @param {Object} [cookieConsentSettings] Additional settings related to cookie consent.
29
+ * @param {boolean} [cookieConsentSettings.comfortCookiesAccepted] Whether comfort cookies
30
+ * are accepted.
31
+ * @param {boolean} [cookieConsentSettings.statisticsCookiesAccepted] Whether statistics cookies
32
+ * are accepted.
33
+ * @returns {MediaProvider}
34
+ */},{key:"handleCookieConsent",value:function handleCookieConsent(container){var _this=this;var cookieConsentSettings=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var iframes=this.getMediaContainers(container);if(!iframes.length||cookieConsentSettings.comfortCookiesAccepted!==false){return this;}iframes.forEach(function(iframe){// Add responsive container around iframes
35
+ _this.responsify(iframe);// Select the container and clear its content
36
+ var responsiveContainer=iframe.parentNode;responsiveContainer.textContent=null;// Add the consent message element to the container
37
+ _this.injectCookieConsentMessage(responsiveContainer);});return this;}/**
38
+ * Injects a cookie consent message element into a container
39
+ * @param {Element} container A DOM container.
40
+ * @returns {MediaProvider}
41
+ */},{key:"injectCookieConsentMessage",value:function injectCookieConsentMessage(container){// Create the wrapper for the message element
42
+ var messageWrapper=document.createElement('div');messageWrapper.classList.add(styles.consentContainer,'common__media-provider_cookie-consent-message-container');// Add an SVG icon (implemented this way, since there where issues with document.createElement)
43
+ messageWrapper.innerHTML=consentMessageIcon;// Create the main message and add it to the wrapper
44
+ var message=document.createElement('span');message.classList.add('common__media-provider_cookie-consent-message-container_message');message.innerHTML=i18n.text('htmlSanitizer.videoCookieConsent.message');messageWrapper.appendChild(message);// Create the link and add it to the wrapper
45
+ var link=document.createElement('a');link.classList.add(styles.consentLink,'common__media-provider_cookie-consent-message-container_link');link.href=PRIVACY_SETTINGS_PATTERN;link.innerHTML=i18n.text('htmlSanitizer.videoCookieConsent.link');messageWrapper.appendChild(link);// Add the wrapper to the container
46
+ container.appendChild(messageWrapper);return this;}/**
19
47
  * Add a DOM container with embedded videos.
20
48
  * @param {NodeList} container A DOM container.
21
49
  * @returns {MediaProvider}
@@ -26,4 +54,4 @@ wrapper.appendChild(container);return this;}/**
26
54
  */},{key:"remove",value:function remove(container){this.containers["delete"](container);return this;}/**
27
55
  * Stops all playing videos within the DOM containers.
28
56
  * @returns {MediaProvider}
29
- */},{key:"stop",value:function stop(){logger.error('MediaProvider.stop() needs to be implemented within an inheriting class');return this;}}]);}();export default MediaProvider;
57
+ */},{key:"stop",value:function stop(){logger.error('MediaProvider.stop() needs to be implemented within an inheriting class');return this;}}]);}();export default MediaProvider;/* eslint-enable class-methods-use-this */
@@ -1,11 +1,15 @@
1
- function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _callSuper(_this,derived,args){function isNativeReflectConstruct(){if(typeof Reflect==="undefined"||!Reflect.construct)return false;if(Reflect.construct.sham)return false;if(typeof Proxy==="function")return true;try{return!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}));}catch(e){return false;}}derived=_getPrototypeOf(derived);return _possibleConstructorReturn(_this,isNativeReflectConstruct()?Reflect.construct(derived,args||[],_getPrototypeOf(_this).constructor):derived.apply(_this,args));}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call;}return _assertThisInitialized(self);}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return self;}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o);};return _getPrototypeOf(o);}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});if(superClass)_setPrototypeOf(subClass,superClass);}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function _setPrototypeOf(o,p){o.__proto__=p;return o;};return _setPrototypeOf(o,p);}import MediaProvider from"./MediaProvider";var scriptUrl='https://player.vimeo.com/api/player.js';/**
1
+ function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _callSuper(_this,derived,args){function isNativeReflectConstruct(){if(typeof Reflect==="undefined"||!Reflect.construct)return false;if(Reflect.construct.sham)return false;if(typeof Proxy==="function")return true;try{return!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}));}catch(e){return false;}}derived=_getPrototypeOf(derived);return _possibleConstructorReturn(_this,isNativeReflectConstruct()?Reflect.construct(derived,args||[],_getPrototypeOf(_this).constructor):derived.apply(_this,args));}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call;}return _assertThisInitialized(self);}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return self;}function _get(target,property,receiver){if(typeof Reflect!=="undefined"&&Reflect.get){_get=Reflect.get;}else{_get=function _get(target,property,receiver){var base=_superPropBase(target,property);if(!base)return;var desc=Object.getOwnPropertyDescriptor(base,property);if(desc.get){return desc.get.call(receiver);}return desc.value;};}return _get(target,property,receiver||target);}function _superPropBase(object,property){while(!Object.prototype.hasOwnProperty.call(object,property)){object=_getPrototypeOf(object);if(object===null)break;}return object;}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o);};return _getPrototypeOf(o);}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});if(superClass)_setPrototypeOf(subClass,superClass);}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function _setPrototypeOf(o,p){o.__proto__=p;return o;};return _setPrototypeOf(o,p);}import MediaProvider from"./MediaProvider";/* eslint-disable class-methods-use-this */var scriptUrl='https://player.vimeo.com/api/player.js';/**
2
2
  * The Vimeo media provider class.
3
3
  */var VimeoMediaProvider=/*#__PURE__*/function(_MediaProvider){/**
4
4
  * Constructor.
5
5
  */function VimeoMediaProvider(){var _this2;_classCallCheck(this,VimeoMediaProvider);_this2=_callSuper(this,VimeoMediaProvider);// Need to check Vimeo.Player presence later
6
6
  _this2.isPending=true;_this2.remoteScriptUrl=scriptUrl;_this2.deferred=[];return _this2;}/**
7
+ * Retrieves a list of media containers for Vimeo.
8
+ * @param {ParentNode} container A DOM container that may contain Vimeo iframes.
9
+ * @returns {NodeListOf<Element>}
10
+ */_inherits(VimeoMediaProvider,_MediaProvider);return _createClass(VimeoMediaProvider,[{key:"getMediaContainers",value:function getMediaContainers(container){return container.querySelectorAll('iframe[src*="vimeo.com"]');}/**
7
11
  * @inheritDoc
8
- */_inherits(VimeoMediaProvider,_MediaProvider);return _createClass(VimeoMediaProvider,[{key:"onScriptLoaded",value:function onScriptLoaded(){var _this3=this;this.isPending=false;if(this.deferred.length){this.deferred.forEach(function(container){_this3.add(container);});this.deferred=[];}}/**
12
+ */},{key:"onScriptLoaded",value:function onScriptLoaded(){var _this3=this;this.isPending=false;if(this.deferred.length){this.deferred.forEach(function(container){_this3.add(container);});this.deferred=[];}}/**
9
13
  * Check if the Provider script to be loaded externally is finished loading
10
14
  * @returns {boolean}
11
15
  */},{key:"checkScriptLoadingStatus",value:function checkScriptLoadingStatus(){if(this.isPending&&typeof window.Vimeo!=='undefined'){this.isPending=false;}return!this.isPending;}/**
@@ -13,8 +17,22 @@ _this2.isPending=true;_this2.remoteScriptUrl=scriptUrl;_this2.deferred=[];return
13
17
  * @override
14
18
  * @param {ParentNode} container A DOM container.
15
19
  * @returns {VimeoMediaProvider}
16
- */},{key:"add",value:function add(container){var _this4=this;if(!this.checkScriptLoadingStatus()){this.deferred.push(container);return this;}var iframes=container.querySelectorAll('iframe[src*="vimeo.com"]');if(!iframes.length){return this;}var players=[];iframes.forEach(function(iframe){_this4.responsify(iframe);players.push(new window.Vimeo.Player(iframe));});this.containers.set(container,players);return this;}/**
20
+ */},{key:"add",value:function add(container){var _this4=this;if(!this.checkScriptLoadingStatus()){this.deferred.push(container);return this;}var iframes=this.getMediaContainers(container);if(!iframes.length){return this;}var players=[];iframes.forEach(function(iframe){_this4.responsify(iframe);players.push(new window.Vimeo.Player(iframe));});this.containers.set(container,players);return this;}/**
17
21
  * Stops all playing videos within the DOM containers.
18
22
  * @override
19
23
  * @returns {VimeoMediaProvider}
20
- */},{key:"stop",value:function stop(){this.containers.forEach(function(players){players.forEach(function(player){player.pause();});});return this;}}]);}(MediaProvider);export default VimeoMediaProvider;
24
+ */},{key:"stop",value:function stop(){this.containers.forEach(function(players){players.forEach(function(player){player.pause();});});return this;}/**
25
+ * Searches for embedded media and replaces it with a placeholder element when comfort cookie
26
+ * consent is not accepted.
27
+ *
28
+ * Should be called before media container / markup is mounted to the DOM.
29
+ * @param {ParentNode} container A DOM container.
30
+ * @param {Object} [cookieConsentSettings] Additional settings related to cookie consent.
31
+ * @param {boolean} [cookieConsentSettings.comfortCookiesAccepted] Whether comfort cookies
32
+ * are accepted.
33
+ * @param {boolean} [cookieConsentSettings.statisticsCookiesAccepted] Whether statistics cookies
34
+ * are accepted.
35
+ * @override
36
+ * @returns {VimeoMediaProvider}
37
+ */},{key:"handleCookieConsent",value:function handleCookieConsent(container,cookieConsentSettings){// Remove Vimeo player scripts since the VimeoMediaProvider has custom logic for it
38
+ container.querySelectorAll('script[src*="vimeo.com"]').forEach(function(entry){entry.remove();});return _get(_getPrototypeOf(VimeoMediaProvider.prototype),"handleCookieConsent",this).call(this,container,cookieConsentSettings);}}]);}(MediaProvider);export default VimeoMediaProvider;/* eslint-enable class-methods-use-this */
@@ -1,15 +1,19 @@
1
- function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_nonIterableRest();}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance");}function _iterableToArrayLimit(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"]!=null)_i["return"]();}finally{if(_d)throw _e;}}return _arr;}function _arrayWithHoles(arr){if(Array.isArray(arr))return arr;}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _callSuper(_this,derived,args){function isNativeReflectConstruct(){if(typeof Reflect==="undefined"||!Reflect.construct)return false;if(Reflect.construct.sham)return false;if(typeof Proxy==="function")return true;try{return!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}));}catch(e){return false;}}derived=_getPrototypeOf(derived);return _possibleConstructorReturn(_this,isNativeReflectConstruct()?Reflect.construct(derived,args||[],_getPrototypeOf(_this).constructor):derived.apply(_this,args));}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call;}return _assertThisInitialized(self);}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return self;}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o);};return _getPrototypeOf(o);}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});if(superClass)_setPrototypeOf(subClass,superClass);}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function _setPrototypeOf(o,p){o.__proto__=p;return o;};return _setPrototypeOf(o,p);}import URLSearchParams from'url-search-params';import MediaProvider from"./MediaProvider";/**
1
+ function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_nonIterableRest();}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance");}function _iterableToArrayLimit(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"]!=null)_i["return"]();}finally{if(_d)throw _e;}}return _arr;}function _arrayWithHoles(arr){if(Array.isArray(arr))return arr;}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _callSuper(_this,derived,args){function isNativeReflectConstruct(){if(typeof Reflect==="undefined"||!Reflect.construct)return false;if(Reflect.construct.sham)return false;if(typeof Proxy==="function")return true;try{return!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}));}catch(e){return false;}}derived=_getPrototypeOf(derived);return _possibleConstructorReturn(_this,isNativeReflectConstruct()?Reflect.construct(derived,args||[],_getPrototypeOf(_this).constructor):derived.apply(_this,args));}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call;}return _assertThisInitialized(self);}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return self;}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o);};return _getPrototypeOf(o);}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});if(superClass)_setPrototypeOf(subClass,superClass);}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function _setPrototypeOf(o,p){o.__proto__=p;return o;};return _setPrototypeOf(o,p);}import URLSearchParams from'url-search-params';import MediaProvider from"./MediaProvider";/* eslint-disable class-methods-use-this */ /**
2
2
  * The YouTube media provider class.
3
- */var YouTubeMediaProvider=/*#__PURE__*/function(_MediaProvider){function YouTubeMediaProvider(){_classCallCheck(this,YouTubeMediaProvider);return _callSuper(this,YouTubeMediaProvider,arguments);}_inherits(YouTubeMediaProvider,_MediaProvider);return _createClass(YouTubeMediaProvider,[{key:"add",value:/**
3
+ */var YouTubeMediaProvider=/*#__PURE__*/function(_MediaProvider){function YouTubeMediaProvider(){_classCallCheck(this,YouTubeMediaProvider);return _callSuper(this,YouTubeMediaProvider,arguments);}_inherits(YouTubeMediaProvider,_MediaProvider);return _createClass(YouTubeMediaProvider,[{key:"getMediaContainers",value:/**
4
+ * Retrieves a list of media containers for YouTube.
5
+ * @param {ParentNode} container A DOM container that may contain YouTube iframes.
6
+ * @returns {NodeListOf<Element>}
7
+ */function getMediaContainers(container){return container.querySelectorAll('iframe[src*="youtube.com"], iframe[src*="youtube-nocookie.com"]');}/**
4
8
  * Add a DOM container with embedded videos.
5
9
  * @override
6
10
  * @param {ParentNode} container A DOM container.
7
11
  * @returns {YouTubeMediaProvider}
8
- */function add(container){var _this2=this;var iframes=container.querySelectorAll('iframe[src*="youtube.com"], iframe[src*="youtube-nocookie.com"]');if(!iframes.length){return this;}// Update the video urls to enable stopping videos via the event API.
12
+ */},{key:"add",value:function add(container){var _this2=this;var iframes=this.getMediaContainers(container);if(!iframes.length){return this;}// Update the video urls to enable stopping videos via the event API.
9
13
  iframes.forEach(function(iframe,index){_this2.responsify(iframe);var src=iframe.src;var _src$split=src.split('?'),_src$split2=_slicedToArray(_src$split,2),url=_src$split2[0],query=_src$split2[1];var urlParams=new URLSearchParams(query);// Enable the js api to allow sending events to the iframe.
10
14
  urlParams.set('enablejsapi',1);// Enable controls to avoid the iframe not being resumable because of controls=0 param on ios.
11
15
  urlParams.set('controls',1);iframes[index].src="".concat(url,"?").concat(urlParams.toString());});this.containers.set(container,iframes);return this;}/**
12
16
  * Stops all playing videos within the DOM containers.
13
17
  * @override
14
18
  * @returns {YouTubeMediaProvider}
15
- */},{key:"stop",value:function stop(){this.containers.forEach(function(iframes){iframes.forEach(function(iframe){if(iframe.contentWindow&&iframe.contentWindow.postMessage){iframe.contentWindow.postMessage('{"event":"command","func":"stopVideo","args":""}','*');}});});return this;}}]);}(MediaProvider);export default YouTubeMediaProvider;
19
+ */},{key:"stop",value:function stop(){this.containers.forEach(function(iframes){iframes.forEach(function(iframe){if(iframe.contentWindow&&iframe.contentWindow.postMessage){iframe.contentWindow.postMessage('{"event":"command","func":"stopVideo","args":""}','*');}});});return this;}}]);}(MediaProvider);export default YouTubeMediaProvider;/* eslint-enable class-methods-use-this */
@@ -1 +1,2 @@
1
- import{css}from'glamor';export default css({position:'relative',height:0,overflow:'hidden',padding:'56.25% 0 0 0',' iframe, object, embed':{position:'absolute',top:0,left:0,width:'100%',height:'100%',border:0}}).toString();
1
+ import{css}from'glamor';import{themeConfig}from'@shopgate/pwa-common/helpers/config';var colors=themeConfig.colors;var responsiveContainer=css({position:'relative',height:0,overflow:'hidden',padding:'56.25% 0 0 0',fontSize:'0.875rem',' iframe, object, embed':{position:'absolute',top:0,left:0,width:'100%',height:'100%',border:0}});var consentContainer=css({position:'absolute',height:'100%',width:'100%',padding:16,lineHeight:'1.2rem',display:'flex',flexDirection:'column',justifyContent:'center',textAlign:'center',gap:16,background:colors.shade10,border:"1px solid ".concat(colors.shade5),// Add a tiny little border radius to make the message container look nice with padding
2
+ borderRadius:4,top:0});var consentLink=css({textAlign:'center',color:colors.primary,fontWeight:500}).toString();var consentIcon=css({fill:colors.shade5,height:40});export default{responsiveContainer:responsiveContainer,consentContainer:consentContainer,consentLink:consentLink,consentIcon:consentIcon};
@@ -1,11 +1,11 @@
1
- import React,{Fragment}from'react';import PropTypes from'prop-types';import Helmet from'react-helmet';import{embeddedMedia}from'@shopgate/pwa-common/collections';/**
2
- * EmbeddedMedia component.
1
+ 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);}import React,{Fragment,useMemo}from'react';import PropTypes from'prop-types';import Helmet from'react-helmet';import{embeddedMedia}from'@shopgate/pwa-common/collections';/**
2
+ * EmbeddedMedia component. Handles loading of media related scripts e.g. the Vimeo Player.
3
3
  * @returns {JSX}
4
- */var EmbeddedMedia=function EmbeddedMedia(_ref){var children=_ref.children;if(!embeddedMedia.getHasPendingProviders()){return children;}// Get all pending providers
5
- var pendingProviders=[].concat(embeddedMedia.providers).filter(function(p){return p.isPending;});/**
4
+ */var EmbeddedMedia=function EmbeddedMedia(_ref){var children=_ref.children,cookieConsentSettings=_ref.cookieConsentSettings;var cookieConsent=useMemo(function(){return _extends({comfortCookiesAccepted:false,statisticsCookiesAccepted:false},cookieConsentSettings);},[cookieConsentSettings]);if(!embeddedMedia.getHasPendingProviders()||!cookieConsent.comfortCookiesAccepted){return children;}// Get all pending providers
5
+ var pendingProviders=Array.from(embeddedMedia.providers).filter(function(p){return p.isPending;});/**
6
6
  * Inject onLoad cb to script tags
7
7
  * @param {Element[]} scriptTags script tags to listen for
8
8
  * @param {MediaProvider} provider Provider
9
9
  */var updateProviderScripts=function updateProviderScripts(_ref2){var scriptTags=_ref2.scriptTags;if(scriptTags){scriptTags.forEach(function(scriptTag){var provider=pendingProviders.find(function(p){return p.remoteScriptUrl===scriptTag.getAttribute('src');});// eslint-disable-next-line no-param-reassign
10
10
  scriptTag.onload=function(){provider.onScriptLoaded();};});}};var scripts=pendingProviders.map(function(provider){return{src:provider.remoteScriptUrl,type:'text/javascript'};});return React.createElement(Fragment,null,React.createElement(Helmet,{script:scripts// Helmet doesn't support `onload` in script objects so we have to hack in our own
11
- ,onChangeClientState:function onChangeClientState(newState,addedTags){return updateProviderScripts(addedTags);}}),children);};export default EmbeddedMedia;
11
+ ,onChangeClientState:function onChangeClientState(newState,addedTags){return updateProviderScripts(addedTags);}}),children);};EmbeddedMedia.defaultProps={cookieConsentSettings:{comfortCookiesAccepted:false,statisticsCookiesAccepted:false}};export default EmbeddedMedia;
@@ -1,5 +1,9 @@
1
- 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);}import{connect}from'react-redux';import{historyPush}from"../../actions/router";/**
1
+ 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);}import{connect}from'react-redux';import{getAreComfortCookiesAccepted,getAreStatisticsCookiesAccepted}from'@shopgate/engage/tracking/selectors';import{historyPush}from"../../actions/router";/**
2
+ * Maps the current application state to the component props.
3
+ * @param {Object} state The current application state.
4
+ * @return {Object} The populated component props.
5
+ */var mapStateToProps=function mapStateToProps(state){return{comfortCookiesAccepted:getAreComfortCookiesAccepted(state),statisticsCookiesAccepted:getAreStatisticsCookiesAccepted(state)};};/**
2
6
  * Connects the dispatch function to a callable function in the props.
3
7
  * @param {Function} dispatch The redux dispatch function.
4
8
  * @return {Object} The extended component props.
5
- */var mapDispatchToProps=function mapDispatchToProps(dispatch){return{navigate:function navigate(pathname,target){return dispatch(historyPush(_extends({pathname:pathname},target&&{state:{target:target}})));}};};export default connect(null,mapDispatchToProps);
9
+ */var mapDispatchToProps=function mapDispatchToProps(dispatch){return{navigate:function navigate(pathname,target){return dispatch(historyPush(_extends({pathname:pathname},target&&{state:{target:target}})));}};};export default connect(mapStateToProps,mapDispatchToProps);
@@ -11,12 +11,12 @@ function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="s
11
11
  * Only update if the HTML changed.
12
12
  * @param {Object} nextProps The next props for the component.
13
13
  * @return {boolean}
14
- */},{key:"shouldComponentUpdate",value:function shouldComponentUpdate(nextProps){return nextProps.children!==this.props.children;}/**
14
+ */},{key:"shouldComponentUpdate",value:function shouldComponentUpdate(nextProps){return nextProps.children!==this.props.children||nextProps.comfortCookiesAccepted!==this.props.comfortCookiesAccepted||nextProps.statisticsCookiesAccepted!==this.props.statisticsCookiesAccepted;}/**
15
15
  * Updates embedded media within the html container.
16
16
  */},{key:"componentDidUpdate",value:function componentDidUpdate(){embeddedMedia.add(this.htmlContainer.current);}/**
17
17
  * Removes the event handler.
18
18
  */},{key:"componentWillUnmount",value:function componentWillUnmount(){this.htmlContainer.current.removeEventListener('click',this.handleTap,true);embeddedMedia.remove(this.htmlContainer.current);}},{key:"render",value:/**
19
19
  * Renders the component.
20
20
  * @returns {JSX}
21
- */function render(){var innerHTML={__html:parseHTML(this.props.children,this.props.decode,this.props.settings,this.props.processStyles)};var Wrapper=this.props.wrapper;return React.createElement(Wrapper,null,React.createElement("div",{// eslint-disable-next-line react/no-danger
22
- dangerouslySetInnerHTML:innerHTML,ref:this.htmlContainer,className:classNames(this.props.className,'common__html-sanitizer')}));}}]);}(Component);_defineProperty(HtmlSanitizer,"defaultProps",{children:'',className:'',decode:false,processStyles:false,settings:{},wrapper:EmbeddedMedia});export default connect(HtmlSanitizer);
21
+ */function render(){var cookieConsentSettings={comfortCookiesAccepted:this.props.comfortCookiesAccepted,statisticsCookiesAccepted:this.props.statisticsCookiesAccepted};var innerHTML={__html:parseHTML(this.props.children,this.props.decode,this.props.settings,this.props.processStyles,cookieConsentSettings)};var Wrapper=this.props.wrapper;return React.createElement(Wrapper,{cookieConsentSettings:cookieConsentSettings},React.createElement("div",{// eslint-disable-next-line react/no-danger
22
+ dangerouslySetInnerHTML:innerHTML,ref:this.htmlContainer,className:classNames(this.props.className,'common__html-sanitizer')}));}}]);}(Component);_defineProperty(HtmlSanitizer,"defaultProps",{children:'',className:'',decode:false,processStyles:false,settings:{},wrapper:EmbeddedMedia,comfortCookiesAccepted:false,statisticsCookiesAccepted:false});export default connect(HtmlSanitizer);
@@ -1,13 +1,13 @@
1
- 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);}import React from'react';import{mount}from'enzyme';import{JSDOM}from'jsdom';import{embeddedMedia}from'@shopgate/pwa-common/collections';import HtmlSanitizer from"./index";jest.mock('@shopgate/pwa-common/collections/EmbeddedMedia',function(){return{add:jest.fn(),remove:jest.fn()};});jest.mock("../EmbeddedMedia",function(){return function(_ref){var children=_ref.children;return children;};});jest.mock("./connector",function(){return function(Cmp){return Cmp;};});/**
1
+ 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);}import React from'react';import{mount}from'enzyme';import{JSDOM}from'jsdom';import{embeddedMedia}from'@shopgate/pwa-common/collections';import HtmlSanitizer from"./index";jest.mock("../EmbeddedMedia",function(){return function(_ref){var children=_ref.children;return children;};});jest.mock("./connector",function(){return function(Cmp){return Cmp;};});/**
2
2
  * @param {string} html HTML markup.
3
3
  * @param {Object} props Component props.
4
4
  * @returns {JSX}
5
- */var createWrapper=function createWrapper(html){var props=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};return mount(React.createElement(HtmlSanitizer,_extends({navigate:function navigate(){}},props),html));};describe('<HtmlSanitizer />',function(){beforeEach(function(){jest.clearAllMocks();});it('should render the HtmlSanitizer',function(){/**
5
+ */var createWrapper=function createWrapper(html){var props=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};return mount(React.createElement(HtmlSanitizer,_extends({navigate:function navigate(){}},props),html));};describe('<HtmlSanitizer />',function(){var embeddedMediaAddSpy;var embeddedMediaRemoveSpy;var embeddedMediaHandleCookieConsentSpy;beforeEach(function(){jest.clearAllMocks();embeddedMediaAddSpy=jest.spyOn(embeddedMedia,'add');embeddedMediaRemoveSpy=jest.spyOn(embeddedMedia,'remove');embeddedMediaHandleCookieConsentSpy=jest.spyOn(embeddedMedia,'handleCookieConsent');});it('should render the HtmlSanitizer',function(){/**
6
6
  * The value for html is the HTML-escaped equivalent of the following:
7
7
  * <h1>Hello World!</h1>
8
8
  * @type {string}
9
9
  */var html='&lt;h1&gt;Hello World!&lt;/h1&gt;';var wrapper=createWrapper(html,{decode:true});// Test result of dangerouslySetInnerHTML.
10
- expect(wrapper.html()).toEqual('<div class="common__html-sanitizer"><h1>Hello World!</h1></div>');expect(wrapper.render()).toMatchSnapshot();});it('should add and remove handlers for embedded media',function(){var wrapper=createWrapper('<div></div>',{decode:true});var ref=wrapper.instance().htmlContainer.current;expect(embeddedMedia.add).toHaveBeenCalledTimes(1);expect(embeddedMedia.add).toHaveBeenCalledWith(ref);expect(embeddedMedia.remove).toHaveBeenCalledTimes(0);wrapper.setProps({children:'<span></span>'});expect(embeddedMedia.add).toHaveBeenCalledTimes(2);expect(embeddedMedia.add).toHaveBeenCalledWith(ref);expect(embeddedMedia.remove).toHaveBeenCalledTimes(0);wrapper.unmount();expect(embeddedMedia.add).toHaveBeenCalledTimes(2);expect(embeddedMedia.remove).toHaveBeenCalledTimes(1);expect(embeddedMedia.remove).toHaveBeenCalledWith(ref);});it('strips out images with relative paths',function(){var html="\n <div>\n <style>a { color: red }</style>\n <a href=\"foo\">\n <img src=\"bar.jpg\" />\n </a>\n </div>\n ";var wrapper=createWrapper(html);expect(wrapper.html()).not.toContain('<img');expect(wrapper.html()).toContain('<style>');expect(wrapper.render()).toMatchSnapshot();});it('should move style blocks out of the content',function(){var html="\n <div>\n <style>a { color: red }</style>\n <a href=\"foo\">\n <img src=\"bar.jpg\" />\n </a>\n </div>\n ";var wrapper=createWrapper(html,{processStyles:true});expect(wrapper.html()).not.toContain('<style>');});it('does not strip out images with absolute paths',function(){var html="\n <div>\n <a href=\"foo\">\n <img src=\"http://google.de/bar.jpg\" />\n </a>\n </div>\n ";var wrapper=createWrapper(html);expect(wrapper.html()).toContain('<img');expect(wrapper.render()).toMatchSnapshot();});it('strips out the script tags',function(){/**
10
+ expect(wrapper.html()).toEqual('<div class="common__html-sanitizer"><h1>Hello World!</h1></div>');expect(wrapper.render()).toMatchSnapshot();});it('should add and remove handlers for embedded media',function(){var wrapper=createWrapper('<div></div>',{decode:true});var ref=wrapper.instance().htmlContainer.current;expect(embeddedMediaAddSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaAddSpy).toHaveBeenCalledWith(ref);expect(embeddedMediaRemoveSpy).toHaveBeenCalledTimes(0);wrapper.setProps({children:'<span></span>'});expect(embeddedMediaAddSpy).toHaveBeenCalledTimes(2);expect(embeddedMediaAddSpy).toHaveBeenCalledWith(ref);expect(embeddedMediaRemoveSpy).toHaveBeenCalledTimes(0);wrapper.unmount();expect(embeddedMediaAddSpy).toHaveBeenCalledTimes(2);expect(embeddedMediaRemoveSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaRemoveSpy).toHaveBeenCalledWith(ref);});it('strips out images with relative paths',function(){var html="\n <div>\n <style>a { color: red }</style>\n <a href=\"foo\">\n <img src=\"bar.jpg\" />\n </a>\n </div>\n ";var wrapper=createWrapper(html);expect(wrapper.html()).not.toContain('<img');expect(wrapper.html()).toContain('<style>');expect(wrapper.render()).toMatchSnapshot();});it('should move style blocks out of the content',function(){var html="\n <div>\n <style>a { color: red }</style>\n <a href=\"foo\">\n <img src=\"bar.jpg\" />\n </a>\n </div>\n ";var wrapper=createWrapper(html,{processStyles:true});expect(wrapper.html()).not.toContain('<style>');});it('does not strip out images with absolute paths',function(){var html="\n <div>\n <a href=\"foo\">\n <img src=\"http://google.de/bar.jpg\" />\n </a>\n </div>\n ";var wrapper=createWrapper(html);expect(wrapper.html()).toContain('<img');expect(wrapper.render()).toMatchSnapshot();});it('strips out the script tags',function(){/**
11
11
  * The value for html is the HTML-escaped equivalent of the following:
12
12
  * <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
13
13
  * <script type="text/javascript">var x = 42;</script>
@@ -15,4 +15,4 @@ expect(wrapper.html()).toEqual('<div class="common__html-sanitizer"><h1>Hello Wo
15
15
  * <script>var y = 23;</script>
16
16
  * @type {string}
17
17
  */var html='&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js&quot;&gt;&lt;/script&gt; &lt;script type=&quot;text/javascript&quot;&gt;var x = 42;&lt;/script&gt; &lt;p&gt;Foo Bar&lt;/p&gt; &lt;script&gt;var y = 23;&lt;/script&gt;';var wrapper=createWrapper(html,{decode:true});// Test result of dangerouslySetInnerHTML.
18
- expect(wrapper.html()).toEqual('<div class="common__html-sanitizer"> <p>Foo Bar</p> </div>');expect(wrapper).toMatchSnapshot();});describe('Link handling',function(){var mockedHandleClick=jest.fn();beforeEach(function(){mockedHandleClick.mockClear();});it('follows a link from a plain <a>',function(){var doc=new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;var html='&lt;a id=&quot;link&quot; href=&quot;#follow-me-and-everything-is-alright&quot;&gt;Plain Link&lt;/a&gt;';var wrapper=mount(React.createElement(HtmlSanitizer,{decode:true,settings:{handleClick:mockedHandleClick},navigate:function navigate(){}},html),{attachTo:doc.getElementsByTagName('div')[0]});var aTag=doc.getElementsByTagName('a')[0];aTag.closest=function(){return aTag;};var event={target:aTag,preventDefault:function preventDefault(){}};wrapper.instance().handleTap(event);expect(mockedHandleClick).toHaveBeenCalledTimes(1);expect(mockedHandleClick).toHaveBeenCalledWith('#follow-me-and-everything-is-alright','');});it('follows a link from a <a> with other HTML inside',function(){var doc=new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;var html='&lt;a id=&quot;link&quot; target=&quot;_blank&quot; href=&quot;#I-ll-be-the-one-to-tuck-you-in-at-night&quot;&gt;&lt;span&gt;Span Link&lt;/span&gt;&lt;/a&gt;';var wrapper=mount(React.createElement(HtmlSanitizer,{decode:true,settings:{handleClick:mockedHandleClick},navigate:function navigate(){}},html),{attachTo:doc.getElementsByTagName('div')[0]});var aTag=doc.getElementsByTagName('a')[0];var spanTag=doc.getElementsByTagName('span')[0];spanTag.closest=function(){return aTag;};var event={target:spanTag,preventDefault:function preventDefault(){}};wrapper.instance().handleTap(event);expect(mockedHandleClick).toHaveBeenCalledTimes(1);expect(mockedHandleClick).toHaveBeenCalledWith('#I-ll-be-the-one-to-tuck-you-in-at-night','_blank');});});});
18
+ expect(wrapper.html()).toEqual('<div class="common__html-sanitizer"> <p>Foo Bar</p> </div>');expect(wrapper).toMatchSnapshot();});describe('Link handling',function(){var mockedHandleClick=jest.fn();beforeEach(function(){mockedHandleClick.mockClear();});it('follows a link from a plain <a>',function(){var doc=new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;var html='&lt;a id=&quot;link&quot; href=&quot;#follow-me-and-everything-is-alright&quot;&gt;Plain Link&lt;/a&gt;';var wrapper=mount(React.createElement(HtmlSanitizer,{decode:true,settings:{handleClick:mockedHandleClick},navigate:function navigate(){}},html),{attachTo:doc.getElementsByTagName('div')[0]});var aTag=doc.getElementsByTagName('a')[0];aTag.closest=function(){return aTag;};var event={target:aTag,preventDefault:function preventDefault(){}};wrapper.instance().handleTap(event);expect(mockedHandleClick).toHaveBeenCalledTimes(1);expect(mockedHandleClick).toHaveBeenCalledWith('#follow-me-and-everything-is-alright','');});it('follows a link from a <a> with other HTML inside',function(){var doc=new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;var html='&lt;a id=&quot;link&quot; target=&quot;_blank&quot; href=&quot;#I-ll-be-the-one-to-tuck-you-in-at-night&quot;&gt;&lt;span&gt;Span Link&lt;/span&gt;&lt;/a&gt;';var wrapper=mount(React.createElement(HtmlSanitizer,{decode:true,settings:{handleClick:mockedHandleClick},navigate:function navigate(){}},html),{attachTo:doc.getElementsByTagName('div')[0]});var aTag=doc.getElementsByTagName('a')[0];var spanTag=doc.getElementsByTagName('span')[0];spanTag.closest=function(){return aTag;};var event={target:spanTag,preventDefault:function preventDefault(){}};wrapper.instance().handleTap(event);expect(mockedHandleClick).toHaveBeenCalledTimes(1);expect(mockedHandleClick).toHaveBeenCalledWith('#I-ll-be-the-one-to-tuck-you-in-at-night','_blank');});});describe('Cookie consent handling',function(){it('should invoke handleCookieConsent method of embedded media with default cookie consent settings',function(){createWrapper('<div></div>',{decode:true});expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document),{comfortCookiesAccepted:false,statisticsCookiesAccepted:false});});it('should invoke handleCookieConsent method of embedded media with accepted comfort cookies',function(){createWrapper('<div></div>',{decode:true,comfortCookiesAccepted:true});expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document),{comfortCookiesAccepted:true,statisticsCookiesAccepted:false});});it('should invoke handleCookieConsent method of embedded media with accepted statistics cookies',function(){createWrapper('<div></div>',{decode:true,statisticsCookiesAccepted:true});expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document),{comfortCookiesAccepted:false,statisticsCookiesAccepted:true});});it('should invoke handleCookieConsent method of embedded media with all cookies accepted',function(){createWrapper('<div></div>',{decode:true,comfortCookiesAccepted:true,statisticsCookiesAccepted:true});expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document),{comfortCookiesAccepted:true,statisticsCookiesAccepted:true});});});});
@@ -46,6 +46,6 @@ newState.isValid=this.props.onValidate(newValue,false);}// Uncontrolled when set
46
46
  if(setOwnState){this.setState(newState);}}/**
47
47
  * Renders the component.
48
48
  * @returns {JSX}
49
- */},{key:"render",value:function render(){var _this3=this;var _this$props=this.props,attributes=_this$props.attributes,className=_this$props.className,password=_this$props.password,onKeyPress=_this$props.onKeyPress,maxlength=_this$props.maxlength;var type=password?'password':this.props.type;var value=this.state.value;var autoComplete=this.props.autoComplete?'on':'off';var autoCorrect=this.props.autoCorrect?'on':'off';var InputComponent=this.props.inputComponent;return React.createElement(InputComponent,_extends({id:this.props.id,name:this.props.name,ref:function ref(_ref){return _this3.handleRef(_ref);},className:classNames(className,'simpleInput','common__simple-input'),type:type,inputMode:type==='number'?'decimal':null,pattern:type==='number'?'[0-9]*':null,min:type==='number'?0:null,step:type==='number'?'any':null,value:value,onKeyPress:onKeyPress// Use onInput for number fields to enable handling for invalid values
49
+ */},{key:"render",value:function render(){var _this3=this;var _this$props=this.props,attributes=_this$props.attributes,className=_this$props.className,password=_this$props.password,onKeyPress=_this$props.onKeyPress,maxLength=_this$props.maxLength;var type=password?'password':this.props.type;var value=this.state.value;var autoComplete=this.props.autoComplete?'on':'off';var autoCorrect=this.props.autoCorrect?'on':'off';var InputComponent=this.props.inputComponent;return React.createElement(InputComponent,_extends({id:this.props.id,name:this.props.name,ref:function ref(_ref){return _this3.handleRef(_ref);},className:classNames(className,'simpleInput','common__simple-input'),type:type,inputMode:type==='number'?'decimal':null,pattern:type==='number'?'[0-9]*':null,min:type==='number'?0:null,step:type==='number'?'any':null,value:value,onKeyPress:onKeyPress// Use onInput for number fields to enable handling for invalid values
50
50
  // (onChange might to be triggered when the input is invalid)
51
- ,onInput:type==='number'?this.handleChange:null,onChange:type!=='number'?this.handleChange:function(){},onFocus:this.handleFocus,onBlur:this.handleBlur,disabled:this.props.disabled,autoCorrect:autoCorrect,autoComplete:autoComplete,maxLength:maxlength},attributes));}}]);}(Component);_defineProperty(SimpleInput,"defaultProps",{attributes:null,autoComplete:false,autoCorrect:false,className:'',disabled:false,id:null,isControlled:false,maxlength:'',name:null,onChange:function onChange(){},onFocusChange:function onFocusChange(){},onKeyPress:function onKeyPress(){},onSanitize:function onSanitize(value){return value;},onValidate:function onValidate(){return true;},password:false,setRef:function setRef(){},type:'text',validateOnBlur:true,value:'',inputComponent:'input'});export default SimpleInput;
51
+ ,onInput:type==='number'?this.handleChange:null,onChange:type!=='number'?this.handleChange:function(){},onFocus:this.handleFocus,onBlur:this.handleBlur,disabled:this.props.disabled,autoCorrect:autoCorrect,autoComplete:autoComplete,maxLength:maxLength},attributes));}}]);}(Component);_defineProperty(SimpleInput,"defaultProps",{attributes:null,autoComplete:false,autoCorrect:false,className:'',disabled:false,id:null,isControlled:false,maxLength:'',name:null,onChange:function onChange(){},onFocusChange:function onFocusChange(){},onKeyPress:function onKeyPress(){},onSanitize:function onSanitize(value){return value;},onValidate:function onValidate(){return true;},password:false,setRef:function setRef(){},type:'text',validateOnBlur:true,value:'',inputComponent:'input'});export default SimpleInput;
@@ -1 +1 @@
1
- import{connect}from'react-redux';import{historyPush as _historyPush,historyReplace as _historyReplace}from"../../actions/router";var mapDispatchToProps={historyPush:function historyPush(params){return _historyPush(params);},historyReplace:function historyReplace(params){return _historyReplace(params);}};export default connect(null,mapDispatchToProps);
1
+ import{connect}from'react-redux';import{historyPush,historyReplace}from"../../actions/router";var mapDispatchToProps={historyPush:historyPush,historyReplace:historyReplace};export default connect(null,mapDispatchToProps);
@@ -7,6 +7,13 @@ var _excluded=["setPattern"];function _typeof(obj){if(typeof Symbol==="function"
7
7
  */},{key:"render",value:function render(){var _this3=this;var _this$props=this.props,cache=_this$props.cache,Component=_this$props.component,pattern=_this$props.pattern;var matches=[];// If the current pattern does not match the whitelist but matches the current route
8
8
  // then add the current route as the only match.
9
9
  if(!cache&&pattern===this.currentRoute.pattern){matches=[[this.currentRoute.id,this.currentRoute]];}else if(cache){var subset=this.context.stack.slice(0,router.routeIndex+1);// Find matching patterns.
10
- matches=subset.filter(function(_ref){var _ref2=_slicedToArray(_ref,2),route=_ref2[1];return route.pattern===pattern;});}if(!matches.length){return null;}return matches.map(function(_ref3){var _ref4=_slicedToArray(_ref3,2),route=_ref4[1];var setPattern=route.setPattern,context=_objectWithoutProperties(route,_excluded);context.open=true;context.visible=route.id===_this3.currentRoute.id;return React.createElement(ErrorBoundary,{key:"error.".concat(route.id)},React.createElement(RouteContext.Provider,{key:route.id,value:context},React.createElement(Suspense,{fallback:React.createElement(Loading,null)},React.createElement(Component,null))));});}}]);}(React.Component);_defineProperty(Route,"contextType",RouterContext);_defineProperty(Route,"NotFound",RouteNotFound);_defineProperty(Route,"defaultProps",{cache:false,transform:null/**
10
+ matches=subset.filter(function(_ref){var _ref2=_slicedToArray(_ref,2),route=_ref2[1];return route.pattern===pattern;});}if(!matches.length){return null;}return matches.map(function(_ref3){var _context$state;var _ref4=_slicedToArray(_ref3,2),route=_ref4[1];var setPattern=route.setPattern,context=_objectWithoutProperties(route,_excluded);context.open=true;context.visible=route.id===_this3.currentRoute.id;/**
11
+ * When a route is "replaced" the router doesn't assign a new route id to the old route
12
+ * stack entry. This can cause issues when a route is replaced by itself, since the content
13
+ * will not remount out of the box.
14
+ *
15
+ * The "replaceRouteId" state prop is injected by the "historyReplace" action. It's used
16
+ * to enforce re-remounting routes which where replaced by itself.
17
+ */var replaceRouteId=(context===null||context===void 0?void 0:(_context$state=context.state)===null||_context$state===void 0?void 0:_context$state.replaceRouteId)||'';return React.createElement(ErrorBoundary,{key:"error.".concat(route.id,"_").concat(replaceRouteId)},React.createElement(RouteContext.Provider,{key:"".concat(route.id,"_").concat(replaceRouteId),value:context},React.createElement(Suspense,{fallback:React.createElement(Loading,null)},React.createElement(Component,null))));});}}]);}(React.Component);_defineProperty(Route,"contextType",RouterContext);_defineProperty(Route,"NotFound",RouteNotFound);_defineProperty(Route,"defaultProps",{cache:false,transform:null/**
11
18
  * @param {Object} props The component props.
12
19
  */});export default Route;
@@ -19,7 +19,8 @@ return Math.ceil(element.offsetHeight+margins);};/**
19
19
  * @param {HTMLElement} element The DOM element.
20
20
  * @param {string} property The style property in camel case
21
21
  * @returns {string}
22
- */export var getStyle=function getStyle(element,property){if(window.getComputedStyle){// getPropertyValue expects the property in kebab case.
22
+ */export var getStyle=function getStyle(element,property){// Use computed styles if possible - doesn't work with elements which are not mounted to the DOM
23
+ if(window.getComputedStyle&&document.body.contains(element)){// getPropertyValue expects the property in kebab case.
23
24
  return window.getComputedStyle(element,null).getPropertyValue(property.replace(/([a-z])([A-Z])/g,'$1-$2').toLowerCase());}return element.style[property];};/**
24
25
  * Check if element is relative.
25
26
  * @param {Element} element The DOM element.
@@ -1,13 +1,20 @@
1
- import{logger}from'@shopgate/pwa-core/helpers';import CryptoJs from'crypto-js';import{getExternalScripts,getInlineScripts,getHTMLContent,getDOMContainer,getStyles}from"./handleDOM";import decodeHTML from"./decodeHTML";/**
1
+ 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);}import{logger}from'@shopgate/pwa-core/helpers';import CryptoJs from'crypto-js';import{embeddedMedia}from"../../collections";import{getExternalScripts,getInlineScripts,getHTMLContent,getDOMContainer,getStyles}from"./handleDOM";import decodeHTML from"./decodeHTML";/**
2
2
  * Receives custom HTML from a widget configuration, parses possible
3
3
  * script tags and executes them after loading external scripts.
4
4
  * @param {string} html The HTML string. It might contain script tags.
5
5
  * @param {boolean} decode Whether the html must be decoded.
6
6
  * @param {Object} settings The settings are used to create a unique ID.
7
7
  * @param {boolean} [processStyles=false] When true, found styles are also added to the DOM.
8
+ * @param {Object} [cookieConsentSettings] Additional settings related to cookie consent.
9
+ * @param {boolean} [cookieConsentSettings.comfortCookiesAccepted] Whether comfort cookies
10
+ * are accepted.
11
+ * @param {boolean} [cookieConsentSettings.statisticsCookiesAccepted] Whether statistics cookies
12
+ * are accepted.
8
13
  * @returns {string} The HTML without any script tags.
9
- */var parseHTML=function parseHTML(html,decode,settings){var processStyles=arguments.length>3&&arguments[3]!==undefined?arguments[3]:false;var id=CryptoJs.MD5(JSON.stringify(settings)).toString();var container=getDOMContainer("html-sanitizer-".concat(id));try{var parser=new DOMParser();var unparsedHTML=decode?decodeHTML(html):html;// Parse the html string to a DOM object.
10
- var dom=parser.parseFromString("<body>".concat(unparsedHTML,"</body>"),'text/html');// How many onloads have been processed.
14
+ */var parseHTML=function parseHTML(html,decode,settings){var processStyles=arguments.length>3&&arguments[3]!==undefined?arguments[3]:false;var cookieConsentSettings=arguments.length>4&&arguments[4]!==undefined?arguments[4]:{};var id=CryptoJs.MD5(JSON.stringify(settings)).toString();var container=getDOMContainer("html-sanitizer-".concat(id));var cookieConsent=_extends({comfortCookiesAccepted:false,statisticsCookiesAccepted:false},cookieConsentSettings);try{var parser=new DOMParser();var unparsedHTML=decode?decodeHTML(html):html;// Parse the html string to a DOM object.
15
+ var dom=parser.parseFromString("<body>".concat(unparsedHTML,"</body>"),'text/html');// Run cookie consent logic from embedded media to remove markup that's not supposed to run
16
+ // when consent is not accepted.
17
+ embeddedMedia.handleCookieConsent(dom,cookieConsent);// How many onloads have been processed.
11
18
  var onloads=0;var inlineScripts=[];var externalScripts=[];/**
12
19
  * Handles the onload events for external scripts.
13
20
  * @return {Array} The collection of external scripts.
@@ -10,6 +10,6 @@ if(messageCache[hash]){return messageCache[hash];}messageCache[hash]=new IntlMes
10
10
  * Get a formatted number by a language code.
11
11
  * @param {string} langCode A language code.
12
12
  * @param {number} value The number to format.
13
- * @param {boolean} fractions Nnumber of digits after dot.
13
+ * @param {boolean} fractions Number of digits after dot.
14
14
  * @returns {string}
15
15
  */var formatNumber=function formatNumber(langCode,value,fractions){return getFormattedNumberFromCache(langCode,fractions).format({value:value});};var getNumberFormatter=curry(formatNumber);export default getNumberFormatter;
@@ -1 +1 @@
1
- import _getTranslator from"./getTranslator";export{_getTranslator as getTranslator};import _getPriceFormatter from"./getPriceFormatter";export{_getPriceFormatter as getPriceFormatter};import _getDateFormatter from"./getDateFormatter";export{_getDateFormatter as getDateFormatter};import _getTimeFormatter from"./getTimeFormatter";export{_getTimeFormatter as getTimeFormatter};import _getNumberFormatter from"./getNumberFormatter";export{_getNumberFormatter as getNumberFormatter};
1
+ export{default as getTranslator}from"./getTranslator";export{default as getPriceFormatter}from"./getPriceFormatter";export{default as getDateFormatter}from"./getDateFormatter";export{default as getTimeFormatter}from"./getTimeFormatter";export{default as getNumberFormatter}from"./getNumberFormatter";
@@ -17,5 +17,5 @@ var _themeLocale$split=themeLocale.split('-'),_themeLocale$split2=_slicedToArray
17
17
  * @return {Object}
18
18
  */var mergeTranslations=function mergeTranslations(theme,extensions){var locale=arguments.length>2&&arguments[2]!==undefined?arguments[2]:process.env.LOCALE_FILE;if(!isPlainObject(extensions)||Object.keys(extensions).length===0){// No extension translations provided.
19
19
  return cloneDeep(theme);}return Object.keys(extensions).reduce(function(result,extensionLocale){if(!localesMatch(locale,extensionLocale)){// Continue if the current extension locale doesn't match the theme locale.
20
- return result;}// Merge the curent extensions into the result.
20
+ return result;}// Merge the current extensions into the result.
21
21
  return merge(result,extensions[extensionLocale]);},cloneDeep(theme));};export default mergeTranslations;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopgate/pwa-common",
3
- "version": "7.20.0-beta.2",
3
+ "version": "7.20.0-beta.3",
4
4
  "description": "Common library for the Shopgate Connect PWA.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Shopgate <support@shopgate.com>",
@@ -16,7 +16,7 @@
16
16
  ],
17
17
  "dependencies": {
18
18
  "@sentry/browser": "6.0.1",
19
- "@shopgate/pwa-benchmark": "7.20.0-beta.2",
19
+ "@shopgate/pwa-benchmark": "7.20.0-beta.3",
20
20
  "@virtuous/conductor": "~2.5.0",
21
21
  "@virtuous/react-conductor": "~2.5.0",
22
22
  "@virtuous/redux-persister": "1.1.0-beta.7",
@@ -44,7 +44,7 @@
44
44
  "url-search-params": "^0.10.0"
45
45
  },
46
46
  "devDependencies": {
47
- "@shopgate/pwa-core": "7.20.0-beta.2",
47
+ "@shopgate/pwa-core": "7.20.0-beta.3",
48
48
  "lodash": "^4.17.4",
49
49
  "prop-types": "~15.7.2",
50
50
  "react": "~16.12.0",