Files
deepseek-harness/.agents/notes/implemented/process/2026-08-06-doc-site-carries-its-images.zh.md
Yichen Jiang 2426be893a fix(scripts): let the documentation site carry its own images
An image the manifest does not publish was rewritten to a raw.githubusercontent
URL, which serves a private repository to nobody: raw answers 404 unauthenticated,
and a github.com session does not authenticate it. Every image on the site was
broken for every reader, and no gate could say so — link checking asks whether
the file exists in the repository, not whether a site reader can fetch it.

The projector now copies a referenced image into the generated tree beside the
page and points the reference at it, so Vite bundles it like any other site
asset and repository visibility cannot reach the published page. The copy lands
beside the page so one relative URL is right from both locale trees and a page's
assets leave with the page; two sources projecting onto one path throw rather
than letting the last copy win.

Canonical Markdown keeps writing ordinary repository-relative paths, so the same
file still renders when read in the repository.

The guide this was found through is renamed to its subject: 配置模型.
2026-08-06 20:21:17 +08:00

4.0 KiB
Raw Blame History

Agent Note: 文档站点自带图片

Status: implemented

English | 中文

Problem

scripts/project-doc-site.ts 会把发布清单未收录的仓库相对目标一律改写成 GitHub 地址,对图片而言就是 https://raw.githubusercontent.com/<owner>/<repo>/<ref>/<path>。站点构建不拷贝任何文件:srcDir 是用完即弃的 .generatedVitePress 没有设置 publicDir(其默认值 <srcDir>/public 恰好位于投影每次运行时删除的那棵树里),而写进去的只有 Markdown。

这只对公开仓库成立。本仓库是私有的,而 raw.githubusercontent.com 对未认证请求一律回 404——github.com 上的登录会话也不能认证它,因为 GitHub 自家界面是用另一套单独签名的地址提供私有 blob 的。于是站点上的每一张图片对每一位读者都是坏的,却没有任何门禁能说出来:verify-md-links 与投影校验的是目标文件在仓库里是否存在,那与站点读者能否取到它是两个问题。

Decision

rewriteMarkdown 新增可选的 placeImage(absPath): string。当页面引用了一张清单未作为页面发布的图片时,投影把该文件复制进生成树中该页面的旁边,并把引用改写为 ./<basename>;随后 Vite 会像处理其他站点资源一样打包它。仓库可见性再也影响不到已发布页面。

副本落在页面旁边,而不是某个共享资源目录。每个 locale 的路由树各持一份副本,因此同一个相对 URL 在 guide/en/guide/ 下都正确,无需按 locale 计算前缀;清单撤下某页时,它的资源也随之消失。两个来源若会投影到同一路径则抛错——与既有的重复路由检查同一个立场——而不是让最后拷贝的那个静默胜出。

placeImage 之所以可选,是因为 rewriteMarkdown 也被它自己的 spec 直接调用,而那里并不存在生成树。不传它时保持原有的 GitHub raw 行为,这也让该接缝保持诚实:对只改写文本的消费方而言,这个回退仍是正确答案。

正本 Markdown 照旧写普通的仓库相对图片路径,因此同一份文件在 GitHub 上和站点上都能正常显示。没有任何文档为了迁就 VitePress 而写站内绝对 URL。

Alternatives considered

publicDir 设到 .generated 之外,并使用站内绝对 URL。 投影这边的活动部件更少,但同一份 Markdown 在仓库中阅读时,每一处图片引用都会是坏的,而正本文档是两种方式都要读的。

把图片放到 assets 分支,就像演示 GIF 那样。 那个分支的存在是为了让大体积二进制不进主线历史,而它的 raw 地址有着完全相同的可见性问题。它仍然是录屏的正确归宿;但它解决不了这件事。

等仓库转为公开。 那只是消除症状,不会让站点自给自足,而且每一张图片都会让站点隐式依赖 GitHub 的可用性与限流。

Consequences

已发布文档中的图片,现在无论谁在阅读、无论仓库是否公开都能显示,站点构建也不再为图片依赖 GitHub 的运行时可达性。生成树会为每个 locale 各增加一份被引用图片的副本——配置模型指南里的四张截图,每个 locale 约 270 KB。

未发布文档引用的图片不受影响:它们仍解析到 GitHub raw对私有仓库仍然失败。今天没有任何消费方用到它们而不在站点上的文档也没有站点构建可以承载其资源。

Testing

scripts/project-doc-site.spec.ts 覆盖placer 收到解析后的绝对路径且其返回的 URL 落进 Markdown、存在 placer 时已发布页面的链接仍解析到自己的路由、以及不传 placer 时不变的 GitHub raw 回退。pnpm docs:check 会带着配置模型指南的截图构建站点,并在来源缺失时失败;被拷贝的文件及其 ./<basename> 引用已在 website/.generated 与运行中的 docs:dev 里核实(两个 locale 均 naturalWidth > 0)。