114 lines
3.3 KiB
TypeScript
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}
|
|
},
|
|
});
|
|
`;
|
|
}
|