const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const os = require('node:os'); const { ensureUserConfigInitialized, ensureUserSiteYmlExists, upsertBookmarksNavInSiteYml, parseBookmarks, generateBookmarksYaml, } = require('../src/bookmark-processor.js'); function stripYamlComments(yamlText) { return yamlText .split(/\r?\n/) .filter(line => !/^\s*#/.test(line)) .join('\n') .trim(); } test('parseBookmarks:解析书签栏、根目录书签与图标映射', () => { const html = `
`; const bookmarks = parseBookmarks(html); assert.ok(bookmarks); assert.ok(Array.isArray(bookmarks.categories)); assert.ok(bookmarks.categories.length >= 2); // 根目录书签应该插入到首位 assert.equal(bookmarks.categories[0].name, '根目录书签'); assert.ok(Array.isArray(bookmarks.categories[0].sites)); assert.equal(bookmarks.categories[0].sites[0].name, 'GitHub'); assert.equal(bookmarks.categories[0].sites[0].icon, 'fab fa-github'); const tools = bookmarks.categories.find(c => c.name === '工具'); assert.ok(tools, '应解析出“工具”分类'); assert.ok(Array.isArray(tools.sites)); assert.equal(tools.sites[0].name, 'Google'); }); test('generateBookmarksYaml:生成 YAML 且可被解析', () => { const bookmarks = { categories: [ { name: '示例分类', icon: 'fas fa-folder', sites: [{ name: 'Example', url: 'https://example.com', icon: 'fas fa-link', description: '' }], }, ], }; const yamlText = generateBookmarksYaml(bookmarks); assert.ok(typeof yamlText === 'string'); assert.ok(yamlText.includes('# 自动生成的书签配置文件')); assert.ok(yamlText.includes('categories:')); const yaml = require('js-yaml'); const parsed = yaml.load(stripYamlComments(yamlText)); assert.equal(parsed.title, '我的书签'); assert.ok(Array.isArray(parsed.categories)); assert.equal(parsed.categories[0].name, '示例分类'); }); test('upsertBookmarksNavInSiteYml:无 navigation 时追加并幂等', () => { const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'menav-test-')); const filePath = path.join(tmp, 'site.yml'); fs.writeFileSync( filePath, `title: Test Site\n`, 'utf8', ); const r1 = upsertBookmarksNavInSiteYml(filePath); assert.equal(r1.updated, true); const updated1 = fs.readFileSync(filePath, 'utf8'); assert.ok(updated1.includes('navigation:')); assert.ok(updated1.includes('- name: 书签')); assert.ok(updated1.includes('id: bookmarks')); const r2 = upsertBookmarksNavInSiteYml(filePath); assert.equal(r2.updated, false); assert.equal(r2.reason, 'already_present'); }); test('ensureUserConfigInitialized/ensureUserSiteYmlExists:可在空目录初始化用户配置', () => { const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'menav-test-')); const originalCwd = process.cwd(); process.chdir(tmp); try { fs.mkdirSync('config/_default/pages', { recursive: true }); fs.writeFileSync('config/_default/site.yml', 'title: Default\n', 'utf8'); fs.writeFileSync('config/_default/pages/home.yml', 'categories: []\n', 'utf8'); const init = ensureUserConfigInitialized(); assert.equal(init.initialized, true); assert.ok(fs.existsSync('config/user/site.yml')); assert.ok(fs.existsSync('config/user/pages/home.yml')); // 若 site.yml 已存在,应直接返回 true assert.equal(ensureUserSiteYmlExists(), true); } finally { process.chdir(originalCwd); } });