119 lines
4.3 KiB
JavaScript
119 lines
4.3 KiB
JavaScript
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 += `<a href="chapter-${i}.html" class="sidebar-chapter ${isCurrent}">第${i}章:${chapter.title}</a>\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 += `<p style="text-align: center; color: var(--text-secondary); text-indent: 0;">···</p>\n`;
|
||
} else if (trimmed.startsWith('(') && trimmed.endsWith(')')) {
|
||
// 结尾标记
|
||
html += `<p style="text-align: center; color: var(--text-secondary); text-indent: 0; margin-top: 2em;">${trimmed}</p>\n`;
|
||
} else {
|
||
html += `<p>${trimmed}</p>\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(); |