Files
VitPress-CMS/src/utils/siteContent.ts
2026-06-05 23:22:42 +08:00

114 lines
3.3 KiB
TypeScript

import type { SiteSettings } from "../types";
export function parseFrontmatter(source: string) {
const match = source.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
if (!match) {
return {
title: "",
description: "",
content: source,
};
}
const frontmatter = match[1];
const title = frontmatter.match(/^title:\s*(.+)$/m)?.[1]?.trim().replace(/^["']|["']$/g, "") ?? "";
const description =
frontmatter.match(/^description:\s*(.+)$/m)?.[1]?.trim().replace(/^["']|["']$/g, "") ?? "";
return {
title,
description,
content: source.slice(match[0].length),
};
}
export function stringifyMarkdownPage(page: {
title: string;
description: string;
content: string;
}) {
const frontmatter = [
"---",
`title: ${page.title || "未命名页面"}`,
`description: ${page.description || ""}`,
"---",
"",
].join("\n");
return `${frontmatter}${page.content.trimStart()}`;
}
function readStringValue(source: string, key: string, fallback = "") {
const pattern = new RegExp(`${key}:\\s*["'\`]([^"'\`]+)["'\`]`);
return source.match(pattern)?.[1] ?? fallback;
}
function readBooleanValue(source: string, key: string, fallback = false) {
const pattern = new RegExp(`${key}:\\s*(true|false)`);
const value = source.match(pattern)?.[1];
return value ? value === "true" : fallback;
}
export function parseSiteSettings(source: string): SiteSettings {
const socialLinksSource = source.match(/socialLinks:\s*\[([\s\S]*?)\]/)?.[1] ?? "";
return {
title: readStringValue(source, "title", "VitePress Site"),
description: readStringValue(source, "description"),
logo: readStringValue(source, "logo", "/logo.svg"),
lastUpdated: readBooleanValue(source, "lastUpdated", true),
localSearch: /search:\s*{[\s\S]*?provider:\s*["']local["'][\s\S]*?}/.test(source),
outline: readBooleanValue(source, "outline", true),
socialKind: readStringValue(socialLinksSource, "icon", "github"),
socialLink: readStringValue(socialLinksSource, "link", "https://github.com/example/vitepress-cms"),
};
}
export function stringifySiteConfig(settings: SiteSettings) {
const searchConfig = settings.localSearch
? ` search: {
provider: "local",
},`
: "";
return `import { defineConfig } from "vitepress";
export default defineConfig({
title: ${JSON.stringify(settings.title)},
description: ${JSON.stringify(settings.description)},
lastUpdated: ${settings.lastUpdated},
themeConfig: {
logo: ${JSON.stringify(settings.logo)},
outline: ${settings.outline},
nav: [
{ text: "首页", link: "/" },
{ text: "指南", link: "/guide/getting-started" },
{ text: "配置", link: "/guide/config" },
{ text: "更新日志", link: "/changelog" },
],
sidebar: {
"/guide/": [
{
text: "指南",
items: [
{ text: "快速开始", link: "/guide/getting-started" },
{ text: "页面管理", link: "/guide/pages" },
{ text: "配置说明", link: "/guide/config" },
],
},
],
},
socialLinks: [
{ icon: ${JSON.stringify(settings.socialKind)}, link: ${JSON.stringify(settings.socialLink)} },
],
footer: {
message: "Powered by VitePress-CMS",
copyright: "Copyright 2026",
},
${searchConfig}
},
});
`;
}