const fs = require('fs'); const path = require('path'); // 读取模板 const templatePath = path.join(__dirname, 'template.html'); const template = fs.readFileSync(templatePath, 'utf-8'); // 读取章节索引 const indexPath = path.join(__dirname, 'data/chapters-index.json'); const indexData = JSON.parse(fs.readFileSync(indexPath, 'utf-8')); const chaptersIndex = indexData.chapters; // 生成侧边栏章节列表 function generateSidebarChapters(currentId, chapters) { const start = Math.max(1, currentId - 30); const end = Math.min(chapters.length, currentId + 30); let html = ''; for (let i = start; i <= end; i++) { const chapter = chapters.find(c => c.id === i); if (chapter) { const isCurrent = i === currentId ? 'current' : ''; html += `第${i}章:${chapter.title}\n`; } } return html; } // 处理章节内容(转换JSON格式为HTML段落) function processContent(content) { // 分割成段落 const paragraphs = content.split('\n').filter(p => p.trim()); let html = ''; for (const para of paragraphs) { const trimmed = para.trim(); if (trimmed.startsWith('---')) { // 分隔线转为特殊标记 html += `
···
\n`; } else if (trimmed.startsWith('(') && trimmed.endsWith(')')) { // 结尾标记 html += `${trimmed}
\n`; } else { html += `${trimmed}
\n`; } } return html; } // 生成HTML页面 function generateChapterHtml(chapter, chapters) { const prevChapter = chapter.id > 1 ? `chapter-${chapter.id - 1}.html` : '#'; const nextChapter = chapter.id < chapters.length ? `chapter-${chapter.id + 1}.html` : '#'; const prevDisabled = chapter.id <= 1 ? 'disabled' : ''; const nextDisabled = chapter.id >= chapters.length ? 'disabled' : ''; let html = template; html = html.replace('{{CHAPTER_ID}}', chapter.id); html = html.replace('{{CHAPTER_NUMBER}}', `Chapter ${chapter.id}`); html = html.replace('{{CHAPTER_TITLE}}', chapter.title); html = html.replace('{{CHAPTER_CONTENT}}', processContent(chapter.content)); html = html.replace('{{PREV_CHAPTER}}', prevChapter); html = html.replace('{{NEXT_CHAPTER}}', nextChapter); html = html.replace('{{PREV_DISABLED}}', prevDisabled); html = html.replace('{{NEXT_DISABLED}}', nextDisabled); html = html.replace('{{SIDEBAR_CHAPTERS}}', generateSidebarChapters(chapter.id, chapters)); return html; } // 主函数 function main() { const chaptersDir = path.join(__dirname, 'chapters'); const dataDir = path.join(__dirname, 'data'); // 确保目录存在 if (!fs.existsSync(chaptersDir)) { fs.mkdirSync(chaptersDir, { recursive: true }); } let generated = 0; let skipped = 0; for (const chapterMeta of chaptersIndex) { const outputPath = path.join(chaptersDir, `chapter-${chapterMeta.id}.html`); const jsonPath = path.join(dataDir, `chapter-${chapterMeta.id}.json`); // 检查JSON文件是否存在 if (!fs.existsSync(jsonPath)) { console.log(`⏭️ 跳过: chapter-${chapterMeta.id}.html (JSON不存在)`); skipped++; continue; } try { // 读取完整章节内容 const jsonData = JSON.parse(fs.readFileSync(jsonPath, 'utf-8')); const chapter = { id: chapterMeta.id, title: jsonData.title || chapterMeta.title, content: jsonData.content || '' }; const html = generateChapterHtml(chapter, chaptersIndex); fs.writeFileSync(outputPath, html, 'utf-8'); generated++; console.log(`✅ 生成: chapter-${chapter.id}.html (${chapter.title})`); } catch (err) { console.error(`❌ 错误: chapter-${chapterMeta.id}.html - ${err.message}`); skipped++; } } console.log(`\n📊 统计: 生成 ${generated} 个文件, 跳过 ${skipped} 个`); } main();