diff --git a/_config.yml b/_config.yml index 0fb2eee..b339e0b 100644 --- a/_config.yml +++ b/_config.yml @@ -65,3 +65,5 @@ exclude: - README.md - node_modules - scripts + - sw.js + - workbox-config.js diff --git a/_includes/pagination.html b/_includes/pagination.html index 151fab2..de1394a 100644 --- a/_includes/pagination.html +++ b/_includes/pagination.html @@ -19,7 +19,7 @@ {% if page == 1%} "/" {% else %} - "{{ site.paginate_path | replace: ':num', page }}" + "{{ site.paginate_path | replace: ':num', page }}/" {% endif %}> {% assign pageMinusOne = paginator.page | minus: 1 %} {% if page == pageMinusOne %} diff --git a/_layouts/blank.html b/_layouts/blank.html index 048c015..c8ce9bb 100644 --- a/_layouts/blank.html +++ b/_layouts/blank.html @@ -6,7 +6,9 @@ {% include svg-icons.html %} diff --git a/js/vendor/sw-cacheable-response.min.js b/js/vendor/sw-cacheable-response.min.js deleted file mode 100644 index 81cc852..0000000 --- a/js/vendor/sw-cacheable-response.min.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - Copyright 2016 Google Inc. All Rights Reserved. - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?b(exports):'function'==typeof define&&define.amd?define(['exports'],b):b((a.goog=a.goog||{},a.goog.cacheableResponse=a.goog.cacheableResponse||{}))})(this,function(a){'use strict';function createCommonjsModule(s,t){return t={exports:{}},s(t,t.exports),t.exports}function throwError(s){const t=new Error(s),u=d.parse(t);throw 3<=u.length&&(t.message=`Invalid call to ${u[2].functionName}() — `+s.replace(/\s+/g,' '),t.name=u[1].functionName.replace(/^Object\./,'')),t}var b='undefined'==typeof window?'undefined'==typeof global?'undefined'==typeof self?{}:self:global:window,c=createCommonjsModule(function(s){(function(u,w){'use strict';s.exports=w()})(b,function(){'use strict';function _isNumber(C){return!isNaN(parseFloat(C))&&isFinite(C)}function _capitalize(C){return C[0].toUpperCase()+C.substring(1)}function _getter(C){return function(){return this[C]}}function StackFrame(C){if(C instanceof Object)for(var D=u.concat(w.concat(x.concat(y))),E=0;E'].indexOf(D[0])?void 0:D[0];return new u({functionName:E,fileName:F,lineNumber:D[1],columnNumber:D[2],source:B})},this)},parseFFOrSafari:function ErrorStackParser$$parseFFOrSafari(z){var A=z.stack.split('\n').filter(function(B){return!B.match(y)},this);return A.map(function(B){if(-1 eval')&&(B=B.replace(/ line (\d+)(?: > eval line \d+)* > eval\:\d+\:\d+/g,':$1')),-1===B.indexOf('@')&&-1===B.indexOf(':'))return new u({functionName:B});var C=B.split('@'),D=this.extractLocation(C.pop()),E=C.join('@')||void 0;return new u({functionName:E,fileName:D[0],lineNumber:D[1],columnNumber:D[2],source:B})},this)},parseOpera:function ErrorStackParser$$parseOpera(z){return!z.stacktrace||-1z.stacktrace.split('\n').length?this.parseOpera9(z):z.stack?this.parseOpera11(z):this.parseOpera10(z)},parseOpera9:function ErrorStackParser$$parseOpera9(z){for(var F,A=/Line (\d+).*script (?:in )?(\S+)/i,B=z.message.split('\n'),C=[],D=2,E=B.length;D/,'$2').replace(/\([^\)]*\)/g,'')||void 0,G;E.match(/\(([^\)]*)\)/)&&(G=E.replace(/^[^\(]+\(([^\)]*)\)$/,'$1'));var H=G===void 0||'[arguments not available]'===G?void 0:G.split(',');return new u({functionName:F,args:H,fileName:D[0],lineNumber:D[1],columnNumber:D[2],source:B})},this)}}})}),f={atLeastOne:function atLeastOne(s){const t=Object.keys(s);t.some((u)=>s[u]!==void 0)||throwError('Please set at least one of the following parameters: '+t.map((u)=>`'${u}'`).join(', '))},hasMethod:function hasMethod(s,t){const u=Object.keys(s).pop(),w=typeof s[u][t];'function'!=w&&throwError(`The '${u}' parameter must be an object that exposes a - '${t}' method.`)},isInstance:function isInstance(s,t){const u=Object.keys(s).pop();s[u]instanceof t||throwError(`The '${u}' parameter must be an instance of - '${t.name}'`)},isOneOf:function isOneOf(s,t){const u=Object.keys(s).pop();t.includes(s[u])||throwError(`The '${u}' parameter must be set to one of the - following: ${t}`)},isType:function isType(s,t){const u=Object.keys(s).pop(),w=typeof s[u];w!==t&&throwError(`The '${u}' parameter has the wrong type. (Expected: - ${t}, actual: ${w})`)},isSWEnv:function isSWEnv(){return'ServiceWorkerGlobalScope'in self&&self instanceof ServiceWorkerGlobalScope},isValue:function isValue(s,t){const u=Object.keys(s).pop(),w=s[u];w!==t&&throwError(`The '${u}' parameter has the wrong value. (Expected: - ${t}, actual: ${w})`)},isArrayOfType:function isArrayOfType(s,t){const u=Object.keys(s).pop(),w=`The '${u}' parameter should be an array containing - one or more '${t}' elements.`;Array.isArray(s[u])||throwError(w);for(let x of s[u])typeof x!==t&&throwError(w)},isArrayOfClass:function isArrayOfClass(s,t){const u=Object.keys(s).pop(),w=`The '${u}' parameter should be an array containing - one or more '${t.name}' instances.`;Array.isArray(s[u])||throwError(w);for(let x of s[u])x instanceof t||throwError(w)}};class LogGroup{constructor({title:s,isPrimary:t}={}){this._isPrimary=t||!1,this._groupTitle=s||'',this._logs=[],this._childGroups=[],this._isFirefox=!1,/Firefox\/\d*\.\d*/.exec(navigator.userAgent)&&(this._isFirefox=!0),this._isEdge=!1,/Edge\/\d*\.\d*/.exec(navigator.userAgent)&&(this._isEdge=!0)}addLog(s){this._logs.push(s)}addChildGroup(s){0===s._logs.length||this._childGroups.push(s)}print(){return this._isEdge?this._printEdgeFriendly():void(this._openGroup(),this._logs.forEach((s)=>{this._printLogDetails(s)}),this._childGroups.forEach((s)=>{s.print()}),this._closeGroup())}_printEdgeFriendly(){this._logs.forEach((s)=>{let u=s.message;'string'==typeof u&&(u=u.replace(/%c/g,''));const w=[u];s.error&&w.push(s.error),s.args&&w.push(s.args);const x=s.logFunc||console.log;x(...w)}),this._childGroups.forEach((s)=>{s.print()})}_printLogDetails(s){const t=s.logFunc?s.logFunc:console.log;let u=s.message,w=[u];s.colors&&!this._isEdge&&(w=w.concat(s.colors)),s.args&&(w=w.concat(s.args)),t(...w)}_openGroup(){if(this._isPrimary){if(0===this._childGroups.length)return;const s=this._logs.shift();if(this._isFirefox)return void this._printLogDetails(s);s.logFunc=console.group,this._printLogDetails(s)}else console.groupCollapsed(this._groupTitle)}_closeGroup(){this._isPrimary&&0===this._childGroups.length||console.groupEnd()}}self.goog=self.goog||{},self.goog.LOG_LEVEL=self.goog.LOG_LEVEL||{none:-1,verbose:0,debug:1,warn:2,error:3};const g=`#bdc3c7`,h=`#7f8c8d`,l=`#2ecc71`,m=`#f1c40f`,o=`#e74c3c`,q=`#3498db`;var r=new class LogHelper{constructor(){this._defaultLogLevel='localhost'===location.hostname?self.goog.LOG_LEVEL.debug:self.goog.LOG_LEVEL.none}log(s){this._printMessage(self.goog.LOG_LEVEL.verbose,s)}debug(s){this._printMessage(self.goog.LOG_LEVEL.debug,s)}warn(s){this._printMessage(self.goog.LOG_LEVEL.warn,s)}error(s){this._printMessage(self.goog.LOG_LEVEL.error,s)}_printMessage(s,t){if(this._shouldLogMessage(s,t)){const u=this._getAllLogGroups(s,t);u.print()}}_getAllLogGroups(s,t){const u=new LogGroup({isPrimary:!0,title:'sw-helpers log.'}),w=this._getPrimaryMessageDetails(s,t);if(u.addLog(w),t.error){const y={message:t.error,logFunc:console.error};u.addLog(y)}const x=new LogGroup({title:'Extra Information.'});if(t.that&&t.that.constructor&&t.that.constructor.name){const y=t.that.constructor.name;x.addLog(this._getKeyValueDetails('class',y))}return t.data&&('object'!=typeof t.data||t.data instanceof Array?x.addLog(this._getKeyValueDetails('additionalData',t.data)):Object.keys(t.data).forEach((y)=>{x.addLog(this._getKeyValueDetails(y,t.data[y]))})),u.addChildGroup(x),u}_getKeyValueDetails(s,t){return{message:`%c${s}: `,colors:[`color: ${q}`],args:t}}_getPrimaryMessageDetails(s,t){let u,w;s===self.goog.LOG_LEVEL.verbose?(u='Info',w=g):s===self.goog.LOG_LEVEL.debug?(u='Debug',w=l):s===self.goog.LOG_LEVEL.warn?(u='Warn',w=m):s===self.goog.LOG_LEVEL.error?(u='Error',w=o):void 0;let x=`%c🔧 %c[${u}]`;const y=[`color: ${g}`,`color: ${w}`];let z;return'string'==typeof t?z=t:t.message&&(z=t.message),z&&(x+=`%c ${z}`,y.push(`color: ${h}; font-weight: normal`)),{message:x,colors:y}}_shouldLogMessage(s,t){if(!t)return!1;let u=this._defaultLogLevel;return self&&self.goog&&'number'==typeof self.goog.logLevel&&(u=self.goog.logLevel),u===self.goog.LOG_LEVEL.none||s{return s.headers.get(u)===this.headers[u]})),!t){const u={response:s};this.statuses&&(u['valid-status-codes']=JSON.stringify(this.statuses)),this.headers&&(u['valid-headers']=JSON.stringify(this.headers)),r.debug({message:`The response does not meet the criteria for being added `+`to the cache.`,data:u})}return t}}a.CacheableResponse=CacheableResponse,a.CacheableResponsePlugin=class CacheableResponsePlugin extends CacheableResponse{cacheWillUpdate({response:s}={}){return this.isResponseCacheable({response:s})}},Object.defineProperty(a,'__esModule',{value:!0})}); -//# sourceMappingURL=sw-cacheable-response.min.js.map diff --git a/js/vendor/sw-lib.min.js b/js/vendor/sw-lib.min.js deleted file mode 100644 index ae1ea24..0000000 --- a/js/vendor/sw-lib.min.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright 2016 Google Inc. All Rights Reserved. - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -(function(t,r){'object'==typeof exports&&'undefined'!=typeof module?module.exports=r():'function'==typeof define&&define.amd?define(r):(t.goog=t.goog||{},t.goog.swlib=r())})(this,function(){'use strict';function createCommonjsModule(ae,ne){return ne={exports:{}},ae(ne,ne.exports),ne.exports}function throwError(ae){const ne=new Error(ae),se=d.parse(ne);throw 3<=se.length&&(ne.message=`Invalid call to ${se[2].functionName}() — `+ae.replace(/\s+/g,' '),ne.name=se[1].functionName.replace(/^Object\./,'')),ne}function parse(ae,ne){for(var de,se=[],ie=0,oe=0,ce='',le=ne&&ne.delimiter||'/';null!=(de=x.exec(ae));){var ue=de[0],pe=de[1],he=de.index;if(ce+=ae.slice(oe,he),oe=he+ue.length,pe){ce+=pe[1];continue}var me=ae[oe],ge=de[2],fe=de[3],ye=de[4],be=de[5],_e=de[6],ve=de[7];ce&&(se.push(ce),ce='');var xe=de[2]||le,ke=ye||be;se.push({name:fe||ie++,prefix:ge||'',delimiter:xe,optional:'?'===_e||'*'===_e,repeat:'+'===_e||'*'===_e,partial:null!=ge&&null!=me&&me!==ge,asterisk:!!ve,pattern:ke?escapeGroup(ke):ve?'.*':'[^'+escapeString(xe)+']+?'})}return oe{return ae.headers.has(ie)===ne.headers.has(ie)&&ae.headers.get(ie)===ne.headers.get(ie)})}class ErrorFactory$1{constructor(ae){this._errors=ae}createError(ae,ne){if(!(ae in this._errors))throw new Error(`Unable to generate error '${ae}'.`);let se=this._errors[ae].replace(/\s+/g,' '),ie=null;ne&&(se+=` [${ne.message}]`,ie=ne.stack);const oe=new Error;return oe.name=ae,oe.message=se,oe.stack=ie,oe}}const t={'not-in-sw':'sw-lib must be loaded in your service worker file.','unsupported-route-type':'Routes must be either a express style route string, a Regex to capture request URLs or a Route instance.','empty-express-string':'The Express style route string must have some characters, an empty string is invalid.','bad-revisioned-cache-list':`The 'cacheRevisionedAssets()' method expects`+`an array of revisioned urls like so: ['/example/hello.1234.txt', `+`{path: 'hello.txt', revision: '1234'}]`,'navigation-route-url-string':`The registerNavigationRoute() method `+`expects a URL string as its first parameter.`};var r=new ErrorFactory$1(t);const a={'express-route-requires-absolute-path':`When using ExpressRoute, you must - provide a path that starts with a '/' character. You can only match - same-origin requests. For more flexibility, use RegExpRoute.`};var s=new ErrorFactory$1(a),o='undefined'==typeof window?'undefined'==typeof global?'undefined'==typeof self?{}:self:global:window,l=createCommonjsModule(function(ae){(function(se,ie){'use strict';ae.exports=ie()})(o,function(){'use strict';function _isNumber(pe){return!isNaN(parseFloat(pe))&&isFinite(pe)}function _capitalize(pe){return pe[0].toUpperCase()+pe.substring(1)}function _getter(pe){return function(){return this[pe]}}function StackFrame(pe){if(pe instanceof Object)for(var he=se.concat(ie.concat(oe.concat(ce))),me=0;me'].indexOf(he[0])?void 0:he[0];return new se({functionName:me,fileName:ge,lineNumber:he[1],columnNumber:he[2],source:ue})},this)},parseFFOrSafari:function ErrorStackParser$$parseFFOrSafari(le){var de=le.stack.split('\n').filter(function(ue){return!ue.match(ce)},this);return de.map(function(ue){if(-1 eval')&&(ue=ue.replace(/ line (\d+)(?: > eval line \d+)* > eval\:\d+\:\d+/g,':$1')),-1===ue.indexOf('@')&&-1===ue.indexOf(':'))return new se({functionName:ue});var pe=ue.split('@'),he=this.extractLocation(pe.pop()),me=pe.join('@')||void 0;return new se({functionName:me,fileName:he[0],lineNumber:he[1],columnNumber:he[2],source:ue})},this)},parseOpera:function ErrorStackParser$$parseOpera(le){return!le.stacktrace||-1le.stacktrace.split('\n').length?this.parseOpera9(le):le.stack?this.parseOpera11(le):this.parseOpera10(le)},parseOpera9:function ErrorStackParser$$parseOpera9(le){for(var ge,de=/Line (\d+).*script (?:in )?(\S+)/i,ue=le.message.split('\n'),pe=[],he=2,me=ue.length;he/,'$2').replace(/\([^\)]*\)/g,'')||void 0,fe;me.match(/\(([^\)]*)\)/)&&(fe=me.replace(/^[^\(]+\(([^\)]*)\)$/,'$1'));var ye=fe===void 0||'[arguments not available]'===fe?void 0:fe.split(',');return new se({functionName:ge,args:ye,fileName:he[0],lineNumber:he[1],columnNumber:he[2],source:ue})},this)}}})}),u={atLeastOne:function atLeastOne(ae){const ne=Object.keys(ae);ne.some((se)=>ae[se]!==void 0)||throwError('Please set at least one of the following parameters: '+ne.map((se)=>`'${se}'`).join(', '))},hasMethod:function hasMethod(ae,ne){const se=Object.keys(ae).pop(),ie=typeof ae[se][ne];'function'!=ie&&throwError(`The '${se}' parameter must be an object that exposes a - '${ne}' method.`)},isInstance:function isInstance(ae,ne){const se=Object.keys(ae).pop();ae[se]instanceof ne||throwError(`The '${se}' parameter must be an instance of - '${ne.name}'`)},isOneOf:function isOneOf(ae,ne){const se=Object.keys(ae).pop();ne.includes(ae[se])||throwError(`The '${se}' parameter must be set to one of the - following: ${ne}`)},isType:function isType(ae,ne){const se=Object.keys(ae).pop(),ie=typeof ae[se];ie!==ne&&throwError(`The '${se}' parameter has the wrong type. (Expected: - ${ne}, actual: ${ie})`)},isSWEnv:function isSWEnv(){return'ServiceWorkerGlobalScope'in self&&self instanceof ServiceWorkerGlobalScope},isValue:function isValue(ae,ne){const se=Object.keys(ae).pop(),ie=ae[se];ie!==ne&&throwError(`The '${se}' parameter has the wrong value. (Expected: - ${ne}, actual: ${ie})`)},isArrayOfType:function isArrayOfType(ae,ne){const se=Object.keys(ae).pop(),ie=`The '${se}' parameter should be an array containing - one or more '${ne}' elements.`;Array.isArray(ae[se])||throwError(ie);for(let oe of ae[se])typeof oe!==ne&&throwError(ie)},isArrayOfClass:function isArrayOfClass(ae,ne){const se=Object.keys(ae).pop(),ie=`The '${se}' parameter should be an array containing - one or more '${ne.name}' instances.`;Array.isArray(ae[se])||throwError(ie);for(let oe of ae[se])oe instanceof ne||throwError(ie)}};const g=['DELETE','GET','HEAD','POST','PUT'];class Route{constructor({match:ae,handler:ne,method:se}={}){u.isType({match:ae},'function'),'object'==typeof ne?u.hasMethod({handler:ne},'handle'):u.isType({handler:ne},'function'),this.match=ae,this.handler='function'==typeof ne?{handle:ne}:ne,se?(u.isOneOf({method:se},g),this.method=se):this.method='GET'}}var f=Array.isArray||function(ae){return'[object Array]'==Object.prototype.toString.call(ae)},y=f,b=pathToRegexp,x=new RegExp(['(\\\\.)','([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'].join('|'),'g');b.parse=parse,b.compile=function compile(ae,ne){return tokensToFunction(parse(ae,ne))},b.tokensToFunction=tokensToFunction,b.tokensToRegExp=tokensToRegExp;class ExpressRoute extends Route{constructor({path:ae,handler:ne,method:se}){if('/'!==ae.substring(0,1))throw s.createError('express-route-requires-absolute-path');let ie=[];const oe=b(ae,ie);super({match:({url:le})=>{if(le.origin!==location.origin)return null;const de=le.pathname.match(oe);if(!de)return null;const ue={};return ie.forEach((pe,he)=>{ue[pe.name]=de[he+1]}),ue},handler:ne,method:se})}}class NavigationRoute extends Route{constructor({whitelist:ae,blacklist:ne,handler:se}={}){u.isArrayOfClass({whitelist:ae},RegExp),ne?u.isArrayOfClass({blacklist:ne},RegExp):ne=[];super({match:({event:oe,url:ce})=>{return'navigate'===oe.request.mode&&ae.some((le)=>le.test(ce.pathname))&&!ne.some((le)=>le.test(ce.pathname))},handler:se,method:'GET'})}}class RegExpRoute extends Route{constructor({regExp:ae,handler:ne,method:se}){u.isInstance({regExp:ae},RegExp);super({match:({url:oe})=>{const ce=oe.href.match(ae);return ce?ce.slice(1):null},handler:ne,method:se})}}self.goog=self.goog||{},self.goog.LOG_LEVEL=self.goog.LOG_LEVEL||{none:-1,verbose:0,debug:1,warn:2,error:3};var q=new class LogHelper{constructor(){this._allowedLogLevel='localhost'===location.hostname?self.goog.LOG_LEVEL.debug:self.goog.LOG_LEVEL.none}log(...ae){this._printMessage(self.goog.LOG_LEVEL.verbose,console.log,ae)}debug(...ae){this._printMessage(self.goog.LOG_LEVEL.debug,console.debug,ae)}warn(...ae){this._printMessage(self.goog.LOG_LEVEL.warn,console.warn,ae)}error(...ae){this._printMessage(self.goog.LOG_LEVEL.error,console.error,ae)}_printMessage(ae,ne,se){let ie=this._allowedLogLevel;self&&self.goog&&self.goog.logLevel&&(ie=self.goog.logLevel);ie===self.goog.LOG_LEVEL.none||ae{const se=new URL(ne.request.url);if(!se.protocol.startsWith('http'))return void q.debug(`[router.js] URL does not start with HTTP`,ne.request.url);let ie;for(let oe of ae||[])if(oe.method===ne.request.method){const ce=oe.match({url:se,event:ne});if(ce){q.debug(`[router.js] Found matching result: `,ne.request.url);let le=ce;Array.isArray(le)&&0===le.length?le=void 0:le.constructor===Object&&0===Object.keys(le).length&&(le=void 0),ie=oe.handler.handle({url:se,event:ne,params:le});break}}!ie&&this.defaultHandler&&(ie=this.defaultHandler.handle({url:se,event:ne})),ie&&this.catchHandler&&(ie=ie.catch((oe)=>{return this.catchHandler.handle({url:se,event:ne,error:oe})})),ie&&ne.respondWith(ie.then((oe)=>{return q.debug(`[router.js] Returning response for `+`'${ne.request.url}': `,oe),oe}))})}registerRoute({route:ae}={}){u.isInstance({route:ae},Route),this.registerRoutes({routes:[ae]})}}class Router$$1 extends Router$2{registerRoute(ae,ne){if('function'==typeof ne&&(ne={handle:ne}),'string'==typeof ae){if(0===ae.length)throw r.createError('empty-express-string');super.registerRoute({route:new ExpressRoute({path:ae,handler:ne})})}else if(ae instanceof RegExp)super.registerRoute({route:new RegExpRoute({regExp:ae,handler:ne})});else if(ae instanceof Route)super.registerRoute({route:ae});else throw r.createError('unsupported-route-type')}registerNavigationRoute(ae,ne={}){if('string'!=typeof ae)throw r.createError('navigation-route-url-string');super.registerRoute({route:new NavigationRoute({handler:()=>caches.match(ae),whitelist:ne.whitelist||[/./],blacklist:ne.blacklist||[]})})}}const O={'not-in-sw':'sw-precaching must be loaded in your service worker file.','invalid-revisioned-entry':`File manifest entries must be either a `+`string with revision info in the url or an object with a 'url' and `+`'revision' parameters.`,'invalid-unrevisioned-entry':``,'bad-cache-bust':`The cache bust parameter must be a boolean.`,'duplicate-entry-diff-revisions':`An attempt was made to cache the same `+`url twice with each having different revisions. This is not supported.`,'request-not-cached':`A request failed the criteria to be cached. By `+`default, only responses with 'response.ok = true' are cached.`,'should-override':'Method should be overridden by the extending class.'};var T=new ErrorFactory$1(O);let w=`sw-runtime-caching`;self&&self.registration&&(w+=`-${self.registration.scope}`);const L=w,I=['cacheDidUpdate','cacheWillMatch','cacheWillUpdate','fetchDidFail','requestWillFetch'];var A=new ErrorFactory$1({'multiple-cache-will-update-plugins':'You cannot register more than one plugin that implements cacheWillUpdate.','multiple-cache-will-match-plugins':'You cannot register more than one plugin that implements cacheWillMatch.','invalid-reponse-for-caching':'The fetched response could not be cached due to an invalid response code, by default only 20X responses can be cached.'}),D=function(ae){return function(){var ne=ae.apply(this,arguments);return new Promise(function(se,ie){function step(oe,ce){try{var le=ne[oe](ce),de=le.value}catch(ue){return void ie(ue)}return le.done?void se(de):Promise.resolve(de).then(function(ue){step('next',ue)},function(ue){step('throw',ue)})}return step('next')})}};class RequestWrapper{constructor({cacheName:ae,plugins:ne,fetchOptions:se,matchOptions:ie}={}){if(ae?(u.isType({cacheName:ae},'string'),this.cacheName=ae):this.cacheName=L,se&&(u.isType({fetchOptions:se},'object'),this.fetchOptions=se),ie&&(u.isType({matchOptions:ie},'object'),this.matchOptions=ie),this.pluginCallbacks={},ne&&(u.isArrayOfType({plugins:ne},'object'),ne.forEach((oe)=>{for(let ce of I)'function'==typeof oe[ce]&&(this.pluginCallbacks[ce]||(this.pluginCallbacks[ce]=[]),this.pluginCallbacks[ce].push(oe[ce].bind(oe)))})),this.pluginCallbacks.cacheWillUpdate&&1!==this.pluginCallbacks.cacheWillUpdate.length)throw A.createError('multiple-cache-will-update-plugins');if(this.pluginCallbacks.cacheWillMatch&&1!==this.pluginCallbacks.cacheWillMatch.length)throw A.createError('multiple-cache-will-match-plugins')}getCache(){var ae=this;return D(function*(){return ae._cache||(ae._cache=yield caches.open(ae.cacheName)),ae._cache})()}match({request:ae}){var ne=this;return D(function*(){u.atLeastOne({request:ae});const se=yield ne.getCache();let ie=yield se.match(ae,ne.matchOptions);return ne.pluginCallbacks.cacheWillMatch&&(ie=ne.pluginCallbacks.cacheWillMatch[0]({cachedResponse:ie})),ie})()}fetch({request:ae}){var ne=this;return D(function*(){u.atLeastOne({request:ae});const se=ne.pluginCallbacks.fetchDidFail?ae.clone():null;if(ne.pluginCallbacks.requestWillFetch)for(let ie of ne.pluginCallbacks.requestWillFetch){const oe=ie({request:ae});u.isInstance({returnedPromise:oe},Promise);const ce=yield oe;u.isInstance({returnedRequest:ce},Request),ae=ce}try{return yield fetch(ae,ne.fetchOptions)}catch(ie){if(ne.pluginCallbacks.fetchDidFail)for(let oe of ne.pluginCallbacks.fetchDidFail)oe({request:se.clone()});throw ie}})()}fetchAndCache({request:ae,waitOnCache:ne,cacheKey:se}){var ie=this;return D(function*(){u.atLeastOne({request:ae});let oe;const ce=yield ie.fetch({request:ae});let le=ce.ok;if(ie.pluginCallbacks.cacheWillUpdate&&(le=ie.pluginCallbacks.cacheWillUpdate[0]({request:ae,response:ce})),le){const de=ce.clone();oe=ie.getCache().then((()=>{var ue=D(function*(pe){let he;'opaque'!==ce.type&&ie.pluginCallbacks.cacheDidUpdate&&(he=yield ie.match({request:ae}));yield pe.put(se||ae,de);for(let ge of ie.pluginCallbacks.cacheDidUpdate||[])ge({cacheName:ie.cacheName,oldResponse:he,newResponse:de,url:ae.url})});return function(){return ue.apply(this,arguments)}})())}else if(!le&&(q.debug(`[RequestWrapper] The response for ${ae.url}, with - a status of ${ce.status}, wasn't cached. By default, only - responses with a status of 200 are cached. You can configure the - cacheableResponse plugin to change this default.`.replace(/\s+/g,' ')),ne))throw A.createError('invalid-reponse-for-caching');return ne&&oe&&(yield oe),ce})()}}class Handler{constructor({requestWrapper:ae}={}){this.requestWrapper=ae?ae:new RequestWrapper}handle({event:ae,params:ne}={}){throw Error('This abstract method must be implemented in a subclass.')}}class CacheFirst extends Handler{handle({event:ae}={}){var ne=this;return D(function*(){u.isInstance({event:ae},FetchEvent);const se=yield ne.requestWrapper.match({request:ae.request});return se||(yield ne.requestWrapper.fetchAndCache({request:ae.request}))})()}}class CacheOnly extends Handler{handle({event:ae}={}){var ne=this;return D(function*(){return u.isInstance({event:ae},FetchEvent),yield ne.requestWrapper.match({request:ae.request})})()}}class NetworkFirst extends Handler{constructor(ae={}){super(ae);const{networkTimeoutSeconds:ne}=ae;ne&&(u.isType({networkTimeoutSeconds:ne},'number'),this.networkTimeoutSeconds=ne)}handle({event:ae}={}){var ne=this;return D(function*(){u.isInstance({event:ae},FetchEvent);const se=[];let ie;return ne.networkTimeoutSeconds&&se.push(new Promise(function(oe){ie=setTimeout(function(){oe(ne.requestWrapper.match({request:ae.request}))},1e3*ne.networkTimeoutSeconds)})),se.push(ne.requestWrapper.fetchAndCache({request:ae.request}).then(function(oe){return ie&&clearTimeout(ie),oe?oe:Promise.reject('No response received; falling back to cache.')}).catch(function(){return ne.requestWrapper.match({request:ae.request})})),Promise.race(se)})()}}class NetworkOnly extends Handler{handle({event:ae}={}){var ne=this;return D(function*(){return u.isInstance({event:ae},FetchEvent),yield ne.requestWrapper.fetch({request:ae.request})})()}}class StaleWhileRevalidate extends Handler{handle({event:ae}={}){var ne=this;return D(function*(){u.isInstance({event:ae},FetchEvent);const se=ne.requestWrapper.fetchAndCache({request:ae.request}).catch(function(){return Response.error()}),ie=yield ne.requestWrapper.match({request:ae.request});return ie||(yield se)})()}}class BaseCacheManager{constructor(ae){this._entriesToCache=new Map,this._requestWrapper=new RequestWrapper({cacheName:ae,fetchOptions:{credentials:'same-origin'}}),this._cacheName=this._requestWrapper.cacheName}_addEntries(ae){this._parsedCacheUrls=null,ae.forEach((ne)=>{this._addEntryToInstallList(this._parseEntry(ne))})}getCacheName(){return this._cacheName}getCachedUrls(){return this._parsedCacheUrls||(this._parsedCacheUrls=Array.from(this._entriesToCache.keys()).map((ae)=>new URL(ae,location).href)),this._parsedCacheUrls}_addEntryToInstallList(ae){const ne=ae.entryID,se=this._entriesToCache.get(ae.entryID);return se?void this._onDuplicateInstallEntryFound(ae,se):void this._entriesToCache.set(ne,ae)}install(){var ae=this;return D(function*(){if(0!==ae._entriesToCache.size){const ne=[];return ae._entriesToCache.forEach(function(se){ne.push(ae._cacheEntry(se))}),Promise.all(ne)}})()}_cacheEntry(ae){var ne=this;return D(function*(){const se=yield ne._isAlreadyCached(ae);if(!se)try{return yield ne._requestWrapper.fetchAndCache({request:ae.getNetworkRequest(),waitOnCache:!0,cacheKey:ae.request}),ne._onEntryCached(ae)}catch(ie){throw T.createError('request-not-cached',{message:`Failed to get a cacheable response for `+`'${ae.request.url}': ${ie.message}`})}})()}cleanup(){var ae=this;return D(function*(){if(yield caches.has(ae._cacheName)){const ne=[];ae._entriesToCache.forEach(function(ce){ne.push(ce.request.url)});const se=yield ae._getCache(),ie=yield se.keys(),oe=ie.filter(function(ce){return!ne.includes(ce.url)});return Promise.all(oe.map(function(ce){return se.delete(ce)}))}})()}_getCache(){var ae=this;return D(function*(){return ae._cache||(ae._cache=yield caches.open(ae._cacheName)),ae._cache})()}_parseEntry(){throw T.createError('should-override')}_onDuplicateEntryFound(){throw T.createError('should-override')}_isAlreadyCached(){throw T.createError('should-override')}_onEntryCached(){throw T.createError('should-override')}}var W=createCommonjsModule(function(ae){'use strict';(function(){function toArray(se){return Array.prototype.slice.call(se)}function promisifyRequest(se){return new Promise(function(ie,oe){se.onsuccess=function(){ie(se.result)},se.onerror=function(){oe(se.error)}})}function promisifyRequestCall(se,ie,oe){var ce,le=new Promise(function(de,ue){ce=se[ie].apply(se,oe),promisifyRequest(ce).then(de,ue)});return le.request=ce,le}function promisifyCursorRequestCall(se,ie,oe){var ce=promisifyRequestCall(se,ie,oe);return ce.then(function(le){return le?new Cursor(le,ce.request):void 0})}function proxyProperties(se,ie,oe){oe.forEach(function(ce){Object.defineProperty(se.prototype,ce,{get:function(){return this[ie][ce]},set:function(le){this[ie][ce]=le}})})}function proxyRequestMethods(se,ie,oe,ce){ce.forEach(function(le){le in oe.prototype&&(se.prototype[le]=function(){return promisifyRequestCall(this[ie],le,arguments)})})}function proxyMethods(se,ie,oe,ce){ce.forEach(function(le){le in oe.prototype&&(se.prototype[le]=function(){return this[ie][le].apply(this[ie],arguments)})})}function proxyCursorRequestMethods(se,ie,oe,ce){ce.forEach(function(le){le in oe.prototype&&(se.prototype[le]=function(){return promisifyCursorRequestCall(this[ie],le,arguments)})})}function Index(se){this._index=se}function Cursor(se,ie){this._cursor=se,this._request=ie}function ObjectStore(se){this._store=se}function Transaction(se){this._tx=se,this.complete=new Promise(function(ie,oe){se.oncomplete=function(){ie()},se.onerror=function(){oe(se.error)},se.onabort=function(){oe(se.error)}})}function UpgradeDB(se,ie,oe){this._db=se,this.oldVersion=ie,this.transaction=new Transaction(oe)}function DB(se){this._db=se}proxyProperties(Index,'_index',['name','keyPath','multiEntry','unique']),proxyRequestMethods(Index,'_index',IDBIndex,['get','getKey','getAll','getAllKeys','count']),proxyCursorRequestMethods(Index,'_index',IDBIndex,['openCursor','openKeyCursor']),proxyProperties(Cursor,'_cursor',['direction','key','primaryKey','value']),proxyRequestMethods(Cursor,'_cursor',IDBCursor,['update','delete']),['advance','continue','continuePrimaryKey'].forEach(function(se){se in IDBCursor.prototype&&(Cursor.prototype[se]=function(){var ie=this,oe=arguments;return Promise.resolve().then(function(){return ie._cursor[se].apply(ie._cursor,oe),promisifyRequest(ie._request).then(function(ce){return ce?new Cursor(ce,ie._request):void 0})})})}),ObjectStore.prototype.createIndex=function(){return new Index(this._store.createIndex.apply(this._store,arguments))},ObjectStore.prototype.index=function(){return new Index(this._store.index.apply(this._store,arguments))},proxyProperties(ObjectStore,'_store',['name','keyPath','indexNames','autoIncrement']),proxyRequestMethods(ObjectStore,'_store',IDBObjectStore,['put','add','delete','clear','get','getAll','getKey','getAllKeys','count']),proxyCursorRequestMethods(ObjectStore,'_store',IDBObjectStore,['openCursor','openKeyCursor']),proxyMethods(ObjectStore,'_store',IDBObjectStore,['deleteIndex']),Transaction.prototype.objectStore=function(){return new ObjectStore(this._tx.objectStore.apply(this._tx,arguments))},proxyProperties(Transaction,'_tx',['objectStoreNames','mode']),proxyMethods(Transaction,'_tx',IDBTransaction,['abort']),UpgradeDB.prototype.createObjectStore=function(){return new ObjectStore(this._db.createObjectStore.apply(this._db,arguments))},proxyProperties(UpgradeDB,'_db',['name','version','objectStoreNames']),proxyMethods(UpgradeDB,'_db',IDBDatabase,['deleteObjectStore','close']),DB.prototype.transaction=function(){return new Transaction(this._db.transaction.apply(this._db,arguments))},proxyProperties(DB,'_db',['name','version','objectStoreNames']),proxyMethods(DB,'_db',IDBDatabase,['close']),['openCursor','openKeyCursor'].forEach(function(se){[ObjectStore,Index].forEach(function(ie){ie.prototype[se.replace('open','iterate')]=function(){var oe=toArray(arguments),ce=oe[oe.length-1],le=this._store||this._index,de=le[se].apply(le,oe.slice(0,-1));de.onsuccess=function(){ce(de.result)}}})}),[Index,ObjectStore].forEach(function(se){se.prototype.getAll||(se.prototype.getAll=function(ie,oe){var ce=this,le=[];return new Promise(function(de){ce.iterateCursor(ie,function(ue){return ue?(le.push(ue.value),void 0!==oe&&le.length==oe?void de(le):void ue.continue()):void de(le)})})})});ae.exports={open:function(se,ie,oe){var ce=promisifyRequestCall(indexedDB,'open',[se,ie]),le=ce.request;return le.onupgradeneeded=function(de){oe&&oe(new UpgradeDB(le.result,de.oldVersion,le.transaction))},ce.then(function(de){return new DB(de)})},delete:function(se){return promisifyRequestCall(indexedDB,'deleteDatabase',[se])}}})()});class IDBHelper{constructor(ae,ne,se){if(ae==void 0||ne==void 0||se==void 0)throw Error('name, version, storeName must be passed to the constructor.');this._name=ae,this._version=ne,this._storeName=se}_getDb(){return this._dbPromise?this._dbPromise:(this._dbPromise=W.open(this._name,this._version,(ae)=>{ae.createObjectStore(this._storeName)}).then((ae)=>{return ae}),this._dbPromise)}close(){return this._dbPromise?this._dbPromise.then((ae)=>{ae.close(),this._dbPromise=null}):void 0}put(ae,ne){return this._getDb().then((se)=>{const ie=se.transaction(this._storeName,'readwrite'),oe=ie.objectStore(this._storeName);return oe.put(ne,ae),ie.complete})}delete(ae){return this._getDb().then((ne)=>{const se=ne.transaction(this._storeName,'readwrite'),ie=se.objectStore(this._storeName);return ie.delete(ae),se.complete})}get(ae){return this._getDb().then((ne)=>{return ne.transaction(this._storeName).objectStore(this._storeName).get(ae)})}getAllValues(){return this._getDb().then((ae)=>{return ae.transaction(this._storeName).objectStore(this._storeName).getAll()})}getAllKeys(){return this._getDb().then((ae)=>{return ae.transaction(this._storeName).objectStore(this._storeName).getAllKeys()})}}let B=`sw-precaching-revisioned-${'v1'}`;self&&self.registration&&(B+=`-${self.registration.scope}`);const K=B;class RevisionDetailsModel{constructor(){this._idbHelper=new IDBHelper('sw-precaching','1','asset-revisions')}get(ae){return this._idbHelper.get(ae)}put(ae,ne){return this._idbHelper.put(ae,ne)}_close(){this._idbHelper.close()}}class BaseCacheEntry{constructor({entryID:ae,revision:ne,request:se,cacheBust:ie}){this.entryID=ae,this.revision=ne,this.request=se,this.cacheBust=ie}getNetworkRequest(){if(!0!==this.cacheBust)return this.request;let ae=this.request.url;const ne={};if(!0===this.cacheBust)if('cache'in Request.prototype)ne.cache='reload';else{const se=new URL(ae,location);se.search+=(se.search?'&':'')+encodeURIComponent('_sw-precaching')+'='+encodeURIComponent(this.revision),ae=se.toString()}return new Request(ae,ne)}}class StringCacheEntry extends BaseCacheEntry{constructor(ae){if(u.isType({url:ae},'string'),0===ae.length)throw T.createError('invalid-revisioned-entry',new Error('Bad url Parameter. It should be a string:'+JSON.stringify(ae)));super({entryID:ae,revision:ae,request:new Request(ae),cacheBust:!1})}}class DefaultsCacheEntry extends BaseCacheEntry{constructor({entryID:ae,revision:ne,url:se,cacheBust:ie}){if('undefined'==typeof ie&&(ie=!0),'undefined'==typeof ae&&(ae=new URL(se,location).toString()),u.isType({revision:ne},'string'),0===ne.length)throw T.createError('invalid-revisioned-entry',new Error('Bad revision Parameter. It should be a string with at least one character: '+JSON.stringify(ne)));if(u.isType({url:se},'string'),0===se.length)throw T.createError('invalid-revisioned-entry',new Error('Bad url Parameter. It should be a string:'+JSON.stringify(se)));if(u.isType({entryID:ae},'string'),0===ae.length)throw T.createError('invalid-revisioned-entry',new Error('Bad entryID Parameter. It should be a string with at least one character: '+JSON.stringify(ae)));u.isType({cacheBust:ie},'boolean'),super({entryID:ae,revision:ne,request:new Request(se),cacheBust:ie})}}class RevisionedCacheManager extends BaseCacheManager{constructor({cacheName:ae}={}){ae=ae||K,super(ae),this._revisionDetailsModel=new RevisionDetailsModel}addToCacheList({revisionedFiles:ae}={}){u.isInstance({revisionedFiles:ae},Array),super._addEntries(ae)}_parseEntry(ae){if('undefined'==typeof ae||null===ae)throw T.createError('invalid-revisioned-entry',new Error('Invalid file entry: '+JSON.stringify(ae)));let ne;switch(typeof ae){case'string':ne=new StringCacheEntry(ae);break;case'object':ne=new DefaultsCacheEntry(ae);break;default:throw T.createError('invalid-revisioned-entry',new Error('Invalid file entry: '+JSON.stringify(ne)));}return ne}_onDuplicateInstallEntryFound(ae,ne){if(ne.revision!==ae.revision)throw T.createError('duplicate-entry-diff-revisions',new Error(`${JSON.stringify(ne)} <=> `+`${JSON.stringify(ae)}`))}_isAlreadyCached(ae){var ne=this;return D(function*(){const se=yield ne._revisionDetailsModel.get(ae.entryID);if(se!==ae.revision)return!1;const ie=yield ne._getCache(),oe=yield ie.match(ae.request);return!!oe})()}_onEntryCached(ae){var ne=this;return D(function*(){yield ne._revisionDetailsModel.put(ae.entryID,ae.revision)})()}_close(){this._revisionDetailsModel._close()}cleanup(){return super.cleanup().then(()=>{return this._close()})}}class RequestCacheEntry extends BaseCacheEntry{constructor(ae){if(!(ae instanceof Request))throw T.createError('invalid-unrevisioned-entry',new Error('Invalid file entry: '+JSON.stringify(ae)));super({entryID:ae.url,request:ae,cacheBust:!1})}}class UnrevisionedCacheManager extends BaseCacheManager{constructor({cacheName:ae}={}){super(ae)}addToCacheList({unrevisionedFiles:ae}={}){u.isInstance({unrevisionedFiles:ae},Array),super._addEntries(ae)}_parseEntry(ae){if('undefined'==typeof ae||null===ae)throw T.createError('invalid-unrevisioned-entry',new Error('Invalid file entry: '+JSON.stringify(ae)));if('string'==typeof ae)return new StringCacheEntry(ae);if(ae instanceof Request)return new RequestCacheEntry(ae);throw T.createError('invalid-unrevisioned-entry',new Error('Invalid file entry: '+JSON.stringify(ae)))}_onDuplicateInstallEntryFound(){}_isAlreadyCached(){return D(function*(){return!1})()}_onEntryCached(){}}if(!u.isSWEnv())throw T.createError('not-in-sw');const V=`sw-cache-expiration-${self.registration.scope}`,H='url',$='timestamp',Y={'max-entries-or-age-required':`Either the maxEntries or maxAgeSeconds - parameters (or both) are required when constructing Plugin.`,'max-entries-must-be-number':`The maxEntries parameter to the Plugin - constructor must either be a number or undefined.`,'max-age-seconds-must-be-number':`The maxAgeSeconds parameter to the Plugin - constructor must either be a number or undefined.`};var z=new ErrorFactory$1(Y);class Plugin{constructor({maxEntries:ae,maxAgeSeconds:ne}={}){if(!(ae||ne))throw z.createError('max-entries-or-age-required');if(ae&&'number'!=typeof ae)throw z.createError('max-entries-must-be-number');if(ne&&'number'!=typeof ne)throw z.createError('max-age-seconds-must-be-number');this.maxEntries=ae,this.maxAgeSeconds=ne,this._dbs=new Map,this._caches=new Map}getDB({cacheName:ae}={}){var ne=this;return D(function*(){u.isType({cacheName:ae},'string');const se=`${V}-${ae}`;if(!ne._dbs.has(se)){const ie=yield W.open(se,1,function(oe){const ce=oe.createObjectStore(ae,{keyPath:H});ce.createIndex($,$,{unique:!1})});ne._dbs.set(se,ie)}return ne._dbs.get(se)})()}getCache({cacheName:ae}={}){var ne=this;return D(function*(){if(u.isType({cacheName:ae},'string'),!ne._caches.has(ae)){const se=yield caches.open(ae);ne._caches.set(ae,se)}return ne._caches.get(ae)})()}cacheWillMatch({cachedResponse:ae,now:ne}={}){return this.isResponseFresh({cachedResponse:ae,now:ne})?ae:null}isResponseFresh({cachedResponse:ae,now:ne}={}){if(ae&&this.maxAgeSeconds){u.isInstance({cachedResponse:ae},Response);const se=ae.headers.get('date');if(se){'undefined'==typeof ne&&(ne=Date.now());const ie=new Date(se);if(ie.getTime()+1e3*this.maxAgeSeconds{this.expireEntries({cacheName:ae,now:ie})})}updateTimestamp({cacheName:ae,url:ne,now:se}={}){var ie=this;return D(function*(){u.isType({url:ne},'string'),u.isType({cacheName:ae},'string'),'undefined'==typeof se&&(se=Date.now());const oe=yield ie.getDB({cacheName:ae}),ce=oe.transaction(ae,'readwrite');ce.objectStore(ae).put({[$]:se,[H]:ne}),yield ce.complete})()}expireEntries({cacheName:ae,now:ne}={}){var se=this;return D(function*(){u.isType({cacheName:ae},'string'),'undefined'==typeof ne&&(ne=Date.now());const ie=se.maxAgeSeconds?yield se.findOldEntries({cacheName:ae,now:ne}):[],oe=se.maxEntries?yield se.findExtraEntries({cacheName:ae}):[],ce=[...new Set(ie.concat(oe))];return yield se.deleteFromCacheAndIDB({cacheName:ae,urls:ce}),ce})()}findOldEntries({cacheName:ae,now:ne}={}){var se=this;return D(function*(){u.isType({cacheName:ae},'string'),u.isType({now:ne},'number');const ie=ne-1e3*se.maxAgeSeconds,oe=[],ce=yield se.getDB({cacheName:ae}),le=ce.transaction(ae,'readonly'),de=le.objectStore(ae),ue=de.index($);return ue.iterateCursor(function(pe){pe&&(pe.value[$]ne.maxEntries&&(oe=ie.transaction(ae,'readonly'),ce=oe.objectStore(ae),le=ce.index($),le.iterateCursor(function(ue){ue&&(se.push(ue.value[H]),de-se.length>ne.maxEntries&&ue.continue())})),yield oe.complete,se})()}deleteFromCacheAndIDB({cacheName:ae,urls:ne}={}){var se=this;return D(function*(){if(u.isType({cacheName:ae},'string'),u.isArrayOfType({urls:ne},'string'),0{var ce=D(function*(le){yield ie.delete(le);const de=oe.transaction(ae,'readwrite'),ue=de.objectStore(ae);yield ue.delete(le),yield de.complete});return function(){return ce.apply(this,arguments)}})())}})()}}const X={'channel-name-required':`The channelName parameter is required when - constructing a new BroadcastCacheUpdate instance.`,'responses-are-same-parameters-required':`The first, second, and - headersToCheck parameters must be valid when calling responsesAreSame()`};var J=new ErrorFactory$1(X);const Z='CACHE_UPDATED',Q=['content-length','etag','last-modified'];class BroadcastCacheUpdate{constructor({channelName:ae,headersToCheck:ne,source:se}={}){if('string'!=typeof ae||0===ae.length)throw J.createError('channel-name-required');this.channelName=ae,this.headersToCheck=ne||Q,this.source=se||'sw-broadcast-cache-update'}get channel(){return this._channel||(this._channel=new BroadcastChannel(this.channelName)),this._channel}notifyIfUpdated({first:ae,second:ne,cacheName:se}){u.isType({cacheName:se},'string'),responsesAreSame({first:ae,second:ne,headersToCheck:this.headersToCheck})||broadcastUpdate({cacheName:se,url:ne.url,channel:this.channel,source:this.source})}}class BroadcastCacheUpdatePlugin extends BroadcastCacheUpdate{cacheDidUpdate({cacheName:ae,oldResponse:ne,newResponse:se}){u.isType({cacheName:ae},'string'),u.isInstance({newResponse:se},Response),ne&&this.notifyIfUpdated({cacheName:ae,first:ne,second:se})}}class Plugin$1{constructor({statuses:ae,headers:ne}={}){u.atLeastOne({statuses:ae,headers:ne}),ae!==void 0&&u.isArrayOfType({statuses:ae},'number'),ne!==void 0&&u.isType({headers:ne},'object'),this.statuses=ae,this.headers=ne}cacheWillUpdate({response:ae}={}){return this.isResponseCacheable({response:ae})}isResponseCacheable({response:ae}={}){u.isInstance({response:ae},Response);let ne=!0;return this.statuses&&(ne=this.statuses.includes(ae.status)),this.headers&&ne&&(ne=Object.keys(this.headers).some((se)=>{return ae.headers.get(se)===this.headers[se]})),ne}}class SWLib{constructor(){this._router=new Router$$1,this._revisionedCacheManager=new RevisionedCacheManager,this._unrevisionedCacheManager=new UnrevisionedCacheManager,this._registerInstallActivateEvents(),this._registerDefaultRoutes()}cacheRevisionedAssets(ae){if(!Array.isArray(ae))throw r.createError('bad-revisioned-cache-list');this._revisionedCacheManager.addToCacheList({revisionedFiles:ae})}warmRuntimeCache(ae){if(!Array.isArray(ae))throw r.createError('bad-revisioned-cache-list');this._unrevisionedCacheManager.addToCacheList({unrevisionedFiles:ae})}get router(){return this._router}get Route(){return Route}cacheFirst(ae){return this._getCachingMechanism(CacheFirst,ae)}cacheOnly(ae){return this._getCachingMechanism(CacheOnly,ae)}networkFirst(ae){return this._getCachingMechanism(NetworkFirst,ae)}networkOnly(ae){return this._getCachingMechanism(NetworkOnly,ae)}staleWhileRevalidate(ae){return this._getCachingMechanism(StaleWhileRevalidate,ae)}_getCachingMechanism(ae,ne={}){const se={cacheExpiration:Plugin,broadcastCacheUpdate:BroadcastCacheUpdatePlugin,cacheableResponse:Plugin$1},ie={plugins:[]};ne.cacheName&&(ie.cacheName=ne.cacheName);const oe=Object.keys(se);return oe.forEach((ce)=>{if(ne[ce]){const le=se[ce],de=ne[ce];ie.plugins.push(new le(de))}}),ne.plugins&&ne.plugins.forEach((ce)=>{ie.plugins.push(ce)}),new ae({requestWrapper:new RequestWrapper(ie)})}_registerInstallActivateEvents(){self.addEventListener('install',(ae)=>{ae.waitUntil(Promise.all([this._revisionedCacheManager.install(),this._unrevisionedCacheManager.install()]))}),self.addEventListener('activate',(ae)=>{ae.waitUntil(Promise.all([this._revisionedCacheManager.cleanup(),this._unrevisionedCacheManager.cleanup()]))})}_registerDefaultRoutes(){const ae=this.cacheFirst({cacheName:this._revisionedCacheManager.getCacheName()}),ne=new this.Route({match:({url:se,event:ie})=>{const oe=this._revisionedCacheManager.getCachedUrls();return-1!==oe.indexOf(se.href)},handler:ae});this.router.registerRoute(ne)}}if(!u.isSWEnv())throw r.createError('not-in-sw');const te=new SWLib;return te}); -//# sourceMappingURL=sw-lib.min.js.map diff --git a/js/vendor/sw-precaching.min.js b/js/vendor/sw-precaching.min.js deleted file mode 100644 index 655796e..0000000 --- a/js/vendor/sw-precaching.min.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright 2016 Google Inc. All Rights Reserved. - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -(function(r,t){'object'==typeof exports&&'undefined'!=typeof module?t(exports):'function'==typeof define&&define.amd?define(['exports'],t):t((r.goog=r.goog||{},r.goog.precaching=r.goog.precaching||{}))})(this,function(r){'use strict';function createCommonjsModule(q,I){return I={exports:{}},q(I,I.exports),I.exports}function throwError(q){const I=new Error(q),D=c.parse(I);throw 3<=D.length&&(I.message=`Invalid call to ${D[2].functionName}() — `+q.replace(/\s+/g,' '),I.name=D[1].functionName.replace(/^Object\./,'')),I}class ErrorFactory$1{constructor(q){this._errors=q}createError(q,I){if(!(q in this._errors))throw new Error(`Unable to generate error '${q}'.`);let D=this._errors[q].replace(/\s+/g,' '),w=null;I&&(D+=` [${I.message}]`,w=I.stack);const S=new Error;return S.name=q,S.message=D,S.stack=w,S}}const t={'not-in-sw':'sw-precaching must be loaded in your service worker file.','invalid-revisioned-entry':`File manifest entries must be either a `+`string with revision info in the url or an object with a 'url' and `+`'revision' parameters.`,'invalid-unrevisioned-entry':``,'bad-cache-bust':`The cache bust parameter must be a boolean.`,'duplicate-entry-diff-revisions':`An attempt was made to cache the same `+`url twice with each having different revisions. This is not supported.`,'request-not-cached':`A request failed the criteria to be cached. By `+`default, only responses with 'response.ok = true' are cached.`,'should-override':'Method should be overridden by the extending class.'};var a=new ErrorFactory$1(t),o='undefined'==typeof window?'undefined'==typeof global?'undefined'==typeof self?{}:self:global:window,s=createCommonjsModule(function(q){(function(D,w){'use strict';q.exports=w()})(o,function(){'use strict';function _isNumber(M){return!isNaN(parseFloat(M))&&isFinite(M)}function _capitalize(M){return M[0].toUpperCase()+M.substring(1)}function _getter(M){return function(){return this[M]}}function StackFrame(M){if(M instanceof Object)for(var F=D.concat(w.concat(S.concat(P))),U=0;U'].indexOf(F[0])?void 0:F[0];return new D({functionName:U,fileName:V,lineNumber:F[1],columnNumber:F[2],source:W})},this)},parseFFOrSafari:function ErrorStackParser$$parseFFOrSafari(T){var A=T.stack.split('\n').filter(function(W){return!W.match(P)},this);return A.map(function(W){if(-1 eval')&&(W=W.replace(/ line (\d+)(?: > eval line \d+)* > eval\:\d+\:\d+/g,':$1')),-1===W.indexOf('@')&&-1===W.indexOf(':'))return new D({functionName:W});var M=W.split('@'),F=this.extractLocation(M.pop()),U=M.join('@')||void 0;return new D({functionName:U,fileName:F[0],lineNumber:F[1],columnNumber:F[2],source:W})},this)},parseOpera:function ErrorStackParser$$parseOpera(T){return!T.stacktrace||-1T.stacktrace.split('\n').length?this.parseOpera9(T):T.stack?this.parseOpera11(T):this.parseOpera10(T)},parseOpera9:function ErrorStackParser$$parseOpera9(T){for(var V,A=/Line (\d+).*script (?:in )?(\S+)/i,W=T.message.split('\n'),M=[],F=2,U=W.length;F/,'$2').replace(/\([^\)]*\)/g,'')||void 0,B;U.match(/\(([^\)]*)\)/)&&(B=U.replace(/^[^\(]+\(([^\)]*)\)$/,'$1'));var K=B===void 0||'[arguments not available]'===B?void 0:B.split(',');return new D({functionName:V,args:K,fileName:F[0],lineNumber:F[1],columnNumber:F[2],source:W})},this)}}})}),l={atLeastOne:function atLeastOne(q){const I=Object.keys(q);I.some((D)=>q[D]!==void 0)||throwError('Please set at least one of the following parameters: '+I.map((D)=>`'${D}'`).join(', '))},hasMethod:function hasMethod(q,I){const D=Object.keys(q).pop(),w=typeof q[D][I];'function'!=w&&throwError(`The '${D}' parameter must be an object that exposes a - '${I}' method.`)},isInstance:function isInstance(q,I){const D=Object.keys(q).pop();q[D]instanceof I||throwError(`The '${D}' parameter must be an instance of - '${I.name}'`)},isOneOf:function isOneOf(q,I){const D=Object.keys(q).pop();I.includes(q[D])||throwError(`The '${D}' parameter must be set to one of the - following: ${I}`)},isType:function isType(q,I){const D=Object.keys(q).pop(),w=typeof q[D];w!==I&&throwError(`The '${D}' parameter has the wrong type. (Expected: - ${I}, actual: ${w})`)},isSWEnv:function isSWEnv(){return'ServiceWorkerGlobalScope'in self&&self instanceof ServiceWorkerGlobalScope},isValue:function isValue(q,I){const D=Object.keys(q).pop(),w=q[D];w!==I&&throwError(`The '${D}' parameter has the wrong value. (Expected: - ${I}, actual: ${w})`)},isArrayOfType:function isArrayOfType(q,I){const D=Object.keys(q).pop(),w=`The '${D}' parameter should be an array containing - one or more '${I}' elements.`;Array.isArray(q[D])||throwError(w);for(let S of q[D])typeof S!==I&&throwError(w)},isArrayOfClass:function isArrayOfClass(q,I){const D=Object.keys(q).pop(),w=`The '${D}' parameter should be an array containing - one or more '${I.name}' instances.`;Array.isArray(q[D])||throwError(w);for(let S of q[D])S instanceof I||throwError(w)}};self.goog=self.goog||{},self.goog.LOG_LEVEL=self.goog.LOG_LEVEL||{none:-1,verbose:0,debug:1,warn:2,error:3};var d=new class LogHelper{constructor(){this._allowedLogLevel='localhost'===location.hostname?self.goog.LOG_LEVEL.debug:self.goog.LOG_LEVEL.none}log(...q){this._printMessage(self.goog.LOG_LEVEL.verbose,console.log,q)}debug(...q){this._printMessage(self.goog.LOG_LEVEL.debug,console.debug,q)}warn(...q){this._printMessage(self.goog.LOG_LEVEL.warn,console.warn,q)}error(...q){this._printMessage(self.goog.LOG_LEVEL.error,console.error,q)}_printMessage(q,I,D){let w=this._allowedLogLevel;self&&self.goog&&self.goog.logLevel&&(w=self.goog.logLevel);w===self.goog.LOG_LEVEL.none||q{for(let P of g)'function'==typeof S[P]&&(this.pluginCallbacks[P]||(this.pluginCallbacks[P]=[]),this.pluginCallbacks[P].push(S[P].bind(S)))})),this.pluginCallbacks.cacheWillUpdate&&1!==this.pluginCallbacks.cacheWillUpdate.length)throw f.createError('multiple-cache-will-update-plugins');if(this.pluginCallbacks.cacheWillMatch&&1!==this.pluginCallbacks.cacheWillMatch.length)throw f.createError('multiple-cache-will-match-plugins')}getCache(){var q=this;return y(function*(){return q._cache||(q._cache=yield caches.open(q.cacheName)),q._cache})()}match({request:q}){var I=this;return y(function*(){l.atLeastOne({request:q});const D=yield I.getCache();let w=yield D.match(q,I.matchOptions);return I.pluginCallbacks.cacheWillMatch&&(w=I.pluginCallbacks.cacheWillMatch[0]({cachedResponse:w})),w})()}fetch({request:q}){var I=this;return y(function*(){l.atLeastOne({request:q});const D=I.pluginCallbacks.fetchDidFail?q.clone():null;if(I.pluginCallbacks.requestWillFetch)for(let w of I.pluginCallbacks.requestWillFetch){const S=w({request:q});l.isInstance({returnedPromise:S},Promise);const P=yield S;l.isInstance({returnedRequest:P},Request),q=P}try{return yield fetch(q,I.fetchOptions)}catch(w){if(I.pluginCallbacks.fetchDidFail)for(let S of I.pluginCallbacks.fetchDidFail)S({request:D.clone()});throw w}})()}fetchAndCache({request:q,waitOnCache:I,cacheKey:D}){var w=this;return y(function*(){l.atLeastOne({request:q});let S;const P=yield w.fetch({request:q});let T=P.ok;if(w.pluginCallbacks.cacheWillUpdate&&(T=w.pluginCallbacks.cacheWillUpdate[0]({request:q,response:P})),T){const A=P.clone();S=w.getCache().then((()=>{var W=y(function*(M){let F;'opaque'!==P.type&&w.pluginCallbacks.cacheDidUpdate&&(F=yield w.match({request:q}));yield M.put(D||q,A);for(let V of w.pluginCallbacks.cacheDidUpdate||[])V({cacheName:w.cacheName,oldResponse:F,newResponse:A,url:q.url})});return function(){return W.apply(this,arguments)}})())}else if(!T&&(d.debug(`[RequestWrapper] The response for ${q.url}, with - a status of ${P.status}, wasn't cached. By default, only - responses with a status of 200 are cached. You can configure the - cacheableResponse plugin to change this default.`.replace(/\s+/g,' ')),I))throw f.createError('invalid-reponse-for-caching');return I&&S&&(yield S),P})()}}class BaseCacheManager{constructor(q){this._entriesToCache=new Map,this._requestWrapper=new RequestWrapper({cacheName:q,fetchOptions:{credentials:'same-origin'}}),this._cacheName=this._requestWrapper.cacheName}_addEntries(q){this._parsedCacheUrls=null,q.forEach((I)=>{this._addEntryToInstallList(this._parseEntry(I))})}getCacheName(){return this._cacheName}getCachedUrls(){return this._parsedCacheUrls||(this._parsedCacheUrls=Array.from(this._entriesToCache.keys()).map((q)=>new URL(q,location).href)),this._parsedCacheUrls}_addEntryToInstallList(q){const I=q.entryID,D=this._entriesToCache.get(q.entryID);return D?void this._onDuplicateInstallEntryFound(q,D):void this._entriesToCache.set(I,q)}install(){var q=this;return y(function*(){if(0!==q._entriesToCache.size){const I=[];return q._entriesToCache.forEach(function(D){I.push(q._cacheEntry(D))}),Promise.all(I)}})()}_cacheEntry(q){var I=this;return y(function*(){const D=yield I._isAlreadyCached(q);if(!D)try{return yield I._requestWrapper.fetchAndCache({request:q.getNetworkRequest(),waitOnCache:!0,cacheKey:q.request}),I._onEntryCached(q)}catch(w){throw a.createError('request-not-cached',{message:`Failed to get a cacheable response for `+`'${q.request.url}': ${w.message}`})}})()}cleanup(){var q=this;return y(function*(){if(yield caches.has(q._cacheName)){const I=[];q._entriesToCache.forEach(function(P){I.push(P.request.url)});const D=yield q._getCache(),w=yield D.keys(),S=w.filter(function(P){return!I.includes(P.url)});return Promise.all(S.map(function(P){return D.delete(P)}))}})()}_getCache(){var q=this;return y(function*(){return q._cache||(q._cache=yield caches.open(q._cacheName)),q._cache})()}_parseEntry(){throw a.createError('should-override')}_onDuplicateEntryFound(){throw a.createError('should-override')}_isAlreadyCached(){throw a.createError('should-override')}_onEntryCached(){throw a.createError('should-override')}}var _=createCommonjsModule(function(q){'use strict';(function(){function toArray(D){return Array.prototype.slice.call(D)}function promisifyRequest(D){return new Promise(function(w,S){D.onsuccess=function(){w(D.result)},D.onerror=function(){S(D.error)}})}function promisifyRequestCall(D,w,S){var P,T=new Promise(function(A,W){P=D[w].apply(D,S),promisifyRequest(P).then(A,W)});return T.request=P,T}function promisifyCursorRequestCall(D,w,S){var P=promisifyRequestCall(D,w,S);return P.then(function(T){return T?new Cursor(T,P.request):void 0})}function proxyProperties(D,w,S){S.forEach(function(P){Object.defineProperty(D.prototype,P,{get:function(){return this[w][P]},set:function(T){this[w][P]=T}})})}function proxyRequestMethods(D,w,S,P){P.forEach(function(T){T in S.prototype&&(D.prototype[T]=function(){return promisifyRequestCall(this[w],T,arguments)})})}function proxyMethods(D,w,S,P){P.forEach(function(T){T in S.prototype&&(D.prototype[T]=function(){return this[w][T].apply(this[w],arguments)})})}function proxyCursorRequestMethods(D,w,S,P){P.forEach(function(T){T in S.prototype&&(D.prototype[T]=function(){return promisifyCursorRequestCall(this[w],T,arguments)})})}function Index(D){this._index=D}function Cursor(D,w){this._cursor=D,this._request=w}function ObjectStore(D){this._store=D}function Transaction(D){this._tx=D,this.complete=new Promise(function(w,S){D.oncomplete=function(){w()},D.onerror=function(){S(D.error)},D.onabort=function(){S(D.error)}})}function UpgradeDB(D,w,S){this._db=D,this.oldVersion=w,this.transaction=new Transaction(S)}function DB(D){this._db=D}proxyProperties(Index,'_index',['name','keyPath','multiEntry','unique']),proxyRequestMethods(Index,'_index',IDBIndex,['get','getKey','getAll','getAllKeys','count']),proxyCursorRequestMethods(Index,'_index',IDBIndex,['openCursor','openKeyCursor']),proxyProperties(Cursor,'_cursor',['direction','key','primaryKey','value']),proxyRequestMethods(Cursor,'_cursor',IDBCursor,['update','delete']),['advance','continue','continuePrimaryKey'].forEach(function(D){D in IDBCursor.prototype&&(Cursor.prototype[D]=function(){var w=this,S=arguments;return Promise.resolve().then(function(){return w._cursor[D].apply(w._cursor,S),promisifyRequest(w._request).then(function(P){return P?new Cursor(P,w._request):void 0})})})}),ObjectStore.prototype.createIndex=function(){return new Index(this._store.createIndex.apply(this._store,arguments))},ObjectStore.prototype.index=function(){return new Index(this._store.index.apply(this._store,arguments))},proxyProperties(ObjectStore,'_store',['name','keyPath','indexNames','autoIncrement']),proxyRequestMethods(ObjectStore,'_store',IDBObjectStore,['put','add','delete','clear','get','getAll','getKey','getAllKeys','count']),proxyCursorRequestMethods(ObjectStore,'_store',IDBObjectStore,['openCursor','openKeyCursor']),proxyMethods(ObjectStore,'_store',IDBObjectStore,['deleteIndex']),Transaction.prototype.objectStore=function(){return new ObjectStore(this._tx.objectStore.apply(this._tx,arguments))},proxyProperties(Transaction,'_tx',['objectStoreNames','mode']),proxyMethods(Transaction,'_tx',IDBTransaction,['abort']),UpgradeDB.prototype.createObjectStore=function(){return new ObjectStore(this._db.createObjectStore.apply(this._db,arguments))},proxyProperties(UpgradeDB,'_db',['name','version','objectStoreNames']),proxyMethods(UpgradeDB,'_db',IDBDatabase,['deleteObjectStore','close']),DB.prototype.transaction=function(){return new Transaction(this._db.transaction.apply(this._db,arguments))},proxyProperties(DB,'_db',['name','version','objectStoreNames']),proxyMethods(DB,'_db',IDBDatabase,['close']),['openCursor','openKeyCursor'].forEach(function(D){[ObjectStore,Index].forEach(function(w){w.prototype[D.replace('open','iterate')]=function(){var S=toArray(arguments),P=S[S.length-1],T=this._store||this._index,A=T[D].apply(T,S.slice(0,-1));A.onsuccess=function(){P(A.result)}}})}),[Index,ObjectStore].forEach(function(D){D.prototype.getAll||(D.prototype.getAll=function(w,S){var P=this,T=[];return new Promise(function(A){P.iterateCursor(w,function(W){return W?(T.push(W.value),void 0!==S&&T.length==S?void A(T):void W.continue()):void A(T)})})})});q.exports={open:function(D,w,S){var P=promisifyRequestCall(indexedDB,'open',[D,w]),T=P.request;return T.onupgradeneeded=function(A){S&&S(new UpgradeDB(T.result,A.oldVersion,T.transaction))},P.then(function(A){return new DB(A)})},delete:function(D){return promisifyRequestCall(indexedDB,'deleteDatabase',[D])}}})()});class IDBHelper{constructor(q,I,D){if(q==void 0||I==void 0||D==void 0)throw Error('name, version, storeName must be passed to the constructor.');this._name=q,this._version=I,this._storeName=D}_getDb(){return this._dbPromise?this._dbPromise:(this._dbPromise=_.open(this._name,this._version,(q)=>{q.createObjectStore(this._storeName)}).then((q)=>{return q}),this._dbPromise)}close(){return this._dbPromise?this._dbPromise.then((q)=>{q.close(),this._dbPromise=null}):void 0}put(q,I){return this._getDb().then((D)=>{const w=D.transaction(this._storeName,'readwrite'),S=w.objectStore(this._storeName);return S.put(I,q),w.complete})}delete(q){return this._getDb().then((I)=>{const D=I.transaction(this._storeName,'readwrite'),w=D.objectStore(this._storeName);return w.delete(q),D.complete})}get(q){return this._getDb().then((I)=>{return I.transaction(this._storeName).objectStore(this._storeName).get(q)})}getAllValues(){return this._getDb().then((q)=>{return q.transaction(this._storeName).objectStore(this._storeName).getAll()})}getAllKeys(){return this._getDb().then((q)=>{return q.transaction(this._storeName).objectStore(this._storeName).getAllKeys()})}}let L=`sw-precaching-revisioned-${'v1'}`;self&&self.registration&&(L+=`-${self.registration.scope}`);const x=L;class RevisionDetailsModel{constructor(){this._idbHelper=new IDBHelper('sw-precaching','1','asset-revisions')}get(q){return this._idbHelper.get(q)}put(q,I){return this._idbHelper.put(q,I)}_close(){this._idbHelper.close()}}class BaseCacheEntry{constructor({entryID:q,revision:I,request:D,cacheBust:w}){this.entryID=q,this.revision=I,this.request=D,this.cacheBust=w}getNetworkRequest(){if(!0!==this.cacheBust)return this.request;let q=this.request.url;const I={};if(!0===this.cacheBust)if('cache'in Request.prototype)I.cache='reload';else{const D=new URL(q,location);D.search+=(D.search?'&':'')+encodeURIComponent('_sw-precaching')+'='+encodeURIComponent(this.revision),q=D.toString()}return new Request(q,I)}}class StringCacheEntry extends BaseCacheEntry{constructor(q){if(l.isType({url:q},'string'),0===q.length)throw a.createError('invalid-revisioned-entry',new Error('Bad url Parameter. It should be a string:'+JSON.stringify(q)));super({entryID:q,revision:q,request:new Request(q),cacheBust:!1})}}class DefaultsCacheEntry extends BaseCacheEntry{constructor({entryID:q,revision:I,url:D,cacheBust:w}){if('undefined'==typeof w&&(w=!0),'undefined'==typeof q&&(q=new URL(D,location).toString()),l.isType({revision:I},'string'),0===I.length)throw a.createError('invalid-revisioned-entry',new Error('Bad revision Parameter. It should be a string with at least one character: '+JSON.stringify(I)));if(l.isType({url:D},'string'),0===D.length)throw a.createError('invalid-revisioned-entry',new Error('Bad url Parameter. It should be a string:'+JSON.stringify(D)));if(l.isType({entryID:q},'string'),0===q.length)throw a.createError('invalid-revisioned-entry',new Error('Bad entryID Parameter. It should be a string with at least one character: '+JSON.stringify(q)));l.isType({cacheBust:w},'boolean'),super({entryID:q,revision:I,request:new Request(D),cacheBust:w})}}class RequestCacheEntry extends BaseCacheEntry{constructor(q){if(!(q instanceof Request))throw a.createError('invalid-unrevisioned-entry',new Error('Invalid file entry: '+JSON.stringify(q)));super({entryID:q.url,request:q,cacheBust:!1})}}if(!l.isSWEnv())throw a.createError('not-in-sw');r.RevisionedCacheManager=class RevisionedCacheManager extends BaseCacheManager{constructor({cacheName:q}={}){q=q||x,super(q),this._revisionDetailsModel=new RevisionDetailsModel}addToCacheList({revisionedFiles:q}={}){l.isInstance({revisionedFiles:q},Array),super._addEntries(q)}_parseEntry(q){if('undefined'==typeof q||null===q)throw a.createError('invalid-revisioned-entry',new Error('Invalid file entry: '+JSON.stringify(q)));let I;switch(typeof q){case'string':I=new StringCacheEntry(q);break;case'object':I=new DefaultsCacheEntry(q);break;default:throw a.createError('invalid-revisioned-entry',new Error('Invalid file entry: '+JSON.stringify(I)));}return I}_onDuplicateInstallEntryFound(q,I){if(I.revision!==q.revision)throw a.createError('duplicate-entry-diff-revisions',new Error(`${JSON.stringify(I)} <=> `+`${JSON.stringify(q)}`))}_isAlreadyCached(q){var I=this;return y(function*(){const D=yield I._revisionDetailsModel.get(q.entryID);if(D!==q.revision)return!1;const w=yield I._getCache(),S=yield w.match(q.request);return!!S})()}_onEntryCached(q){var I=this;return y(function*(){yield I._revisionDetailsModel.put(q.entryID,q.revision)})()}_close(){this._revisionDetailsModel._close()}cleanup(){return super.cleanup().then(()=>{return this._close()})}},r.UnrevisionedCacheManager=class UnrevisionedCacheManager extends BaseCacheManager{constructor({cacheName:q}={}){super(q)}addToCacheList({unrevisionedFiles:q}={}){l.isInstance({unrevisionedFiles:q},Array),super._addEntries(q)}_parseEntry(q){if('undefined'==typeof q||null===q)throw a.createError('invalid-unrevisioned-entry',new Error('Invalid file entry: '+JSON.stringify(q)));if('string'==typeof q)return new StringCacheEntry(q);if(q instanceof Request)return new RequestCacheEntry(q);throw a.createError('invalid-unrevisioned-entry',new Error('Invalid file entry: '+JSON.stringify(q)))}_onDuplicateInstallEntryFound(){}_isAlreadyCached(){return y(function*(){return!1})()}_onEntryCached(){}},Object.defineProperty(r,'__esModule',{value:!0})}); -//# sourceMappingURL=sw-precaching.min.js.map diff --git a/js/vendor/sw-routing.min.js b/js/vendor/sw-routing.min.js deleted file mode 100644 index c0ac3b5..0000000 --- a/js/vendor/sw-routing.min.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright 2016 Google Inc. All Rights Reserved. - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?b(exports):'function'==typeof define&&define.amd?define(['exports'],b):b((a.goog=a.goog||{},a.goog.routing=a.goog.routing||{}))})(this,function(a){'use strict';function createCommonjsModule(B,C){return C={exports:{}},B(C,C.exports),C.exports}function throwError(B){const C=new Error(B),D=h.parse(C);throw 3<=D.length&&(C.message=`Invalid call to ${D[2].functionName}() — `+B.replace(/\s+/g,' '),C.name=D[1].functionName.replace(/^Object\./,'')),C}function parse(B,C){for(var I,D=[],E=0,F=0,G='',H=C&&C.delimiter||'/';null!=(I=z.exec(B));){var J=I[0],K=I[1],L=I.index;if(G+=B.slice(F,L),F=L+J.length,K){G+=K[1];continue}var M=B[F],N=I[2],O=I[3],P=I[4],Q=I[5],R=I[6],S=I[7];G&&(D.push(G),G='');var W=I[2]||H,X=P||Q;D.push({name:O||E++,prefix:N||'',delimiter:W,optional:'?'===R||'*'===R,repeat:'+'===R||'*'===R,partial:null!=N&&null!=M&&M!==N,asterisk:!!S,pattern:X?escapeGroup(X):S?'.*':'[^'+escapeString(W)+']+?'})}return F'].indexOf(L[0])?void 0:L[0];return new D({functionName:M,fileName:N,lineNumber:L[1],columnNumber:L[2],source:J})},this)},parseFFOrSafari:function ErrorStackParser$$parseFFOrSafari(H){var I=H.stack.split('\n').filter(function(J){return!J.match(G)},this);return I.map(function(J){if(-1 eval')&&(J=J.replace(/ line (\d+)(?: > eval line \d+)* > eval\:\d+\:\d+/g,':$1')),-1===J.indexOf('@')&&-1===J.indexOf(':'))return new D({functionName:J});var K=J.split('@'),L=this.extractLocation(K.pop()),M=K.join('@')||void 0;return new D({functionName:M,fileName:L[0],lineNumber:L[1],columnNumber:L[2],source:J})},this)},parseOpera:function ErrorStackParser$$parseOpera(H){return!H.stacktrace||-1H.stacktrace.split('\n').length?this.parseOpera9(H):H.stack?this.parseOpera11(H):this.parseOpera10(H)},parseOpera9:function ErrorStackParser$$parseOpera9(H){for(var N,I=/Line (\d+).*script (?:in )?(\S+)/i,J=H.message.split('\n'),K=[],L=2,M=J.length;L/,'$2').replace(/\([^\)]*\)/g,'')||void 0,O;M.match(/\(([^\)]*)\)/)&&(O=M.replace(/^[^\(]+\(([^\)]*)\)$/,'$1'));var P=O===void 0||'[arguments not available]'===O?void 0:O.split(',');return new D({functionName:N,args:P,fileName:L[0],lineNumber:L[1],columnNumber:L[2],source:J})},this)}}})}),l={atLeastOne:function atLeastOne(B){const C=Object.keys(B);C.some((D)=>B[D]!==void 0)||throwError('Please set at least one of the following parameters: '+C.map((D)=>`'${D}'`).join(', '))},hasMethod:function hasMethod(B,C){const D=Object.keys(B).pop(),E=typeof B[D][C];'function'!=E&&throwError(`The '${D}' parameter must be an object that exposes a - '${C}' method.`)},isInstance:function isInstance(B,C){const D=Object.keys(B).pop();B[D]instanceof C||throwError(`The '${D}' parameter must be an instance of - '${C.name}'`)},isOneOf:function isOneOf(B,C){const D=Object.keys(B).pop();C.includes(B[D])||throwError(`The '${D}' parameter must be set to one of the - following: ${C}`)},isType:function isType(B,C){const D=Object.keys(B).pop(),E=typeof B[D];E!==C&&throwError(`The '${D}' parameter has the wrong type. (Expected: - ${C}, actual: ${E})`)},isSWEnv:function isSWEnv(){return'ServiceWorkerGlobalScope'in self&&self instanceof ServiceWorkerGlobalScope},isValue:function isValue(B,C){const D=Object.keys(B).pop(),E=B[D];E!==C&&throwError(`The '${D}' parameter has the wrong value. (Expected: - ${C}, actual: ${E})`)},isArrayOfType:function isArrayOfType(B,C){const D=Object.keys(B).pop(),E=`The '${D}' parameter should be an array containing - one or more '${C}' elements.`;Array.isArray(B[D])||throwError(E);for(let F of B[D])typeof F!==C&&throwError(E)},isArrayOfClass:function isArrayOfClass(B,C){const D=Object.keys(B).pop(),E=`The '${D}' parameter should be an array containing - one or more '${C.name}' instances.`;Array.isArray(B[D])||throwError(E);for(let F of B[D])F instanceof C||throwError(E)}};const q=['DELETE','GET','HEAD','POST','PUT'];class Route{constructor({match:B,handler:C,method:D}={}){l.isType({match:B},'function'),'object'==typeof C?l.hasMethod({handler:C},'handle'):l.isType({handler:C},'function'),this.match=B,this.handler='function'==typeof C?{handle:C}:C,D?(l.isOneOf({method:D},q),this.method=D):this.method='GET'}}var r=Array.isArray||function(B){return'[object Array]'==Object.prototype.toString.call(B)},s=r,t=pathToRegexp,z=new RegExp(['(\\\\.)','([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'].join('|'),'g');t.parse=parse,t.compile=function compile(B,C){return tokensToFunction(parse(B,C))},t.tokensToFunction=tokensToFunction,t.tokensToRegExp=tokensToRegExp;self.goog=self.goog||{},self.goog.LOG_LEVEL=self.goog.LOG_LEVEL||{none:-1,verbose:0,debug:1,warn:2,error:3};var A=new class LogHelper{constructor(){this._allowedLogLevel='localhost'===location.hostname?self.goog.LOG_LEVEL.debug:self.goog.LOG_LEVEL.none}log(...B){this._printMessage(self.goog.LOG_LEVEL.verbose,console.log,B)}debug(...B){this._printMessage(self.goog.LOG_LEVEL.debug,console.debug,B)}warn(...B){this._printMessage(self.goog.LOG_LEVEL.warn,console.warn,B)}error(...B){this._printMessage(self.goog.LOG_LEVEL.error,console.error,B)}_printMessage(B,C,D){let E=this._allowedLogLevel;self&&self.goog&&self.goog.logLevel&&(E=self.goog.logLevel);E===self.goog.LOG_LEVEL.none||B{if(H.origin!==location.origin)return null;const I=H.pathname.match(F);if(!I)return null;const J={};return E.forEach((K,L)=>{J[K.name]=I[L+1]}),J},handler:C,method:D})}},a.NavigationRoute=class NavigationRoute extends Route{constructor({whitelist:B,blacklist:C,handler:D}={}){l.isArrayOfClass({whitelist:B},RegExp),C?l.isArrayOfClass({blacklist:C},RegExp):C=[];super({match:({event:F,url:G})=>{return'navigate'===F.request.mode&&B.some((H)=>H.test(G.pathname))&&!C.some((H)=>H.test(G.pathname))},handler:D,method:'GET'})}},a.RegExpRoute=class RegExpRoute extends Route{constructor({regExp:B,handler:C,method:D}){l.isInstance({regExp:B},RegExp);super({match:({url:F})=>{const G=F.href.match(B);return G?G.slice(1):null},handler:C,method:D})}},a.Route=Route,a.Router=class Router{setDefaultHandler({handler:B}={}){l.hasMethod({handler:B},'handle'),this.defaultHandler=B}setCatchHandler({handler:B}={}){l.hasMethod({handler:B},'handle'),this.catchHandler=B}registerRoutes({routes:B}={}){l.isArrayOfClass({routes:B},Route),self.addEventListener('fetch',(C)=>{const D=new URL(C.request.url);if(!D.protocol.startsWith('http'))return void A.debug(`[router.js] URL does not start with HTTP`,C.request.url);let E;for(let F of B||[])if(F.method===C.request.method){const G=F.match({url:D,event:C});if(G){A.debug(`[router.js] Found matching result: `,C.request.url);let H=G;Array.isArray(H)&&0===H.length?H=void 0:H.constructor===Object&&0===Object.keys(H).length&&(H=void 0),E=F.handler.handle({url:D,event:C,params:H});break}}!E&&this.defaultHandler&&(E=this.defaultHandler.handle({url:D,event:C})),E&&this.catchHandler&&(E=E.catch((F)=>{return this.catchHandler.handle({url:D,event:C,error:F})})),E&&C.respondWith(E.then((F)=>{return A.debug(`[router.js] Returning response for `+`'${C.request.url}': `,F),F}))})}registerRoute({route:B}={}){l.isInstance({route:B},Route),this.registerRoutes({routes:[B]})}},Object.defineProperty(a,'__esModule',{value:!0})}); -//# sourceMappingURL=sw-routing.min.js.map diff --git a/js/vendor/sw-runtime-caching.min.js b/js/vendor/sw-runtime-caching.min.js deleted file mode 100644 index fa537e4..0000000 --- a/js/vendor/sw-runtime-caching.min.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright 2016 Google Inc. All Rights Reserved. - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?b(exports):'function'==typeof define&&define.amd?define(['exports'],b):b((a.goog=a.goog||{},a.goog.runtimeCaching=a.goog.runtimeCaching||{}))})(this,function(a){'use strict';function createCommonjsModule(s,t){return t={exports:{}},s(t,t.exports),t.exports}function throwError(s){const t=new Error(s),u=d.parse(t);throw 3<=u.length&&(t.message=`Invalid call to ${u[2].functionName}() — `+s.replace(/\s+/g,' '),t.name=u[1].functionName.replace(/^Object\./,'')),t}var b='undefined'==typeof window?'undefined'==typeof global?'undefined'==typeof self?{}:self:global:window,c=createCommonjsModule(function(s){(function(u,w){'use strict';s.exports=w()})(b,function(){'use strict';function _isNumber(C){return!isNaN(parseFloat(C))&&isFinite(C)}function _capitalize(C){return C[0].toUpperCase()+C.substring(1)}function _getter(C){return function(){return this[C]}}function StackFrame(C){if(C instanceof Object)for(var D=u.concat(w.concat(x.concat(y))),E=0;E'].indexOf(D[0])?void 0:D[0];return new u({functionName:E,fileName:F,lineNumber:D[1],columnNumber:D[2],source:B})},this)},parseFFOrSafari:function ErrorStackParser$$parseFFOrSafari(z){var A=z.stack.split('\n').filter(function(B){return!B.match(y)},this);return A.map(function(B){if(-1 eval')&&(B=B.replace(/ line (\d+)(?: > eval line \d+)* > eval\:\d+\:\d+/g,':$1')),-1===B.indexOf('@')&&-1===B.indexOf(':'))return new u({functionName:B});var C=B.split('@'),D=this.extractLocation(C.pop()),E=C.join('@')||void 0;return new u({functionName:E,fileName:D[0],lineNumber:D[1],columnNumber:D[2],source:B})},this)},parseOpera:function ErrorStackParser$$parseOpera(z){return!z.stacktrace||-1z.stacktrace.split('\n').length?this.parseOpera9(z):z.stack?this.parseOpera11(z):this.parseOpera10(z)},parseOpera9:function ErrorStackParser$$parseOpera9(z){for(var F,A=/Line (\d+).*script (?:in )?(\S+)/i,B=z.message.split('\n'),C=[],D=2,E=B.length;D/,'$2').replace(/\([^\)]*\)/g,'')||void 0,G;E.match(/\(([^\)]*)\)/)&&(G=E.replace(/^[^\(]+\(([^\)]*)\)$/,'$1'));var H=G===void 0||'[arguments not available]'===G?void 0:G.split(',');return new u({functionName:F,args:H,fileName:D[0],lineNumber:D[1],columnNumber:D[2],source:B})},this)}}})}),f={atLeastOne:function atLeastOne(s){const t=Object.keys(s);t.some((u)=>s[u]!==void 0)||throwError('Please set at least one of the following parameters: '+t.map((u)=>`'${u}'`).join(', '))},hasMethod:function hasMethod(s,t){const u=Object.keys(s).pop(),w=typeof s[u][t];'function'!=w&&throwError(`The '${u}' parameter must be an object that exposes a - '${t}' method.`)},isInstance:function isInstance(s,t){const u=Object.keys(s).pop();s[u]instanceof t||throwError(`The '${u}' parameter must be an instance of - '${t.name}'`)},isOneOf:function isOneOf(s,t){const u=Object.keys(s).pop();t.includes(s[u])||throwError(`The '${u}' parameter must be set to one of the - following: ${t}`)},isType:function isType(s,t){const u=Object.keys(s).pop(),w=typeof s[u];w!==t&&throwError(`The '${u}' parameter has the wrong type. (Expected: - ${t}, actual: ${w})`)},isSWEnv:function isSWEnv(){return'ServiceWorkerGlobalScope'in self&&self instanceof ServiceWorkerGlobalScope},isValue:function isValue(s,t){const u=Object.keys(s).pop(),w=s[u];w!==t&&throwError(`The '${u}' parameter has the wrong value. (Expected: - ${t}, actual: ${w})`)},isArrayOfType:function isArrayOfType(s,t){const u=Object.keys(s).pop(),w=`The '${u}' parameter should be an array containing - one or more '${t}' elements.`;Array.isArray(s[u])||throwError(w);for(let x of s[u])typeof x!==t&&throwError(w)},isArrayOfClass:function isArrayOfClass(s,t){const u=Object.keys(s).pop(),w=`The '${u}' parameter should be an array containing - one or more '${t.name}' instances.`;Array.isArray(s[u])||throwError(w);for(let x of s[u])x instanceof t||throwError(w)}};self.goog=self.goog||{},self.goog.LOG_LEVEL=self.goog.LOG_LEVEL||{none:-1,verbose:0,debug:1,warn:2,error:3};var g=new class LogHelper{constructor(){this._allowedLogLevel='localhost'===location.hostname?self.goog.LOG_LEVEL.debug:self.goog.LOG_LEVEL.none}log(...s){this._printMessage(self.goog.LOG_LEVEL.verbose,console.log,s)}debug(...s){this._printMessage(self.goog.LOG_LEVEL.debug,console.debug,s)}warn(...s){this._printMessage(self.goog.LOG_LEVEL.warn,console.warn,s)}error(...s){this._printMessage(self.goog.LOG_LEVEL.error,console.error,s)}_printMessage(s,t,u){let w=this._allowedLogLevel;self&&self.goog&&self.goog.logLevel&&(w=self.goog.logLevel);w===self.goog.LOG_LEVEL.none||s{for(let y of m)'function'==typeof x[y]&&(this.pluginCallbacks[y]||(this.pluginCallbacks[y]=[]),this.pluginCallbacks[y].push(x[y].bind(x)))})),this.pluginCallbacks.cacheWillUpdate&&1!==this.pluginCallbacks.cacheWillUpdate.length)throw q.createError('multiple-cache-will-update-plugins');if(this.pluginCallbacks.cacheWillMatch&&1!==this.pluginCallbacks.cacheWillMatch.length)throw q.createError('multiple-cache-will-match-plugins')}getCache(){var s=this;return r(function*(){return s._cache||(s._cache=yield caches.open(s.cacheName)),s._cache})()}match({request:s}){var t=this;return r(function*(){f.atLeastOne({request:s});const u=yield t.getCache();let w=yield u.match(s,t.matchOptions);return t.pluginCallbacks.cacheWillMatch&&(w=t.pluginCallbacks.cacheWillMatch[0]({cachedResponse:w})),w})()}fetch({request:s}){var t=this;return r(function*(){f.atLeastOne({request:s});const u=t.pluginCallbacks.fetchDidFail?s.clone():null;if(t.pluginCallbacks.requestWillFetch)for(let w of t.pluginCallbacks.requestWillFetch){const x=w({request:s});f.isInstance({returnedPromise:x},Promise);const y=yield x;f.isInstance({returnedRequest:y},Request),s=y}try{return yield fetch(s,t.fetchOptions)}catch(w){if(t.pluginCallbacks.fetchDidFail)for(let x of t.pluginCallbacks.fetchDidFail)x({request:u.clone()});throw w}})()}fetchAndCache({request:s,waitOnCache:t,cacheKey:u}){var w=this;return r(function*(){f.atLeastOne({request:s});let x;const y=yield w.fetch({request:s});let z=y.ok;if(w.pluginCallbacks.cacheWillUpdate&&(z=w.pluginCallbacks.cacheWillUpdate[0]({request:s,response:y})),z){const A=y.clone();x=w.getCache().then((()=>{var B=r(function*(C){let D;'opaque'!==y.type&&w.pluginCallbacks.cacheDidUpdate&&(D=yield w.match({request:s}));yield C.put(u||s,A);for(let F of w.pluginCallbacks.cacheDidUpdate||[])F({cacheName:w.cacheName,oldResponse:D,newResponse:A,url:s.url})});return function(){return B.apply(this,arguments)}})())}else if(!z&&(g.debug(`[RequestWrapper] The response for ${s.url}, with - a status of ${y.status}, wasn't cached. By default, only - responses with a status of 200 are cached. You can configure the - cacheableResponse plugin to change this default.`.replace(/\s+/g,' ')),t))throw q.createError('invalid-reponse-for-caching');return t&&x&&(yield x),y})()}}class Handler{constructor({requestWrapper:s}={}){this.requestWrapper=s?s:new RequestWrapper}handle({event:s,params:t}={}){throw Error('This abstract method must be implemented in a subclass.')}}a.CacheFirst=class CacheFirst extends Handler{handle({event:s}={}){var t=this;return r(function*(){f.isInstance({event:s},FetchEvent);const u=yield t.requestWrapper.match({request:s.request});return u||(yield t.requestWrapper.fetchAndCache({request:s.request}))})()}},a.CacheOnly=class CacheOnly extends Handler{handle({event:s}={}){var t=this;return r(function*(){return f.isInstance({event:s},FetchEvent),yield t.requestWrapper.match({request:s.request})})()}},a.Handler=Handler,a.NetworkFirst=class NetworkFirst extends Handler{constructor(s={}){super(s);const{networkTimeoutSeconds:t}=s;t&&(f.isType({networkTimeoutSeconds:t},'number'),this.networkTimeoutSeconds=t)}handle({event:s}={}){var t=this;return r(function*(){f.isInstance({event:s},FetchEvent);const u=[];let w;return t.networkTimeoutSeconds&&u.push(new Promise(function(x){w=setTimeout(function(){x(t.requestWrapper.match({request:s.request}))},1e3*t.networkTimeoutSeconds)})),u.push(t.requestWrapper.fetchAndCache({request:s.request}).then(function(x){return w&&clearTimeout(w),x?x:Promise.reject('No response received; falling back to cache.')}).catch(function(){return t.requestWrapper.match({request:s.request})})),Promise.race(u)})()}},a.NetworkOnly=class NetworkOnly extends Handler{handle({event:s}={}){var t=this;return r(function*(){return f.isInstance({event:s},FetchEvent),yield t.requestWrapper.fetch({request:s.request})})()}},a.RequestWrapper=RequestWrapper,a.StaleWhileRevalidate=class StaleWhileRevalidate extends Handler{handle({event:s}={}){var t=this;return r(function*(){f.isInstance({event:s},FetchEvent);const u=t.requestWrapper.fetchAndCache({request:s.request}).catch(function(){return Response.error()}),w=yield t.requestWrapper.match({request:s.request});return w||(yield u)})()}},a.defaultCacheName=l,Object.defineProperty(a,'__esModule',{value:!0})}); -//# sourceMappingURL=sw-runtime-caching.min.js.map diff --git a/package-lock.json b/package-lock.json index 739ef59..b09ba72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -168,6 +168,15 @@ } } }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "requires": { + "string-width": "^2.0.0" + } + }, "ansi-escapes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", @@ -255,12 +264,6 @@ "arr-flatten": "^1.0.1" } }, - "arr-exclude": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/arr-exclude/-/arr-exclude-1.0.0.tgz", - "integrity": "sha1-38fC5VKicHI8zaBM8xKMjL/lxjE=", - "dev": true - }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", @@ -359,6 +362,16 @@ "eslint-visitor-keys": "^1.0.0" } }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, "babylon": { "version": "7.0.0-beta.44", "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", @@ -506,6 +519,21 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", "dev": true }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -671,61 +699,6 @@ "supports-color": "^5.3.0" } }, - "chalk-cli": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk-cli/-/chalk-cli-3.0.0.tgz", - "integrity": "sha1-M90yWarzxXS7aKyrFsJUYpLg0/s=", - "dev": true, - "requires": { - "arr-exclude": "^1.0.0", - "chalk": "^1.0.0", - "dot-prop": "^3.0.0", - "get-stdin": "^5.0.1", - "meow": "^3.5.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, "chardet": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.5.0.tgz", @@ -766,6 +739,33 @@ "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", "dev": true }, + "ci-info": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.3.tgz", + "integrity": "sha512-SK/846h/Rcy8q9Z9CAwGBLfCJ6EkjJWdpelWDufQpqVDYq2Wnnv8zlSO6AMQap02jvhVruKKpEtQOufo3pFhLg==", + "dev": true + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-spinners": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz", + "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==", + "dev": true + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", @@ -872,6 +872,12 @@ "graceful-readlink": ">= 1.0.0" } }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true + }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", @@ -906,6 +912,31 @@ "proto-list": "~1.2.1" } }, + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "dev": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + } + } + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -942,6 +973,12 @@ "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", "dev": true }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -968,6 +1005,12 @@ "which": "^1.2.9" } }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, "css-select": { "version": "1.3.0-rc0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.3.0-rc0.tgz", @@ -1335,15 +1378,6 @@ "domelementtype": "1" } }, - "dot-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", - "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, "download": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/download/-/download-4.4.3.tgz", @@ -1884,6 +1918,17 @@ "integrity": "sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ==", "dev": true }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "fs-minipass": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", @@ -1973,12 +2018,6 @@ "rc": "^1.1.2" } }, - "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", - "dev": true - }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -2091,6 +2130,15 @@ } } }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, "globals": { "version": "11.7.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", @@ -2385,6 +2433,12 @@ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", + "dev": true + }, "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", @@ -2592,6 +2646,18 @@ } } }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", @@ -2758,6 +2824,15 @@ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true }, + "is-ci": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz", + "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", + "dev": true, + "requires": { + "ci-info": "^1.0.0" + } + }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", @@ -2821,6 +2896,16 @@ "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=", "dev": true }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, "is-jpg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-1.0.1.tgz", @@ -2833,6 +2918,12 @@ "integrity": "sha1-fUxXKDd+84bD4ZSpkRv1fG3DNec=", "dev": true }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true + }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", @@ -2854,6 +2945,15 @@ "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", "dev": true }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -2965,6 +3065,23 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "isemail": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.1.3.tgz", + "integrity": "sha512-5xbsG5wYADIcB+mfLsd+nst1V/D+I7EU7LEZPo2GOIMu4JzfcRs5yQoypP4avA7QtUqgxYLKBYNv4IdzBmbhdw==", + "dev": true, + "requires": { + "punycode": "2.x.x" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2996,6 +3113,17 @@ "is-object": "^1.0.1" } }, + "joi": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-11.4.0.tgz", + "integrity": "sha512-O7Uw+w/zEWgbL6OcHbyACKSj0PkQeUgmehdoXVSxt92QFCq4+1390Rwh5moI2K/OgC7D8RHRZqHZxT2husMJHA==", + "dev": true, + "requires": { + "hoek": "4.x.x", + "isemail": "3.x.x", + "topo": "2.x.x" + } + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -3066,6 +3194,15 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", @@ -3099,6 +3236,15 @@ "integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=", "dev": true }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "dev": true, + "requires": { + "package-json": "^4.0.0" + } + }, "lazy-req": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", @@ -3296,6 +3442,15 @@ "lodash.escape": "^3.0.0" } }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, "logalot": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", @@ -3877,6 +4032,18 @@ "wordwrap": "~1.0.0" } }, + "ora": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-1.4.0.tgz", + "integrity": "sha512-iMK1DOQxzzh2MBlVsU42G80mnrvUhqsMh74phHtDlrcTZPK0pH6o7l7DRshK+0YsxDyEuaOkziVdvM3T0QTzpw==", + "dev": true, + "requires": { + "chalk": "^2.1.0", + "cli-cursor": "^2.1.0", + "cli-spinners": "^1.0.1", + "log-symbols": "^2.1.0" + } + }, "ordered-read-streams": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", @@ -3991,6 +4158,51 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + }, + "dependencies": { + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + } + } + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -4060,6 +4272,12 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -4511,6 +4729,12 @@ "integrity": "sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w==", "dev": true }, + "pretty-bytes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", + "dev": true + }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -4695,6 +4919,12 @@ "strip-indent": "^1.0.1" } }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", @@ -4704,6 +4934,25 @@ "is-equal-shallow": "^0.1.3" } }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "^1.0.1" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -4797,6 +5046,27 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + } + } + }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -4815,6 +5085,21 @@ "is-promise": "^2.1.0" } }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "*" + } + }, "rxjs": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.2.tgz", @@ -4863,6 +5148,15 @@ "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "^5.0.3" + } + }, "semver-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", @@ -5462,31 +5756,6 @@ } } }, - "sw-cacheable-response": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/sw-cacheable-response/-/sw-cacheable-response-0.0.18.tgz", - "integrity": "sha1-CoI4BThrWF0mQxRznjgZHaghs8w=" - }, - "sw-lib": { - "version": "0.0.17", - "resolved": "https://registry.npmjs.org/sw-lib/-/sw-lib-0.0.17.tgz", - "integrity": "sha1-IcokhlFszHSqqywt5w8IRi6NzAs=" - }, - "sw-precaching": { - "version": "0.0.17", - "resolved": "https://registry.npmjs.org/sw-precaching/-/sw-precaching-0.0.17.tgz", - "integrity": "sha1-njfo9U1m2unspnIqPwwcKlhHTwM=" - }, - "sw-routing": { - "version": "0.0.17", - "resolved": "https://registry.npmjs.org/sw-routing/-/sw-routing-0.0.17.tgz", - "integrity": "sha1-tUt0D+OiKJbzy8HJN68ozre+5L8=" - }, - "sw-runtime-caching": { - "version": "0.0.17", - "resolved": "https://registry.npmjs.org/sw-runtime-caching/-/sw-runtime-caching-0.0.17.tgz", - "integrity": "sha1-h8hxyvNAbOsmQwFOG1DnijbR2LE=" - }, "symbol-tree": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", @@ -5572,6 +5841,15 @@ "uuid": "^3.0.1" } }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -5678,6 +5956,15 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, + "topo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", + "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", + "dev": true, + "requires": { + "hoek": "4.x.x" + } + }, "tough-cookie": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", @@ -5785,6 +6072,21 @@ "through2-filter": "^2.0.0" } }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "unquote": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", @@ -5797,6 +6099,24 @@ "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", "dev": true }, + "update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "dev": true, + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, "url-parse-lax": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", @@ -6015,6 +6335,15 @@ "string-width": "^1.0.2 || 2" } }, + "widest-line": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz", + "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", + "dev": true, + "requires": { + "string-width": "^2.1.1" + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -6022,6 +6351,237 @@ "dev": true, "optional": true }, + "workbox-background-sync": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-3.4.1.tgz", + "integrity": "sha512-Ksb2nCg/2wOyBMhSBqSbtCEwuKaf5sHgTY8HdCxbLIQSzDh9/qZqg+1P11CKlgJmHtje3EK3B8EsrzukZo10xA==", + "dev": true, + "requires": { + "workbox-core": "^3.4.1" + } + }, + "workbox-broadcast-cache-update": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-broadcast-cache-update/-/workbox-broadcast-cache-update-3.4.1.tgz", + "integrity": "sha512-+WPqHFk4ER4RICAMOYrP88yBbiUQ9ZOFNruqwbl9YxGfbADV16OEGmYpIs+Az6HT6DNDCx8eQqtFiaG8N3O11Q==", + "dev": true, + "requires": { + "workbox-core": "^3.4.1" + } + }, + "workbox-build": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-3.4.1.tgz", + "integrity": "sha512-Qi04XdHjkXbRN0CV5XO1oqDWbJSIm7VYhxmxjtnVcKK8PrMT6rOUFUi9ziDI+8UQgcXbLK4ZChWf2ptZS1/MbA==", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "common-tags": "^1.4.0", + "fs-extra": "^4.0.2", + "glob": "^7.1.2", + "joi": "^11.1.1", + "lodash.template": "^4.4.0", + "pretty-bytes": "^4.0.2", + "workbox-background-sync": "^3.4.1", + "workbox-broadcast-cache-update": "^3.4.1", + "workbox-cache-expiration": "^3.4.1", + "workbox-cacheable-response": "^3.4.1", + "workbox-core": "^3.4.1", + "workbox-google-analytics": "^3.4.1", + "workbox-navigation-preload": "^3.4.1", + "workbox-precaching": "^3.4.1", + "workbox-range-requests": "^3.4.1", + "workbox-routing": "^3.4.1", + "workbox-strategies": "^3.4.1", + "workbox-streams": "^3.4.1", + "workbox-sw": "^3.4.1" + }, + "dependencies": { + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0" + } + } + } + }, + "workbox-cache-expiration": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-cache-expiration/-/workbox-cache-expiration-3.4.1.tgz", + "integrity": "sha512-AzOPB+dwfxg13v4+q5jWkxsw/oim9mPIzew1anu8ALA3vB8qySaJJToXp+ZlVh/Co+sDK0tgjlB76bvSFHgZ4g==", + "dev": true, + "requires": { + "workbox-core": "^3.4.1" + } + }, + "workbox-cacheable-response": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-3.4.1.tgz", + "integrity": "sha512-SO2k830JT93GitPwc5tzJI49d9VwyVxXwiCbyvo+Sqo+dcvWSrmpsyuXdzy6zuasbPrWUF0vsFj1uGtZbOym8Q==", + "dev": true, + "requires": { + "workbox-core": "^3.4.1" + } + }, + "workbox-cli": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-cli/-/workbox-cli-3.4.1.tgz", + "integrity": "sha512-QDKSAQfT3K7Y2U4pO2d7aPPSKbWJZA/1ouwskoCICo51nVVCQ+xR0czvJ++OzcR2qB3RsgZ7ZSbDvhOgyh9CTg==", + "dev": true, + "requires": { + "chalk": "^2.1.0", + "common-tags": "^1.4.0", + "fs-extra": "^4.0.2", + "glob": "^7.1.2", + "inquirer": "^3.3.0", + "meow": "^3.7.0", + "ora": "^1.3.0", + "pretty-bytes": "^4.0.2", + "update-notifier": "^2.3.0", + "workbox-build": "^3.4.1" + }, + "dependencies": { + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + } + } + }, + "workbox-core": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-3.4.1.tgz", + "integrity": "sha512-RqMV2so9/KLAu9aUxJ/85pvrZMUn835B8zoHmqRyGNetiDr8B1zSBeKXPZAjFlX/88KdhizNwiRlJtqlXtM4tA==", + "dev": true + }, + "workbox-google-analytics": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-3.4.1.tgz", + "integrity": "sha512-w6Osz2Rr1/4+W0gram6Yzg6NNWLvHP51RwFCNAZSpEnipr0qSEtD+yvwrdaHfiJHWhcK2yH/V6E1MV8Hrczmvw==", + "dev": true, + "requires": { + "workbox-background-sync": "^3.4.1", + "workbox-core": "^3.4.1", + "workbox-routing": "^3.4.1", + "workbox-strategies": "^3.4.1" + } + }, + "workbox-navigation-preload": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-3.4.1.tgz", + "integrity": "sha512-P3FHAcyZ8db2QiW/BpMkuosC1OkRsEoUaT7U3QOgg7JSjjsJoEbF7G5olNe+P+PQYdVhJA7TCuptI6dy2gLS/g==", + "dev": true, + "requires": { + "workbox-core": "^3.4.1" + } + }, + "workbox-precaching": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-3.4.1.tgz", + "integrity": "sha512-ykU2mly9xmRrCW6iMeUWYydWiso/WSE16+7wponhI0WC53jiQSt2JvykWm0VpWFJSs6ZTSZZ1WK2gs/brRnPug==", + "dev": true, + "requires": { + "workbox-core": "^3.4.1" + } + }, + "workbox-range-requests": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-3.4.1.tgz", + "integrity": "sha512-ktgjl6liZrRTmQjPw1pBblC5umHnTb8XcvFVitdGz17B23jj6cUV4EXzEU2ilGn6jO6+MLV1Vn9SWajtLSc2Gg==", + "dev": true, + "requires": { + "workbox-core": "^3.4.1" + } + }, + "workbox-routing": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-3.4.1.tgz", + "integrity": "sha512-6j6cXMUYfMPYTycmElxVOfBTr6WV5zAn/JUFJ7GJ5pYFIE9cqztprnrcOsWJ42+AiNIeHPbKfyIWE/rZVviMxQ==", + "dev": true, + "requires": { + "workbox-core": "^3.4.1" + } + }, + "workbox-strategies": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-3.4.1.tgz", + "integrity": "sha512-7mJuzFsgejflzjfnChXCFma1S0mi9WC6wlSU2wE50M7bJmEuf9A3j3MojpKcsTEM58hbhbnU6QF/u9iIV7+opw==", + "dev": true, + "requires": { + "workbox-core": "^3.4.1" + } + }, + "workbox-streams": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-3.4.1.tgz", + "integrity": "sha512-krw+5bp+oe9Za5c6WlTWM3SgZGfExYcqRSn1gsyYgKeXmgzTwf+DOb5Lwult0KSWlJfq8B3Wk7sW8Sl7lRzSbA==", + "dev": true, + "requires": { + "workbox-core": "^3.4.1" + } + }, + "workbox-sw": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-3.4.1.tgz", + "integrity": "sha512-nnm2by5oaQGXRH7x4M5/n2KqjUGVmP4P8azUmJITnYa3DWVYn/ghDg3LJ5+h4A28vYq9V6ePgATaEPfb6B5pug==", + "dev": true + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", @@ -6084,6 +6644,17 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, "x-ray": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/x-ray/-/x-ray-2.3.3.tgz", @@ -6275,6 +6846,12 @@ "format-parser": "0.0.2" } }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + }, "xml-name-validator": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", diff --git a/package.json b/package.json index 7c50ea4..084e742 100644 --- a/package.json +++ b/package.json @@ -3,19 +3,12 @@ "private": true, "version": "0.1.3", "description": "A collection of Progressive Web App case studies.", - "dependencies": { - "sw-cacheable-response": "0.0.18", - "sw-lib": "0.0.17", - "sw-precaching": "0.0.17", - "sw-routing": "0.0.17", - "sw-runtime-caching": "0.0.17" - }, + "dependencies": {}, "devDependencies": { "chalk": "^2.4.1", - "chalk-cli": "^3.0.0", - "imagemin": "^5.3.1", "imagemin-mozjpeg": "^7.0.0", "imagemin-pngquant": "^5.1.0", + "imagemin": "^5.3.1", "inquirer": "^6.0.0", "node-fetch": "^2.1.2", "prettier": "^1.13.7", @@ -23,21 +16,19 @@ "request-x-ray": "^0.1.4", "sharp": "^0.20.5", "svgo": "^1.0.5", + "workbox-cli": "^3.4.1", "x-ray": "^2.3.3" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "install:sw-helpers": "cp node_modules/sw-*/build/sw-*.min.js js/vendor/", - "postinstall": "npm run install:sw-helpers", - "preversion": "echo BE SURE TO UPDATE THE VERSION NUMBER IN SW.JS | chalk red bold", "version:patch": "npm --silent version patch", "version:minor": "npm --silent version minor", "version:major": "npm --silent version major", "fetch-icon": "./scripts/fetch-icon.js", "resize-images": "./scripts/resize-images.js", "purgecss": "./scripts/purgecss.js", - "start": "npm run purgecss; bundle exec jekyll serve", - "build": "npm run purgecss; bundle exec jekyll build" + "inject-sw-manifest": "workbox injectManifest workbox-config.js", + "start": "npm run inject-sw-manifest; npm run purgecss; bundle exec jekyll serve", + "build": "npm run purgecss; bundle exec jekyll build; npm run inject-sw-manifest; cp revisioned-sw.js _site" }, "repository": { "type": "git", diff --git a/revisioned-sw.js b/revisioned-sw.js new file mode 100644 index 0000000..3d1821f --- /dev/null +++ b/revisioned-sw.js @@ -0,0 +1,170 @@ +importScripts( + 'https://storage.googleapis.com/workbox-cdn/releases/3.3.1/workbox-sw.js' +); + +workbox.setConfig({ + debug: true +}); + +workbox.core.setLogLevel(workbox.core.LOG_LEVELS.debug); + +const CACHES = { + cssJs: 'css-js', + images: 'images', + fonts: 'google-fonts' +}; + +// // Cache fallback for HTML files +// workbox.routing.registerRoute(/(?:^[^.]+|\.html)$/, args => +// workbox.strategies +// .networkFirst() +// .handle(args) +// .then( +// // page is not in cache, respond with 404 page (even if the page exists) +// response => (response === undefined ? caches.match('/404/') : response) +// ) +// ); + +// Cache CSS and JS files +workbox.routing.registerRoute( + /\.(?:js|css)$/, + workbox.strategies.staleWhileRevalidate({ + cacheName: CACHES.cssJs + }) +); + +// Cache images +workbox.routing.registerRoute( + /\.(?:png|gif|jpg|jpeg|svg)$/, + workbox.strategies.cacheFirst({ + cacheName: CACHES.images, + plugins: [ + new workbox.expiration.Plugin({ + maxEntries: 60, + maxAgeSeconds: 30 * 24 * 60 * 60 // 30 Days + }) + ] + }) +); + +// Cache Google Fonts +workbox.routing.registerRoute( + new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'), + workbox.strategies.cacheFirst({ + cacheName: CACHES.fonts, + plugins: [ + new workbox.expiration.Plugin({ + maxEntries: 30 + }), + new workbox.cacheableResponse.Plugin({ + statuses: [200] + }) + ] + }) +); + +// filled in automatically +const precacheUrls = [ + { + "url": "404.html", + "revision": "c655e20ab80ee387eac1bcf97b34028b" + }, + { + "url": "error.html", + "revision": "94a7cc218631709c36263493b3200839" + }, + { + "url": "index.html", + "revision": "02dcd892ddcff83482354b242a2d285f" + }, + { + "url": "page2/index.html", + "revision": "ec61a1113aa31cfe480ee75a2d6d7d1b" + }, + { + "url": "page3/index.html", + "revision": "0cb83fdee3057a1c3aa0e31103abb63b" + }, + { + "url": "page4/index.html", + "revision": "e4815d2e0618aa86b51fbd13f18d42b6" + }, + { + "url": "page5/index.html", + "revision": "ede7e811827f2ebde7281d42770e9a7d" + } +]; + +workbox.precaching.precacheAndRoute(precacheUrls); + +/** + * Simplifies a url to one that might be in the precache + * @example "https://pwastats.com/page2/" => "/page2/index.html" + * @param {Location} location the url to simplify + */ +const getPrecachedUrl = location => { + const parsed = new URL(location.href, location); + // remove target and query params + parsed.hash = ''; + parsed.search = ''; + return parsed + .toString() + .replace(location.protocol + '//' + location.host, '') // remove hostname (if it matches) so it is just the path + .replace(/\/$/, '/index.html'); // if it ends with slash, add /index.html +}; + +workbox.routing.registerRoute( + new workbox.routing.NavigationRoute(req => + workbox.strategies + .networkFirst() + .handle(req) + .then(async response => { + console.log('response', response); + console.log('matching?', response === undefined); + if (response === undefined) { + console.log('request', req); + const simplifiedUrl = getPrecachedUrl(req.url); + console.log('checking for', simplifiedUrl); + const matching = await caches.match(simplifiedUrl); + console.log('matching request', matching); + if (matching === undefined) { + console.log('there is no cached version of this page'); + const fallback = await caches.match('404.html'); + console.log('fallback is', fallback); + return fallback; + } + return matching; + } + return response; + }) + ) +); + +/** + * Returns true if the cache is one of the specified caches or starts with workbox- + * @param {string} cacheName + */ +const isCacheValid = cacheName => + Object.values(CACHES).includes(cacheName) || cacheName.startsWith('workbox-'); + +/** + * Delete out-of-date caches + */ +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(cacheNameList => + Promise.all( + cacheNameList.map(cacheName => { + if (!isCacheValid(cacheName)) { + console.info(`Deleting cache "${cacheName}"`); + return caches.delete(cacheName); + } + }) + ) + ) + ); +}); + +// Automatically start workbox +workbox.skipWaiting(); +workbox.clientsClaim(); diff --git a/sw.js b/sw.js index da11177..354280b 100644 --- a/sw.js +++ b/sw.js @@ -1,103 +1,119 @@ importScripts( - 'js/vendor/sw-cacheable-response.min.js', - 'js/vendor/sw-routing.min.js', - 'js/vendor/sw-runtime-caching.min.js', - 'js/vendor/sw-precaching.min.js' + 'https://storage.googleapis.com/workbox-cdn/releases/3.3.1/workbox-sw.js' ); -// Make this always match package.json version -const version = '0.1.3'; -const cacheName = `defaultCache_${version}`; - -const { cacheableResponse, precaching, routing, runtimeCaching } = goog; +const CACHES = { + cssJs: 'css-js', + images: 'images', + fonts: 'google-fonts' +}; -const router = new routing.Router(); -const localhost = registration.scope; -const staticCache = new precaching.UnrevisionedCacheManager({ cacheName }); -const requestWrapper = new runtimeCaching.RequestWrapper({ cacheName }); -const cdnRequestWrapper = new runtimeCaching.RequestWrapper({ - plugins: [ - new cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }) - ], - cacheName -}); +// Cache CSS and JS files +workbox.routing.registerRoute( + /\.(?:js|css)$/, + workbox.strategies.staleWhileRevalidate({ + cacheName: CACHES.cssJs + }) +); -/** - * Route for local CSS and JS assets - * - * Strategy: - * https://developers.google.com/web/fundamentals/instant-and-offline/ - * offline-cookbook/#stale-while-revalidate - */ -const assetRoute = new routing.RegExpRoute({ - regExp: new RegExp(`^${localhost}.*\\.(css|js|png|svg)$`), - handler: new runtimeCaching.StaleWhileRevalidate({ requestWrapper }) -}); +// Cache images +workbox.routing.registerRoute( + /\.(?:png|gif|jpg|jpeg|svg)$/, + workbox.strategies.cacheFirst({ + cacheName: CACHES.images, + plugins: [ + new workbox.expiration.Plugin({ + maxEntries: 60, + maxAgeSeconds: 30 * 24 * 60 * 60 // 30 Days + }) + ] + }) +); -/** - * Route for assets on cloudfront.net CDN - * - * Strategy: - * https://developers.google.com/web/fundamentals/instant-and-offline/ - * offline-cookbook/#stale-while-revalidate - */ -const cdnAssetRoute = new routing.RegExpRoute({ - regExp: new RegExp('^https://.*\\.cloudfront\\.net/.*\\.(png|svg)$'), - handler: new runtimeCaching.StaleWhileRevalidate({ - requestWrapper: cdnRequestWrapper +// Cache Google Fonts +workbox.routing.registerRoute( + new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'), + workbox.strategies.cacheFirst({ + cacheName: CACHES.fonts, + plugins: [ + new workbox.expiration.Plugin({ + maxEntries: 30 + }), + new workbox.cacheableResponse.Plugin({ + statuses: [200] + }) + ] }) -}); +); -/** - * Route for pages - * - * Strategy: - * https://developers.google.com/web/fundamentals/instant-and-offline/ - * offline-cookbook/#network-falling-back-to-cache - */ -const navRoute = new routing.NavigationRoute({ - whitelist: [/./], - handler: new runtimeCaching.NetworkFirst({ requestWrapper }) -}); +// filled in automatically +const precacheUrls = []; + +workbox.precaching.precacheAndRoute(precacheUrls); /** - * Precache resources + * Simplifies a url to one that might be in the precache + * @example "https://pwastats.com/page2/" => "/page2/index.html" + * @param {Location} location the url to simplify */ -staticCache.addToCacheList({ - unrevisionedFiles: ['/', '/404/', '/error/'] -}); - -self.oninstall = event => { - event.waitUntil(Promise.all([staticCache.install().then(skipWaiting)])); +const getPrecachedUrl = location => { + const parsed = new URL(location.href, location); + // remove target and query params + parsed.hash = ''; + parsed.search = ''; + return parsed + .toString() + .replace(location.protocol + '//' + location.host, '') // remove hostname (if it matches) so it is just the path + .replace(/\/$/, '/index.html'); // if it ends with slash, add /index.html }; -self.onactivate = event => { - caches.keys().then(keys => { - keys.forEach(cacheName => { - if (!cacheName.endsWith(version)) { - caches.delete(cacheName); - } - }); - }); - return event.waitUntil(clients.claim()); -}; - -router.registerRoutes({ - routes: [assetRoute, cdnAssetRoute, navRoute] -}); +workbox.routing.registerRoute( + new workbox.routing.NavigationRoute(req => + workbox.strategies + .networkFirst() + .handle(req) + .then(async response => { + if (response === undefined) { + const simplifiedUrl = getPrecachedUrl(req.url); + console.log('falling back to precache, checking for', simplifiedUrl); + const matching = await caches.match(simplifiedUrl); + if (matching === undefined) { + console.log('not in precache, responding with 404'); + const fallback = await caches.match('404.html'); + return fallback; + } + return matching; + } + return response; + }) + ) +); /** - * Fallback route for stuff that doesn't match + * Returns true if the cache is one of the specified caches or starts with workbox- + * @param {string} cacheName */ -router.setDefaultHandler({ - handler: new runtimeCaching.NetworkOnly() -}); +const isCacheValid = cacheName => + Object.values(CACHES).includes(cacheName) || cacheName.startsWith('workbox-'); /** - * Catch-all fetch error handler + * Delete out-of-date caches */ -router.setCatchHandler({ - handler: { - handle: () => caches.match('/error/') - } +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(cacheNameList => + Promise.all( + cacheNameList.map(cacheName => { + if (!isCacheValid(cacheName)) { + console.info(`Deleting cache "${cacheName}"`); + return caches.delete(cacheName); + } + }) + ) + ) + ); }); + +// Automatically start workbox +workbox.skipWaiting(); +workbox.clientsClaim(); diff --git a/workbox-config.js b/workbox-config.js new file mode 100644 index 0000000..5f0c991 --- /dev/null +++ b/workbox-config.js @@ -0,0 +1,7 @@ +module.exports = { + swSrc: 'sw.js', + swDest: 'revisioned-sw.js', + globDirectory: '_site', + globPatterns: ['*.html', 'page?/index.html'], + injectionPointRegexp: /(const precacheUrls = )\[\](;)/ +};