Skip to content
58 changes: 42 additions & 16 deletions packages/block-library/src/post-excerpt/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { useEntityProp } from '@wordpress/core-data';
import { useEntityProp, store as coreStore } from '@wordpress/core-data';
import { useMemo } from '@wordpress/element';
import {
AlignmentToolbar,
Expand All @@ -18,6 +18,7 @@ import {
} from '@wordpress/block-editor';
import { PanelBody, ToggleControl, RangeControl } from '@wordpress/components';
import { __, _x } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
Expand All @@ -32,13 +33,40 @@ export default function PostExcerptEditor( {
} ) {
const isDescendentOfQueryLoop = Number.isFinite( queryId );
const userCanEdit = useCanEditEntity( 'postType', postType, postId );
const isEditable = userCanEdit && ! isDescendentOfQueryLoop;

const [
rawExcerpt,
setExcerpt,
{ rendered: renderedExcerpt, protected: isProtected } = {},
] = useEntityProp( 'postType', postType, 'excerpt', postId );

// Check if the post type supports excerpts.
let postTypeSupportsExcerpts = useSelect( ( select ) =>
postType
? !! select( coreStore ).getPostType( postType )?.supports.excerpt
: false
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few notes:

  • The useSelect needs a postType dependency.
  • We can return true early when postType === page from the selector.
  • There's no need for ternary. Casting the return value to boolean will do the trick.

The end results will be something like this:

// Check if the post type supports excerpts.
const postTypeSupportsExcerpts = useSelect(
	( select ) => {
		if ( postType === 'page' ) {
			return true;
		}

		return !! select( coreStore ).getPostType( postType )?.supports
			.excerpt;
	},
	[ postType ]
);


/**
* Add an exception for the page post type,
* which is registered without support for the excerpt UI,
* but supports saving the excerpt to the database.
* See: https://core.trac.wordpress.org/browser/branches/6.1/src/wp-includes/post.php#L65
* Without this exception, users that have excerpts saved to the database will
* not be able to edit the excerpts.
*/
if ( postType === 'page' ) {
postTypeSupportsExcerpts = true;
}

/**
* The excerpt is editable if:
* - The user can edit the post
* - It is not a descendent of a Query Loop block
* - The post type supports excerpts
*/
const isEditable =
userCanEdit && ! isDescendentOfQueryLoop && postTypeSupportsExcerpts;

const blockProps = useBlockProps( {
className: classnames( {
[ `has-text-align-${ textAlign }` ]: textAlign,
Expand Down Expand Up @@ -122,15 +150,14 @@ export default function PostExcerptEditor( {
/**
* The excerpt length setting needs to be applied to both
* the raw and the rendered excerpt depending on which is being used.
* If there is no excerpt the value is set to '' to make sure it is not undefined (See line 89).
*/
const rawOrRenderedExcerpt = !! renderedExcerpt
? strippedRenderedExcerpt
: rawExcerpt;
let rawOrRenderedExcerpt = rawExcerpt || strippedRenderedExcerpt;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which excerpt variation is preferred here when we have both?

Copy link
Contributor Author

@carolinan carolinan Mar 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm yes In this case the rawExcerpt should be prioritized because it is the customized excerpt text.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I asked because the previous logic prioritized renderedExcerpt if it was available, and here we're changing the logic.

Suggestion (non-blocking): You can also use parentheses around expression and trim returned value in a single go:

const rawOrRenderedExcerpt = ( rawExcerpt || strippedRenderedExcerpt ).trim();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the previous logic was wrong and this would correct it.
Looking at the code before #44964, the rawExcerpt comes first.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the confirmation, @carolinan!

rawOrRenderedExcerpt = rawOrRenderedExcerpt.trim();

let trimmedExcerpt = '';
if ( wordCountType === 'words' ) {
trimmedExcerpt = rawOrRenderedExcerpt
.trim()
.split( ' ', excerptLength )
.join( ' ' );
} else if ( wordCountType === 'characters_excluding_spaces' ) {
Expand All @@ -143,7 +170,6 @@ export default function PostExcerptEditor( {
* so that the spaces are excluded from the word count.
*/
const excerptWithSpaces = rawOrRenderedExcerpt
.trim()
.split( '', excerptLength )
.join( '' );

Expand All @@ -152,14 +178,13 @@ export default function PostExcerptEditor( {
excerptWithSpaces.replaceAll( ' ', '' ).length;

trimmedExcerpt = rawOrRenderedExcerpt
.trim()
.split( '', excerptLength + numberOfSpaces )
.join( '' );
} else if ( wordCountType === 'characters_including_spaces' ) {
trimmedExcerpt = rawOrRenderedExcerpt.trim().split( '', excerptLength );
trimmedExcerpt = rawOrRenderedExcerpt.split( '', excerptLength );
}

trimmedExcerpt = trimmedExcerpt + '...';
const isTrimmed = trimmedExcerpt !== rawOrRenderedExcerpt ? true : false;

const excerptContent = isEditable ? (
<RichText
Expand All @@ -168,17 +193,19 @@ export default function PostExcerptEditor( {
value={
isSelected
? rawOrRenderedExcerpt
: ( trimmedExcerpt !== '...' ? trimmedExcerpt : '' ) ||
: ( ! isTrimmed
? rawOrRenderedExcerpt
: trimmedExcerpt + '…' ) ||
__( 'No post excerpt found' )
}
onChange={ setExcerpt }
tagName="p"
/>
) : (
<p className={ excerptClassName }>
{ trimmedExcerpt !== '...'
? trimmedExcerpt
: __( 'No post excerpt found' ) }
{ ! isTrimmed
? rawOrRenderedExcerpt || __( 'No post excerpt found' )
: trimmedExcerpt + '…' }
</p>
);
return (
Expand Down Expand Up @@ -208,7 +235,6 @@ export default function PostExcerptEditor( {
value={ excerptLength }
onChange={ ( value ) => {
setAttributes( { excerptLength: value } );
setExcerpt();
} }
min="10"
max="100"
Expand Down