Files
fusion/packages/dashboard/app/utils/highlightDiff.tsx
gsxdsm fa096cf518 feat(FN-683): add diff syntax highlighting with background colors
- Add highlightDiff utility React component for diff rendering
- Add CSS styles for diff-add (green), diff-del (red), diff-hunk (blue) line highlighting
- Integrate highlightDiff in TaskChangesTab for inline diffs
- Integrate highlightDiff in ChangedFilesModal for file diffs
- Add unit tests for highlightDiff utility
2026-04-02 09:58:04 -07:00

43 lines
1.4 KiB
TypeScript

import React from "react";
/**
* Highlights diff output by wrapping each line in a <span> with appropriate CSS classes.
*
* - Lines starting with `+` (but not `+++`) → class `diff-add`
* - Lines starting with `-` (but not `---`) → class `diff-del`
* - Lines starting with `@@` → class `diff-hunk`
* - Context lines and other diff headers → no special class
*
* @param diff - The raw diff string to highlight
* @returns An array of React nodes with appropriate span wrappers
*/
export function highlightDiff(diff: string): React.ReactNode[] {
const lines = diff.split("\n");
return lines.map((line, index) => {
// Determine the class for this line based on its prefix
let className = "";
if (line.startsWith("+") && !line.startsWith("+++")) {
className = "diff-add";
} else if (line.startsWith("-") && !line.startsWith("---")) {
className = "diff-del";
} else if (line.startsWith("@@")) {
className = "diff-hunk";
}
// Wrap in a span if we have a class, otherwise return the line as-is
if (className) {
return (
<span key={index} className={className}>
{`${line}\n`}
</span>
);
}
// For lines without special classes, we still need to add the newline
// We use a fragment to avoid unnecessary wrapper elements
return <React.Fragment key={index}>{`${line}\n`}</React.Fragment>;
});
}