Skip to content

Commit

Permalink
Fix the styles compatibility hook for the editor iframes (#40842)
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad authored May 5, 2022
1 parent ad2a96b commit acf2957
Showing 1 changed file with 62 additions and 54 deletions.
116 changes: 62 additions & 54 deletions packages/block-editor/src/components/iframe/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
useState,
createPortal,
forwardRef,
useEffect,
useMemo,
useReducer,
} from '@wordpress/element';
Expand All @@ -34,61 +33,66 @@ const BLOCK_PREFIX = 'wp-block';
*
* Ideally, this hook should be removed in the future and styles should be added
* explicitly as editor styles.
*
* @param {Document} doc The document to append cloned stylesheets to.
*/
function styleSheetsCompat( doc ) {
// Search the document for stylesheets targetting the editor canvas.
Array.from( document.styleSheets ).forEach( ( styleSheet ) => {
try {
// May fail for external styles.
// eslint-disable-next-line no-unused-expressions
styleSheet.cssRules;
} catch ( e ) {
return;
}

const { ownerNode, cssRules } = styleSheet;

if ( ! cssRules ) {
return;
}
function useStylesCompatibility() {
return useRefEffect( ( node ) => {
// Search the document for stylesheets targetting the editor canvas.
Array.from( document.styleSheets ).forEach( ( styleSheet ) => {
try {
// May fail for external styles.
// eslint-disable-next-line no-unused-expressions
styleSheet.cssRules;
} catch ( e ) {
return;
}

// Generally, ignore inline styles. We add inline styles belonging to a
// stylesheet later, which may or may not match the selectors.
if ( ownerNode.tagName !== 'LINK' ) {
return;
}
const { ownerNode, cssRules } = styleSheet;

// 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;
}

const isMatch = Array.from( cssRules ).find(
( { selectorText } ) =>
selectorText &&
( selectorText.includes( `.${ BODY_CLASS_NAME }` ) ||
selectorText.includes( `.${ BLOCK_PREFIX }` ) )
);
if ( ! cssRules ) {
return;
}

if ( isMatch && ! doc.getElementById( ownerNode.id ) ) {
// Display warning once we have a way to add style dependencies to the editor.
// See: https://github.com/WordPress/gutenberg/pull/37466.
// Generally, ignore inline styles. We add inline styles belonging to a
// stylesheet later, which may or may not match the selectors.
if ( ownerNode.tagName !== 'LINK' ) {
return;
}

doc.head.appendChild( ownerNode.cloneNode( true ) );
// 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;
}

// Add inline styles belonging to the stylesheet.
const inlineCssId = ownerNode.id.replace( '-css', '-inline-css' );
const inlineCssElement = document.getElementById( inlineCssId );
const isMatch = Array.from( cssRules ).find(
( { selectorText } ) =>
selectorText &&
( selectorText.includes( `.${ BODY_CLASS_NAME }` ) ||
selectorText.includes( `.${ BLOCK_PREFIX }` ) )
);

if ( inlineCssElement ) {
doc.head.appendChild( inlineCssElement.cloneNode( true ) );
if (
isMatch &&
! node.ownerDocument.getElementById( ownerNode.id )
) {
// Display warning once we have a way to add style dependencies to the editor.
// See: https://github.com/WordPress/gutenberg/pull/37466.
node.appendChild( ownerNode.cloneNode( true ) );

// Add inline styles belonging to the stylesheet.
const inlineCssId = ownerNode.id.replace(
'-css',
'-inline-css'
);
const inlineCssElement = document.getElementById( inlineCssId );

if ( inlineCssElement ) {
node.appendChild( inlineCssElement.cloneNode( true ) );
}
}
}
} );
} );
}, [] );
}

/**
Expand Down Expand Up @@ -222,12 +226,7 @@ function Iframe(
} );
}, [] );
const bodyRef = useMergeRefs( [ contentRef, clearerRef, writingFlowRef ] );

useEffect( () => {
if ( iframeDocument ) {
styleSheetsCompat( iframeDocument );
}
}, [ iframeDocument ] );
const styleCompatibilityRef = useStylesCompatibility();

head = (
<>
Expand Down Expand Up @@ -275,6 +274,15 @@ function Iframe(
...bodyClasses
) }
>
{ /*
* This is a wrapper for the extra styles and scripts
* rendered imperatively by cloning the parent,
* it's important that this div's content remains uncontrolled.
*/ }
<div
style={ { display: 'none' } }
ref={ styleCompatibilityRef }
/>
<StyleProvider document={ iframeDocument }>
{ children }
</StyleProvider>
Expand Down

0 comments on commit acf2957

Please sign in to comment.