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.
Built from https://develop.svn.wordpress.org/trunk@38126


git-svn-id: http://core.svn.wordpress.org/trunk@38067 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Andrew Ozz 2016-07-21 03:42:34 +00:00
parent e6267dcf19
commit 04319a7898
8 changed files with 44 additions and 36 deletions

View File

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

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

@ -4,7 +4,7 @@
* *
* @global string $wp_version * @global string $wp_version
*/ */
$wp_version = '4.6-beta4-38125'; $wp_version = '4.6-beta4-38126';
/** /**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.