diff --git a/.changeset/fix-sass-baseurl-resolution.md b/.changeset/fix-sass-baseurl-resolution.md new file mode 100644 index 000000000000..e96d0a9f2fcf --- /dev/null +++ b/.changeset/fix-sass-baseurl-resolution.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes Sass/SCSS `@use` and `@import` not resolving bare specifiers against `baseUrl` in `tsconfig.json`. Projects using `@use "colors.scss"` with `"baseUrl": "src"` now resolve correctly. diff --git a/package.json b/package.json index 08ec341971c9..1dc0d42c5d7c 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "prettier-plugin-astro": "^0.14.1", "publint": "^0.3.17", "tinyglobby": "^0.2.15", - "turbo": "^2.8.11", + "turbo": "^2.8.15", "typescript": "~5.9.3", "typescript-eslint": "^8.56.1", "valibot": "^1.2.0" diff --git a/packages/astro/src/vite-plugin-config-alias/index.ts b/packages/astro/src/vite-plugin-config-alias/index.ts index 57d518da3079..795156a1abef 100644 --- a/packages/astro/src/vite-plugin-config-alias/index.ts +++ b/packages/astro/src/vite-plugin-config-alias/index.ts @@ -91,7 +91,7 @@ const getViteResolveAlias = (settings: AstroSettings) => { for (const resolvedValue of resolvedValues) { const resolved = resolvedValue.replace('*', id); const stats = fs.statSync(resolved, { throwIfNoEntry: false }); - if (stats && stats.isFile()) { + if (stats?.isFile()) { return normalizePath(resolved); } } @@ -110,6 +110,25 @@ const getViteResolveAlias = (settings: AstroSettings) => { } } + // Add baseUrl alias for CSS/Sass bare specifiers (e.g. `@use "colors.scss"`). + // This mirrors the baseUrl handling in getConfigAlias() but is scoped to + // style file extensions to avoid intercepting JS/npm package imports, + // which are handled by the resolveId hook instead. + if (baseUrl) { + aliases.push({ + find: /^(?!\.*\/|\.*$|\w:)(.+\.(?:css|scss|sass|less|styl|stylus))$/, + replacement: '$1', + customResolver(id: string) { + const resolved = path.resolve(resolvedBaseUrl, id); + const stats = fs.statSync(resolved, { throwIfNoEntry: false }); + if (stats?.isFile()) { + return normalizePath(resolved); + } + return null; + }, + }); + } + return aliases; }; diff --git a/packages/astro/test/alias-tsconfig.test.js b/packages/astro/test/alias-tsconfig.test.js index 66ddc7bff82d..c026c3a32603 100644 --- a/packages/astro/test/alias-tsconfig.test.js +++ b/packages/astro/test/alias-tsconfig.test.js @@ -88,6 +88,12 @@ describe('Aliases with tsconfig.json', () => { assert.equal($('#alias').text(), 'foo'); }); + it('resolves Sass @use via baseUrl', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + // The Sass variable $accent: green should be applied via baseUrl resolution + assert.ok(html.includes('green')); + }); + it('works for import.meta.glob', async () => { const html = await fixture.fetch('/').then((res) => res.text()); const $ = cheerio.load(html); @@ -144,6 +150,14 @@ describe('Aliases with tsconfig.json', () => { assert.equal($('#alias').text(), 'foo'); }); + it('resolves Sass @use via baseUrl', async () => { + const html = await fixture.readFile('/index.html'); + const content = await Promise.all(getLinks(html).map((href) => getLinkContent(href))); + const allCss = content.map(({ css }) => css).join(''); + // The Sass variable $accent: green should be compiled into the CSS + assert.ok(allCss.includes('green')); + }); + it('handles multiple replacements in one alias', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); diff --git a/packages/astro/test/fixtures/alias-tsconfig/src/colors.scss b/packages/astro/test/fixtures/alias-tsconfig/src/colors.scss new file mode 100644 index 000000000000..0a9308d87bec --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig/src/colors.scss @@ -0,0 +1 @@ +$accent: green; diff --git a/packages/astro/test/fixtures/alias-tsconfig/src/components/SassBaseUrl.astro b/packages/astro/test/fixtures/alias-tsconfig/src/components/SassBaseUrl.astro new file mode 100644 index 000000000000..4d7527a2438a --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig/src/components/SassBaseUrl.astro @@ -0,0 +1,11 @@ +--- +--- +

sass-baseurl

+ + diff --git a/packages/astro/test/fixtures/alias-tsconfig/src/pages/index.astro b/packages/astro/test/fixtures/alias-tsconfig/src/pages/index.astro index be6eaf50a402..ff297fbbcca3 100644 --- a/packages/astro/test/fixtures/alias-tsconfig/src/pages/index.astro +++ b/packages/astro/test/fixtures/alias-tsconfig/src/pages/index.astro @@ -10,6 +10,7 @@ import Baz from "@short/Baz" import StyleComp from 'src/components/Style.astro'; import { foo, index } from 'src/utils/constants'; import { doNothing } from '@pages'; +import SassBaseUrl from '@components/SassBaseUrl.astro'; const globResult = Object.keys(import.meta.glob('@components/glob/*.js')).join(', ') @@ -37,6 +38,7 @@ doNothing()

style-red

style-blue

{globResult}

+ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3eb644db812e..93bf40a23474 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -69,8 +69,8 @@ importers: specifier: ^0.2.15 version: 0.2.15 turbo: - specifier: ^2.8.11 - version: 2.8.11 + specifier: ^2.8.15 + version: 2.8.15 typescript: specifier: ~5.9.3 version: 5.9.3 @@ -15219,38 +15219,38 @@ packages: resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - turbo-darwin-64@2.8.11: - resolution: {integrity: sha512-XKaCWaz4OCt77oYYvGCIRpvYD4c/aNaKjRkUpv+e8rN3RZb+5Xsyew4yRO+gaHdMIUhQznXNXfHlhs+/p7lIhA==} + turbo-darwin-64@2.8.15: + resolution: {integrity: sha512-EElCh+Ltxex9lXYrouV3hHjKP3HFP31G91KMghpNHR/V99CkFudRcHcnWaorPbzAZizH1m8o2JkLL8rptgb8WQ==} cpu: [x64] os: [darwin] - turbo-darwin-arm64@2.8.11: - resolution: {integrity: sha512-VvynLHGUNvQ9k7GZjRPSsRcK4VkioTfFb7O7liAk4nHKjEcMdls7GqxzjVWgJiKz3hWmQGaP9hRa9UUnhVWCxA==} + turbo-darwin-arm64@2.8.15: + resolution: {integrity: sha512-ORmvtqHiHwvNynSWvLIleyU8dKtwQ4ILk39VsEwfKSEzSHWYWYxZhBmD9GAGRPlNl7l7S1irrziBlDEGVpq+vQ==} cpu: [arm64] os: [darwin] - turbo-linux-64@2.8.11: - resolution: {integrity: sha512-cbSn37dcm+EmkQ7DD0euy7xV7o2el4GAOr1XujvkAyKjjNvQ+6QIUeDgQcwAx3D17zPpDvfDMJY2dLQadWnkmQ==} + turbo-linux-64@2.8.15: + resolution: {integrity: sha512-Bk1E61a+PCWUTfhqfXFlhEJMLp6nak0J0Qt14IZX1og1zyaiBLkM6M1GQFbPpiWfbUcdLwRaYQhO0ySB07AJ8w==} cpu: [x64] os: [linux] - turbo-linux-arm64@2.8.11: - resolution: {integrity: sha512-+trymp2s2aBrhS04l6qFxcExzZ8ffndevuUB9c5RCeqsVpZeiWuGQlWNm5XjOmzoMayxRARZ5ma7yiWbGMiLqQ==} + turbo-linux-arm64@2.8.15: + resolution: {integrity: sha512-3BX0Vk+XkP0uiZc8pkjQGNsAWjk5ojC53bQEMp6iuhSdWpEScEFmcT6p7DL7bcJmhP2mZ1HlAu0A48wrTGCtvg==} cpu: [arm64] os: [linux] - turbo-windows-64@2.8.11: - resolution: {integrity: sha512-3kJjFSM4yw1n9Uzmi+XkAUgCae19l/bH6RJ442xo7mnZm0tpOjo33F+FYHoSVpIWVMd0HG0LDccyafPSdylQbA==} + turbo-windows-64@2.8.15: + resolution: {integrity: sha512-m14ogunMF+grHZ1jzxSCO6q0gEfF1tmr+0LU+j1QNd/M1X33tfKnQqmpkeUR/REsGjfUlkQlh6PAzqlT3cA3Pg==} cpu: [x64] os: [win32] - turbo-windows-arm64@2.8.11: - resolution: {integrity: sha512-JOM4uF2vuLsJUvibdR6X9QqdZr6BhC6Nhlrw4LKFPsXZZI/9HHLoqAiYRpE4MuzIwldCH/jVySnWXrI1SKto0g==} + turbo-windows-arm64@2.8.15: + resolution: {integrity: sha512-HWh6dnzhl7nu5gRwXeqP61xbyDBNmQ4UCeWNa+si4/6RAtHlKEcZTNs7jf4U+oqBnbtv4uxbKZZPf/kN0EK4+A==} cpu: [arm64] os: [win32] - turbo@2.8.11: - resolution: {integrity: sha512-H+rwSHHPLoyPOSoHdmI1zY0zy0GGj1Dmr7SeJW+nZiWLz2nex8EJ+fkdVabxXFMNEux+aywI4Sae8EqhmnOv4A==} + turbo@2.8.15: + resolution: {integrity: sha512-ERZf7pKOR155NKs/PZt1+83NrSEJfUL7+p9/TGZg/8xzDVMntXEFQlX4CsNJQTyu4h3j+dZYiQWOOlv5pssuHQ==} hasBin: true twoslash-protocol@0.3.6: @@ -25197,32 +25197,32 @@ snapshots: tunnel@0.0.6: {} - turbo-darwin-64@2.8.11: + turbo-darwin-64@2.8.15: optional: true - turbo-darwin-arm64@2.8.11: + turbo-darwin-arm64@2.8.15: optional: true - turbo-linux-64@2.8.11: + turbo-linux-64@2.8.15: optional: true - turbo-linux-arm64@2.8.11: + turbo-linux-arm64@2.8.15: optional: true - turbo-windows-64@2.8.11: + turbo-windows-64@2.8.15: optional: true - turbo-windows-arm64@2.8.11: + turbo-windows-arm64@2.8.15: optional: true - turbo@2.8.11: + turbo@2.8.15: optionalDependencies: - turbo-darwin-64: 2.8.11 - turbo-darwin-arm64: 2.8.11 - turbo-linux-64: 2.8.11 - turbo-linux-arm64: 2.8.11 - turbo-windows-64: 2.8.11 - turbo-windows-arm64: 2.8.11 + turbo-darwin-64: 2.8.15 + turbo-darwin-arm64: 2.8.15 + turbo-linux-64: 2.8.15 + turbo-linux-arm64: 2.8.15 + turbo-windows-64: 2.8.15 + turbo-windows-arm64: 2.8.15 twoslash-protocol@0.3.6: {}