148 lines
4.3 KiB
TypeScript
148 lines
4.3 KiB
TypeScript
import fs from "fs";
|
|
import path from "path";
|
|
import { globSync } from "glob";
|
|
|
|
interface Config {
|
|
outputDir: string;
|
|
outputFilenameWithExt: string;
|
|
scanDirs: string[];
|
|
importPrefix: string;
|
|
predefineStatements: string[];
|
|
includeExtensions: string[];
|
|
excludeDirs: string[];
|
|
excludeFileExtensions: string[];
|
|
excludePatterns: RegExp[];
|
|
}
|
|
|
|
const cssConfig: Config = {
|
|
outputDir: "src",
|
|
outputFilenameWithExt: "index.css",
|
|
scanDirs: ["src"],
|
|
importPrefix: "@import",
|
|
predefineStatements: [],
|
|
includeExtensions: [".css"],
|
|
excludeDirs: ["__tests__", "tests", "story", "stories", "types"],
|
|
excludeFileExtensions: [],
|
|
excludePatterns: [/^index\.(css)$/, /\.(test|spec)\./, /\.(story|stories)\./],
|
|
};
|
|
|
|
const tsConfig: Config = {
|
|
outputDir: "src",
|
|
outputFilenameWithExt: "index.ts",
|
|
scanDirs: ["src"],
|
|
importPrefix: "export * from",
|
|
predefineStatements: ["import './index.css'"],
|
|
includeExtensions: [".ts", "tsx", "js", "jsx"],
|
|
excludeDirs: ["__tests__", "tests", "story", "stories", "types"],
|
|
excludeFileExtensions: [".d.ts"],
|
|
excludePatterns: [
|
|
/^index\.(ts|tsx|js|jsx)$/,
|
|
/\.(test|spec)\./,
|
|
/\.(story|stories)\./,
|
|
],
|
|
};
|
|
|
|
const normalizePath = (p: string) => p.replace(/\\/g, "/");
|
|
|
|
const isExcludeDir = (filePath: string, excludeDirs: string[]) => {
|
|
const normalized = normalizePath(filePath);
|
|
return excludeDirs.some((dir) => normalized.includes(`/${dir}/`));
|
|
};
|
|
|
|
const isExcludeFileExtensions = (
|
|
filePath: string,
|
|
excludeFileExtensions: string[],
|
|
) => excludeFileExtensions.some((ext) => filePath.endsWith(ext));
|
|
|
|
const isExcludePattern = (fileName: string, excludePatterns: RegExp[]) =>
|
|
excludePatterns.some((pattern) => pattern.test(fileName));
|
|
|
|
// ----------------------------------------
|
|
function isValidFile(filePath: string, config: Config): boolean {
|
|
const fileName = filePath.split(/[\\/]/).pop()!;
|
|
|
|
if (isExcludeDir(filePath, config.excludeDirs)) return false;
|
|
if (isExcludeFileExtensions(filePath, config.excludeFileExtensions))
|
|
return false;
|
|
if (isExcludePattern(fileName, config.excludePatterns)) return false;
|
|
|
|
const ext = path.extname(filePath);
|
|
return config.includeExtensions.includes(ext);
|
|
}
|
|
// -----------------------------------------
|
|
function generateIndexFile(config: Config) {
|
|
const currentPath = process.cwd();
|
|
const outputPath = path.resolve(currentPath, config.outputDir);
|
|
let exportStatements: string[] = [];
|
|
|
|
// ------ scanDirs forEach start ------------------------
|
|
config.scanDirs.forEach((dir) => {
|
|
const scanPattern = path.resolve(currentPath, dir, "**", "*.*");
|
|
|
|
const allFilePath = globSync(scanPattern, {
|
|
absolute: true,
|
|
windowsPathsNoEscape: true,
|
|
dot: false,
|
|
follow: true,
|
|
});
|
|
|
|
const validFiles = allFilePath.filter((filePath) => {
|
|
return isValidFile(filePath, config);
|
|
});
|
|
|
|
if (validFiles.length === 0) {
|
|
console.log(
|
|
`⚠️ 未找到符合条件的文件,跳过生成 ${config.outputFilenameWithExt}`,
|
|
);
|
|
return;
|
|
}
|
|
|
|
validFiles.sort();
|
|
|
|
validFiles.forEach((file) => {
|
|
const relativePath = path.relative(outputPath, file);
|
|
const importPath = `./${relativePath.replace(/\\/g, "/")}`;
|
|
exportStatements.push(`${config.importPrefix} '${importPath}';`);
|
|
});
|
|
});
|
|
|
|
// --------- scanDirs forEach end ----------------
|
|
|
|
const indexFileContent = `
|
|
${config.predefineStatements.join("\n")}
|
|
${exportStatements.join("\n")}
|
|
`.trim();
|
|
|
|
const indexFilePath = path.resolve(
|
|
currentPath,
|
|
config.outputDir,
|
|
config.outputFilenameWithExt,
|
|
);
|
|
|
|
// ✅ 内容比对,避免重复写入
|
|
if (fs.existsSync(indexFilePath)) {
|
|
const old = fs.readFileSync(indexFilePath, "utf8");
|
|
if (old === indexFileContent) {
|
|
console.log(
|
|
`✅ ${config.outputFilenameWithExt} 内容无变化,无需重新生成`,
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
fs.writeFileSync(indexFilePath, indexFileContent, "utf8");
|
|
console.log(`✅ 成功生成 ${config.outputFilenameWithExt}: ${indexFilePath}`);
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
|
|
try {
|
|
console.log(`🚀 [gen-index] 开始扫描`);
|
|
generateIndexFile(cssConfig);
|
|
generateIndexFile(tsConfig);
|
|
} catch (err) {
|
|
const msg = err instanceof Error ? err.message : String(err);
|
|
console.error(`❌ [gen-index] 执行失败: ${msg}`);
|
|
process.exit(1);
|
|
}
|