Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editor styles: cache transform #57810

Merged
merged 1 commit into from Jan 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
89 changes: 52 additions & 37 deletions packages/block-editor/src/utils/transform-styles/index.js
Expand Up @@ -5,6 +5,52 @@ import postcss, { CssSyntaxError } from 'postcss';
import wrap from 'postcss-prefixwrap';
import rebaseUrl from 'postcss-urlrebase';

const transformStylesCache = new WeakMap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WeakMap is such a magic tool :P

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, very!


function transformStyle(
{ css, ignoredSelectors = [], baseURL },
wrapperSelector = ''
) {
// When there is no wrapper selector or base URL, there is no need
// to transform the CSS. This is most cases because in the default
// iframed editor, no wrapping is needed, and not many styles
// provide a base URL.
if ( ! wrapperSelector && ! baseURL ) {
return css;
}

try {
return postcss(
[
wrapperSelector &&
wrap( wrapperSelector, {
ignoredSelectors: [
...ignoredSelectors,
wrapperSelector,
],
} ),
baseURL && rebaseUrl( { rootUrl: baseURL } ),
].filter( Boolean )
).process( css, {} ).css; // use sync PostCSS API
} catch ( error ) {
if ( error instanceof CssSyntaxError ) {
// eslint-disable-next-line no-console
console.warn(
'wp.blockEditor.transformStyles Failed to transform CSS.',
error.message + '\n' + error.showSourceCode( false )
);
} else {
// eslint-disable-next-line no-console
console.warn(
'wp.blockEditor.transformStyles Failed to transform CSS.',
error
);
}

return null;
}
}

/**
* Applies a series of CSS rule transforms to wrap selectors inside a given class and/or rewrite URLs depending on the parameters passed.
*
Expand All @@ -18,45 +64,14 @@ import rebaseUrl from 'postcss-urlrebase';
* @return {Array} converted rules.
*/
const transformStyles = ( styles, wrapperSelector = '' ) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in person, if we're using an iframe, transforming styles might not be necessary anymore assuming we also pass the "url" to the stylesheet in addition to its content. We could just use the URL to load the stylesheets within the iframe.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I'll try this next. This PR is still useful for an editor without iframe though (when there's a registered block that is not v3)

return styles.map( ( { css, ignoredSelectors = [], baseURL } ) => {
// When there is no wrapper selector or base URL, there is no need
// to transform the CSS. This is most cases because in the default
// iframed editor, no wrapping is needed, and not many styles
// provide a base URL.
if ( ! wrapperSelector && ! baseURL ) {
return css;
return styles.map( ( style ) => {
if ( transformStylesCache.has( style ) ) {
return transformStylesCache.get( style );
}

try {
return postcss(
[
wrapperSelector &&
wrap( wrapperSelector, {
ignoredSelectors: [
...ignoredSelectors,
wrapperSelector,
],
} ),
baseURL && rebaseUrl( { rootUrl: baseURL } ),
].filter( Boolean )
).process( css, {} ).css; // use sync PostCSS API
} catch ( error ) {
if ( error instanceof CssSyntaxError ) {
// eslint-disable-next-line no-console
console.warn(
'wp.blockEditor.transformStyles Failed to transform CSS.',
error.message + '\n' + error.showSourceCode( false )
);
} else {
// eslint-disable-next-line no-console
console.warn(
'wp.blockEditor.transformStyles Failed to transform CSS.',
error
);
}

return null;
}
const transformedStyle = transformStyle( style, wrapperSelector );
transformStylesCache.set( style, transformedStyle );
return transformedStyle;
} );
};

Expand Down