diff --git a/packages/block-editor/src/components/link-control/index.js b/packages/block-editor/src/components/link-control/index.js
index 38fec35f6ab6b6..4bbb1c1232b7bb 100644
--- a/packages/block-editor/src/components/link-control/index.js
+++ b/packages/block-editor/src/components/link-control/index.js
@@ -13,9 +13,10 @@ import { useCallback, useState, Fragment } from '@wordpress/element';
import {
safeDecodeURI,
filterURLForDisplay,
- isURL,
prependHTTP,
getProtocol,
+ isValidFragment,
+ isUri,
} from '@wordpress/url';
import { useInstanceId } from '@wordpress/compose';
import { useSelect } from '@wordpress/data';
@@ -85,31 +86,22 @@ function LinkControl( {
};
const handleEntitySearch = async ( val, args ) => {
- const results = await Promise.all( [
- fetchSearchSuggestions( val, {
- ...( args.isInitialSuggestions ? { perPage: 3 } : {} ),
- } ),
- handleDirectEntry( val ),
- ] );
-
- const couldBeURL = ! val.includes( ' ' );
-
- // If it's potentially a URL search then concat on a URL search suggestion
- // just for good measure. That way once the actual results run out we always
- // have a URL option to fallback on.
- return couldBeURL && ! args.isInitialSuggestions ? results[ 0 ].concat( results[ 1 ] ) : results[ 0 ];
+ return await fetchSearchSuggestions( val, {
+ ...( args.isInitialSuggestions ? { perPage: 3 } : {} ),
+ } );
};
- // Effects
- const getSearchHandler = useCallback( ( val, args ) => {
- const protocol = getProtocol( val ) || '';
- const isMailto = protocol.includes( 'mailto' );
- const isInternal = startsWith( val, '#' );
- const isTel = protocol.includes( 'tel' );
+ const couldBeURI = function( val ) {
+ const isInternal = startsWith( val, '#' ) && isValidFragment( val );
+ const includesWWW = !! ( val && val.includes( 'www.' ) );
- const handleManualEntry = isInternal || isMailto || isTel || isURL( val ) || ( val && val.includes( 'www.' ) );
+ return isUri( val ) || includesWWW || isInternal;
+ };
- return ( handleManualEntry ) ? handleDirectEntry( val, args ) : handleEntitySearch( val, args );
+ // Effects
+ const getSearchHandler = useCallback( ( val, args ) => {
+ // If it has a fragment and it is valid
+ return ( couldBeURI( val ) ) ? handleDirectEntry( val, args ) : handleEntitySearch( val, args );
}, [ handleDirectEntry, fetchSearchSuggestions ] );
// Render Components
diff --git a/packages/url/README.md b/packages/url/README.md
index 9436880c51f43c..7b59a0258a442c 100644
--- a/packages/url/README.md
+++ b/packages/url/README.md
@@ -227,6 +227,25 @@ _Returns_
- `boolean`: Whether or not it looks like an email.
+# **isURI**
+
+Determines whether the given string looks like a URI (of any type).
+
+_Usage_
+
+```js
+const isURI = isURI( 'https://wordpress.org' ); // true
+const anotherURI = isURI('mailto:hello@wordpress.org'); // true
+```
+
+_Parameters_
+
+- _uri_ `string`: The string to scrutinise.
+
+_Returns_
+
+- `boolean`: Whether or not it looks like a URI.
+
# **isURL**
Determines whether the given string looks like a URL.
diff --git a/packages/url/package.json b/packages/url/package.json
index 73c82ab0daeb52..bd92afdcb1e6fc 100644
--- a/packages/url/package.json
+++ b/packages/url/package.json
@@ -24,7 +24,8 @@
"dependencies": {
"@babel/runtime": "^7.4.4",
"lodash": "^4.17.15",
- "qs": "^6.5.2"
+ "qs": "^6.5.2",
+ "valid-url": "^1.0.9"
},
"publishConfig": {
"access": "public"
diff --git a/packages/url/src/index.js b/packages/url/src/index.js
index 3a47cba0bc3b59..e108c326b12311 100644
--- a/packages/url/src/index.js
+++ b/packages/url/src/index.js
@@ -1,3 +1,5 @@
+
+export { isURI } from './is-uri';
export { isURL } from './is-url';
export { isEmail } from './is-email';
export { getProtocol } from './get-protocol';
diff --git a/packages/url/src/is-uri.js b/packages/url/src/is-uri.js
new file mode 100644
index 00000000000000..6f98411c5e510a
--- /dev/null
+++ b/packages/url/src/is-uri.js
@@ -0,0 +1,21 @@
+/**
+ * External dependencies
+ */
+import { isUri } from 'valid-url';
+
+/**
+ * Determines whether the given string looks like a URI (of any type).
+ *
+ * @param {string} uri The string to scrutinise.
+ *
+ * @example
+ * ```js
+ * const isURI = isURI( 'https://wordpress.org' ); // true
+ * const anotherURI = isURI('mailto:hello@wordpress.org'); // true
+ * ```
+ *
+ * @return {boolean} Whether or not it looks like a URI.
+ */
+export function isURI( uri ) {
+ return isUri( uri );
+}