| 433 | } |
| 434 | |
| 435 | export function generateCodeFrame( |
| 436 | source: string, |
| 437 | indent = 0, |
| 438 | loc: { line: number; column: number } | number, |
| 439 | range = 2, |
| 440 | ): string { |
| 441 | const start |
| 442 | = typeof loc === 'object' |
| 443 | ? positionToOffset(source, loc.line, loc.column) |
| 444 | : loc |
| 445 | const end = start |
| 446 | const lines = source.split(lineSplitRE) |
| 447 | const nl = /\r\n/.test(source) ? 2 : 1 |
| 448 | let count = 0 |
| 449 | let res: string[] = [] |
| 450 | |
| 451 | const columns = process.stdout?.columns || 80 |
| 452 | |
| 453 | for (let i = 0; i < lines.length; i++) { |
| 454 | count += lines[i].length + nl |
| 455 | if (count >= start) { |
| 456 | for (let j = i - range; j <= i + range || end > count; j++) { |
| 457 | if (j < 0 || j >= lines.length) { |
| 458 | continue |
| 459 | } |
| 460 | |
| 461 | const lineLength = lines[j].length |
| 462 | const strippedContent = stripVTControlCharacters(lines[j]) |
| 463 | |
| 464 | if (strippedContent.startsWith('//# sourceMappingURL')) { |
| 465 | continue |
| 466 | } |
| 467 | |
| 468 | // too long, maybe it's a minified file, skip for codeframe |
| 469 | if (strippedContent.length > 200) { |
| 470 | return '' |
| 471 | } |
| 472 | |
| 473 | const truncatedLine = truncateString(lines[j].replace(/\t/g, ' '), columns - 5 - indent).trimEnd() |
| 474 | res.push(lineNo(j + 1) + (truncatedLine ? ' ' + truncatedLine : truncatedLine)) |
| 475 | |
| 476 | if (j === i) { |
| 477 | // push underline |
| 478 | const pad = start - (count - lineLength) + (nl - 1) |
| 479 | const length = Math.max( |
| 480 | 1, |
| 481 | end > count ? lineLength - pad : end - start, |
| 482 | ) |
| 483 | res.push(lineNo() + ' '.repeat(pad + 1) + c.red('^'.repeat(length))) |
| 484 | } |
| 485 | else if (j > i) { |
| 486 | if (end > count) { |
| 487 | const length = Math.max(1, Math.min(end - count, lineLength)) |
| 488 | res.push(lineNo() + ' ' + c.red('^'.repeat(length))) |
| 489 | } |
| 490 | count += lineLength + 1 |
| 491 | } |
| 492 | } |