Skip to content

Commit

Permalink
Iframe: calc compat styles once per page load (#57798)
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix authored Jan 16, 2024
1 parent 45eb9a5 commit 33b6e64
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 125 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
let compatibilityStyles = null;

/**
* Returns a list of stylesheets that target the editor canvas. A stylesheet is
* considered targetting the editor a canvas if it contains the
* `editor-styles-wrapper`, `wp-block`, or `wp-block-*` class selectors.
*
* Ideally, this hook should be removed in the future and styles should be added
* explicitly as editor styles.
*/
export function getCompatibilityStyles() {
if ( compatibilityStyles ) {
return compatibilityStyles;
}

// Only memoize the result once on load, since these stylesheets should not
// change.
compatibilityStyles = Array.from( document.styleSheets ).reduce(
( accumulator, styleSheet ) => {
try {
// May fail for external styles.
// eslint-disable-next-line no-unused-expressions
styleSheet.cssRules;
} catch ( e ) {
return accumulator;
}

const { ownerNode, cssRules } = styleSheet;

// Stylesheet is added by another stylesheet. See
// https://developer.mozilla.org/en-US/docs/Web/API/StyleSheet/ownerNode#notes.
if ( ownerNode === null ) {
return accumulator;
}

if ( ! cssRules ) {
return accumulator;
}

// Don't try to add the reset styles, which were removed as a dependency
// from `edit-blocks` for the iframe since we don't need to reset admin
// styles.
if ( ownerNode.id === 'wp-reset-editor-styles-css' ) {
return accumulator;
}

// Don't try to add styles without ID. Styles enqueued via the WP dependency system will always have IDs.
if ( ! ownerNode.id ) {
return accumulator;
}

function matchFromRules( _cssRules ) {
return Array.from( _cssRules ).find(
( {
selectorText,
conditionText,
cssRules: __cssRules,
} ) => {
// If the rule is conditional then it will not have selector text.
// Recurse into child CSS ruleset to determine selector eligibility.
if ( conditionText ) {
return matchFromRules( __cssRules );
}

return (
selectorText &&
( selectorText.includes(
'.editor-styles-wrapper'
) ||
selectorText.includes( '.wp-block' ) )
);
}
);
}

if ( matchFromRules( cssRules ) ) {
const isInline = ownerNode.tagName === 'STYLE';

if ( isInline ) {
// If the current target is inline,
// it could be a dependency of an existing stylesheet.
// Look for that dependency and add it BEFORE the current target.
const mainStylesCssId = ownerNode.id.replace(
'-inline-css',
'-css'
);
const mainStylesElement =
document.getElementById( mainStylesCssId );
if ( mainStylesElement ) {
accumulator.push( mainStylesElement.cloneNode( true ) );
}
}

accumulator.push( ownerNode.cloneNode( true ) );

if ( ! isInline ) {
// If the current target is not inline,
// we still look for inline styles that could be relevant for the current target.
// If they exist, add them AFTER the current target.
const inlineStylesCssId = ownerNode.id.replace(
'-css',
'-inline-css'
);
const inlineStylesElement =
document.getElementById( inlineStylesCssId );
if ( inlineStylesElement ) {
accumulator.push(
inlineStylesElement.cloneNode( true )
);
}
}
}

return accumulator;
},
[]
);

return compatibilityStyles;
}
5 changes: 2 additions & 3 deletions packages/block-editor/src/components/iframe/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { useSelect } from '@wordpress/data';
*/
import { useBlockSelectionClearer } from '../block-selection-clearer';
import { useWritingFlow } from '../writing-flow';
import { useCompatibilityStyles } from './use-compatibility-styles';
import { getCompatibilityStyles } from './get-compatibility-styles';
import { store as blockEditorStore } from '../../store';

function bubbleEvent( event, Constructor, frame ) {
Expand Down Expand Up @@ -121,7 +121,6 @@ function Iframe( {
const { styles = '', scripts = '' } = resolvedAssets;
const [ iframeDocument, setIframeDocument ] = useState();
const [ bodyClasses, setBodyClasses ] = useState( [] );
const compatStyles = useCompatibilityStyles();
const clearerRef = useBlockSelectionClearer();
const [ before, writingFlowRef, after ] = useWritingFlow();
const [ contentResizeListener, { height: contentHeight } ] =
Expand Down Expand Up @@ -156,7 +155,7 @@ function Iframe( {

contentDocument.dir = ownerDocument.dir;

for ( const compatStyle of compatStyles ) {
for ( const compatStyle of getCompatibilityStyles() ) {
if ( contentDocument.getElementById( compatStyle.id ) ) {
continue;
}
Expand Down

This file was deleted.

0 comments on commit 33b6e64

Please sign in to comment.