Skip to content

Commit

Permalink
Inserter: use lighter grammar parse to check allowed status (#64902)
Browse files Browse the repository at this point in the history
Co-authored-by: ellatrix <ellatrix@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>
Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org>
Co-authored-by: tyxla <tyxla@git.wordpress.org>
  • Loading branch information
5 people authored and vcanales committed Sep 4, 2024
1 parent 0b33f8a commit 9b9bbe8
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 14 deletions.
2 changes: 2 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions packages/block-editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@wordpress/a11y": "file:../a11y",
"@wordpress/api-fetch": "file:../api-fetch",
"@wordpress/blob": "file:../blob",
"@wordpress/block-serialization-default-parser": "file:../block-serialization-default-parser",
"@wordpress/blocks": "file:../blocks",
"@wordpress/commands": "file:../commands",
"@wordpress/components": "file:../components",
Expand Down
8 changes: 4 additions & 4 deletions packages/block-editor/src/store/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
checkAllowListRecursive,
getAllPatternsDependants,
getInsertBlockTypeDependants,
getParsedPattern,
getGrammar,
} from './utils';
import { INSERTER_PATTERN_TYPES } from '../components/inserter/block-patterns-tab/utils';
import { STORE_NAME } from './constants';
Expand Down Expand Up @@ -300,10 +300,10 @@ export const hasAllowedPatterns = createRegistrySelector( ( select ) =>
if ( ! inserter ) {
return false;
}
const { blocks } = getParsedPattern( pattern );
const grammar = getGrammar( pattern );
return (
checkAllowListRecursive( blocks, allowedBlockTypes ) &&
blocks.every( ( { name: blockName } ) =>
checkAllowListRecursive( grammar, allowedBlockTypes ) &&
grammar.every( ( { name: blockName } ) =>
canInsertBlockType( state, blockName, rootClientId )
)
);
Expand Down
23 changes: 17 additions & 6 deletions packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
getAllPatternsDependants,
getInsertBlockTypeDependants,
getParsedPattern,
getGrammar,
} from './utils';
import { orderBy } from '../utils/sorting';
import { STORE_NAME } from './constants';
Expand Down Expand Up @@ -2376,17 +2377,27 @@ export const __experimentalGetAllowedPatterns = createRegistrySelector(
const { getAllPatterns } = unlock( select( STORE_NAME ) );
const patterns = getAllPatterns();
const { allowedBlockTypes } = getSettings( state );

const parsedPatterns = patterns
.filter( ( { inserter = true } ) => !! inserter )
.map( getParsedPattern );
.map( ( pattern ) => {
return {
...pattern,
get blocks() {
return getParsedPattern( pattern ).blocks;
},
};
} );

const availableParsedPatterns = parsedPatterns.filter(
( { blocks } ) =>
checkAllowListRecursive( blocks, allowedBlockTypes )
( pattern ) =>
checkAllowListRecursive(
getGrammar( pattern ),
allowedBlockTypes
)
);
const patternsAllowed = availableParsedPatterns.filter(
( { blocks } ) =>
blocks.every( ( { name } ) =>
( pattern ) =>
getGrammar( pattern ).every( ( { blockName: name } ) =>
canInsertBlockType( state, name, rootClientId )
)
);
Expand Down
20 changes: 16 additions & 4 deletions packages/block-editor/src/store/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* WordPress dependencies
*/
import { parse } from '@wordpress/blocks';
import { parse as grammarParse } from '@wordpress/block-serialization-default-parser';

/**
* Internal dependencies
Expand All @@ -13,6 +14,7 @@ import { STORE_NAME } from './constants';
export const withRootClientIdOptionKey = Symbol( 'withRootClientId' );

const parsedPatternCache = new WeakMap();
const grammarMapCache = new WeakMap();

function parsePattern( pattern ) {
const blocks = parse( pattern.content, {
Expand All @@ -37,14 +39,24 @@ function parsePattern( pattern ) {

export function getParsedPattern( pattern ) {
let parsedPattern = parsedPatternCache.get( pattern );
if ( parsedPattern ) {
return parsedPattern;
if ( ! parsedPattern ) {
parsedPattern = parsePattern( pattern );
parsedPatternCache.set( pattern, parsedPattern );
}
parsedPattern = parsePattern( pattern );
parsedPatternCache.set( pattern, parsedPattern );
return parsedPattern;
}

export function getGrammar( pattern ) {
let grammarMap = grammarMapCache.get( pattern );
if ( ! grammarMap ) {
grammarMap = grammarParse( pattern.content );
// Block names are null only at the top level for whitespace.
grammarMap = grammarMap.filter( ( block ) => block.blockName !== null );
grammarMapCache.set( pattern, grammarMap );
}
return grammarMap;
}

export const checkAllowList = ( list, item, defaultResult = null ) => {
if ( typeof list === 'boolean' ) {
return list;
Expand Down
1 change: 1 addition & 0 deletions packages/block-editor/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"references": [
{ "path": "../a11y" },
{ "path": "../api-fetch" },
{ "path": "../block-serialization-default-parser" },
{ "path": "../blob" },
{ "path": "../components" },
{ "path": "../compose" },
Expand Down
57 changes: 57 additions & 0 deletions test/e2e/specs/editor/various/parsing-patterns.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* WordPress dependencies
*/
const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );

test.describe( 'Parsing patterns', () => {
test( 'Considers a pattern with whitespace an allowed pattern', async ( {
admin,
editor,
page,
} ) => {
await admin.createNewPost();
await editor.insertBlock( {
name: 'core/buttons',
innerBlocks: [ { name: 'core/button', attributes: { text: 'a' } } ],
} );
await page.keyboard.press( 'ArrowDown' );
await page.getByLabel( 'Toggle block inserter' ).click();

await page.getByRole( 'tab', { name: 'Patterns' } ).click();
await page.evaluate( () => {
window.wp.data.dispatch( 'core/block-editor' ).updateSettings( {
__experimentalBlockPatterns: [
{
name: 'test/whitespace',
title: 'Pattern with top-level whitespace',
description: '',
content: `<!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button">test</a></div>
<!-- /wp:button -->
<!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button">test</a></div>
<!-- /wp:button -->`,
},
],
} );
} );
await page.fill(
'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]',
'whitespace'
);
await page
.locator( 'role=option[name="Pattern with top-level whitespace"i]' )
.click();
expect( await editor.getBlocks() ).toMatchObject( [
{
name: 'core/buttons',
innerBlocks: [
{ name: 'core/button', attributes: { text: 'a' } },
{ name: 'core/button', attributes: { text: 'test' } },
{ name: 'core/button', attributes: { text: 'test' } },
],
},
] );
} );
} );

0 comments on commit 9b9bbe8

Please sign in to comment.