(entry: StackTraceEntry)
| 142 | } |
| 143 | |
| 144 | export function getSourceCodeFrame(entry: StackTraceEntry): string | null { |
| 145 | if (!entry.source || !entry.sourceMap) { |
| 146 | return null; |
| 147 | } |
| 148 | const source = entry.sourceMap.sourceContentFor(entry.source, true); |
| 149 | if (!source) { |
| 150 | return null; |
| 151 | } |
| 152 | |
| 153 | const {line, column} = entry; |
| 154 | const lastLine = line + 2; |
| 155 | const spacing = lastLine.toString().length; |
| 156 | const language = getExtension(entry.source) ?? 'ts'; |
| 157 | |
| 158 | const code = highlight |
| 159 | .highlight(source, {language}) |
| 160 | .value.split('\n') |
| 161 | .slice(line - 1, lastLine); |
| 162 | |
| 163 | const formatted = code.map( |
| 164 | (text, index) => |
| 165 | `${(line + index).toString().padStart(spacing, ' ')} | ${text}`, |
| 166 | ); |
| 167 | formatted.splice(1, 0, `${' '.repeat(spacing)} | ${' '.repeat(column)}^`); |
| 168 | return formatted.join('\n'); |
| 169 | } |
| 170 | |
| 171 | export async function findAndOpenFirstUserFile(stack: string) { |
| 172 | const entry = await resolveStackTrace(stack, true); |
no test coverage detected