diff --git a/README.md b/README.md index dca6e31..59a89fc 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ QuantPilot is not a production live-trading system. It is a platform skeleton an | Category | Technology | |----------|------------| -| Language | TypeScript 5 (100% first-party source, no new JavaScript source files) | +| Language | TypeScript 5 (TypeScript-first first-party source; no new JavaScript source files in `apps`, `packages`, or `scripts`) | | Frontend | React 18 + react-router-dom 6 | | Build | Vite 5 | | Styling | vanilla-extract | diff --git a/README.zh-CN.md b/README.zh-CN.md index 803f3c7..65a60bf 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -10,7 +10,7 @@ QuantPilot 不是一个可直接用于实盘的生产交易系统。它当前定 | 类别 | 技术 | |------|------| -| 语言 | TypeScript 5(第一方源码 100%,禁止新增 JavaScript 源文件) | +| 语言 | TypeScript 5(第一方源码 TypeScript-first;`apps`、`packages`、`scripts` 中禁止新增 JavaScript 源文件) | | 前端 | React 18 + react-router-dom 6 | | 构建 | Vite 5 | | 样式 | vanilla-extract | diff --git a/scripts/check-no-js-source.ts b/scripts/check-no-js-source.ts index 82ac05c..7a9b569 100644 --- a/scripts/check-no-js-source.ts +++ b/scripts/check-no-js-source.ts @@ -1,9 +1,10 @@ +import { execFileSync } from 'node:child_process'; import { readdirSync } from 'node:fs'; import { join, relative } from 'node:path'; const repoRoot = process.cwd(); const sourceRoots = ['apps', 'packages', 'scripts']; -const blockedExtensions = new Set(['.js', '.mjs', '.cjs']); +const blockedExtensions = new Set(['.js', '.jsx', '.mjs', '.cjs']); const ignoredDirs = new Set(['node_modules', 'dist', 'coverage', '.git', '.vite']); function walk(dirPath: string, hits: string[]) { @@ -25,24 +26,36 @@ function walk(dirPath: string, hits: string[]) { } } +function findTrackedJavaScriptFiles() { + const output = execFileSync('git', ['ls-files', '*.js', '*.jsx', '*.mjs', '*.cjs'], { + cwd: repoRoot, + encoding: 'utf8', + }); + + return output.split('\n').filter(Boolean); +} + function main() { const hits: string[] = []; + const trackedHits = findTrackedJavaScriptFiles(); for (const sourceRoot of sourceRoots) { walk(join(repoRoot, sourceRoot), hits); } - if (hits.length > 0) { - console.error('JavaScript source files are not allowed in first-party source roots.'); - console.error('Migrate these files to TypeScript instead:'); - for (const hit of hits.sort()) { + const allHits = Array.from(new Set([...trackedHits, ...hits])).sort(); + + if (allHits.length > 0) { + console.error('JavaScript files are not allowed in first-party source or tracked files.'); + console.error('Migrate these files to TypeScript or remove generated artifacts from Git:'); + for (const hit of allHits) { console.error(`- ${hit}`); } process.exitCode = 1; return; } - console.info('No JavaScript source files found in first-party source roots.'); + console.info('No JavaScript files found in first-party source roots or Git-tracked files.'); } main();