diff --git a/blocks/README.md b/blocks/README.md index 239bbe82ba972..9383695c2906f 100644 --- a/blocks/README.md +++ b/blocks/README.md @@ -246,6 +246,7 @@ editor interface where blocks are implemented. - `save( { attributes: Object } ): WPElement | String` - Returns an element describing the markup of a block to be saved in the published content. This function is called before save and when switching to an editor's HTML view. +- `keywords` - An optional array of keywords used to filter the block list. ### `wp.blocks.getBlockType( name: string )` diff --git a/blocks/api/registration.js b/blocks/api/registration.js index cc34dbd2656bb..679abff7d3296 100644 --- a/blocks/api/registration.js +++ b/blocks/api/registration.js @@ -67,6 +67,12 @@ export function registerBlockType( name, settings ) { ); return; } + if ( 'keywords' in settings && settings.keywords.length > 3 ) { + console.error( + 'The block "' + name + '" can have a maximum of 3 keywords.' + ); + return; + } const block = Object.assign( { name }, settings ); blocks[ name ] = block; return block; diff --git a/blocks/api/test/registration.js b/blocks/api/test/registration.js index 3dbab80710bbb..ea98cf73644cb 100644 --- a/blocks/api/test/registration.js +++ b/blocks/api/test/registration.js @@ -88,6 +88,13 @@ describe( 'blocks', () => { expect( block ).toBeUndefined(); } ); + it( 'should reject blocks with more than 3 keywords', () => { + const blockType = { save: noop, keywords: [ 'apple', 'orange', 'lemon', 'pineapple' ] }, + block = registerBlockType( 'my-plugin/fancy-block-7', blockType ); + expect( console.error ).toHaveBeenCalledWith( 'The block "my-plugin/fancy-block-7" can have a maximum of 3 keywords.' ); + expect( block ).toBeUndefined(); + } ); + it( 'should store a copy of block type', () => { const blockType = { settingName: 'settingValue', save: noop }; registerBlockType( 'core/test-block-with-settings', blockType ); diff --git a/blocks/library/verse/index.js b/blocks/library/verse/index.js index 3b93d3553c05c..966124ca2324c 100644 --- a/blocks/library/verse/index.js +++ b/blocks/library/verse/index.js @@ -21,6 +21,8 @@ registerBlockType( 'core/verse', { category: 'formatting', + keywords: [ __( 'poetry' ) ], + attributes: { content: children( 'pre' ), }, diff --git a/editor/inserter/menu.js b/editor/inserter/menu.js index c8f990484701f..021a23975dc06 100644 --- a/editor/inserter/menu.js +++ b/editor/inserter/menu.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { flow, groupBy, sortBy, findIndex, filter, debounce, find } from 'lodash'; +import { flow, groupBy, sortBy, findIndex, filter, debounce, find, some } from 'lodash'; import { connect } from 'react-redux'; /** @@ -20,6 +20,15 @@ import './style.scss'; import { getBlocks, getRecentlyUsedBlocks } from '../selectors'; import { showInsertionPoint, hideInsertionPoint } from '../actions'; +export const searchBlocks = ( blocks, searchTerm ) => { + const normalizedSearchTerm = searchTerm.toLowerCase(); + const matchSearch = ( string ) => string.toLowerCase().indexOf( normalizedSearchTerm ) !== -1; + + return blocks.filter( ( block ) => + matchSearch( block.title ) || some( block.keywords, matchSearch ) + ); +}; + export class InserterMenu extends Component { constructor() { super( ...arguments ); @@ -88,8 +97,7 @@ export class InserterMenu extends Component { } searchBlocks( blockTypes ) { - const matchesSearch = ( block ) => block.title.toLowerCase().indexOf( this.state.filterValue.toLowerCase() ) !== -1; - return filter( blockTypes, matchesSearch ); + return searchBlocks( blockTypes, this.state.filterValue ); } getBlocksForCurrentTab() { diff --git a/editor/inserter/test/menu.js b/editor/inserter/test/menu.js index 224f504a90827..07c171e63a798 100644 --- a/editor/inserter/test/menu.js +++ b/editor/inserter/test/menu.js @@ -12,7 +12,7 @@ import { registerBlockType, unregisterBlockType, getBlockTypes } from 'blocks'; /** * Internal dependencies */ -import { InserterMenu } from '../menu'; +import { InserterMenu, searchBlocks } from '../menu'; const textBlock = { name: 'core/text-block', @@ -53,6 +53,7 @@ const youtubeBlock = { save: noop, edit: noop, category: 'embed', + keywords: [ 'google' ], }; const textEmbedBlock = { @@ -196,3 +197,19 @@ describe( 'InserterMenu', () => { expect( visibleBlocks.at( 2 ).childAt( 1 ).text() ).toBe( 'A Text Embed' ); } ); } ); + +describe( 'searchBlocks', () => { + it( 'should search blocks using the title ignoring case', () => { + const blocks = [ textBlock, advancedTextBlock, moreBlock, youtubeBlock, textEmbedBlock ]; + expect( searchBlocks( blocks, 'TEXT' ) ).toEqual( + [ textBlock, advancedTextBlock, textEmbedBlock ] + ); + } ); + + it( 'should search blocks using the keywords', () => { + const blocks = [ textBlock, advancedTextBlock, moreBlock, youtubeBlock, textEmbedBlock ]; + expect( searchBlocks( blocks, 'GOOGL' ) ).toEqual( + [ youtubeBlock ] + ); + } ); +} );