diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 5da6bff0973f8c..cb6f9336368fab 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -12,6 +12,7 @@ - `SelectControl`: Fix font-size for medium screens to ensure consistency with other inputs ([#70619](https://github.com/WordPress/gutenberg/pull/70619)). - `SelectControl`: Move classnames to the root ([#70643](https://github.com/WordPress/gutenberg/pull/70643)). - `Autocomplete`: Prevent text cursor position loss when clicking to insert an item ([#70660](https://github.com/WordPress/gutenberg/pull/70660)). +- `Autocomplete`: Fix matching logic to prefer longest overlapping trigger ([#70400](https://github.com/WordPress/gutenberg/pull/70400)). ### Internal diff --git a/packages/components/src/autocomplete/index.tsx b/packages/components/src/autocomplete/index.tsx index 78be906b64d1f4..17bad5e1ed66ef 100644 --- a/packages/components/src/autocomplete/index.tsx +++ b/packages/components/src/autocomplete/index.tsx @@ -237,24 +237,33 @@ export function useAutocomplete( { return; } - // Find the completer with the highest triggerPrefix index in the - // textContent. - const completer = completers.reduce< WPCompleter | null >( - ( lastTrigger, currentCompleter ) => { - const triggerIndex = textContent.lastIndexOf( - currentCompleter.triggerPrefix - ); - const lastTriggerIndex = - lastTrigger !== null - ? textContent.lastIndexOf( lastTrigger.triggerPrefix ) - : -1; - - return triggerIndex > lastTriggerIndex - ? currentCompleter - : lastTrigger; - }, - null - ); + let lastCompleter: WPCompleter | null = null; + let lastTriggerEndIndex = -1; + + for ( const completer of completers ) { + const { triggerPrefix } = completer; + const triggerIndex = textContent.lastIndexOf( triggerPrefix ); + const triggerEndIndex = triggerIndex + triggerPrefix.length; + + if ( triggerIndex === -1 ) { + continue; + } + + // Choose the completer whose trigger appears later in + // the text, or, if at the same position, the one with + // the longer triggerPrefix. + if ( + lastCompleter === null || + triggerEndIndex > lastTriggerEndIndex || + ( triggerEndIndex === lastTriggerEndIndex && + triggerPrefix.length > lastCompleter.triggerPrefix.length ) + ) { + lastCompleter = completer; + lastTriggerEndIndex = triggerEndIndex; + } + } + + const completer = lastCompleter; if ( ! completer ) { if ( autocompleter ) {