ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

WordPress「Time to Read」块深度解析:阅读时长与字数统计的完整实现指南

WordPress「Time to Read」块深度解析:阅读时长与字数统计的完整实现指南 WordPress「Time to Read」块深度解析阅读时长与字数统计的完整实现指南【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg导读本文基于 GutenbergWordPress 块编辑器仓库中的core/post-time-to-read块关联文档见 README系统讲解这个动态块Dynamic Block的完整技术实现它如何在后端根据文章内容计算阅读时长、如何在前端编辑器中实时预览、以及如何通过块属性Attributes与块支持Supports控制显示方式。读完本文你将掌握该块的全部属性配置、服务端渲染算法、编辑器端数据获取逻辑与版本兼容机制并能在自己的主题或文章模板中直接使用它。一、块概览一个展示阅读信息的主题类动态块core/post-time-to-read中文名为 Time to Read即阅读时间用于显示读完当前文章所需的分钟数同时也可以切换为显示文章的字数统计。它归属于theme主题分类属于站点编辑器中文章模板场景下的典型装饰性信息块。依据 block.json 中的元数据声明该块的核心标识如下项目值块名称Namecore/post-time-to-read分类CategorythemeAPI 版本3块类型Dynamic服务端渲染不在文章内容中保存 HTML从源码结构看该块目录下包含完整的实现文件block.json —— 块元数据属性、支持项、上下文声明index.php —— 服务端渲染逻辑与字数统计函数edit.jsx —— 编辑器内实时预览与设置面板variations.js —— 两个可插入的变体Time to Read / Word Countdeprecated.js —— 旧版本兼容与迁移逻辑style.scss —— 基础样式由于它是动态块文章内容中不保存渲染后的 HTML只保存一个块注释标记!-- wp:post-time-to-read /--浏览器最终看到的分钟数/字数文本全部由服务端在每次渲染时实时计算生成。二、属性Attributes详解控制显示方式的三个开关该块的全部属性均通过block.json的attributes字段声明定义在 block.json 中共三个属性类型默认值说明displayAsRangebooleantrue是否以区间形式显示阅读时间例如 2–3 minutes关闭后显示为单值displayModestringtime显示模式time显示阅读分钟数words显示字数averageReadingSpeednumber189平均阅读速度字/分钟用于把字数换算成分钟数这三个属性对应三条核心逻辑displayMode是块的主开关。它由两个块变体variation分别固定time-to-read变体将displayMode设为timeword-count变体将其设为words见 variations.js。当用户在编辑器中搜索Time to Read或Word Count时实际插入的就是同一个块的两个不同预配置形态两个变体之间还可以互相转换scope: [ inserter, transform ]。displayAsRange仅对time模式生效控制输出单个分钟数还是分钟区间。averageReadingSpeed是换算阅读时长的核心参数。默认值189字/分钟来自 WordPress 的常见阅读速度基准服务端渲染时通过$attributes[averageReadingSpeed] ?? 189取值见 index.php编辑器端则直接读取attributes.averageReadingSpeed。三、服务端渲染分钟数与字数是怎样算出来的3.1 注册与渲染回调在 index.php 中该块通过register_block_type_from_metadata()注册并把render_block_core_post_time_to_read指定为render_callback在init钩子上完成注册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 );3.2 上下文Context依赖文章 ID渲染函数的第一步是读取块上下文中的postId文章 ID这正是 README 中Uses context:postId、postType的含义——声明于 block.json 的usesContext字段。若上下文里拿不到postId例如该块被放到一个与具体文章无关的模板中渲染函数会直接返回空字符串if ( ! isset( $block-context[postId] ) ) { return ; }拿到postId后通过get_the_content()取得完整文章内容再调用字数统计函数$content get_the_content(); $average_reading_rate $attributes[averageReadingSpeed] ?? 189; $display_mode $attributes[displayMode] ?? time; $word_count_type wp_get_word_count_type(); $total_words block_core_post_time_to_read_word_count( $content, $word_count_type );注意这里的关键设计统计的字数类型并非写死为 words而是通过wp_get_word_count_type()动态获取。对于中日韩等以单字符为计量单位的语言WordPress 站点可以将统计类型配置为characters_excluding_spaces不含空格的字符数或characters_including_spaces含空格的字符数从而保证东亚语言的字数统计是准确的。3.3 字数统计一套与 JS 保持一致的 PHP 正则管线block_core_post_time_to_read_word_count()index.php实现了一套基于正则表达式的文本清洗管线。函数的注释明确指出该实现刻意与编辑器端 JavaScript 的wordpress/wordcount保持一致任何改进例如改用IntlBreakIterator都必须与 JS 端同步避免编辑器预览与页面渲染出现数字差异。管线步骤如下剥离 HTML 标签将tag替换为换行符移除 HTML 注释规范化不间断空格nbsp;/#160;转为普通空格按统计类型分支处理words单词删除 HTML 实体将连接符--与长破折号—替换为空格让被连接的词分别计数再删除标点等非词字符characters字符把 HTML 实体替换为字符a、把增补平面astral字符替换为a保证每个可见字符都计为 1最后用对应的words_regexp/characters_excluding_spaces_regexp/characters_including_spaces_regexp做preg_match_all计数。类型入参会被强制清洗为三种合法值之一非法值回退为wordsif ( characters_excluding_spaces ! $type characters_including_spaces ! $type ) { $type words; }3.4 时间换算单值与 ±20% 区间算法拿到总字数后渲染函数按displayMode与displayAsRange组合出显示文本单值模式displayAsRange为假$minutes_to_read max( 1, (int) round( $total_words / $average_reading_rate ) ); $time_string sprintf( _n( %s minute, %s minutes, $minutes_to_read ), $minutes_to_read );用round()四舍五入并用max( 1, ... )保证至少为 1 分钟。区间模式displayAsRange为真默认$min_minutes max( 1, (int) round( $total_words / $average_reading_rate * 0.8 ) ); $max_minutes max( 1, (int) round( $total_words / $average_reading_rate * 1.2 ) ); if ( $min_minutes $max_minutes ) { $max_minutes $min_minutes 1; } $time_string sprintf( _x( %1$s–%2$s minutes, Range of minutes to read ), $min_minutes, $max_minutes );区间算法以平均阅读速度为准上下浮动 20%下限按 80% 速度读得更快、分钟更少上限按 120% 速度读得更慢、分钟更多。当四舍五入后上下限相等例如短文章都算成 1 分钟时强制将上限1保证输出始终是形如1–2 minutes的有意义区间。字数模式displayMode为words根据统计类型输出X words或X characters数字使用number_format_i18n()做本地化格式化千分位分隔符随语言环境变化$word_count_string words $word_count_type ? sprintf( _n( %s word, %s words, $total_words ), number_format_i18n( $total_words ) ) : sprintf( _n( %s character, %s characters, $total_words ), number_format_i18n( $total_words ) );两种模式可以叠加吗从源码看渲染函数用两个独立的if分支向$parts[]数组追加文本再以br连接因此displayMode为time时仅输出时间、为words时仅输出字数二者互斥displayMode是单个字符串而非数组。3.5 输出包装最终输出被包进一个带wp-block-post-time-to-read类名的div同时把textAlign映射为对齐类名$align_class_name empty( $attributes[textAlign] ) ? : has-text-align-{$attributes[textAlign]}; $wrapper_attributes get_block_wrapper_attributes( array( class $align_class_name ) ); return sprintf( div %1$s%2$s/div, $wrapper_attributes, $display_string );基础样式中仅有一条规则style.scss用于让自定义 padding 表现可预期.wp-block-post-time-to-read { box-sizing: border-box; }四、编辑器端实现实时预览与设置面板4.1 数据获取与渲染端同源的统计口径编辑器端的 edit.jsx 需要预览与页面一致的结果。它通过wordpress/core-data的两个钩子拿到当前文章的原始内容与已解析块const [ contentStructure ] useEntityProp( postType, postType, content, postId ); const [ blocks ] useEntityBlockEditor( postType, postType, { id: postId } );其中postId、postType正是从块上下文context中解构出来的——与 README 声明的 Uses context 一一对应。随后编辑端复刻了getEditedPostContent()的内容生成逻辑优先使用已解析的 blocks经__unstableSerializeAndClean( blocks )序列化因为解析过程会应用块废弃与旧块转换比原始字符串更干净否则回退到原始contentStructure。4.2 字数统计与显示字符串统计时编辑端调用wordpress/wordcount的count()函数统计类型通过一个带翻译说明的_x()获取提示翻译者按字符计数的语言应改为characters_excluding_spaces或characters_including_spaces且该字符串不可翻译const wordCountType _x( words, Word count type. Do not translate! ); const totalWords wordCount( content || , wordCountType );随后在useMemo中完整复刻服务端的三种输出分支displayMode time且displayAsRange为真计算minMinutes×0.8与maxMinutes×1.2相等时上限1输出%1$s–%2$s minutesdisplayMode time且非区间输出Math.max( 1, Math.round( totalWords / averageReadingSpeed ) )对应的%s minute(s)displayMode words按统计类型输出%s word(s)或%s character(s)使用toLocaleString()本地化数字。可以看到编辑器端与 PHP 渲染端的算法逐行对应这正是该块预览即所得的根基。4.3 设置面板Inspector Controls当displayMode为time时编辑器的右侧设置面板会通过InspectorControls渲染一个ToolsPanel设置面板内含一个Display as range显示为区间开关ToggleControl label{ __( Display as range ) } checked{ !! displayAsRange } onChange{ () setAttributes( { displayAsRange: ! displayAsRange } ) } /resetAll与onDeselect都会把displayAsRange重置回默认值true。注意averageReadingSpeed目前并未暴露在设置面板中它保持 189 的默认值仅作为内部换算参数存在从源码结构看后续版本可能将其开放为可配置项。五、支持项Supports排版与样式的可定制能力依据 README 与 block.json该块支持以下通用能力支持项配置说明anchortrue允许设置 HTML 锚点 IDcolor.gradientstrue支持文本/背景色及渐变默认控制项开启背景色与文本色htmlfalse禁止用户在代码编辑器中直接改 HTMLspacing.margin/spacing.paddingtrue支持外边距与内边距默认控制项不展开typography.fontSizetrue字号默认控制项已展开typography.lineHeighttrue行高typography.textAligntrue文本对齐左/中/右映射为has-text-align-*类typography实验项字体族/字重/字体风格/文本转换/文本装饰/字间距进阶排版能力__experimental*前缀interactivity.clientNavigationtrue支持客户端导航站点编辑器中无刷新切换视图__experimentalBorder圆角/颜色/宽度/样式边框定制实验性这些支持项意味着在站点编辑器中选中该块后用户可以直接在右侧面板调整配色、间距、字号、对齐与边框无需编写任何 CSS。六、版本兼容废弃与迁移机制deprecated.js 记录了该块的 v1 版本兼容逻辑。旧版本将textAlign作为块属性存储而当前版本改为通过supports.typography.textAlign统一管理。当检测到旧内容中的块带有textAlign属性或has-text-align-(left|center|right)类名时isEligible()返回true触发迁移migrate: migrateTextAlign将旧属性转换为新的支持项体系迁移逻辑来自../utils/migrate-text-align与多个历史块共用save: () null表示 v1 同样是服务端渲染不保存 HTML。这套机制保证了老文章中的该块被再次打开编辑时能平滑升级到新格式而不丢失对齐设置。七、使用方式与实践建议7.1 在哪里使用core/post-time-to-read需要依赖postId上下文才能渲染因此它必须被放置在能提供文章上下文的模板中典型场景包括单篇文章模板Single Post Template文章信息模板部件或区块模式pattern中的元信息行查询循环Query Loop内展示每篇文章的阅读时长。若放置在首页、归档页等没有文章上下文的位置服务端渲染函数会返回空字符串前端不显示任何内容。7.2 手动插入的两种方式方式一编辑器界面操作在站点编辑器的区块插入器中搜索Time to Read阅读时间或Word Count字数统计——它们对应 variations.js 中注册的两个变体插入后会自动带上对应的displayMode预设值。方式二直接在模板 HTML 中写块标记!-- wp:post-time-to-read {displayAsRange:false} /--例如关闭区间显示、只输出单个分钟数也可以把displayMode切换为字数!-- wp:post-time-to-read {displayMode:words} /--7.3 定制建议统计口径默认按单词计数适合英文等内容对于中文、日文、韩文站点应通过 WordPress 的语言/统计配置将wp_get_word_count_type()返回characters_excluding_spaces等字符统计类型否则阅读时长会因分词方式不同而偏差。阅读速度默认 189 字/分钟是行业通用基准若站点受众以精读为主可在块属性中整体调整averageReadingSpeed当前未暴露在 UI 中可预设在模板块标记里。视觉风格充分利用spacing、typography、color支持项让阅读时长信息与文章排版融为一体间距等默认控制项未展开如需在面板直接显示需在主题中开启相应默认控制。八、小结core/post-time-to-read是一个麻雀虽小、五脏俱全的动态块范本block.json声明元数据与上下文依赖PHP 端用正则管线完成与 JS 端严格一致的字数统计±20% 浮动算法生成阅读时间区间variations提供阅读时间/字数两种插入形态deprecated保证旧内容平滑迁移。理解它的实现既能帮助你直接用好这个块也能为开发自定义信息类动态块提供完整的参考模板。继续深入阅读推荐块元数据与属性定义block.json服务端渲染与字数统计算法index.php编辑器实时预览与设置面板edit.jsx插入器变体variations.js版本迁移与兼容deprecated.js官方 API 文档索引docs/reference-guides【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表