Files
mengyanote/mengyanote-frontend/scripts/generateData.js
2025-12-13 20:48:21 +08:00

215 lines
7.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 路径配置
const NOTES_SOURCE_PATH = path.join(__dirname, '../public/mengyanote');
const OUTPUT_PATH = path.join(__dirname, '../src/data');
const PUBLIC_OUTPUT_PATH = path.join(__dirname, '../public/data');
const IGNORE_FILE_PATH = path.join(NOTES_SOURCE_PATH, 'ignore.json');
// 文件节点类型
const NODE_TYPES = {
FOLDER: 'folder',
FILE: 'file'
};
// 读取忽略配置
function loadIgnoreConfig() {
try {
if (fs.existsSync(IGNORE_FILE_PATH)) {
const ignoreContent = fs.readFileSync(IGNORE_FILE_PATH, 'utf-8');
const ignoreConfig = JSON.parse(ignoreContent);
console.log('✓ 已加载忽略配置:', ignoreConfig.ignore);
return ignoreConfig.ignore || [];
}
} catch (error) {
console.warn('⚠️ 读取ignore.json失败使用默认配置:', error.message);
}
return [];
}
// 检查是否为Markdown文件
function isMarkdownFile(filename) {
return filename.toLowerCase().endsWith('.md');
}
// 检查是否应该忽略的文件/文件夹
function shouldIgnore(name, customIgnoreList = []) {
const defaultIgnoredItems = ['.obsidian', '.trash', '.git', 'node_modules'];
const allIgnoredItems = [...defaultIgnoredItems, ...customIgnoreList];
return allIgnoredItems.includes(name) || name.startsWith('.');
}
// 创建文件树节点
function createNode(name, type, path, children = []) {
return {
id: path,
name,
type,
path,
children,
isExpanded: false
};
}
// 递归读取目录结构
function readDirectoryTree(dirPath, basePath = NOTES_SOURCE_PATH, ignoreList = []) {
try {
const items = fs.readdirSync(dirPath, { withFileTypes: true });
const children = [];
for (const item of items) {
if (shouldIgnore(item.name, ignoreList)) {
continue;
}
const itemPath = path.join(dirPath, item.name);
const relativePath = path.relative(basePath, itemPath).replace(/\\/g, '/');
if (item.isDirectory()) {
const subChildren = readDirectoryTree(itemPath, basePath, ignoreList);
if (subChildren.length > 0) {
children.push(createNode(item.name, NODE_TYPES.FOLDER, relativePath, subChildren));
}
} else if (isMarkdownFile(item.name)) {
children.push(createNode(item.name, NODE_TYPES.FILE, relativePath));
}
}
// 排序:文件夹在前,文件在后,同类型按名称排序
children.sort((a, b) => {
if (a.type !== b.type) {
return a.type === NODE_TYPES.FOLDER ? -1 : 1;
}
return a.name.localeCompare(b.name, 'zh-CN');
});
return children;
} catch (error) {
console.error('Error reading directory:', error);
return [];
}
}
// 读取所有Markdown文件内容
function readAllMarkdownFiles(dirPath, basePath = NOTES_SOURCE_PATH, fileContents = {}, ignoreList = []) {
try {
const items = fs.readdirSync(dirPath, { withFileTypes: true });
for (const item of items) {
if (shouldIgnore(item.name, ignoreList)) {
continue;
}
const itemPath = path.join(dirPath, item.name);
const relativePath = path.relative(basePath, itemPath).replace(/\\/g, '/');
if (item.isDirectory()) {
readAllMarkdownFiles(itemPath, basePath, fileContents, ignoreList);
} else if (isMarkdownFile(item.name)) {
try {
const content = fs.readFileSync(itemPath, 'utf-8');
fileContents[relativePath] = content;
console.log(`✓ 读取文件: ${relativePath}`);
} catch (error) {
console.error(`✗ 读取文件失败: ${relativePath}`, error.message);
}
}
}
return fileContents;
} catch (error) {
console.error('Error reading markdown files:', error);
return fileContents;
}
}
// 生成数据文件
function generateData() {
console.log('🚀 开始生成静态数据...');
// 检查源目录是否存在
if (!fs.existsSync(NOTES_SOURCE_PATH)) {
console.error(`❌ 源目录不存在: ${NOTES_SOURCE_PATH}`);
process.exit(1);
}
// 创建输出目录
if (!fs.existsSync(OUTPUT_PATH)) {
fs.mkdirSync(OUTPUT_PATH, { recursive: true });
}
if (!fs.existsSync(PUBLIC_OUTPUT_PATH)) {
fs.mkdirSync(PUBLIC_OUTPUT_PATH, { recursive: true });
}
// 加载忽略配置
console.log('📋 加载忽略配置...');
const ignoreList = loadIgnoreConfig();
console.log('📁 读取目录结构...');
const directoryTree = readDirectoryTree(NOTES_SOURCE_PATH, NOTES_SOURCE_PATH, ignoreList);
console.log('📄 读取Markdown文件内容...');
const fileContents = readAllMarkdownFiles(NOTES_SOURCE_PATH, NOTES_SOURCE_PATH, {}, ignoreList);
// 生成统计信息
const stats = {
totalFiles: Object.keys(fileContents).length,
totalFolders: countFolders(directoryTree),
generatedAt: new Date().toISOString(),
sourceDirectory: NOTES_SOURCE_PATH
};
// 生成到 src/data 目录
const treeOutputPath = path.join(OUTPUT_PATH, 'directoryTree.json');
const contentOutputPath = path.join(OUTPUT_PATH, 'fileContents.json');
const statsOutputPath = path.join(OUTPUT_PATH, 'stats.json');
fs.writeFileSync(treeOutputPath, JSON.stringify(directoryTree, null, 2), 'utf-8');
fs.writeFileSync(contentOutputPath, JSON.stringify(fileContents, null, 2), 'utf-8');
fs.writeFileSync(statsOutputPath, JSON.stringify(stats, null, 2), 'utf-8');
console.log(`✓ 目录树已生成: ${treeOutputPath}`);
console.log(`✓ 文件内容已生成: ${contentOutputPath}`);
console.log(`✓ 统计信息已生成: ${statsOutputPath}`);
// 生成到 public/data 目录
const publicTreeOutputPath = path.join(PUBLIC_OUTPUT_PATH, 'directoryTree.json');
const publicContentOutputPath = path.join(PUBLIC_OUTPUT_PATH, 'fileContents.json');
const publicStatsOutputPath = path.join(PUBLIC_OUTPUT_PATH, 'stats.json');
fs.writeFileSync(publicTreeOutputPath, JSON.stringify(directoryTree, null, 2), 'utf-8');
fs.writeFileSync(publicContentOutputPath, JSON.stringify(fileContents, null, 2), 'utf-8');
fs.writeFileSync(publicStatsOutputPath, JSON.stringify(stats, null, 2), 'utf-8');
console.log(`✓ 目录树已生成到public: ${publicTreeOutputPath}`);
console.log(`✓ 文件内容已生成到public: ${publicContentOutputPath}`);
console.log(`✓ 统计信息已生成到public: ${publicStatsOutputPath}`);
console.log('🎉 数据生成完成!');
console.log(`📊 统计信息:`);
console.log(` - 文件数量: ${stats.totalFiles}`);
console.log(` - 文件夹数量: ${stats.totalFolders}`);
console.log(` - 生成时间: ${stats.generatedAt}`);
}
// 计算文件夹数量
function countFolders(nodes) {
let count = 0;
for (const node of nodes) {
if (node.type === NODE_TYPES.FOLDER) {
count++;
if (node.children && node.children.length > 0) {
count += countFolders(node.children);
}
}
}
return count;
}
// 执行生成
generateData();