省流:使用 vitepress-plugin-rss 这个插件

前言

在看许多个人博客站点的时候,右上角总会有个RSS订阅的标志

恰好我的博客也是基于 VitePress 搭建的,就想看看能不能也实现这个功能呢?

动手前先搜了一下,先是看到了vitepress-blog-zaun上有这个RSS的实现支持,再搜了一下发现Vue的官方博客 vuejs/blog 也是用的这样的实现

大概就是自定义 VitePress 的 buildEnd 钩子,在里面实现逻辑获取 md 文件列表,然后通过 feed 生成 RSS 文件,整个逻辑就 50+ 行代码

由于我的博客还分离了独立的主题包 @sugarat/theme,我想把这个功能加到我的主题包里,这样使用这个主题的就可以简单的配置一下就能使用了,当然也为了方便广大 VitePress 用户更加简便的使用,我将这段逻辑单独分离封装到了 vitepress-plugin-rss 这个插件里。

接下来我将会先介绍一下如何食用这个插件,再介绍它的核心实现原理

插件使用

通过 pnpm/npm/yarn 安装插件

pnpm add vitepress-plugin-rss

.vitepress/config.ts 配置文件中添加配置使用

下面是最基础的使用配置

import { RssPlugin, RSSOptions } from 'vitepress-plugin-rss'
const baseUrl = 'https://sugarat.top'
const RSS: RSSOptions = {
title: '粥里有勺糖',
baseUrl,
copyright: 'Copyright (c) 2018-present, 粥里有勺糖',
} export default defineConfig({
vite: {
// ↓↓↓↓↓
plugins: [RssPlugin(RSS)]
// ↑↑↑↑↑
}
})

然后运行 build 命令,你可以看到在rendering pages...后打印了生成 feed.rss 日志...

pnpm run build

同时会在导航栏的 socialLinks 中添加 rss 图标链接

使用是不是非常简单,只需要 10 行代码。

如果你对插件的实现原理感兴趣,请接着往下看 。

核心实现原理解析

VitePress 的拓展在官方文档 Use Cases 部分有提到

其是基于 Vite 的,因此可以使用 Vite 的插件机制来实现主题内容的拓展。

buildEnd 修改

从官方的demo种可以看到,RSS 的生成逻辑是放在 buildEnd 中的,因此咱们插件也需要实现间接修改 buildEnd 方法

这个非常的简单,利用 Vite 的插件提供的 configResolved 钩子就行

下面是简单的demo

import { SiteConfig } from 'vitepress'

let resolveConfig: any = null

function configResolved(config: any) {
// 避免多次执行
if (resolveConfig) {
return
}
resolveConfig = config const VPConfig: SiteConfig = config.vitepress
if (!VPConfig) {
return
}
const selfBuildEnd = VPConfig.buildEnd
// 自定义 buildEnd 方法,添加 rss 生成支持
VPConfig.buildEnd = async (siteConfig: any) => {
// 调用自己的
await selfBuildEnd?.(siteConfig)
console.log('buildEnd', '生成 rss 文件');
}
}

通过config.vitepress即可拿到vitepress的配置,然后重新定义 buildEnd 方法即可

这里可以直接快速的验证一下

运行后可以看到打印了 buildEnd 生成 rss 文件,说明我们的插件的修改已经生效了

icon 添加

这个也非常的简单,VitePress 在官方文档里有介绍 socialLinks

我们只需要在配置修改中添加一个 socialLinks 的配置即可

接着上述的demo,添加如下代码

VPConfig.site.themeConfig.socialLinks = [
{
icon: {
svg: 'svg icon'
},
link: 'rss url'
},
...VPConfig.site.themeConfig.socialLinks
]

svg的图标可以通过 xicons 这个网站查找

比如我这里找了一个 sun 的图标配上

启动博客后就能看见右上角这个小太阳了

MD文件获取与解析

这个是最核心的逻辑了,① 需要获取所有的 md 文件,② 解析里面的 frontmatter ③ 渲染HTML

这个在 vuejs/blog 中可以看到使用的是 VitePress 内置的 createContentLoader 方法(里面包含了上述3部分逻辑)

这里把其核心实现拆出来,方便大家理解和更好的自定义(笔者在插件里也没直接使用 createContentLoader 这个方法)

① 通过 fast-glob 获取所有的 md 文件

import glob from 'fast-glob'

const files = glob.sync(`${srcDir}/**/*.md`, { ignore: ['node_modules'] })

其中 srcDir 即文章所在的目录,可以通过如下方式获取到相对路径

// config 即 SiteConfig
const srcDir =
config.srcDir.replace(config.root, '').replace(/^\//, '') ||
process.argv.slice(2)?.[1] ||
'.'

② 通过 gray-matter 解析 frontmatter

这里frontmatter就是文章开头里两个---之间的内容

例如

---
title: 示例标题
description: 文章介绍
---

利用 gray-matter 解析

import matter from 'gray-matter'
import fs from 'fs' for (const file of files) {
const fileContent = fs.readFileSync(file, 'utf-8')
const { data: frontmatter, excerpt } = matter(fileContent, {
excerpt: true
})
}

其中 excerpt 即为文章的摘要信息(description)

③ MD 渲染为 HTML

这个使用 VitePress 提供的 createMarkdownRenderer 即可

// 由于插件里最后构建成 CJS/ESM 两种格式,VitePress 最新的版本支持 ESM,因此需要动态引入
const { createMarkdownRenderer } = await import('vitepress') const mdRender = await createMarkdownRenderer(
config.srcDir,
config.markdown,
config.site.base,
config.logger
)
for (const file of files) {
const fileContent = fs.readFileSync(file, 'utf-8')
// 生成html
const html = mdRender.render(fileContent)
}

RSS文件生成

通过上面的 markdown 文件的解析,我们已经拿到了所有的文章信息,接下来就是通过 feed 这个库生成 RSS 文件了

import { Feed } from 'feed'
const feedOptions = {
// ...
}
const feed = new Feed(feedOptions) for (const file of files){
// 通过前面解析的信息,生成 feed item
feed.addItem({
title,
id: link,
link,
description,
content: html,
author: [
{
name: author,
...authorInfo
}
],
image: frontmatter?.cover,
date: new Date(date)
})
} const RSSFilename = 'feed.rss'
const RSSFilepath = path.join(config.outDir, RSSFilename) // 生成 rss 文件
writeFileSync(RSSFilepath, feed.rss2())

最后

插件的完整源码见 GitHub,欢迎大家试用和反馈

参考

为 VitePress 网站添加 RSS 订阅支持的更多相关文章

  1. 2019-9-2-给博客添加rss订阅

    title author date CreateTime categories 给博客添加rss订阅 lindexi 2019-09-02 12:57:38 +0800 2018-2-13 17:23 ...

  2. 给博客添加rss订阅

    如果是自己搭建博客,有一个问题是如何写一篇新的文章就可以告诉读者,你写了一篇新的?一个简单方法是使用 rss ,RSS订阅是站点用来和其他站点之间共享内容的一种简易方式,即Really Simple ...

  3. 安装FeedReader添加RSS订阅

    #0x1 FeedReader FeedReader是一款功能齐全,界面优美的GTK+ 3RSS阅读器客户端,用于在线RSS服务. FeedReader目前支持Feedbin,Feedly,Fresh ...

  4. 为网站加入Drupal星球制作RSS订阅源

    目前中文 Drupal 星球的版块还未成立,但大家的积极性挺高,不少站长都已经调整好自己的网站,生成了可供Drupal Planet 使用的RSS订阅源. 如果你也想让网站做好准备,可以不必再花上不少 ...

  5. 在自己的网站上使用RSS订阅功能

    要增加RSS订阅功能其实很简单 就是填写一个规定好的xml文档,按照要求填好就可以实现 具体的步骤如下: 这是在网上查到的RSSxml文档 <?xml version="1.0&quo ...

  6. 做个简单的RSS订阅(ASP.NET Core),节省自己的时间

    0x01 前言 因为每天上下班路上,午休前,都是看看新闻,但是种类繁多,又要自己找感兴趣的,所以肯定会耗费不少时间. 虽说现在有很多软件也可以订阅一些自己喜欢的新闻,要安装到手机,还是挺麻烦的.所以就 ...

  7. rome实现rss订阅与发布

    1. 什么是RSS RSS也叫聚合RSS,是在线共享内容的一种简易方式(也叫聚合内容, 简易供稿,Really Simple Syndication(真正简单的聚合 )).通常在时效性比较强的内容上使 ...

  8. 如何用RSS订阅?

    本文由云+社区发表 摘要:我们常常会有订阅别人文章的需求,有更新的时候希望能有提醒的功能,RSS就是这样一个订阅的方式.很多网站上看到RSS的入口,点进去以后总是显示一堆的XML代码,我们来看看怎么使 ...

  9. 利用Feed43为网站自制RSS源

    什么是RSS,它可以做什么 快2020年了,RSS日渐式微,我也是去年机缘巧合下才开始使用的,以前只是听说过.RSS,全称Really Simple Syndication,又称简易信息聚合(也叫聚合 ...

  10. Rss 订阅:php动态生成xml格式的rss文件

    Rss 简介: 简易信息聚合(也 叫聚合内容)是一种描述和同步网站内容的格式.使用RSS订阅能更快地获取信息,网站提供RSS输出,有利于让用户获取网站内容的最新更新.网络用户可以在客户端借助于支持RS ...

随机推荐

  1. Jenkins - 安装部署

    Jenkins安装部署 简介 Jenkins是一个开源的软件项目,是基于java开发的一种持续集成工具,用于监控持续重复的工作,提供一个开放易用的软件平台,使软件的持续集成变成可能. 主要用于: 持续 ...

  2. [vuex] unknown action type:***

    vuex 分模块后使用mapActions调用action老是提示 [vuex] unknown action type:*** 异常 目录 index.js是这样的 import Vue from ...

  3. 电赛控制类PID算法实现

    一.什么是PID 学过自动控制原理的对PID并不陌生,PID控制是对偏差信号e(t)进行比例.积分和微分运算变换后形成的一种控制规律.PID 算法的一般形式: PID控制系统原理框图 二.PID离散化 ...

  4. How to use the shell command to get the version of Linux Distributions All In One

    How to use the shell command to get the version of Linux Distributions All In One 如何使用 shell 命令获取 Li ...

  5. .NET周报 【6月第2期 2023-06-11】

    国内文章 如何计算一个实例占用多少内存? https://www.cnblogs.com/artech/p/size-calculation.html 我们都知道CPU和内存是程序最为重要的两类指标, ...

  6. 页面status:500,报错 server encountered an internal error that prevented it from fulfilling this request.

    The server encountered an internal error that prevented it from fulfilling this request.服务器遇到了一个内部错误 ...

  7. 前端Vue仿滴滴打车百度地图定位查找附近出租车或门店信息(更新版)

    前端vue仿滴滴打车百度地图定位查找附近出租车或门店信息, 下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=12982 效果图如下 ...

  8. 逍遥自在学C语言 | 多级指针探秘

    前言 多级指针在C语言中是一种特殊的指针类型,它可以指向其他指针的指针. 通过多级指针,我们可以间接地访问或修改存储在内存中的数据. 在本文中,我们将讨论多级指针的概念.使用方法.使用场景以及常见错误 ...

  9. php发起支付加密数据供获取订单状态使用

    <?php//作者主页: https://www.bz80.comnamespace Index\Controller; class PayController extends BaseCont ...

  10. Django容易被遗忘却无比重要的框架默认文件介绍及使用方法

    在Python Web开发领域,Django框架的地位犹如璀璨的明星,其全面.高效和安全的特性使其在全球范围内广受欢迎.本文将全面解析Django框架的默认文件,并深入探讨每个文件及其组成的意义和用途 ...