@automattic/newspack-blocks 4.33.0 → 4.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## @automattic/newspack-blocks [4.33.1](https://github.com/Automattic/newspack-workspace/compare/newspack-blocks@4.33.0...newspack-blocks@4.33.1) (2026-09-21)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **iframe:** stop lazy-loaded embeds loading the page inside them ([#1115](https://github.com/Automattic/newspack-workspace/issues/1115)) ([bb97d4c](https://github.com/Automattic/newspack-workspace/commit/bb97d4c46864b3260f24b22690bb570eaf91e404))
7
+
1
8
  # @automattic/newspack-blocks [4.33.0](https://github.com/Automattic/newspack-workspace/compare/newspack-blocks@4.32.1...newspack-blocks@4.33.0) (2026-09-18)
2
9
 
3
10
 
@@ -1 +1 @@
1
- <?php return array('dependencies' => array('wp-dom-ready'), 'version' => '0adcb9c939693718d723');
1
+ <?php return array('dependencies' => array('wp-dom-ready'), 'version' => '99e53b29d2f8cbe6ee9e');
@@ -1 +1 @@
1
- (()=>{"use strict";var e={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},d:(t,n)=>{for(var a in n)e.o(n,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:n[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.wp.domReady;e.n(t)()(()=>{Array.from(document.querySelectorAll(".wp-block-newspack-blocks-iframe iframe")).forEach(e=>{let t=0;const n=setInterval(()=>{!(e=>{const t=e.contentDocument;return null!==t&&"about:blank"===t.URL})(e)||t>=10?clearInterval(n):(t++,e.contentWindow.location.replace(e.src))},2e3);window.addEventListener("message",function(t){if(t.origin!==new URL(e.src).origin||e.contentWindow!==t.source)return;let n=0;t.data&&t.data.height&&("number"==typeof t.data.height?n=t.data.height:"string"==typeof t.data.height&&(n=Number(t.data.height))),!isNaN(n)&&n>0&&(e.parentElement&&"auto"!==e.parentElement.style.height&&(e.parentElement.style.height="auto"),e.style.height=n+"px")})})})})();
1
+ (()=>{"use strict";var e={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.wp.domReady;e.n(t)()(()=>{Array.from(document.querySelectorAll(".wp-block-newspack-blocks-iframe iframe")).forEach(e=>{let t=0;const n=setInterval(()=>{!(e=>Boolean(e.getAttribute("src")))(e)||!(e=>{const t=e.contentDocument;return null!==t&&"about:blank"===t.URL})(e)||t>=10?clearInterval(n):(t++,e.contentWindow.location.replace(e.src))},2e3);window.addEventListener("message",function(t){if(t.origin!==new URL(e.src).origin||e.contentWindow!==t.source)return;let n=0;t.data&&t.data.height&&("number"==typeof t.data.height?n=t.data.height:"string"==typeof t.data.height&&(n=Number(t.data.height))),!isNaN(n)&&n>0&&(e.parentElement&&"auto"!==e.parentElement.style.height&&(e.parentElement.style.height="auto"),e.style.height=n+"px")})})})})();
@@ -7,7 +7,7 @@
7
7
  * Author URI: https://newspack.com/
8
8
  * Text Domain: newspack-blocks
9
9
  * Domain Path: /languages
10
- * Version: 4.33.0
10
+ * Version: 4.33.1
11
11
  *
12
12
  * @package Newspack_Blocks
13
13
  */
@@ -15,7 +15,7 @@
15
15
  define( 'NEWSPACK_BLOCKS__PLUGIN_FILE', __FILE__ );
16
16
  define( 'NEWSPACK_BLOCKS__BLOCKS_DIRECTORY', 'dist/' );
17
17
  define( 'NEWSPACK_BLOCKS__PLUGIN_DIR', plugin_dir_path( NEWSPACK_BLOCKS__PLUGIN_FILE ) );
18
- define( 'NEWSPACK_BLOCKS__VERSION', '4.33.0' );
18
+ define( 'NEWSPACK_BLOCKS__VERSION', '4.33.1' );
19
19
 
20
20
  require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks.php';
21
21
  require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks-api.php';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/newspack-blocks",
3
- "version": "4.33.0",
3
+ "version": "4.33.1",
4
4
  "author": "Automattic",
5
5
  "description": "=== Newspack Blocks === Contributors: (this should be a list of wordpress.org userid's) Donate link: https://example.com/ Tags: comments, spam Requires at least: 4.5 Tested up to: 5.1.1 Stable tag: 0.1.0 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html",
6
6
  "repository": {
@@ -26,6 +26,18 @@ const isStillBlank = iframe => {
26
26
  return doc !== null && doc.URL === 'about:blank';
27
27
  };
28
28
 
29
+ /**
30
+ * Whether the frame has an address of its own to retry. A lazy loader can hold it
31
+ * back until the frame nears the viewport (perfmatters moves it to data-src). With
32
+ * no src, iframe.src is '', which location.replace() resolves to this page, and an
33
+ * empty src attribute reads back as this page's URL. Either way a retry would load
34
+ * the page inside its own frame, where this script runs again on the copy's frames.
35
+ *
36
+ * @param {HTMLIFrameElement} iframe The iframe.
37
+ * @return {boolean} Whether the frame has a src to load.
38
+ */
39
+ const hasOwnSrc = iframe => Boolean( iframe.getAttribute( 'src' ) );
40
+
29
41
  /**
30
42
  * Re-navigations before giving up on a frame that never loads. A 204 resolves in a
31
43
  * retry or two; without a bound, a permanently blank embed keeps requesting for as
@@ -39,10 +51,11 @@ domReady( () => {
39
51
  // Don't wait for the load event: it may have fired before this script ran
40
52
  // (delayed JS). Navigate with location.replace(), since resetting src on a
41
53
  // loaded frame adds a history entry and makes readers press Back twice
42
- // (NPPM-3180).
54
+ // (NPPM-3180). The src check runs on each tick rather than once here, so a
55
+ // frame a lazy loader fills in before the first tick still gets its retries.
43
56
  let attempts = 0;
44
57
  const retry = setInterval( () => {
45
- if ( ! isStillBlank( iframe ) || attempts >= MAX_RETRIES ) {
58
+ if ( ! hasOwnSrc( iframe ) || ! isStillBlank( iframe ) || attempts >= MAX_RETRIES ) {
46
59
  clearInterval( retry );
47
60
  return;
48
61
  }
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * The iframe block's retry (NPPM-3180) must leave a frame that already holds a
3
- * document alone, and must never reset `src`, which adds a history entry.
3
+ * document alone, must never reset `src`, which adds a history entry, and must
4
+ * never navigate a frame with no src of its own, which would load the page inside it.
4
5
  */
5
6
 
6
7
  const SRC = 'https://embed.example.test/widget';
@@ -14,10 +15,12 @@ const SRC = 'https://embed.example.test/widget';
14
15
  * null once a cross-origin document has loaded.
15
16
  * A detached frame reports null, as does its
16
17
  * contentWindow.
18
+ * @param {string} attributes The frame's markup attributes. A lazy loader may have
19
+ * moved the address out of src.
17
20
  * @return {Object} The iframe, its state holder, and the `replace` and `setSrc` spies.
18
21
  */
19
- function renderIframe( contentDocument ) {
20
- document.body.innerHTML = `<figure class="wp-block-newspack-blocks-iframe"><div class="wp-block-embed__wrapper"><iframe src="${ SRC }"></iframe></div></figure>`;
22
+ function renderIframe( contentDocument, attributes = `src="${ SRC }"` ) {
23
+ document.body.innerHTML = `<figure class="wp-block-newspack-blocks-iframe"><div class="wp-block-embed__wrapper"><iframe ${ attributes }></iframe></div></figure>`;
21
24
  const iframe = document.querySelector( 'iframe' );
22
25
  const state = { contentDocument };
23
26
  const replace = jest.fn();
@@ -25,7 +28,12 @@ function renderIframe( contentDocument ) {
25
28
  const contentWindow = { location: { replace } };
26
29
  Object.defineProperty( iframe, 'contentDocument', { configurable: true, get: () => ( iframe.isConnected ? state.contentDocument : null ) } );
27
30
  Object.defineProperty( iframe, 'contentWindow', { configurable: true, get: () => ( iframe.isConnected ? contentWindow : null ) } );
28
- Object.defineProperty( iframe, 'src', { configurable: true, get: () => SRC, set: setSrc } );
31
+ // Read src back as a browser does: '' with no attribute, otherwise the value resolved against the page.
32
+ Object.defineProperty( iframe, 'src', {
33
+ configurable: true,
34
+ get: () => ( iframe.hasAttribute( 'src' ) ? new URL( iframe.getAttribute( 'src' ), document.baseURI ).href : '' ),
35
+ set: setSrc,
36
+ } );
29
37
  jest.isolateModules( () => require( './view' ) );
30
38
  return { iframe, state, replace, setSrc };
31
39
  }
@@ -73,6 +81,26 @@ describe( 'iframe block view script', () => {
73
81
  expect( setSrc ).not.toHaveBeenCalled();
74
82
  } );
75
83
 
84
+ it.each( [
85
+ // perfmatters' markup: the address waits in data-src until the frame nears the viewport.
86
+ [ 'no src', `class="perfmatters-lazy" data-src="${ SRC }"` ],
87
+ [ 'an empty src', 'src=""' ],
88
+ ] )( 'never navigates a blank frame with %s, which would load this page inside it', ( _, attributes ) => {
89
+ const { replace, setSrc } = renderIframe( { URL: 'about:blank' }, attributes );
90
+ jest.advanceTimersByTime( 20000 );
91
+ expect( replace ).not.toHaveBeenCalled();
92
+ expect( setSrc ).not.toHaveBeenCalled();
93
+ expect( jest.getTimerCount() ).toBe( 0 );
94
+ } );
95
+
96
+ it( 'retries a lazy-loaded frame that has its src by the first check', () => {
97
+ const { iframe, replace } = renderIframe( { URL: 'about:blank' }, `class="perfmatters-lazy" data-src="${ SRC }"` );
98
+ // The lazy loader copies data-src into src as the frame nears the viewport.
99
+ iframe.setAttribute( 'src', SRC );
100
+ jest.advanceTimersByTime( 2000 );
101
+ expect( replace ).toHaveBeenCalledWith( SRC );
102
+ } );
103
+
76
104
  it( 'gives up after 10 attempts on a frame that never loads', () => {
77
105
  const { replace } = renderIframe( { URL: 'about:blank' } );
78
106
  jest.advanceTimersByTime( 20000 );
@@ -3,7 +3,7 @@
3
3
  'name' => 'automattic/newspack-blocks',
4
4
  'pretty_version' => 'dev-main',
5
5
  'version' => 'dev-main',
6
- 'reference' => 'f5456bae41f1968ab4928044aa8c079c93a4ea82',
6
+ 'reference' => 'bb97d4c46864b3260f24b22690bb570eaf91e404',
7
7
  'type' => 'wordpress-plugin',
8
8
  'install_path' => __DIR__ . '/../../',
9
9
  'aliases' => array(),
@@ -13,7 +13,7 @@
13
13
  'automattic/newspack-blocks' => array(
14
14
  'pretty_version' => 'dev-main',
15
15
  'version' => 'dev-main',
16
- 'reference' => 'f5456bae41f1968ab4928044aa8c079c93a4ea82',
16
+ 'reference' => 'bb97d4c46864b3260f24b22690bb570eaf91e404',
17
17
  'type' => 'wordpress-plugin',
18
18
  'install_path' => __DIR__ . '/../../',
19
19
  'aliases' => array(),