diff --git a/src/services/htmlLinks.ts b/src/services/htmlLinks.ts index 7880189..6f1833a 100644 --- a/src/services/htmlLinks.ts +++ b/src/services/htmlLinks.ts @@ -71,21 +71,26 @@ function createLink(document: TextDocument, documentContext: DocumentContext, at if (!workspaceUrl) { return undefined; } - const target = validateAndCleanURI(workspaceUrl); - - + const target = validateAndCleanURI(workspaceUrl, document); + return { range: Range.create(document.positionAt(startOffset), document.positionAt(endOffset)), target }; } -function validateAndCleanURI(uriStr: string) : string | undefined { +const _hash = '#'.charCodeAt(0); + +function validateAndCleanURI(uriStr: string, document: TextDocument): string | undefined { try { - const uri = Uri.parse(uriStr); + let uri = Uri.parse(uriStr); if (uri.scheme === 'file' && uri.query) { // see https://github.com/microsoft/vscode/issues/194577 & https://github.com/microsoft/vscode/issues/206238 - return uri.with({ query: null }).toString(/* skipEncodig*/ true); + uri = uri.with({ query: null }); + uriStr = uri.toString(/* skipEncodig*/ true); + } + if (uri.scheme === 'file' && uri.fragment && !(uriStr.startsWith(document.uri) && uriStr.charCodeAt(document.uri.length) === _hash)) { + return uri.with({ fragment: null }).toString(/* skipEncodig*/ true); } return uriStr; } catch (e) { @@ -154,6 +159,8 @@ export class HTMLDocumentLinks { if (offset !== undefined) { const pos = document.positionAt(offset); link.target = `${localWithHash}${pos.line + 1},${pos.character + 1}`; + } else { + link.target = document.uri; } } } diff --git a/src/test/links.test.ts b/src/test/links.test.ts index 48d78a6..6e3c2d9 100644 --- a/src/test/links.test.ts +++ b/src/test/links.test.ts @@ -34,7 +34,7 @@ suite('HTML Link Detection', () => { test('Link creation', () => { testLinkCreation('http://model/1.html', 'javascript:void;', null); testLinkCreation('http://model/1.html', ' \tjavascript:alert(7);', null); - testLinkCreation('http://model/1.html', ' #relative', 'http://model/1.html#relative'); + testLinkCreation('http://model/1.html', ' #relative', 'http://model/1.html'); testLinkCreation('http://model/1.html', 'file:///C:\\Alex\\src\\path\\to\\file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt'); testLinkCreation('http://model/1.html', 'http://www.microsoft.com/', 'http://www.microsoft.com/'); testLinkCreation('http://model/1.html', 'https://www.microsoft.com/', 'https://www.microsoft.com/'); @@ -46,7 +46,7 @@ suite('HTML Link Detection', () => { testLinkCreation('file:///C:/Alex/src/path/to/file.html', 'javascript:void;', null); testLinkCreation('file:///C:/Alex/src/path/to/file.html', ' \tjavascript:alert(7);', null); - testLinkCreation('file:///C:/Alex/src/path/to/file.html', ' #relative', 'file:///C:/Alex/src/path/to/file.html#relative'); + testLinkCreation('file:///C:/Alex/src/path/to/file.html', ' #relative', 'file:///C:/Alex/src/path/to/file.html'); testLinkCreation('file:///C:/Alex/src/path/to/file.html', 'file:///C:\\Alex\\src\\path\\to\\file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt'); testLinkCreation('file:///C:/Alex/src/path/to/file.html', 'http://www.microsoft.com/', 'http://www.microsoft.com/'); testLinkCreation('file:///C:/Alex/src/path/to/file.html', 'https://www.microsoft.com/', 'https://www.microsoft.com/'); @@ -89,11 +89,13 @@ suite('HTML Link Detection', () => { testLinkDetection('
', [{ offset: 18, length: 7, target: 'file:///test/data/abc/foo.png' }]); testLinkDetection('