refactor: 模块化重构 generator 和 runtime
This commit is contained in:
135
src/generator/cache/projects.js
vendored
Normal file
135
src/generator/cache/projects.js
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
function tryLoadProjectsRepoCache(pageId, config) {
|
||||
if (!pageId) return null;
|
||||
|
||||
const cacheDirFromEnv = process.env.PROJECTS_CACHE_DIR ? String(process.env.PROJECTS_CACHE_DIR) : '';
|
||||
const cacheDirFromConfig =
|
||||
config && config.site && config.site.github && config.site.github.cacheDir
|
||||
? String(config.site.github.cacheDir)
|
||||
: '';
|
||||
const cacheDir = cacheDirFromEnv || cacheDirFromConfig || 'dev';
|
||||
|
||||
const cacheBaseDir = path.isAbsolute(cacheDir) ? cacheDir : path.join(process.cwd(), cacheDir);
|
||||
const cachePath = path.join(cacheBaseDir, `${pageId}.repo-cache.json`);
|
||||
if (!fs.existsSync(cachePath)) return null;
|
||||
|
||||
try {
|
||||
const raw = fs.readFileSync(cachePath, 'utf8');
|
||||
const parsed = JSON.parse(raw);
|
||||
if (!parsed || typeof parsed !== 'object') return null;
|
||||
|
||||
const repos = Array.isArray(parsed.repos) ? parsed.repos : [];
|
||||
const map = new Map();
|
||||
repos.forEach((r) => {
|
||||
const url = r && r.url ? String(r.url) : '';
|
||||
if (!url) return;
|
||||
map.set(url, {
|
||||
language: r && r.language ? String(r.language) : '',
|
||||
languageColor: r && r.languageColor ? String(r.languageColor) : '',
|
||||
stars: Number.isFinite(r && r.stars) ? r.stars : null,
|
||||
forks: Number.isFinite(r && r.forks) ? r.forks : null,
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
map,
|
||||
meta: {
|
||||
pageId: parsed.pageId || pageId,
|
||||
generatedAt: parsed.generatedAt || '',
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
console.warn(`[WARN] projects 缓存读取失败:${cachePath}(将仅展示标题与描述)`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeGithubRepoUrl(url) {
|
||||
if (!url) return '';
|
||||
try {
|
||||
const u = new URL(String(url));
|
||||
if (u.hostname.toLowerCase() !== 'github.com') return '';
|
||||
const parts = u.pathname.split('/').filter(Boolean);
|
||||
if (parts.length < 2) return '';
|
||||
const owner = parts[0];
|
||||
const repo = parts[1].replace(/\\.git$/i, '');
|
||||
if (!owner || !repo) return '';
|
||||
return `https://github.com/${owner}/${repo}`;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function applyRepoMetaToCategories(categories, repoMetaMap) {
|
||||
if (!Array.isArray(categories) || !(repoMetaMap instanceof Map)) return;
|
||||
|
||||
const walk = (node) => {
|
||||
if (!node || typeof node !== 'object') return;
|
||||
if (Array.isArray(node.subcategories)) node.subcategories.forEach(walk);
|
||||
if (Array.isArray(node.groups)) node.groups.forEach(walk);
|
||||
if (Array.isArray(node.subgroups)) node.subgroups.forEach(walk);
|
||||
|
||||
if (Array.isArray(node.sites)) {
|
||||
node.sites.forEach((site) => {
|
||||
if (!site || typeof site !== 'object' || !site.url) return;
|
||||
const canonical = normalizeGithubRepoUrl(site.url);
|
||||
if (!canonical) return;
|
||||
const meta = repoMetaMap.get(canonical);
|
||||
if (!meta) return;
|
||||
|
||||
site.language = meta.language || '';
|
||||
site.languageColor = meta.languageColor || '';
|
||||
site.stars = meta.stars;
|
||||
site.forks = meta.forks;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
categories.forEach(walk);
|
||||
}
|
||||
|
||||
function normalizeGithubHeatmapColor(input) {
|
||||
const raw = String(input || '')
|
||||
.trim()
|
||||
.replace(/^#/, '');
|
||||
const color = raw.toLowerCase();
|
||||
if (/^[0-9a-f]{6}$/.test(color)) return color;
|
||||
if (/^[0-9a-f]{3}$/.test(color)) return color;
|
||||
return '339af0';
|
||||
}
|
||||
|
||||
function getGithubUsernameFromConfig(config) {
|
||||
const username =
|
||||
config && config.site && config.site.github && config.site.github.username
|
||||
? String(config.site.github.username).trim()
|
||||
: '';
|
||||
return username;
|
||||
}
|
||||
|
||||
function buildProjectsMeta(config) {
|
||||
const username = getGithubUsernameFromConfig(config);
|
||||
if (!username) return null;
|
||||
|
||||
const color = normalizeGithubHeatmapColor(
|
||||
config && config.site && config.site.github && config.site.github.heatmapColor
|
||||
? config.site.github.heatmapColor
|
||||
: '339af0'
|
||||
);
|
||||
|
||||
return {
|
||||
heatmap: {
|
||||
username,
|
||||
profileUrl: `https://github.com/${username}`,
|
||||
imageUrl: `https://ghchart.rshah.org/${color}/${username}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
tryLoadProjectsRepoCache,
|
||||
applyRepoMetaToCategories,
|
||||
buildProjectsMeta,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user