From 1015736635307c6b5e3ccfbe131f016f38fd0821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B6=B5=E6=9B=A6?= Date: Fri, 13 Dec 2024 16:23:27 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=BF=E6=8D=A2=20GitHub=20=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E8=B5=84=E6=BA=90=E9=93=BE=E6=8E=A5=E4=B8=BA=E4=BB=A3?= =?UTF-8?q?=E7=90=86=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.vitepress/config.mts | 1 + .../vitepress-plugin-github-issues.mts | 241 +++++++++--------- 2 files changed, 126 insertions(+), 116 deletions(-) diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index a311932..9018eae 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -62,6 +62,7 @@ export default async ({ mode }) => { targetUrl: '/issues', }, ], + githubProxy: 'https://cloudflare-github-proxy.hanxi-info.workers.dev/proxy', }), ], } diff --git a/docs/.vitepress/vitepress-plugin-github-issues.mts b/docs/.vitepress/vitepress-plugin-github-issues.mts index 1a8743a..fc9e7b1 100644 --- a/docs/.vitepress/vitepress-plugin-github-issues.mts +++ b/docs/.vitepress/vitepress-plugin-github-issues.mts @@ -11,55 +11,56 @@ interface ReplaceRule { } interface GitHubIssuesPluginOptions { - repo: string; // GitHub repository info in the format 'owner/repo' - token: string; - replaceRules: ReplaceRule[]; + repo: string; // GitHub repository info in the format 'owner/repo' + token: string; + replaceRules: ReplaceRule[]; + githubProxy: string; } async function fetchAllIssues(repo: string, token: string): Promise { - const maxRetries = 3; // 最大重试次数 - let attempt = 0; - const allIssues: any[] = []; - let page = 1; + const maxRetries = 3; // 最大重试次数 + let attempt = 0; + const allIssues: any[] = []; + let page = 1; - while (true) { - while (attempt < maxRetries) { - try { - const response = await axios.get(`https://api.github.com/repos/${repo}/issues`, { - headers: { - Authorization: `token ${token}` - }, - params: { - page: page, - per_page: 100 // 每页最多返回100条记录 - } - }); + while (true) { + while (attempt < maxRetries) { + try { + const response = await axios.get(`https://api.github.com/repos/${repo}/issues`, { + headers: { + Authorization: `token ${token}` + }, + params: { + page: page, + per_page: 100 // 每页最多返回100条记录 + } + }); - // 如果没有更多问题了,退出循环 - if (response.data.length === 0) { - return allIssues; - } + // 如果没有更多问题了,退出循环 + if (response.data.length === 0) { + return allIssues; + } - allIssues.push(...response.data); - page++; // 下一页 - attempt = 0; // 重置尝试次数 - break; // 退出尝试循环 - } catch (error) { - if (error.response && error.response.status === 503) { - console.error(`服务不可用, 正在重试...`); - attempt++; - const waitTime = Math.pow(2, attempt) * 1000; // 指数等待时间 - await new Promise(resolve => setTimeout(resolve, waitTime)); - } else { - throw error; // 如果不是503错误,抛出错误并停止重试 - } - } - } + allIssues.push(...response.data); + page++; // 下一页 + attempt = 0; // 重置尝试次数 + break; // 退出尝试循环 + } catch (error) { + if (error.response && error.response.status === 503) { + console.error(`服务不可用, 正在重试...`); + attempt++; + const waitTime = Math.pow(2, attempt) * 1000; // 指数等待时间 + await new Promise(resolve => setTimeout(resolve, waitTime)); + } else { + throw error; // 如果不是503错误,抛出错误并停止重试 + } + } + } - if (attempt >= maxRetries) { - throw new Error('最大重试次数已达,请检查 API 状态(可能是请求过于频繁)'); - } - } + if (attempt >= maxRetries) { + throw new Error('最大重试次数已达,请检查 API 状态(可能是请求过于频繁)'); + } + } } async function fetchIssueComments(repo: string, issueNumber: number, token: string): Promise { @@ -111,69 +112,69 @@ async function fetchIssueComments(repo: string, issueNumber: number, token: stri } function clearDirectory(dir: string) { - if (fs.existsSync(dir)) { - fs.readdirSync(dir).forEach((file) => { - const filePath = path.join(dir, file); - if (fs.lstatSync(filePath).isDirectory()) { - clearDirectory(filePath); // 递归清理子目录 - fs.rmdirSync(filePath); - } else { - fs.unlinkSync(filePath); // 删除文件 - } - }); - console.log(`Cleared directory: ${dir}`); - } + if (fs.existsSync(dir)) { + fs.readdirSync(dir).forEach((file) => { + const filePath = path.join(dir, file); + if (fs.lstatSync(filePath).isDirectory()) { + clearDirectory(filePath); // 递归清理子目录 + fs.rmdirSync(filePath); + } else { + fs.unlinkSync(filePath); // 删除文件 + } + }); + console.log(`Cleared directory: ${dir}`); + } } function copyReadmeFile(source: string, destination: string) { - if (fs.existsSync(source)) { - fs.copyFileSync(source, destination); - console.log(`Copied README.md from ${source} to ${destination}`); - } else { - console.error(`README.md not found at ${source}`); - } + if (fs.existsSync(source)) { + fs.copyFileSync(source, destination); + console.log(`Copied README.md from ${source} to ${destination}`); + } else { + console.error(`README.md not found at ${source}`); + } } export default function GitHubIssuesPlugin(options: GitHubIssuesPluginOptions): Plugin { - const { repo, token, replaceRules } = options; + const { repo, token, replaceRules, githubProxy } = options; - return { - name: 'vitepress-plugin-github-issues', + return { + name: 'vitepress-plugin-github-issues', - async buildStart() { - try { - const issues = await fetchAllIssues(repo, token); + async buildStart() { + try { + const issues = await fetchAllIssues(repo, token); - console.log(`Fetched ${issues.length} issues from GitHub`); // Log the number of issues fetched + console.log(`Fetched ${issues.length} issues from GitHub`); // Log the number of issues fetched - const docsDir = path.join(process.cwd(), 'issues'); + const docsDir = path.join(process.cwd(), 'issues'); - // 清空 issues 目录 - clearDirectory(docsDir); + // 清空 issues 目录 + clearDirectory(docsDir); - // Create a directory to store markdown files if it doesn't exist - if (!fs.existsSync(docsDir)) { - fs.mkdirSync(docsDir); - console.log(`Created docs directory: ${docsDir}`); - } + // Create a directory to store markdown files if it doesn't exist + if (!fs.existsSync(docsDir)) { + fs.mkdirSync(docsDir); + console.log(`Created docs directory: ${docsDir}`); + } - // 拷贝 ../README.md 文件到当前目录 - const readmeSource = path.join(process.cwd(), '../README.md'); - const readmeDestination = path.join(docsDir, 'index.md'); - copyReadmeFile(readmeSource, readmeDestination); + // 拷贝 ../README.md 文件到当前目录 + const readmeSource = path.join(process.cwd(), '../README.md'); + const readmeDestination = path.join(docsDir, 'index.md'); + copyReadmeFile(readmeSource, readmeDestination); - for (const issue of issues) { - // 仅处理包含 "文档" 标签的 issue - const hasDocumentLabel = issue.labels.some(label => label.name === '文档'); - if (hasDocumentLabel) { - const title = issue.title.replace(/[\/\\?%*:|"<>]/g, '-'); - const fileName = `${issue.number}.md`; + for (const issue of issues) { + // 仅处理包含 "文档" 标签的 issue + const hasDocumentLabel = issue.labels.some(label => label.name === '文档'); + if (hasDocumentLabel) { + const title = issue.title.replace(/[\/\\?%*:|"<>]/g, '-'); + const fileName = `${issue.number}.md`; - // 获取评论数据 + // 获取评论数据 const comments = await fetchIssueComments(repo, issue.number, token); - let content = - `--- + let content = + `--- title: ${issue.title} --- @@ -185,44 +186,52 @@ ${issue.body} `; - // 插入评论 - if (comments.length > 0) { - comments.forEach((comment, index) => { - content += ` + // 插入评论 + if (comments.length > 0) { + comments.forEach((comment, index) => { + content += ` ### 评论 ${index + 1} - ${comment.user.login} ${comment.body} --- `; - }); - } else { - content += "没有评论。\n"; - } + }); + } else { + content += "没有评论。\n"; + } - replaceRules.forEach(({ baseUrl, targetUrl }) => { - // 将 baseUrl 转换为正则表达式,匹配后接的路径部分 - const pattern = new RegExp(`${baseUrl.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}(/\\d+)`, 'g'); - // 替换为目标 URL - content = content.replace(pattern, `${targetUrl}$1.html`); - }); + replaceRules.forEach(({ baseUrl, targetUrl }) => { + // 将 baseUrl 转换为正则表达式,匹配后接的路径部分 + const pattern = new RegExp(`${baseUrl.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}(/\\d+)`, 'g'); + // 替换为目标 URL + content = content.replace(pattern, `${targetUrl}$1.html`); + }); - content += `[链接到 GitHub Issue](${issue.html_url})\n` + content = content.replace( + /(https:\/\/github\.com\/([^\/]+\/[^\/]+\/assets\/[^\s]+)/g, + (match, p1) => { + const proxyUrl = `${githubProxy}/${p1}`; // 使用传入的 base URL + return proxyUrl; + } + ); - const filePath = path.join(docsDir, fileName); + content += `[链接到 GitHub Issue](${issue.html_url})\n` - fs.writeFileSync(filePath, content, { encoding: 'utf8' }); - console.log(`Created file: ${filePath}`); // Log each created file - } else { - console.log(`Skipped issue: ${issue.title}`); // Log skipped issues - } - } + const filePath = path.join(docsDir, fileName); - console.log(`Successfully created markdown files from GitHub issues.`); - } catch (error) { - console.error('Error fetching GitHub issues:', error); - } - }, - }; + fs.writeFileSync(filePath, content, { encoding: 'utf8' }); + console.log(`Created file: ${filePath}`); // Log each created file + } else { + console.log(`Skipped issue: ${issue.title}`); // Log skipped issues + } + } + + console.log(`Successfully created markdown files from GitHub issues.`); + } catch (error) { + console.error('Error fetching GitHub issues:', error); + } + }, + }; }