搜索 K
主题
@vaultkit/vitepress-plugin-bilibili 为 VitePress / markdown-it 提供 ::: bilibili 容器,一行 Markdown 嵌入哔哩哔哩官方外链播放器(player.bilibili.com)。它基于 markdown-it-container 在构建期直接产出 HTML + CSS,客户端零 JS;属性语义逐项对齐官方播放器 QueryString 文档,并针对嵌入场景矫正了最要命的一个默认值——官方缺省会自动播放,本插件缺省显式关闭。
16 个容器属性覆盖 UGC 稿件、OGV 番剧、分 P、起播时间、弹幕、画质、宽高比等全部嵌入场景。本文逐项给出语义与示例,并讲透 deferSrc 模式背后的 bfcache 机理。
直接从 B 站「分享 → 嵌入代码」复制 iframe 到 Markdown 里,有三个绕不开的问题:
<iframe> 定宽定高,不随正文栏宽自适应,移动端直接破版::: bilibili 容器把这些一次收拾干净:CSS aspect-ratio 自适应宽度、缺省显式 autoplay=0、未知属性与视频 ID 全缺都在构建期抛错(fail-fast),坏嵌入根本到不了线上。
pnpm add -D @vaultkit/vitepress-plugin-bilibili注册 markdown-it 插件并在主题入口引入一次样式:
// .vitepress/config.ts
import { bilibiliEmbed } from '@vaultkit/vitepress-plugin-bilibili'
import { defineConfig } from 'vitepress'
export default defineConfig({
markdown: {
config(md) {
md.use(bilibiliEmbed)
},
},
})// .vitepress/theme/index.ts
import '@vaultkit/vitepress-plugin-bilibili/styles/index.css'如果你用的是 @vaultkit/vitepress-theme-vault 主题,本插件开箱即带,::: bilibili 容器无需任何配置即可直接用。
语法(花括号 key=value,容器正文渲染为视频下方的说明文字,可省):
::: bilibili {bvid="BV1B7411m7LV" danmaku=false}
容器正文渲染为视频下方的说明文字(可省)。
:::效果——下面就是本页构建期真实渲染出的播放器:
全部 16 个属性一览(VitePress 下由内建 markdown-it-attrs 原生解析;非 VitePress 宿主自动回退内置解析,额外接受无引号值):
| 属性 | 进播放器 URL | 说明 |
|---|---|---|
bvid | bvid | UGC 视频 BV 号(推荐) |
aid | aid | UGC 视频 av 号 |
cid | cid | 稿件分 P 弹幕池 ID |
episodeId | episodeId | OGV 番剧单集 ID |
seasonId | seasonId | OGV 番剧季 ID |
p | p | 多 P 集数 |
t | t | 起播时间点(秒) |
poster | poster | 展示封面 |
autoplay | autoplay | 自动播放(缺省显式置 0) |
muted | muted | 静音 |
danmaku | danmaku | false 关闭弹幕 |
highQuality | high_quality | 高画质开关 |
ratio | 不进 URL | 容器宽高比(CSS aspect-ratio) |
title | 不进 URL | iframe 无障碍标题 |
class | 不进 URL | 透传外层容器类名 |
id | 不进 URL | 透传外层容器 id |
UGC 稿件的 BV 号,与 aid 二选一,官方与本插件都推荐 bvid(av 号存在整型溢出史):
::: bilibili {bvid="BV1B7411m7LV"}
:::UGC 稿件的 av 号(纯数字,不带 av 前缀),老文章迁移时常见:
::: bilibili {aid=170001}
:::稿件分 P 的弹幕池 ID,精确锁定某一 P 的弹幕上下文。注意:提供 cid 时官方播放器会忽略 p 参数:
::: bilibili {bvid="BV1B7411m7LV" cid=279786}
:::OGV(番剧)单集 ID。官方播放器里 episodeId 优先级高于 aid / bvid——同时给出时以番剧集为准。kebab-case 别名 episode-id 同义:
::: bilibili {episodeId=374717}
:::OGV 番剧的季 ID,播放该季正片。别名 season-id:
::: bilibili {seasonId=33802}
:::多 P 稿件的集数(从 1 起)。如上所述,有 cid 时官方忽略此参数:
::: bilibili {aid=170001 p=2}
:::起播时间点,单位秒。写教程时「从第 90 秒的重点看起」非常好用:
::: bilibili {bvid="BV1B7411m7LV" t=90}
:::是否展示封面(布尔)。true/1 序列化为 poster=1,false/0 为 poster=0,不写则不进 URL、跟随官方缺省:
::: bilibili {bvid="BV1B7411m7LV" poster=true}
:::自动播放。这是本插件唯一「强制矫正」的属性:不写时也会显式输出 autoplay=0——官方缺省是自动播放,嵌入场景是反模式。确有需要(如配合 muted 的静音自动播)再显式打开:
::: bilibili {bvid="BV1B7411m7LV" autoplay=true muted=true}
:::静音起播。与 autoplay=true 搭配是浏览器自动播放策略下唯一稳妥的组合:
::: bilibili {bvid="BV1B7411m7LV" muted=true}
:::弹幕开关。写 danmaku=false 关闭初始弹幕层,正文嵌入通常建议关掉以免干扰阅读:
::: bilibili {bvid="BV1B7411m7LV" danmaku=false}
:::高画质开关,序列化为官方的 high_quality=1。注意官方限制:未登录观众最高仍只有 360p,聊胜于无。别名 high-quality:
::: bilibili {bvid="BV1B7411m7LV" highQuality=true}
:::容器宽高比,直接写进 iframe 的 CSS aspect-ratio,缺省 16 / 9。竖屏视频、4:3 老番都靠它:
::: bilibili {bvid="BV1B7411m7LV" ratio="4 / 3"}
:::iframe 的无障碍标题(title 属性),屏幕阅读器朗读用,缺省 Bilibili video player(可经插件 options 改缺省):
::: bilibili {bvid="BV1B7411m7LV" title="示例视频:VitePress 入门"}
:::透传到外层 .bili-embed 容器的额外类名,配合站点自定义 CSS 微调:
::: bilibili {bvid="BV1B7411m7LV" class="hero-video"}
:::透传到外层容器的 id,可作页内锚点跳转目标:
::: bilibili {bvid="BV1B7411m7LV" id="demo-video"}
:::md.use(bilibiliEmbed, options) 的 BilibiliOptions 共三项:
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defaultTitle | string | 'Bilibili video player' | iframe title 缺省文案 |
defaultRatio | string | '16 / 9' | 容器宽高比缺省值(CSS aspect-ratio 语法) |
deferSrc | boolean | false | 输出 data-src 而非 src,由宿主 IntersectionObserver 注入 |
md.use(bilibiliEmbed, {
defaultTitle: '哔哩哔哩视频',
defaultRatio: '16 / 9',
deferSrc: true,
})缺省产物的 iframe 带 loading="lazy",看似万事大吉,实则有两个坑:
deferSrc: true 把懒加载语义从浏览器手里拿回来:构建产物输出 data-src 而非 src,由宿主用 IntersectionObserver 在 iframe 进入视口附近时才注入真实地址(宿主须自备注入脚本,@vaultkit/vitepress-theme-vault 内置)。
还有一个反直觉的细节:deferSrc 模式下产物刻意不带 loading="lazy"——无 src 的 lazy iframe 会让 Chromium 挂起一个子帧 about:blank 导航(bfcache 排除原因 SubframeIsNavigating),反而破坏 bfcache。懒加载语义已由 IO 注入承担,二者不可叠加。
两条校验都发生在构建期,坏嵌入不会带病上线:
bvid / aid / episodeId 全缺 → 抛「缺少视频 ID」danmaku 拼成 danmu)→ 抛「未知属性」VitePress 内建 markdown-it-attrs,花括号属性由它原生解析进 token.attrs;非 VitePress 的 markdown-it 宿主没有这一步,插件自动回退到解析 info 行尾花括号的内置实现,且与 markdown-it-attrs 行为一致(接受无引号值)。同一份 Markdown 在两类宿主下产物相同。
视频区域空白? 检查 bvid 是否有效、视频是否为区域限定内容——播放器加载失败不会回调页面。
能不能不写 caption? 可以。容器正文只含空白时视觉无痕(样式对空 caption 做了收敛处理),单纯 ::: bilibili {...} + ::: 即可。
样式没生效? styles/index.css 需在主题入口显式引入一次,它不随 JS 自动注入(插件 sideEffects: false)。