Skip to content

Commit

Permalink
Retain the same specificity for non iframed selectors (WordPress#64534)
Browse files Browse the repository at this point in the history
* WIP

* Small fixes, improvements to root selector handling, avoid double prefixing

* Add test for compound :where statements

* Fix too specific layout styles in non-iframed editor

* Update handling of root selectors

* Fix all the problems

* Update comment

* Add text for root selector text in middle of selector

* Also avoid double-prefix of root selectors

* Change how root selectors are transformed, inject the prefix after the root part of the selector

* Remove hard-coded editor-styles-wrapper prefix from selectors

* Update tests and fix double prefixing for root selectors

* Fix test

* Update comment

* Update another test

* Avoid transforming selectors that already contain .editor-styles-wrapper

* Update ignored selectors to match behavior of postcss-prefix-wrap

* Stop using snapshots

* Add more tests

* Fix typo

* Add tests for regex ignores

* Fix ropey root selectors and add tests

* Use a tokenizer for root prefixing

* Small optimization, Use a for loop to avoid unneccessary looping

* Remove outdated comment

* Update block library editor-styles-wrapper styles

* Update comment

* Add comment

* Add more detail to nav block style comment

* Also use same scope specificity in widget editor

* Fix strings that look like regular expressions in ignoredSelectors

* Reduce diff

* Explain the function behavior further

----

Unlinked contributors: ktmn.

Co-authored-by: talldan <talldanwp@git.wordpress.org>
Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org>
Co-authored-by: kevin940726 <kevin940726@git.wordpress.org>
Co-authored-by: mrleemon <leemon@git.wordpress.org>
Co-authored-by: apmeyer <apmeyer@git.wordpress.org>
Co-authored-by: wongjn <wongjn@git.wordpress.org>
  • Loading branch information
7 people authored and bph committed Aug 31, 2024
1 parent c348dc9 commit 6d92b0c
Show file tree
Hide file tree
Showing 22 changed files with 455 additions and 263 deletions.
45 changes: 29 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 1 addition & 10 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -811,21 +811,12 @@ _Parameters_

- _styles_ `EditorStyle[]`: CSS rules.
- _wrapperSelector_ `string`: Wrapper selector.
- _transformOptions_ `TransformOptions`: Additional options for style transformation.

_Returns_

- `Array`: converted rules.

_Type Definition_

- _EditorStyle_ `Object`

_Properties_

- _css_ `string`: the CSS block(s), as a single string.
- _baseURL_ `?string`: the base URL to be used as the reference when rewritting urls.
- _ignoredSelectors_ `?string[]`: the selectors not to wrap.

### Typewriter

Ensures that the text selection keeps the same vertical distance from the viewport during keyboard events within this component. The vertical distance can vary. It is the last clicked or scrolled to position.
Expand Down
3 changes: 2 additions & 1 deletion packages/block-editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@
"diff": "^4.0.2",
"fast-deep-equal": "^3.1.3",
"memize": "^2.1.0",
"parsel-js": "^1.1.2",
"postcss": "^8.4.21",
"postcss-prefixwrap": "^1.51.0",
"postcss-prefix-selector": "^1.16.0",
"postcss-urlrebase": "^1.4.0",
"react-autosize-textarea": "^7.1.0",
"react-easy-crop": "^5.0.6",
Expand Down
10 changes: 9 additions & 1 deletion packages/block-editor/src/components/block-canvas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ import { useMouseMoveTypingReset } from '../observe-typing';
import { useBlockSelectionClearer } from '../block-selection-clearer';
import { useBlockCommands } from '../use-block-commands';

// EditorStyles is a memoized component, so avoid passing a new
// object reference on each render.
const EDITOR_STYLE_TRANSFORM_OPTIONS = {
// Don't transform selectors that already specify `.editor-styles-wrapper`.
ignoredSelectors: [ /\.editor-styles-wrapper/gi ],
};

export function ExperimentalBlockCanvas( {
shouldIframe = true,
height = '300px',
Expand All @@ -38,7 +45,8 @@ export function ExperimentalBlockCanvas( {
>
<EditorStyles
styles={ styles }
scope=".editor-styles-wrapper"
scope=":where(.editor-styles-wrapper)"
transformOptions={ EDITOR_STYLE_TRANSFORM_OPTIONS }
/>
<WritingFlow
ref={ contentRef }
Expand Down
7 changes: 4 additions & 3 deletions packages/block-editor/src/components/editor-styles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function useDarkThemeBodyClassName( styles, scope ) {
);
}

function EditorStyles( { styles, scope } ) {
function EditorStyles( { styles, scope, transformOptions } ) {
const overrides = useSelect(
( select ) => unlock( select( blockEditorStore ) ).getStyleOverrides(),
[]
Expand All @@ -88,14 +88,15 @@ function EditorStyles( { styles, scope } ) {
return [
transformStyles(
_styles.filter( ( style ) => style?.css ),
scope
scope,
transformOptions
),
_styles
.filter( ( style ) => style.__unstableType === 'svgs' )
.map( ( style ) => style.assets )
.join( '' ),
];
}, [ styles, overrides, scope ] );
}, [ styles, overrides, scope, transformOptions ] );

return (
<>
Expand Down
4 changes: 0 additions & 4 deletions packages/block-editor/src/hooks/duotone.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,6 @@ function useDuotoneStyles( {
const selectors = duotoneSelector.split( ',' );

const selectorsScoped = selectors.map( ( selectorPart ) => {
// Extra .editor-styles-wrapper specificity is needed in the editor
// since we're not using inline styles to apply the filter. We need to
// override duotone applied by global styles and theme.json.

// Assuming the selector part is a subclass selector (not a tag name)
// so we can prepend the filter id class. If we want to support elements
// such as `img` or namespaces, we'll need to add a case for that here.
Expand Down
5 changes: 1 addition & 4 deletions packages/block-editor/src/hooks/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,10 +381,7 @@ function useBlockProps( { name, style } ) {
useBlockProps
) }`;

// The .editor-styles-wrapper selector is required on elements styles. As it is
// added to all other editor styles, not providing it causes reset and global
// styles to override element styles because of higher specificity.
const baseElementSelector = `.editor-styles-wrapper .${ blockElementsContainerIdentifier }`;
const baseElementSelector = `.${ blockElementsContainerIdentifier }`;
const blockElementStyles = style?.elements;

const styles = useMemo( () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/block-editor/src/layouts/test/grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import grid from '../grid';

describe( 'getLayoutStyle', () => {
it( 'should return only `grid-template-columns` and `container-type` properties if no non-default params are provided', () => {
const expected = `.editor-styles-wrapper .my-container { grid-template-columns: repeat(auto-fill, minmax(min(12rem, 100%), 1fr)); container-type: inline-size; }`;
const expected = `.my-container { grid-template-columns: repeat(auto-fill, minmax(min(12rem, 100%), 1fr)); container-type: inline-size; }`;

const result = grid.getLayoutStyle( {
selector: '.my-container',
Expand All @@ -19,7 +19,7 @@ describe( 'getLayoutStyle', () => {
expect( result ).toBe( expected );
} );
it( 'should return only `grid-template-columns` if columnCount property is provided', () => {
const expected = `.editor-styles-wrapper .my-container { grid-template-columns: repeat(3, minmax(0, 1fr)); }`;
const expected = `.my-container { grid-template-columns: repeat(3, minmax(0, 1fr)); }`;

const result = grid.getLayoutStyle( {
selector: '.my-container',
Expand Down
14 changes: 6 additions & 8 deletions packages/block-editor/src/layouts/test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const layoutDefinitions = {
describe( 'getBlockGapCSS', () => {
it( 'should output default blockGap rules', () => {
const expected =
'.editor-styles-wrapper .my-container > * { margin-block-start: 0; margin-block-end: 0; }.editor-styles-wrapper .my-container > * + * { margin-block-start: 3em; margin-block-end: 0; }';
'.my-container > * { margin-block-start: 0; margin-block-end: 0; }.my-container > * + * { margin-block-start: 3em; margin-block-end: 0; }';

const result = getBlockGapCSS(
'.my-container',
Expand All @@ -50,7 +50,7 @@ describe( 'getBlockGapCSS', () => {
} );

it( 'should output flex blockGap rules', () => {
const expected = '.editor-styles-wrapper .my-container { gap: 3em; }';
const expected = '.my-container { gap: 3em; }';

const result = getBlockGapCSS(
'.my-container',
Expand Down Expand Up @@ -97,7 +97,7 @@ describe( 'getBlockGapCSS', () => {
} );

it( 'should treat a blockGap string containing 0 as a valid value', () => {
const expected = '.editor-styles-wrapper .my-container { gap: 0; }';
const expected = '.my-container { gap: 0; }';

const result = getBlockGapCSS(
'.my-container',
Expand All @@ -113,21 +113,19 @@ describe( 'getBlockGapCSS', () => {
describe( 'appendSelectors', () => {
it( 'should append a subselector without an appended selector', () => {
expect( appendSelectors( '.original-selector' ) ).toBe(
'.editor-styles-wrapper .original-selector'
'.original-selector'
);
} );

it( 'should append a subselector to a single selector', () => {
expect( appendSelectors( '.original-selector', '.appended' ) ).toBe(
'.editor-styles-wrapper .original-selector .appended'
'.original-selector .appended'
);
} );

it( 'should append a subselector to multiple selectors', () => {
expect(
appendSelectors( '.first-selector,.second-selector', '.appended' )
).toBe(
'.editor-styles-wrapper .first-selector .appended,.editor-styles-wrapper .second-selector .appended'
);
).toBe( '.first-selector .appended,.second-selector .appended' );
} );
} );
10 changes: 1 addition & 9 deletions packages/block-editor/src/layouts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,11 @@ import { LAYOUT_DEFINITIONS } from './definitions';
* @return {string} - CSS selector.
*/
export function appendSelectors( selectors, append = '' ) {
// Ideally we shouldn't need the `.editor-styles-wrapper` increased specificity here
// The problem though is that we have a `.editor-styles-wrapper p { margin: reset; }` style
// it's used to reset the default margin added by wp-admin to paragraphs
// so we need this to be higher speficity otherwise, it won't be applied to paragraphs inside containers
// When the post editor is fully iframed, this extra classname could be removed.

return selectors
.split( ',' )
.map(
( subselector ) =>
`.editor-styles-wrapper ${ subselector }${
append ? ` ${ append }` : ''
}`
`${ subselector }${ append ? ` ${ append }` : '' }`
)
.join( ',' );
}
Expand Down
Loading

0 comments on commit 6d92b0c

Please sign in to comment.