更新模块化配置支持

This commit is contained in:
Zuoling Rong
2025-05-02 20:14:21 +08:00
parent 58227f9d53
commit 33d573698a
11 changed files with 717 additions and 235 deletions

View File

@@ -15,48 +15,199 @@ function escapeHtml(unsafe) {
.replace(/'/g, "'");
}
// 读取配置文件
function loadConfig() {
let config = null;
try {
// 优先尝试读取用户配置
if (fs.existsSync('config.user.yml')) {
const userConfigFile = fs.readFileSync('config.user.yml', 'utf8');
config = yaml.load(userConfigFile);
console.log('Using user configuration from config.user.yml');
}
// 如果没有用户配置,则使用默认配置
else {
const defaultConfigFile = fs.readFileSync('config.yml', 'utf8');
config = yaml.load(defaultConfigFile);
console.log('No user configuration found, using default config.yml');
/**
* 从文件合并配置到主配置对象
* @param {Object} config 主配置对象
* @param {string} filePath 配置文件路径
*/
function mergeConfigFromFile(config, filePath) {
if (fs.existsSync(filePath)) {
try {
const fileContent = fs.readFileSync(filePath, 'utf8');
const fileConfig = yaml.load(fileContent);
// 提取文件名(不含扩展名)作为配置
const configKey = path.basename(filePath, path.extname(filePath));
// 如果是site或navigation文件直接合并到主配置
if (configKey === 'site' || configKey === 'navigation') {
if (!config[configKey]) config[configKey] = {};
deepMerge(config[configKey], fileConfig);
} else {
// 其他配置直接合并到根级别
deepMerge(config, fileConfig);
}
console.log(`Loaded and merged configuration from ${filePath}`);
} catch (e) {
console.error(`Error loading configuration from ${filePath}:`, e);
}
}
}
/**
* 加载页面配置目录中的所有配置文件
* @param {Object} config 主配置对象
* @param {string} dirPath 页面配置目录路径
*/
function loadPageConfigs(config, dirPath) {
if (fs.existsSync(dirPath)) {
const files = fs.readdirSync(dirPath).filter(file =>
file.endsWith('.yml') || file.endsWith('.yaml'));
files.forEach(file => {
try {
const filePath = path.join(dirPath, file);
const fileContent = fs.readFileSync(filePath, 'utf8');
const fileConfig = yaml.load(fileContent);
// 提取文件名(不含扩展名)作为配置键
const configKey = path.basename(file, path.extname(file));
// 将页面配置添加到主配置对象
config[configKey] = fileConfig;
console.log(`Loaded page configuration from ${filePath}`);
} catch (e) {
console.error(`Error loading page configuration from ${path.join(dirPath, file)}:`, e);
}
});
}
}
/**
* 深度合并两个对象
* @param {Object} target 目标对象
* @param {Object} source 源对象
* @returns {Object} 合并后的对象
*/
function deepMerge(target, source) {
if (!source) return target;
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] === 'object' && source[key] !== null) {
// 确保目标对象有这个属性
if (!target[key]) {
if (Array.isArray(source[key])) {
target[key] = [];
} else {
target[key] = {};
}
}
// 递归合并
if (Array.isArray(source[key])) {
// 对于数组,直接替换或添加
target[key] = source[key];
} else {
// 对于对象,递归合并
deepMerge(target[key], source[key]);
}
} else {
// 对于基本类型,直接替换
target[key] = source[key];
}
}
} catch (e) {
console.error('Error loading configuration file:', e);
process.exit(1);
}
// 尝试读取书签配置
return target;
}
// 读取配置文件
function loadConfig() {
// 初始化空配置对象
let config = {
site: {},
navigation: [],
fonts: {},
profile: {},
social: [],
categories: []
};
// 处理配置目录结构,按照优先级从低到高加载
// 4. 最低优先级: config.yml (传统默认配置)
if (fs.existsSync('config.yml')) {
const defaultConfigFile = fs.readFileSync('config.yml', 'utf8');
const defaultConfig = yaml.load(defaultConfigFile);
deepMerge(config, defaultConfig);
console.log('Loaded legacy default config.yml');
}
// 3. 其次优先级: config/_default/ 目录
if (fs.existsSync('config/_default')) {
console.log('Loading modular default configuration from config/_default/');
// 加载基础配置
mergeConfigFromFile(config, 'config/_default/site.yml');
mergeConfigFromFile(config, 'config/_default/navigation.yml');
// 加载页面配置
if (fs.existsSync('config/_default/pages')) {
loadPageConfigs(config, 'config/_default/pages');
}
}
// 2. 次高优先级: config.user.yml (传统用户配置)
if (fs.existsSync('config.user.yml')) {
const userConfigFile = fs.readFileSync('config.user.yml', 'utf8');
const userConfig = yaml.load(userConfigFile);
// 深度合并配置
deepMerge(config, userConfig);
console.log('Merged legacy user configuration from config.user.yml');
}
// 1. 最高优先级: config/user/ 目录
if (fs.existsSync('config/user')) {
console.log('Loading modular user configuration from config/user/ (highest priority)');
// 覆盖基础配置
mergeConfigFromFile(config, 'config/user/site.yml');
mergeConfigFromFile(config, 'config/user/navigation.yml');
// 覆盖页面配置
if (fs.existsSync('config/user/pages')) {
loadPageConfigs(config, 'config/user/pages');
}
}
// 处理书签文件(保持现有功能)
try {
let bookmarksConfig = null;
let bookmarksSource = null;
// 优先尝试读取用户书签配置
if (fs.existsSync('bookmarks.user.yml')) {
// 按照相同的优先级顺序处理书签配置
// 1. 模块化用户书签配置 (最高优先级)
if (fs.existsSync('config/user/pages/bookmarks.yml')) {
const userBookmarksFile = fs.readFileSync('config/user/pages/bookmarks.yml', 'utf8');
bookmarksConfig = yaml.load(userBookmarksFile);
bookmarksSource = 'config/user/pages/bookmarks.yml';
}
// 2. 传统用户书签配置
else if (fs.existsSync('bookmarks.user.yml')) {
const userBookmarksFile = fs.readFileSync('bookmarks.user.yml', 'utf8');
bookmarksConfig = yaml.load(userBookmarksFile);
console.log('Using user bookmarks configuration from bookmarks.user.yml');
bookmarksSource = 'bookmarks.user.yml';
}
// 如果没有用户书签配置,则尝试读取默认书签配置
// 3. 模块化默认书签配置
else if (fs.existsSync('config/_default/pages/bookmarks.yml')) {
const defaultBookmarksFile = fs.readFileSync('config/_default/pages/bookmarks.yml', 'utf8');
bookmarksConfig = yaml.load(defaultBookmarksFile);
bookmarksSource = 'config/_default/pages/bookmarks.yml';
}
// 4. 传统默认书签配置 (最低优先级)
else if (fs.existsSync('bookmarks.yml')) {
const bookmarksFile = fs.readFileSync('bookmarks.yml', 'utf8');
bookmarksConfig = yaml.load(bookmarksFile);
console.log('Using default bookmarks configuration from bookmarks.yml');
bookmarksSource = 'bookmarks.yml';
}
// 添加书签页面配置
if (bookmarksConfig) {
config.bookmarks = bookmarksConfig;
console.log(`Using bookmarks configuration from ${bookmarksSource}`);
// 确保导航中有书签页面
const hasBookmarksNav = config.navigation.some(nav => nav.id === 'bookmarks');