agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
158 lines (139 loc) • 5.31 kB
JavaScript
/**
* @file Project-wide UI/UX analyzer for comprehensive user experience assessment
* @description Single responsibility: Coordinate UI problem detection across entire frontend projects
*
* This analyzer orchestrates comprehensive UI/UX analysis across entire projects,
* identifying systematic user interface problems, design inconsistencies, and usability
* issues that impact user experience at scale. It provides project-level UI quality
* metrics and strategic recommendations for improving user experience consistency.
*
* Design rationale:
* - Project-wide analysis identifies systematic UI patterns and consistency issues
* - Frontend-focused file filtering targets relevant UI components and pages
* - Issue aggregation reveals project-wide UI problems requiring systematic solutions
* - Scoring system provides quantitative UI quality assessment for tracking improvements
* - Strategic recommendations prioritize UI improvements for maximum user experience impact
*
* UI analysis scope:
* - Cross-component UI consistency and design pattern adherence
* - Project-wide accessibility issues and compliance gaps
* - Systematic styling problems and maintainability concerns
* - User experience flow issues and interaction patterns
* - Performance-impacting UI patterns affecting user satisfaction
*/
const fs = require('fs');
const path = require('path');
const { analyzeFileUIProblems } = require('./uiFileAnalyzer');
const { getAllUIFiles } = require('./uiFileCollector');
/**
* Generate project-level UI recommendations
* @param {Array} allIssues - All UI issues from files
* @returns {Array} Project recommendations
*/
function generateProjectRecommendations(allIssues) {
const recommendations = [];
if (allIssues.length === 0) {
recommendations.push({
priority: 'low',
type: 'maintenance',
description: 'No UI issues detected - maintain current standards'
});
return recommendations;
}
// Group issues by type
const issuesByType = {};
allIssues.forEach(issue => {
if (!issuesByType[issue.type]) issuesByType[issue.type] = [];
issuesByType[issue.type].push(issue);
});
// Generate recommendations based on issue patterns
Object.keys(issuesByType).forEach(type => {
const issues = issuesByType[type];
if (type === 'ambiguous_labels' && issues.length > 2) {
recommendations.push({
priority: 'high',
type: 'accessibility',
description: `Address ${issues.length} ambiguous labels to improve accessibility and UX`
});
}
if (type === 'inconsistent_icons' && issues.length > 0) {
recommendations.push({
priority: 'medium',
type: 'design_consistency',
description: 'Standardize icon library usage across the project'
});
}
if (type === 'excessive_inline_styles' && issues.length > 1) {
recommendations.push({
priority: 'medium',
type: 'maintainability',
description: 'Move inline styles to CSS classes for better maintainability'
});
}
});
return recommendations;
}
/**
* Analyze UI problems across a project
* @param {string} projectPath - Project directory path
* @param {Object} options - Analysis options
* @returns {Object} Project UI analysis results
*/
async function analyzeProjectUIProblems(projectPath, options = {}) {
const {
extensions = ['.js', '.jsx', '.ts', '.tsx', '.vue'],
excludePatterns = ['node_modules', '.git', 'dist', 'build']
} = options;
try {
const files = await getAllUIFiles(projectPath, extensions, excludePatterns);
const fileAnalyses = [];
const allIssues = [];
let totalScore = 0;
let criticalIssues = 0;
for (let i = 0; i < files.length; i++) {
const file = files[i];
try {
const analysis = await analyzeFileUIProblems(file);
fileAnalyses.push(analysis);
allIssues.push(...analysis.issues);
totalScore += analysis.uiScore;
criticalIssues += analysis.metrics?.criticalIssues || 0;
} catch (error) {
console.warn(`Warning: Could not analyze ${file}`);
}
}
const averageScore = files.length > 0 ? Math.round(totalScore / files.length) : 100;
return {
summary: {
totalFiles: files.length,
issuesFound: allIssues.length,
criticalIssues,
uiScore: averageScore,
totalEffort: allIssues.length * 2 // Estimated effort
},
files: fileAnalyses,
issues: allIssues,
recommendations: generateProjectRecommendations(allIssues)
};
} catch (error) {
console.error(`UI Problems project analysis failed: ${error.message}`);
throw new Error(`UI Problems analysis failed: ${error.message}`);
}
}
function generateProjectRecommendations(issues) {
const groupedIssues = {};
for (let i = 0; i < issues.length; i++) {
const issue = issues[i];
groupedIssues[issue.type] = (groupedIssues[issue.type] || 0) + 1;
}
return Object.entries(groupedIssues).map(([type, count]) => ({
type,
count,
priority: 'MEDIUM',
recommendation: `Address ${count} instances of ${type} across the project`
}));
}
module.exports = {
analyzeProjectUIProblems,
generateProjectRecommendations
};