const fs = require('fs'); const yaml = require('js-yaml'); const path = require('path'); // HTML转义函数,防止XSS攻击 function escapeHtml(unsafe) { if (unsafe === undefined || unsafe === null) { return ''; } return String(unsafe) .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } // 读取配置文件 function loadConfig() { let config = {}; // 读取默认配置 try { const defaultConfigFile = fs.readFileSync('config.yml', 'utf8'); config = yaml.load(defaultConfigFile); } catch (e) { console.error('Error loading default config file:', e); process.exit(1); } // 尝试读取用户配置并合并 try { if (fs.existsSync('config.user.yml')) { const userConfigFile = fs.readFileSync('config.user.yml', 'utf8'); const userConfig = yaml.load(userConfigFile); // 深度合并配置,用户配置优先 config = mergeConfigs(config, userConfig); console.log('Using user configuration from config.user.yml'); } else { console.log('No user configuration found, using default config.yml'); } } catch (e) { console.error('Error loading user config file:', e); console.log('Falling back to default configuration'); } return config; } // 深度合并配置对象 function mergeConfigs(defaultConfig, userConfig) { if (!userConfig) return defaultConfig; const merged = { ...defaultConfig }; for (const key in userConfig) { if (typeof userConfig[key] === 'object' && !Array.isArray(userConfig[key])) { merged[key] = mergeConfigs(defaultConfig[key] || {}, userConfig[key]); } else { merged[key] = userConfig[key]; } } return merged; } // 生成导航菜单 function generateNavigation(navigation) { return navigation.map(nav => `
${escapeHtml(nav.name)}
`).join('\n'); } // 生成网站卡片HTML function generateSiteCards(sites) { return sites.map(site => `

${escapeHtml(site.name)}

${escapeHtml(site.description)}

`).join('\n'); } // 生成分类HTML function generateCategories(categories) { return categories.map(category => `

${escapeHtml(category.name)}

${generateSiteCards(category.sites)}
`).join('\n'); } // 生成社交链接HTML function generateSocialLinks(social) { return social.map(link => `
${escapeHtml(link.name)}
`).join('\n'); } // 生成页面内容 function generatePageContent(pageId, data) { return `

${escapeHtml(data.title)}

${escapeHtml(data.subtitle)}

${generateCategories(data.categories)}`; } // 生成搜索结果页面 function generateSearchResultsPage(config) { // 获取所有导航页面ID const pageIds = config.navigation.map(nav => nav.id); // 生成所有页面的搜索结果区域 const searchSections = pageIds.map(pageId => { // 根据页面ID获取对应的图标和名称 const navItem = config.navigation.find(nav => nav.id === pageId); const icon = navItem ? navItem.icon : 'fas fa-file'; const name = navItem ? navItem.name : pageId; return ` `; }).join('\n'); return `

搜索结果

在所有页面中找到的匹配项

${searchSections}
`; } // 生成Google Fonts链接 function generateGoogleFontsLink(config) { const fonts = config.fonts; const googleFonts = []; // 收集需要加载的Google字体 Object.values(fonts).forEach(font => { if (font.source === 'google') { const fontName = font.family.replace(/["']/g, ''); const fontWeight = font.weight || 400; googleFonts.push(`family=${fontName}:wght@${fontWeight}`); } }); return googleFonts.length > 0 ? `` : ''; } // 生成字体CSS变量 function generateFontVariables(config) { const fonts = config.fonts; let css = ':root {\n'; Object.entries(fonts).forEach(([key, font]) => { css += ` --font-${key}: ${font.family};\n`; if (font.weight) { css += ` --font-weight-${key}: ${font.weight};\n`; } }); css += '}'; return css; } // 生成完整的HTML function generateHTML(config) { const googleFontsLink = generateGoogleFontsLink(config); const fontVariables = generateFontVariables(config); const currentYear = new Date().getFullYear(); return ` ${escapeHtml(config.site.title)} ${googleFontsLink}

${escapeHtml(config.profile.title)}

${escapeHtml(config.profile.subtitle)}

${escapeHtml(config.profile.description)}

${generateCategories(config.categories)}
${generatePageContent('projects', config.projects)}
${generatePageContent('articles', config.articles)}
${generatePageContent('friends', config.friends)}
${generateSearchResultsPage(config)}
`; } // 复制静态文件 function copyStaticFiles(config) { // 如果配置了favicon,确保文件存在并复制 if (config.site.favicon) { try { if (fs.existsSync(config.site.favicon)) { fs.copyFileSync(config.site.favicon, path.basename(config.site.favicon)); console.log(`Copied favicon: ${config.site.favicon}`); } else { console.warn(`Warning: Favicon file not found: ${config.site.favicon}`); } } catch (e) { console.error('Error copying favicon:', e); } } } // 主函数 function main() { const config = loadConfig(); const html = generateHTML(config); try { // 生成HTML fs.writeFileSync('index.html', html); console.log('Successfully generated index.html'); // 复制静态文件 copyStaticFiles(config); } catch (e) { console.error('Error in main function:', e); process.exit(1); } } main();