1import type { StackFrame } from 'stacktrace-parser'; 2 3export type MetroStackFrame = StackFrame & { collapse?: boolean }; 4 5export function formatProjectFilePath(projectRoot: string, file?: string | null): string { 6 if (file == null) { 7 return '<unknown>'; 8 } 9 10 return pathRelativeToPath(file.replace(/\\/g, '/'), projectRoot.replace(/\\/g, '/')).replace( 11 /\?.*$/, 12 '' 13 ); 14} 15 16function pathRelativeToPath(path: string, relativeTo: string, sep = '/') { 17 const relativeToParts = relativeTo.split(sep); 18 const pathParts = path.split(sep); 19 let i = 0; 20 while (i < relativeToParts.length && i < pathParts.length) { 21 if (relativeToParts[i] !== pathParts[i]) { 22 break; 23 } 24 i++; 25 } 26 return pathParts.slice(i).join(sep); 27} 28 29export function getStackFormattedLocation(projectRoot: string, frame: MetroStackFrame) { 30 const column = frame.column != null && parseInt(String(frame.column), 10); 31 const location = 32 formatProjectFilePath(projectRoot, frame.file) + 33 (frame.lineNumber != null 34 ? ':' + frame.lineNumber + (column && !isNaN(column) ? ':' + (column + 1) : '') 35 : ''); 36 37 return location; 38} 39