diff --git a/packages/block-editor/src/components/link-control/search-item.js b/packages/block-editor/src/components/link-control/search-item.js index e91326b3ba4ee7..c332fecd19a95b 100644 --- a/packages/block-editor/src/components/link-control/search-item.js +++ b/packages/block-editor/src/components/link-control/search-item.js @@ -13,7 +13,8 @@ import { file, } from '@wordpress/icons'; import { __unstableStripHTML as stripHTML } from '@wordpress/dom'; -import { safeDecodeURI, filterURLForDisplay } from '@wordpress/url'; +import { safeDecodeURI, filterURLForDisplay, getPath } from '@wordpress/url'; +import { pipe } from '@wordpress/compose'; const ICONS_MAP = { post: postList, @@ -44,6 +45,58 @@ function SearchItemIcon( { isURL, suggestion } ) { return null; } +/** + * Adds a leading slash to a url if it doesn't already have one. + * @param {string} url the url to add a leading slash to. + * @return {string} the url with a leading slash. + */ +function addLeadingSlash( url ) { + const trimmedURL = url?.trim(); + + if ( ! trimmedURL?.length ) return url; + + return url?.replace( /^\/?/, '/' ); +} + +function removeTrailingSlash( url ) { + const trimmedURL = url?.trim(); + + if ( ! trimmedURL?.length ) return url; + + return url?.replace( /\/$/, '' ); +} + +const partialRight = + ( fn, ...partialArgs ) => + ( ...args ) => + fn( ...args, ...partialArgs ); + +const defaultTo = ( d ) => ( v ) => { + return v === null || v === undefined || v !== v ? d : v; +}; + +/** + * Prepares a URL for display in the UI. + * - decodes the URL. + * - filters it (removes protocol, www, etc.). + * - truncates it if necessary. + * - adds a leading slash. + * @param {string} url the url. + * @return {string} the processed url to display. + */ +function getURLForDisplay( url ) { + if ( ! url ) return url; + + return pipe( + safeDecodeURI, + getPath, + defaultTo( '' ), + partialRight( filterURLForDisplay, 24 ), + removeTrailingSlash, + addLeadingSlash + )( url ); +} + export const LinkControlSearchItem = ( { itemProps, suggestion, @@ -54,7 +107,7 @@ export const LinkControlSearchItem = ( { } ) => { const info = isURL ? __( 'Press ENTER to add this link' ) - : filterURLForDisplay( safeDecodeURI( suggestion?.url ), 24 ); + : getURLForDisplay( suggestion.url ); return ( { hasText: 'Block 2 of 2, Level 1', // proxy for filtering by description. } ) .getByText( 'Top Level Item 2' ) - ).not.toBeVisible(); + ).toBeHidden(); } ); test( `can edit menu items`, async ( { page, editor, requestUtils } ) => { @@ -525,7 +525,7 @@ test.describe( 'Navigation block - List view editing', () => { // Check that despite being the last inserted block, the Link UI is not displayed // in this scenario because it was not **just** inserted into the List View (i.e. // we have unmounted the list view and then remounted it). - await expect( linkControl.getSearchInput() ).not.toBeVisible(); + await expect( linkControl.getSearchInput() ).toBeHidden(); } ); } ); @@ -573,9 +573,7 @@ class LinkControl { await expect( result ).toBeVisible(); return result - .locator( - '.components-menu-item__info-wrapper .components-menu-item__item' - ) // this is the only way to get the label text without the URL. + .locator( '.components-menu-item__item' ) // this is the only way to get the label text without the URL. .innerText(); } }