Skip to content

Commit

Permalink
Add new "Post Time To Read" block
Browse files Browse the repository at this point in the history
  • Loading branch information
t-hamano committed Sep 18, 2022
1 parent 533e0b7 commit 06f27dd
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 0 deletions.
9 changes: 9 additions & 0 deletions docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,15 @@ Post terms. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages
- **Supports:** color (background, gradients, link, text), typography (fontSize, lineHeight), ~~html~~
- **Attributes:** prefix, separator, suffix, term, textAlign

## Post Time To Read

Time to read the post. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-time-to-read))

- **Name:** core/post-time-to-read
- **Category:** theme
- **Supports:** ~~html~~
- **Attributes:** minutesToRead, textAlign

## Post Title

Displays the title of a post, page, or any other content-type. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/post-title))
Expand Down
1 change: 1 addition & 0 deletions lib/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ function gutenberg_reregister_core_block_types() {
'post-featured-image.php' => 'core/post-featured-image',
'post-navigation-link.php' => 'core/post-navigation-link',
'post-terms.php' => 'core/post-terms',
'post-time-to-read.php' => 'core/post-time-to-read',
'post-title.php' => 'core/post-title',
'query.php' => 'core/query',
'post-template.php' => 'core/post-template',
Expand Down
2 changes: 2 additions & 0 deletions packages/block-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@wordpress/date": "file:../date",
"@wordpress/deprecated": "file:../deprecated",
"@wordpress/dom": "file:../dom",
"@wordpress/editor": "file:../editor",
"@wordpress/element": "file:../element",
"@wordpress/hooks": "file:../hooks",
"@wordpress/html-entities": "file:../html-entities",
Expand All @@ -57,6 +58,7 @@
"@wordpress/server-side-render": "file:../server-side-render",
"@wordpress/url": "file:../url",
"@wordpress/viewport": "file:../viewport",
"@wordpress/wordcount": "file:../wordcount",
"change-case": "^4.1.2",
"classnames": "^2.3.1",
"colord": "^2.7.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/block-library/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ import * as postFeaturedImage from './post-featured-image';
import * as postNavigationLink from './post-navigation-link';
import * as postTemplate from './post-template';
import * as postTerms from './post-terms';
import * as postTimeToRead from './post-time-to-read';
import * as postTitle from './post-title';
import * as preformatted from './preformatted';
import * as pullquote from './pullquote';
Expand Down Expand Up @@ -195,6 +196,7 @@ const getAllBlocks = () =>
postTerms,
postNavigationLink,
postTemplate,
postTimeToRead,
queryPagination,
queryPaginationNext,
queryPaginationNumbers,
Expand Down
21 changes: 21 additions & 0 deletions packages/block-library/src/post-time-to-read/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 2,
"name": "core/post-time-to-read",
"title": "Post Time To Read",
"category": "theme",
"description": "Time to read the post.",
"textdomain": "default",
"usesContext": [ "postType", "postId" ],
"attributes": {
"textAlign": {
"type": "string"
},
"minutesToRead": {
"type": "number"
}
},
"supports": {
"html": false
}
}
96 changes: 96 additions & 0 deletions packages/block-library/src/post-time-to-read/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import {
AlignmentControl,
BlockControls,
store as blockEditorStore,
useBlockProps,
} from '@wordpress/block-editor';
import { store as editorStore } from '@wordpress/editor';
import { useDispatch, useSelect } from '@wordpress/data';
import { useEffect } from '@wordpress/element';
import { _x, _n, __, sprintf } from '@wordpress/i18n';
import { count as wordCount } from '@wordpress/wordcount';

/**
* Average reading rate - based on average taken from
* https://irisreading.com/average-reading-speed-in-various-languages/
* (Characters/minute used for Chinese rather than words).
*/
const AVERAGE_READING_RATE = 189;

function PostTimeToReadEdit( { attributes, setAttributes } ) {
const { textAlign, minutesToRead } = attributes;

const content = useSelect(
( select ) => select( editorStore ).getEditedPostAttribute( 'content' ),
[]
);

const { __unstableMarkNextChangeAsNotPersistent } =
useDispatch( blockEditorStore );

/*
* 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!' );

useEffect( () => {
const newMinutesToRead = Math.round(
wordCount( content, wordCountType ) / AVERAGE_READING_RATE
);
// This is required to keep undo working and not create 2 undo steps
// for the content change.
__unstableMarkNextChangeAsNotPersistent();
setAttributes( {
minutesToRead: content ? newMinutesToRead : undefined,
} );
}, [ content ] );

let minutesToReadString = __( 'There is no content.' );

if ( minutesToRead !== undefined ) {
minutesToReadString =
minutesToRead !== 0
? sprintf(
/* translators: %d is the number of minutes the post will take to read. */
_n(
'You can read this post in %d minute.',
'You can read this post in %d minutes.',
minutesToRead
),
minutesToRead
)
: __( 'You can read this post less than a minute.' );
}

const blockProps = useBlockProps( {
className: classnames( {
[ `has-text-align-${ textAlign }` ]: textAlign,
} ),
} );

return (
<>
<BlockControls group="block">
<AlignmentControl
value={ textAlign }
onChange={ ( nextAlign ) => {
setAttributes( { textAlign: nextAlign } );
} }
/>
</BlockControls>
<p { ...blockProps }>{ minutesToReadString }</p>
</>
);
}

export default PostTimeToReadEdit;
15 changes: 15 additions & 0 deletions packages/block-library/src/post-time-to-read/icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* WordPress dependencies
*/
import { SVG, Path } from '@wordpress/components';

export default (
<SVG
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<Path d="M 12 3.25 a 8.75 8.75 0 1 0 0 17.5 a 8.75 8.75 0 0 0 0 -17.5 Z m -7.25 8.75 a 7.25 7.25 0 1 1 14.5 0 a 7.25 7.25 0 0 1 -14.5 0 z m 10.3 1.97 l -2.28 -2.28 V 8.5 a 0.75 0.75 0 0 0 -1.5 0 V 12 a 0.747 0.747 0 0 0 0.218 0.529 l 1.282 -0.84 l -1.28 0.842 l 2.5 2.5 a 0.75 0.75 0 1 0 1.06 -1.061 z" />
</SVG>
);
17 changes: 17 additions & 0 deletions packages/block-library/src/post-time-to-read/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Internal dependencies
*/
import initBlock from '../utils/init-block';
import metadata from './block.json';
import edit from './edit';
import icon from './icon';

const { name } = metadata;
export { metadata, name };

export const settings = {
icon,
edit,
};

export const init = () => initBlock( { name, metadata, settings } );
57 changes: 57 additions & 0 deletions packages/block-library/src/post-time-to-read/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php
/**
* Server-side rendering of the `core/post-time-to-read` block.
*
* @package WordPress
*/

/**
* Renders the `core/post-time-to-read` block on the server.
*
* @param array $attributes Block attributes.
* @param string $content Block default content.
* @param WP_Block $block Block instance.
* @return string Returns the rendered post author name block.
*/
function render_block_core_post_time_to_read( $attributes, $content, $block ) {
if ( ! isset( $block->context['postId'] ) ) {
return '';
}

$minutes_to_read = ! empty( $attributes['minutesToRead'] ) ? (int) $attributes['minutesToRead'] : 0;

$minutes_to_read_string = $minutes_to_read !== 0
? sprintf(
/* translators: %d is the number of minutes the post will take to read. */
_n(
'You can read this post in %d minute.',
'You can read this post in %d minutes.',
$minutes_to_read
),
$minutes_to_read
)
: __( 'You can read this post less than a minute.' );

$align_class_name = empty( $attributes['textAlign'] ) ? '' : "has-text-align-{$attributes['textAlign']}";

$wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $align_class_name ) );

return sprintf(
'<p %1$s>%2$s</p>',
$wrapper_attributes,
$minutes_to_read_string
);
}

/**
* Registers the `core/post-time-to-read` block on the server.
*/
function register_block_core_post_time_to_read() {
register_block_type_from_metadata(
__DIR__ . '/post-time-to-read',
array(
'render_callback' => 'render_block_core_post_time_to_read',
)
);
}
add_action( 'init', 'register_block_core_post_time_to_read' );

0 comments on commit 06f27dd

Please sign in to comment.