搜索 K
主题
@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 插件。
pnpm add -D @vaultkit/vitepress-plugin-repo-card// .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()] },
})// .vitepress/theme/index.ts
import '@vaultkit/vitepress-plugin-repo-card/styles/index.css'使用 @vaultkit/vitepress-theme-vault 主题则开箱即带,容器直接可用。
主参数走 info-string 位(VitePress 容器惯例),单行即闭合、::: 收尾可省:
::: repo-card vuejs/vitepress
::: repo-card https://github.com/vuejs/core {size="lg"}
::: repo-card examples/showcase {platform="cnb"}实活效果(本页构建期真实抓取渲染):
info-string 位直接写仓库路径,缺省按 GitHub 解释;CNB 仓库配 platform="cnb"(CNB 支持多级组织 org/sub/repo):
::: repo-card vuejs/vitepress
::: repo-card examples/showcase {platform="cnb"}写完整仓库主页地址,平台自动识别(github.com / cnb.cool),无需再给 platform:
::: repo-card https://github.com/vuejs/vitepress
::: repo-card https://cnb.cool/examples/showcase无法解析的 URL(比如贴成了文件页 blob 地址)构建期抛错。
全部 5 个属性:
| 属性 | 类型 | 缺省 | 说明 |
|---|---|---|---|
repo | string | — | 仓库路径(等价于 info-string 主参数的简写形态) |
url | string | — | 仓库主页 URL(等价于主参数的 URL 形态) |
platform | string | github | github / cnb,仅简写形态需要 |
size | string | md | sm / md / lg |
class | string | — | 卡片额外类名 |
repo / url 是旧的纯属性形态,原样兼容(主参数优先级更高):
::: repo-card {repo="vuejs/vitepress" size="md"}platform 只支持 github / cnb,size 只支持三档,其余值构建期抛错;未知属性名同样 fail-fast。
图标 + 路径 + star 数,一行高,适合正文顺带提及:
对齐 GitHub profile pinned 卡语义:名称、描述、语言色点、星叉统计,列仓库清单用:
大标题 + 描述 + topics 徽标(至多 5 个)+ 统计行,悬停时光泽扫过,适合个人主页 / 关于页展示代表作:
CNB 平台卡片同理(图标呈 CNB 官方品牌橙 #FF6200;本文不做实活演示以免构建依赖 CNB_TOKEN):
::: repo-card examples/showcase {platform="cnb" size="lg"}repoCard(options) 的 RepoCardOptions 共 5 项:
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
githubToken | string | 环境变量 GITHUB_TOKEN | GitHub 令牌,可选(仅提高限额) |
cnbToken | string | 环境变量 CNB_TOKEN | CNB 令牌,CNB 卡必需 |
cnbApiBase | string | 'https://api.cnb.cool' | CNB API 基址 |
ttl | number | 3_600_000 | 缓存有效期(ms,缺省 1 小时) |
cacheDir | string | node_modules/.cache/vitepress-plugin-repo-card | 缓存目录 |
repoCard({
ttl: 24 * 3_600_000, // 一天内不重抓
cacheDir: '.cache/repo-card', // CI 上指向可持久化路径
})| 平台 | 端点 | 鉴权 |
|---|---|---|
| GitHub | api.github.com/repos/{repo} | 匿名可用(60 次/时);GITHUB_TOKEN 提至 5000 次/时 |
| CNB | api.cnb.cool/{repo} | 必需令牌(权限含 repo-code:r)——连公开仓库也要认证,实测 401 |
鉴权、URL 解析、缓存全部来自底座包 @vaultkit/repo-platform-kit。
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 原文改写系」容器同此行为)。
每个 API URL 以 sha1 为键落盘 JSON(内容 + 抓取时间戳):
GITHUB_TOKEN,401 提示 CNB 令牌权限)CI 上建议持久化 node_modules/.cache,能把外部 API 压力降到近乎为零。
卡片数据多久更新? 每次构建时若缓存过期即重抓;不重新构建则不变——这是静态站的固有语义。
star 数显示 1.2k 这种格式? 是,千位以上缩写为 k,与 GitHub 界面口径一致。
能只用旧属性形态吗? 可以,{repo=… size=…} 完整兼容,但推荐主参数形态:更短、单行即闭合。