Files
orca/src/shared/file-link-location.ts
T
Brennan Benson 845db9e5e2 fix(native-chat): underline only file links a click can act on (#22370)
* fix(native-chat): underline only file links a click can act on

A chat message could underline a bare file name such as `deck.md` that
resolved nowhere, and clicking it did nothing, so it read as a broken link.

- Inline code and quoted text become file links only when they name a path
  (contain a `/` or `\`), matching plain prose; a bare file name stays plain code.
- Every file link click now answers: it opens, or says the file was not found,
  that the host could not be checked, or that the path could not be resolved.
- Explicit links like [x](README.md:5) route as files, and linked text keeps
  `#`, `?` and `%XX` literally instead of re-parsing them as URL syntax.

* fix(native-chat): wrap the parsed file location so file URIs in chat text still open

Linkified prose, quoted text and inline code wrapped their display text, which the
literal wrapped-href route no longer URL-parses, so file:///... resolved as a relative
path under the worktree. Wrap pathText[:line[:col]] from the parsed link instead.
2026-09-23 13:29:24 -07:00

33 lines
993 B
TypeScript

export type ParsedFileLinkLocation = {
pathText: string
line: number | null
column: number | null
}
export function parseFileLinkLocation(value: string): ParsedFileLinkLocation | null {
const match = /^(.*?)(?::(\d+))?(?::(\d+))?$/.exec(value)
const pathText = match?.[1]
if (!pathText) {
return null
}
const line = match[2] ? Number.parseInt(match[2], 10) : null
const column = match[3] ? Number.parseInt(match[3], 10) : null
if ((line !== null && line < 1) || (column !== null && column < 1)) {
return null
}
return { pathText, line, column }
}
/** Inverse of `parseFileLinkLocation`: `path`, `path:line`, or `path:line:column`. */
export function formatFileLinkLocation(location: {
pathText: string
line: number | null
column?: number | null
}): string {
if (location.line === null) {
return location.pathText
}
const column = location.column == null ? '' : `:${location.column}`
return `${location.pathText}:${location.line}${column}`
}