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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,52 @@ import postcss, { CssSyntaxError } from 'postcss'; | |
import wrap from 'postcss-prefixwrap'; | ||
import rebaseUrl from 'postcss-urlrebase'; | ||
|
||
const transformStylesCache = new WeakMap(); | ||
|
||
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. | ||
* | ||
|
@@ -18,45 +64,14 @@ import rebaseUrl from 'postcss-urlrebase'; | |
* @return {Array} converted rules. | ||
*/ | ||
const transformStyles = ( styles, wrapperSelector = '' ) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
} ); | ||
}; | ||
|
||
|
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, very!