Files
emdash-cms--emdash/docs/src/pages/llms.txt.ts
T
wehub-resource-sync b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:23:53 +08:00

94 lines
2.8 KiB
TypeScript

import type { APIRoute } from "astro";
import { getCollection, getEntry } from "astro:content";
import config from "virtual:starlight/user-config";
export const prerender = true;
type SidebarItem = NonNullable<typeof config.sidebar>[number];
type DocsEntry = Awaited<ReturnType<typeof getCollection<"docs">>>[number];
type Link = { label: string; href: string };
const TRIM_SLASHES = /^\/|\/$/g;
const ABSOLUTE_URL = /^https?:\/\//;
export const GET: APIRoute = async ({ site }) => {
// Pre-load the docs collection so autogenerated groups can resolve
// without one `getEntry` call per page.
const docs = await getCollection("docs");
const lang = config.defaultLocale.lang;
const title = (lang ? config.title[lang] : undefined) ?? Object.values(config.title)[0] ?? "";
const lines: string[] = [`# ${title}`];
if (config.tagline) {
lines.push("", `> ${config.tagline}`);
}
for (const item of config.sidebar ?? []) {
const links = await resolveItem(item, docs);
if (links.length === 0) continue;
const groupLabel = typeof item !== "string" && "label" in item ? item.label : undefined;
if (groupLabel && typeof item !== "string" && ("items" in item || "autogenerate" in item)) {
lines.push("", `## ${groupLabel}`, "");
} else {
lines.push("");
}
for (const link of links) {
lines.push(`- [${link.label}](${absUrl(link.href, site)})`);
}
}
return new Response(lines.join("\n") + "\n", {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
};
async function resolveItem(item: SidebarItem, docs: DocsEntry[]): Promise<Link[]> {
// Shorthand: a string is a slug reference.
if (typeof item === "string") {
const entry = getEntry("docs", item);
return entry ? [entryLink(entry)] : [];
}
if ("link" in item && item.link) {
return [{ label: item.label, href: item.link }];
}
if ("slug" in item && item.slug) {
const entry = await getEntry("docs", item.slug);
return entry ? [entryLink(entry, item.label)] : [];
}
if ("items" in item && item.items) {
const out: Link[] = [];
for (const child of item.items) {
out.push(...(await resolveItem(child, docs)));
}
return out;
}
if ("autogenerate" in item && item.autogenerate) {
const prefix = item.autogenerate.directory.replace(TRIM_SLASHES, "") + "/";
return docs
.filter((entry) => entry.id.startsWith(prefix))
.toSorted((a, b) => a.id.localeCompare(b.id))
.map((entry) => entryLink(entry));
}
return [];
}
function entryLink(entry: DocsEntry, override?: string): Link {
const slug = entry.id === "index" ? "" : entry.id;
const href = "/" + slug + (slug ? "/" : "");
const label = override ?? entry.data.sidebar?.label ?? entry.data.title;
return { label, href };
}
function absUrl(href: string, site: URL | undefined): string {
if (ABSOLUTE_URL.test(href)) return href;
if (!site) return href;
return new URL(href, site).toString();
}