Skip to content

Commit

Permalink
Also patch the Gutenberg plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
adamziel committed Oct 9, 2023
1 parent adee636 commit 3bd1580
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 38 deletions.
99 changes: 61 additions & 38 deletions packages/playground/blueprints/src/lib/steps/install-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export const installPlugin: StepHandler<InstallPluginStep<File>> = async (
);
}

await maybeApplyGutenbergPatch(playground);
await applyGutenbergPatchOnce(playground);
} catch (error) {
console.error(
`Proceeding without the ${zipNiceName} plugin. Could not install it in wp-admin. ` +
Expand All @@ -93,64 +93,87 @@ export const installPlugin: StepHandler<InstallPluginStep<File>> = async (
}
};

async function maybeApplyGutenbergPatch(playground: UniversalPHP) {
async function applyGutenbergPatchOnce(playground: UniversalPHP) {
/**
* The patch below is no longer necessary as it's been fixed upstream:
* Ensures the block editor iframe is controlled by the playground
* service worker. Tl;dr it must use a HTTP URL as its src, not a
* data URL, blob URL, or a srcDoc like it does by default.
*
* https://github.com/WordPress/gutenberg/pull/50875
* @see https://github.com/WordPress/wordpress-playground/pull/668
*
* It can be removed in the next few WordPress releases.
*
* ---
*
* Pair the site editor's nested iframe to the Service Worker.
*
* Without the patch below, the site editor initiates network requests that
* aren't routed through the service worker. That's a known browser issue:
*
* * https://bugs.chromium.org/p/chromium/issues/detail?id=880768
* * https://bugzilla.mozilla.org/show_bug.cgi?id=1293277
* * https://github.com/w3c/ServiceWorker/issues/765
*
* The problem with iframes using srcDoc and src="about:blank" as they
* fail to inherit the root site's service worker.
*
* Gutenberg loads the site editor using <iframe srcDoc="<!doctype html">
* to force the standards mode and not the quirks mode:
*
* https://github.com/WordPress/gutenberg/pull/38855
*
* This commit patches the site editor to achieve the same result via
* <iframe src="/doctype.html"> and a doctype.html file containing just
* `<!doctype html>`. This allows the iframe to inherit the service worker
* and correctly load all the css, js, fonts, images, and other assets.
*
* Ideally this issue would be fixed directly in Gutenberg and the patch
* below would be removed.
*
* See https://github.com/WordPress/wordpress-playground/issues/42 for more details
* The code below repeated in the WordPress bundler in
* compile-wordpress/build-assets/controlled-iframe.js.
*/

if (
(await playground.isDir('/wordpress/wp-content/plugins/gutenberg')) &&
!(await playground.fileExists('/wordpress/.gutenberg-patched'))
) {
const controlledIframe = `
/**
* A synchronous function to read a blob URL as text.
*
* @param {string} url
* @returns {string}
*/
const __playground_readBlobAsText = function (url) {
try {
let xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.overrideMimeType('text/plain;charset=utf-8');
xhr.send();
return xhr.responseText;
} catch(e) {
return '';
} finally {
URL.revokeObjectURL(url);
}
}
window.__playground_ControlledIframe = window.wp.element.forwardRef(function (props, ref) {
const source = window.wp.element.useMemo(function () {
if (props.srcDoc) {
// WordPress <= 6.2 uses a srcDoc that only contains a doctype.
return '/wp-includes/empty.html';
} else if (props.src && props.src.startsWith('blob:')) {
// WordPress 6.3 uses a blob URL with doctype and a list of static assets.
// Let's pass the document content to empty.html and render it there.
return '/wp-includes/empty.html#' + encodeURIComponent(__playground_readBlobAsText(props.src));
} else {
// WordPress >= 6.4 uses a plain HTTPS URL that needs no correction.
return props.src;
}
}, [props.src]);
return (
window.wp.element.createElement('iframe', {
...props,
ref: ref,
src: source,
// Make sure there's no srcDoc, as it would interfere with the src.
srcDoc: undefined
})
)
});`;

await playground.writeFile('/wordpress/.gutenberg-patched', '1');
await updateFile(
playground,
`/wordpress/wp-content/plugins/gutenberg/build/block-editor/index.js`,
(contents) =>
controlledIframe +
contents.replace(
/srcDoc:("[^"]+"|[^,]+)/g,
'src:"/wp-includes/empty.html"'
/\(\s*"iframe",/g,
'(window.__playground_ControlledIframe,'
)
);
await updateFile(
playground,
`/wordpress/wp-content/plugins/gutenberg/build/block-editor/index.min.js`,
(contents) =>
controlledIframe +
contents.replace(
/srcDoc:("[^"]+"|[^,]+)/g,
'src:"/wp-includes/empty.html"'
/\(\s*"iframe",/g,
'(window.__playground_ControlledIframe,'
)
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
/**
* Ensures the block editor iframe is controlled by the playground
* service worker. The block-editor.js is patched to use `__playground_ControlledIframe`
* instead of the plain HTML iframe element.
*
* @see https://github.com/WordPress/wordpress-playground/pull/668
* @see https://github.com/WordPress/wordpress-playground/issues/42
*
* This code is repeated in the Gutenberg plugin patcher in
* playground/blueprints/src/lib/steps/install-plugin.ts
*/

/**
* A synchronous function to read a blob URL as text.
*
Expand Down

0 comments on commit 3bd1580

Please sign in to comment.