Skip to content

Commit

Permalink
Prevent link paste in RichText components in Button and Navigation bl…
Browse files Browse the repository at this point in the history
…ocks (#28130)
  • Loading branch information
youknowriad authored Jan 13, 2021
1 parent d8c5dee commit 2408100
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 48 deletions.
34 changes: 1 addition & 33 deletions packages/rich-text/src/component/format-edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,20 @@
import { getActiveFormat } from '../get-active-format';
import { getActiveObject } from '../get-active-object';

/**
* Set of all interactive content tags.
*
* @see https://html.spec.whatwg.org/multipage/dom.html#interactive-content
*/
const interactiveContentTags = new Set( [
'a',
'audio',
'button',
'details',
'embed',
'iframe',
'input',
'label',
'select',
'textarea',
'video',
] );

export default function FormatEdit( {
formatTypes,
onChange,
onFocus,
value,
allowedFormats,
withoutInteractiveFormatting,
forwardedRef,
} ) {
return formatTypes.map( ( settings ) => {
const { name, edit: Edit, tagName } = settings;
const { name, edit: Edit } = settings;

if ( ! Edit ) {
return null;
}

if ( allowedFormats && allowedFormats.indexOf( name ) === -1 ) {
return null;
}

if (
withoutInteractiveFormatting &&
interactiveContentTags.has( tagName )
) {
return null;
}

const activeFormat = getActiveFormat( value, name );
const isActive = activeFormat !== undefined;
const activeObject = getActiveObject( value );
Expand Down
6 changes: 2 additions & 4 deletions packages/rich-text/src/component/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ function RichText(
} = useFormatTypes( {
clientId,
identifier,
withoutInteractiveFormatting,
allowedFormats,
} );

// For backward compatibility, fall back to tagName if it's a string.
Expand Down Expand Up @@ -1102,10 +1104,6 @@ function RichText(
<>
{ isSelected && (
<FormatEdit
allowedFormats={ allowedFormats }
withoutInteractiveFormatting={
withoutInteractiveFormatting
}
value={ record.current }
onChange={ handleChange }
onFocus={ focus }
Expand Down
18 changes: 12 additions & 6 deletions packages/rich-text/src/component/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { useFormatTypes } from './use-format-types';
import FormatEdit from './format-edit';
import { applyFormat } from '../apply-format';
import { getActiveFormat } from '../get-active-format';
Expand All @@ -46,7 +47,6 @@ import { isCollapsed } from '../is-collapsed';
import { remove } from '../remove';
import styles from './style.scss';
import ToolbarButtonWithOptions from './toolbar-button-with-options';
import { store as richTextStore } from '../store';

const unescapeSpaces = ( text ) => {
return text.replace( /&nbsp;|&#160;/gi, ' ' );
Expand Down Expand Up @@ -799,7 +799,6 @@ export class RichText extends Component {
maxWidth,
formatTypes,
parentBlockStyles,
withoutInteractiveFormatting,
accessibilityLabel,
disableEditingMenu = false,
} = this.props;
Expand Down Expand Up @@ -953,9 +952,6 @@ export class RichText extends Component {
<FormatEdit
formatTypes={ formatTypes }
value={ record }
withoutInteractiveFormatting={
withoutInteractiveFormatting
}
onChange={ this.onFormatChange }
onFocus={ () => {} }
/>
Expand All @@ -977,6 +973,16 @@ RichText.defaultProps = {
tagName: 'div',
};

const withFormatTypes = ( WrappedComponent ) => ( props ) => {
const { formatTypes } = useFormatTypes( {
clientId: props.clientId,
identifier: props.identifier,
withoutInteractiveFormatting: props.withoutInteractiveFormatting,
} );

return <WrappedComponent { ...props } formatTypes={ formatTypes } />;
};

export default compose( [
withSelect( ( select, { clientId } ) => {
const { getBlockParents, getBlock, getSettings } = select(
Expand All @@ -988,12 +994,12 @@ export default compose( [
get( parentBlock, [ 'attributes', 'childrenStyles' ] ) || {};

return {
formatTypes: select( richTextStore ).getFormatTypes(),
areMentionsSupported:
getSettings( 'capabilities' ).mentions === true,
areXPostsSupported: getSettings( 'capabilities' ).xposts === true,
...{ parentBlockStyles },
};
} ),
withPreferredColorScheme,
withFormatTypes,
] )( RichText );
53 changes: 48 additions & 5 deletions packages/rich-text/src/component/use-format-types.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* WordPress dependencies
*/
import { useMemo } from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
/**
* Internal dependencies
Expand All @@ -11,16 +12,58 @@ function formatTypesSelector( select ) {
return select( richTextStore ).getFormatTypes();
}

/**
* Set of all interactive content tags.
*
* @see https://html.spec.whatwg.org/multipage/dom.html#interactive-content
*/
const interactiveContentTags = new Set( [
'a',
'audio',
'button',
'details',
'embed',
'iframe',
'input',
'label',
'select',
'textarea',
'video',
] );

/**
* This hook provides RichText with the `formatTypes` and its derived props from
* experimental format type settings.
*
* @param {Object} $0 Options
* @param {string} $0.clientId Block client ID.
* @param {string} $0.identifier Block attribute.
* @param {Object} $0 Options
* @param {string} $0.clientId Block client ID.
* @param {string} $0.identifier Block attribute.
* @param {boolean} $0.withoutInteractiveFormatting Whether to clean the interactive formattings or not.
* @param {Array} $0.allowedFormats Allowed formats
*/
export function useFormatTypes( { clientId, identifier } ) {
const formatTypes = useSelect( formatTypesSelector, [] );
export function useFormatTypes( {
clientId,
identifier,
withoutInteractiveFormatting,
allowedFormats,
} ) {
const allFormatTypes = useSelect( formatTypesSelector, [] );
const formatTypes = useMemo( () => {
return allFormatTypes.filter( ( { name, tagName } ) => {
if ( allowedFormats && allowedFormats.includes( name ) ) {
return false;
}

if (
withoutInteractiveFormatting &&
interactiveContentTags.has( tagName )
) {
return false;
}

return true;
} );
}, [ allFormatTypes, allowedFormats, interactiveContentTags ] );
const keyedSelected = useSelect(
( select ) =>
formatTypes.reduce( ( accumulator, type ) => {
Expand Down

0 comments on commit 2408100

Please sign in to comment.