fix(docs): correct versioned nav links and local dev version routing (#74)

This commit is contained in:
2026-05-18 01:07:17 -07:00
committed by GitHub
parent 6b2cb002ac
commit 799cce6991
19 changed files with 1000 additions and 57 deletions
+66 -11
View File
@@ -1,10 +1,27 @@
import { spawnSync } from 'node:child_process';
import { createHash } from 'node:crypto';
import { cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
import {
cpSync,
existsSync,
lstatSync,
mkdirSync,
readFileSync,
readdirSync,
readlinkSync,
rmSync,
symlinkSync,
writeFileSync,
} from 'node:fs';
import { join, resolve } from 'node:path';
import {
collectSharedAssetPaths,
dedupeVersionedPublicAssets,
pruneArchiveCacheGenerations,
} from './docs-versioned-assets';
import {
buildVersionManifest,
stableTagsWithDocs,
versionArchiveCacheKey,
versionArchiveCacheName,
versionOutputPath,
versionPath,
@@ -18,7 +35,11 @@ const archiveCacheRoot = join(repoRoot, '.tmp/docs-versioned-archive-cache');
const maxCloudflareFiles = 20_000;
const maxCloudflareFileBytes = 25 * 1024 * 1024;
function run(command: string, args: string[], options: { cwd?: string; env?: NodeJS.ProcessEnv } = {}) {
function run(
command: string,
args: string[],
options: { cwd?: string; env?: NodeJS.ProcessEnv } = {},
) {
const result = spawnSync(command, args, {
cwd: options.cwd ?? repoRoot,
env: options.env ?? process.env,
@@ -144,12 +165,14 @@ function buildDocs(options: {
latestStable: string;
manifestJson: string;
}) {
console.info(`[docs] building ${options.version ?? options.channel} -> ${options.base}`);
run('bun', ['run', '--cwd', currentDocsSite, 'vitepress', 'build', options.snapshotDocsSite], {
cwd: repoRoot,
env: {
...process.env,
SUBMINER_DOCS_BASE: options.base,
SUBMINER_DOCS_OUT_DIR: options.outDir,
SUBMINER_DOCS_SOURCE_DIR: options.snapshotDocsSite,
SUBMINER_DOCS_CHANNEL: options.channel,
SUBMINER_DOCS_VERSION: options.version ?? '',
SUBMINER_DOCS_LATEST_STABLE: options.latestStable,
@@ -160,25 +183,28 @@ function buildDocs(options: {
}
function updateHashWithPath(hash: ReturnType<typeof createHash>, path: string) {
if (isGeneratedVitePressPath(path)) {
if (isSharedInternalsHashIgnoredPath(path)) {
return;
}
const stat = lstatSync(path);
hash.update(path.replace(repoRoot, ''));
hash.update(String(stat.mode));
const relativePath = path.replace(repoRoot, '');
if (stat.isSymbolicLink()) {
hash.update(`symlink:${relativePath}`);
hash.update(readlinkSync(path));
return;
}
if (stat.isDirectory()) {
hash.update(`dir:${relativePath}`);
for (const entry of readdirSync(path).sort()) {
updateHashWithPath(hash, join(path, entry));
}
return;
}
hash.update(`file:${relativePath}`);
hash.update(readFileSync(path));
}
@@ -186,8 +212,15 @@ function isGeneratedVitePressPath(path: string): boolean {
return /[\\/]\\.vitepress[\\/](cache|dist)([\\/]|$)/.test(path);
}
function isSharedInternalsHashIgnoredPath(path: string): boolean {
return isGeneratedVitePressPath(path) || /\.test\.[cm]?[jt]s$/.test(path);
}
function computeSharedInternalsHash(): string {
const hash = createHash('sha256');
hash.update(
`version-link-origin:${process.env.SUBMINER_DOCS_VERSION_LINK_ORIGIN === 'local' ? 'local' : 'production'}`,
);
const paths = [
join(currentDocsSite, '.vitepress'),
join(currentDocsSite, 'public/assets/fonts'),
@@ -216,6 +249,7 @@ function restoreCachedArchive(version: string, sharedInternalsHash: string): boo
return false;
}
console.info(`[docs] cache hit ${version}`);
cpSync(cachedArchive, join(aggregateOutDir, versionOutputPath(version)), {
recursive: true,
force: true,
@@ -267,9 +301,7 @@ function assertCloudflarePagesLimits(root: string) {
}
if (oversizedFiles.length > 0) {
throw new Error(
`Versioned docs output has files over 25 MiB:\n${oversizedFiles.join('\n')}`,
);
throw new Error(`Versioned docs output has files over 25 MiB:\n${oversizedFiles.join('\n')}`);
}
}
@@ -284,6 +316,9 @@ function main() {
const manifest = buildVersionManifest({ latestStable, stableVersions });
const manifestJson = JSON.stringify(manifest);
const sharedInternalsHash = computeSharedInternalsHash();
const archiveCacheKey = versionArchiveCacheKey({ sharedInternalsHash, manifestJson });
const sharedAssetPaths = collectSharedAssetPaths(join(currentDocsSite, 'public/assets'));
console.info(`[docs] archive cache key ${archiveCacheKey.slice(0, 12)}`);
rmSync(buildRoot, { recursive: true, force: true });
rmSync(aggregateOutDir, { recursive: true, force: true });
@@ -302,11 +337,13 @@ function main() {
});
for (const version of stableVersions) {
if (restoreCachedArchive(version, sharedInternalsHash)) {
if (restoreCachedArchive(version, archiveCacheKey)) {
continue;
}
const snapshot = version === latestStable ? latestStableSnapshot : prepareSnapshot(version, version);
console.info(`[docs] rebuilding archive ${version}`);
const snapshot =
version === latestStable ? latestStableSnapshot : prepareSnapshot(version, version);
buildDocs({
snapshotDocsSite: snapshot,
base: versionPath(version),
@@ -316,7 +353,12 @@ function main() {
latestStable,
manifestJson,
});
saveArchiveCache(version, sharedInternalsHash);
dedupeVersionedPublicAssets({
outDir: join(aggregateOutDir, versionOutputPath(version)),
base: versionPath(version),
sharedAssetPaths,
});
saveArchiveCache(version, archiveCacheKey);
}
const mainSnapshot = prepareSnapshot('main');
@@ -329,9 +371,22 @@ function main() {
latestStable,
manifestJson,
});
dedupeVersionedPublicAssets({
outDir: join(aggregateOutDir, 'main'),
base: '/main/',
sharedAssetPaths,
});
writeFileSync(join(aggregateOutDir, 'versions.json'), `${JSON.stringify(manifest, null, 2)}\n`);
assertCloudflarePagesLimits(aggregateOutDir);
const prunedArchives = pruneArchiveCacheGenerations({
cacheRoot: archiveCacheRoot,
activeCacheKey: archiveCacheKey,
});
if (prunedArchives.length > 0) {
console.info(`[docs] pruned ${prunedArchives.length} stale archive cache directories`);
}
rmSync(buildRoot, { recursive: true, force: true });
}
main();