From 53aef1eb642fec402d2d2e045bb9410d85892d1c Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Thu, 5 Nov 2026 22:13:19 +0800 Subject: [PATCH] Prioritize Endorphin and retire Endor from the catalog --- apps/docs/scripts/auth-cli.ts | 11 +++++++++++ apps/docs/src/lib/collections.ts | 13 +++++++++++-- apps/docs/src/lib/docs.ts | 3 ++- apps/docs/src/pages/api/search.ts | 3 ++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/apps/docs/scripts/auth-cli.ts b/apps/docs/scripts/auth-cli.ts index 78f376c..05a4fab 100644 --- a/apps/docs/scripts/auth-cli.ts +++ b/apps/docs/scripts/auth-cli.ts @@ -258,6 +258,17 @@ async function main() { for (const id of ids) assert.ok(html.includes(`href="#${id}"`), `TOC anchor: ${route}#${id}`); } } + assert.ok(!home.includes('data-category="Endor"'), "Superseded Endor collection is absent from navigation"); + if (searchIndex.some((doc: { collection: string }) => doc.collection === "Endorphin")) { + assert.equal([...home.matchAll(/data-category="([^"]+)"/g)][0]?.[1], "Endorphin", "Endorphin is the first category"); + assert.ok(home.includes('/docs/endorphin/value-proposition'), "Endorphin opens at its value proposition"); + } + // Retired documents remain reachable for historical links and gallery checks. + if (!purpose) { + const archived = await request("/docs/endor/endor-purpose-draft", { headers }); + assert.equal(archived.status, 200); + purpose = await archived.text(); + } assert.ok(home.includes("资料库")); assert.ok(home.includes("/docs/source-studies/pretext/overview")); // Inline preview and zoom dialog must both use the compressed browser asset. diff --git a/apps/docs/src/lib/collections.ts b/apps/docs/src/lib/collections.ts index 04a9ef5..50022b8 100644 --- a/apps/docs/src/lib/collections.ts +++ b/apps/docs/src/lib/collections.ts @@ -1,5 +1,11 @@ import type { DocLink } from "@/lib/docs"; +// Keep superseded Endor pages addressable without offering them as current material. +export function catalogDocuments(docs: T[]): T[] { + return docs.filter((doc) => doc.collection !== "Endor 文档") + .sort((a, b) => Number(b.collection === "Endorphin") - Number(a.collection === "Endorphin")); +} + export function collectionLabel(name: string) { return name.replace(/ 文档$| 源码教程$|问题集$/g, ""); } @@ -15,10 +21,13 @@ export function collectionIcon(name?: string): "book" | "code" | "layers" | "nod if (name?.includes("垃圾回收")) return "nodes"; return "book"; } -export function collectionEntries(docs: DocLink[]) { +export function collectionEntries(documents: DocLink[]) { + const docs = catalogDocuments(documents); return [...new Set(docs.map((doc) => doc.collection))].map((name) => { const items = docs.filter((doc) => doc.collection === name); - const entry = items.find((doc) => doc.slug.endsWith("/overview")) ?? items[0]; + const entry = items.find((doc) => doc.slug.endsWith("/overview")) + ?? (name === "Endorphin" ? items.find((doc) => doc.featured) : undefined) + ?? items[0]; return { name, entry, count: items.length }; }); } diff --git a/apps/docs/src/lib/docs.ts b/apps/docs/src/lib/docs.ts index ced0e1c..6e31061 100644 --- a/apps/docs/src/lib/docs.ts +++ b/apps/docs/src/lib/docs.ts @@ -1,4 +1,5 @@ import { randomUUID, createHash } from "node:crypto"; +import { catalogDocuments } from "./collections"; import { openSiteDatabase } from "./site-database"; import { DocumentValidationError, DocumentConflictError } from "./document-errors"; import { sectionSchema, loadSections, reconcileSections, persistSections, splitSections, outline, @@ -188,7 +189,7 @@ export async function readDoc(slug: string): Promise { } export async function listDocs(): Promise { - return allDocuments().map(({ content: _, ...doc }) => { void _; return doc; }); + return catalogDocuments(allDocuments()).map(({ content: _, ...doc }) => { void _; return doc; }); } // Explicit, atomic bootstrap only. Runtime reads never import repository data. diff --git a/apps/docs/src/pages/api/search.ts b/apps/docs/src/pages/api/search.ts index 0dccf33..3eacc5d 100644 --- a/apps/docs/src/pages/api/search.ts +++ b/apps/docs/src/pages/api/search.ts @@ -1,4 +1,5 @@ import type { NextApiRequest, NextApiResponse } from "next"; +import { catalogDocuments } from "@/lib/collections"; import { allDocuments } from "@/lib/docs"; // The proxy authenticates this endpoint, including index content. @@ -9,7 +10,7 @@ export default async function handler(request: NextApiRequest, response: NextApi return response.status(405).end(); } try { - const index = allDocuments().map(({ content, ...doc }) => ({ ...doc, searchText: content })); + const index = catalogDocuments(allDocuments()).map(({ content, ...doc }) => ({ ...doc, searchText: content })); return response.status(200).json(index); } catch { return response.status(503).json({ error: "文档数据库暂时不可用" }); -- 2.52.0