Skip to content

Commit

Permalink
Post excerpt: Add excerpt length control (#44964)
Browse files Browse the repository at this point in the history
* Post excerpt: Add excerpt length control
  • Loading branch information
carolinan authored Feb 9, 2023
1 parent 2c17b65 commit 86d527c
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 15 deletions.
2 changes: 1 addition & 1 deletion docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ Display a post's excerpt. ([Source](https://github.com/WordPress/gutenberg/tree/
- **Name:** core/post-excerpt
- **Category:** theme
- **Supports:** anchor, color (background, gradients, link, text), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
- **Attributes:** moreText, showMoreOnNewLine, textAlign
- **Attributes:** excerptLength, moreText, showMoreOnNewLine, textAlign

## Post Featured Image

Expand Down
4 changes: 4 additions & 0 deletions packages/block-library/src/post-excerpt/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
"showMoreOnNewLine": {
"type": "boolean",
"default": true
},
"excerptLength": {
"type": "number",
"default": 55
}
},
"usesContext": [ "postId", "postType", "queryId" ],
Expand Down
79 changes: 72 additions & 7 deletions packages/block-library/src/post-excerpt/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,24 @@ import {
Warning,
useBlockProps,
} from '@wordpress/block-editor';
import { PanelBody, ToggleControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { PanelBody, ToggleControl, RangeControl } from '@wordpress/components';
import { __, _x } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { useCanEditEntity } from '../utils/hooks';

export default function PostExcerptEditor( {
attributes: { textAlign, moreText, showMoreOnNewLine },
attributes: { textAlign, moreText, showMoreOnNewLine, excerptLength },
setAttributes,
isSelected,
context: { postId, postType, queryId },
} ) {
const isDescendentOfQueryLoop = Number.isFinite( queryId );
const userCanEdit = useCanEditEntity( 'postType', postType, postId );
const isEditable = userCanEdit && ! isDescendentOfQueryLoop;

const [
rawExcerpt,
setExcerpt,
Expand All @@ -43,6 +44,14 @@ export default function PostExcerptEditor( {
[ `has-text-align-${ textAlign }` ]: textAlign,
} ),
} );

/**
* translators: If your word count is based on single characters (e.g. East Asian characters),
* enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'.
* Do not translate into your own language.
*/
const wordCountType = _x( 'words', 'Word count type. Do not translate!' );

/**
* When excerpt is editable, strip the html tags from
* rendered excerpt. This will be used if the entity's
Expand Down Expand Up @@ -109,21 +118,67 @@ export default function PostExcerptEditor( {
const excerptClassName = classnames( 'wp-block-post-excerpt__excerpt', {
'is-inline': ! showMoreOnNewLine,
} );

/**
* The excerpt length setting needs to be applied to both
* the raw and the rendered excerpt depending on which is being used.
*/
const rawOrRenderedExcerpt = !! renderedExcerpt
? strippedRenderedExcerpt
: rawExcerpt;

let trimmedExcerpt = '';
if ( wordCountType === 'words' ) {
trimmedExcerpt = rawOrRenderedExcerpt
.trim()
.split( ' ', excerptLength )
.join( ' ' );
} else if ( wordCountType === 'characters_excluding_spaces' ) {
/*
* 1. Split the excerpt at the character limit,
* then join the substrings back into one string.
* 2. Count the number of spaces in the excerpt
* by comparing the lengths of the string with and without spaces.
* 3. Add the number to the length of the visible excerpt,
* so that the spaces are excluded from the word count.
*/
const excerptWithSpaces = rawOrRenderedExcerpt
.trim()
.split( '', excerptLength )
.join( '' );

const numberOfSpaces =
excerptWithSpaces.length -
excerptWithSpaces.replaceAll( ' ', '' ).length;

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

trimmedExcerpt = trimmedExcerpt + '...';

const excerptContent = isEditable ? (
<RichText
className={ excerptClassName }
aria-label={ __( 'Post excerpt text' ) }
value={
rawExcerpt ||
strippedRenderedExcerpt ||
( isSelected ? '' : __( 'No post excerpt found' ) )
isSelected
? rawOrRenderedExcerpt
: ( trimmedExcerpt !== '...' ? trimmedExcerpt : '' ) ||
__( 'No post excerpt found' )
}
onChange={ setExcerpt }
tagName="p"
/>
) : (
<p className={ excerptClassName }>
{ strippedRenderedExcerpt || __( 'No post excerpt found' ) }
{ trimmedExcerpt !== '...'
? trimmedExcerpt
: __( 'No post excerpt found' ) }
</p>
);
return (
Expand All @@ -147,6 +202,16 @@ export default function PostExcerptEditor( {
} )
}
/>
<RangeControl
label={ __( 'Max number of words' ) }
value={ excerptLength }
onChange={ ( value ) => {
setAttributes( { excerptLength: value } );
setExcerpt();
} }
min="10"
max="100"
/>
</PanelBody>
</InspectorControls>
<div { ...blockProps }>
Expand Down
34 changes: 29 additions & 5 deletions packages/block-library/src/post-excerpt/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,18 @@ function render_block_core_post_excerpt( $attributes, $content, $block ) {
return '';
}

$excerpt = get_the_excerpt();

if ( empty( $excerpt ) ) {
return '';
/*
* The purpose of the excerpt length setting is to limit the length of both
* automatically generated and user-created excerpts.
* Because the excerpt_length filter only applies to auto generated excerpts,
* wp_trim_words is used instead.
*/
$excerpt_length = $attributes['excerptLength'];
if ( isset( $excerpt_length ) ) {
$excerpt = wp_trim_words( get_the_excerpt(), $excerpt_length );
} else {
$excerpt = get_the_excerpt();
}

$more_text = ! empty( $attributes['moreText'] ) ? '<a class="wp-block-post-excerpt__more-link" href="' . esc_url( get_the_permalink( $block->context['postId'] ) ) . '">' . wp_kses_post( $attributes['moreText'] ) . '</a>' : '';
$filter_excerpt_more = function( $more ) use ( $more_text ) {
return empty( $more_text ) ? $more : '';
Expand Down Expand Up @@ -70,3 +76,21 @@ function register_block_core_post_excerpt() {
);
}
add_action( 'init', 'register_block_core_post_excerpt' );

/**
* If themes or plugins filter the excerpt_length, we need to
* override the filter in the editor, otherwise
* the excerpt length block setting has no effect.
* Returns 100 because 100 is the max length in the setting.
*/
if ( is_admin() ||
defined( 'REST_REQUEST' ) ||
'REST_REQUEST' ) {
add_filter(
'excerpt_length',
function() {
return 100;
},
PHP_INT_MAX
);
}
3 changes: 2 additions & 1 deletion test/integration/fixtures/blocks/core__post-excerpt.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"name": "core/post-excerpt",
"isValid": true,
"attributes": {
"showMoreOnNewLine": true
"showMoreOnNewLine": true,
"excerptLength": 55
},
"innerBlocks": []
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@
"name": "core/post-excerpt",
"isValid": true,
"attributes": {
"showMoreOnNewLine": true
"showMoreOnNewLine": true,
"excerptLength": 55
},
"innerBlocks": []
}
Expand Down

0 comments on commit 86d527c

Please sign in to comment.