(url: string)
| 450 | * Normalizes a repository URL to a standard format. |
| 451 | */ |
| 452 | export function normalizeRepositoryUrl(url: string): string { |
| 453 | let normalized = url.toLowerCase().trim() |
| 454 | |
| 455 | // Remove .git suffix |
| 456 | if (normalized.endsWith('.git')) { |
| 457 | normalized = normalized.slice(0, -4) |
| 458 | } |
| 459 | |
| 460 | // Convert SSH to HTTPS |
| 461 | if (normalized.startsWith('git@github.com:')) { |
| 462 | normalized = normalized.replace('git@github.com:', 'https://github.com/') |
| 463 | } |
| 464 | |
| 465 | // Ensure https:// prefix for github URLs |
| 466 | if (!normalized.startsWith('http') && normalized.includes('github.com')) { |
| 467 | normalized = 'https://' + normalized |
| 468 | } |
| 469 | |
| 470 | // Parse URL to extract base repository URL (strip extra paths like /pull/123/files) |
| 471 | try { |
| 472 | const urlObj = new URL(normalized) |
| 473 | const pathSegments = urlObj.pathname |
| 474 | .split('/') |
| 475 | .filter((segment) => segment.length > 0) |
| 476 | |
| 477 | // For known Git hosting providers, only keep the first two path segments (owner/repo) |
| 478 | const knownHosts = ['github.com', 'gitlab.com', 'bitbucket.org'] |
| 479 | if (knownHosts.includes(urlObj.hostname) && pathSegments.length >= 2) { |
| 480 | // Reconstruct URL with only owner/repo path |
| 481 | const basePath = `/${pathSegments[0]}/${pathSegments[1]}` |
| 482 | normalized = `${urlObj.protocol}//${urlObj.hostname}${basePath}` |
| 483 | } |
| 484 | } catch (error) { |
| 485 | // If URL parsing fails, return the normalized string as-is |
| 486 | // This maintains backward compatibility |
| 487 | } |
| 488 | |
| 489 | return normalized |
| 490 | } |
| 491 | |
| 492 | /** |
| 493 | * Validates and normalizes a repository URL. |
no outgoing calls
no test coverage detected