Skip to content

Commit 6760ddb

Browse files
authored
Links with fragment can't be Ctrl+clicked (#180)
1 parent 6b384d3 commit 6760ddb

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

src/services/htmlLinks.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,21 +71,26 @@ function createLink(document: TextDocument, documentContext: DocumentContext, at
7171
if (!workspaceUrl) {
7272
return undefined;
7373
}
74-
const target = validateAndCleanURI(workspaceUrl);
75-
76-
74+
const target = validateAndCleanURI(workspaceUrl, document);
75+
7776
return {
7877
range: Range.create(document.positionAt(startOffset), document.positionAt(endOffset)),
7978
target
8079
};
8180
}
8281

83-
function validateAndCleanURI(uriStr: string) : string | undefined {
82+
const _hash = '#'.charCodeAt(0);
83+
84+
function validateAndCleanURI(uriStr: string, document: TextDocument): string | undefined {
8485
try {
85-
const uri = Uri.parse(uriStr);
86+
let uri = Uri.parse(uriStr);
8687
if (uri.scheme === 'file' && uri.query) {
8788
// see https://github.com/microsoft/vscode/issues/194577 & https://github.com/microsoft/vscode/issues/206238
88-
return uri.with({ query: null }).toString(/* skipEncodig*/ true);
89+
uri = uri.with({ query: null });
90+
uriStr = uri.toString(/* skipEncodig*/ true);
91+
}
92+
if (uri.scheme === 'file' && uri.fragment && !(uriStr.startsWith(document.uri) && uriStr.charCodeAt(document.uri.length) === _hash)) {
93+
return uri.with({ fragment: null }).toString(/* skipEncodig*/ true);
8994
}
9095
return uriStr;
9196
} catch (e) {
@@ -154,6 +159,8 @@ export class HTMLDocumentLinks {
154159
if (offset !== undefined) {
155160
const pos = document.positionAt(offset);
156161
link.target = `${localWithHash}${pos.line + 1},${pos.character + 1}`;
162+
} else {
163+
link.target = document.uri;
157164
}
158165
}
159166
}

src/test/links.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ suite('HTML Link Detection', () => {
3434
test('Link creation', () => {
3535
testLinkCreation('http://model/1.html', 'javascript:void;', null);
3636
testLinkCreation('http://model/1.html', ' \tjavascript:alert(7);', null);
37-
testLinkCreation('http://model/1.html', ' #relative', 'http://model/1.html#relative');
37+
testLinkCreation('http://model/1.html', ' #relative', 'http://model/1.html');
3838
testLinkCreation('http://model/1.html', 'file:///C:\\Alex\\src\\path\\to\\file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt');
3939
testLinkCreation('http://model/1.html', 'http://www.microsoft.com/', 'http://www.microsoft.com/');
4040
testLinkCreation('http://model/1.html', 'https://www.microsoft.com/', 'https://www.microsoft.com/');
@@ -46,7 +46,7 @@ suite('HTML Link Detection', () => {
4646

4747
testLinkCreation('file:///C:/Alex/src/path/to/file.html', 'javascript:void;', null);
4848
testLinkCreation('file:///C:/Alex/src/path/to/file.html', ' \tjavascript:alert(7);', null);
49-
testLinkCreation('file:///C:/Alex/src/path/to/file.html', ' #relative', 'file:///C:/Alex/src/path/to/file.html#relative');
49+
testLinkCreation('file:///C:/Alex/src/path/to/file.html', ' #relative', 'file:///C:/Alex/src/path/to/file.html');
5050
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');
5151
testLinkCreation('file:///C:/Alex/src/path/to/file.html', 'http://www.microsoft.com/', 'http://www.microsoft.com/');
5252
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', () => {
8989
testLinkDetection('<blockquote cite="foo.png">', [{ offset: 18, length: 7, target: 'file:///test/data/abc/foo.png' }]);
9090
testLinkDetection('<style src="styles.css?t=345">', [{ offset: 12, length: 16, target: 'file:///test/data/abc/styles.css' }]);
9191
testLinkDetection('<a href="https://werkenvoor.be/nl/jobs?f%5B0%5D=activitydomains%3A115&f%5B1%5D=lang%3Anl">link</a>', [{ offset: 9, length: 79, target: 'https://werkenvoor.be/nl/jobs?f%5B0%5D=activitydomains%3A115&f%5B1%5D=lang%3Anl' }]);
92+
testLinkDetection('<a href="jobs.html?f=bar">link</a>', [{ offset: 9, length: 15, target: 'file:///test/data/abc/jobs.html' }]);
9293
});
9394

9495
test('Local targets', () => {
9596
testLinkDetection('<body><h1 id="title"></h1><a href="#title"</a></body>', [{ offset: 35, length: 6, target: 'file:///test/data/abc/test.html#1,14' }]);
9697
testLinkDetection('<body><h1 id="title"></h1><a href="file:///test/data/abc/test.html#title"</a></body>', [{ offset: 35, length: 37, target: 'file:///test/data/abc/test.html#1,14' }]);
98+
testLinkDetection('<body><h1 id="title"></h1><a href="#body"</a></body>', [{ offset: 35, length: 5, target: 'file:///test/data/abc/test.html' }]);
9799
});
98100

99101
});

0 commit comments

Comments
 (0)