Files
orca/mobile/src/source-control/github-pr-link-parse.ts
T
c9bd61376f feat(mobile): combine PR sidebar and checks parity (#5641)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
2026-06-17 22:52:12 -07:00

47 lines
1.5 KiB
TypeScript

// Parses a GitHub PR/issue reference from user input — a bare number, "#42", or a
// full GitHub URL — mirroring the desktop parseGitHubIssueOrPRNumber
// (src/renderer/src/lib/github-links.ts). Ported (not imported) so the mobile bundle
// stays free of renderer modules. Returns null for anything unparseable; guards
// number > 0 so the link flow never persists PR #0.
const GH_ITEM_PATH_RE = /^\/([^/]+)\/([^/]+)\/(issues|pull)\/(\d+)(?:\/.*)?$/i
// Why: this parser is GitHub-specific (the link flow writes the worktree's
// GitHub linkedPR key), so only github.com / its enterprise subdomains may parse —
// otherwise `https://example.com/o/r/pull/7` would be mistaken for a GitHub PR.
function isGitHubHost(hostname: string): boolean {
const host = hostname.toLowerCase()
return host === 'github.com' || host.endsWith('.github.com')
}
export function parseGitHubPrReference(input: string): number | null {
const trimmed = input.trim()
if (!trimmed) {
return null
}
const numeric = trimmed.startsWith('#') ? trimmed.slice(1) : trimmed
if (/^\d+$/.test(numeric)) {
const n = Number.parseInt(numeric, 10)
return n > 0 ? n : null
}
let url: URL
try {
url = new URL(trimmed)
} catch {
return null
}
if (url.protocol !== 'https:' && url.protocol !== 'http:') {
return null
}
if (!isGitHubHost(url.hostname)) {
return null
}
const match = GH_ITEM_PATH_RE.exec(url.pathname.replace(/\/+$/, ''))
if (!match) {
return null
}
const n = Number.parseInt(match[4], 10)
return n > 0 ? n : null
}