From 72c2503749d9764db95570ba4bad9d77d107caa9 Mon Sep 17 00:00:00 2001 From: anomiex Date: Fri, 5 Nov 2021 14:40:27 +0000 Subject: [PATCH] Use webpack config js package in everything except Jetpack (#21580) * lazy-images: Use the new webpack-config package Mostly as a proof of concept. But I also took the opportunity to clean a few things up: * Name the built JS as ".min.js" like it should be. * Use copy-webpack-plugin to copy the src version of intersection-observer. * Use @wordpress/dependency-extraction-webpack-plugin to handle the cache-buster version in `wp_enqueue_script()`. * connection-ui: Use the new webpack-config package I tried not to change too much in this iteration, but I do note that the new package uses a newer version of @wordpress/browserslist-config than calyspo-build does so it now transpiles without IE11 support. * identity-crisis: Use the new webpack-config package I tried not to change too much in this iteration, but I do note that the new package uses a newer version of @wordpress/browserslist-config than calyspo-build does so it now transpiles without IE11 support. Also I dropped babel-minify-webpack-plugin, as terser that's included with webpack seems to work just as well (and has been updated more recently than 4 years ago). * jitm: Use the new webpack-config package This results in no change to the production build. The development build is no longer actually minified. * backup: Use the new webpack-config package This also reverts the "bring back the "Cloud" icon, the path changed after the Webpack update" bit from #20900 and similar code. The problem was Automattic/wp-calypso#56111, which is not present in the new package. Committed via a GitHub action: https://github.com/Automattic/jetpack/actions/runs/1426089502 --- CHANGELOG.md | 8 + dist/intersection-observer.js | 1 - dist/intersection-observer.min.asset.php | 1 + dist/intersection-observer.min.js | 1 + dist/intersection-observer.src.js | 1015 +--------------------- dist/lazy-images.js | 1 - dist/lazy-images.min.asset.php | 1 + dist/lazy-images.min.js | 1 + package.json | 11 +- src/lazy-images.php | 35 +- webpack.config.js | 56 +- 11 files changed, 70 insertions(+), 1061 deletions(-) delete mode 100644 dist/intersection-observer.js create mode 100644 dist/intersection-observer.min.asset.php create mode 100644 dist/intersection-observer.min.js delete mode 100644 dist/lazy-images.js create mode 100644 dist/lazy-images.min.asset.php create mode 100644 dist/lazy-images.min.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cd9021..a6d35be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.5-alpha] - unreleased + +This is an alpha version! The changes listed here are not final. + +### Changed +- Update webpack build config. + ## [2.0.4] - 2021-11-02 ### Changed - Set `convertDeprecationsToExceptions` true in PHPUnit config. @@ -128,6 +135,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Lazy Images: Move into a package +[2.0.5-alpha]: https://github.com/Automattic/jetpack-lazy-images/compare/v2.0.4...v2.0.5-alpha [2.0.4]: https://github.com/Automattic/jetpack-lazy-images/compare/v2.0.3...v2.0.4 [2.0.3]: https://github.com/Automattic/jetpack-lazy-images/compare/v2.0.2...v2.0.3 [2.0.2]: https://github.com/Automattic/jetpack-lazy-images/compare/v2.0.1...v2.0.2 diff --git a/dist/intersection-observer.js b/dist/intersection-observer.js deleted file mode 100644 index 57928b9..0000000 --- a/dist/intersection-observer.js +++ /dev/null @@ -1 +0,0 @@ -!function(){var t={};!function(){"use strict";if("object"==typeof window)if("IntersectionObserver"in window&&"IntersectionObserverEntry"in window&&"intersectionRatio"in window.IntersectionObserverEntry.prototype)"isIntersecting"in window.IntersectionObserverEntry.prototype||Object.defineProperty(window.IntersectionObserverEntry.prototype,"isIntersecting",{get:function(){return this.intersectionRatio>0}});else{var t=function(t){for(var e=window.document,o=i(e);o;)o=i(e=o.ownerDocument);return e}(),e=[],o=null,n=null;s.prototype.THROTTLE_TIMEOUT=100,s.prototype.POLL_INTERVAL=null,s.prototype.USE_MUTATION_OBSERVER=!0,s._setupCrossOriginUpdater=function(){return o||(o=function(t,o){n=t&&o?l(t,o):{top:0,bottom:0,left:0,right:0,width:0,height:0},e.forEach((function(t){t._checkForIntersections()}))}),o},s._resetCrossOriginUpdater=function(){o=null,n=null},s.prototype.observe=function(t){if(!this._observationTargets.some((function(e){return e.element==t}))){if(!t||1!=t.nodeType)throw new Error("target must be an Element");this._registerInstance(),this._observationTargets.push({element:t,entry:null}),this._monitorIntersections(t.ownerDocument),this._checkForIntersections()}},s.prototype.unobserve=function(t){this._observationTargets=this._observationTargets.filter((function(e){return e.element!=t})),this._unmonitorIntersections(t.ownerDocument),0==this._observationTargets.length&&this._unregisterInstance()},s.prototype.disconnect=function(){this._observationTargets=[],this._unmonitorAllIntersections(),this._unregisterInstance()},s.prototype.takeRecords=function(){var t=this._queuedEntries.slice();return this._queuedEntries=[],t},s.prototype._initThresholds=function(t){var e=t||[0];return Array.isArray(e)||(e=[e]),e.sort().filter((function(t,e,o){if("number"!=typeof t||isNaN(t)||t<0||t>1)throw new Error("threshold must be a number between 0 and 1 inclusively");return t!==o[e-1]}))},s.prototype._parseRootMargin=function(t){var e=(t||"0px").split(/\s+/).map((function(t){var e=/^(-?\d*\.?\d+)(px|%)$/.exec(t);if(!e)throw new Error("rootMargin must be specified in pixels or percent");return{value:parseFloat(e[1]),unit:e[2]}}));return e[1]=e[1]||e[0],e[2]=e[2]||e[0],e[3]=e[3]||e[1],e},s.prototype._monitorIntersections=function(e){var o=e.defaultView;if(o&&-1==this._monitoringDocuments.indexOf(e)){var n=this._checkForIntersections,r=null,s=null;this.POLL_INTERVAL?r=o.setInterval(n,this.POLL_INTERVAL):(h(o,"resize",n,!0),h(e,"scroll",n,!0),this.USE_MUTATION_OBSERVER&&"MutationObserver"in o&&(s=new o.MutationObserver(n)).observe(e,{attributes:!0,childList:!0,characterData:!0,subtree:!0})),this._monitoringDocuments.push(e),this._monitoringUnsubscribes.push((function(){var t=e.defaultView;t&&(r&&t.clearInterval(r),u(t,"resize",n,!0)),u(e,"scroll",n,!0),s&&s.disconnect()}));var c=this.root&&(this.root.ownerDocument||this.root)||t;if(e!=c){var a=i(e);a&&this._monitorIntersections(a.ownerDocument)}}},s.prototype._unmonitorIntersections=function(e){var o=this._monitoringDocuments.indexOf(e);if(-1!=o){var n=this.root&&(this.root.ownerDocument||this.root)||t,r=this._observationTargets.some((function(t){var o=t.element.ownerDocument;if(o==e)return!0;for(;o&&o!=n;){var r=i(o);if((o=r&&r.ownerDocument)==e)return!0}return!1}));if(!r){var s=this._monitoringUnsubscribes[o];if(this._monitoringDocuments.splice(o,1),this._monitoringUnsubscribes.splice(o,1),s(),e!=n){var h=i(e);h&&this._unmonitorIntersections(h.ownerDocument)}}}},s.prototype._unmonitorAllIntersections=function(){var t=this._monitoringUnsubscribes.slice(0);this._monitoringDocuments.length=0,this._monitoringUnsubscribes.length=0;for(var e=0;e=0&&m>=0&&{top:u,bottom:a,left:f,right:d,width:g,height:m}||null),!v)break;_=_&&p(_)}return v}},s.prototype._getRootRect=function(){var e;if(this.root&&!d(this.root))e=c(this.root);else{var o=d(this.root)?this.root:t,n=o.documentElement,i=o.body;e={top:0,left:0,right:n.clientWidth||i.clientWidth,width:n.clientWidth||i.clientWidth,bottom:n.clientHeight||i.clientHeight,height:n.clientHeight||i.clientHeight}}return this._expandRectByRootMargin(e)},s.prototype._expandRectByRootMargin=function(t){var e=this._rootMarginValues.map((function(e,o){return"px"==e.unit?e.value:e.value*(o%2?t.width:t.height)/100})),o={top:t.top-e[0],right:t.right+e[1],bottom:t.bottom+e[2],left:t.left-e[3]};return o.width=o.right-o.left,o.height=o.bottom-o.top,o},s.prototype._hasCrossedThreshold=function(t,e){var o=t&&t.isIntersecting?t.intersectionRatio||0:-1,n=e.isIntersecting?e.intersectionRatio||0:-1;if(o!==n)for(var i=0;i array(), 'version' => '3ca22a168a1e1d85e6101f2960316103'); \ No newline at end of file diff --git a/dist/intersection-observer.min.js b/dist/intersection-observer.min.js new file mode 100644 index 0000000..5fa4e6e --- /dev/null +++ b/dist/intersection-observer.min.js @@ -0,0 +1 @@ +!function(){"use strict";if("object"==typeof window)if("IntersectionObserver"in window&&"IntersectionObserverEntry"in window&&"intersectionRatio"in window.IntersectionObserverEntry.prototype)"isIntersecting"in window.IntersectionObserverEntry.prototype||Object.defineProperty(window.IntersectionObserverEntry.prototype,"isIntersecting",{get:function(){return this.intersectionRatio>0}});else{var t=function(t){for(var e=window.document,o=i(e);o;)o=i(e=o.ownerDocument);return e}(),e=[],o=null,n=null;s.prototype.THROTTLE_TIMEOUT=100,s.prototype.POLL_INTERVAL=null,s.prototype.USE_MUTATION_OBSERVER=!0,s._setupCrossOriginUpdater=function(){return o||(o=function(t,o){n=t&&o?l(t,o):{top:0,bottom:0,left:0,right:0,width:0,height:0},e.forEach((function(t){t._checkForIntersections()}))}),o},s._resetCrossOriginUpdater=function(){o=null,n=null},s.prototype.observe=function(t){if(!this._observationTargets.some((function(e){return e.element==t}))){if(!t||1!=t.nodeType)throw new Error("target must be an Element");this._registerInstance(),this._observationTargets.push({element:t,entry:null}),this._monitorIntersections(t.ownerDocument),this._checkForIntersections()}},s.prototype.unobserve=function(t){this._observationTargets=this._observationTargets.filter((function(e){return e.element!=t})),this._unmonitorIntersections(t.ownerDocument),0==this._observationTargets.length&&this._unregisterInstance()},s.prototype.disconnect=function(){this._observationTargets=[],this._unmonitorAllIntersections(),this._unregisterInstance()},s.prototype.takeRecords=function(){var t=this._queuedEntries.slice();return this._queuedEntries=[],t},s.prototype._initThresholds=function(t){var e=t||[0];return Array.isArray(e)||(e=[e]),e.sort().filter((function(t,e,o){if("number"!=typeof t||isNaN(t)||t<0||t>1)throw new Error("threshold must be a number between 0 and 1 inclusively");return t!==o[e-1]}))},s.prototype._parseRootMargin=function(t){var e=(t||"0px").split(/\s+/).map((function(t){var e=/^(-?\d*\.?\d+)(px|%)$/.exec(t);if(!e)throw new Error("rootMargin must be specified in pixels or percent");return{value:parseFloat(e[1]),unit:e[2]}}));return e[1]=e[1]||e[0],e[2]=e[2]||e[0],e[3]=e[3]||e[1],e},s.prototype._monitorIntersections=function(e){var o=e.defaultView;if(o&&-1==this._monitoringDocuments.indexOf(e)){var n=this._checkForIntersections,r=null,s=null;this.POLL_INTERVAL?r=o.setInterval(n,this.POLL_INTERVAL):(h(o,"resize",n,!0),h(e,"scroll",n,!0),this.USE_MUTATION_OBSERVER&&"MutationObserver"in o&&(s=new o.MutationObserver(n)).observe(e,{attributes:!0,childList:!0,characterData:!0,subtree:!0})),this._monitoringDocuments.push(e),this._monitoringUnsubscribes.push((function(){var t=e.defaultView;t&&(r&&t.clearInterval(r),c(t,"resize",n,!0)),c(e,"scroll",n,!0),s&&s.disconnect()}));var u=this.root&&(this.root.ownerDocument||this.root)||t;if(e!=u){var a=i(e);a&&this._monitorIntersections(a.ownerDocument)}}},s.prototype._unmonitorIntersections=function(e){var o=this._monitoringDocuments.indexOf(e);if(-1!=o){var n=this.root&&(this.root.ownerDocument||this.root)||t,r=this._observationTargets.some((function(t){var o=t.element.ownerDocument;if(o==e)return!0;for(;o&&o!=n;){var r=i(o);if((o=r&&r.ownerDocument)==e)return!0}return!1}));if(!r){var s=this._monitoringUnsubscribes[o];if(this._monitoringDocuments.splice(o,1),this._monitoringUnsubscribes.splice(o,1),s(),e!=n){var h=i(e);h&&this._unmonitorIntersections(h.ownerDocument)}}}},s.prototype._unmonitorAllIntersections=function(){var t=this._monitoringUnsubscribes.slice(0);this._monitoringDocuments.length=0,this._monitoringUnsubscribes.length=0;for(var e=0;e=0&&m>=0&&{top:c,bottom:a,left:f,right:d,width:g,height:m}||null),!v)break;_=_&&p(_)}return v}},s.prototype._getRootRect=function(){var e;if(this.root&&!d(this.root))e=u(this.root);else{var o=d(this.root)?this.root:t,n=o.documentElement,i=o.body;e={top:0,left:0,right:n.clientWidth||i.clientWidth,width:n.clientWidth||i.clientWidth,bottom:n.clientHeight||i.clientHeight,height:n.clientHeight||i.clientHeight}}return this._expandRectByRootMargin(e)},s.prototype._expandRectByRootMargin=function(t){var e=this._rootMarginValues.map((function(e,o){return"px"==e.unit?e.value:e.value*(o%2?t.width:t.height)/100})),o={top:t.top-e[0],right:t.right+e[1],bottom:t.bottom+e[2],left:t.left-e[3]};return o.width=o.right-o.left,o.height=o.bottom-o.top,o},s.prototype._hasCrossedThreshold=function(t,e){var o=t&&t.isIntersecting?t.intersectionRatio||0:-1,n=e.isIntersecting?e.intersectionRatio||0:-1;if(o!==n)for(var i=0;i 0; - } - }); - } - return; -} - -/** - * Returns the embedding frame element, if any. - * @param {!Document} doc - * @return {!Element} - */ -function getFrameElement(doc) { - try { - return doc.defaultView && doc.defaultView.frameElement || null; - } catch (e) { - // Ignore the error. - return null; - } -} - -/** - * A local reference to the root document. - */ -var document = (function(startDoc) { - var doc = startDoc; - var frame = getFrameElement(doc); - while (frame) { - doc = frame.ownerDocument; - frame = getFrameElement(doc); - } - return doc; -})(window.document); - -/** - * An IntersectionObserver registry. This registry exists to hold a strong - * reference to IntersectionObserver instances currently observing a target - * element. Without this registry, instances without another reference may be - * garbage collected. - */ -var registry = []; - -/** - * The signal updater for cross-origin intersection. When not null, it means - * that the polyfill is configured to work in a cross-origin mode. - * @type {function(DOMRect|ClientRect, DOMRect|ClientRect)} - */ -var crossOriginUpdater = null; - -/** - * The current cross-origin intersection. Only used in the cross-origin mode. - * @type {DOMRect|ClientRect} - */ -var crossOriginRect = null; - - -/** - * Creates the global IntersectionObserverEntry constructor. - * https://w3c.github.io/IntersectionObserver/#intersection-observer-entry - * @param {Object} entry A dictionary of instance properties. - * @constructor - */ -function IntersectionObserverEntry(entry) { - this.time = entry.time; - this.target = entry.target; - this.rootBounds = ensureDOMRect(entry.rootBounds); - this.boundingClientRect = ensureDOMRect(entry.boundingClientRect); - this.intersectionRect = ensureDOMRect(entry.intersectionRect || getEmptyRect()); - this.isIntersecting = !!entry.intersectionRect; - - // Calculates the intersection ratio. - var targetRect = this.boundingClientRect; - var targetArea = targetRect.width * targetRect.height; - var intersectionRect = this.intersectionRect; - var intersectionArea = intersectionRect.width * intersectionRect.height; - - // Sets intersection ratio. - if (targetArea) { - // Round the intersection ratio to avoid floating point math issues: - // https://github.com/w3c/IntersectionObserver/issues/324 - this.intersectionRatio = Number((intersectionArea / targetArea).toFixed(4)); - } else { - // If area is zero and is intersecting, sets to 1, otherwise to 0 - this.intersectionRatio = this.isIntersecting ? 1 : 0; - } -} - - -/** - * Creates the global IntersectionObserver constructor. - * https://w3c.github.io/IntersectionObserver/#intersection-observer-interface - * @param {Function} callback The function to be invoked after intersection - * changes have queued. The function is not invoked if the queue has - * been emptied by calling the `takeRecords` method. - * @param {Object=} opt_options Optional configuration options. - * @constructor - */ -function IntersectionObserver(callback, opt_options) { - - var options = opt_options || {}; - - if (typeof callback != 'function') { - throw new Error('callback must be a function'); - } - - if ( - options.root && - options.root.nodeType != 1 && - options.root.nodeType != 9 - ) { - throw new Error('root must be a Document or Element'); - } - - // Binds and throttles `this._checkForIntersections`. - this._checkForIntersections = throttle( - this._checkForIntersections.bind(this), this.THROTTLE_TIMEOUT); - - // Private properties. - this._callback = callback; - this._observationTargets = []; - this._queuedEntries = []; - this._rootMarginValues = this._parseRootMargin(options.rootMargin); - - // Public properties. - this.thresholds = this._initThresholds(options.threshold); - this.root = options.root || null; - this.rootMargin = this._rootMarginValues.map(function(margin) { - return margin.value + margin.unit; - }).join(' '); - - /** @private @const {!Array} */ - this._monitoringDocuments = []; - /** @private @const {!Array} */ - this._monitoringUnsubscribes = []; -} - - -/** - * The minimum interval within which the document will be checked for - * intersection changes. - */ -IntersectionObserver.prototype.THROTTLE_TIMEOUT = 100; - - -/** - * The frequency in which the polyfill polls for intersection changes. - * this can be updated on a per instance basis and must be set prior to - * calling `observe` on the first target. - */ -IntersectionObserver.prototype.POLL_INTERVAL = null; - -/** - * Use a mutation observer on the root element - * to detect intersection changes. - */ -IntersectionObserver.prototype.USE_MUTATION_OBSERVER = true; - - -/** - * Sets up the polyfill in the cross-origin mode. The result is the - * updater function that accepts two arguments: `boundingClientRect` and - * `intersectionRect` - just as these fields would be available to the - * parent via `IntersectionObserverEntry`. This function should be called - * each time the iframe receives intersection information from the parent - * window, e.g. via messaging. - * @return {function(DOMRect|ClientRect, DOMRect|ClientRect)} - */ -IntersectionObserver._setupCrossOriginUpdater = function() { - if (!crossOriginUpdater) { - /** - * @param {DOMRect|ClientRect} boundingClientRect - * @param {DOMRect|ClientRect} intersectionRect - */ - crossOriginUpdater = function(boundingClientRect, intersectionRect) { - if (!boundingClientRect || !intersectionRect) { - crossOriginRect = getEmptyRect(); - } else { - crossOriginRect = convertFromParentRect(boundingClientRect, intersectionRect); - } - registry.forEach(function(observer) { - observer._checkForIntersections(); - }); - }; - } - return crossOriginUpdater; -}; - - -/** - * Resets the cross-origin mode. - */ -IntersectionObserver._resetCrossOriginUpdater = function() { - crossOriginUpdater = null; - crossOriginRect = null; -}; - - -/** - * Starts observing a target element for intersection changes based on - * the thresholds values. - * @param {Element} target The DOM element to observe. - */ -IntersectionObserver.prototype.observe = function(target) { - var isTargetAlreadyObserved = this._observationTargets.some(function(item) { - return item.element == target; - }); - - if (isTargetAlreadyObserved) { - return; - } - - if (!(target && target.nodeType == 1)) { - throw new Error('target must be an Element'); - } - - this._registerInstance(); - this._observationTargets.push({element: target, entry: null}); - this._monitorIntersections(target.ownerDocument); - this._checkForIntersections(); -}; - - -/** - * Stops observing a target element for intersection changes. - * @param {Element} target The DOM element to observe. - */ -IntersectionObserver.prototype.unobserve = function(target) { - this._observationTargets = - this._observationTargets.filter(function(item) { - return item.element != target; - }); - this._unmonitorIntersections(target.ownerDocument); - if (this._observationTargets.length == 0) { - this._unregisterInstance(); - } -}; - - -/** - * Stops observing all target elements for intersection changes. - */ -IntersectionObserver.prototype.disconnect = function() { - this._observationTargets = []; - this._unmonitorAllIntersections(); - this._unregisterInstance(); -}; - - -/** - * Returns any queue entries that have not yet been reported to the - * callback and clears the queue. This can be used in conjunction with the - * callback to obtain the absolute most up-to-date intersection information. - * @return {Array} The currently queued entries. - */ -IntersectionObserver.prototype.takeRecords = function() { - var records = this._queuedEntries.slice(); - this._queuedEntries = []; - return records; -}; - - -/** - * Accepts the threshold value from the user configuration object and - * returns a sorted array of unique threshold values. If a value is not - * between 0 and 1 and error is thrown. - * @private - * @param {Array|number=} opt_threshold An optional threshold value or - * a list of threshold values, defaulting to [0]. - * @return {Array} A sorted list of unique and valid threshold values. - */ -IntersectionObserver.prototype._initThresholds = function(opt_threshold) { - var threshold = opt_threshold || [0]; - if (!Array.isArray(threshold)) threshold = [threshold]; - - return threshold.sort().filter(function(t, i, a) { - if (typeof t != 'number' || isNaN(t) || t < 0 || t > 1) { - throw new Error('threshold must be a number between 0 and 1 inclusively'); - } - return t !== a[i - 1]; - }); -}; - - -/** - * Accepts the rootMargin value from the user configuration object - * and returns an array of the four margin values as an object containing - * the value and unit properties. If any of the values are not properly - * formatted or use a unit other than px or %, and error is thrown. - * @private - * @param {string=} opt_rootMargin An optional rootMargin value, - * defaulting to '0px'. - * @return {Array} An array of margin objects with the keys - * value and unit. - */ -IntersectionObserver.prototype._parseRootMargin = function(opt_rootMargin) { - var marginString = opt_rootMargin || '0px'; - var margins = marginString.split(/\s+/).map(function(margin) { - var parts = /^(-?\d*\.?\d+)(px|%)$/.exec(margin); - if (!parts) { - throw new Error('rootMargin must be specified in pixels or percent'); - } - return {value: parseFloat(parts[1]), unit: parts[2]}; - }); - - // Handles shorthand. - margins[1] = margins[1] || margins[0]; - margins[2] = margins[2] || margins[0]; - margins[3] = margins[3] || margins[1]; - - return margins; -}; - - -/** - * Starts polling for intersection changes if the polling is not already - * happening, and if the page's visibility state is visible. - * @param {!Document} doc - * @private - */ -IntersectionObserver.prototype._monitorIntersections = function(doc) { - var win = doc.defaultView; - if (!win) { - // Already destroyed. - return; - } - if (this._monitoringDocuments.indexOf(doc) != -1) { - // Already monitoring. - return; - } - - // Private state for monitoring. - var callback = this._checkForIntersections; - var monitoringInterval = null; - var domObserver = null; - - // If a poll interval is set, use polling instead of listening to - // resize and scroll events or DOM mutations. - if (this.POLL_INTERVAL) { - monitoringInterval = win.setInterval(callback, this.POLL_INTERVAL); - } else { - addEvent(win, 'resize', callback, true); - addEvent(doc, 'scroll', callback, true); - if (this.USE_MUTATION_OBSERVER && 'MutationObserver' in win) { - domObserver = new win.MutationObserver(callback); - domObserver.observe(doc, { - attributes: true, - childList: true, - characterData: true, - subtree: true - }); - } - } - - this._monitoringDocuments.push(doc); - this._monitoringUnsubscribes.push(function() { - // Get the window object again. When a friendly iframe is destroyed, it - // will be null. - var win = doc.defaultView; - - if (win) { - if (monitoringInterval) { - win.clearInterval(monitoringInterval); - } - removeEvent(win, 'resize', callback, true); - } - - removeEvent(doc, 'scroll', callback, true); - if (domObserver) { - domObserver.disconnect(); - } - }); - - // Also monitor the parent. - var rootDoc = - (this.root && (this.root.ownerDocument || this.root)) || document; - if (doc != rootDoc) { - var frame = getFrameElement(doc); - if (frame) { - this._monitorIntersections(frame.ownerDocument); - } - } -}; - - -/** - * Stops polling for intersection changes. - * @param {!Document} doc - * @private - */ -IntersectionObserver.prototype._unmonitorIntersections = function(doc) { - var index = this._monitoringDocuments.indexOf(doc); - if (index == -1) { - return; - } - - var rootDoc = - (this.root && (this.root.ownerDocument || this.root)) || document; - - // Check if any dependent targets are still remaining. - var hasDependentTargets = - this._observationTargets.some(function(item) { - var itemDoc = item.element.ownerDocument; - // Target is in this context. - if (itemDoc == doc) { - return true; - } - // Target is nested in this context. - while (itemDoc && itemDoc != rootDoc) { - var frame = getFrameElement(itemDoc); - itemDoc = frame && frame.ownerDocument; - if (itemDoc == doc) { - return true; - } - } - return false; - }); - if (hasDependentTargets) { - return; - } - - // Unsubscribe. - var unsubscribe = this._monitoringUnsubscribes[index]; - this._monitoringDocuments.splice(index, 1); - this._monitoringUnsubscribes.splice(index, 1); - unsubscribe(); - - // Also unmonitor the parent. - if (doc != rootDoc) { - var frame = getFrameElement(doc); - if (frame) { - this._unmonitorIntersections(frame.ownerDocument); - } - } -}; - - -/** - * Stops polling for intersection changes. - * @param {!Document} doc - * @private - */ -IntersectionObserver.prototype._unmonitorAllIntersections = function() { - var unsubscribes = this._monitoringUnsubscribes.slice(0); - this._monitoringDocuments.length = 0; - this._monitoringUnsubscribes.length = 0; - for (var i = 0; i < unsubscribes.length; i++) { - unsubscribes[i](); - } -}; - - -/** - * Scans each observation target for intersection changes and adds them - * to the internal entries queue. If new entries are found, it - * schedules the callback to be invoked. - * @private - */ -IntersectionObserver.prototype._checkForIntersections = function() { - if (!this.root && crossOriginUpdater && !crossOriginRect) { - // Cross origin monitoring, but no initial data available yet. - return; - } - - var rootIsInDom = this._rootIsInDom(); - var rootRect = rootIsInDom ? this._getRootRect() : getEmptyRect(); - - this._observationTargets.forEach(function(item) { - var target = item.element; - var targetRect = getBoundingClientRect(target); - var rootContainsTarget = this._rootContainsTarget(target); - var oldEntry = item.entry; - var intersectionRect = rootIsInDom && rootContainsTarget && - this._computeTargetAndRootIntersection(target, targetRect, rootRect); - - var rootBounds = null; - if (!this._rootContainsTarget(target)) { - rootBounds = getEmptyRect(); - } else if (!crossOriginUpdater || this.root) { - rootBounds = rootRect; - } - - var newEntry = item.entry = new IntersectionObserverEntry({ - time: now(), - target: target, - boundingClientRect: targetRect, - rootBounds: rootBounds, - intersectionRect: intersectionRect - }); - - if (!oldEntry) { - this._queuedEntries.push(newEntry); - } else if (rootIsInDom && rootContainsTarget) { - // If the new entry intersection ratio has crossed any of the - // thresholds, add a new entry. - if (this._hasCrossedThreshold(oldEntry, newEntry)) { - this._queuedEntries.push(newEntry); - } - } else { - // If the root is not in the DOM or target is not contained within - // root but the previous entry for this target had an intersection, - // add a new record indicating removal. - if (oldEntry && oldEntry.isIntersecting) { - this._queuedEntries.push(newEntry); - } - } - }, this); - - if (this._queuedEntries.length) { - this._callback(this.takeRecords(), this); - } -}; - - -/** - * Accepts a target and root rect computes the intersection between then - * following the algorithm in the spec. - * TODO(philipwalton): at this time clip-path is not considered. - * https://w3c.github.io/IntersectionObserver/#calculate-intersection-rect-algo - * @param {Element} target The target DOM element - * @param {Object} targetRect The bounding rect of the target. - * @param {Object} rootRect The bounding rect of the root after being - * expanded by the rootMargin value. - * @return {?Object} The final intersection rect object or undefined if no - * intersection is found. - * @private - */ -IntersectionObserver.prototype._computeTargetAndRootIntersection = - function(target, targetRect, rootRect) { - // If the element isn't displayed, an intersection can't happen. - if (window.getComputedStyle(target).display == 'none') return; - - var intersectionRect = targetRect; - var parent = getParentNode(target); - var atRoot = false; - - while (!atRoot && parent) { - var parentRect = null; - var parentComputedStyle = parent.nodeType == 1 ? - window.getComputedStyle(parent) : {}; - - // If the parent isn't displayed, an intersection can't happen. - if (parentComputedStyle.display == 'none') return null; - - if (parent == this.root || parent.nodeType == /* DOCUMENT */ 9) { - atRoot = true; - if (parent == this.root || parent == document) { - if (crossOriginUpdater && !this.root) { - if (!crossOriginRect || - crossOriginRect.width == 0 && crossOriginRect.height == 0) { - // A 0-size cross-origin intersection means no-intersection. - parent = null; - parentRect = null; - intersectionRect = null; - } else { - parentRect = crossOriginRect; - } - } else { - parentRect = rootRect; - } - } else { - // Check if there's a frame that can be navigated to. - var frame = getParentNode(parent); - var frameRect = frame && getBoundingClientRect(frame); - var frameIntersect = - frame && - this._computeTargetAndRootIntersection(frame, frameRect, rootRect); - if (frameRect && frameIntersect) { - parent = frame; - parentRect = convertFromParentRect(frameRect, frameIntersect); - } else { - parent = null; - intersectionRect = null; - } - } - } else { - // If the element has a non-visible overflow, and it's not the - // or element, update the intersection rect. - // Note: and cannot be clipped to a rect that's not also - // the document rect, so no need to compute a new intersection. - var doc = parent.ownerDocument; - if (parent != doc.body && - parent != doc.documentElement && - parentComputedStyle.overflow != 'visible') { - parentRect = getBoundingClientRect(parent); - } - } - - // If either of the above conditionals set a new parentRect, - // calculate new intersection data. - if (parentRect) { - intersectionRect = computeRectIntersection(parentRect, intersectionRect); - } - if (!intersectionRect) break; - parent = parent && getParentNode(parent); - } - return intersectionRect; -}; - - -/** - * Returns the root rect after being expanded by the rootMargin value. - * @return {ClientRect} The expanded root rect. - * @private - */ -IntersectionObserver.prototype._getRootRect = function() { - var rootRect; - if (this.root && !isDoc(this.root)) { - rootRect = getBoundingClientRect(this.root); - } else { - // Use / instead of window since scroll bars affect size. - var doc = isDoc(this.root) ? this.root : document; - var html = doc.documentElement; - var body = doc.body; - rootRect = { - top: 0, - left: 0, - right: html.clientWidth || body.clientWidth, - width: html.clientWidth || body.clientWidth, - bottom: html.clientHeight || body.clientHeight, - height: html.clientHeight || body.clientHeight - }; - } - return this._expandRectByRootMargin(rootRect); -}; - - -/** - * Accepts a rect and expands it by the rootMargin value. - * @param {DOMRect|ClientRect} rect The rect object to expand. - * @return {ClientRect} The expanded rect. - * @private - */ -IntersectionObserver.prototype._expandRectByRootMargin = function(rect) { - var margins = this._rootMarginValues.map(function(margin, i) { - return margin.unit == 'px' ? margin.value : - margin.value * (i % 2 ? rect.width : rect.height) / 100; - }); - var newRect = { - top: rect.top - margins[0], - right: rect.right + margins[1], - bottom: rect.bottom + margins[2], - left: rect.left - margins[3] - }; - newRect.width = newRect.right - newRect.left; - newRect.height = newRect.bottom - newRect.top; - - return newRect; -}; - - -/** - * Accepts an old and new entry and returns true if at least one of the - * threshold values has been crossed. - * @param {?IntersectionObserverEntry} oldEntry The previous entry for a - * particular target element or null if no previous entry exists. - * @param {IntersectionObserverEntry} newEntry The current entry for a - * particular target element. - * @return {boolean} Returns true if a any threshold has been crossed. - * @private - */ -IntersectionObserver.prototype._hasCrossedThreshold = - function(oldEntry, newEntry) { - - // To make comparing easier, an entry that has a ratio of 0 - // but does not actually intersect is given a value of -1 - var oldRatio = oldEntry && oldEntry.isIntersecting ? - oldEntry.intersectionRatio || 0 : -1; - var newRatio = newEntry.isIntersecting ? - newEntry.intersectionRatio || 0 : -1; - - // Ignore unchanged ratios - if (oldRatio === newRatio) return; - - for (var i = 0; i < this.thresholds.length; i++) { - var threshold = this.thresholds[i]; - - // Return true if an entry matches a threshold or if the new ratio - // and the old ratio are on the opposite sides of a threshold. - if (threshold == oldRatio || threshold == newRatio || - threshold < oldRatio !== threshold < newRatio) { - return true; - } - } -}; - - -/** - * Returns whether or not the root element is an element and is in the DOM. - * @return {boolean} True if the root element is an element and is in the DOM. - * @private - */ -IntersectionObserver.prototype._rootIsInDom = function() { - return !this.root || containsDeep(document, this.root); -}; - - -/** - * Returns whether or not the target element is a child of root. - * @param {Element} target The target element to check. - * @return {boolean} True if the target element is a child of root. - * @private - */ -IntersectionObserver.prototype._rootContainsTarget = function(target) { - var rootDoc = - (this.root && (this.root.ownerDocument || this.root)) || document; - return ( - containsDeep(rootDoc, target) && - (!this.root || rootDoc == target.ownerDocument) - ); -}; - - -/** - * Adds the instance to the global IntersectionObserver registry if it isn't - * already present. - * @private - */ -IntersectionObserver.prototype._registerInstance = function() { - if (registry.indexOf(this) < 0) { - registry.push(this); - } -}; - - -/** - * Removes the instance from the global IntersectionObserver registry. - * @private - */ -IntersectionObserver.prototype._unregisterInstance = function() { - var index = registry.indexOf(this); - if (index != -1) registry.splice(index, 1); -}; - - -/** - * Returns the result of the performance.now() method or null in browsers - * that don't support the API. - * @return {number} The elapsed time since the page was requested. - */ -function now() { - return window.performance && performance.now && performance.now(); -} - - -/** - * Throttles a function and delays its execution, so it's only called at most - * once within a given time period. - * @param {Function} fn The function to throttle. - * @param {number} timeout The amount of time that must pass before the - * function can be called again. - * @return {Function} The throttled function. - */ -function throttle(fn, timeout) { - var timer = null; - return function () { - if (!timer) { - timer = setTimeout(function() { - fn(); - timer = null; - }, timeout); - } - }; -} - - -/** - * Adds an event handler to a DOM node ensuring cross-browser compatibility. - * @param {Node} node The DOM node to add the event handler to. - * @param {string} event The event name. - * @param {Function} fn The event handler to add. - * @param {boolean} opt_useCapture Optionally adds the even to the capture - * phase. Note: this only works in modern browsers. - */ -function addEvent(node, event, fn, opt_useCapture) { - if (typeof node.addEventListener == 'function') { - node.addEventListener(event, fn, opt_useCapture || false); - } - else if (typeof node.attachEvent == 'function') { - node.attachEvent('on' + event, fn); - } -} - - -/** - * Removes a previously added event handler from a DOM node. - * @param {Node} node The DOM node to remove the event handler from. - * @param {string} event The event name. - * @param {Function} fn The event handler to remove. - * @param {boolean} opt_useCapture If the event handler was added with this - * flag set to true, it should be set to true here in order to remove it. - */ -function removeEvent(node, event, fn, opt_useCapture) { - if (typeof node.removeEventListener == 'function') { - node.removeEventListener(event, fn, opt_useCapture || false); - } - else if (typeof node.detatchEvent == 'function') { - node.detatchEvent('on' + event, fn); - } -} - - -/** - * Returns the intersection between two rect objects. - * @param {Object} rect1 The first rect. - * @param {Object} rect2 The second rect. - * @return {?Object|?ClientRect} The intersection rect or undefined if no - * intersection is found. - */ -function computeRectIntersection(rect1, rect2) { - var top = Math.max(rect1.top, rect2.top); - var bottom = Math.min(rect1.bottom, rect2.bottom); - var left = Math.max(rect1.left, rect2.left); - var right = Math.min(rect1.right, rect2.right); - var width = right - left; - var height = bottom - top; - - return (width >= 0 && height >= 0) && { - top: top, - bottom: bottom, - left: left, - right: right, - width: width, - height: height - } || null; -} - - -/** - * Shims the native getBoundingClientRect for compatibility with older IE. - * @param {Element} el The element whose bounding rect to get. - * @return {DOMRect|ClientRect} The (possibly shimmed) rect of the element. - */ -function getBoundingClientRect(el) { - var rect; - - try { - rect = el.getBoundingClientRect(); - } catch (err) { - // Ignore Windows 7 IE11 "Unspecified error" - // https://github.com/w3c/IntersectionObserver/pull/205 - } - - if (!rect) return getEmptyRect(); - - // Older IE - if (!(rect.width && rect.height)) { - rect = { - top: rect.top, - right: rect.right, - bottom: rect.bottom, - left: rect.left, - width: rect.right - rect.left, - height: rect.bottom - rect.top - }; - } - return rect; -} - - -/** - * Returns an empty rect object. An empty rect is returned when an element - * is not in the DOM. - * @return {ClientRect} The empty rect. - */ -function getEmptyRect() { - return { - top: 0, - bottom: 0, - left: 0, - right: 0, - width: 0, - height: 0 - }; -} - - -/** - * Ensure that the result has all of the necessary fields of the DOMRect. - * Specifically this ensures that `x` and `y` fields are set. - * - * @param {?DOMRect|?ClientRect} rect - * @return {?DOMRect} - */ -function ensureDOMRect(rect) { - // A `DOMRect` object has `x` and `y` fields. - if (!rect || 'x' in rect) { - return rect; - } - // A IE's `ClientRect` type does not have `x` and `y`. The same is the case - // for internally calculated Rect objects. For the purposes of - // `IntersectionObserver`, it's sufficient to simply mirror `left` and `top` - // for these fields. - return { - top: rect.top, - y: rect.top, - bottom: rect.bottom, - left: rect.left, - x: rect.left, - right: rect.right, - width: rect.width, - height: rect.height - }; -} - - -/** - * Inverts the intersection and bounding rect from the parent (frame) BCR to - * the local BCR space. - * @param {DOMRect|ClientRect} parentBoundingRect The parent's bound client rect. - * @param {DOMRect|ClientRect} parentIntersectionRect The parent's own intersection rect. - * @return {ClientRect} The local root bounding rect for the parent's children. - */ -function convertFromParentRect(parentBoundingRect, parentIntersectionRect) { - var top = parentIntersectionRect.top - parentBoundingRect.top; - var left = parentIntersectionRect.left - parentBoundingRect.left; - return { - top: top, - left: left, - height: parentIntersectionRect.height, - width: parentIntersectionRect.width, - bottom: top + parentIntersectionRect.height, - right: left + parentIntersectionRect.width - }; -} - - -/** - * Checks to see if a parent element contains a child element (including inside - * shadow DOM). - * @param {Node} parent The parent element. - * @param {Node} child The child element. - * @return {boolean} True if the parent node contains the child node. - */ -function containsDeep(parent, child) { - var node = child; - while (node) { - if (node == parent) return true; - - node = getParentNode(node); - } - return false; -} - - -/** - * Gets the parent node of an element or its host element if the parent node - * is a shadow root. - * @param {Node} node The node whose parent to get. - * @return {Node|null} The parent node or null if no parent exists. - */ -function getParentNode(node) { - var parent = node.parentNode; - - if (node.nodeType == /* DOCUMENT */ 9 && node != document) { - // If this node is a document node, look for the embedding frame. - return getFrameElement(node); - } - - // If the parent has element that is assigned through shadow root slot - if (parent && parent.assignedSlot) { - parent = parent.assignedSlot.parentNode - } - - if (parent && parent.nodeType == 11 && parent.host) { - // If the parent is a shadow root, return the host element. - return parent.host; - } - - return parent; -} - -/** - * Returns true if `node` is a Document. - * @param {!Node} node - * @returns {boolean} - */ -function isDoc(node) { - return node && node.nodeType === 9; -} - - -// Exposes the constructors globally. -window.IntersectionObserver = IntersectionObserver; -window.IntersectionObserverEntry = IntersectionObserverEntry; - -}()); +!function(){"use strict";if("object"==typeof window)if("IntersectionObserver"in window&&"IntersectionObserverEntry"in window&&"intersectionRatio"in window.IntersectionObserverEntry.prototype)"isIntersecting"in window.IntersectionObserverEntry.prototype||Object.defineProperty(window.IntersectionObserverEntry.prototype,"isIntersecting",{get:function(){return this.intersectionRatio>0}});else{var t=function(t){for(var e=window.document,o=i(e);o;)o=i(e=o.ownerDocument);return e}(),e=[],o=null,n=null;s.prototype.THROTTLE_TIMEOUT=100,s.prototype.POLL_INTERVAL=null,s.prototype.USE_MUTATION_OBSERVER=!0,s._setupCrossOriginUpdater=function(){return o||(o=function(t,o){n=t&&o?l(t,o):{top:0,bottom:0,left:0,right:0,width:0,height:0},e.forEach((function(t){t._checkForIntersections()}))}),o},s._resetCrossOriginUpdater=function(){o=null,n=null},s.prototype.observe=function(t){if(!this._observationTargets.some((function(e){return e.element==t}))){if(!t||1!=t.nodeType)throw new Error("target must be an Element");this._registerInstance(),this._observationTargets.push({element:t,entry:null}),this._monitorIntersections(t.ownerDocument),this._checkForIntersections()}},s.prototype.unobserve=function(t){this._observationTargets=this._observationTargets.filter((function(e){return e.element!=t})),this._unmonitorIntersections(t.ownerDocument),0==this._observationTargets.length&&this._unregisterInstance()},s.prototype.disconnect=function(){this._observationTargets=[],this._unmonitorAllIntersections(),this._unregisterInstance()},s.prototype.takeRecords=function(){var t=this._queuedEntries.slice();return this._queuedEntries=[],t},s.prototype._initThresholds=function(t){var e=t||[0];return Array.isArray(e)||(e=[e]),e.sort().filter((function(t,e,o){if("number"!=typeof t||isNaN(t)||t<0||t>1)throw new Error("threshold must be a number between 0 and 1 inclusively");return t!==o[e-1]}))},s.prototype._parseRootMargin=function(t){var e=(t||"0px").split(/\s+/).map((function(t){var e=/^(-?\d*\.?\d+)(px|%)$/.exec(t);if(!e)throw new Error("rootMargin must be specified in pixels or percent");return{value:parseFloat(e[1]),unit:e[2]}}));return e[1]=e[1]||e[0],e[2]=e[2]||e[0],e[3]=e[3]||e[1],e},s.prototype._monitorIntersections=function(e){var o=e.defaultView;if(o&&-1==this._monitoringDocuments.indexOf(e)){var n=this._checkForIntersections,r=null,s=null;this.POLL_INTERVAL?r=o.setInterval(n,this.POLL_INTERVAL):(h(o,"resize",n,!0),h(e,"scroll",n,!0),this.USE_MUTATION_OBSERVER&&"MutationObserver"in o&&(s=new o.MutationObserver(n)).observe(e,{attributes:!0,childList:!0,characterData:!0,subtree:!0})),this._monitoringDocuments.push(e),this._monitoringUnsubscribes.push((function(){var t=e.defaultView;t&&(r&&t.clearInterval(r),c(t,"resize",n,!0)),c(e,"scroll",n,!0),s&&s.disconnect()}));var u=this.root&&(this.root.ownerDocument||this.root)||t;if(e!=u){var a=i(e);a&&this._monitorIntersections(a.ownerDocument)}}},s.prototype._unmonitorIntersections=function(e){var o=this._monitoringDocuments.indexOf(e);if(-1!=o){var n=this.root&&(this.root.ownerDocument||this.root)||t,r=this._observationTargets.some((function(t){var o=t.element.ownerDocument;if(o==e)return!0;for(;o&&o!=n;){var r=i(o);if((o=r&&r.ownerDocument)==e)return!0}return!1}));if(!r){var s=this._monitoringUnsubscribes[o];if(this._monitoringDocuments.splice(o,1),this._monitoringUnsubscribes.splice(o,1),s(),e!=n){var h=i(e);h&&this._unmonitorIntersections(h.ownerDocument)}}}},s.prototype._unmonitorAllIntersections=function(){var t=this._monitoringUnsubscribes.slice(0);this._monitoringDocuments.length=0,this._monitoringUnsubscribes.length=0;for(var e=0;e=0&&m>=0&&{top:c,bottom:a,left:f,right:d,width:g,height:m}||null),!v)break;_=_&&p(_)}return v}},s.prototype._getRootRect=function(){var e;if(this.root&&!d(this.root))e=u(this.root);else{var o=d(this.root)?this.root:t,n=o.documentElement,i=o.body;e={top:0,left:0,right:n.clientWidth||i.clientWidth,width:n.clientWidth||i.clientWidth,bottom:n.clientHeight||i.clientHeight,height:n.clientHeight||i.clientHeight}}return this._expandRectByRootMargin(e)},s.prototype._expandRectByRootMargin=function(t){var e=this._rootMarginValues.map((function(e,o){return"px"==e.unit?e.value:e.value*(o%2?t.width:t.height)/100})),o={top:t.top-e[0],right:t.right+e[1],bottom:t.bottom+e[2],left:t.left-e[3]};return o.width=o.right-o.left,o.height=o.bottom-o.top,o},s.prototype._hasCrossedThreshold=function(t,e){var o=t&&t.isIntersecting?t.intersectionRatio||0:-1,n=e.isIntersecting?e.intersectionRatio||0:-1;if(o!==n)for(var i=0;i0;)s(e[0])}function l(t){for(var a=0;a0&&(n.unobserve(i.target),s(i.target))}0===e.length&&n.disconnect()}function c(){if(!t&&(e.length>0||i.length>0)){(t=document.createElement("div")).id="loadingWarning",t.style.fontWeight="bold",t.innerText=jetpackLazyImagesL10n.loading_warning;var n=document.createElement("style");n.innerHTML="#loadingWarning { display: none; }\n@media print {\n#loadingWarning { display: block; }\nbody > #loadingWarning ~ * { display: none !important; }\n}",t.appendChild(n),r.insertBefore(t,r.firstChild)}e.length>0&&o(),t&&alert(jetpackLazyImagesL10n.loading_warning)}function s(t){var n;if(t instanceof HTMLImageElement){var a=t.getAttribute("data-lazy-srcset"),r=t.getAttribute("data-lazy-sizes");t.removeAttribute("data-lazy-srcset"),t.removeAttribute("data-lazy-sizes"),t.removeAttribute("data-lazy-src"),t.classList.add("jetpack-lazy-image--handled"),t.setAttribute("data-lazy-loaded",1),r&&t.setAttribute("sizes",r),a?t.setAttribute("srcset",a):t.removeAttribute("srcset"),t.setAttribute("loading","eager"),i.push(t);var d=e.indexOf(t);d>=0&&e.splice(d,1),t.complete?g.call(t,null):(t.addEventListener("load",g,{once:!0}),t.addEventListener("error",g,{once:!0}));try{n=new Event("jetpack-lazy-loaded-image",{bubbles:!0,cancelable:!0})}catch(o){(n=document.createEvent("Event")).initEvent("jetpack-lazy-loaded-image",!0,!0)}t.dispatchEvent(n)}}function g(){var n=i.indexOf(this);n>=0&&i.splice(n,1),t&&0===e.length&&0===i.length&&(t.parentNode.removeChild(t),t=null)}r&&(r.addEventListener("is.post-load",d),r.addEventListener("jetpack-lazy-images-load",d))};"interactive"===document.readyState||"complete"===document.readyState?t():document.addEventListener("DOMContentLoaded",t);var n=window;for(var a in e)n[a]=e[a];e.__esModule&&Object.defineProperty(n,"__esModule",{value:!0})}(); \ No newline at end of file diff --git a/dist/lazy-images.min.asset.php b/dist/lazy-images.min.asset.php new file mode 100644 index 0000000..1cac1b5 --- /dev/null +++ b/dist/lazy-images.min.asset.php @@ -0,0 +1 @@ + array(), 'version' => '2a2ce39799fd13782a342658d578624a'); \ No newline at end of file diff --git a/dist/lazy-images.min.js b/dist/lazy-images.min.js new file mode 100644 index 0000000..d606a49 --- /dev/null +++ b/dist/lazy-images.min.js @@ -0,0 +1 @@ +!function(){var e=function(){var e,t,n,a={rootMargin:"200px 0px",threshold:.01},i=[];d();var r=document.querySelector("body");function d(){e=[].slice.call(document.querySelectorAll("img.jetpack-lazy-image:not(.jetpack-lazy-image--handled)")),n&&n.disconnect(),"IntersectionObserver"in window?(n=new IntersectionObserver(l,a),e.forEach((function(e){e.getAttribute("data-lazy-loaded")||n.observe(e)})),window.addEventListener("beforeprint",c),window.matchMedia&&window.matchMedia("print").addListener((function(e){e.matches&&c()}))):o()}function o(){for(n&&n.disconnect();e.length>0;)s(e[0])}function l(t){for(var a=0;a0&&(n.unobserve(i.target),s(i.target))}0===e.length&&n.disconnect()}function c(){if(!t&&(e.length>0||i.length>0)){(t=document.createElement("div")).id="loadingWarning",t.style.fontWeight="bold",t.innerText=jetpackLazyImagesL10n.loading_warning;var n=document.createElement("style");n.innerHTML="#loadingWarning { display: none; }\n@media print {\n#loadingWarning { display: block; }\nbody > #loadingWarning ~ * { display: none !important; }\n}",t.appendChild(n),r.insertBefore(t,r.firstChild)}e.length>0&&o(),t&&alert(jetpackLazyImagesL10n.loading_warning)}function s(t){var n;if(t instanceof HTMLImageElement){var a=t.getAttribute("data-lazy-srcset"),r=t.getAttribute("data-lazy-sizes");t.removeAttribute("data-lazy-srcset"),t.removeAttribute("data-lazy-sizes"),t.removeAttribute("data-lazy-src"),t.classList.add("jetpack-lazy-image--handled"),t.setAttribute("data-lazy-loaded",1),r&&t.setAttribute("sizes",r),a?t.setAttribute("srcset",a):t.removeAttribute("srcset"),t.setAttribute("loading","eager"),i.push(t);var d=e.indexOf(t);d>=0&&e.splice(d,1),t.complete?g.call(t,null):(t.addEventListener("load",g,{once:!0}),t.addEventListener("error",g,{once:!0}));try{n=new Event("jetpack-lazy-loaded-image",{bubbles:!0,cancelable:!0})}catch(e){(n=document.createEvent("Event")).initEvent("jetpack-lazy-loaded-image",!0,!0)}t.dispatchEvent(n)}}function g(){var n=i.indexOf(this);n>=0&&i.splice(n,1),t&&0===e.length&&0===i.length&&(t.parentNode.removeChild(t),t=null)}r&&(r.addEventListener("is.post-load",d),r.addEventListener("jetpack-lazy-images-load",d))};"interactive"===document.readyState||"complete"===document.readyState?e():document.addEventListener("DOMContentLoaded",e)}(); \ No newline at end of file diff --git a/package.json b/package.json index 4ed976b..fc00b64 100644 --- a/package.json +++ b/package.json @@ -16,20 +16,17 @@ ], "scripts": { "build": "pnpm run install-if-deps-outdated && pnpm run clean && pnpm run build-js", - "build-js": "calypso-build && cp ./node_modules/intersection-observer/intersection-observer.js ./dist/intersection-observer.src.js", + "build-js": "webpack", "build-production": "pnpm run distclean && pnpm run install-if-deps-outdated && pnpm run build-production-js", "build-production-js": "NODE_ENV=production BABEL_ENV=production pnpm run build-js", "clean": "rm -rf dist", "distclean": "rm -rf node_modules && pnpm run clean", "install-if-deps-outdated": "pnpm install --no-prod --frozen-lockfile" }, - "dependencies": { - "intersection-observer": "0.12.0" - }, "devDependencies": { - "@automattic/calypso-build": "9.0.0", - "@wordpress/browserslist-config": "4.1.0", - "eslint": "7.32.0", + "@automattic/jetpack-webpack-config": "workspace:^0.1.0-alpha", + "copy-webpack-plugin": "9.0.1", + "intersection-observer": "0.12.0", "webpack": "5.51.1" } } diff --git a/src/lazy-images.php b/src/lazy-images.php index 59e5567..45386ab 100644 --- a/src/lazy-images.php +++ b/src/lazy-images.php @@ -32,16 +32,6 @@ */ class Jetpack_Lazy_Images { - /** - * The assets version. - * - * @since 1.0.0 - * @since-jetpack 8.8.0 - * - * @var string Assets version. - */ - const ASSETS_VERSION = '1.1.3'; - /** * Class instance. * @@ -495,18 +485,31 @@ private static function build_attributes_string( $attributes ) { * @return void */ public function enqueue_assets() { + $script_path = Assets::get_file_url_for_environment( '../dist/intersection-observer.min.js', '../dist/intersection-observer.src.js', __FILE__ ); + $script_asset_path = '../dist/intersection-observer.min.assets.php'; + $script_asset = file_exists( $script_asset_path ) ? require $script_asset_path : array( + 'dependencies' => array(), + 'version' => filemtime( __DIR__ . '/../dist/intersection-observer.min.js' ), + ); wp_enqueue_script( 'jetpack-lazy-images-polyfill-intersectionobserver', - Assets::get_file_url_for_environment( '../dist/intersection-observer.js', '../dist/intersection-observer.src.js', __FILE__ ), - array(), - self::ASSETS_VERSION, + $script_path, + $script_asset['dependencies'], + $script_asset['version'], true ); + + $script_path = Assets::get_file_url_for_environment( '../dist/lazy-images.min.js', 'js/lazy-images.js', __FILE__ ); + $script_asset_path = '../dist/lazy-images.min.assets.php'; + $script_asset = file_exists( $script_asset_path ) ? require $script_asset_path : array( + 'dependencies' => array(), + 'version' => filemtime( __DIR__ . '/../dist/lazy-images.min.js' ), + ); wp_enqueue_script( 'jetpack-lazy-images', - Assets::get_file_url_for_environment( '../dist/lazy-images.js', 'js/lazy-images.js', __FILE__ ), - array( 'jetpack-lazy-images-polyfill-intersectionobserver' ), - self::ASSETS_VERSION, + $script_path, + array_merge( $script_asset['dependencies'], array( 'jetpack-lazy-images-polyfill-intersectionobserver' ) ), + $script_asset['version'], true ); wp_localize_script( diff --git a/webpack.config.js b/webpack.config.js index 4b35a3e..4d5d2bd 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,31 +1,43 @@ -/** - * External dependencies - */ -const getBaseWebpackConfig = require( '@automattic/calypso-build/webpack.config.js' ); +const jetpackWebpackConfig = require( '@automattic/jetpack-webpack-config/webpack' ); const path = require( 'path' ); - -const baseConfig = getBaseWebpackConfig( - { WP: false }, - { - entry: {}, // We'll override later - 'output-filename': '[name].js', - 'output-path': path.join( __dirname, './dist' ), - } -); +const CopyWebpackPlugin = require( 'copy-webpack-plugin' ); module.exports = [ { - ...baseConfig, + entry: { + 'lazy-images': './src/js/lazy-images.js', + 'intersection-observer': require.resolve( 'intersection-observer/intersection-observer.js' ), + }, + mode: jetpackWebpackConfig.mode, + devtool: jetpackWebpackConfig.devtool, + output: { + ...jetpackWebpackConfig.output, + path: path.resolve( './dist' ), + }, + optimization: { + ...jetpackWebpackConfig.optimization, + }, resolve: { - ...baseConfig.resolve, - modules: [ 'node_modules' ], + ...jetpackWebpackConfig.resolve, }, - entry: { - 'lazy-images': path.join( __dirname, './src/js/lazy-images.js' ), - 'intersection-observer': path.join( - __dirname, - './node_modules/intersection-observer/intersection-observer.js' - ), + node: false, + plugins: [ + ...jetpackWebpackConfig.StandardPlugins(), + new CopyWebpackPlugin( { + patterns: [ + { + from: require.resolve( 'intersection-observer/intersection-observer.js' ), + to: 'intersection-observer.src.js', + }, + ], + } ), + ], + module: { + strictExportPresence: true, + rules: [ + // Transpile JavaScript, including node_modules. + jetpackWebpackConfig.TranspileRule(), + ], }, }, ];