docs: 替换 GitHub 图片资源链接为代理链接

This commit is contained in:
涵曦 2024-12-13 16:23:27 +08:00
parent 1e0949703f
commit 1015736635
2 changed files with 126 additions and 116 deletions

View File

@ -62,6 +62,7 @@ export default async ({ mode }) => {
targetUrl: '/issues', targetUrl: '/issues',
}, },
], ],
githubProxy: 'https://cloudflare-github-proxy.hanxi-info.workers.dev/proxy',
}), }),
], ],
} }

View File

@ -11,55 +11,56 @@ interface ReplaceRule {
} }
interface GitHubIssuesPluginOptions { interface GitHubIssuesPluginOptions {
repo: string; // GitHub repository info in the format 'owner/repo' repo: string; // GitHub repository info in the format 'owner/repo'
token: string; token: string;
replaceRules: ReplaceRule[]; replaceRules: ReplaceRule[];
githubProxy: string;
} }
async function fetchAllIssues(repo: string, token: string): Promise<any[]> { async function fetchAllIssues(repo: string, token: string): Promise<any[]> {
const maxRetries = 3; // 最大重试次数 const maxRetries = 3; // 最大重试次数
let attempt = 0; let attempt = 0;
const allIssues: any[] = []; const allIssues: any[] = [];
let page = 1; let page = 1;
while (true) { while (true) {
while (attempt < maxRetries) { while (attempt < maxRetries) {
try { try {
const response = await axios.get(`https://api.github.com/repos/${repo}/issues`, { const response = await axios.get(`https://api.github.com/repos/${repo}/issues`, {
headers: { headers: {
Authorization: `token ${token}` Authorization: `token ${token}`
}, },
params: { params: {
page: page, page: page,
per_page: 100 // 每页最多返回100条记录 per_page: 100 // 每页最多返回100条记录
} }
}); });
// 如果没有更多问题了,退出循环 // 如果没有更多问题了,退出循环
if (response.data.length === 0) { if (response.data.length === 0) {
return allIssues; return allIssues;
} }
allIssues.push(...response.data); allIssues.push(...response.data);
page++; // 下一页 page++; // 下一页
attempt = 0; // 重置尝试次数 attempt = 0; // 重置尝试次数
break; // 退出尝试循环 break; // 退出尝试循环
} catch (error) { } catch (error) {
if (error.response && error.response.status === 503) { if (error.response && error.response.status === 503) {
console.error(`服务不可用, 正在重试...`); console.error(`服务不可用, 正在重试...`);
attempt++; attempt++;
const waitTime = Math.pow(2, attempt) * 1000; // 指数等待时间 const waitTime = Math.pow(2, attempt) * 1000; // 指数等待时间
await new Promise(resolve => setTimeout(resolve, waitTime)); await new Promise(resolve => setTimeout(resolve, waitTime));
} else { } else {
throw error; // 如果不是503错误抛出错误并停止重试 throw error; // 如果不是503错误抛出错误并停止重试
} }
} }
} }
if (attempt >= maxRetries) { if (attempt >= maxRetries) {
throw new Error('最大重试次数已达,请检查 API 状态(可能是请求过于频繁)'); throw new Error('最大重试次数已达,请检查 API 状态(可能是请求过于频繁)');
} }
} }
} }
async function fetchIssueComments(repo: string, issueNumber: number, token: string): Promise<any[]> { async function fetchIssueComments(repo: string, issueNumber: number, token: string): Promise<any[]> {
@ -111,69 +112,69 @@ async function fetchIssueComments(repo: string, issueNumber: number, token: stri
} }
function clearDirectory(dir: string) { function clearDirectory(dir: string) {
if (fs.existsSync(dir)) { if (fs.existsSync(dir)) {
fs.readdirSync(dir).forEach((file) => { fs.readdirSync(dir).forEach((file) => {
const filePath = path.join(dir, file); const filePath = path.join(dir, file);
if (fs.lstatSync(filePath).isDirectory()) { if (fs.lstatSync(filePath).isDirectory()) {
clearDirectory(filePath); // 递归清理子目录 clearDirectory(filePath); // 递归清理子目录
fs.rmdirSync(filePath); fs.rmdirSync(filePath);
} else { } else {
fs.unlinkSync(filePath); // 删除文件 fs.unlinkSync(filePath); // 删除文件
} }
}); });
console.log(`Cleared directory: ${dir}`); console.log(`Cleared directory: ${dir}`);
} }
} }
function copyReadmeFile(source: string, destination: string) { function copyReadmeFile(source: string, destination: string) {
if (fs.existsSync(source)) { if (fs.existsSync(source)) {
fs.copyFileSync(source, destination); fs.copyFileSync(source, destination);
console.log(`Copied README.md from ${source} to ${destination}`); console.log(`Copied README.md from ${source} to ${destination}`);
} else { } else {
console.error(`README.md not found at ${source}`); console.error(`README.md not found at ${source}`);
} }
} }
export default function GitHubIssuesPlugin(options: GitHubIssuesPluginOptions): Plugin { export default function GitHubIssuesPlugin(options: GitHubIssuesPluginOptions): Plugin {
const { repo, token, replaceRules } = options; const { repo, token, replaceRules, githubProxy } = options;
return { return {
name: 'vitepress-plugin-github-issues', name: 'vitepress-plugin-github-issues',
async buildStart() { async buildStart() {
try { try {
const issues = await fetchAllIssues(repo, token); 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 目录 // 清空 issues 目录
clearDirectory(docsDir); clearDirectory(docsDir);
// Create a directory to store markdown files if it doesn't exist // Create a directory to store markdown files if it doesn't exist
if (!fs.existsSync(docsDir)) { if (!fs.existsSync(docsDir)) {
fs.mkdirSync(docsDir); fs.mkdirSync(docsDir);
console.log(`Created docs directory: ${docsDir}`); console.log(`Created docs directory: ${docsDir}`);
} }
// 拷贝 ../README.md 文件到当前目录 // 拷贝 ../README.md 文件到当前目录
const readmeSource = path.join(process.cwd(), '../README.md'); const readmeSource = path.join(process.cwd(), '../README.md');
const readmeDestination = path.join(docsDir, 'index.md'); const readmeDestination = path.join(docsDir, 'index.md');
copyReadmeFile(readmeSource, readmeDestination); copyReadmeFile(readmeSource, readmeDestination);
for (const issue of issues) { for (const issue of issues) {
// 仅处理包含 "文档" 标签的 issue // 仅处理包含 "文档" 标签的 issue
const hasDocumentLabel = issue.labels.some(label => label.name === '文档'); const hasDocumentLabel = issue.labels.some(label => label.name === '文档');
if (hasDocumentLabel) { if (hasDocumentLabel) {
const title = issue.title.replace(/[\/\\?%*:|"<>]/g, '-'); const title = issue.title.replace(/[\/\\?%*:|"<>]/g, '-');
const fileName = `${issue.number}.md`; const fileName = `${issue.number}.md`;
// 获取评论数据 // 获取评论数据
const comments = await fetchIssueComments(repo, issue.number, token); const comments = await fetchIssueComments(repo, issue.number, token);
let content = let content =
`--- `---
title: ${issue.title} title: ${issue.title}
--- ---
@ -185,44 +186,52 @@ ${issue.body}
`; `;
// 插入评论 // 插入评论
if (comments.length > 0) { if (comments.length > 0) {
comments.forEach((comment, index) => { comments.forEach((comment, index) => {
content += ` content += `
### ${index + 1} - ${comment.user.login} ### ${index + 1} - ${comment.user.login}
${comment.body} ${comment.body}
--- ---
`; `;
}); });
} else { } else {
content += "没有评论。\n"; content += "没有评论。\n";
} }
replaceRules.forEach(({ baseUrl, targetUrl }) => { replaceRules.forEach(({ baseUrl, targetUrl }) => {
// 将 baseUrl 转换为正则表达式,匹配后接的路径部分 // 将 baseUrl 转换为正则表达式,匹配后接的路径部分
const pattern = new RegExp(`${baseUrl.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}(/\\d+)`, 'g'); const pattern = new RegExp(`${baseUrl.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}(/\\d+)`, 'g');
// 替换为目标 URL // 替换为目标 URL
content = content.replace(pattern, `${targetUrl}$1.html`); 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' }); const filePath = path.join(docsDir, fileName);
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.`); fs.writeFileSync(filePath, content, { encoding: 'utf8' });
} catch (error) { console.log(`Created file: ${filePath}`); // Log each created file
console.error('Error fetching GitHub issues:', error); } 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);
}
},
};
} }