Skip to content

Commit 2f956c8

Browse files
Implemented changes requested in pr microsoft#440
1 parent a75501c commit 2f956c8

File tree

4 files changed

+73
-82
lines changed

4 files changed

+73
-82
lines changed

src/services/cssNavigation.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -423,19 +423,15 @@ export class CSSNavigation {
423423
}
424424

425425
// Treat bare module names (“bootstrap/...”) like sass-loader does
426-
const startsWithSchemeRegex = /^\w[\w\d+.-]:/;
427-
428-
const isBareImport = !target.startsWith('.') // not ./ or ../
429-
&& !target.startsWith('/') // not workspace-absolute
430-
&& !startsWithSchemeRegex.test(target); // not a scheme (file://, http://, etc.)
431-
432-
if (isBareImport) {
433-
const moduleRef = await this.mapReference(
434-
await this.resolveModuleReference(target, documentUri, documentContext),
435-
isRawLink);
436-
if (moduleRef) { return moduleRef; }
426+
if (this.resolveModuleReferences && importIsBare(target)) {
427+
const resolvedModuleRef = await this.resolveModuleReference(target, documentUri, documentContext);
428+
const moduleRef = await this.mapReference(resolvedModuleRef, isRawLink);
429+
430+
if (moduleRef != null) {
431+
return moduleRef;
432+
}
437433
}
438-
434+
439435
const ref = await this.mapReference(
440436
documentContext.resolveReference(target, documentUri), isRawLink);
441437

@@ -588,6 +584,12 @@ function toTwoDigitHex(n: number): string {
588584
return r.length !== 2 ? '0' + r : r;
589585
}
590586

587+
function importIsBare(target: string): boolean {
588+
return !target.startsWith('.') // not ./ or ../
589+
&& !target.startsWith('/') // not workspace-absolute
590+
&& !startsWithSchemeRegex.test(target); // not a scheme (file://, http://, etc.)
591+
}
592+
591593
export function getModuleNameFromPath(path: string) {
592594
const firstSlash = path.indexOf('/');
593595
if (firstSlash === -1) {

src/test/scss/schemeImportLinks.test.ts

Lines changed: 0 additions & 46 deletions
This file was deleted.

src/test/scss/scssNavigation-node-modules.test.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/test/scss/scssNavigation.test.ts

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import * as nodes from '../../parser/cssNodes';
88
import { assertSymbolsInScope, assertScopesAndSymbols, assertHighlights, assertColorSymbols, assertLinks, newRange, getTestResource, assertDocumentSymbols } from '../css/navigation.test';
9-
import { getSCSSLanguageService, DocumentLink, TextDocument, SymbolKind, LanguageSettings } from '../../cssLanguageService';
9+
import { getSCSSLanguageService, DocumentLink, TextDocument, SymbolKind, LanguageSettings, DocumentContext } from '../../cssLanguageService';
1010
import * as assert from 'assert';
1111
import * as path from 'path';
1212
import { URI } from 'vscode-uri';
@@ -20,11 +20,11 @@ function getSCSSLS() {
2020
function aliasSettings(): LanguageSettings {
2121
return {
2222
"importAliases": {
23-
"@SassStylesheet": "/src/assets/styles.scss",
24-
"@NoUnderscoreDir/": "/noUnderscore/",
25-
"@UnderscoreDir/": "/underscore/",
26-
"@BothDir/": "/both/",
27-
}
23+
"@SassStylesheet": "/src/assets/styles.scss",
24+
"@NoUnderscoreDir/": "/noUnderscore/",
25+
"@UnderscoreDir/": "/underscore/",
26+
"@BothDir/": "/both/",
27+
}
2828
};
2929
}
3030

@@ -57,6 +57,21 @@ async function assertNoDynamicLinks(docUri: string, input: string, extecedTarget
5757

5858
}
5959

60+
function createDocument(contents: string, uri = 'file:///test.scss') {
61+
return TextDocument.create(uri, 'scss', 0, contents);
62+
}
63+
64+
const dummyContext: DocumentContext = {
65+
resolveReference: (ref: string, _base: string) => ref
66+
};
67+
68+
async function getLinks(contents: string) {
69+
const ls = getSCSSLS();
70+
const doc = createDocument(contents);
71+
const stylesheet = ls.parseStylesheet(doc);
72+
return ls.findDocumentLinks2(doc, stylesheet, dummyContext);
73+
}
74+
6075
suite('SCSS - Navigation', () => {
6176

6277
suite('Scopes and Symbols', () => {
@@ -353,4 +368,42 @@ suite('SCSS - Navigation', () => {
353368
});
354369
});
355370

371+
suite('URL Scheme Imports', () => {
372+
373+
test('http scheme import is treated as absolute URL, not bare import', async () => {
374+
const links = await getLinks(`@import "http://example.com/foo.css";`);
375+
assert.strictEqual(links.length, 1);
376+
assert.strictEqual(links[0].target, 'http://example.com/foo.css');
377+
});
378+
379+
test('https scheme import is treated as absolute URL, not bare import', async () => {
380+
const links = await getLinks(`@import "https://cdn.example.com/reset.css";`);
381+
assert.strictEqual(links.length, 1);
382+
assert.strictEqual(links[0].target, 'https://cdn.example.com/reset.css');
383+
});
384+
385+
test('file scheme import is treated as absolute URL, not bare import', async () => {
386+
const links = await getLinks(`@import "file:///Users/test/project/styles/base.scss";`);
387+
assert.strictEqual(links.length, 1);
388+
assert.strictEqual(links[0].target, 'file:///Users/test/project/styles/base.scss');
389+
});
390+
391+
test('custom scheme import (vscode-resource) is treated as absolute URL, not bare import', async () => {
392+
const links = await getLinks(`@import "vscode-resource://file/some.css";`);
393+
assert.strictEqual(links.length, 1);
394+
assert.strictEqual(links[0].target, 'vscode-resource://file/some.css');
395+
});
396+
});
397+
398+
suite('Bare Imports', () => {
399+
400+
test('resolves bare import path on Windows', async () => {
401+
const ls = getSCSSLS();
402+
403+
const doc = TextDocument.create('file:///c:/proj/app.scss', 'scss', 1, "@import 'bootstrap/scss/variables';");
404+
const links = await ls.findDocumentLinks2(doc, ls.parseStylesheet(doc), getDocumentContext('c:/proj'));
405+
const expected = URI.file('c:/proj/node_modules/bootstrap/scss/_variables.scss').toString();
406+
assert.strictEqual(links[0].target, expected);
407+
});
408+
});
356409
});

0 commit comments

Comments
 (0)