Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rich text: only consider a format active if active at every selected index #48789

Merged
merged 5 commits into from
Mar 20, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 2 additions & 32 deletions packages/block-editor/src/components/rich-text/format-edit.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
/**
* WordPress dependencies
*/
import {
getActiveFormat,
getActiveObject,
isCollapsed,
} from '@wordpress/rich-text';
import { getActiveFormat, getActiveObject } from '@wordpress/rich-text';

export default function FormatEdit( {
formatTypes,
Expand All @@ -22,37 +18,11 @@ export default function FormatEdit( {
}

const activeFormat = getActiveFormat( value, name );
let isActive = activeFormat !== undefined;
const isActive = activeFormat !== undefined;
const activeObject = getActiveObject( value );
const isObjectActive =
activeObject !== undefined && activeObject.type === name;

// Edge case: un-collapsed link formats.
// If there is a missing link format at either end of the selection
// then we shouldn't show the Edit UI because the selection has exceeded
// the bounds of the link format.
// Also if the format objects don't match then we're dealing with two separate
// links so we should not allow the link to be modified over the top.
if ( name === 'core/link' && ! isCollapsed( value ) ) {
const formats = value.formats;

const linkFormatAtStart = formats[ value.start ]?.find(
( { type } ) => type === 'core/link'
);

const linkFormatAtEnd = formats[ value.end - 1 ]?.find(
( { type } ) => type === 'core/link'
);

if (
! linkFormatAtStart ||
! linkFormatAtEnd ||
linkFormatAtStart !== linkFormatAtEnd
) {
isActive = false;
}
}

return (
<Edit
key={ name }
Expand Down
38 changes: 33 additions & 5 deletions packages/rich-text/src/get-active-formats.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
/** @typedef {import('./create').RichTextValue} RichTextValue */
/** @typedef {import('./create').RichTextFormatList} RichTextFormatList */

/**
* Internal dependencies
*/
import { slice } from './slice';

/**
* Gets the all format objects at the start of the selection.
*
Expand All @@ -10,10 +15,8 @@
*
* @return {RichTextFormatList} Active format objects.
*/
export function getActiveFormats(
{ formats, start, end, activeFormats },
EMPTY_ACTIVE_FORMATS = []
) {
export function getActiveFormats( value, EMPTY_ACTIVE_FORMATS = [] ) {
const { formats, start, end, activeFormats } = value;
if ( start === undefined ) {
return EMPTY_ACTIVE_FORMATS;
}
Expand All @@ -37,5 +40,30 @@ export function getActiveFormats(
return formatsAfter;
}

return formats[ start ] || EMPTY_ACTIVE_FORMATS;
// If there's no formats at the start index, there are not active formats.
if ( ! formats[ start ] ) {
return EMPTY_ACTIVE_FORMATS;
}

const selectedValue = slice( value );

let _activeFormats = selectedValue.formats[ 0 ];
let i = selectedValue.formats.length;

while ( i-- ) {
const formatsAtIndex = selectedValue.formats[ i ];

// If we run into any index without formats, we're sure that there's no
// active formats.
if ( ! formatsAtIndex ) {
return EMPTY_ACTIVE_FORMATS;
}

// Only keep an acive format if it's active for every single index.
ellatrix marked this conversation as resolved.
Show resolved Hide resolved
_activeFormats = _activeFormats.filter(
( format, index ) => format === formatsAtIndex[ index ]
);
}

return _activeFormats || EMPTY_ACTIVE_FORMATS;
}