更新书签处理逻辑,生成用户自定义的 bookmarks.user.yml 配置文件

This commit is contained in:
Zuoling Rong
2025-05-02 02:25:25 +08:00
parent 9a043ec82f
commit 89946cb5c4
5 changed files with 155 additions and 67 deletions

View File

@@ -53,21 +53,51 @@ jobs:
- name: Process bookmark file
if: steps.check_bookmark_files.outputs.found == 'true'
run: node src/bookmark-processor.js
run: |
echo "Processing bookmark files..."
node src/bookmark-processor.js
- name: Debug directory contents
if: steps.check_bookmark_files.outputs.found == 'true'
run: |
echo "Current directory contents:"
ls -la
echo "Does bookmarks.user.yml exist?"
if [ -f bookmarks.user.yml ]; then
echo "YES - bookmarks.user.yml exists"
cat bookmarks.user.yml | head -n 10
else
echo "NO - bookmarks.user.yml does not exist"
fi
- name: Commit bookmarks.yml changes
- name: Commit bookmarks.user.yml changes
if: steps.check_bookmark_files.outputs.found == 'true'
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action (Bookmarks)"
# 检查 bookmarks.yml 是否真的被修改了
if ! git diff --quiet bookmarks.yml; then
echo "bookmarks.yml changed, committing..."
git add bookmarks.yml
git commit -m "Update bookmarks.yml from imported bookmarks"
# 不需要push因为构建步骤会使用当前工作区的内容
# Check if the file exists
if [ -f bookmarks.user.yml ]; then
# Check if file is already tracked by git
if git ls-files --error-unmatch bookmarks.user.yml 2>/dev/null; then
echo "bookmarks.user.yml exists and is tracked by git"
# Check if it has changes
if ! git diff --quiet bookmarks.user.yml; then
echo "bookmarks.user.yml has changes, committing..."
git add bookmarks.user.yml
git commit -m "Update bookmarks.user.yml from imported bookmarks"
else
echo "No changes to bookmarks.user.yml"
fi
else
echo "bookmarks.user.yml exists but is not tracked by git (new file)"
git add bookmarks.user.yml
git commit -m "Add bookmarks.user.yml from imported bookmarks"
fi
else
echo "No changes to bookmarks.yml"
echo "ERROR: bookmarks.user.yml does not exist! Bookmark processing may have failed."
echo "Current directory contents:"
ls -la
fi
- name: Clean up processed bookmark files
@@ -97,6 +127,20 @@ jobs:
# 使用 GITHUB_TOKEN 推送
if: steps.check_bookmark_files.outputs.found == 'true'
run: |
echo "Checking git status before pushing..."
git status
echo "Checking bookmarks.user.yml existence before pushing..."
if [ -f bookmarks.user.yml ]; then
echo "bookmarks.user.yml exists with content:"
ls -la bookmarks.user.yml
echo "First 5 lines:"
head -n 5 bookmarks.user.yml
else
echo "WARNING: bookmarks.user.yml does not exist before pushing!"
fi
echo "Pushing changes to repository..."
git push "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" HEAD:${{ github.ref_name }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -206,14 +206,15 @@ npm run dev
- 系统会扫描 `bookmarks` 目录查找最新的HTML书签文件
- 解析书签文件中的链接和文件夹结构
- 自动为书签分配适当的图标
- 生成 `bookmarks.yml` 配置文件
- 生成 `bookmarks.user.yml` 配置文件(而不是直接修改 `bookmarks.yml`
- 处理完成后会自动清空 `bookmarks` 目录(防止重复处理)
- 重新构建并部署网站
4. **注意事项**
- 每次只处理一个书签文件,如有多个文件,系统会选择最新的那个
- 书签导入是构建时的一次性操作,不会在浏览器中保存或同步您的书签
- 如果想要更新书签,可以直接编辑 `bookmarks.yml`,或重新导出书签文件并重新导入
- 如果想要更新书签,可以直接编辑 `bookmarks.user.yml`,或重新导出书签文件并重新导入
- 系统会优先使用 `bookmarks.user.yml`,如果同时存在 `bookmarks.yml`,它们的内容会被合并(用户配置优先)
### 自动化工作流程详解
@@ -226,7 +227,7 @@ MeNav使用单一的GitHub Actions工作流处理书签导入与网站部署
2. **书签处理步骤**:
- 自动检测 `bookmarks` 目录中的HTML文件
- 使用 `bookmark-processor.js` 脚本处理书签文件
- 生成/更新 `bookmarks.yml` 配置文件
- 生成/更新 `bookmarks.user.yml` 配置文件
- 提交更改(如有)并保存至仓库
- 自动清理已处理的HTML书签文件
@@ -241,10 +242,10 @@ MeNav使用单一的GitHub Actions工作流处理书签导入与网站部署
### 书签配置自定义
处理后生成的 `bookmarks.yml` 文件可以手动编辑以进一步自定义:
处理后生成的 `bookmarks.user.yml` 文件可以手动编辑以进一步自定义:
```yaml
# 自动生成的书签配置示例
# 自动生成的书签配置示例(用户自定义版本)
title: 我的书签
subtitle: 从浏览器导入的书签收藏
categories:
@@ -265,7 +266,10 @@ categories:
- 重新组织书签分类结构
- 添加或删除特定书签
**提示**: 尽管自动处理会清理原始HTML文件但修改后的 `bookmarks.yml` 会被保留,您可以随时手动编辑它来更新书签内容。
**提示**:
- 尽管自动处理会清理原始HTML文件但修改后的 `bookmarks.user.yml` 会被保留,您可以随时手动编辑它来更新书签内容
- 如果项目中同时存在 `bookmarks.yml``bookmarks.user.yml`,系统会合并两者的内容,以 `bookmarks.user.yml` 中的配置为优先
- 这种设计允许您在更新源仓库时保留自己的书签配置
### 模板说明

View File

@@ -18,11 +18,12 @@
git push
```
4. GitHub Actions将自动处理书签文件生成`bookmarks.yml`,并重新构建站点
4. GitHub Actions将自动处理书签文件生成`bookmarks.user.yml`,并重新构建站点
## 注意事项
- 仅支持标准HTML格式的书签文件
- 每次只会处理目录中最新的一个书签文件
- 处理完成后,书签文件会被自动清除,以防止重复处理
- 已导入的书签可以在生成的`bookmarks.yml`文件中查看和编辑
- 已导入的书签可以在生成的`bookmarks.user.yml`文件中查看和编辑
- 系统会优先使用`bookmarks.user.yml`的配置,如果存在`bookmarks.yml`,会自动合并两者的内容(用户配置优先)

View File

@@ -2,10 +2,12 @@ const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
// 书签文件夹路径
const BOOKMARKS_DIR = path.join(__dirname, '..', 'bookmarks');
// 输出配置文件路径
const OUTPUT_FILE = path.join(__dirname, '..', 'bookmarks.yml');
// 书签文件夹路径 - 使用相对路径
const BOOKMARKS_DIR = 'bookmarks';
// 输出配置文件路径 - 使用相对路径
const OUTPUT_FILE = 'bookmarks.user.yml';
// 默认书签配置文件路径 - 使用相对路径
const DEFAULT_BOOKMARKS_FILE = 'bookmarks.yml';
// 图标映射根据URL关键字匹配合适的图标
const ICON_MAPPING = {
@@ -191,9 +193,10 @@ function generateBookmarksYaml(bookmarks) {
// 添加注释
const yamlWithComment =
`# 自动生成的书签配置文件 - 请勿手动编辑
`# 自动生成的书签配置文件 - 用户自定义版本
# 由bookmark-processor.js生成于 ${new Date().toISOString()}
# 若要更新请将新的书签HTML文件放入bookmarks/目录
# 注意此文件会覆盖bookmarks.yml中的同名配置
${yamlString}`;
@@ -206,8 +209,8 @@ ${yamlString}`;
// 更新现有config.yml中的导航添加书签页面
function updateConfigWithBookmarks() {
const configFile = path.join(__dirname, '..', 'config.yml');
const userConfigFile = path.join(__dirname, '..', 'config.user.yml');
const configFile = 'config.yml';
const userConfigFile = 'config.user.yml';
// 优先使用用户配置文件,如果存在
const targetConfigFile = fs.existsSync(userConfigFile) ? userConfigFile : configFile;
@@ -245,6 +248,10 @@ function updateConfigWithBookmarks() {
// 主函数
async function main() {
console.log('Starting bookmark processing...');
console.log(`Current working directory: ${process.cwd()}`);
console.log(`Output file will be: ${OUTPUT_FILE} (absolute: ${path.resolve(OUTPUT_FILE)})`);
// 获取最新的书签文件
const bookmarkFile = getLatestBookmarkFile();
if (!bookmarkFile) {
@@ -254,21 +261,67 @@ async function main() {
try {
// 读取文件内容
console.log(`Reading bookmark file: ${bookmarkFile}`);
const htmlContent = fs.readFileSync(bookmarkFile, 'utf8');
// 解析书签
const bookmarks = parseBookmarks(htmlContent);
console.log(`Found ${bookmarks.categories.length} categories with bookmarks`);
if (bookmarks.categories.length === 0) {
console.error('ERROR: No bookmark categories found in the HTML file. Processing aborted.');
return;
}
console.log('Categories found:');
bookmarks.categories.forEach(cat => {
console.log(`- ${cat.name}: ${cat.sites.length} sites`);
});
// 生成YAML
const yaml = generateBookmarksYaml(bookmarks);
if (yaml) {
if (!yaml) {
console.error('ERROR: Failed to generate YAML from bookmarks. Processing aborted.');
return;
}
// 显示将要写入的YAML前几行
console.log('Generated YAML preview (first 5 lines):');
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 });
}
// 保存YAML文件
console.log(`Writing to: ${OUTPUT_FILE}`);
fs.writeFileSync(OUTPUT_FILE, yaml, 'utf8');
console.log(`Saved bookmarks configuration to ${OUTPUT_FILE}`);
// 验证文件是否确实被创建
if (fs.existsSync(OUTPUT_FILE)) {
const stats = fs.statSync(OUTPUT_FILE);
console.log(`Successfully saved bookmarks configuration to ${OUTPUT_FILE}`);
console.log(`Verified file exists: ${OUTPUT_FILE}`);
console.log(`File size: ${stats.size} bytes`);
console.log(`File permissions: ${stats.mode.toString(8)}`);
// 列出当前目录内容以确认
console.log('Current directory contains:');
fs.readdirSync('.').forEach(file => {
console.log(`- ${file}`);
});
} else {
console.error(`ERROR: File was not created: ${OUTPUT_FILE}`);
process.exit(1);
}
// 更新导航
updateConfigWithBookmarks();
} catch (writeError) {
console.error(`ERROR writing file ${OUTPUT_FILE}:`, writeError);
process.exit(1);
}
} catch (error) {
console.error('Error processing bookmark file:', error);

View File

@@ -17,40 +17,45 @@ function escapeHtml(unsafe) {
// 读取配置文件
function loadConfig() {
let config = {};
let config = null;
// 读取默认配置
try {
const defaultConfigFile = fs.readFileSync('config.yml', 'utf8');
config = yaml.load(defaultConfigFile);
} catch (e) {
console.error('Error loading default config file:', e);
process.exit(1);
}
// 尝试读取用户配置并合并
try {
// 优先尝试读取用户配置
if (fs.existsSync('config.user.yml')) {
const userConfigFile = fs.readFileSync('config.user.yml', 'utf8');
const userConfig = yaml.load(userConfigFile);
// 深度合并配置,用户配置优先
config = mergeConfigs(config, userConfig);
config = yaml.load(userConfigFile);
console.log('Using user configuration from config.user.yml');
} else {
}
// 如果没有用户配置,则使用默认配置
else {
const defaultConfigFile = fs.readFileSync('config.yml', 'utf8');
config = yaml.load(defaultConfigFile);
console.log('No user configuration found, using default config.yml');
}
} catch (e) {
console.error('Error loading user config file:', e);
console.log('Falling back to default configuration');
console.error('Error loading configuration file:', e);
process.exit(1);
}
// 尝试读取书签配置并合并
// 尝试读取书签配置
try {
if (fs.existsSync('bookmarks.yml')) {
let bookmarksConfig = null;
// 优先尝试读取用户书签配置
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');
}
// 如果没有用户书签配置,则尝试读取默认书签配置
else if (fs.existsSync('bookmarks.yml')) {
const bookmarksFile = fs.readFileSync('bookmarks.yml', 'utf8');
const bookmarksConfig = yaml.load(bookmarksFile);
// 添加书签页面配置
bookmarksConfig = yaml.load(bookmarksFile);
console.log('Using default bookmarks configuration from bookmarks.yml');
}
// 添加书签页面配置
if (bookmarksConfig) {
config.bookmarks = bookmarksConfig;
// 确保导航中有书签页面
@@ -63,8 +68,6 @@ function loadConfig() {
active: false
});
}
console.log('Loaded bookmarks configuration from bookmarks.yml');
}
} catch (e) {
console.error('Error loading bookmarks configuration:', e);
@@ -73,23 +76,6 @@ function loadConfig() {
return config;
}
// 深度合并配置对象
function mergeConfigs(defaultConfig, userConfig) {
if (!userConfig) return defaultConfig;
const merged = { ...defaultConfig };
for (const key in userConfig) {
if (typeof userConfig[key] === 'object' && !Array.isArray(userConfig[key])) {
merged[key] = mergeConfigs(defaultConfig[key] || {}, userConfig[key]);
} else {
merged[key] = userConfig[key];
}
}
return merged;
}
// 生成导航菜单
function generateNavigation(navigation) {
return navigation.map(nav => `