mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 18:17:36 +00:00
* fix(mobile): open wrapped terminal urls and paths with desktop's link detection Desktop's terminal URL and file-link detectors move to src/shared and the phone's WebView document calls them, replacing its single-row copies. File taps carry every reading of the tapped text so the phone opens the longest one the host finds, as desktop does. * fix(mobile): keep the unc host of osc 8 file links for the host to resolve * fix(mobile): resolve terminal file-tap readings a few at a time A tap inside a run of path rows yields hundreds of hard-wrap guesses; firing them all at once overflowed the page bridge's pending-request cap and the real path was never checked. * refactor(terminal): share the osc 8 link classifier and trim file-tap plumbing Desktop and the phone now read OSC 8 targets through one shared classifier. Terminal file taps carry only their candidate list, deduped by path, and desktop checks OSC overlap only for candidates it can resolve. * refactor(terminal): keep shared link files under the line cap The xterm buffer subset gets its own module, and the text-only OSC resolver goes now that the router uses findExactTerminalFileLink.
79 lines
2.2 KiB
TypeScript
79 lines
2.2 KiB
TypeScript
import { parseFileLinkLocation, type ParsedFileLinkLocation } from './file-link-location'
|
|
import {
|
|
joinAbsolutePath,
|
|
normalizeAbsolutePath,
|
|
resolveTildePath
|
|
} from './terminal-path-normalization'
|
|
|
|
export type ParsedExplicitFileLinkTarget = ParsedFileLinkLocation
|
|
|
|
export type ResolvedExplicitFileLinkTarget = Pick<
|
|
ParsedExplicitFileLinkTarget,
|
|
'line' | 'column'
|
|
> & {
|
|
absolutePath: string
|
|
}
|
|
|
|
type ParseExplicitFileLinkTargetOptions = {
|
|
allowRelativeDirectoryPath?: boolean
|
|
}
|
|
|
|
function canKeepTrailingSeparator(pathText: string): boolean {
|
|
// Bare roots are ambiguous link targets; absolute/tilde paths need a real segment to identify directories.
|
|
if (/^[\\/]+$/.test(pathText) || /^~[\\/]$/.test(pathText) || /^[A-Za-z]:[\\/]$/.test(pathText)) {
|
|
return false
|
|
}
|
|
return /^(?:~[\\/]|[\\/]|[A-Za-z]:[\\/])/.test(pathText)
|
|
}
|
|
|
|
export function parseExplicitFileLinkTarget(
|
|
value: string,
|
|
options: ParseExplicitFileLinkTargetOptions = {}
|
|
): ParsedExplicitFileLinkTarget | null {
|
|
const parsed = parseFileLinkLocation(value)
|
|
if (!parsed) {
|
|
return null
|
|
}
|
|
const { pathText, line, column } = parsed
|
|
const hasLineOrColumn = line !== null || column !== null
|
|
if (/^[\\/]\s/.test(pathText)) {
|
|
return null
|
|
}
|
|
if (/[\\/]$/.test(pathText)) {
|
|
const canKeepRelativeDirectory = options.allowRelativeDirectoryPath === true && !hasLineOrColumn
|
|
if (hasLineOrColumn || (!canKeepRelativeDirectory && !canKeepTrailingSeparator(pathText))) {
|
|
return null
|
|
}
|
|
}
|
|
|
|
return { pathText, line, column }
|
|
}
|
|
|
|
export function resolveExplicitFileLinkTargetPath(
|
|
pathText: string,
|
|
cwd: string,
|
|
homePath?: string | null
|
|
): string | null {
|
|
if (/^~[\\/]/.test(pathText)) {
|
|
return resolveTildePath(pathText, cwd, homePath)
|
|
}
|
|
return normalizeAbsolutePath(pathText)?.normalized ?? joinAbsolutePath(cwd, pathText)
|
|
}
|
|
|
|
export function resolveExplicitFileLinkTarget(
|
|
parsed: ParsedExplicitFileLinkTarget,
|
|
cwd: string,
|
|
homePath?: string | null
|
|
): ResolvedExplicitFileLinkTarget | null {
|
|
const absolutePath = resolveExplicitFileLinkTargetPath(parsed.pathText, cwd, homePath)
|
|
if (!absolutePath) {
|
|
return null
|
|
}
|
|
|
|
return {
|
|
absolutePath,
|
|
line: parsed.line,
|
|
column: parsed.column
|
|
}
|
|
}
|