feat(app): support file:// protocol URLs for opening workspace files
This commit is contained in:
@@ -5,6 +5,8 @@ export interface InlinePathTarget {
|
||||
lineEnd?: number;
|
||||
}
|
||||
|
||||
const FILE_PROTOCOL = "file:";
|
||||
|
||||
function normalizePathToken(value: string): string | null {
|
||||
const trimmed = value
|
||||
.trim()
|
||||
@@ -79,3 +81,64 @@ export function parseInlinePathToken(value: string): InlinePathTarget | null {
|
||||
};
|
||||
}
|
||||
|
||||
export function parseFileProtocolUrl(value: string): InlinePathTarget | null {
|
||||
const trimmed = value?.trim();
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let parsedUrl: URL;
|
||||
try {
|
||||
parsedUrl = new URL(trimmed);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parsedUrl.protocol !== FILE_PROTOCOL) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const normalizedPath = normalizeFileUrlPath(parsedUrl.pathname);
|
||||
if (!normalizedPath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const rawFragment = parsedUrl.hash.startsWith("#")
|
||||
? parsedUrl.hash.slice(1)
|
||||
: parsedUrl.hash;
|
||||
const lineMatch = rawFragment.match(/^L([0-9]+)(?:-L?([0-9]+))?$/i);
|
||||
const lineStart = lineMatch?.[1] ? parseInt(lineMatch[1], 10) : undefined;
|
||||
const lineEnd = lineMatch?.[2] ? parseInt(lineMatch[2], 10) : undefined;
|
||||
|
||||
if (
|
||||
(lineStart !== undefined && (!Number.isFinite(lineStart) || lineStart <= 0)) ||
|
||||
(lineEnd !== undefined && (!Number.isFinite(lineEnd) || lineEnd <= 0)) ||
|
||||
(lineStart !== undefined && lineEnd !== undefined && lineEnd < lineStart)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
raw: value,
|
||||
path: normalizedPath,
|
||||
lineStart,
|
||||
lineEnd,
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeFileUrlPath(pathname: string): string | null {
|
||||
if (!pathname) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const decoded = decodeURIComponent(pathname).replace(/\\/g, "/");
|
||||
if (!decoded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (/^\/[A-Za-z]:\//.test(decoded)) {
|
||||
return decoded.slice(1);
|
||||
}
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user