diff --git a/app/components/Contribute.tsx b/app/components/Contribute.tsx index 02254b4..f104e39 100644 --- a/app/components/Contribute.tsx +++ b/app/components/Contribute.tsx @@ -19,17 +19,13 @@ import styles from "./Contribute.module.css"; import { TreeSelect } from "antd"; import type { DefaultOptionType } from "antd/es/select"; import { DataNode } from "antd/es/tree"; - -const REPO_OWNER = "InvolutionHell"; -const REPO_NAME = "involutionhell.github.io"; -const DEFAULT_BRANCH = "main"; -const DOCS_BASE = "app/docs"; +import { buildDocsNewUrl } from "@/lib/github"; type DirNode = { name: string; path: string; children?: DirNode[] }; +// 统一调用工具函数生成 GitHub 新建链接,路径规则与 Edit 按钮一致 function buildGithubNewUrl(dirPath: string, filename: string, title: string) { const file = filename.endsWith(".mdx") ? filename : `${filename}.mdx`; - const fullDir = `${DOCS_BASE}/${dirPath}`.replace(/\/+/g, "/"); const frontMatter = `--- title: ${title || "New Article"} description: @@ -42,7 +38,7 @@ tags: [] Write your content here. `; const params = new URLSearchParams({ filename: file, value: frontMatter }); - return `https://github.com/${REPO_OWNER}/${REPO_NAME}/new/${DEFAULT_BRANCH}/${encodeURIComponent(fullDir)}?${params.toString()}`; + return buildDocsNewUrl(dirPath, params); } // ✅ 用纯文本 label + 一级节点 selectable:false diff --git a/app/components/EditOnGithub.tsx b/app/components/EditOnGithub.tsx new file mode 100644 index 0000000..2e2ec0d --- /dev/null +++ b/app/components/EditOnGithub.tsx @@ -0,0 +1,25 @@ +import Link from "next/link"; + +// 复用的编辑链接按钮,统一封装图标与样式 +interface EditOnGithubProps { + href: string; +} + +export function EditOnGithub({ href }: EditOnGithubProps) { + return ( + + + edit + + + ); +} diff --git a/app/docs/[...slug]/page.tsx b/app/docs/[...slug]/page.tsx index a71654f..a415990 100644 --- a/app/docs/[...slug]/page.tsx +++ b/app/docs/[...slug]/page.tsx @@ -4,7 +4,8 @@ import { notFound } from "next/navigation"; import type { Metadata } from "next"; import { getMDXComponents } from "@/mdx-components"; import { GiscusComments } from "@/app/components/GiscusComments"; -import { getContributors } from "@/lib/github"; +import { EditOnGithub } from "@/app/components/EditOnGithub"; +import { buildDocsEditUrl, getContributors } from "@/lib/github"; import { Contributors } from "@/app/components/Contributors"; interface Param { @@ -21,25 +22,26 @@ export default async function DocPage({ params }: Param) { notFound(); } + // 统一通过工具函数生成 Edit 链接,内部已处理中文目录编码 + const editUrl = buildDocsEditUrl(page.path); // Get file path for contributors const filePath = "app/docs/" + page.file.path; - // Fetch contributors data on server side const contributors = await getContributors(filePath); - const Mdx = page.data.body; return ( -

- {page.data.title} -

+
+

+ {page.data.title} +

+ +
+ -
- -
); diff --git a/app/layout.tsx b/app/layout.tsx index c609f04..0bc4091 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -31,6 +31,11 @@ export default function RootLayout({ + {/* 谷歌图标字体用于 Edit 按钮的 material symbol */} + (segment ?? "").trim().length > 0) + .join("/") + .replace(/\/+/g, "/") + .replace(/^\/+/, "") + .replace(/\/+$/, ""); +} + +// 将路径逐段 URL 编码,处理中文等特殊字符 +function encodeRepoPath(...segments: (string | undefined)[]) { + const joined = joinPath(...segments); + if (!joined) return ""; + return joined + .split("/") + .map((segment) => encodeURIComponent(segment)) + .join("/"); +} + +// 构建文档的 GitHub 编辑链接 +export function buildDocsEditUrl(relativeDocPath: string) { + const encoded = encodeRepoPath(DOCS_BASE, relativeDocPath); + return `${REPO_BASE_URL}/edit/${DEFAULT_BRANCH}/${encoded}`; +} + +// 构建在 GitHub 新建文档的链接,附带 frontmatter 参数 +export function buildDocsNewUrl(relativeDir: string, params: URLSearchParams) { + const encodedDir = encodeRepoPath(DOCS_BASE, relativeDir); + const query = params.toString(); + const suffix = query ? `?${query}` : ""; + return `${REPO_BASE_URL}/new/${DEFAULT_BRANCH}/${encodedDir}${suffix}`; +} + +// 帮助预览完整 docs 路径(未编码) +export function normalizeDocsPath(relative: string) { + return joinPath(DOCS_BASE, relative); +} + +// 暴露常量给其他场景复用 +export const githubConstants = { + owner: GITHUB_OWNER, + repo: GITHUB_REPO, + defaultBranch: DEFAULT_BRANCH, + docsBase: DOCS_BASE, + repoBaseUrl: REPO_BASE_URL, +}; + + + // Define contributor data structure interface Contributor { login: string;