动态友链算是挺常见的一个需求 —— 自动抓取友链站点最近的 RSS,不会让“友链”栏只显示一个孤零零的头像。Stellar 主题虽然自带了动态友链的实现,但用起来并不优雅

原版

原版动态友链的流程如下:

  1. Fork 仓库,在自己仓库的 Issues 里按模板提交友链
  2. 通过 GitHub Actions 定时拉取 Issues,抓取每个友链的 RSS,生成 data.json
  3. 利用 GitHub Pages 托管这份 JSON,前端通过 {% friends %} 标签拉取并渲染

还算省心,但:

  • 滥用 Issues:把数据塞进 Issue,和 Gitalk 一样,都是在滥用 GitHub 的 Issue 功能,我个人并不喜欢
  • 难以脱离 GitHub:作者写的 Action 用到了一些 GitHub API,无法直接搬到 Forgejo 上运行

刚好最近在学 Rust,这个需求正适合拿来练手。

思路

整个方案拆成三部分:

graph LR
  yml[friends.yml
label.yml] --> cli[stellar-friends] rss[RSS/Atom] --> cli cli --> json[data.json] json --> page[静态托管
Codeberg Pages] page --> theme[Blog]
  • 数据:友链和标签采用 YAML(当初踩了个坑,本应使用更方便的 TOML,不过懒得改了
  • 工具:用 Rust 写的 stellar-friends,读 YAML 输出 Stellar 的 v2 JSON
  • 托管:JSON 扔到 Codeberg Pages,前端通过 {% friends %} 拉取,与主题原生流程一致

数据格式

友链和标签均采用 YAML 格式,与原版大同小异。

friends.yml

1
2
3
4
5
6
7
8
9
- title: Bingxin Blog                                   # 友链标题
url: https://blog.byteloid.one/ # 友链地址
description: 普通人,而已 # 友链描述
icon: https://blog.byteloid.one/img/march7th.webp # 友链图标
feed: https://blog.byteloid.one/atom.xml # 友链 RSS/Atom 链接,可选
issue_number: 2 # 排序序号
#snapshot: # 站点快照,可选
#keywords: # 友链关键词,逗号分隔,可选
#labels: # 标签列表,可选

label.yml (可选):

1
2
3
4
5
6
7
8
9
10
11
- name: 老友        # 标签名称
color: "228879" # 标签颜色(十六进制,无 `#`)
hue: 171 # HSL 色相
saturation: 60 # HSL 饱和度
lightness: 33 # HSL 亮度

- name: 失联
color: "D93F0B"
hue: 15
saturation: 90
lightness: 45

Rust 实现

这一部分应该没人爱看吧,大概?
项目挺简单的,可以直看源码(写的菜,轻喷

部署

可以利用 Github/Forgejo Actions,写一个定时任务将生成的 JSON 放到仓库的另一个分支,并启用 Pages 托管这个分支,就能得到一个静态 URL 了

这一部分可以参考我在 Codeberg 的 Actions

接入 Stellar 主题

部署完成后,只需在文章里添加一行:

1
{% friends posts:true api:https://v-conet.codeberg.page/friends_api/v2/data.json %}

主题会按 issue_number 排序,效果与原版一致。

结语

自我感觉这个方案比原版更好,而且也能在本地运行,如果你也在用 Stellar 主题且对原版友链方案不太满意,不妨试试这个工具,欢迎到 GitHub 提 Issue 或 PR!