Skip to content

Commit

Permalink
Improve search
Browse files Browse the repository at this point in the history
  • Loading branch information
Mamaduka committed Jul 18, 2022
1 parent af6ef39 commit d16c616
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
useCreateTemplatePartFromBlocks,
} from './utils/hooks';
import { createTemplatePartId } from './utils/create-template-part-id';
import { searchItems } from './utils/search';
import { searchPatterns } from './utils/search';

export default function TemplatePartSelectionModal( {
setAttributes,
Expand All @@ -52,12 +52,12 @@ export default function TemplatePartSelectionModal( {
templatePart,
} ) );

return searchItems( partsAsPatterns, searchValue );
return searchPatterns( partsAsPatterns, searchValue );
}, [ templateParts, searchValue ] );
const shownTemplateParts = useAsyncList( filteredTemplateParts );
const blockPatterns = useAlternativeBlockPatterns( area, clientId );
const filteredBlockPatterns = useMemo( () => {
return searchItems( blockPatterns, searchValue );
return searchPatterns( blockPatterns, searchValue );
}, [ blockPatterns, searchValue ] );
const shownBlockPatterns = useAsyncList( filteredBlockPatterns );

Expand Down
76 changes: 66 additions & 10 deletions packages/block-library/src/template-part/edit/utils/search.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,76 @@
/**
* Filters an item list given a search term.
* External dependencies
*/
import removeAccents from 'remove-accents';

/**
* Sanitizes the search input string.
*
* @param {string} input The search input to normalize.
*
* @return {string} The normalized search input.
*/
function normalizeSearchInput( input = '' ) {
// Disregard diacritics.
input = removeAccents( input );

// Trim & Lowercase.
input = input.trim().toLowerCase();

return input;
}

/**
* Get the search rank for a given pattern and a specific search term.
*
* @param {Object} pattern Pattern to rank
* @param {string} searchValue Search term
* @return {number} A pattern search rank
*/
function getSearchPatternRank( pattern, searchValue ) {
const normalizedSearchValue = normalizeSearchInput( searchValue );
const normalizedTitle = normalizeSearchInput( pattern.title );

let rank = 0;

if ( normalizedSearchValue === normalizedTitle ) {
rank += 30;
} else if ( normalizedTitle.startsWith( normalizedSearchValue ) ) {
rank += 20;
} else {
const searchTerms = normalizedSearchValue.split( ' ' );
const hasMatchedTerms = searchTerms.every( ( searchTerm ) =>
normalizedTitle.includes( searchTerm )
);

// Prefer pattern with every search word in the title.
if ( hasMatchedTerms ) {
rank += 10;
}
}

return rank;
}

/**
* Filters an pattern list given a search term.
*
* @param {Array} items Item list
* @param {Array} patterns Item list
* @param {string} searchValue Search input.
*
* @return {Array} Filtered item list.
* @return {Array} Filtered pattern list.
*/
export function searchItems( items, searchValue ) {
export function searchPatterns( patterns = [], searchValue = '' ) {
if ( ! searchValue ) {
return items;
return patterns;
}

const normalizedSearchValue = searchValue.toLowerCase();
return items.filter( ( item ) => {
const normalizedTitle = item.title.toLowerCase();
const rankedPatterns = patterns
.map( ( pattern ) => {
return [ pattern, getSearchPatternRank( pattern, searchValue ) ];
} )
.filter( ( [ , rank ] ) => rank > 0 );

return normalizedTitle.includes( normalizedSearchValue );
} );
rankedPatterns.sort( ( [ , rank1 ], [ , rank2 ] ) => rank2 - rank1 );
return rankedPatterns.map( ( [ pattern ] ) => pattern );
}

0 comments on commit d16c616

Please sign in to comment.