refactor: reorganize project structure and improve code quality
- Move CI/CD configs to config/ci/ directory - Reorganize scripts into categorized directories (deployment, monitoring, testing, utils) - Consolidate documentation into docs/ directory with proper structure - Update linting and testing configurations - Remove obsolete test reports and performance summaries - Add new documentation for code quality tools and contact form security - Improve project organization and maintainability - Fix lint-staged config to only lint JS/TS files - Disable react/react-in-jsx-scope rule for Next.js compatibility - Ignore scripts and test config directories in ESLint
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import { meetsWCAGStandard } from '../../src/lib/color-contrast';
|
||||
|
||||
interface ColorPair {
|
||||
name: string;
|
||||
foreground: string;
|
||||
background: string;
|
||||
textSize?: 'normal' | 'large';
|
||||
}
|
||||
|
||||
const criticalColorPairs: ColorPair[] = [
|
||||
{ name: 'Primary text on primary background', foreground: '#1C1C1C', background: '#FFFFFF' },
|
||||
{ name: 'Secondary text on primary background', foreground: '#3D3D3D', background: '#FFFFFF' },
|
||||
{ name: 'Tertiary text on primary background', foreground: '#4A4A4A', background: '#FFFFFF' },
|
||||
{ name: 'Muted text on primary background', foreground: '#6B6B6B', background: '#FFFFFF' },
|
||||
{ name: 'Brand primary on white', foreground: '#C41E3A', background: '#FFFFFF' },
|
||||
{ name: 'Brand primary on brand bg', foreground: '#C41E3A', background: '#FEF2F4' },
|
||||
{ name: 'Link on hover', foreground: '#C41E3A', background: '#FFFFFF' },
|
||||
];
|
||||
|
||||
function checkContrast() {
|
||||
console.log('🎨 Color Contrast Check\n');
|
||||
|
||||
let failures = 0;
|
||||
let passes = 0;
|
||||
|
||||
criticalColorPairs.forEach(pair => {
|
||||
const result = meetsWCAGStandard(
|
||||
pair.foreground,
|
||||
pair.background,
|
||||
'AA',
|
||||
pair.textSize || 'normal'
|
||||
);
|
||||
|
||||
const status = result.passes ? '✅ PASS' : '❌ FAIL';
|
||||
const ratio = result.ratio.toFixed(2);
|
||||
|
||||
console.log(`${status} ${pair.name}`);
|
||||
console.log(` Ratio: ${ratio}:1 (Required: ${result.requiredRatio}:1)`);
|
||||
console.log(` FG: ${pair.foreground} | BG: ${pair.background}\n`);
|
||||
|
||||
if (result.passes) {
|
||||
passes++;
|
||||
} else {
|
||||
failures++;
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`\n📊 Summary:`);
|
||||
console.log(` Total: ${criticalColorPairs.length}`);
|
||||
console.log(` ✅ Passes: ${passes}`);
|
||||
console.log(` ❌ Failures: ${failures}`);
|
||||
|
||||
if (failures > 0) {
|
||||
console.log('\n⚠️ Some color pairs do not meet WCAG AA standards!');
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log('\n✅ All color pairs meet WCAG AA standards!');
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
checkContrast();
|
||||
@@ -0,0 +1,26 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const coverageFilePath = path.join(__dirname, '..', 'coverage', 'coverage-final.json');
|
||||
|
||||
try {
|
||||
if (!fs.existsSync(coverageFilePath)) {
|
||||
console.error('Coverage file not found:', coverageFilePath);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const coverage = JSON.parse(fs.readFileSync(coverageFilePath, 'utf8'));
|
||||
|
||||
const metrics = {
|
||||
statements: coverage.total.statements.pct,
|
||||
branches: coverage.total.branches.pct,
|
||||
functions: coverage.total.functions.pct,
|
||||
lines: coverage.total.lines.pct,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
|
||||
console.log(JSON.stringify(metrics, null, 2));
|
||||
} catch (error) {
|
||||
console.error('Error reading coverage:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
console.log('🔍 验证Woodpecker CI配置...');
|
||||
|
||||
const configFiles = [
|
||||
'.woodpecker/test-tiered.yml',
|
||||
'.woodpecker/test-tiered-simple.yml',
|
||||
];
|
||||
|
||||
let allValid = true;
|
||||
|
||||
for (const configFile of configFiles) {
|
||||
const filePath = path.join(__dirname, '..', configFile);
|
||||
|
||||
if (!fs.existsSync(filePath)) {
|
||||
console.log(`❌ 配置文件不存在: ${configFile}`);
|
||||
allValid = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
const content = fs.readFileSync(filePath, 'utf-8');
|
||||
|
||||
if (content.includes('when:') && content.includes('pipeline:')) {
|
||||
console.log(`✅ ${configFile} - 配置格式正确`);
|
||||
} else {
|
||||
console.log(`❌ ${configFile} - 配置格式错误`);
|
||||
allValid = false;
|
||||
}
|
||||
|
||||
if (content.includes('TEST_TIER')) {
|
||||
console.log(`✅ ${configFile} - 包含分层测试环境变量`);
|
||||
} else {
|
||||
console.log(`❌ ${configFile} - 缺少分层测试环境变量`);
|
||||
allValid = false;
|
||||
}
|
||||
|
||||
if (content.includes('depends_on')) {
|
||||
console.log(`✅ ${configFile} - 包含任务依赖配置`);
|
||||
} else {
|
||||
console.log(`⚠️ ${configFile} - 未配置任务依赖`);
|
||||
}
|
||||
}
|
||||
|
||||
const reportScript = path.join(__dirname, '..', 'e2e/scripts/generate-report.js');
|
||||
if (fs.existsSync(reportScript)) {
|
||||
console.log(`✅ 测试报告脚本存在`);
|
||||
} else {
|
||||
console.log(`❌ 测试报告脚本不存在`);
|
||||
allValid = false;
|
||||
}
|
||||
|
||||
if (allValid) {
|
||||
console.log('\n✅ 所有配置验证通过');
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.log('\n❌ 部分配置验证失败');
|
||||
process.exit(1);
|
||||
}
|
||||
Reference in New Issue
Block a user