refactor: 优化重构后的系统并添加文档

This commit is contained in:
Zuoling Rong
2025-05-09 00:08:01 +08:00
parent 9ea6cb1f09
commit 4c3c5d23fa
13 changed files with 960 additions and 659 deletions

View File

@@ -28,7 +28,6 @@ function loadHandlebarsTemplates() {
const layoutPath = path.join(layoutsDir, file);
const layoutContent = fs.readFileSync(layoutPath, 'utf8');
handlebars.registerPartial(layoutName, layoutContent);
console.log(`Registered layout template: ${layoutName}`);
}
});
} else {
@@ -44,23 +43,45 @@ function loadHandlebarsTemplates() {
const componentPath = path.join(componentsDir, file);
const componentContent = fs.readFileSync(componentPath, 'utf8');
handlebars.registerPartial(componentName, componentContent);
console.log(`Registered component template: ${componentName}`);
}
});
} else {
throw new Error('Components directory not found. Cannot proceed without component templates.');
}
// 识别并注册默认布局模板
// 识别并检查默认布局模板是否存在
const defaultLayoutPath = path.join(layoutsDir, 'default.hbs');
if (fs.existsSync(defaultLayoutPath)) {
console.log('Default layout template found and registered.');
return true;
} else {
if (!fs.existsSync(defaultLayoutPath)) {
throw new Error('Default layout template not found. Cannot proceed without default layout.');
}
}
/**
* 获取默认布局模板
* @returns {Object} 包含模板路径和编译的模板函数
*/
function getDefaultLayoutTemplate() {
const defaultLayoutPath = path.join(process.cwd(), 'templates', 'layouts', 'default.hbs');
// 检查默认布局模板是否存在
if (!fs.existsSync(defaultLayoutPath)) {
throw new Error('Default layout template not found. Cannot proceed without default layout.');
}
try {
// 读取布局内容并编译模板
const layoutContent = fs.readFileSync(defaultLayoutPath, 'utf8');
const layoutTemplate = handlebars.compile(layoutContent);
return {
path: defaultLayoutPath,
template: layoutTemplate
};
} catch (error) {
throw new Error(`Error loading default layout template: ${error.message}`);
}
}
// 渲染Handlebars模板函数
function renderTemplate(templateName, data, useLayout = true) {
const templatePath = path.join(process.cwd(), 'templates', 'pages', `${templateName}.hbs`);
@@ -82,23 +103,16 @@ function renderTemplate(templateName, data, useLayout = true) {
return pageContent;
}
// 使用布局模板
const defaultLayoutPath = path.join(process.cwd(), 'templates', 'layouts', 'default.hbs');
if (!fs.existsSync(defaultLayoutPath)) {
throw new Error('Default layout template not found. Cannot proceed without layout.');
}
try {
// 使用辅助函数获取默认布局模板
const { template: layoutTemplate } = getDefaultLayoutTemplate();
// 准备布局数据,包含页面内容
const layoutData = {
...data,
body: pageContent
};
// 加载默认布局模板
const layoutContent = fs.readFileSync(defaultLayoutPath, 'utf8');
const layoutTemplate = handlebars.compile(layoutContent);
// 渲染完整页面
return layoutTemplate(layoutData);
} catch (layoutError) {
@@ -123,23 +137,31 @@ function escapeHtml(unsafe) {
}
/**
* 加载单个配置文件
* 统一处理配置文件加载错误
* @param {string} filePath 配置文件路径
* @param {Error} error 错误对象
*/
function handleConfigLoadError(filePath, error) {
console.error(`Error loading configuration from ${filePath}:`, error);
}
/**
* 安全地加载YAML配置文件
* @param {string} filePath 配置文件路径
* @returns {Object|null} 配置对象如果文件不存在或加载失败则返回null
*/
function loadSingleConfig(filePath) {
if (fs.existsSync(filePath)) {
try {
const fileContent = fs.readFileSync(filePath, 'utf8');
const fileConfig = yaml.load(fileContent);
console.log(`Loaded configuration from ${filePath}`);
return fileConfig;
} catch (e) {
console.error(`Error loading configuration from ${filePath}:`, e);
return null;
}
}
function safeLoadYamlConfig(filePath) {
if (!fs.existsSync(filePath)) {
return null;
}
try {
const fileContent = fs.readFileSync(filePath, 'utf8');
return yaml.load(fileContent);
} catch (error) {
handleConfigLoadError(filePath, error);
return null;
}
}
/**
@@ -163,34 +185,22 @@ function loadModularConfig(dirPath) {
// 加载基础配置
const siteConfigPath = path.join(dirPath, 'site.yml');
if (fs.existsSync(siteConfigPath)) {
try {
const fileContent = fs.readFileSync(siteConfigPath, 'utf8');
const siteConfig = yaml.load(fileContent);
// 将site.yml中的内容分配到正确的配置字段
config.site = siteConfig;
// 提取特殊字段到顶层配置
if (siteConfig.fonts) config.fonts = siteConfig.fonts;
if (siteConfig.profile) config.profile = siteConfig.profile;
if (siteConfig.social) config.social = siteConfig.social;
console.log(`Loaded site configuration from ${siteConfigPath}`);
} catch (e) {
console.error(`Error loading site configuration from ${siteConfigPath}:`, e);
}
const siteConfig = safeLoadYamlConfig(siteConfigPath);
if (siteConfig) {
// 将site.yml中的内容分配到正确的配置字段
config.site = siteConfig;
// 提取特殊字段到顶层配置
if (siteConfig.fonts) config.fonts = siteConfig.fonts;
if (siteConfig.profile) config.profile = siteConfig.profile;
if (siteConfig.social) config.social = siteConfig.social;
}
// 加载导航配置
const navConfigPath = path.join(dirPath, 'navigation.yml');
if (fs.existsSync(navConfigPath)) {
try {
const fileContent = fs.readFileSync(navConfigPath, 'utf8');
config.navigation = yaml.load(fileContent);
console.log(`Loaded navigation configuration from ${navConfigPath}`);
} catch (e) {
console.error(`Error loading navigation configuration from ${navConfigPath}:`, e);
}
const navConfig = safeLoadYamlConfig(navConfigPath);
if (navConfig) {
config.navigation = navConfig;
}
// 加载页面配置
@@ -200,11 +210,10 @@ function loadModularConfig(dirPath) {
file.endsWith('.yml') || file.endsWith('.yaml'));
files.forEach(file => {
try {
const filePath = path.join(pagesPath, file);
const fileContent = fs.readFileSync(filePath, 'utf8');
const fileConfig = yaml.load(fileContent);
const filePath = path.join(pagesPath, file);
const fileConfig = safeLoadYamlConfig(filePath);
if (fileConfig) {
// 提取文件名(不含扩展名)作为配置键
const configKey = path.basename(file, path.extname(file));
@@ -215,10 +224,6 @@ function loadModularConfig(dirPath) {
// 将页面配置添加到主配置对象
config[configKey] = fileConfig;
console.log(`Loaded page configuration from ${filePath}`);
} catch (e) {
console.error(`Error loading page configuration from ${path.join(pagesPath, file)}:`, e);
}
});
}
@@ -254,15 +259,6 @@ function ensureConfigDefaults(config) {
modeToggle: true
};
// 确保主题颜色设置存在
if (!result.site.theme) {
result.site.theme = {
primary: '#4a89dc',
background: '#f5f7fa',
modeToggle: true
};
}
// 用户资料默认值
result.profile = result.profile || {};
result.profile.title = result.profile.title || '欢迎使用';
@@ -300,42 +296,51 @@ function validateConfig(config) {
return false;
}
// 检查必要的顶级属性
if (!config.site) {
console.warn('配置警告: 缺少site配置节点');
}
// 导航配置检查
if (!Array.isArray(config.navigation)) {
console.warn('配置警告: navigation不是数组类型');
}
// 验证分类和站点结构
if (!Array.isArray(config.categories)) {
console.warn('配置警告: categories不是数组类型');
} else {
// 检查分类结构
config.categories.forEach((category, index) => {
if (!category.name) {
console.warn(`配置警告: 第${index+1}个分类没有name属性`);
}
if (!Array.isArray(category.sites)) {
console.warn(`配置警告: 分类 "${category.name || `#${index+1}`}" 的sites不是数组类型`);
} else {
// 检查站点URL
category.sites.forEach((site, siteIndex) => {
if (!site.url) {
console.warn(`配置警告: 分类 "${category.name || `#${index+1}`}" 中第${siteIndex+1}个站点缺少url属性`);
}
});
}
});
}
// 所有其他验证被移除,因为它们只是检查但没有实际操作
// 配置默认值和数据修复已经在ensureConfigDefaults函数中处理
return true;
}
/**
* 获取导航项的子菜单数据
* @param {Object} navItem 导航项对象
* @param {Object} config 配置对象
* @returns {Array|null} 子菜单数据数组或null
*/
function getSubmenuForNavItem(navItem, config) {
if (!navItem || !navItem.id || !config) {
return null;
}
// 首页页面添加子菜单(分类)
if (navItem.id === 'home' && Array.isArray(config.categories)) {
return config.categories;
}
// 书签页面添加子菜单(分类)
else if (navItem.id === 'bookmarks' && config.bookmarks && Array.isArray(config.bookmarks.categories)) {
return config.bookmarks.categories;
}
// 项目页面添加子菜单
else if (navItem.id === 'projects' && config.projects && Array.isArray(config.projects.categories)) {
return config.projects.categories;
}
// 文章页面添加子菜单
else if (navItem.id === 'articles' && config.articles && Array.isArray(config.articles.categories)) {
return config.articles.categories;
}
// 友链页面添加子菜单
else if (navItem.id === 'friends' && config.friends && Array.isArray(config.friends.categories)) {
return config.friends.categories;
}
// 通用处理:任意自定义页面的子菜单生成
else if (config[navItem.id] && config[navItem.id].categories && Array.isArray(config[navItem.id].categories)) {
return config[navItem.id].categories;
}
return null;
}
/**
* 准备渲染数据,添加模板所需的特殊属性
* @param {Object} config 配置对象
@@ -355,7 +360,7 @@ function prepareRenderData(config) {
// 确保navigation是数组
if (!Array.isArray(renderData.navigation)) {
renderData.navigation = [];
console.warn('Warning: navigation is not an array. Using empty array instead.');
// 移除警告日志,数据处理逻辑保留
}
// 添加导航项的活动状态标记和子菜单
@@ -368,30 +373,10 @@ function prepareRenderData(config) {
active: index === 0 // 兼容原有逻辑
};
// 为导航项添加子菜单
// 首页页面添加子菜单(分类)
if (item.id === 'home' && Array.isArray(renderData.categories)) {
navItem.submenu = renderData.categories;
}
// 书签页面添加子菜单(分类)
else if (item.id === 'bookmarks' && renderData.bookmarks && Array.isArray(renderData.bookmarks.categories)) {
navItem.submenu = renderData.bookmarks.categories;
}
// 项目页面添加子菜单
else if (item.id === 'projects' && renderData.projects && Array.isArray(renderData.projects.categories)) {
navItem.submenu = renderData.projects.categories;
}
// 文章页面添加子菜单
else if (item.id === 'articles' && renderData.articles && Array.isArray(renderData.articles.categories)) {
navItem.submenu = renderData.articles.categories;
}
// 友链页面添加子菜单
else if (item.id === 'friends' && renderData.friends && Array.isArray(renderData.friends.categories)) {
navItem.submenu = renderData.friends.categories;
}
// 通用处理:任意自定义页面的子菜单生成
else if (renderData[item.id] && renderData[item.id].categories && Array.isArray(renderData[item.id].categories)) {
navItem.submenu = renderData[item.id].categories;
// 使用辅助函数获取子菜单
const submenu = getSubmenuForNavItem(navItem, renderData);
if (submenu) {
navItem.submenu = submenu;
}
return navItem;
@@ -428,22 +413,18 @@ function loadConfig() {
// 根据优先级顺序选择最高优先级的配置
if (hasUserModularConfig) {
// 1. 最高优先级: config/user/ 目录
console.log('Using modular user configuration from config/user/ (highest priority)');
config = loadModularConfig('config/user');
} else if (hasDefaultModularConfig) {
// 2. 次高优先级: config/_default/ 目录
console.log('Using modular default configuration from config/_default/');
config = loadModularConfig('config/_default');
} else {
// 3. 最低优先级: 旧版单文件配置 (config.yml or config.yaml)
console.log('Using legacy single-file configuration');
const legacyConfigPath = fs.existsSync('config.yml') ? 'config.yml' : 'config.yaml';
if (fs.existsSync(legacyConfigPath)) {
try {
const fileContent = fs.readFileSync(legacyConfigPath, 'utf8');
config = yaml.load(fileContent);
console.log(`Loaded legacy configuration from ${legacyConfigPath}`);
} catch (e) {
console.error(`Error loading configuration from ${legacyConfigPath}:`, e);
}
@@ -457,7 +438,7 @@ function loadConfig() {
config = ensureConfigDefaults(config);
if (!validateConfig(config)) {
console.warn('Configuration validation warnings found. Continuing with defaults.');
// 移除警告日志,保留函数调用
}
// 准备渲染数据
@@ -471,72 +452,15 @@ function generateNavigation(navigation, config) {
return navigation.map(nav => {
// 根据页面ID获取对应的子菜单项分类
let submenuItems = '';
// 首页页面添加子菜单(分类)
if (nav.id === 'home' && Array.isArray(config.categories)) {
// 使用辅助函数获取子菜单数据
const submenu = getSubmenuForNavItem(nav, config);
// 如果存在子菜单生成HTML
if (submenu && Array.isArray(submenu)) {
submenuItems = `
<div class="submenu">
${config.categories.map(category => `
<a href="#${category.name}" class="submenu-item" data-page="${nav.id}" data-category="${category.name}">
<i class="${escapeHtml(category.icon)}"></i>
<span>${escapeHtml(category.name)}</span>
</a>
`).join('')}
</div>`;
}
// 书签页面添加子菜单(分类)
else if (nav.id === 'bookmarks' && config.bookmarks && Array.isArray(config.bookmarks.categories)) {
submenuItems = `
<div class="submenu">
${config.bookmarks.categories.map(category => `
<a href="#${category.name}" class="submenu-item" data-page="${nav.id}" data-category="${category.name}">
<i class="${escapeHtml(category.icon)}"></i>
<span>${escapeHtml(category.name)}</span>
</a>
`).join('')}
</div>`;
}
// 项目页面添加子菜单
else if (nav.id === 'projects' && config.projects && Array.isArray(config.projects.categories)) {
submenuItems = `
<div class="submenu">
${config.projects.categories.map(category => `
<a href="#${category.name}" class="submenu-item" data-page="${nav.id}" data-category="${category.name}">
<i class="${escapeHtml(category.icon)}"></i>
<span>${escapeHtml(category.name)}</span>
</a>
`).join('')}
</div>`;
}
// 文章页面添加子菜单
else if (nav.id === 'articles' && config.articles && Array.isArray(config.articles.categories)) {
submenuItems = `
<div class="submenu">
${config.articles.categories.map(category => `
<a href="#${category.name}" class="submenu-item" data-page="${nav.id}" data-category="${category.name}">
<i class="${escapeHtml(category.icon)}"></i>
<span>${escapeHtml(category.name)}</span>
</a>
`).join('')}
</div>`;
}
// 友链页面添加子菜单
else if (nav.id === 'friends' && config.friends && Array.isArray(config.friends.categories)) {
submenuItems = `
<div class="submenu">
${config.friends.categories.map(category => `
<a href="#${category.name}" class="submenu-item" data-page="${nav.id}" data-category="${category.name}">
<i class="${escapeHtml(category.icon)}"></i>
<span>${escapeHtml(category.name)}</span>
</a>
`).join('')}
</div>`;
}
// 通用处理:任意自定义页面的子菜单生成
else if (config[nav.id] && config[nav.id].categories && Array.isArray(config[nav.id].categories)) {
submenuItems = `
<div class="submenu">
${config[nav.id].categories.map(category => `
${submenu.map(category => `
<a href="#${category.name}" class="submenu-item" data-page="${nav.id}" data-category="${category.name}">
<i class="${escapeHtml(category.icon)}"></i>
<span>${escapeHtml(category.name)}</span>
@@ -623,22 +547,9 @@ function generateSocialLinks(social) {
</a>`).join('\n');
}
// 生成欢迎区域和首页内容
function generateHomeContent(config) {
const profile = config.profile || {};
return `
<div class="welcome-section">
<h2>${escapeHtml(profile.title || '欢迎使用')}</h2>
<h3>${escapeHtml(profile.subtitle || '个人导航站')}</h3>
<p class="subtitle">${escapeHtml(profile.description || '快速访问您的常用网站')}</p>
</div>
${generateCategories(config.categories)}`;
}
// 生成页面内容
// 生成页面内容(包括首页和其他页面)
function generatePageContent(pageId, data) {
// 确保数据对象存在且有必要的字段
// 确保数据对象存在
if (!data) {
console.error(`Missing data for page: ${pageId}`);
return `
@@ -648,13 +559,23 @@ function generatePageContent(pageId, data) {
</div>`;
}
// 设置默认值
const title = data.title || `${pageId} 页面`;
const subtitle = data.subtitle || '';
const categories = data.categories || [];
// 如果是书签页面使用bookmarks配置
if (pageId === 'bookmarks') {
// 首页使用profile数据其他页面使用自身数据
if (pageId === 'home') {
const profile = data.profile || {};
return `
<div class="welcome-section">
<h2>${escapeHtml(profile.title || '欢迎使用')}</h2>
<h3>${escapeHtml(profile.subtitle || '个人导航站')}</h3>
<p class="subtitle">${escapeHtml(profile.description || '快速访问您的常用网站')}</p>
</div>
${generateCategories(data.categories)}`;
} else {
// 其他页面使用通用结构
const title = data.title || `${pageId} 页面`;
const subtitle = data.subtitle || '';
const categories = data.categories || [];
return `
<div class="welcome-section">
<h2>${escapeHtml(title)}</h2>
@@ -662,13 +583,6 @@ function generatePageContent(pageId, data) {
</div>
${generateCategories(categories)}`;
}
return `
<div class="welcome-section">
<h2>${escapeHtml(title)}</h2>
<p class="subtitle">${escapeHtml(subtitle)}</p>
</div>
${generateCategories(categories)}`;
}
// 生成搜索结果页面
@@ -762,30 +676,10 @@ function renderPage(pageId, config) {
active: nav.id === pageId // 兼容原有逻辑
};
// 确保子菜单信息正确
// 首页页面添加子菜单(分类)
if (nav.id === 'home' && Array.isArray(config.categories)) {
navItem.submenu = config.categories;
}
// 书签页面添加子菜单(分类)
else if (nav.id === 'bookmarks' && config.bookmarks && Array.isArray(config.bookmarks.categories)) {
navItem.submenu = config.bookmarks.categories;
}
// 项目页面添加子菜单
else if (nav.id === 'projects' && config.projects && Array.isArray(config.projects.categories)) {
navItem.submenu = config.projects.categories;
}
// 文章页面添加子菜单
else if (nav.id === 'articles' && config.articles && Array.isArray(config.articles.categories)) {
navItem.submenu = config.articles.categories;
}
// 友链页面添加子菜单
else if (nav.id === 'friends' && config.friends && Array.isArray(config.friends.categories)) {
navItem.submenu = config.friends.categories;
}
// 通用处理:任意自定义页面的子菜单生成
else if (config[nav.id] && config[nav.id].categories && Array.isArray(config[nav.id].categories)) {
navItem.submenu = config[nav.id].categories;
// 使用辅助函数获取子菜单
const submenu = getSubmenuForNavItem(navItem, config);
if (submenu) {
navItem.submenu = submenu;
}
return navItem;
@@ -813,10 +707,6 @@ function renderPage(pageId, config) {
* @returns {Object} 包含所有页面HTML的对象
*/
function generateAllPagesHTML(config) {
// 初始化模板系统这已经在main中执行过但为了确保我们在这里再次调用
loadHandlebarsTemplates();
console.log('Handlebars templates available. Using template rendering.');
// 页面内容集合
const pages = {};
@@ -859,17 +749,10 @@ function generateHTML(config) {
const navigationData = config.navigation.map(nav => {
const navItem = { ...nav };
// 根据页面ID获取对应的子菜单项分类
if (nav.id === 'home' && Array.isArray(config.categories)) {
navItem.submenu = config.categories;
}
// 书签页面添加子菜单(分类)
else if (nav.id === 'bookmarks' && config.bookmarks && Array.isArray(config.bookmarks.categories)) {
navItem.submenu = config.bookmarks.categories;
}
// 其他页面添加子菜单
else if (config[nav.id] && config[nav.id].categories && Array.isArray(config[nav.id].categories)) {
navItem.submenu = config[nav.id].categories;
// 使用辅助函数获取子菜单
const submenu = getSubmenuForNavItem(navItem, config);
if (submenu) {
navItem.submenu = submenu;
}
return navItem;
@@ -898,15 +781,8 @@ function generateHTML(config) {
};
try {
// 使用Handlebars模板
const defaultLayoutPath = path.join(process.cwd(), 'templates', 'layouts', 'default.hbs');
if (!fs.existsSync(defaultLayoutPath)) {
throw new Error('Default layout template not found.');
}
// 加载默认布局模板
const layoutContent = fs.readFileSync(defaultLayoutPath, 'utf8');
const layoutTemplate = handlebars.compile(layoutContent);
// 使用辅助函数获取默认布局模板
const { template: layoutTemplate } = getDefaultLayoutTemplate();
// 渲染模板
return layoutTemplate(layoutData);
@@ -926,7 +802,6 @@ function copyStaticFiles(config) {
// 复制CSS文件
try {
fs.copyFileSync('assets/style.css', 'dist/style.css');
console.log('Copied style.css to dist/');
} catch (e) {
console.error('Error copying style.css:', e);
}
@@ -934,7 +809,6 @@ function copyStaticFiles(config) {
// 复制JavaScript文件
try {
fs.copyFileSync('src/script.js', 'dist/script.js');
console.log('Copied script.js to dist/');
} catch (e) {
console.error('Error copying script.js:', e);
}
@@ -944,10 +818,8 @@ function copyStaticFiles(config) {
try {
if (fs.existsSync(`assets/${config.site.favicon}`)) {
fs.copyFileSync(`assets/${config.site.favicon}`, `dist/${path.basename(config.site.favicon)}`);
console.log(`Copied favicon: ${config.site.favicon} to dist/`);
} else if (fs.existsSync(config.site.favicon)) {
fs.copyFileSync(config.site.favicon, `dist/${path.basename(config.site.favicon)}`);
console.log(`Copied favicon: ${config.site.favicon} to dist/`);
} else {
console.warn(`Warning: Favicon file not found: ${config.site.favicon}`);
}
@@ -957,98 +829,10 @@ function copyStaticFiles(config) {
}
}
// 处理模板文件,替换占位符
function processTemplate(template, config) {
const currentYear = new Date().getFullYear();
const googleFontsLink = generateGoogleFontsLink(config);
const fontVariables = generateFontVariables(config);
// 使用Handlebars渲染
const defaultLayoutPath = path.join(process.cwd(), 'templates', 'layouts', 'default.hbs');
if (!fs.existsSync(defaultLayoutPath)) {
throw new Error('Default layout template not found. Cannot proceed.');
}
// 确保config.navigation是数组
if (!Array.isArray(config.navigation)) {
throw new Error('config.navigation is not an array in processTemplate.');
}
// 准备导航数据添加submenu字段
const navigationData = config.navigation.map(nav => {
const navItem = { ...nav };
// 根据页面ID获取对应的子菜单项分类
if (nav.id === 'home' && Array.isArray(config.categories)) {
navItem.submenu = config.categories;
}
// 书签页面添加子菜单(分类)
else if (nav.id === 'bookmarks' && config.bookmarks && Array.isArray(config.bookmarks.categories)) {
navItem.submenu = config.bookmarks.categories;
}
// 项目页面添加子菜单
else if (nav.id === 'projects' && config.projects && Array.isArray(config.projects.categories)) {
navItem.submenu = config.projects.categories;
}
// 文章页面添加子菜单
else if (nav.id === 'articles' && config.articles && Array.isArray(config.articles.categories)) {
navItem.submenu = config.articles.categories;
}
// 友链页面添加子菜单
else if (nav.id === 'friends' && config.friends && Array.isArray(config.friends.categories)) {
navItem.submenu = config.friends.categories;
}
// 通用处理:任意自定义页面的子菜单生成
else if (config[nav.id] && config[nav.id].categories && Array.isArray(config[nav.id].categories)) {
navItem.submenu = config[nav.id].categories;
}
return navItem;
});
// 准备模板数据
const templateData = {
site: config.site || {},
navigation: generateNavigation(config.navigation, config),
navigationData: navigationData, // 带有子菜单的导航数据
social: Array.isArray(config.social) ? config.social : [], // 社交数据
categories: Array.isArray(config.categories) ? config.categories : [],
profile: config.profile || {},
googleFontsLink: googleFontsLink,
fontVariables: fontVariables,
currentYear: currentYear,
socialLinks: generateSocialLinks(config.social), // 使用生成的HTML
searchResults: generateSearchResultsPage(config),
body: config.content || '' // 支持布局模板用
};
// 加载默认布局模板
const layoutContent = fs.readFileSync(defaultLayoutPath, 'utf8');
const layoutTemplate = handlebars.compile(layoutContent);
// 渲染模板
return layoutTemplate(templateData);
}
// 调试函数
function debugConfig(config) {
console.log('==== DEBUG INFO ====');
console.log('Navigation items:', config.navigation.map(nav => nav.id));
console.log('Has bookmarks config:', !!config.bookmarks);
if (config.bookmarks) {
console.log('Bookmarks title:', config.bookmarks.title);
console.log('Bookmarks categories:', config.bookmarks.categories.length);
}
console.log('==================');
}
// 主函数
function main() {
const config = loadConfig();
// 输出调试信息
debugConfig(config);
try {
// 确保dist目录存在
if (!fs.existsSync('dist')) {
@@ -1058,15 +842,11 @@ function main() {
// 初始化Handlebars模板系统
loadHandlebarsTemplates();
console.log('Handlebars templates are initialized.');
// 使用generateHTML函数生成完整的HTML
const htmlContent = generateHTML(config);
console.log('Successfully rendered all pages using Handlebars templates.');
// 生成HTML
fs.writeFileSync('dist/index.html', htmlContent);
console.log('Successfully generated dist/index.html');
// 复制静态文件
copyStaticFiles(config);