feat(docs): version-based docs, correct Gitea tag links, form guide help
- each release now carries a full docs snapshot (reference + handbook) under docs/releases/<v>/; the docs frontend loads a version's snapshot for /docs/vX.Y.Z/* and shows the handbook/reference of that version - version dropdown navigates to /docs/<version> (docs home) instead of the release notes page; old /docs/vX.Y.Z redirect removed - generator: --snapshot writes handbook + reference; build copies versioned snapshots (last 7 versions) into /docs/versions/<v>/ - fix Gitea tag links: /admin/tool-evaluator/tags/<v> was 404, correct URL is /releases/tag/<v> - add GuideHelp button to forms/pages linking to the matching handbook guide (rating, tool add/edit, costs, compare, watchlist, analytics)
This commit is contained in:
@@ -196,7 +196,7 @@ function slugify(name) {
|
||||
return name.replace(/\.md$/, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-");
|
||||
}
|
||||
|
||||
async function buildHandbookIndex() {
|
||||
async function readHandbookPages() {
|
||||
let files;
|
||||
try {
|
||||
files = (await readdir(handbookDir)).filter(isHandbookFile);
|
||||
@@ -213,13 +213,35 @@ async function buildHandbookIndex() {
|
||||
file,
|
||||
title: frontmatter.title ?? extractTitle(body) ?? basename(file),
|
||||
order: typeof frontmatter.order === "number" ? frontmatter.order : 999,
|
||||
body,
|
||||
});
|
||||
await writeFile(join(targetDir, "handbook", file), body);
|
||||
}
|
||||
pages.sort((a, b) => a.order - b.order || a.title.localeCompare(b.title));
|
||||
return pages;
|
||||
}
|
||||
|
||||
async function writeHandbookTo(dir) {
|
||||
const pages = await readHandbookPages();
|
||||
await mkdir(dir, { recursive: true });
|
||||
for (const page of pages) {
|
||||
await writeFile(join(dir, page.file), page.body);
|
||||
}
|
||||
await writeFile(
|
||||
join(dir, "index.json"),
|
||||
JSON.stringify(
|
||||
pages.map(({ slug, file, title, order }) => ({ slug, file, title, order })),
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
return pages;
|
||||
}
|
||||
|
||||
async function buildHandbookIndex() {
|
||||
const pages = await writeHandbookTo(join(targetDir, "handbook"));
|
||||
return pages;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Search index
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -295,7 +317,8 @@ async function writeSnapshot(version) {
|
||||
const dir = join(releasesDir, version);
|
||||
await mkdir(dir, { recursive: true });
|
||||
await writeFile(join(dir, "reference.json"), JSON.stringify(reference, null, 2));
|
||||
console.log(`[generate-docs] snapshot ${version} -> ${join(dir, "reference.json")}`);
|
||||
await writeHandbookTo(join(dir, "handbook"));
|
||||
console.log(`[generate-docs] snapshot ${version} -> ${dir}/ (reference.json + handbook)`);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -343,27 +366,48 @@ async function main() {
|
||||
JSON.stringify(handbookPages, null, 2),
|
||||
);
|
||||
|
||||
// 3. Release notes + versioned reference snapshots
|
||||
// 3. Release notes + versioned docs snapshots (last 7 versions)
|
||||
const versions = [];
|
||||
for (const name of releaseNames) {
|
||||
for (const name of releaseNames.slice(0, 7)) {
|
||||
const version = parseVersion(name);
|
||||
const content = await readFile(join(releasesDir, name), "utf8");
|
||||
await copyFile(join(releasesDir, name), join(targetDir, "releases", name));
|
||||
const hasSnapshot = await stat(join(releasesDir, version, "reference.json"))
|
||||
const snapDir = join(releasesDir, version);
|
||||
const hasReference = await stat(join(snapDir, "reference.json"))
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
if (hasSnapshot) {
|
||||
const hasHandbook = await stat(join(snapDir, "handbook", "index.json"))
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
if (hasReference) {
|
||||
await copyFile(
|
||||
join(releasesDir, version, "reference.json"),
|
||||
join(snapDir, "reference.json"),
|
||||
join(targetDir, "versions", `${version}.json`),
|
||||
);
|
||||
}
|
||||
if (hasHandbook) {
|
||||
await mkdir(join(targetDir, "versions", version, "handbook"), { recursive: true });
|
||||
await copyFile(
|
||||
join(snapDir, "handbook", "index.json"),
|
||||
join(targetDir, "versions", version, "handbook", "index.json"),
|
||||
);
|
||||
const pages = JSON.parse(
|
||||
await readFile(join(snapDir, "handbook", "index.json"), "utf8"),
|
||||
);
|
||||
for (const page of pages) {
|
||||
await copyFile(
|
||||
join(snapDir, "handbook", page.file),
|
||||
join(targetDir, "versions", version, "handbook", page.file),
|
||||
);
|
||||
}
|
||||
}
|
||||
versions.push({
|
||||
version,
|
||||
file: `releases/${name}`,
|
||||
title: extractTitle(content) ?? version,
|
||||
date: extractDate(content) ?? null,
|
||||
hasReference: hasSnapshot,
|
||||
hasReference,
|
||||
hasHandbook,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user