178 lines
5.2 KiB
JavaScript
178 lines
5.2 KiB
JavaScript
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 NODE_TYPES = {
|
|
FOLDER: 'folder',
|
|
FILE: 'file'
|
|
};
|
|
|
|
// 检查是否为Markdown文件
|
|
function isMarkdownFile(filename) {
|
|
return filename.toLowerCase().endsWith('.md');
|
|
}
|
|
|
|
// 检查是否应该忽略的文件/文件夹
|
|
function shouldIgnore(name) {
|
|
const ignoredItems = ['.obsidian', '.trash', '.git', 'node_modules'];
|
|
return ignoredItems.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) {
|
|
try {
|
|
const items = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
const children = [];
|
|
|
|
for (const item of items) {
|
|
if (shouldIgnore(item.name)) {
|
|
continue;
|
|
}
|
|
|
|
const itemPath = path.join(dirPath, item.name);
|
|
const relativePath = path.relative(basePath, itemPath).replace(/\\/g, '/');
|
|
|
|
if (item.isDirectory()) {
|
|
const subChildren = readDirectoryTree(itemPath, basePath);
|
|
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 = {}) {
|
|
try {
|
|
const items = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
|
|
for (const item of items) {
|
|
if (shouldIgnore(item.name)) {
|
|
continue;
|
|
}
|
|
|
|
const itemPath = path.join(dirPath, item.name);
|
|
const relativePath = path.relative(basePath, itemPath).replace(/\\/g, '/');
|
|
|
|
if (item.isDirectory()) {
|
|
readAllMarkdownFiles(itemPath, basePath, fileContents);
|
|
} 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 });
|
|
}
|
|
|
|
console.log('📁 读取目录结构...');
|
|
const directoryTree = readDirectoryTree(NOTES_SOURCE_PATH);
|
|
|
|
console.log('📄 读取Markdown文件内容...');
|
|
const fileContents = readAllMarkdownFiles(NOTES_SOURCE_PATH);
|
|
|
|
// 生成目录树文件
|
|
const treeOutputPath = path.join(OUTPUT_PATH, 'directoryTree.json');
|
|
fs.writeFileSync(treeOutputPath, JSON.stringify(directoryTree, null, 2), 'utf-8');
|
|
console.log(`✓ 目录树已生成: ${treeOutputPath}`);
|
|
|
|
// 生成文件内容文件
|
|
const contentOutputPath = path.join(OUTPUT_PATH, 'fileContents.json');
|
|
fs.writeFileSync(contentOutputPath, JSON.stringify(fileContents, null, 2), 'utf-8');
|
|
console.log(`✓ 文件内容已生成: ${contentOutputPath}`);
|
|
|
|
// 生成统计信息
|
|
const stats = {
|
|
totalFiles: Object.keys(fileContents).length,
|
|
totalFolders: countFolders(directoryTree),
|
|
generatedAt: new Date().toISOString(),
|
|
sourceDirectory: NOTES_SOURCE_PATH
|
|
};
|
|
|
|
const statsOutputPath = path.join(OUTPUT_PATH, 'stats.json');
|
|
fs.writeFileSync(statsOutputPath, JSON.stringify(stats, null, 2), 'utf-8');
|
|
console.log(`✓ 统计信息已生成: ${statsOutputPath}`);
|
|
|
|
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(); |