fb63a88cd1
Co-authored-by: Kandev Agent <agent@kandev.dev>
71 lines
2.4 KiB
TypeScript
71 lines
2.4 KiB
TypeScript
import { createTwoFilesPatch } from "diff";
|
|
|
|
import { djb2Hash } from "./hash";
|
|
import { t } from "@/lib/i18n";
|
|
|
|
/**
|
|
* Generate a unified diff between original and modified content
|
|
* @param original - Original file content
|
|
* @param modified - Modified file content
|
|
* @param filename - File name (used in diff header)
|
|
* @returns Unified diff string
|
|
*/
|
|
export function generateUnifiedDiff(original: string, modified: string, filename: string): string {
|
|
// createTwoFilesPatch generates a unified diff with headers
|
|
// Parameters: oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options
|
|
// Note: oldHeader and newHeader should be empty strings or valid timestamps
|
|
// The go-diff library on the backend expects standard unified diff format
|
|
const diff = createTwoFilesPatch(
|
|
filename,
|
|
filename,
|
|
original,
|
|
modified,
|
|
"", // Empty oldHeader - backend doesn't need timestamps
|
|
"", // Empty newHeader - backend doesn't need timestamps
|
|
{ context: 3 }, // Number of context lines
|
|
);
|
|
|
|
return diff;
|
|
}
|
|
|
|
/**
|
|
* Calculate hash of content for change detection.
|
|
* Uses Web Crypto API (SHA-256) in secure contexts (HTTPS, localhost).
|
|
* Falls back to djb2 in non-secure contexts (HTTP) — sufficient for detecting
|
|
* content changes, not for security purposes.
|
|
* @param content - Content to hash
|
|
* @returns Hex-encoded hash string
|
|
*/
|
|
export async function calculateHash(content: string): Promise<string> {
|
|
// crypto.subtle is only available in secure contexts (HTTPS, localhost)
|
|
if (typeof crypto !== "undefined" && crypto.subtle) {
|
|
try {
|
|
const encoder = new TextEncoder();
|
|
const data = encoder.encode(content);
|
|
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
} catch {
|
|
// Fall through to djb2
|
|
}
|
|
}
|
|
return djb2Hash(content);
|
|
}
|
|
|
|
/**
|
|
* Format diff stats for display
|
|
* @param additions - Number of additions
|
|
* @param deletions - Number of deletions
|
|
* @returns Formatted string like "+5 -3"
|
|
*/
|
|
export function formatDiffStats(additions: number, deletions: number): string {
|
|
const parts: string[] = [];
|
|
if (additions > 0) {
|
|
parts.push(`+${additions}`);
|
|
}
|
|
if (deletions > 0) {
|
|
parts.push(`-${deletions}`);
|
|
}
|
|
return parts.join(" ") || t("task:noChanges");
|
|
}
|