跳转到内容
关系图谱

repo-card:GitHub 与 CNB 仓库卡片完全指南

1,627 字 6 分钟

属性 1
series
VaultKit 包指南

@vaultkit/vitepress-plugin-repo-card 提供 ::: repo-card 容器:构建期抓取 GitHub / CNB 仓库元数据(名称、描述、语言、星叉、topics),渲染为静态卡片,零客户端 JS。动画全部 CSS——悬停浮起 + 品牌描边,lg 档另有光泽扫过,prefers-reduced-motion 下全部关闭。

它与系列前三篇的 markdown-it 容器不同:repo-card 是单段 Vite 插件enforce: 'pre'),在 markdown 编译之前直接把容器改写为原生 HTML 块。本文覆盖主参数的两种形态、全部 5 个属性、三档尺寸逐档实活演示、全部 5 个插件 options,以及缓存韧性与鉴权设计。

为什么需要它

文章里提到一个开源仓库时,裸链接的信息量太低:读者看不到它是干什么的、有多少 star、什么语言。手工贴徽章(shields.io)则是运行时请求,一页十几个徽章就是十几个第三方请求。

repo-card 在构建期把元数据固化进 HTML:页面加载零额外请求,磁盘缓存 + 陈缓存回退让构建对 API 限额和弱网都有韧性,且数据随每次部署自动刷新。

安装

TIP

注意注册位置——它是 Vite 插件而非 markdown-it 插件。

sh
pnpm add -D @vaultkit/vitepress-plugin-repo-card
ts
// .vitepress/config.ts —— 注册在 vite.plugins(非 markdown.config)
import { repoCard } from '@vaultkit/vitepress-plugin-repo-card'
import { defineConfig } from 'vitepress'

export default defineConfig({
  vite: { plugins: [repoCard()] },
})
ts
// .vitepress/theme/index.ts
import '@vaultkit/vitepress-plugin-repo-card/styles/index.css'

使用 @vaultkit/vitepress-theme-vault 主题则开箱即带,容器直接可用。

快速上手

主参数走 info-string 位(VitePress 容器惯例),单行即闭合、::: 收尾可省:

md
::: repo-card vuejs/vitepress

::: repo-card https://github.com/vuejs/core {size="lg"}

::: repo-card examples/showcase {platform="cnb"}

实活效果(本页构建期真实抓取渲染):

主参数的两种形态

owner/repo 简写

info-string 位直接写仓库路径,缺省按 GitHub 解释;CNB 仓库配 platform="cnb"(CNB 支持多级组织 org/sub/repo):

md
::: repo-card vuejs/vitepress

::: repo-card examples/showcase {platform="cnb"}

仓库 URL

写完整仓库主页地址,平台自动识别(github.com / cnb.cool),无需再给 platform

md
::: repo-card https://github.com/vuejs/vitepress

::: repo-card https://cnb.cool/examples/showcase

无法解析的 URL(比如贴成了文件页 blob 地址)构建期抛错。

容器属性逐项详解

全部 5 个属性:

属性类型缺省说明
repostring仓库路径(等价于 info-string 主参数的简写形态)
urlstring仓库主页 URL(等价于主参数的 URL 形态)
platformstringgithubgithub / cnb,仅简写形态需要
sizestringmdsm / md / lg
classstring卡片额外类名

repo / url 是旧的纯属性形态,原样兼容(主参数优先级更高):

md
::: repo-card {repo="vuejs/vitepress" size="md"}

platform 只支持 github / cnbsize 只支持三档,其余值构建期抛错;未知属性名同样 fail-fast。

三档尺寸逐档演示

sm:行内徽章条

图标 + 路径 + star 数,一行高,适合正文顺带提及:

md:钉选卡(缺省)

对齐 GitHub profile pinned 卡语义:名称、描述、语言色点、星叉统计,列仓库清单用:

lg:作品陈列卡

大标题 + 描述 + topics 徽标(至多 5 个)+ 统计行,悬停时光泽扫过,适合个人主页 / 关于页展示代表作:

CNB 平台卡片同理(图标呈 CNB 官方品牌橙 #FF6200;本文不做实活演示以免构建依赖 CNB_TOKEN):

md
::: repo-card examples/showcase {platform="cnb" size="lg"}

插件 Options 全览

repoCard(options)RepoCardOptions 共 5 项:

名称类型默认值说明
githubTokenstring环境变量 GITHUB_TOKENGitHub 令牌,可选(仅提高限额)
cnbTokenstring环境变量 CNB_TOKENCNB 令牌,CNB 卡必需
cnbApiBasestring'https://api.cnb.cool'CNB API 基址
ttlnumber3_600_000缓存有效期(ms,缺省 1 小时)
cacheDirstringnode_modules/.cache/vitepress-plugin-repo-card缓存目录
ts
repoCard({
  ttl: 24 * 3_600_000, // 一天内不重抓
  cacheDir: '.cache/repo-card', // CI 上指向可持久化路径
})

数据源与鉴权

平台端点鉴权
GitHubapi.github.com/repos/{repo}匿名可用(60 次/时);GITHUB_TOKEN 提至 5000 次/时
CNBapi.cnb.cool/{repo}必需令牌(权限含 repo-code:r)——连公开仓库也要认证,实测 401

鉴权、URL 解析、缓存全部来自底座包 @vaultkit/repo-platform-kit

设计机制

为什么是 Vite 插件而不是 markdown-it 插件

markdown-it 的渲染规则是同步的,没法在里面 await fetch()。repo-card 需要抓 API,唯一干净的异步时机是 md 编译之前——于是实现为 enforce: 'pre' 的 Vite transform:匹配 .md 模块源文本里的容器行,抓数据、拼 HTML、原地替换。卡片是纯 HTML,不需要 markdown-it 管线的任何协作,单段就够(对比 remote-file 的两段架构)。

改写产物的外层 <div> 顶行起笔,恰好落进 CommonMark type-6 HTML block 规则——后续 markdown 编译对它原样透传,不会二次加工。

行首正则与围栏的边界

Vite transform 看到的是原始文本,本不知道 markdown 围栏的存在——插件为此在改写前先按 CommonMark 围栏规则把源文切段,只改写围栏外的段。所以代码块里顶格演示 ::: repo-card 语法也是安全的,会原样保留(repo-card / npm-card / remote-file 三个「vite 原文改写系」容器同此行为)。

TTL 缓存 + 陈缓存回退

每个 API URL 以 sha1 为键落盘 JSON(内容 + 抓取时间戳):

  • TTL 内(缺省 1 小时)直接命中,构建完全不发请求
  • 过期重抓;抓取失败回退陈缓存并告警——弱网、限额、上游抖动都不炸构建
  • 既无网又无缓存才 fail-fast,且报错自带行动指引(403 提示设 GITHUB_TOKEN,401 提示 CNB 令牌权限)

CI 上建议持久化 node_modules/.cache,能把外部 API 压力降到近乎为零。

常见问题

卡片数据多久更新? 每次构建时若缓存过期即重抓;不重新构建则不变——这是静态站的固有语义。

star 数显示 1.2k 这种格式? 是,千位以上缩写为 k,与 GitHub 界面口径一致。

能只用旧属性形态吗? 可以,{repo=… size=…} 完整兼容,但推荐主参数形态:更短、单行即闭合。

相关链接