mirror of
https://github.com/motajs/template.git
synced 2026-04-12 15:11:10 +08:00
fix: 文档监听与 vitepress 竞态问题
This commit is contained in:
parent
5a1a0fee42
commit
5550fac160
@ -1,59 +1,64 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import chokidar from 'chokidar';
|
||||
import { basename, join, resolve } from 'node:path';
|
||||
import { DefaultTheme } from 'vitepress';
|
||||
import { readdir, stat, writeFile } from 'node:fs/promises';
|
||||
|
||||
const apiDir = path.resolve('./docs/api');
|
||||
const sidebarConfigPath = path.resolve('./docs/.vitepress/apiSidebar.ts');
|
||||
const apiDir = resolve('./docs/api');
|
||||
const sidebarConfigPath = resolve('./docs/.vitepress/apiSidebar.ts');
|
||||
|
||||
const weight: Record<string, number> = {
|
||||
主页: 10,
|
||||
函数: 5
|
||||
};
|
||||
|
||||
function generateSidebar(): void {
|
||||
export async function generateSidebar(): Promise<void> {
|
||||
const sidebar: DefaultTheme.SidebarItem[] = [
|
||||
{ text: '目录', link: '/api/' }
|
||||
];
|
||||
|
||||
// 遍历 api 目录,查找 package 目录
|
||||
const packages = fs
|
||||
.readdirSync(apiDir)
|
||||
.filter(pkg => fs.statSync(path.join(apiDir, pkg)).isDirectory());
|
||||
const dir = await readdir(apiDir);
|
||||
const packages = [];
|
||||
for (const pkg of dir) {
|
||||
const stats = await stat(join(apiDir, pkg));
|
||||
if (stats.isDirectory()) {
|
||||
packages.push(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
packages.forEach(pkg => {
|
||||
const pkgPath = path.join(apiDir, pkg);
|
||||
const files = fs
|
||||
.readdirSync(pkgPath)
|
||||
.filter(file => file.endsWith('.md'));
|
||||
await Promise.all(
|
||||
packages.map(async pkg => {
|
||||
const pkgPath = join(apiDir, pkg);
|
||||
const dir = await readdir(pkgPath);
|
||||
const files = dir.filter(file => file.endsWith('.md'));
|
||||
|
||||
const items: DefaultTheme.SidebarItem[] = files.map(file => {
|
||||
const filePath = `api/${pkg}/${file}`;
|
||||
const fileName = path.basename(file, '.md');
|
||||
const items: DefaultTheme.SidebarItem[] = files.map(file => {
|
||||
const filePath = `api/${pkg}/${file}`;
|
||||
const fileName = basename(file, '.md');
|
||||
|
||||
return {
|
||||
text:
|
||||
fileName === 'index'
|
||||
? '主页'
|
||||
: fileName === 'functions'
|
||||
? '函数'
|
||||
: fileName,
|
||||
link: `/${filePath.replace(/\\/g, '/')}` // 兼容 Windows 路径
|
||||
};
|
||||
});
|
||||
return {
|
||||
text:
|
||||
fileName === 'index'
|
||||
? '主页'
|
||||
: fileName === 'functions'
|
||||
? '函数'
|
||||
: fileName,
|
||||
link: `/${filePath.replace(/\\/g, '/')}` // 兼容 Windows 路径
|
||||
};
|
||||
});
|
||||
|
||||
items.sort((a, b) => {
|
||||
const titleA = a.text ?? '';
|
||||
const titleB = b.text ?? '';
|
||||
return (weight[titleB] ?? 0) - (weight[titleA] ?? 0);
|
||||
});
|
||||
items.sort((a, b) => {
|
||||
const titleA = a.text ?? '';
|
||||
const titleB = b.text ?? '';
|
||||
return (weight[titleB] ?? 0) - (weight[titleA] ?? 0);
|
||||
});
|
||||
|
||||
sidebar.push({
|
||||
text: pkg,
|
||||
collapsed: true,
|
||||
items
|
||||
});
|
||||
});
|
||||
sidebar.push({
|
||||
text: pkg,
|
||||
collapsed: true,
|
||||
items
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
// 生成 sidebar.ts
|
||||
const sidebarContent = `import { DefaultTheme } from 'vitepress';
|
||||
@ -63,35 +68,6 @@ export default ${JSON.stringify(
|
||||
null,
|
||||
4
|
||||
)} as DefaultTheme.SidebarItem[];`;
|
||||
fs.writeFileSync(sidebarConfigPath, sidebarContent);
|
||||
await writeFile(sidebarConfigPath, sidebarContent);
|
||||
console.log('✅ Sidebar 配置已更新');
|
||||
}
|
||||
|
||||
// 初次运行
|
||||
generateSidebar();
|
||||
|
||||
// 监听文件变动
|
||||
chokidar
|
||||
.watch(apiDir, { ignoreInitial: true })
|
||||
.on('add', filePath => {
|
||||
console.log(`📄 文件新增: ${filePath}`);
|
||||
generateSidebar();
|
||||
})
|
||||
.on('unlink', filePath => {
|
||||
console.log(`❌ 文件删除: ${filePath}`);
|
||||
generateSidebar();
|
||||
})
|
||||
.on('addDir', dirPath => {
|
||||
console.log(`📁 目录新增: ${dirPath}`);
|
||||
generateSidebar();
|
||||
})
|
||||
.on('unlinkDir', dirPath => {
|
||||
console.log(`📁 目录删除: ${dirPath}`);
|
||||
generateSidebar();
|
||||
})
|
||||
.on('raw', (event, path, details) => {
|
||||
if (event === 'rename') {
|
||||
console.log(`🔄 文件或文件夹重命名: ${path}`);
|
||||
generateSidebar();
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,39 @@
|
||||
import { defineConfig } from 'vitepress';
|
||||
import { defineConfig, Plugin } from 'vitepress';
|
||||
import { MermaidMarkdown, MermaidPlugin } from 'vitepress-plugin-mermaid';
|
||||
import api from './apiSidebar';
|
||||
import { join } from 'path';
|
||||
import { generateSidebar } from './api';
|
||||
|
||||
function listenSidebar(): Plugin {
|
||||
return {
|
||||
name: 'sidebar-listen',
|
||||
configureServer(server) {
|
||||
server.watcher
|
||||
.on('add', filePath => {
|
||||
console.log(`📄 文件新增: ${filePath}`);
|
||||
generateSidebar();
|
||||
})
|
||||
.on('unlink', filePath => {
|
||||
console.log(`❌ 文件删除: ${filePath}`);
|
||||
generateSidebar();
|
||||
})
|
||||
.on('addDir', dirPath => {
|
||||
console.log(`📁 目录新增: ${dirPath}`);
|
||||
generateSidebar();
|
||||
})
|
||||
.on('unlinkDir', dirPath => {
|
||||
console.log(`📁 目录删除: ${dirPath}`);
|
||||
generateSidebar();
|
||||
})
|
||||
.on('raw', (event, path, _) => {
|
||||
if (event === 'rename') {
|
||||
console.log(`🔄 文件或文件夹重命名: ${path}`);
|
||||
generateSidebar();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
@ -157,7 +189,7 @@ export default defineConfig({
|
||||
},
|
||||
vite: {
|
||||
// @ts-expect-error 类型错误
|
||||
plugins: [MermaidPlugin()],
|
||||
plugins: [MermaidPlugin(), listenSidebar()],
|
||||
optimizeDeps: {
|
||||
include: ['mermaid']
|
||||
},
|
||||
|
||||
5
docs/.vitepress/init.ts
Normal file
5
docs/.vitepress/init.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { generateSidebar } from './api';
|
||||
|
||||
(() => {
|
||||
generateSidebar();
|
||||
})();
|
||||
@ -12,7 +12,7 @@
|
||||
"build:packages": "vue-tsc --noEmit && tsx script/build-packages.ts",
|
||||
"build:game": "tsx script/declare.ts && vue-tsc --noEmit && tsx script/build-game.ts",
|
||||
"build:lib": "vue-tsc --noEmit && tsx script/build-lib.ts",
|
||||
"docs:dev": "concurrently -k -n SIDEBAR,VITEPRESS -c blue,green \"tsx docs/.vitepress/api.ts\" \"vitepress dev docs\"",
|
||||
"docs:dev": "tsx docs/.vitepress/init.ts && vitepress dev docs",
|
||||
"docs:build": "vitepress build docs",
|
||||
"docs:preview": "vitepress preview docs",
|
||||
"pack:template": "tsx script/pack-template.ts"
|
||||
|
||||
@ -7,5 +7,13 @@
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true
|
||||
},
|
||||
"include": ["vite.config.ts", "script/**/*.ts", "mota.config.ts"]
|
||||
"include": [
|
||||
"vite.config.ts",
|
||||
"script/**/*.ts",
|
||||
"docs/**/*.ts",
|
||||
"docs/.vitepress/api.ts",
|
||||
"docs/.vitepress/config.ts",
|
||||
"docs/.vitepress/apiSidebar.ts",
|
||||
"docs/.vitepress/init.ts"
|
||||
]
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user