refactor: 移除旧式双文件配置支持

- 简化配置加载逻辑,仅支持模块化配置
- 移除所有处理旧式配置文件的代码
- 创建配置迁移脚本,便于用户从旧版本迁移
This commit is contained in:
Zuoling Rong
2025-05-05 03:30:13 +08:00
parent 297890315b
commit f3da13035f
7 changed files with 334 additions and 573 deletions

View File

@@ -4,12 +4,12 @@ const yaml = require('js-yaml');
// 书签文件夹路径 - 使用相对路径
const BOOKMARKS_DIR = 'bookmarks';
// 输出配置文件路径 - 使用相对路径
const OUTPUT_FILE = 'bookmarks.user.yml';
// 模块化配置目录
const CONFIG_USER_DIR = 'config/user';
// 模块化页面配置目录
const CONFIG_USER_PAGES_DIR = path.join(CONFIG_USER_DIR, 'pages');
// 模块化输出配置文件路径
const MODULAR_OUTPUT_FILE = 'config/user/pages/bookmarks.yml';
// 默认书签配置文件路径 - 使用相对路径
const DEFAULT_BOOKMARKS_FILE = 'bookmarks.yml';
const MODULAR_OUTPUT_FILE = path.join(CONFIG_USER_PAGES_DIR, 'bookmarks.yml');
// 模块化默认书签配置文件路径
const MODULAR_DEFAULT_BOOKMARKS_FILE = 'config/_default/pages/bookmarks.yml';
@@ -197,10 +197,10 @@ function generateBookmarksYaml(bookmarks) {
// 添加注释
const yamlWithComment =
`# 自动生成的书签配置文件 - 用户自定义版本
`# 自动生成的书签配置文件
# 由bookmark-processor.js生成于 ${new Date().toISOString()}
# 若要更新请将新的书签HTML文件放入bookmarks/目录
# 注意此文件会覆盖bookmarks.yml中的同名配置
# 此文件使用模块化配置格式位于config/user/pages/目录下
${yamlString}`;
@@ -211,58 +211,96 @@ ${yamlString}`;
}
}
// 更新现有config.yml中的导航添加书签页面
function updateConfigWithBookmarks() {
// 传统配置文件
const configFile = 'config.yml';
const userConfigFile = 'config.user.yml';
// 更新导航以包含书签页面
function updateNavigationWithBookmarks() {
console.log('Checking navigation configuration for bookmarks page...');
// 模块化配置文件
const modularNavFile = 'config/_default/navigation.yml';
const modularUserNavFile = 'config/user/navigation.yml';
const modularUserNavFile = path.join(CONFIG_USER_DIR, 'navigation.yml');
const modularDefaultNavFile = 'config/_default/navigation.yml';
let navigationUpdated = false;
// 按优先级顺序尝试更新导航配置
// 1. 最高优先级: 模块化用户导航配置
// 1. 首选: 模块化用户导航配置
if (fs.existsSync(modularUserNavFile)) {
navigationUpdated = updateNavigationFile(modularUserNavFile);
if (navigationUpdated) {
console.log(`Updated modular user navigation file: ${modularUserNavFile} (highest priority)`);
console.log(`Updated modular user navigation file: ${modularUserNavFile}`);
}
}
// 2. 次高优先级: 传统用户配置
if (!navigationUpdated && fs.existsSync(userConfigFile)) {
navigationUpdated = updateTraditionalConfig(userConfigFile);
if (navigationUpdated) {
console.log(`Updated legacy user config file: ${userConfigFile}`);
// 2. 其次: 模块化默认导航配置
else if (fs.existsSync(modularDefaultNavFile)) {
// 如果用户导航文件不存在,我们需要先创建它,然后基于默认文件更新
try {
// 读取默认导航文件
const defaultNavContent = fs.readFileSync(modularDefaultNavFile, 'utf8');
const defaultNav = yaml.load(defaultNavContent);
// 确保目录存在
if (!fs.existsSync(CONFIG_USER_DIR)) {
fs.mkdirSync(CONFIG_USER_DIR, { recursive: true });
}
// 写入用户导航文件
fs.writeFileSync(modularUserNavFile, defaultNavContent, 'utf8');
console.log(`Created user navigation file based on default: ${modularUserNavFile}`);
// 更新新创建的文件
navigationUpdated = updateNavigationFile(modularUserNavFile);
if (navigationUpdated) {
console.log(`Updated newly created navigation file: ${modularUserNavFile}`);
}
} catch (error) {
console.error(`Error creating user navigation file:`, error);
}
}
// 3. 次低优先级: 模块化默认导航
if (!navigationUpdated && fs.existsSync(modularNavFile)) {
navigationUpdated = updateNavigationFile(modularNavFile);
if (navigationUpdated) {
console.log(`Updated modular default navigation file: ${modularNavFile}`);
}
}
// 4. 最低优先级: 传统默认配置
if (!navigationUpdated && fs.existsSync(configFile)) {
navigationUpdated = updateTraditionalConfig(configFile);
if (navigationUpdated) {
console.log(`Updated legacy default config file: ${configFile} (lowest priority)`);
// 3. 如果都不存在,创建一个基本的导航文件
else {
try {
// 确保目录存在
if (!fs.existsSync(CONFIG_USER_DIR)) {
fs.mkdirSync(CONFIG_USER_DIR, { recursive: true });
}
// 创建基本导航配置
const basicNav = [
{
name: "首页",
icon: "fas fa-home",
id: "home",
active: true
},
{
name: "书签",
icon: "fas fa-bookmark",
id: "bookmarks",
active: false
}
];
// 写入用户导航文件
fs.writeFileSync(
modularUserNavFile,
yaml.dump(basicNav, { indent: 2, lineWidth: -1, quotingType: '"' }),
'utf8'
);
console.log(`Created basic navigation file: ${modularUserNavFile}`);
navigationUpdated = true;
} catch (error) {
console.error(`Error creating basic navigation file:`, error);
}
}
if (!navigationUpdated) {
console.log('Did not find any configuration file to update with bookmarks navigation');
console.log('Did not update any navigation configuration with bookmarks page');
}
return navigationUpdated;
}
// 更新单个导航配置文件(模块化版本)
// 更新单个导航配置文件
function updateNavigationFile(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf8');
@@ -304,55 +342,9 @@ function updateNavigationFile(filePath) {
}
}
// 更新传统配置文件(整体配置)
function updateTraditionalConfig(filePath) {
try {
const configContent = fs.readFileSync(filePath, 'utf8');
const config = yaml.load(configContent);
// 检查导航中是否已有书签页面
const hasBookmarksNav = config.navigation &&
Array.isArray(config.navigation) &&
config.navigation.some(nav => nav.id === 'bookmarks');
if (!hasBookmarksNav) {
// 确保navigation数组存在
if (!config.navigation) {
config.navigation = [];
}
// 添加书签页面到导航
config.navigation.push({
name: '书签',
icon: 'fas fa-bookmark',
id: 'bookmarks',
active: false
});
// 更新配置文件
const updatedYaml = yaml.dump(config, {
indent: 2,
lineWidth: -1,
quotingType: '"'
});
fs.writeFileSync(filePath, updatedYaml, 'utf8');
return true;
}
return false; // 无需更新
} catch (error) {
console.error(`Error updating config file ${filePath}:`, error);
return false;
}
}
// 主函数
async function main() {
console.log('Starting bookmark processing...');
console.log(`Current working directory: ${process.cwd()}`);
console.log(`Legacy output file will be: ${OUTPUT_FILE} (absolute: ${path.resolve(OUTPUT_FILE)})`);
console.log(`Modular output file will be: ${MODULAR_OUTPUT_FILE} (absolute: ${path.resolve(MODULAR_OUTPUT_FILE)})`);
// 获取最新的书签文件
const bookmarkFile = getLatestBookmarkFile();
@@ -390,58 +382,37 @@ async function main() {
console.log(yaml.split('\n').slice(0, 5).join('\n') + '\n...');
try {
// 确保传统目标目录存在
const outputDir = path.dirname(OUTPUT_FILE);
if (!fs.existsSync(outputDir) && outputDir !== '.') {
console.log(`Creating output directory: ${outputDir}`);
fs.mkdirSync(outputDir, { recursive: true });
// 确保目标目录存在
if (!fs.existsSync(CONFIG_USER_PAGES_DIR)) {
console.log(`Creating output directory structure: ${CONFIG_USER_PAGES_DIR}`);
fs.mkdirSync(CONFIG_USER_PAGES_DIR, { recursive: true });
}
// 确保模块化目标目录存在
const modularOutputDir = path.dirname(MODULAR_OUTPUT_FILE);
if (!fs.existsSync(modularOutputDir)) {
console.log(`Creating modular output directory structure: ${modularOutputDir}`);
fs.mkdirSync(modularOutputDir, { recursive: true });
}
// 保存YAML到传统位置
console.log(`Writing to legacy location: ${OUTPUT_FILE}`);
fs.writeFileSync(OUTPUT_FILE, yaml, 'utf8');
// 保存YAML到模块化位置
console.log(`Writing to modular location: ${MODULAR_OUTPUT_FILE}`);
console.log(`Writing bookmarks configuration to: ${MODULAR_OUTPUT_FILE}`);
fs.writeFileSync(MODULAR_OUTPUT_FILE, yaml, 'utf8');
// 验证文件是否确实被创建
let success = false;
if (fs.existsSync(OUTPUT_FILE)) {
const stats = fs.statSync(OUTPUT_FILE);
console.log(`Successfully saved bookmarks configuration to ${OUTPUT_FILE}`);
console.log(`File size: ${stats.size} bytes`);
success = true;
} else {
console.error(`ERROR: Legacy file was not created: ${OUTPUT_FILE}`);
}
if (fs.existsSync(MODULAR_OUTPUT_FILE)) {
const stats = fs.statSync(MODULAR_OUTPUT_FILE);
console.log(`Successfully saved bookmarks configuration to ${MODULAR_OUTPUT_FILE}`);
console.log(`File size: ${stats.size} bytes`);
success = true;
console.log(`Successfully saved bookmarks configuration (${stats.size} bytes)`);
} else {
console.error(`ERROR: Modular file was not created: ${MODULAR_OUTPUT_FILE}`);
}
if (!success) {
console.error('ERROR: No output files were created successfully');
console.error(`ERROR: File was not created: ${MODULAR_OUTPUT_FILE}`);
process.exit(1);
}
// 更新导航
updateConfigWithBookmarks();
updateNavigationWithBookmarks();
// 处理完成后删除原始HTML文件以防止重复处理
try {
fs.unlinkSync(bookmarkFile);
console.log(`Deleted processed HTML file: ${bookmarkFile}`);
} catch (deleteError) {
console.warn(`Warning: Could not delete processed HTML file: ${deleteError.message}`);
}
} catch (writeError) {
console.error(`ERROR writing files:`, writeError);
console.error(`ERROR writing file:`, writeError);
process.exit(1);
}
} catch (error) {
@@ -450,8 +421,10 @@ async function main() {
}
}
// 执行主函数
main().catch(error => {
console.error('Unhandled error:', error);
process.exit(1);
});
// 启动处理
if (require.main === module) {
main().catch(err => {
console.error('Unhandled error in bookmark processing:', err);
process.exit(1);
});
}

View File

@@ -131,24 +131,17 @@ function loadConfig() {
categories: []
};
// 检查所有可能的配置来源是否存在
// 检查模块化配置来源是否存在
const hasUserModularConfig = fs.existsSync('config/user');
const hasUserLegacyConfig = fs.existsSync('config.user.yml');
const hasDefaultModularConfig = fs.existsSync('config/_default');
const hasDefaultLegacyConfig = fs.existsSync('config.yml');
// 根据优先级顺序选择最高优先级的配置
if (hasUserModularConfig) {
// 1. 最高优先级: config/user/ 目录
console.log('Using modular user configuration from config/user/ (highest priority)');
config = loadModularConfig('config/user');
} else if (hasUserLegacyConfig) {
// 2. 次高优先级: config.user.yml (传统用户配置)
console.log('Using legacy user configuration from config.user.yml');
const userConfigFile = fs.readFileSync('config.user.yml', 'utf8');
config = yaml.load(userConfigFile);
} else if (hasDefaultModularConfig) {
// 3. 其次优先级: config/_default/ 目录
// 2. 其次优先级: config/_default/ 目录
console.log('Using modular default configuration from config/_default/');
// 从模块化默认配置加载
@@ -174,11 +167,6 @@ function loadConfig() {
console.error(`Error loading home.yml: ${e.message}`);
}
}
} else if (hasDefaultLegacyConfig) {
// 4. 最低优先级: config.yml (传统默认配置)
console.log('Using legacy default config.yml');
const defaultConfigFile = fs.readFileSync('config.yml', 'utf8');
config = yaml.load(defaultConfigFile);
} else {
console.log('No configuration found, using default empty config');
}
@@ -191,43 +179,29 @@ function loadConfig() {
config.social = config.social || [];
config.categories = config.categories || [];
// 处理书签文件(保持现有功能,但使用新逻辑)
// 处理书签文件
try {
let bookmarksConfig = null;
let bookmarksSource = null;
// 按照相同的优先级顺序处理书签配置
// 按照优先级顺序处理书签配置
// 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);
bookmarksSource = 'bookmarks.user.yml';
}
// 3. 模块化默认书签配置
// 2. 模块化默认书签配置
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);
bookmarksSource = 'bookmarks.yml';
}
// 添加书签页面配置
if (bookmarksConfig) {
config.bookmarks = bookmarksConfig;
console.log(`Using bookmarks configuration from ${bookmarksSource}`);
// 移除自动添加书签页面到导航的逻辑
}
} catch (e) {
console.error('Error loading bookmarks configuration:', e);

178
src/migrate-config.js Normal file
View File

@@ -0,0 +1,178 @@
/**
* MeNav 配置迁移工具
* 将旧版双文件配置转换为新版模块化配置
*/
const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
// 配置文件路径
const LEGACY_CONFIG_FILE = 'config.yml';
const LEGACY_USER_CONFIG_FILE = 'config.user.yml';
const LEGACY_BOOKMARKS_FILE = 'bookmarks.yml';
const LEGACY_USER_BOOKMARKS_FILE = 'bookmarks.user.yml';
// 模块化配置目录
const CONFIG_USER_DIR = 'config/user';
const CONFIG_USER_PAGES_DIR = path.join(CONFIG_USER_DIR, 'pages');
/**
* 迁移旧式配置文件到模块化格式
*/
function migrateConfiguration() {
console.log('\n======== MeNav 配置迁移工具 ========');
console.log('将旧式双文件配置转换为模块化配置\n');
// 检查是否存在旧式配置文件
const hasUserConfig = fs.existsSync(LEGACY_USER_CONFIG_FILE);
const hasDefaultConfig = fs.existsSync(LEGACY_CONFIG_FILE);
const hasUserBookmarks = fs.existsSync(LEGACY_USER_BOOKMARKS_FILE);
const hasDefaultBookmarks = fs.existsSync(LEGACY_BOOKMARKS_FILE);
if (!hasUserConfig && !hasDefaultConfig && !hasUserBookmarks && !hasDefaultBookmarks) {
console.log('未找到任何旧式配置文件,无需迁移。');
return;
}
// 确保目标目录存在
if (!fs.existsSync(CONFIG_USER_DIR)) {
fs.mkdirSync(CONFIG_USER_DIR, { recursive: true });
}
if (!fs.existsSync(CONFIG_USER_PAGES_DIR)) {
fs.mkdirSync(CONFIG_USER_PAGES_DIR, { recursive: true });
}
// 优先使用用户配置,如果不存在则使用默认配置
const configFile = hasUserConfig ? LEGACY_USER_CONFIG_FILE : hasDefaultConfig ? LEGACY_CONFIG_FILE : null;
// 迁移主配置文件
if (configFile) {
try {
console.log(`迁移配置文件: ${configFile}`);
const configContent = fs.readFileSync(configFile, 'utf8');
const config = yaml.load(configContent);
// 提取站点配置
if (config.site) {
const siteConfig = {
title: config.site.title || '',
description: config.site.description || '',
author: config.site.author || '',
favicon: config.site.favicon || 'favicon.ico'
};
// 添加字体配置
if (config.fonts) {
siteConfig.fonts = config.fonts;
}
// 添加个人资料配置
if (config.profile) {
siteConfig.profile = config.profile;
}
// 添加社交媒体配置
if (config.social && config.social.length > 0) {
siteConfig.social = config.social;
}
// 写入站点配置
const siteYaml = yaml.dump(siteConfig, { indent: 2, lineWidth: -1, quotingType: '"' });
fs.writeFileSync(
path.join(CONFIG_USER_DIR, 'site.yml'),
`# 由migrate-config.js从${configFile}迁移\n# 生成于 ${new Date().toISOString()}\n\n${siteYaml}`,
'utf8'
);
console.log('✓ 已创建站点配置文件: site.yml');
}
// 提取导航配置
if (config.navigation && config.navigation.length > 0) {
const navigationYaml = yaml.dump(config.navigation, { indent: 2, lineWidth: -1, quotingType: '"' });
fs.writeFileSync(
path.join(CONFIG_USER_DIR, 'navigation.yml'),
`# 由migrate-config.js从${configFile}迁移\n# 生成于 ${new Date().toISOString()}\n\n${navigationYaml}`,
'utf8'
);
console.log('✓ 已创建导航配置文件: navigation.yml');
}
// 提取所有页面配置
const pageIds = config.navigation ? config.navigation.map(nav => nav.id) : [];
pageIds.forEach(pageId => {
if (config[pageId]) {
const pageConfig = { ...config[pageId] };
// 特殊处理首页的categories
if (pageId === 'home' && !pageConfig.categories && config.categories) {
pageConfig.categories = config.categories;
}
const pageYaml = yaml.dump(pageConfig, { indent: 2, lineWidth: -1, quotingType: '"' });
fs.writeFileSync(
path.join(CONFIG_USER_PAGES_DIR, `${pageId}.yml`),
`# 由migrate-config.js从${configFile}迁移\n# 生成于 ${new Date().toISOString()}\n\n${pageYaml}`,
'utf8'
);
console.log(`✓ 已创建页面配置文件: ${pageId}.yml`);
}
});
// 如果首页不在pageIds中但存在categories创建一个home.yml
if (!pageIds.includes('home') && config.categories) {
const homeConfig = {
title: '我的导航',
subtitle: '个人收藏网址',
categories: config.categories
};
const homeYaml = yaml.dump(homeConfig, { indent: 2, lineWidth: -1, quotingType: '"' });
fs.writeFileSync(
path.join(CONFIG_USER_PAGES_DIR, 'home.yml'),
`# 由migrate-config.js从${configFile}迁移\n# 生成于 ${new Date().toISOString()}\n\n${homeYaml}`,
'utf8'
);
console.log('✓ 已创建首页配置文件: home.yml');
}
} catch (error) {
console.error(`迁移配置文件${configFile}时出错:`, error);
}
}
// 迁移书签配置文件
const bookmarksFile = hasUserBookmarks ? LEGACY_USER_BOOKMARKS_FILE : hasDefaultBookmarks ? LEGACY_BOOKMARKS_FILE : null;
if (bookmarksFile) {
try {
console.log(`\n迁移书签配置文件: ${bookmarksFile}`);
// 直接复制书签配置文件
fs.copyFileSync(
bookmarksFile,
path.join(CONFIG_USER_PAGES_DIR, 'bookmarks.yml')
);
console.log('✓ 已创建书签配置文件: bookmarks.yml');
} catch (error) {
console.error(`迁移书签配置文件${bookmarksFile}时出错:`, error);
}
}
console.log('\n迁移完成');
console.log('您现在可以删除旧的配置文件:');
if (hasUserConfig) console.log(`- ${LEGACY_USER_CONFIG_FILE}`);
if (hasDefaultConfig) console.log(`- ${LEGACY_CONFIG_FILE}`);
if (hasUserBookmarks) console.log(`- ${LEGACY_USER_BOOKMARKS_FILE}`);
if (hasDefaultBookmarks) console.log(`- ${LEGACY_BOOKMARKS_FILE}`);
console.log('\n新的模块化配置文件位于');
console.log(`- ${CONFIG_USER_DIR}/`);
console.log(`- ${CONFIG_USER_PAGES_DIR}/`);
}
// 如果直接运行该脚本,则执行迁移
if (require.main === module) {
migrateConfiguration();
}
module.exports = { migrateConfiguration };