diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..9f68e7e --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,2 @@ +# Supported browsers for pace-js 2.x, frozen for the whole major version: https://web.dev/baseline +baseline 2021 with downstream diff --git a/README.md b/README.md index 94fa562..640739f 100644 --- a/README.md +++ b/README.md @@ -297,14 +297,15 @@ None! Support ------- -Pace is designed to support IE8+ (standards mode), FF 3.5+, Chrome, Safari 4+, Opera 10.5+, and all modern -mobile browsers. If you run into a compatibility issue, or can make a case for supporting something else, -please create an issue. +Pace supports Chrome and Edge 96+, Firefox 95+, and Safari 15.2+ on macOS and iOS, plus browsers built +on the same engines, such as Opera and Samsung Internet. For older browsers, use pace-js 1.x. + +If you run into a compatibility issue, please create an issue. Size ---- -pace.js is 4kb minified and gzipped. The themes vary between 0.5 and 4kb. +pace.min.js is under 4 kB gzipped. The themes are between 0.2 and 3.2 kB gzipped. Issues ------ diff --git a/pace.js b/pace.js index 5c60305..c5e4770 100644 --- a/pace.js +++ b/pace.js @@ -3,18 +3,11 @@ * https://github.com/CodeByZach/pace/ * Licensed MIT © HubSpot, Inc. */ -(function() { - var AjaxMonitor, Bar, DocumentMonitor, ElementMonitor, ElementTracker, EventLagMonitor, Evented, Events, NoTargetError, Pace, RequestIntercept, SOURCE_KEYS, Scaler, SocketRequestTracker, XHRRequestTracker, addEventListener, animation, avgAmplitude, bar, cancelAnimation, cancelAnimationFrame, defaultOptions, extend, extendNative, getFromDOM, getIntercept, handlePushState, ignoreStack, init, now, options, requestAnimationFrame, result, runAnimation, scalers, shouldIgnoreURL, shouldTrack, source, sources, uniScaler, _WebSocket, _XDomainRequest, _XMLHttpRequest, _i, _intercept, _len, _pushState, _ref, _ref1, _replaceState, - __slice = [].slice, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, - __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - defaultOptions = { +(function () { + const defaultOptions = { className: '', catchupTime: 100, - initialRate: .03, + initialRate: 0.03, minTime: 250, ghostTime: 100, maxProgressPerFrame: 20, @@ -25,262 +18,171 @@ target: 'body', elements: { checkInterval: 100, - selectors: ['body'] + selectors: ['body'], }, eventLag: { minSamples: 10, sampleCount: 3, - lagThreshold: 3 + lagThreshold: 3, }, ajax: { trackMethods: ['GET'], trackWebSockets: true, - ignoreURLs: [] - } - }; - - now = function() { - var _ref; - return (_ref = typeof performance !== "undefined" && performance !== null ? typeof performance.now === "function" ? performance.now() : void 0 : void 0) != null ? _ref : +(new Date); + ignoreURLs: [], + }, }; - requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; - - cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame; - - addEventListener = function(obj, event, callback) { - if (typeof obj.addEventListener === "function") { - return obj.addEventListener(event, callback, false); - } else { - return function() { - if (typeof obj["on" + event] !== "function" || typeof obj["on" + event].eventListeners !== "object") { - var eventListeners = new Events(); - if (typeof obj["on" + event] === "function") { - eventListeners.on(event, obj["on" + event]); - } - obj["on" + event] = function(evt) { - return eventListeners.trigger(event, evt); - }; - obj["on" + event].eventListeners = eventListeners; - } else { - var eventListeners = obj["on" + event].eventListeners; - } - eventListeners.on(event, callback); - }(); - } - }; + const now = () => performance.now(); - if (requestAnimationFrame == null) { - requestAnimationFrame = function(fn) { - return setTimeout(fn, 50); - }; - cancelAnimationFrame = function(id) { - return clearTimeout(id); - }; - } + const requestAnimationFrame = window.requestAnimationFrame; + const cancelAnimationFrame = window.cancelAnimationFrame; - runAnimation = function(fn) { - var last, tick; - last = now(); - tick = function() { - var diff; - diff = now() - last; + const runAnimation = (fn) => { + let last = now(); + const tick = () => { + const diff = now() - last; if (diff >= 33) { last = now(); - return fn(diff, function() { - return requestAnimationFrame(tick); - }); - } else { - return setTimeout(tick, 33 - diff); + return fn(diff, () => requestAnimationFrame(tick)); } + return setTimeout(tick, 33 - diff); }; return tick(); }; - result = function() { - var args, key, obj; - obj = arguments[0], key = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : []; + const result = (obj, key, ...args) => { if (typeof obj[key] === 'function') { return obj[key].apply(obj, args); - } else { - return obj[key]; } + return obj[key]; }; - extend = function() { - var key, out, source, sources, val, _i, _len; - out = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : []; - for (_i = 0, _len = sources.length; _i < _len; _i++) { - source = sources[_i]; - if (source) { - for (key in source) { - if (!__hasProp.call(source, key)) continue; - if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue; - val = source[key]; - if ((out[key] != null) && typeof out[key] === 'object' && (val != null) && typeof val === 'object') { - extend(out[key], val); - } else { - out[key] = val; - } + const extend = (out, ...sources) => { + for (const source of sources) { + if (!source) { + continue; + } + for (const key in source) { + if (!Object.prototype.hasOwnProperty.call(source, key)) continue; + if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue; + const val = source[key]; + if (out[key] != null && typeof out[key] === 'object' && val != null && typeof val === 'object') { + extend(out[key], val); + } else { + out[key] = val; } } } return out; }; - avgAmplitude = function(arr) { - var count, sum, v, _i, _len; - sum = count = 0; - for (_i = 0, _len = arr.length; _i < _len; _i++) { - v = arr[_i]; + const avgAmplitude = (arr) => { + let sum = 0; + let count = 0; + for (const v of arr) { sum += Math.abs(v); count++; } return sum / count; }; - getFromDOM = function(key, json) { - var data, e, el; - if (key == null) { - key = 'options'; - } - if (json == null) { - json = true; - } - el = document.querySelector("script[data-pace-" + key + "]"); + const getFromDOM = (key = 'options', json = true) => { + const el = document.querySelector(`script[data-pace-${key}]`); if (!el) { return; } - data = el.getAttribute("data-pace-" + key); + const data = el.getAttribute(`data-pace-${key}`); if (!json) { return data; } try { return JSON.parse(data); - } catch (_error) { - e = _error; - return typeof console !== "undefined" && console !== null ? console.error("Error parsing inline pace options", e) : void 0; + } catch (e) { + console.error('Error parsing inline pace options', e); } }; - Evented = (function() { - function Evented() {} + const Pace = window.Pace || {}; - Evented.prototype.on = function(event, handler, ctx, once) { - var _base; - if (once == null) { - once = false; - } - if (this.bindings == null) { - this.bindings = {}; - } - if ((_base = this.bindings)[event] == null) { - _base[event] = []; - } - return this.bindings[event].push({ - handler: handler, - ctx: ctx, - once: once - }); - }; + window.Pace = Pace; - Evented.prototype.once = function(event, handler, ctx) { - return this.on(event, handler, ctx, true); - }; + Object.assign(Pace, { + on(event, handler, ctx, once) { + once ??= false; + this.bindings ??= {}; + this.bindings[event] ??= []; + this.bindings[event].push({ handler, ctx, once }); + }, - Evented.prototype.off = function(event, handler) { - var i, _ref, _results; - if (((_ref = this.bindings) != null ? _ref[event] : void 0) == null) { + once(event, handler, ctx) { + this.on(event, handler, ctx, true); + }, + + off(event, handler) { + if (this.bindings?.[event] == null) { return; } if (handler == null) { - return delete this.bindings[event]; - } else { - i = 0; - _results = []; - while (i < this.bindings[event].length) { - if (this.bindings[event][i].handler === handler) { - _results.push(this.bindings[event].splice(i, 1)); - } else { - _results.push(i++); - } + delete this.bindings[event]; + return; + } + let i = 0; + while (i < this.bindings[event].length) { + if (this.bindings[event][i].handler === handler) { + this.bindings[event].splice(i, 1); + } else { + i++; } - return _results; } - }; + }, - Evented.prototype.trigger = function() { - var args, ctx, event, handler, i, once, _ref, _ref1, _results; - event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; - if ((_ref = this.bindings) != null ? _ref[event] : void 0) { - i = 0; - _results = []; - while (i < this.bindings[event].length) { - _ref1 = this.bindings[event][i], handler = _ref1.handler, ctx = _ref1.ctx, once = _ref1.once; - handler.apply(ctx != null ? ctx : this, args); - if (once) { - _results.push(this.bindings[event].splice(i, 1)); - } else { - _results.push(i++); - } + trigger(event, ...args) { + if (!this.bindings?.[event]) { + return; + } + let i = 0; + while (i < this.bindings[event].length) { + const { handler, ctx, once } = this.bindings[event][i]; + handler.apply(ctx ?? this, args); + if (once) { + this.bindings[event].splice(i, 1); + } else { + i++; } - return _results; } - }; - - return Evented; - - })(); - - Pace = window.Pace || {}; - - window.Pace = Pace; - - extend(Pace, Evented.prototype); + }, + }); - options = Pace.options = extend({}, defaultOptions, window.paceOptions, getFromDOM()); + const options = (Pace.options = extend({}, defaultOptions, window.paceOptions, getFromDOM())); - _ref = ['ajax', 'document', 'eventLag', 'elements']; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - source = _ref[_i]; - if (options[source] === true) { - options[source] = defaultOptions[source]; + for (const key of ['ajax', 'document', 'eventLag', 'elements']) { + if (options[key] === true) { + options[key] = defaultOptions[key]; } } - NoTargetError = (function(_super) { - __extends(NoTargetError, _super); - - function NoTargetError() { - _ref1 = NoTargetError.__super__.constructor.apply(this, arguments); - return _ref1; - } - - return NoTargetError; - - })(Error); + class NoTargetError extends Error {} - Bar = (function() { - function Bar() { + class Bar { + constructor() { this.progress = 0; } - Bar.prototype.getElement = function() { - var activity, inner, progress, targetElement; + getElement() { if (this.el == null) { - targetElement = document.querySelector(options.target); + const targetElement = document.querySelector(options.target); if (!targetElement) { - throw new NoTargetError; + throw new NoTargetError(); } this.el = document.createElement('div'); - this.el.className = "pace pace-active"; + this.el.className = 'pace pace-active'; document.body.className = document.body.className.replace(/(pace-done )|/, 'pace-running '); - progress = document.createElement('div'); + const progress = document.createElement('div'); progress.className = 'pace-progress' + (options.className !== '' ? ' ' + options.className : ''); - inner = document.createElement('div'); + const inner = document.createElement('div'); inner.className = 'pace-progress-inner'; progress.appendChild(inner); - activity = document.createElement('div'); + const activity = document.createElement('div'); activity.className = 'pace-activity'; this.el.appendChild(progress); this.el.appendChild(activity); @@ -291,488 +193,349 @@ } } return this.el; - }; + } - Bar.prototype.finish = function() { - var el; - el = this.getElement(); + finish() { + const el = this.getElement(); el.className = el.className.replace('pace-active', 'pace-inactive'); - return document.body.className = document.body.className.replace('pace-running ', 'pace-done '); - }; + document.body.className = document.body.className.replace('pace-running ', 'pace-done '); + } - Bar.prototype.update = function(prog) { + update(prog) { this.progress = prog; Pace.trigger('progress', prog); - return this.render(); - }; + this.render(); + } - Bar.prototype.destroy = function() { + destroy() { try { this.getElement().parentNode.removeChild(this.getElement()); - } catch (_error) { - NoTargetError = _error; + } catch (error) { + NoTargetError = error; } - return this.el = void 0; - }; + this.el = undefined; + } - Bar.prototype.render = function() { - var el, key, progressStr, transform, _j, _len1, _ref2; + render() { if (document.querySelector(options.target) == null) { - return false; - } - el = this.getElement(); - transform = "translate3d(" + this.progress + "%, 0, 0)"; - _ref2 = ['webkitTransform', 'msTransform', 'transform']; - for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { - key = _ref2[_j]; - el.children[0].style[key] = transform; + return; } + const el = this.getElement(); + el.children[0].style.transform = `translate3d(${this.progress}%, 0, 0)`; if (!this.lastRenderedProgress || this.lastRenderedProgress | 0 !== this.progress | 0) { - el.children[0].setAttribute('data-progress-text', "" + (this.progress | 0) + "%"); + el.children[0].setAttribute('data-progress-text', `${this.progress | 0}%`); + let progressStr; if (this.progress >= 100) { progressStr = '99'; } else { - progressStr = this.progress < 10 ? "0" : ""; + progressStr = this.progress < 10 ? '0' : ''; progressStr += this.progress | 0; } - el.children[0].setAttribute('data-progress', "" + progressStr); + el.children[0].setAttribute('data-progress', progressStr); } Pace.trigger('change', this.progress); - return this.lastRenderedProgress = this.progress; - }; + this.lastRenderedProgress = this.progress; + } - Bar.prototype.done = function() { + done() { return this.progress >= 100; - }; - - return Bar; - - })(); + } + } - Events = (function() { - function Events() { + class Events { + constructor() { this.bindings = {}; } - Events.prototype.trigger = function(name, val) { - var binding, _j, _len1, _ref2, _results; + trigger(name, val) { if (this.bindings[name] != null) { - _ref2 = this.bindings[name]; - _results = []; - for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { - binding = _ref2[_j]; - _results.push(binding.call(this, val)); + // A copy, so listeners added while this runs wait for the next trigger. + for (const binding of this.bindings[name].slice()) { + binding.call(this, val); } - return _results; } - }; - - Events.prototype.on = function(name, fn) { - var _base; - if ((_base = this.bindings)[name] == null) { - _base[name] = []; - } - return this.bindings[name].push(fn); - }; - - return Events; - - })(); + } - _XMLHttpRequest = window.XMLHttpRequest; + on(name, fn) { + this.bindings[name] ??= []; + this.bindings[name].push(fn); + } + } - _XDomainRequest = window.XDomainRequest; + const _XMLHttpRequest = window.XMLHttpRequest; - _WebSocket = window.WebSocket; + const _WebSocket = window.WebSocket; - extendNative = function(to, from) { - var e, key, _results; - _results = []; - for (key in from.prototype) { + const extendNative = (to, from) => { + for (const key in from.prototype) { try { - if ((to[key] == null) && typeof from[key] !== 'function') { - if (typeof Object.defineProperty === 'function') { - _results.push(Object.defineProperty(to, key, { - get: (function(key) { - return function() { - return from.prototype[key]; - }; - })(key), - configurable: true, - enumerable: true - })); - } else { - _results.push(to[key] = from.prototype[key]); - } - } else { - _results.push(void 0); + if (to[key] == null && typeof from[key] !== 'function') { + Object.defineProperty(to, key, { + get: () => from.prototype[key], + configurable: true, + enumerable: true, + }); } - } catch (_error) { - e = _error; - } + } catch {} } - return _results; }; - ignoreStack = []; + const ignoreStack = []; - Pace.ignore = function() { - var args, fn, ret; - fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + Pace.ignore = (fn, ...args) => { ignoreStack.unshift('ignore'); - ret = fn.apply(null, args); + const ret = fn.apply(null, args); ignoreStack.shift(); return ret; }; - Pace.track = function() { - var args, fn, ret; - fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + Pace.track = (fn, ...args) => { ignoreStack.unshift('track'); - ret = fn.apply(null, args); + const ret = fn.apply(null, args); ignoreStack.shift(); return ret; }; - shouldTrack = function(method) { - var _ref2; - if (method == null) { - method = 'GET'; - } + const shouldTrack = (method) => { + method ??= 'GET'; if (ignoreStack[0] === 'track') { return 'force'; } if (!ignoreStack.length && options.ajax) { if (method === 'socket' && options.ajax.trackWebSockets) { return true; - } else if (_ref2 = method.toUpperCase(), __indexOf.call(options.ajax.trackMethods, _ref2) >= 0) { + } else if (options.ajax.trackMethods.includes(method.toUpperCase())) { return true; } } return false; }; - RequestIntercept = (function(_super) { - __extends(RequestIntercept, _super); - - function RequestIntercept() { - var monitorXHR, - _this = this; - RequestIntercept.__super__.constructor.apply(this, arguments); - monitorXHR = function(req) { - var _open; - _open = req.open; - return req.open = function(type, url, async) { - if (shouldTrack(type)) { - _this.trigger('request', { - type: type, - url: url, - request: req - }); - } - return _open.apply(req, arguments); - }; + // Outside the class on purpose: class bodies are strict mode, where assigning + // to a read-only property (a page may lock window.XMLHttpRequest) throws. + const installIntercepts = (intercept) => { + const monitorXHR = (req) => { + const _open = req.open; + req.open = (...args) => { + const [type, url] = args; + if (shouldTrack(type)) { + intercept.trigger('request', { type, url, request: req }); + } + return _open.apply(req, args); }; - window.XMLHttpRequest = function(flags) { - var req; - req = new _XMLHttpRequest(flags); - monitorXHR(req); + }; + // Plain functions, not arrow functions: pages call these with `new`. + window.XMLHttpRequest = function (flags) { + const req = new _XMLHttpRequest(flags); + monitorXHR(req); + return req; + }; + try { + extendNative(window.XMLHttpRequest, _XMLHttpRequest); + } catch {} + if (options.ajax.trackWebSockets) { + window.WebSocket = function (url, protocols) { + let req; + if (protocols != null) { + req = new _WebSocket(url, protocols); + } else { + req = new _WebSocket(url); + } + if (shouldTrack('socket')) { + intercept.trigger('request', { type: 'socket', url, protocols, request: req }); + } return req; }; try { - extendNative(window.XMLHttpRequest, _XMLHttpRequest); - } catch (_error) {} - if (_XDomainRequest != null) { - window.XDomainRequest = function() { - var req; - req = new _XDomainRequest; - monitorXHR(req); - return req; - }; - try { - extendNative(window.XDomainRequest, _XDomainRequest); - } catch (_error) {} - } - if ((_WebSocket != null) && options.ajax.trackWebSockets) { - window.WebSocket = function(url, protocols) { - var req; - if (protocols != null) { - req = new _WebSocket(url, protocols); - } else { - req = new _WebSocket(url); - } - if (shouldTrack('socket')) { - _this.trigger('request', { - type: 'socket', - url: url, - protocols: protocols, - request: req - }); - } - return req; - }; - try { - extendNative(window.WebSocket, _WebSocket); - } catch (_error) {} - } + extendNative(window.WebSocket, _WebSocket); + } catch {} } + }; - return RequestIntercept; - - })(Events); + class RequestIntercept extends Events { + constructor() { + super(); + installIntercepts(this); + } + } - _intercept = null; + let _intercept = null; - getIntercept = function() { - if (_intercept == null) { - _intercept = new RequestIntercept; - } + const getIntercept = () => { + _intercept ??= new RequestIntercept(); return _intercept; }; - shouldIgnoreURL = function(url) { - var pattern, _j, _len1, _ref2; - _ref2 = options.ajax.ignoreURLs; - for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { - pattern = _ref2[_j]; + const shouldIgnoreURL = (url) => { + const patterns = options.ajax.ignoreURLs; + for (let i = 0, n = patterns.length; i < n; i++) { + const pattern = patterns[i]; if (typeof pattern === 'string') { if (url.indexOf(pattern) !== -1) { return true; } - } else { - if (pattern.test(url)) { - return true; - } + } else if (pattern.test(url)) { + return true; } } return false; }; - getIntercept().on('request', function(_arg) { - var after, args, request, type, url; - type = _arg.type, request = _arg.request, url = _arg.url; + getIntercept().on('request', (event) => { + const { type, request, url } = event; if (shouldIgnoreURL(url)) { return; } if (!Pace.running && (options.restartOnRequestAfter !== false || shouldTrack(type) === 'force')) { - args = arguments; - after = options.restartOnRequestAfter || 0; + let after = options.restartOnRequestAfter || 0; if (typeof after === 'boolean') { after = 0; } - return setTimeout(function() { - var stillActive, _j, _len1, _ref2, _ref3, _results; + setTimeout(() => { + let stillActive; if (type === 'socket') { stillActive = request.readyState < 1; } else { - stillActive = (0 < (_ref2 = request.readyState) && _ref2 < 4); + stillActive = 0 < request.readyState && request.readyState < 4; } if (stillActive) { Pace.restart(); - _ref3 = Pace.sources; - _results = []; - for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { - source = _ref3[_j]; + for (let i = 0, n = Pace.sources.length; i < n; i++) { + const source = Pace.sources[i]; if (source instanceof AjaxMonitor) { - source.watch.apply(source, args); + source.watch(event); break; - } else { - _results.push(void 0); } } - return _results; } }, after); } }); - AjaxMonitor = (function() { - function AjaxMonitor() { - this.complete = __bind(this.complete, this); - var _this = this; + class AjaxMonitor { + constructor() { + this.complete = this.complete.bind(this); this.elements = []; - getIntercept().on('request', function() { - return _this.watch.apply(_this, arguments); - }); + getIntercept().on('request', (event) => this.watch(event)); } - AjaxMonitor.prototype.watch = function(_arg) { - var request, tracker, type, url; - type = _arg.type, request = _arg.request, url = _arg.url; + watch({ type, request, url }) { if (shouldIgnoreURL(url)) { return; } + let tracker; if (type === 'socket') { tracker = new SocketRequestTracker(request, this.complete); } else { tracker = new XHRRequestTracker(request, this.complete); } - return this.elements.push(tracker); - }; - - AjaxMonitor.prototype.complete = function(tracker) { - return this.elements = this.elements.filter(function(e) { - return e !== tracker; - }); - }; - - return AjaxMonitor; + this.elements.push(tracker); + } - })(); + complete(tracker) { + this.elements = this.elements.filter((e) => e !== tracker); + } + } - XHRRequestTracker = (function() { - function XHRRequestTracker(request, completeCallback) { - var event, size, _j, _len1, _onreadystatechange, _ref2, - _this = this; + class XHRRequestTracker { + constructor(request, completeCallback) { this.progress = 0; - if (window.ProgressEvent != null) { - size = null; - addEventListener(request, 'progress', function(evt) { - if (evt.lengthComputable) { - return _this.progress = 100 * evt.loaded / evt.total; - } else { - return _this.progress = _this.progress + (100 - _this.progress) / 2; - } - }, false); - _ref2 = ['load', 'abort', 'timeout', 'error']; - for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { - event = _ref2[_j]; - addEventListener(request, event, function() { - completeCallback(_this); - return _this.progress = 100; - }, false); + request.addEventListener('progress', (evt) => { + if (evt.lengthComputable) { + this.progress = (100 * evt.loaded) / evt.total; + } else { + this.progress = this.progress + (100 - this.progress) / 2; } - } else { - _onreadystatechange = request.onreadystatechange; - request.onreadystatechange = function() { - var _ref3; - if ((_ref3 = request.readyState) === 0 || _ref3 === 4) { - completeCallback(_this); - _this.progress = 100; - } else if (request.readyState === 3) { - _this.progress = 50; - } - return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0; - }; + }, false); + for (const event of ['load', 'abort', 'timeout', 'error']) { + request.addEventListener(event, () => { + completeCallback(this); + this.progress = 100; + }, false); } } + } - return XHRRequestTracker; - - })(); - - SocketRequestTracker = (function() { - function SocketRequestTracker(request, completeCallback) { - var event, _j, _len1, _ref2, - _this = this; + class SocketRequestTracker { + constructor(request, completeCallback) { this.progress = 0; - _ref2 = ['error', 'open']; - for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { - event = _ref2[_j]; - addEventListener(request, event, function() { - completeCallback(_this); - return _this.progress = 100; + for (const event of ['error', 'open']) { + request.addEventListener(event, () => { + completeCallback(this); + this.progress = 100; }, false); } } + } - return SocketRequestTracker; - - })(); - - ElementMonitor = (function() { - function ElementMonitor(options) { - var selector, _j, _len1, _ref2; - if (options == null) { - options = {}; - } - this.complete = __bind(this.complete, this); + class ElementMonitor { + constructor(settings) { + settings ??= {}; + this.complete = this.complete.bind(this); this.elements = []; - if (options.selectors == null) { - options.selectors = []; - } - _ref2 = options.selectors; - for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { - selector = _ref2[_j]; - this.elements.push(new ElementTracker(selector, this.complete)); + settings.selectors ??= []; + const selectors = settings.selectors; + for (let i = 0, n = selectors.length; i < n; i++) { + this.elements.push(new ElementTracker(selectors[i], this.complete)); } } - ElementMonitor.prototype.complete = function(tracker) { - return this.elements = this.elements.filter(function(e) { - return e !== tracker; - }); - }; - - return ElementMonitor; - - })(); + complete(tracker) { + this.elements = this.elements.filter((e) => e !== tracker); + } + } - ElementTracker = (function() { - function ElementTracker(selector, completeCallback) { + class ElementTracker { + constructor(selector, completeCallback) { this.selector = selector; this.completeCallback = completeCallback; this.progress = 0; this.check(); } - ElementTracker.prototype.check = function() { - var _this = this; + check() { if (document.querySelector(this.selector)) { - return this.done(); + this.done(); } else { - return setTimeout((function() { - return _this.check(); - }), options.elements.checkInterval); + setTimeout(() => this.check(), options.elements.checkInterval); } - }; + } - ElementTracker.prototype.done = function() { + done() { this.completeCallback(this); this.completeCallback = null; - return this.progress = 100; - }; - - return ElementTracker; - - })(); - - DocumentMonitor = (function() { - DocumentMonitor.prototype.states = { - loading: 0, - interactive: 50, - complete: 100 - }; + this.progress = 100; + } + } - function DocumentMonitor() { - var _onreadystatechange, _ref2, - _this = this; - this.progress = (_ref2 = this.states[document.readyState]) != null ? _ref2 : 100; - _onreadystatechange = document.onreadystatechange; - document.onreadystatechange = function() { - if (_this.states[document.readyState] != null) { - _this.progress = _this.states[document.readyState]; + class DocumentMonitor { + constructor() { + this.progress = this.states[document.readyState] ?? 100; + const _onreadystatechange = document.onreadystatechange; + document.onreadystatechange = (...args) => { + if (this.states[document.readyState] != null) { + this.progress = this.states[document.readyState]; } - return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0; + return typeof _onreadystatechange === 'function' ? _onreadystatechange.apply(null, args) : undefined; }; } + } - return DocumentMonitor; - - })(); + DocumentMonitor.prototype.states = { + loading: 0, + interactive: 50, + complete: 100, + }; - EventLagMonitor = (function() { - function EventLagMonitor(settings) { - var avg, interval, last, points, samples, - _this = this; + class EventLagMonitor { + constructor(settings) { this.progress = 0; - avg = 0; - samples = []; - points = 0; - last = now(); - interval = setInterval(function() { - var diff; - diff = now() - last - 50; + let avg = 0; + const samples = []; + let points = 0; + let last = now(); + const interval = setInterval(() => { + const diff = now() - last - 50; last = now(); samples.push(diff); if (samples.length > settings.sampleCount) { @@ -780,20 +543,17 @@ } avg = avgAmplitude(samples); if (++points >= settings.minSamples && avg < settings.lagThreshold) { - _this.progress = 100; - return clearInterval(interval); + this.progress = 100; + clearInterval(interval); } else { - return _this.progress = 100 * (3 / (avg + 3)); + this.progress = 100 * (3 / (avg + 3)); } }, 50); } + } - return EventLagMonitor; - - })(); - - Scaler = (function() { - function Scaler(source) { + class Scaler { + constructor(source) { this.source = source; this.last = this.sinceLastUpdate = 0; this.rate = options.initialRate; @@ -804,11 +564,8 @@ } } - Scaler.prototype.tick = function(frameTime, val) { - var scaling; - if (val == null) { - val = result(this.source, 'progress'); - } + tick(frameTime, val) { + val ??= result(this.source, 'progress'); if (val >= 100) { this.done = true; } @@ -825,120 +582,101 @@ if (val > this.progress) { this.progress += this.catchup * frameTime; } - scaling = 1 - Math.pow(this.progress / 100, options.easeFactor); + const scaling = 1 - Math.pow(this.progress / 100, options.easeFactor); this.progress += scaling * this.rate * frameTime; this.progress = Math.min(this.lastProgress + options.maxProgressPerFrame, this.progress); this.progress = Math.max(0, this.progress); this.progress = Math.min(100, this.progress); this.lastProgress = this.progress; return this.progress; - }; - - return Scaler; - - })(); - - sources = null; - - scalers = null; - - bar = null; - - uniScaler = null; - - animation = null; + } + } - cancelAnimation = null; + let sources = null; + let scalers = null; + let bar = null; + let uniScaler = null; + let animation = null; + let cancelAnimation = null; Pace.running = false; - handlePushState = function() { + const handlePushState = () => { if (options.restartOnPushState) { - return Pace.restart(); + Pace.restart(); } }; - if (window.history.pushState != null) { - _pushState = window.history.pushState; - window.history.pushState = function() { - handlePushState(); - return _pushState.apply(window.history, arguments); - }; - } + const _pushState = window.history.pushState; + window.history.pushState = (...args) => { + handlePushState(); + return _pushState.apply(window.history, args); + }; - if (window.history.replaceState != null) { - _replaceState = window.history.replaceState; - window.history.replaceState = function() { - handlePushState(); - return _replaceState.apply(window.history, arguments); - }; - } + const _replaceState = window.history.replaceState; + window.history.replaceState = (...args) => { + handlePushState(); + return _replaceState.apply(window.history, args); + }; - SOURCE_KEYS = { + const SOURCE_KEYS = { ajax: AjaxMonitor, elements: ElementMonitor, document: DocumentMonitor, - eventLag: EventLagMonitor + eventLag: EventLagMonitor, }; - (init = function() { - var type, _j, _k, _len1, _len2, _ref2, _ref3, _ref4; + const init = () => { Pace.sources = sources = []; - _ref2 = ['ajax', 'elements', 'document', 'eventLag']; - for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { - type = _ref2[_j]; + for (const type of ['ajax', 'elements', 'document', 'eventLag']) { if (options[type] !== false) { sources.push(new SOURCE_KEYS[type](options[type])); } } - _ref4 = (_ref3 = options.extraSources) != null ? _ref3 : []; - for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) { - source = _ref4[_k]; - sources.push(new source(options)); + const extraSources = options.extraSources ?? []; + for (let i = 0, n = extraSources.length; i < n; i++) { + sources.push(new extraSources[i](options)); } - Pace.bar = bar = new Bar; + Pace.bar = bar = new Bar(); scalers = []; - return uniScaler = new Scaler; - })(); + uniScaler = new Scaler(); + }; + + init(); - Pace.stop = function() { + Pace.stop = () => { Pace.trigger('stop'); Pace.running = false; bar.destroy(); cancelAnimation = true; if (animation != null) { - if (typeof cancelAnimationFrame === "function") { - cancelAnimationFrame(animation); - } + cancelAnimationFrame(animation); animation = null; } - return init(); + init(); }; - Pace.restart = function() { + Pace.restart = () => { Pace.trigger('restart'); Pace.stop(); - return Pace.start(); + Pace.start(); }; - Pace.go = function() { - var start; + Pace.go = () => { Pace.running = true; bar.render(); - start = now(); + const start = now(); cancelAnimation = false; - return animation = runAnimation(function(frameTime, enqueueNextFrame) { - var avg, count, done, element, elements, i, j, remaining, scaler, scalerList, sum, _j, _k, _len1, _len2, _ref2; - remaining = 100 - bar.progress; - count = sum = 0; - done = true; - for (i = _j = 0, _len1 = sources.length; _j < _len1; i = ++_j) { - source = sources[i]; - scalerList = scalers[i] != null ? scalers[i] : scalers[i] = []; - elements = (_ref2 = source.elements) != null ? _ref2 : [source]; - for (j = _k = 0, _len2 = elements.length; _k < _len2; j = ++_k) { - element = elements[j]; - scaler = scalerList[j] != null ? scalerList[j] : scalerList[j] = new Scaler(element); + animation = runAnimation((frameTime, enqueueNextFrame) => { + let count = 0; + let sum = 0; + let done = true; + for (let i = 0, n = sources.length; i < n; i++) { + const source = sources[i]; + const scalerList = (scalers[i] ??= []); + const elements = source.elements ?? [source]; + for (let j = 0, m = elements.length; j < m; j++) { + const scaler = (scalerList[j] ??= new Scaler(elements[j])); done &= scaler.done; if (scaler.done) { continue; @@ -947,48 +685,42 @@ sum += scaler.tick(frameTime); } } - avg = sum / count; + const avg = sum / count; bar.update(uniScaler.tick(frameTime, avg)); if (bar.done() || done || cancelAnimation) { bar.update(100); Pace.trigger('done'); - return setTimeout(function() { + return setTimeout(() => { bar.finish(); Pace.running = false; - return Pace.trigger('hide'); + Pace.trigger('hide'); }, Math.max(options.ghostTime, Math.max(options.minTime - (now() - start), 0))); - } else { - return enqueueNextFrame(); } + return enqueueNextFrame(); }); }; - Pace.start = function(_options) { + Pace.start = (_options) => { extend(options, _options); Pace.running = true; try { bar.render(); - } catch (_error) { - NoTargetError = _error; + } catch (error) { + NoTargetError = error; } if (!document.querySelector('.pace')) { - return setTimeout(Pace.start, 50); + setTimeout(Pace.start, 50); } else { Pace.trigger('start'); - return Pace.go(); + Pace.go(); } }; if (typeof define === 'function' && define.amd) { - define(function() { - return Pace; - }); + define(() => Pace); } else if (typeof exports === 'object') { module.exports = Pace; - } else { - if (options.startOnPageLoad) { - Pace.start(); - } + } else if (options.startOnPageLoad) { + Pace.start(); } - -}).call(this); \ No newline at end of file +})(); diff --git a/pace.min.js b/pace.min.js index 6b6be08..7fed67c 100644 --- a/pace.min.js +++ b/pace.min.js @@ -2,4 +2,4 @@ * pace.js v1.3.1 * https://github.com/CodeByZach/pace/ * Licensed MIT © HubSpot, Inc. - */(function(){var O,Y,Q,V,Z,$,ee,C,q,u,te,re,F,ne,se,E,w,ie,g,R,x,X,v,L,oe,U,D,y,ue,d,l,T,I,ae,b,H,P,p,_,W,k,M,z,A,j,le,ce,B,fe,pe,S=[].slice,he={}.hasOwnProperty,ge=function(t,e){for(var r in e)he.call(e,r)&&(t[r]=e[r]);function n(){this.constructor=t}return n.prototype=e.prototype,t.prototype=new n,t.__super__=e.prototype,t},we=[].indexOf||function(t){for(var e=0,r=this.length;e=33?(e=d(),t(n,function(){return T(r)})):setTimeout(r,33-n)},r()},I=function(){var t,e,r;return r=arguments[0],e=arguments[1],t=3<=arguments.length?S.call(arguments,2):[],typeof r[e]=="function"?r[e].apply(r,t):r[e]},v=function(){var t,e,r,n,s,i,o;for(e=arguments[0],n=2<=arguments.length?S.call(arguments,1):[],i=0,o=n.length;i=100?n="99":(n=this.progress<10?"0":"",n+=this.progress|0),e.children[0].setAttribute("data-progress",""+n)),u.trigger("change",this.progress),this.lastRenderedProgress=this.progress},t.prototype.done=function(){return this.progress>=100},t})(),C=(function(){function t(){this.bindings={}}return t.prototype.trigger=function(e,r){var n,s,i,o,a;if(this.bindings[e]!=null){for(o=this.bindings[e],a=[],s=0,i=o.length;s=0)return!0}return!1},te=(function(t){ge(e,t);function e(){var r,n=this;e.__super__.constructor.apply(this,arguments),r=function(s){var i;return i=s.open,s.open=function(o,a,f){return P(o)&&n.trigger("request",{type:o,url:a,request:s}),i.apply(s,arguments)}},window.XMLHttpRequest=function(s){var i;return i=new z(s),r(i),i};try{L(window.XMLHttpRequest,z)}catch(s){}if(M!=null){window.XDomainRequest=function(){var s;return s=new M,r(s),s};try{L(window.XDomainRequest,M)}catch(s){}}if(k!=null&&l.ajax.trackWebSockets){window.WebSocket=function(s,i){var o;return i!=null?o=new k(s,i):o=new k(s),P("socket")&&n.trigger("request",{type:"socket",url:s,protocols:i,request:o}),o};try{L(window.WebSocket,k)}catch(s){}}}return e})(C),j=null,U=function(){return j==null&&(j=new te),j},H=function(t){var e,r,n,s;for(s=l.ajax.ignoreURLs,r=0,n=s.length;re.sampleCount&&o.shift(),r=ie(o),++i>=e.minSamples&&r=100&&(this.done=!0),r===this.last?this.sinceLastUpdate+=e:(this.sinceLastUpdate&&(this.rate=(r-this.last)/this.sinceLastUpdate),this.catchup=(r-this.progress)/l.catchupTime,this.sinceLastUpdate=0,this.last=r),r>this.progress&&(this.progress+=this.catchup*e),n=1-Math.pow(this.progress/100,l.easeFactor),this.progress+=n*this.rate*e,this.progress=Math.min(this.lastProgress+l.maxProgressPerFrame,this.progress),this.progress=Math.max(0,this.progress),this.progress=Math.min(100,this.progress),this.lastProgress=this.progress,this.progress},t})(),_=null,b=null,g=null,W=null,w=null,R=null,u.running=!1,D=function(){if(l.restartOnPushState)return u.restart()},window.history.pushState!=null&&(ce=window.history.pushState,window.history.pushState=function(){return D(),ce.apply(window.history,arguments)}),window.history.replaceState!=null&&(pe=window.history.replaceState,window.history.replaceState=function(){return D(),pe.apply(window.history,arguments)}),re={ajax:O,elements:V,document:Q,eventLag:$},(ue=function(){var t,e,r,n,s,i,o,a;for(u.sources=_=[],i=["ajax","elements","document","eventLag"],e=0,n=i.length;eperformance.now(),I=window.requestAnimationFrame,W=window.cancelAnimationFrame,H=s=>{let e=l();const t=()=>{const r=l()-e;return r>=33?(e=l(),s(r,()=>I(t))):setTimeout(t,33-r)};return t()},L=(s,e,...t)=>typeof s[e]=="function"?s[e].apply(s,t):s[e],y=(s,...e)=>{for(const t of e)if(t)for(const r in t){if(!Object.prototype.hasOwnProperty.call(t,r)||r==="__proto__"||r==="constructor"||r==="prototype")continue;const n=t[r];s[r]!=null&&typeof s[r]=="object"&&n!=null&&typeof n=="object"?y(s[r],n):s[r]=n}return s},X=s=>{let e=0,t=0;for(const r of s)e+=Math.abs(r),t++;return e/t},$=(s="options",e=!0)=>{const t=document.querySelector(`script[data-pace-${s}]`);if(!t)return;const r=t.getAttribute(`data-pace-${s}`);if(!e)return r;try{return JSON.parse(r)}catch(n){console.error("Error parsing inline pace options",n)}},i=window.Pace||{};window.Pace=i,Object.assign(i,{on(s,e,t,r){r??=!1,this.bindings??={},this.bindings[s]??=[],this.bindings[s].push({handler:e,ctx:t,once:r})},once(s,e,t){this.on(s,e,t,!0)},off(s,e){if(this.bindings?.[s]==null)return;if(e==null){delete this.bindings[s];return}let t=0;for(;t=100?t="99":(t=this.progress<10?"0":"",t+=this.progress|0),e.children[0].setAttribute("data-progress",t)}i.trigger("change",this.progress),this.lastRenderedProgress=this.progress}done(){return this.progress>=100}}class D{constructor(){this.bindings={}}trigger(e,t){if(this.bindings[e]!=null)for(const r of this.bindings[e].slice())r.call(this,t)}on(e,t){this.bindings[e]??=[],this.bindings[e].push(t)}}const q=window.XMLHttpRequest,b=window.WebSocket,R=(s,e)=>{for(const t in e.prototype)try{s[t]==null&&typeof e[t]!="function"&&Object.defineProperty(s,t,{get:()=>e.prototype[t],configurable:!0,enumerable:!0})}catch{}},p=[];i.ignore=(s,...e)=>{p.unshift("ignore");const t=s.apply(null,e);return p.shift(),t},i.track=(s,...e)=>{p.unshift("track");const t=s.apply(null,e);return p.shift(),t};const k=s=>{if(s??="GET",p[0]==="track")return"force";if(!p.length&&o.ajax){if(s==="socket"&&o.ajax.trackWebSockets)return!0;if(o.ajax.trackMethods.includes(s.toUpperCase()))return!0}return!1},G=s=>{const e=t=>{const r=t.open;t.open=(...n)=>{const[a,c]=n;return k(a)&&s.trigger("request",{type:a,url:c,request:t}),r.apply(t,n)}};window.XMLHttpRequest=function(t){const r=new q(t);return e(r),r};try{R(window.XMLHttpRequest,q)}catch{}if(o.ajax.trackWebSockets){window.WebSocket=function(t,r){let n;return r!=null?n=new b(t,r):n=new b(t),k("socket")&&s.trigger("request",{type:"socket",url:t,protocols:r,request:n}),n};try{R(window.WebSocket,b)}catch{}}};class J extends D{constructor(){super(),G(this)}}let P=null;const M=()=>(P??=new J,P),v=s=>{const e=o.ajax.ignoreURLs;for(let t=0,r=e.length;t{const{type:e,request:t,url:r}=s;if(!v(r)&&!i.running&&(o.restartOnRequestAfter!==!1||k(e)==="force")){let n=o.restartOnRequestAfter||0;typeof n=="boolean"&&(n=0),setTimeout(()=>{let a;if(e==="socket"?a=t.readyState<1:a=0this.watch(e))}watch({type:e,request:t,url:r}){if(v(r))return;let n;e==="socket"?n=new Y(t,this.complete):n=new K(t,this.complete),this.elements.push(n)}complete(e){this.elements=this.elements.filter(t=>t!==e)}}class K{constructor(e,t){this.progress=0,e.addEventListener("progress",r=>{r.lengthComputable?this.progress=100*r.loaded/r.total:this.progress=this.progress+(100-this.progress)/2},!1);for(const r of["load","abort","timeout","error"])e.addEventListener(r,()=>{t(this),this.progress=100},!1)}}class Y{constructor(e,t){this.progress=0;for(const r of["error","open"])e.addEventListener(r,()=>{t(this),this.progress=100},!1)}}class z{constructor(e){e??={},this.complete=this.complete.bind(this),this.elements=[],e.selectors??=[];const t=e.selectors;for(let r=0,n=t.length;rt!==e)}}class Q{constructor(e,t){this.selector=e,this.completeCallback=t,this.progress=0,this.check()}check(){document.querySelector(this.selector)?this.done():setTimeout(()=>this.check(),o.elements.checkInterval)}done(){this.completeCallback(this),this.completeCallback=null,this.progress=100}}class O{constructor(){this.progress=this.states[document.readyState]??100;const e=document.onreadystatechange;document.onreadystatechange=(...t)=>(this.states[document.readyState]!=null&&(this.progress=this.states[document.readyState]),typeof e=="function"?e.apply(null,t):void 0)}}O.prototype.states={loading:0,interactive:50,complete:100};class V{constructor(e){this.progress=0;let t=0;const r=[];let n=0,a=l();const c=setInterval(()=>{const u=l()-a-50;a=l(),r.push(u),r.length>e.sampleCount&&r.shift(),t=X(r),++n>=e.minSamples&&t=100&&(this.done=!0),t===this.last?this.sinceLastUpdate+=e:(this.sinceLastUpdate&&(this.rate=(t-this.last)/this.sinceLastUpdate),this.catchup=(t-this.progress)/o.catchupTime,this.sinceLastUpdate=0,this.last=t),t>this.progress&&(this.progress+=this.catchup*e);const r=1-Math.pow(this.progress/100,o.easeFactor);return this.progress+=r*this.rate*e,this.progress=Math.min(this.lastProgress+o.maxProgressPerFrame,this.progress),this.progress=Math.max(0,this.progress),this.progress=Math.min(100,this.progress),this.lastProgress=this.progress,this.progress}}let d=null,A=null,h=null,C=null,g=null,S=null;i.running=!1;const j=()=>{o.restartOnPushState&&i.restart()},Z=window.history.pushState;window.history.pushState=(...s)=>(j(),Z.apply(window.history,s));const ee=window.history.replaceState;window.history.replaceState=(...s)=>(j(),ee.apply(window.history,s));const te={ajax:N,elements:z,document:O,eventLag:V},_=()=>{i.sources=d=[];for(const e of["ajax","elements","document","eventLag"])o[e]!==!1&&d.push(new te[e](o[e]));const s=o.extraSources??[];for(let e=0,t=s.length;e{i.trigger("stop"),i.running=!1,h.destroy(),S=!0,g!=null&&(W(g),g=null),_()},i.restart=()=>{i.trigger("restart"),i.stop(),i.start()},i.go=()=>{i.running=!0,h.render();const s=l();S=!1,g=H((e,t)=>{let r=0,n=0,a=!0;for(let u=0,f=d.length;u{h.finish(),i.running=!1,i.trigger("hide")},Math.max(o.ghostTime,Math.max(o.minTime-(l()-s),0)))):t()})},i.start=s=>{y(o,s),i.running=!0;try{h.render()}catch(e){w=e}document.querySelector(".pace")?(i.trigger("start"),i.go()):setTimeout(i.start,50)},typeof define=="function"&&define.amd?define(()=>i):typeof exports=="object"?module.exports=i:o.startOnPageLoad&&i.start()})(); diff --git a/package-lock.json b/package-lock.json index 6a28335..55ccc2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "devDependencies": { "@playwright/test": "1.64.1", "acorn": "8.19.0", + "es-check": "9.8.1", "esbuild": "0.28.2" } }, @@ -456,6 +457,44 @@ "node": ">=18" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@playwright/test": { "version": "1.64.1", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.64.1.tgz", @@ -485,6 +524,128 @@ "node": ">=0.4.0" } }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.35", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.35.tgz", + "integrity": "sha512-GNk8KX52CHqeNKGk8+7tZnQab/2k1t/BgrUHPKNdijzpEhF1saPQZHVKb6m5loSAxB39gyrTYw34Qf9CQ3u1qQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.0.tgz", + "integrity": "sha512-3GSvyjvDI4Dur1Meg2BekJquu5uF+9R9a1+5M1Mde192eZoXbeXjzgOsgqPS2V8D5wrrip0gR5Hf/GhWQ9ZzaA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.23", + "caniuse-lite": "^1.0.30001810", + "electron-to-chromium": "^1.5.427", + "node-releases": "^2.0.55", + "update-browserslist-db": "^1.3.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001823", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001823.tgz", + "integrity": "sha512-TQ5s/djDjNk1axreUW+4rULH+BmdCMLiJkhaXnO5wqivG7tITkSUj4ItIdzqdZHKaXcHAV8dhH3JxOM7/7bwqw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.478", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.478.tgz", + "integrity": "sha512-pftG+ma5Lm8O6/p45bhYT6StBN5ziQymaRzmCZwFl8DwWHKPPD93FdOmP1aqftcepolQYvrcyTLa17kE8Yf+jg==", + "dev": true, + "license": "ISC" + }, + "node_modules/es-check": { + "version": "9.8.1", + "resolved": "https://registry.npmjs.org/es-check/-/es-check-9.8.1.tgz", + "integrity": "sha512-F6bumjRmN+OWpEUh3ewhE/S1ey6cHKGMNXPn0iE2tBnict3O855Uij6UYbuHnLS1E3eILvg61KdH6kHbGi9www==", + "dev": true, + "license": "MIT", + "workspaces": [ + "site" + ], + "dependencies": { + "acorn": "8.18.0", + "browserslist": "4.29.0", + "fast-glob": "^3.3.3" + }, + "bin": { + "es-check": "lib/cli/index.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/es-check/node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/esbuild": { "version": "0.28.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", @@ -527,6 +688,156 @@ "@esbuild/win32-x64": "0.28.2" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz", + "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/node-releases": { + "version": "2.0.63", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.63.tgz", + "integrity": "sha512-6li2QanLsAXpIH2R6j77MzRyvOyrvdTqlKtO4CgBdHGNvN99ZZfyxszHc5o5+IZBWD5u6Hzwg83JoGXmqZNG9Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/playwright": { "version": "1.64.1", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.64.1.tgz", @@ -555,6 +866,106 @@ "engines": { "node": ">=20" } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz", + "integrity": "sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } } } } diff --git a/package.json b/package.json index 9ac2b11..d5daf16 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "scripts": { "build": "node scripts/build.mjs", "test": "npm run test:syntax && npm run test:browsers", - "test:syntax": "acorn --ecma5 --silent pace.js pace.min.js", + "test:syntax": "acorn --ecma2021 --silent pace.js pace.min.js && es-check checkBrowser --checkFeatures --quiet pace.js pace.min.js", "test:browsers": "playwright test" }, "repository": { @@ -47,6 +47,7 @@ "devDependencies": { "@playwright/test": "1.64.1", "acorn": "8.19.0", + "es-check": "9.8.1", "esbuild": "0.28.2" } } diff --git a/scripts/build.mjs b/scripts/build.mjs index 38d4058..c157fc1 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -17,8 +17,11 @@ import { Color } from './color.mjs'; const root = path.resolve(import.meta.dirname, '..'); -// pace.js is ES5, and so is its minified build (as in 1.2.4). -const TARGET = 'es5'; +// The oldest browser versions in .browserslistrc ("baseline 2021 with +// downstream"). esbuild doesn't read Browserslist, so they're listed here: +// https://esbuild.github.io/api/#target. `npm test` checks the minified build +// against .browserslistrc, so the two can't drift apart unnoticed. +const TARGET = ['chrome96', 'edge96', 'firefox95', 'safari15.2', 'ios15.2']; // The 10 theme colors, from the original Gruntfile.coffee `themeColors`. const PALETTE = {