Hexo获取文章封面的方法

在官网公开的一些模板中,文章列表页大多是标题+段落描述(取前N个字)。而像WordPress、Typecho、Emlog这些网站模板,又或是astro、nuxt之类基于tailwind的页面模板,绝大多数都包含了文章封面的展示形式、

那么这一章,我们就聊聊在Hexo中如何实现获取文章首图/设置封面图的方式

01 封面获取策略

封面获取逻辑比较简单,加上补偿机制后整体逻辑如下:

  • 读取md文件头部的Front-matter,判断是否存在变量cover
    • 存在变量:以cover作为文章封面。
    • 不存在变量:下一步,尝试获取文章内的图片。
  • 读取文章内容,尝试提取第一张图片。
    • 提取成功:以第一张图片作为文章封面。
    • 提取失败:设置默认图片作为文章封面。

02 编写插件

在项目根目录的scripts文件夹中创建一个名为my-plugin.js的js文件来存放插件。并填充以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
hexo.extend.filter.register('before_post_render', function (data) {
// 不处理文章外的数据
if (data.layout !== 'post') {
return data
}

/**
* 如果Front-matter中设置cover变量,此处可以通过data.cover获取到。
* 获取不到则代表不存在变量了,就进入提取文章内图片的逻辑了
*/
if (!data.cover) {
const imageRegex = /!\[.*?\]\((.*?)\)/g
const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i

const matches = data.content.matchAll(imageRegex)
const firstImageMatch = Array.from(matches).find(match => {
let url = match[1]
return imageExtensions.test(url)
})

// 如果文章中包含图片标签,则将第一个匹配的图片链接设置为首图
if (firstImageMatch) {

let url = firstImageMatch[1]
if (!url.startsWith('http')) {
url = '/' + data.path.replace('.html', '') + '/' + url
}
data.cover = url
} else {
// 如果文章中没有图片标签,则设置默认的首图链接
data.cover = 'https://默认图片路径'
}
}

return data
})

Tips
(1) 默认图片推荐用网络图片地址,配置相对比较简单。
(2) 如果非要使用本地图片,假设设置内容为/images/default.jpg,则需要将图片放到以下位置themes/当前使用的模板/source/images/default.jpg。在项目编译后,source目录下的全部内容会被放置到项目根目录。
(3) 如果网站运行在二级目录下(比如 www.xxxx.com/web/ ),则本地图片路径应变更为/web/images/default.jpg

03 在模板中使用

之后在模板中就可以通过post.cover的形式来使用封面了。

1
2
3
<% page.posts.each(function(post, i){ %>
<%= post.cover %>
<% } %>

评论区