在 Hexo 的主题开发中,Helper(辅助函数)是你最得力的助手。你可以把它们想象成模板中的“快捷指令”或“瑞士军刀”,它们能让你在编写模板文件(如 .ejs、.swig 或 .pug)时,快速插入复杂的代码片段、处理数据或生成标准的 HTML 结构。
请注意一个核心规则:Helper 只能在模板文件中使用,不能直接在源文件(如 Markdown 文章)中调用。
下面我们将详细拆解 Hexo 内置的各类 Helper,帮助你从零开始掌握它们。
一、URL 辅助函数:智能构建链接
在博客中,链接的路径处理非常关键。如果路径写死,一旦网站部署到子目录(例如 example.com/blog/),所有链接都会失效。Hexo 的 URL Helper 能自动处理这些前缀和编码问题。
1. url_for
功能:在路径前自动加上配置的根路径(root),并自动进行 URL 编码。
这就好比你寄快递,只需要写“收件人”,Helper 会自动帮你补上“省市区”的前缀,确保快递能送到。
语法:
1 | <%- url_for(path, [option]) %> |
参数说明:
path(必填):目标路径字符串。option(可选):配置对象。relative:布尔值。是否输出相对链接。默认跟随配置文件_config.yml中的relative_link设置。
配置与示例:
场景 A:基础用法(自动添加根路径)
假设你的 _config.yml 配置了 root: /blog/。
1 | <%- url_for('/a/path') %> |
即使你写的是 /a/path,它也会自动变成 /blog/a/path,防止链接断裂。
场景 B:相对链接(离线浏览或子目录部署)
当你在 _config.yml 中设置 relative_link: true 时,Hexo 会计算当前页面与目标文件的相对路径。
假设当前页面路径是 /foo/bar/index.html:
1 | # _config.yml |
1 | <%- url_for('/css/style.css') %> |
它会自动向上回溯两级目录去找 css 文件夹。
场景 C:强制覆盖配置
有时候你想在全局开启相对链接的情况下,对某个特定链接强制使用绝对路径(或反之)。可以通过第二个参数实现:
1 | // 即使全局开启了 relative_link,这里强制输出非相对链接 |
2. relative_url
功能:手动计算从 from 路径到 to 路径的相对 URL。
这就像导航软件,你告诉它“起点”和“终点”,它告诉你“怎么走”。
语法:
1 | <%- relative_url(from, to) %> |
示例:
1 | <%- relative_url('foo/bar/', 'css/style.css') %> |
3. full_url_for
功能:在路径前加上完整的域名配置(config.url)。
用于生成带有域名的绝对链接,常用于 SEO 优化、RSS 订阅或社交媒体分享。
语法:
1 | <%- full_url_for(path) %> |
示例:
假设 _config.yml 中配置了 url: https://example.com/blog。
1 | <%- full_url_for('/a/path') %> |
4. gravatar
功能:根据邮箱地址生成 Gravatar 全球通用头像的 URL。
Gravatar 会根据邮箱的哈希值返回对应的头像图片。
语法:
1 | <%- gravatar(email, [options]) %> |
参数说明:
email:用户邮箱地址。options:可选参数,有三种形式:- 不传:使用默认配置(尺寸 80px)。
- 数字:直接作为图片尺寸 (
s)。 - 对象:自定义多个参数。
s:图片尺寸 (size),默认 80。d:默认图片 (default),当邮箱未注册时显示的图片 URL。f:强制默认 (force default),总是显示默认图。r:评级 (rating),控制图片内容级别 (g, pg, r, x)。
示例:
1 | // 1. 默认用法 (80px) |
二、HTML 标签生成:一键引入资源
手动编写 <link> 或 <script> 标签容易出错且繁琐,这些 Helper 能自动生成标准标签,并处理路径前缀。
1. css Helper
功能:自动生成 <link rel="stylesheet"> 标签。
它会自动在文件路径前加上配置的根路径(root),并在末尾自动补上 .css 后缀(如果你没写的话)。更重要的是,它支持多种输入格式,让你能轻松管理单个文件、多个文件列表,甚至是带有自定义属性的复杂配置。
语法:
1 | <%- css(path, ...) %> |
参数详解:
path:这是核心参数,非常灵活,支持以下四种形式:- 字符串:单个文件路径。
- 数组:包含多个文件路径的列表。
- 对象:用于定义单个文件及其自定义 HTML 属性(如
integrity,media等)。 - 对象数组:同时加载多个带有不同自定义属性的文件。
关键属性说明(对象模式):
href:在对象模式中,用来指定文件路径。integrity:**子资源完整性(SRI)**校验值。这是一个安全特性,浏览器会计算下载文件的哈希值并与该值比对,如果文件被篡改(例如被 CDN 注入恶意代码),浏览器将拒绝执行。格式通常为sha384-...。media:指定媒体类型,如print(打印专用)、screen(屏幕专用)。
详细示例:
场景 1:加载单个文件(最简模式)
只需传入文件名,Helper 会自动补全路径和后缀。
1 | <%- css('style.css') %> |
场景 2:一次性加载多个文件
传入一个字符串数组,Helper 会循环生成多个标签。
1 | <%- css(['style.css', 'screen.css']) %> |
场景 3:添加自定义属性(对象模式)
当你需要添加 integrity 校验码或其他非标准属性时,必须使用对象格式。
1 | <%- css({ href: 'style.css', integrity: 'sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC' }) %> |
说明:这里 href 指定了文件,integrity 添加了安全校验。如果文件内容不匹配该哈希,浏览器会阻止样式加载,防止样式污染攻击。
场景 4:复杂组合(对象数组)
这是最强大的用法,可以为每个文件单独配置不同的属性。
1 | <%- css([ |
2. js Helper
功能:自动生成 <script> 标签。
逻辑与 css Helper 高度一致,自动处理根路径和 .js 后缀。在现代网页开发中,JS 的加载策略(同步、异步、延迟)对性能至关重要,这个 Helper 能让你轻松配置这些属性。
语法:
1 | <%- js(path, ...) %> |
参数详解:
path:同样支持字符串、数组、对象、对象数组。- 对象模式下的关键属性:
src:指定 JS 文件路径。async:异步加载。布尔值。设置为true时,脚本会立即下载并执行,不阻塞 HTML 解析。适用于统计代码、广告脚本等不依赖 DOM 结构的脚本。defer:延迟执行。布尔值。设置为true时,脚本会立即下载,但等到 HTML 解析完成后才按顺序执行。适用于依赖 DOM 结构的主逻辑脚本。integrity:同 CSS,用于子资源完整性校验,防止 JS 文件被篡改。type:指定脚本类型,如module(ES6 模块)。
详细示例:
场景 1:加载单个脚本
1 | <%- js('script.js') %> |
场景 2:加载多个脚本
1 | <%- js(['script.js', 'gallery.js']) %> |
场景 3:配置异步与安全校验(重要)
这是现代网站优化的常见配置。我们通常希望统计脚本异步加载不影响首屏速度,同时确保第三方库未被篡改。
1 | <%- js({ |
说明:async 属性在 HTML 中即表示开启异步。Helper 会自动处理这种布尔值的渲染。
场景 4:混合配置(对象数组)
你可以为不同的脚本设置不同的加载策略。主逻辑脚本用 defer 保证 DOM 就绪,第三方库用 integrity 保证安全。
1 | <%- js([ |
总结建议:
- 对于简单的内部样式和脚本,直接使用字符串或数组即可。
- 对于引用 CDN 上的第三方资源,强烈建议使用对象模式添加
integrity属性。 - 合理使用
async或defer属性可以显著提升页面的首屏加载速度。
3. link_to
功能:插入超链接 <a> 标签。
语法:
1 | <%- link_to(path, [text], [options]) %> |
参数说明:
path:链接地址。text:(可选) 显示的文字。如果不填,默认显示 path 本身。options:(可选) 配置对象。external:布尔值。是否在新标签页打开 (target="_blank"),默认false。开启时会自动添加rel="noopener"以增强安全性。class:CSS 类名。id:元素 ID。
示例:
1 | // 1. 仅地址 (文字默认为地址) |
4. mail_to
功能:插入邮件链接 mailto:。
语法:
1 | <%- mail_to(path, [text], [options]) %> |
参数说明:
options支持更多邮件专用属性:subject:邮件主题。cc:抄送。bcc:密送。body:邮件正文。class,id:样式属性。
示例:
1 | <%- mail_to('a@abc.com', '联系我', {subject: '合作咨询', body: '你好,我想咨询...'}) %> |
5. image_tag & favicon_tag
功能:分别插入图片 <img> 和网站图标 <link rel="icon">。
image_tag 示例:
1 | <%- image_tag('logo.png', {alt: '网站 Logo', class: 'header-logo', width: 100}) %> |
favicon_tag 示例:
1 | <%- favicon_tag('favicon.ico') %> |
6. feed_tag
功能:插入 RSS/Atom 订阅链接。
语法:
1 | <%- feed_tag(path, [options]) %> |
参数说明:
title:订阅源标题,默认读取_config.yml中的title。type:类型,如atom或rss。
示例:
1 | // 1. 指定文件 |
三、条件判断标签:模板的逻辑开关
在开发主题时,我们需要根据不同页面(首页、文章页、归档页)展示不同的布局。这些 Helper 就是判断当前页面类型的“开关”。
| Helper | 功能描述 | 参数说明 |
|---|---|---|
is_current(path, [strict]) |
检查当前 URL 是否匹配给定路径 | strict: 开启严格匹配模式 |
is_home() |
是否为首页 | 无 |
is_home_first_page() |
是否为首页的第一页 | Hexo 6.3.0+ 新增。用于区分首页的分页情况 |
is_post() |
是否为文章页 (Post) | 无 |
is_page() |
是否为独立页面 (Page) | 无 |
is_archive() |
是否为归档页 | 无 |
is_year() |
是否为年份归档页 | 无 |
is_month() |
是否为月份归档页 | 无 |
is_category([name]) |
是否为分类页 | 可传字符串检查特定分类,如 is_category('tech') |
is_tag([name]) |
是否为标签页 | 可传字符串检查特定标签,如 is_tag('js') |
概念辨析:Post vs Page
- Post (文章):有发布时间,属于某个分类或标签,会出现在归档列表和时间轴中。
- Page (页面):通常是静态的独立页面,如“关于我”、“友情链接”,没有时间属性,不属于归档。
使用示例:
1 | <% if (is_post()) { %> |
四、字符串操作:文本处理工具
在展示文章摘要或标题时,经常需要清洗或格式化文本。
1. 基础清洗
trim(string):去除字符串首尾的空格。strip_html(string):移除所有 HTML 标签,只保留纯文本。常用于生成不含标签的文章摘要。1
2<%- strip_html('这是 <b>重要</b> 的内容') %>
// 结果: 这是 重要 的内容escape_html(str):转义 HTML 实体(如<变为<)。用于防止 XSS 攻击或在页面上显示源码。1
2<%- escape_html('<p>Hello</p>') %>
// 结果: <p>Hello</p>
2. 格式转换
titlecase(string):将字符串转换为标题大小写(每个单词首字母大写)。1
2<%- titlecase('this is an apple') %>
// 结果: This Is An Applemarkdown(str):将 Markdown 语法的字符串渲染为 HTML。1
2<%- markdown('make me **strong**') %>
// 结果: make me <strong>strong</strong>render(str, engine, [options]):使用指定引擎(如 pug, swig)渲染字符串。1
2<%- render('p(class="example") Test', 'pug'); %>
// 结果: <p class="example">Test</p>
3. 文本截断与换行
word_wrap(str, [length]):按指定长度强制换行。默认长度 80。1
2<%- word_wrap('Once upon a time', 8) %>
// 结果: Once upon\n a timetruncate(text, [options]):截断文本并添加省略号,比单纯截取更智能。length:截断长度,默认 30。separator:分隔符。如果设置了,会在该分隔符处截断,避免切断单词。omission:省略号内容,默认...。
示例:
1
2
3
4
5
6
7
8
9
10
11// 1. 简单截断 (可能在单词中间切断)
<%- truncate('Once upon a time in a world', {length: 17}) %>
// 结果: Once upon a ti...
// 2. 按空格截断 (保持单词完整)
<%- truncate('Once upon a time in a world', {length: 17, separator: ' '}) %>
// 结果: Once upon a...
// 3. 自定义省略内容
<%- truncate('And they found sleep.', {length: 25, omission: '... (continued)'}) %>
// 结果: And they f... (continued)
五、模板复用与缓存
1. partial
功能:加载其他模板文件(局部模板)。
就像搭乐高,把头部、底部、侧边栏做成独立的模块,随时调用。
语法:
1 | <%- partial(layout, [locals], [options]) %> |
参数说明:
layout:模板文件名(不含扩展名,如_partial/header)。locals:(可选) 传递给局部模板的变量对象。options:(可选)cache:布尔值。是否启用片段缓存,默认false。only:布尔值。严格模式。如果为true,局部模板只能访问locals中的变量,无法访问父级模板的变量。默认false。
2. fragment_cache
功能:缓存一段生成的 HTML 内容。
对于渲染耗时较长的内容(如复杂的目录树、统计图表),缓存可以显著提升页面加载速度。
语法:
1 | <%- fragment_cache(id, fn) %> |
示例:
1 | <%- fragment_cache('header', function(){ |
第一次请求时执行函数并保存结果,后续请求直接返回缓存的 HTML,不再重复执行函数。
六、日期与时间:Moment.js 的强大封装
Hexo 的日期 Helper 底层基于 Moment.js,支持多种输入格式(Unix 时间戳、ISO 字符串、Date 对象等)。
date(date, [format]):格式化日期。format:默认读取_config.yml的date_format。
1
2
3
4
5<%- date(Date.now()) %>
// 结果: 2023-01-01 (取决于配置)
<%- date(Date.now(), 'YYYY/M/D') %>
// 结果: 2023/1/1date_xml(date):生成 XML 标准格式日期(ISO 8601),专用于 RSS/Atom 订阅。1
2<%- date_xml(Date.now()) %>
// 结果: 2023-01-01T00:00:00.000Ztime(date, [format]):格式化时间。format:默认读取time_format。
1
2<%- time(Date.now(), 'h:mm:ss a') %>
// 结果: 1:05:12 pmfull_date(date, [format]):同时格式化日期和时间。1
2<%- full_date(new Date(), 'dddd, MMMM Do YYYY') %>
// 结果: Tuesday, January 1st 2023relative_date(date):生成相对时间(如“3 小时前”、“2 年前”),提升用户体验。1
2
3
4
5<%- relative_date(new Date()) %>
// 结果: a few seconds ago
<%- relative_date(new Date(1000000000000)) %>
// 结果: 22 years agotime_tag(date, [format]):生成语义化的<time>标签,利于 SEO。1
2<%- time_tag(new Date(), 'MMM-D-YYYY') %>
// <time datetime="2024-01-22T...">Jan-22-2024</time>moment:直接暴露 Moment.js 库对象,可进行更复杂的日期运算。
七、列表生成器:自动化目录与归档
这些 Helper 能自动遍历 Hexo 的数据模型,生成分类、标签、归档等列表,无需手动编写循环。
1. list_categories
功能:生成分类列表。
关键参数:
orderby:排序字段,默认name。order:1(升序) 或-1(降序)。show_count:是否显示文章数,默认true。style:list(无序列表<ul>) 或其他值(纯文本分隔)。depth:层级深度。0(所有层级),1(仅顶级),-1(扁平化显示所有)。transform:函数,用于转换分类名称显示。suffix:给链接添加后缀。
示例:
1 | // 自定义类名,并将分类名转为首字母大写 |
2. list_tags
功能:生成标签列表。参数与 list_categories 类似,额外支持 amount (限制数量) 和更细致的 class 对象定制。
Class 高级定制:
你可以传入一个对象来分别定义 <ul>, <li>, <a>, <span> (计数) 的类名。
class.ul:<ul>类名。class.li:<li>类名。class.a:<a>类名。class.count: 计数<span>类名。
示例:
1 | // 1. 普通字符串类名,非列表风格,用 | 分隔 |
3. list_archives
功能:生成归档列表。
type:yearly(年) 或monthly(月,默认)。format:日期格式,默认MMMM YYYY。
4. list_posts
功能:生成文章列表。
amount:显示数量,默认 6。设为 0 表示不限制。orderby:默认date。
5. tagcloud
功能:生成标签云,字体大小随标签热度(文章数)变化。
关键参数:
min_font,max_font:字体大小范围,默认 10-20。unit:单位,默认px。color:是否启用颜色渐变,默认false。start_color,end_color:渐变的起止颜色(支持 hex, rgba, hsla)。show_count:(Hexo 6.3.0+) 是否显示文章数。
示例:
1 | // 1. 默认标签云 |
八、其他实用工具 (Miscellaneous)
1. paginator (分页器)
功能:生成分页导航链接。这是博客多页展示的核心组件。
语法:
1 | <%- paginator(options) %> |
常用参数详解:
base:基础 URL,默认/。format:URL 格式,默认page/%d/(%d代表页码)。total:总页数。current:当前页码。prev_text,next_text:上一页/下一页的文字或 HTML。end_size:两端显示的页码数,默认 1(即始终显示第 1 页和最后 1 页)。mid_size:当前页两侧显示的页码数,默认 2。show_all:布尔值。如果为true,显示所有页码,此时end_size和mid_size失效。escape:布尔值。是否转义 HTML。如果你想在prev_text中使用图标(如<i>标签),必须设为false。force_prev_next:(Hexo 6.3.0+) 强制显示上一页/下一页链接,即使它们不可用(通常用于占位)。page_class,current_class等:(Hexo 6.3.0+) 自定义各部分类名。
示例:
1 | // 1. 简单自定义文字 |
2. search_form
功能:插入 Google 搜索表单。
button:是否显示搜索按钮。可以是true/false,也可以是字符串(作为按钮文字)。
3. number_format
功能:格式化数字,添加千分位分隔符或控制小数精度。
参数:
precision:小数精度。可以是false或非负整数。delimiter:千分位分隔符,默认,。separator:小数点分隔符,默认.。
示例:
1 | <%- number_format(12345.67, {precision: 1}) %> |
4. meta_generator & open_graph
meta_generator():插入<meta name="generator" content="Hexo x.x.x">,标识建站工具。open_graph([options]):自动生成 Open Graph 协议标签。这对于社交媒体分享(Facebook, Twitter, 微信等)至关重要,它能自动抓取文章标题、图片、描述等信息,生成精美的分享卡片。- 常用选项:
title,type,image,description,twitter_card等。大多数情况下直接使用<%- open_graph() %>即可,它会自动读取页面数据。
- 常用选项:
5. toc (目录)
功能:解析文章内容中的标题(h1-h6),自动生成目录树。
语法:
1 | <%- toc(str, [options]) %> |
通常传入 page.content。
参数:
list_number:是否显示编号,默认true。max_depth,min_depth:控制目录层级深度。class_*:(Hexo 6.3.0+) 精细化控制各部分类名(如class_item,class_link等)。max_items:(Hexo 7.3.0+) 限制目录最大条目数。
特殊功能:data-toc-unnumbered
如果在 Markdown 标题中添加 data-toc-unnumbered="true" 属性,该标题在生成的目录中将不显示编号。
注意:这需要你的 Markdown 渲染器(如 hexo-renderer-markdown-it)支持保留 HTML 属性。
示例:
1 | <%- toc(page.content, {class: 'my-toc', max_depth: 3}) %> |
通过熟练掌握这些 Helper,你可以极大地提高 Hexo 主题开发的效率,将精力集中在设计和逻辑上,而不是重复编写基础代码。