UNPKG

ctrlshiftleft

Version:

AI-powered toolkit for embedding QA and security testing into development workflows

103 lines 3.81 kB
"use strict"; /** * Utilities for calculating and displaying diffs between files * Used for security change analysis in the watch command */ Object.defineProperty(exports, "__esModule", { value: true }); exports.diff = diff; exports.isSecuritySensitiveChange = isSecuritySensitiveChange; exports.highlightSecurityChanges = highlightSecurityChanges; /** * Compute diff between two strings * @param oldStr Previous string content * @param newStr New string content * @returns Array of diff changes */ function diff(oldStr, newStr) { if (oldStr === newStr) { return [{ value: newStr }]; } // Convert strings to arrays of lines const oldLines = oldStr.split('\n'); const newLines = newStr.split('\n'); const result = []; // Myers diff algorithm simplified for line-by-line comparison const MAX_EDIT_LENGTH = Math.max(oldLines.length, newLines.length); // Identify unchanged lines let i = 0; while (i < oldLines.length && i < newLines.length && oldLines[i] === newLines[i]) { i++; } if (i > 0) { // Add context of unchanged lines at the beginning (limited to a few lines) const contextLines = oldLines.slice(Math.max(0, i - 3), i); if (contextLines.length > 0) { result.push({ value: contextLines.join('\n') }); } } // Find trailing same lines let j = 0; while (oldLines.length - j - 1 >= 0 && newLines.length - j - 1 >= 0 && oldLines[oldLines.length - j - 1] === newLines[newLines.length - j - 1] && oldLines.length - j - 1 > i && newLines.length - j - 1 > i) { j++; } // Add removed lines if (i < oldLines.length - j) { const removedLines = oldLines.slice(i, oldLines.length - j); result.push({ value: removedLines.join('\n'), removed: true }); } // Add added lines if (i < newLines.length - j) { const addedLines = newLines.slice(i, newLines.length - j); result.push({ value: addedLines.join('\n'), added: true }); } // Add unchanged lines at the end for context if (j > 0) { const contextLines = oldLines.slice(oldLines.length - Math.min(j, 3), oldLines.length); if (contextLines.length > 0) { result.push({ value: contextLines.join('\n') }); } } return result; } /** * Check if a line contains security-sensitive changes * @param line Line of code to check * @returns Whether line contains security-sensitive keywords */ function isSecuritySensitiveChange(line) { const securityKeywords = [ 'auth', 'password', 'token', 'secret', 'key', 'credential', 'encrypt', 'decrypt', 'hash', 'salt', 'security', 'permission', 'XSS', 'CSRF', 'SQL', 'injection', 'sanitize', 'validate', 'CORS', 'header', 'certificate', 'SSL', 'TLS', 'HTTPS' ]; const lowerLine = line.toLowerCase(); return securityKeywords.some(keyword => lowerLine.includes(keyword.toLowerCase())); } /** * Highlight security-sensitive changes in diff output * @param changes Diff changes to analyze * @returns Formatted string with highlighted security changes */ function highlightSecurityChanges(changes) { let highlightedOutput = ''; for (const change of changes) { const lines = change.value.split('\n'); for (const line of lines) { const isSecurityLine = isSecuritySensitiveChange(line); const indicator = change.added ? '+' : change.removed ? '-' : ' '; if (isSecurityLine) { highlightedOutput += `🔒 ${indicator} ${line}\n`; } else { highlightedOutput += `${indicator} ${line}\n`; } } } return highlightedOutput; } //# sourceMappingURL=diffUtils.js.map