import { readFileSync } from 'fs';
import { parseComponent } from '../parsers/jsx-parser.js';
import { compareComponents } from '../diff/component-diff.js';
import type { ComparisonResult } from '../types/index.js';
export interface CompareInput {
oldFile: string;
newFile: string;
}
export function compareComponentFiles(input: CompareInput): ComparisonResult {
const { oldFile, newFile } = input;
// Read both files
const oldCode = readFileSync(oldFile, 'utf-8');
const newCode = readFileSync(newFile, 'utf-8');
// Parse both components
const oldComponent = parseComponent(oldCode, oldFile);
const newComponent = parseComponent(newCode, newFile);
// Compare and return result
return compareComponents(oldComponent, newComponent);
}
export function formatComparisonResult(result: ComparisonResult): string {
const lines: string[] = [];
lines.push(`# Component Comparison`);
lines.push('');
lines.push(`**Summary:** ${result.summary}`);
lines.push('');
// Text changes
if (result.changes.text.length > 0) {
lines.push('## Text Changes');
for (const change of result.changes.text) {
const icon = change.type === 'added' ? '➕' : change.type === 'removed' ? '➖' : '✏️';
lines.push(`${icon} **${change.location}**`);
if (change.oldText) lines.push(` Old: "${change.oldText}"`);
if (change.newText) lines.push(` New: "${change.newText}"`);
}
lines.push('');
}
// Child component changes
if (result.changes.children.length > 0) {
lines.push('## Child Component Changes');
for (const change of result.changes.children) {
const icon = change.type === 'added' ? '➕' : change.type === 'removed' ? '➖' : '✏️';
lines.push(`${icon} **<${change.componentName}>** at ${change.location}`);
if (change.props && change.props.length > 0) {
for (const prop of change.props) {
const propIcon = prop.type === 'added' ? '+' : prop.type === 'removed' ? '-' : '~';
lines.push(` ${propIcon} ${prop.name}: ${prop.oldValue ?? 'none'} → ${prop.newValue ?? 'none'}`);
}
}
}
lines.push('');
}
// Prop changes
if (result.changes.props.length > 0) {
lines.push('## Root Prop Changes');
for (const change of result.changes.props) {
const icon = change.type === 'added' ? '➕' : change.type === 'removed' ? '➖' : '✏️';
lines.push(`${icon} **${change.name}**: ${change.oldValue ?? 'none'} → ${change.newValue ?? 'none'}`);
}
lines.push('');
}
// Style changes - Colors
if (result.changes.styles.colors.length > 0) {
lines.push('## Color Changes');
for (const change of result.changes.styles.colors) {
const icon = change.type === 'added' ? '➕' : change.type === 'removed' ? '➖' : '✏️';
lines.push(`${icon} **${change.property}**: ${change.oldValue ?? 'none'} → ${change.newValue ?? 'none'}`);
}
lines.push('');
}
// Style changes - Spacing
if (result.changes.styles.spacing.length > 0) {
lines.push('## Spacing Changes');
for (const change of result.changes.styles.spacing) {
const icon = change.type === 'added' ? '➕' : change.type === 'removed' ? '➖' : '✏️';
lines.push(`${icon} **${change.property}**: ${change.oldValue ?? 'none'} → ${change.newValue ?? 'none'}`);
}
lines.push('');
}
// Style changes - Typography
if (result.changes.styles.typography.length > 0) {
lines.push('## Typography Changes');
for (const change of result.changes.styles.typography) {
const icon = change.type === 'added' ? '➕' : change.type === 'removed' ? '➖' : '✏️';
lines.push(`${icon} **${change.property}**: ${change.oldValue ?? 'none'} → ${change.newValue ?? 'none'}`);
}
lines.push('');
}
return lines.join('\n');
}