Files
homarr/apps/docs/src/lib/source.ts
T
+12 fcd7c979df feat!: release v2 (#6545)
Co-authored-by: Artur <145776561+arturict@users.noreply.github.com>
Co-authored-by: arturict <arturict@users.noreply.github.com>
Co-authored-by: Thomas <thomas@ajnart.fr>
Co-authored-by: Afonso Jorge Ramos <afonsojorgeramos@gmail.com>
Co-authored-by: Danura30082 <danura30082+github@gmail.com>
Co-authored-by: Kushie <122986913+kushiemoon-dev@users.noreply.github.com>
Co-authored-by: ajnart <thomas@ajnart.fr>
Co-authored-by: ajnart <thomas@ajnart.dev>
Co-authored-by: chenjun <chenjun@foxmail.com>
Co-authored-by: Wikibear <wikibear@users.noreply.github.com>
Co-authored-by: Bergasha <bergasha@gmail.com>
Co-authored-by: leafyelin <43306196+leafyelin@users.noreply.github.com>
Co-authored-by: Lucas Araujo <lucas.lra@gmail.com>
Co-authored-by: GreenMonito <86085570+GreenMonito@users.noreply.github.com>
Co-authored-by: Nerdy-Technician <roffo@nerdy-technician.social>
Co-authored-by: Jun <34545896+jcstrong@users.noreply.github.com>
Co-authored-by: Edmond Abraham <54119952+gitedmond@users.noreply.github.com>
Co-authored-by: thrawnx <tight.bulb9384@fastmail.com>
Co-authored-by: Chris <58918656+nordada@users.noreply.github.com>
Co-authored-by: yi111 <153097222+Yi-111-a@users.noreply.github.com>
Co-authored-by: Yanis <naamaneyanis@gmail.com>
Co-authored-by: Wikibear <me@sej.de>
Co-authored-by: alessiottavo <93441886+alessiottavo@users.noreply.github.com>
2026-10-02 21:00:14 +02:00

152 lines
4.4 KiB
TypeScript

import { llms, loader } from "fumadocs-core/source";
import { metaSchema, pageSchema } from "fumadocs-core/source/schema";
import { defineCollections, defineDocs } from "fumadocs-mdx/macro";
import { z } from "zod";
import { metadataMarkdownComponents } from "@/components/mdx/metadata-markdown";
const titleFromSource = (source: string, path: string) => {
const heading = /^#\s+(.+)$/m
.exec(source)?.[1]
?.replace(/\[([^\]]+)\]\([^)]*\)/g, "$1")
.replace(/[*_`]/g, "")
.trim();
if (heading) return heading;
const name =
path
.split("/")
.at(-1)
?.replace(/\.(md|mdx)$/, "")
.replace(/^index$/, "Overview") ?? "Overview";
return name.replace(/[-_]+/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
};
const docs = defineDocs({
dir: "docs",
docs: {
schema: ({ source, path }) =>
pageSchema
.extend({
title: z.string().optional(),
hide_title: z.boolean().optional(),
sidebar_label: z.string().optional(),
sidebar_position: z.number().optional(),
tags: z.array(z.string()).optional(),
})
.transform((data) => ({ ...data, title: data.title ?? titleFromSource(source, path) })),
postprocess: {
extractLinkReferences: true,
includeProcessedMarkdown: { output: "function" },
},
},
meta: {
schema: metaSchema,
},
});
export const posts = defineCollections({
type: "doc",
dir: "blog",
files: ["**/index.mdx"],
schema: pageSchema.extend({
date: z.string().date(),
authors: z.array(z.string()),
tags: z.array(z.string()).optional(),
slug: z.string().optional(),
}),
postprocess: {
extractLinkReferences: true,
includeProcessedMarkdown: true,
},
});
export const docsRoute = "/docs";
export const docsContentRoute = "/llms.mdx/docs";
export const source = loader({
baseUrl: docsRoute,
source: docs.toFumadocsSource(),
pageTree: {
transformers: [
{
folder(node) {
return node.children.length === 0 ? { ...node, collapsible: false } : node;
},
},
],
},
});
export function getPageMarkdownUrl(page: (typeof source)["$inferPage"]) {
const segments = [...page.slugs, "content.md"];
return {
segments,
url: `/${[...docsContentRoute.split("/"), ...segments].filter(Boolean).join("/")}`,
};
}
export const docsLlms = llms(source, {
renderDescription(node, { lang }) {
if (node.type === "page") {
const page = source.getNodePage(node, lang);
if (page) {
return [page.data.description, `[Markdown](${getPageMarkdownUrl(page).url})`].filter(Boolean).join(" ");
}
}
if (typeof node.description === "string") return node.description;
return "";
},
async renderPage(page) {
const processed = await getPageMarkdown(page);
const body = processed.replace(/^\s*#\s+[^\n]+\n+/, "");
return `# ${page.data.title} (${page.url})\n\n${body}`;
},
});
export function getPageMarkdown(page: (typeof source)["$inferPage"]) {
return page.data.getText("processed", { components: metadataMarkdownComponents });
}
export type BlogPost = (typeof posts.entries)[number];
export function getPostSegments(post: BlogPost) {
if (post.slug) return [post.slug];
const [year, datedFolder = ""] = post.info.path.split("/");
const match = /^(\d{2})-(\d{2})-(.+)$/.exec(datedFolder);
return match ? [year, match[1], match[2], match[3]] : [year, datedFolder].filter(Boolean);
}
export function getPostUrl(post: BlogPost) {
return `/blog/${getPostSegments(post).join("/")}`;
}
export function getPostBySegments(segments: string[]) {
return posts.entries.find((post) => getPostSegments(post).join("/") === segments.join("/"));
}
export function getPostMarkdownUrl(post: BlogPost) {
return `/llms.mdx/blog/${[...getPostSegments(post), "content.md"].join("/")}`;
}
export async function getPostLLMText(post: BlogPost) {
const processed = await post.getText("processed");
return `# ${post.title} (${getPostUrl(post)})\n\n${processed}`;
}
export async function getPostExcerpt(post: BlogPost) {
const raw = await post.getText("raw");
return raw
.replace(/^---[\s\S]*?---\s*/, "")
.split("{/* Historical excerpt boundary. */}", 1)[0]
.replace(/^import\s.+$/gm, "")
.replace(/^#\s+.+$/m, "")
.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1")
.replace(/\[([^\]]+)\]\([^)]*\)/g, "$1")
.replace(/[*_`>#]/g, "")
.replace(/\s+/g, " ")
.trim();
}