Skip to content

Commit

Permalink
URL: Conform to URL Living Standard definition of valid URL (#19871)
Browse files Browse the repository at this point in the history
* Framework: Add URL polyfill

* URL: Conform to URL Living Standard definition of valid URL

* Block Editor: Remove redundant checks for `isMailto`, `isTel`

These are now considered valid by `isURL` and are not necessary to evaluate separately.

* Compat: Register URL polyfill only if not registered

* Compat: Add "Remove by" message for URL polyfill

* Compat: Add upstream patch ticket reference for URL polyfill
  • Loading branch information
aduth authored Feb 4, 2020
1 parent aae6d1b commit 056d7c1
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 33 deletions.
45 changes: 45 additions & 0 deletions lib/compat.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,51 @@ function gutenberg_safe_style_css_column_flex_basis( $attr ) {
}
add_filter( 'safe_style_css', 'gutenberg_safe_style_css_column_flex_basis' );

/**
* Adds a polyfill for the WHATWG URL in environments which do not support it.
* The intention in how this action is handled is under the assumption that this
* code would eventually be placed at `wp_default_packages_vendor`, which is
* called as a result of `wp_default_packages` via the `wp_default_scripts`.
*
* This can be removed when plugin support requires WordPress 5.4.0+.
*
* @see https://core.trac.wordpress.org/ticket/49360
* @see https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
* @see https://developer.wordpress.org/reference/functions/wp_default_packages_vendor/
*
* @since 7.3.0
*
* @param WP_Scripts $scripts WP_Scripts object.
*/
function gutenberg_add_url_polyfill( $scripts ) {
// Only register polyfill if not already registered. This prevents handling
// in an environment where core has updated to manage the polyfill. This
// depends on the action being handled after default script registration.
$is_polyfill_script_registered = (bool) $scripts->query( 'wp-polyfill-url', 'registered' );
if ( $is_polyfill_script_registered ) {
return;
}

gutenberg_register_vendor_script(
$scripts,
'wp-polyfill-url',
'https://unpkg.com/[email protected]/polyfills/URL/polyfill.js',
array(),
'3.26.0-0'
);

did_action( 'init' ) && $scripts->add_inline_script(
'wp-polyfill',
wp_get_script_polyfill(
$scripts,
array(
'\'URL\' in window' => 'wp-polyfill-url',
)
)
);
}
add_action( 'wp_default_scripts', 'gutenberg_add_url_polyfill', 20 );

/**
* Sets the current post for usage in template blocks.
*
Expand Down
9 changes: 1 addition & 8 deletions packages/block-editor/src/components/link-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,17 +214,10 @@ function LinkControl( {
// 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 handleManualEntry =
isInternal ||
isMailto ||
isTel ||
isURL( val ) ||
( val && val.includes( 'www.' ) );
isInternal || isURL( val ) || ( val && val.includes( 'www.' ) );

return handleManualEntry
? handleDirectEntry( val, args )
Expand Down
6 changes: 6 additions & 0 deletions packages/url/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## Master

### Bug Fixes

- `isURL` now correctly returns `true` for many other forms of a valid URL, as it now conforms to the [URL Living Standard](https://url.spec.whatwg.org/) definition of a [valid URL string](https://url.spec.whatwg.org/#valid-url-string).

## 2.3.3 (2019-01-03)

### Bug Fixes
Expand Down
5 changes: 5 additions & 0 deletions packages/url/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ _Returns_

Determines whether the given string looks like a URL.

_Related_

- <https://url.spec.whatwg.org/>
- <https://url.spec.whatwg.org/#valid-url-string>

_Usage_

```js
Expand Down
14 changes: 11 additions & 3 deletions packages/url/src/is-url.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const URL_REGEXP = /^(?:https?:)?\/\/\S+$/i;

/**
* Determines whether the given string looks like a URL.
*
Expand All @@ -10,8 +8,18 @@ const URL_REGEXP = /^(?:https?:)?\/\/\S+$/i;
* const isURL = isURL( 'https://wordpress.org' ); // true
* ```
*
* @see https://url.spec.whatwg.org/
* @see https://url.spec.whatwg.org/#valid-url-string
*
* @return {boolean} Whether or not it looks like a URL.
*/
export function isURL( url ) {
return URL_REGEXP.test( url );
// A URL can be considered value if the `URL` constructor is able to parse
// it. The constructor throws an error for an invalid URL.
try {
new URL( url );
return true;
} catch ( error ) {
return false;
}
}
46 changes: 24 additions & 22 deletions packages/url/src/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,30 @@ import {
} from '../';

describe( 'isURL', () => {
it( 'returns true when given things that look like a URL', () => {
const urls = [
'http://wordpress.org',
'https://wordpress.org',
'HTTPS://WORDPRESS.ORG',
'https://wordpress.org/foo#bar',
'https://localhost/foo#bar',
];

expect( every( urls, isURL ) ).toBe( true );
} );

it( "returns false when given things that don't look like a URL", () => {
const urls = [
'HTTP: HyperText Transfer Protocol',
'URLs begin with a http:// prefix',
'Go here: http://wordpress.org',
'http://',
'',
];

expect( every( urls, isURL ) ).toBe( false );
it.each( [
[ 'http://wordpress.org' ],
[ 'https://wordpress.org' ],
[ 'HTTPS://WORDPRESS.ORG' ],
[ 'https://wordpress.org/./foo' ],
[ 'https://wordpress.org/path?query#fragment' ],
[ 'https://localhost/foo#bar' ],
[ 'mailto:[email protected]' ],
[ 'ssh://user:[email protected]:8080' ],
] )( 'valid (true): %s', ( url ) => {
expect( isURL( url ) ).toBe( true );
} );

it.each( [
[ 'http://word press.org' ],
[ 'http://wordpress.org:port' ],
[ 'http://[wordpress.org]/' ],
[ 'HTTP: HyperText Transfer Protocol' ],
[ 'URLs begin with a http:// prefix' ],
[ 'Go here: http://wordpress.org' ],
[ 'http://' ],
[ '' ],
] )( 'invalid (false): %s', ( url ) => {
expect( isURL( url ) ).toBe( false );
} );
} );

Expand Down

0 comments on commit 056d7c1

Please sign in to comment.