feat: sync full workspace including web modules, docs, and configurations to Gitea

Optimized the root .gitignore to exclude virtual environments, node modules,
and temp folders to ensure clean and lightweight version tracking.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
王冕
2026-06-09 18:12:25 +08:00
parent 351688006e
commit a27e3b8e43
1510 changed files with 162044 additions and 1517 deletions

View File

@@ -0,0 +1,121 @@
#!/usr/bin/env node
/**
* 为 dist 目录下的所有 JS 文件生成对应的 HTML 文件
* 使用 html-template.html 模板,用于构建后直接访问
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const workspaceRoot = path.resolve(__dirname, '..');
const distDir = path.resolve(workspaceRoot, 'dist');
const adminDir = path.resolve(workspaceRoot, 'admin');
const templatePath = path.join(adminDir, 'html-template.html');
let generatedCount = 0;
// 检查模板是否存在
if (!fs.existsSync(templatePath)) {
console.error('错误: html-template.html 模板不存在,请先构建 prototype-admin');
console.error('路径:', templatePath);
process.exit(1);
}
// 检查 dist 目录是否存在
if (!fs.existsSync(distDir)) {
console.log('dist 目录不存在,跳过 HTML 生成');
process.exit(0);
}
const template = fs.readFileSync(templatePath, 'utf8');
/**
* 递归遍历目录,为每个 JS 文件生成 HTML
*/
function generateHtmlForDirectory(dir, baseDir = distDir) {
const items = fs.readdirSync(dir, { withFileTypes: true });
for (const item of items) {
const itemPath = path.join(dir, item.name);
if (item.isDirectory()) {
// 递归处理子目录
generateHtmlForDirectory(itemPath, baseDir);
} else if (item.name.endsWith('.js') && !item.name.includes('.worker')) {
// 为 JS 文件生成 HTML
const relativePath = path.relative(baseDir, itemPath);
const jsName = relativePath.replace('.js', '');
const htmlPath = path.join(dir, item.name.replace('.js', '.html'));
// 根据路径生成标题
let title = 'Preview';
if (jsName.startsWith('components/')) {
const name = jsName.replace('components/', '');
title = `Element: ${name}`;
} else if (jsName.startsWith('prototypes/')) {
const name = jsName.replace('prototypes/', '');
title = `Page: ${name}`;
}
// 计算 JS 文件的相对路径(从 HTML 的位置)
const jsFileName = `./${item.name}`;
// 计算 bootstrap JS 的相对路径
const relativeDir = path.relative(baseDir, dir);
const depth = relativeDir ? relativeDir.split(path.sep).length : 0;
const bootstrapPath = depth > 0
? '../'.repeat(depth) + 'assets/html-template-bootstrap.js'
: './assets/html-template-bootstrap.js';
// 替换模板变量
let html = template.replace('{{TITLE}}', title);
html = html.replace('{{ENTRY}}', jsFileName);
html = html.replace('{{BOOTSTRAP_PATH}}', bootstrapPath);
// 写入 HTML 文件
fs.writeFileSync(htmlPath, html, 'utf8');
console.log(`生成: ${relativePath.replace('.js', '.html')}`);
generatedCount++;
}
}
}
console.log('\n开始为 dist 目录生成 HTML 文件...\n');
generateHtmlForDirectory(distDir);
console.log(`\n完成!共生成 ${generatedCount} 个 HTML 文件。`);
console.log('模板文件: admin/html-template.html\n');
// 复制 bootstrap JS 到 dist/assets
const srcBootstrap = path.join(adminDir, 'assets/html-template-bootstrap.js');
const destAssetsDir = path.join(distDir, 'assets');
const destBootstrap = path.join(destAssetsDir, 'html-template-bootstrap.js');
if (fs.existsSync(srcBootstrap)) {
if (!fs.existsSync(destAssetsDir)) {
fs.mkdirSync(destAssetsDir, { recursive: true });
}
fs.copyFileSync(srcBootstrap, destBootstrap);
console.log('✓ html-template-bootstrap.js 已复制到 dist/assets');
// 同时复制其他必要的依赖(如果有的话)
const assetsFiles = fs.readdirSync(path.join(adminDir, 'assets'));
for (const file of assetsFiles) {
// 复制 bootstrap 依赖的 chunk 文件
if (file.startsWith('index-') && file.endsWith('.js')) {
const src = path.join(adminDir, 'assets', file);
const dest = path.join(destAssetsDir, file);
fs.copyFileSync(src, dest);
console.log(`${file} 已复制到 dist/assets`);
}
}
} else {
console.warn('⚠ html-template-bootstrap.js 不存在,请先构建 prototype-admin');
}