build/scripts/block-library
accordion
6 months ago
accordion-heading
9 months ago
accordion-item
4 months ago
accordion-panel
7 months ago
archives
7 months ago
audio
10 months ago
avatar
7 months ago
block
7 months ago
breadcrumbs
7 months ago
button
6 months ago
buttons
7 months ago
calendar
7 months ago
categories
7 months ago
code
10 months ago
column
10 months ago
columns
10 months ago
comment-author-avatar
10 months ago
comment-author-name
7 months ago
comment-content
7 months ago
comment-date
7 months ago
comment-edit-link
7 months ago
comment-reply-link
7 months ago
comment-template
7 months ago
comments
7 months ago
comments-pagination
7 months ago
comments-pagination-next
7 months ago
comments-pagination-numbers
7 months ago
comments-pagination-previous
7 months ago
comments-title
7 months ago
cover
10 months ago
details
10 months ago
embed
7 months ago
file
10 months ago
footnotes
7 months ago
form
4 months ago
form-input
4 months ago
form-submission-notification
4 months ago
form-submit-button
4 months ago
freeform
7 months ago
gallery
6 months ago
group
4 months ago
heading
7 months ago
home-link
7 months ago
html
5 months ago
icon
5 months ago
image
6 months ago
latest-comments
7 months ago
latest-posts
7 months ago
list
7 months ago
list-item
5 months ago
loginout
7 months ago
math
7 months ago
media-text
10 months ago
missing
7 months ago
more
7 months ago
navigation
6 months ago
navigation-link
5 months ago
navigation-overlay-close
6 months ago
navigation-submenu
6 months ago
nextpage
5 months ago
page-list
6 months ago
page-list-item
6 months ago
paragraph
6 months ago
pattern
9 months ago
playlist
6 months ago
playlist-track
6 months ago
post-author
6 months ago
post-author-biography
6 months ago
post-author-name
6 months ago
post-comment
10 months ago
post-comments-count
6 months ago
post-comments-form
6 months ago
post-comments-link
6 months ago
post-content
7 months ago
post-date
5 months ago
post-excerpt
5 months ago
post-featured-image
7 months ago
post-navigation-link
6 months ago
post-template
7 months ago
post-terms
6 months ago
post-time-to-read
6 months ago
post-title
6 months ago
preformatted
10 months ago
pullquote
4 months ago
query
6 months ago
query-no-results
7 months ago
query-pagination
7 months ago
query-pagination-next
7 months ago
query-pagination-numbers
7 months ago
query-pagination-previous
7 months ago
query-title
6 months ago
query-total
7 months ago
quote
10 months ago
read-more
7 months ago
rss
7 months ago
search
4 months ago
separator
10 months ago
shortcode
5 months ago
site-logo
7 months ago
site-tagline
6 months ago
site-title
6 months ago
social-link
7 months ago
social-links
7 months ago
spacer
10 months ago
tab
4 months ago
tab-list
4 months ago
tab-panel
4 months ago
tab-panels
4 months ago
table
10 months ago
table-of-contents
7 months ago
tabs
4 months ago
tag-cloud
7 months ago
template-part
10 months ago
term-count
7 months ago
term-description
6 months ago
term-name
7 months ago
term-template
7 months ago
terms-query
7 months ago
text-columns
10 months ago
verse
6 months ago
video
10 months ago
accordion-item.php
2.9 KB
5 months ago
accordion.php
1.2 KB
10 months ago
archives.php
4.4 KB
7 months ago
avatar.php
5.6 KB
7 months ago
block.php
4.1 KB
10 months ago
blocks-manifest.php
213.3 KB
4 months ago
breadcrumbs.php
19.0 KB
7 months ago
button.php
4.2 KB
6 months ago
calendar.php
6.1 KB
10 months ago
categories.php
4.9 KB
7 months ago
comment-author-avatar.php
2.5 KB
7 months ago
comment-author-name.php
2.1 KB
10 months ago
comment-content.php
2.4 KB
10 months ago
comment-date.php
1.9 KB
10 months ago
comment-edit-link.php
1.7 KB
10 months ago
comment-reply-link.php
2.1 KB
10 months ago
comment-template.php
4.5 KB
10 months ago
comments-pagination-next.php
1.9 KB
10 months ago
comments-pagination-numbers.php
1.6 KB
10 months ago
comments-pagination-previous.php
1.8 KB
10 months ago
comments-pagination.php
1.3 KB
10 months ago
comments-title.php
2.8 KB
7 months ago
comments.php
6.7 KB
10 months ago
cover.php
7.3 KB
5 months ago
details.php
1.5 KB
5 months ago
file.php
1.9 KB
10 months ago
footnotes.php
3.8 KB
7 months ago
form-input.php
1.2 KB
10 months ago
form-submission-notification.php
1.5 KB
10 months ago
form.php
5.8 KB
10 months ago
gallery.php
8.9 KB
6 months ago
heading.php
1.3 KB
10 months ago
home-link.php
4.9 KB
5 months ago
icon.php
4.0 KB
6 months ago
image.php
17.4 KB
4 months ago
index.js
2.6 MB
3 months ago
index.js.map
3.9 MB
3 months ago
index.min.asset.php
696 B
3 months ago
index.min.js
1.1 MB
3 months ago
index.min.js.map
4.0 MB
3 months ago
latest-comments.php
5.4 KB
7 months ago
latest-posts.php
8.7 KB
4 months ago
list.php
1.3 KB
10 months ago
loginout.php
2.1 KB
5 months ago
media-text.php
4.2 KB
6 months ago
navigation-link.php
15.3 KB
5 months ago
navigation-overlay-close.php
1.8 KB
6 months ago
navigation-submenu.php
11.0 KB
5 months ago
navigation.php
63.6 KB
3 months ago
page-list-item.php
385 B
10 months ago
page-list.php
14.3 KB
5 months ago
paragraph.php
1.2 KB
7 months ago
pattern.php
1.8 KB
10 months ago
playlist-track.php
2.1 KB
6 months ago
playlist.php
4.6 KB
6 months ago
post-author-biography.php
1.5 KB
10 months ago
post-author-name.php
1.9 KB
10 months ago
post-author.php
2.7 KB
10 months ago
post-comment.php
429 B
10 months ago
post-comments-count.php
1.3 KB
10 months ago
post-comments-form.php
2.8 KB
10 months ago
post-comments-link.php
2.2 KB
10 months ago
post-content.php
2.3 KB
10 months ago
post-date.php
3.6 KB
7 months ago
post-excerpt.php
4.3 KB
7 months ago
post-featured-image.php
9.1 KB
6 months ago
post-navigation-link.php
4.7 KB
7 months ago
post-template.php
5.9 KB
4 months ago
post-terms.php
3.6 KB
10 months ago
post-time-to-read.php
6.3 KB
7 months ago
post-title.php
2.1 KB
7 months ago
query-no-results.php
1.8 KB
10 months ago
query-pagination-next.php
3.6 KB
6 months ago
query-pagination-numbers.php
4.6 KB
6 months ago
query-pagination-previous.php
3.4 KB
6 months ago
query-pagination.php
1.2 KB
10 months ago
query-title.php
2.7 KB
6 months ago
query-total.php
2.5 KB
6 months ago
query.php
5.6 KB
10 months ago
read-more.php
1.8 KB
10 months ago
rss.php
4.5 KB
10 months ago
search.php
24.1 KB
4 months ago
shortcode.php
779 B
10 months ago
site-logo.php
6.4 KB
10 months ago
site-tagline.php
1.2 KB
10 months ago
site-title.php
1.9 KB
10 months ago
social-link.php
66.2 KB
7 months ago
tab-list.php
2.1 KB
4 months ago
tab-panel.php
2.1 KB
4 months ago
tab.php
2.1 KB
4 months ago
table-of-contents.php
1.2 KB
10 months ago
tabs.php
4.6 KB
4 months ago
tag-cloud.php
1.6 KB
10 months ago
template-part.php
10.3 KB
6 months ago
term-count.php
1.8 KB
10 months ago
term-description.php
1.8 KB
10 months ago
term-name.php
2.0 KB
7 months ago
term-template.php
4.5 KB
7 months ago
video.php
2.7 KB
10 months ago
post-time-to-read.php in Gutenberg 23.2.0, at build/scripts/block-library/post-time-to-read.php
| 1 | <?php |
| 2 | /** |
| 3 | * Server-side rendering of the `core/post-time-to-read` block. |
| 4 | * |
| 5 | * @package WordPress |
| 6 | */ |
| 7 | |
| 8 | /** |
| 9 | * Counts words or characters in a provided text string. |
| 10 | * |
| 11 | * This function currently employs an array of regular expressions |
| 12 | * to parse HTML and count words, which may result in inaccurate |
| 13 | * word counts. However, it is designed primarily to agree with the |
| 14 | * corresponding JavaScript function. |
| 15 | * |
| 16 | * Any improvements in the word counting, for example with the HTML API |
| 17 | * and {@see \IntlBreakIterator::createWordInstance()} should coordinate |
| 18 | * with changes to the JavaScript implementation to ensure consistency |
| 19 | * between the editor and the rendered page. |
| 20 | * |
| 21 | * @since 6.9.0 |
| 22 | * |
| 23 | * @param string $text Text to count elements in. |
| 24 | * @param string $type The type of count. Accepts 'words', 'characters_excluding_spaces', or 'characters_including_spaces'. |
| 25 | * |
| 26 | * @return string The rendered word count. |
| 27 | */ |
| 28 | function gutenberg_block_core_post_time_to_read_word_count( $text, $type ) { |
| 29 | $settings = array( |
| 30 | 'html_regexp' => '/<\/?[a-z][^>]*?>/i', |
| 31 | 'html_comment_regexp' => '/<!--[\s\S]*?-->/', |
| 32 | 'space_regexp' => '/ | /i', |
| 33 | 'html_entity_regexp' => '/&\S+?;/', |
| 34 | 'connector_regexp' => "/--|\x{2014}/u", |
| 35 | 'remove_regexp' => "/[\x{0021}-\x{0040}\x{005B}-\x{0060}\x{007B}-\x{007E}\x{0080}-\x{00BF}\x{00D7}\x{00F7}\x{2000}-\x{2BFF}\x{2E00}-\x{2E7F}]/u", |
| 36 | 'astral_regexp' => "/[\x{010000}-\x{10FFFF}]/u", |
| 37 | 'words_regexp' => '/\S\s+/u', |
| 38 | 'characters_excluding_spaces_regexp' => '/\S/u', |
| 39 | 'characters_including_spaces_regexp' => "/[^\f\n\r\t\v\x{00AD}\x{2028}\x{2029}]/u", |
| 40 | ); |
| 41 | |
| 42 | $count = 0; |
| 43 | |
| 44 | if ( '' === trim( $text ) ) { |
| 45 | return $count; |
| 46 | } |
| 47 | |
| 48 | // Sanitize type to one of three possibilities: 'words', 'characters_excluding_spaces' or 'characters_including_spaces'. |
| 49 | if ( 'characters_excluding_spaces' !== $type && 'characters_including_spaces' !== $type ) { |
| 50 | $type = 'words'; |
| 51 | } |
| 52 | |
| 53 | $text .= "\n"; |
| 54 | |
| 55 | // Replace all HTML with a new-line. |
| 56 | $text = preg_replace( $settings['html_regexp'], "\n", $text ); |
| 57 | |
| 58 | // Remove all HTML comments. |
| 59 | $text = preg_replace( $settings['html_comment_regexp'], '', $text ); |
| 60 | |
| 61 | // If a shortcode regular expression has been provided use it to remove shortcodes. |
| 62 | if ( ! empty( $settings['shortcodes_regexp'] ) ) { |
| 63 | $text = preg_replace( $settings['shortcodes_regexp'], "\n", $text ); |
| 64 | } |
| 65 | |
| 66 | // Normalize non-breaking space to a normal space. |
| 67 | $text = preg_replace( $settings['space_regexp'], ' ', $text ); |
| 68 | |
| 69 | if ( 'words' === $type ) { |
| 70 | // Remove HTML Entities. |
| 71 | $text = preg_replace( $settings['html_entity_regexp'], '', $text ); |
| 72 | |
| 73 | // Convert connectors to spaces to count attached text as words. |
| 74 | $text = preg_replace( $settings['connector_regexp'], ' ', $text ); |
| 75 | |
| 76 | // Remove unwanted characters. |
| 77 | $text = preg_replace( $settings['remove_regexp'], '', $text ); |
| 78 | } else { |
| 79 | // Convert HTML Entities to "a". |
| 80 | $text = preg_replace( $settings['html_entity_regexp'], 'a', $text ); |
| 81 | |
| 82 | // Remove surrogate points. |
| 83 | $text = preg_replace( $settings['astral_regexp'], 'a', $text ); |
| 84 | } |
| 85 | |
| 86 | // Match with the selected type regular expression to count the items. |
| 87 | return (int) preg_match_all( $settings[ $type . '_regexp' ], $text ); |
| 88 | } |
| 89 | |
| 90 | /** |
| 91 | * Renders the `core/post-time-to-read` block on the server. |
| 92 | * |
| 93 | * @since 6.9.0 |
| 94 | * |
| 95 | * @param array $attributes Block attributes. |
| 96 | * @param string $content Block default content. |
| 97 | * @param WP_Block $block Block instance. |
| 98 | * @return string Returns the rendered post author name block. |
| 99 | */ |
| 100 | function gutenberg_render_block_core_post_time_to_read( $attributes, $content, $block ) { |
| 101 | if ( ! isset( $block->context['postId'] ) ) { |
| 102 | return ''; |
| 103 | } |
| 104 | |
| 105 | $content = get_the_content(); |
| 106 | $average_reading_rate = $attributes['averageReadingSpeed'] ?? 189; |
| 107 | |
| 108 | $display_mode = $attributes['displayMode'] ?? 'time'; |
| 109 | |
| 110 | $word_count_type = wp_get_word_count_type(); |
| 111 | $total_words = gutenberg_block_core_post_time_to_read_word_count( $content, $word_count_type ); |
| 112 | |
| 113 | $parts = array(); |
| 114 | |
| 115 | // Add "time to read" part, if enabled. |
| 116 | if ( 'time' === $display_mode ) { |
| 117 | if ( ! empty( $attributes['displayAsRange'] ) ) { |
| 118 | // Calculate faster reading rate with 20% speed = lower minutes, |
| 119 | // and slower reading rate with 20% speed = higher minutes. |
| 120 | $min_minutes = max( 1, (int) round( $total_words / $average_reading_rate * 0.8 ) ); |
| 121 | $max_minutes = max( 1, (int) round( $total_words / $average_reading_rate * 1.2 ) ); |
| 122 | if ( $min_minutes === $max_minutes ) { |
| 123 | $max_minutes = $min_minutes + 1; |
| 124 | } |
| 125 | /* translators: 1: minimum minutes, 2: maximum minutes to read the post. */ |
| 126 | $time_string = sprintf( |
| 127 | /* translators: 1: minimum minutes, 2: maximum minutes to read the post. */ |
| 128 | _x( '%1$s–%2$s minutes', 'Range of minutes to read' ), |
| 129 | $min_minutes, |
| 130 | $max_minutes |
| 131 | ); |
| 132 | } else { |
| 133 | $minutes_to_read = max( 1, (int) round( $total_words / $average_reading_rate ) ); |
| 134 | $time_string = sprintf( |
| 135 | /* translators: %s: the number of minutes to read the post. */ |
| 136 | _n( '%s minute', '%s minutes', $minutes_to_read ), |
| 137 | $minutes_to_read |
| 138 | ); |
| 139 | } |
| 140 | $parts[] = $time_string; |
| 141 | } |
| 142 | |
| 143 | // Add "word count" part, if enabled. |
| 144 | if ( 'words' === $display_mode ) { |
| 145 | $word_count_string = 'words' === $word_count_type ? sprintf( |
| 146 | /* translators: %s: the number of words in the post. */ |
| 147 | _n( '%s word', '%s words', $total_words ), |
| 148 | number_format_i18n( $total_words ) |
| 149 | ) : sprintf( |
| 150 | /* translators: %s: the number of characters in the post. */ |
| 151 | _n( '%s character', '%s characters', $total_words ), |
| 152 | number_format_i18n( $total_words ) |
| 153 | ); |
| 154 | $parts[] = $word_count_string; |
| 155 | } |
| 156 | |
| 157 | $display_string = implode( '<br>', $parts ); |
| 158 | |
| 159 | $align_class_name = empty( $attributes['textAlign'] ) ? '' : "has-text-align-{$attributes['textAlign']}"; |
| 160 | |
| 161 | $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $align_class_name ) ); |
| 162 | |
| 163 | return sprintf( |
| 164 | '<div %1$s>%2$s</div>', |
| 165 | $wrapper_attributes, |
| 166 | $display_string |
| 167 | ); |
| 168 | } |
| 169 | |
| 170 | |
| 171 | /** |
| 172 | * Registers the `core/post-time-to-read` block on the server. |
| 173 | * |
| 174 | * @since 6.9.0 |
| 175 | */ |
| 176 | function gutenberg_register_block_core_post_time_to_read() { |
| 177 | register_block_type_from_metadata( |
| 178 | __DIR__ . '/post-time-to-read', |
| 179 | array( |
| 180 | 'render_callback' => 'gutenberg_render_block_core_post_time_to_read', |
| 181 | ) |
| 182 | ); |
| 183 | } |
| 184 | |
| 185 | add_action( 'init', 'gutenberg_register_block_core_post_time_to_read', 20 ); |
| 186 |