Skip to content

Commit 310f544

Browse files
fix(site): restore Last Updated across split build
分卷构建(scripts/build.ts)把 md 复制到 gitignored 的 site/.vitepress/.build-tmp/ 再交 VitePress 构建。VitePress 的 lastUpdated 默认对构建源文件跑 git log 取时间,副本不在 git index 里拿不到历史(实测返回空),导致线上 Last Updated 消失。新增 git-timestamp.ts:transformPageData 用 pageData.relativePath 定位 documents/ 下真实源文件(副本保留目录结构、EN 带 en/ 前缀),对其 git log 取毫秒时间戳覆盖 pageData.lastUpdated,单位对齐 VitePress 内部 +new Date(--pretty=%ai)。本地构建验证:GPIO 页渲染 <time datetime=2026-06-15T11:08:53Z>,全站 1009 页含 last-updated 块。
1 parent 8779005 commit 310f544

2 files changed

Lines changed: 64 additions & 1 deletion

File tree

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { execFileSync } from 'node:child_process'
2+
import { existsSync } from 'node:fs'
3+
import { join } from 'node:path'
4+
import { fileURLToPath } from 'node:url'
5+
6+
// 本文件恒定位于 site/.vitepress/config/,上推三级 = 项目根。
7+
// 用 import.meta.url 定位,分卷构建时本文件仍从真实位置加载(不被复制),路径稳定。
8+
const HERE = fileURLToPath(new URL('./', import.meta.url))
9+
const DOCUMENTS = join(HERE, '..', '..', '..', 'documents')
10+
11+
const cache = new Map<string, number | undefined>()
12+
13+
/**
14+
* 返回某 markdown 源文件最后的 git 提交时间(毫秒),供 VitePress 的
15+
* `transformPageData` 覆盖 `pageData.lastUpdated` 用。
16+
*
17+
* 为什么需要它:`scripts/build.ts` 分卷构建会把 `documents/` 下的 md 复制到
18+
* `site/.vitepress/.build-tmp/`(gitignored) 再交给 VitePress 构建。VitePress 的
19+
* `lastUpdated` 默认对构建源文件跑 `git log` 取时间,但这些副本不在 git index 里、
20+
* 拿不到任何历史(实测 `git log` 对副本返回空),导致线上 "Last Updated" 一片空白。
21+
*
22+
* 解法:`transformPageData` 拿到的 `pageData.relativePath` 反映的是文件在 documents/
23+
* 树里的相对位置——分卷副本原样保留了目录结构,EN 副本也带 `en/` 前缀——所以直接用
24+
* 它在真实的 `documents/` 下定位源文件、对源文件跑 `git log`,把毫秒级时间戳喂回
25+
* `pageData.lastUpdated`,绕开副本丢历史的问题。dev / 单体构建(srcDir 指向 documents/)
26+
* 下查的也是同一份真实文件,行为与 VitePress 默认一致。
27+
*
28+
* 单位对齐:VitePress 内部 `getGitTimestamp` 用 `+new Date(git log --pretty=%ai)`,
29+
* 结果是毫秒;这里用 `git log --format=%at`(秒) × 1000 对齐,避免显示成 1970 年。
30+
*/
31+
export function getGitTimestampMs(relativePath: string): number | undefined {
32+
if (!relativePath) return undefined
33+
if (cache.has(relativePath)) return cache.get(relativePath)
34+
35+
const realPath = join(DOCUMENTS, relativePath)
36+
let result: number | undefined
37+
if (existsSync(realPath)) {
38+
try {
39+
const out = execFileSync(
40+
'git',
41+
['log', '-1', '--format=%at', '--', realPath],
42+
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
43+
).trim()
44+
const sec = out ? parseInt(out, 10) : NaN
45+
result = Number.isFinite(sec) ? sec * 1000 : undefined
46+
} catch {
47+
result = undefined // 非 git 仓库 / 无历史 → 回退,交由 VitePress 默认行为
48+
}
49+
}
50+
cache.set(relativePath, result)
51+
return result
52+
}

site/.vitepress/config/shared.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import type { DefaultTheme } from 'vitepress'
1+
import type { DefaultTheme, PageData } from 'vitepress'
22
import { navZh, navEn } from './nav'
3+
import { getGitTimestampMs } from './git-timestamp'
34
import { kbdPlugin } from '../plugins/kbd-plugin'
45
import { cppTemplateEscapePlugin } from '../plugins/escape-cpp-templates'
56
import { mermaidPlugin } from '../plugins/mermaid-plugin'
@@ -38,6 +39,16 @@ export const sharedBase = {
3839
cleanUrls: true,
3940
lastUpdated: true,
4041

42+
// 分卷构建(scripts/build.ts)把 md 复制到 gitignored 的临时目录再交给 VitePress,
43+
// VitePress 默认对副本跑 `git log` 拿不到历史,"Last Updated" 渲染不出来。这里改用
44+
// documents/ 下真实源文件的提交时间覆盖 pageData.lastUpdated。详见 git-timestamp.ts。
45+
async transformPageData(pageData: PageData) {
46+
const ms = getGitTimestampMs(pageData.relativePath)
47+
if (ms) {
48+
pageData.lastUpdated = ms
49+
}
50+
},
51+
4152
vite: {
4253
build: {
4354
chunkSizeWarningLimit: 5000,

0 commit comments

Comments
 (0)