TinyMCE, link check:

- Use `wp.a11y.speak()` to announce bad URLs.
- Do not add a title to the link toolbar.
- Better error message.

Props afercia, azaozz.
See #36638.

git-svn-id: https://develop.svn.wordpress.org/trunk@38126 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Andrew Ozz 2016-07-21 03:41:17 +00:00
parent 7e52b06003
commit fb1fbcfdc0
4 changed files with 41 additions and 33 deletions

View File

@ -3906,26 +3906,25 @@ function wp_ajax_test_url() {
$href = get_bloginfo( 'url' ) . $href;
}
// No redirects
$response = wp_safe_remote_get( $href, array(
'timeout' => 15,
// Use an explicit user-agent
'user-agent' => 'WordPress URL Test',
) );
$message = null;
$error = false;
if ( is_wp_error( $response ) ) {
$error = $response->get_error_message();
if ( strpos( $message, 'resolve host' ) !== false ) {
$message = array( 'error' => __( 'Invalid host name.' ) );
if ( strpos( $response->get_error_message(), 'resolve host' ) !== false ) {
$error = true;
}
wp_send_json_error( $message );
} elseif ( wp_remote_retrieve_response_code( $response ) === 404 ) {
$error = true;
}
if ( wp_remote_retrieve_response_code( $response ) === 404 ) {
wp_send_json_error( array( 'error' => __( 'Not found, HTTP error 404.' ) ) );
if ( $error ) {
wp_send_json_error( array( 'httpError' => true ) );
}
wp_send_json_success();

View File

@ -1065,7 +1065,7 @@ final class _WP_Editors {
'Ctrl + letter:' => __( 'Ctrl + letter:' ),
'Letter' => __( 'Letter' ),
'Action' => __( 'Action' ),
'Invalid host name.' => __( 'Invalid host name.' ),
'Warning: the link has been inserted but the destination cannot be reached.' => __( 'Warning: the link has been inserted but the destination cannot be reached.' ),
'To move focus to other buttons use Tab or the arrow keys. To return focus to the editor press Escape or use one of the buttons.' =>
__( 'To move focus to other buttons use Tab or the arrow keys. To return focus to the editor press Escape or use one of the buttons.' ),
'When starting a new paragraph with one of these formatting shortcuts followed by a space, the formatting will be applied automatically. Press Backspace or Escape to undo.' =>

View File

@ -94,6 +94,9 @@
var doingUndoRedoTimer;
var $ = window.jQuery;
var urlErrors = {};
var emailRegex = /^(mailto:)?[a-z0-9._%+-]+@[a-z0-9][a-z0-9.-]*\.[a-z]{2,63}$/i;
var speak = ( typeof window.wp !== 'undefined' && window.wp.a11y && window.wp.a11y.speak ) ? window.wp.a11y.speak : function() {};
var hasLinkError = false;
function getSelectedLink() {
var href, html,
@ -147,6 +150,16 @@
});
}
function setLinkError( $link ) {
hasLinkError = true;
$link.attr( 'data-wplink-url-error', 'true' );
speak( editor.translate( 'Warning: the link has been inserted but the destination cannot be reached.' ), 'assertive' );
if ( toolbar && toolbar.visible() ) {
toolbar.$el.find( '.wp-link-preview a' ).addClass( 'wplink-url-error' );
}
}
function checkLink( node ) {
var $link = editor.$( node );
var href = $link.attr( 'href' );
@ -155,13 +168,14 @@
return;
}
// Early check
if ( /^http/i.test( href ) && ! /\.[a-z]{2,63}(\/|$)/i.test( href ) ) {
urlErrors[href] = tinymce.translate( 'Invalid host name.' );
hasLinkError = false;
if ( /^http/i.test( href ) && ! /^https?:\/\/[a-z0-9][a-z0-9.-]*\.[a-z]{2,63}(\/|$)/i.test( href ) ) {
urlErrors[href] = true;
}
if ( urlErrors.hasOwnProperty( href ) ) {
$link.attr( 'data-wplink-url-error', 'true' );
setLinkError( $link );
return;
} else {
$link.removeAttr( 'data-wplink-url-error' );
@ -179,13 +193,9 @@
return;
}
if ( response.data && response.data.error ) {
urlErrors[href] = response.data.error;
$link.attr( 'data-wplink-url-error', 'true' );
if ( toolbar && toolbar.visible() ) {
toolbar.$el.find( '.wp-link-preview a' ).addClass( 'wplink-url-error' ).attr( 'title', editor.dom.encode( response.data.error ) );
}
if ( response.data && response.data.httpError ) {
urlErrors[href] = true;
setLinkError( $link );
}
});
}
@ -274,7 +284,7 @@
return;
}
if ( ! /^(?:[a-z]+:|#|\?|\.|\/)/.test( href ) ) {
if ( ! /^(?:[a-z]+:|#|\?|\.|\/)/.test( href ) && ! emailRegex.test( href ) ) {
href = 'http://' + href;
}
@ -291,8 +301,8 @@
editor.nodeChanged();
// Audible confirmation message when a link has been inserted in the Editor.
if ( typeof window.wp !== 'undefined' && window.wp.a11y && typeof window.wpLinkL10n !== 'undefined' ) {
window.wp.a11y.speak( window.wpLinkL10n.linkInserted );
if ( typeof window.wpLinkL10n !== 'undefined' && ! hasLinkError ) {
speak( window.wpLinkL10n.linkInserted );
}
} );
@ -449,10 +459,9 @@
$input.val( ui.item.permalink );
$( element.firstChild.nextSibling ).val( ui.item.title );
if ( 9 === event.keyCode && typeof window.wp !== 'undefined' &&
window.wp.a11y && typeof window.wpLinkL10n !== 'undefined' ) {
if ( 9 === event.keyCode && typeof window.wpLinkL10n !== 'undefined' ) {
// Audible confirmation message when a link has been selected.
window.wp.a11y.speak( window.wpLinkL10n.linkSelected );
speak( window.wpLinkL10n.linkSelected );
}
return false;
@ -536,7 +545,7 @@
editor.on( 'wptoolbar', function( event ) {
var linkNode = editor.dom.getParent( event.element, 'a' ),
$linkNode, href, edit, title;
$linkNode, href, edit;
if ( typeof window.wpLink !== 'undefined' && window.wpLink.modalOpen ) {
editToolbar.tempHide = true;
@ -561,12 +570,12 @@
previewInstance.setURL( href );
event.element = linkNode;
event.toolbar = toolbar;
title = urlErrors.hasOwnProperty( href ) ? editor.dom.encode( urlErrors[ href ] ) : null;
if ( $linkNode.attr( 'data-wplink-url-error' ) === 'true' ) {
toolbar.$el.find( '.wp-link-preview a' ).addClass( 'wplink-url-error' ).attr( 'title', title );
toolbar.$el.find( '.wp-link-preview a' ).addClass( 'wplink-url-error' );
} else {
toolbar.$el.find( '.wp-link-preview a' ).removeClass( 'wplink-url-error' ).attr( 'title', null );
toolbar.$el.find( '.wp-link-preview a' ).removeClass( 'wplink-url-error' );
hasLinkError = false;
}
}
} else if ( editToolbar.visible() ) {

View File

@ -2,8 +2,8 @@ var wpLink;
( function( $, wpLinkL10n, wp ) {
var editor, searchTimer, River, Query, correctedURL, linkNode,
emailRegexp = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
urlRegexp = /^(https?|ftp):\/\/[A-Z0-9.-]+\.[A-Z]{2,4}[^ "]*$/i,
emailRegexp = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,63}$/i,
urlRegexp = /^(https?|ftp):\/\/[A-Z0-9.-]+\.[A-Z]{2,63}[^ "]*$/i,
inputs = {},
rivers = {},
isTouch = ( 'ontouchend' in document );