diff --git a/packages/angular_devkit/build_angular/src/tools/sass/rebasing-importer.ts b/packages/angular_devkit/build_angular/src/tools/sass/rebasing-importer.ts index 736f3c28d6a9..729c0f70d819 100644 --- a/packages/angular_devkit/build_angular/src/tools/sass/rebasing-importer.ts +++ b/packages/angular_devkit/build_angular/src/tools/sass/rebasing-importer.ts @@ -33,13 +33,20 @@ export interface DirectoryEntry { const MODULE_RESOLUTION_PREFIX = '__NG_PACKAGE__'; function packModuleSpecifier(specifier: string, resolveDir: string): string { - const packed = MODULE_RESOLUTION_PREFIX + ';' + resolveDir + ';' + specifier; - - // Normalize path separators and escape characters - // https://developer.mozilla.org/en-US/docs/Web/CSS/url#syntax - const normalizedPacked = packed.replace(/\\/g, '/').replace(/[()\s'"]/g, '\\$&'); - - return normalizedPacked; + const packed = + MODULE_RESOLUTION_PREFIX + + ';' + + // Encode the resolve directory to prevent unsupported characters from being present when + // Sass processes the URL. This is important on Windows which can contain drive letters + // and colons which would otherwise be interpreted as a URL scheme. + encodeURIComponent(resolveDir) + + ';' + + // Escape characters instead of encoding to provide more friendly not found error messages. + // Unescaping is automatically handled by Sass. + // https://developer.mozilla.org/en-US/docs/Web/CSS/url#syntax + specifier.replace(/[()\s'"]/g, '\\$&'); + + return packed; } function unpackModuleSpecifier(specifier: string): { specifier: string; resolveDir?: string } { @@ -51,7 +58,7 @@ function unpackModuleSpecifier(specifier: string): { specifier: string; resolveD return { specifier: values[2], - resolveDir: values[1], + resolveDir: decodeURIComponent(values[1]), }; } diff --git a/tests/legacy-cli/e2e/tests/build/styles/scss-partial-resolution.ts b/tests/legacy-cli/e2e/tests/build/styles/scss-partial-resolution.ts index f3863ad72adb..313ec5e03e58 100644 --- a/tests/legacy-cli/e2e/tests/build/styles/scss-partial-resolution.ts +++ b/tests/legacy-cli/e2e/tests/build/styles/scss-partial-resolution.ts @@ -12,10 +12,14 @@ export default async function () { await writeMultipleFiles({ 'src/styles.scss': ` - @use '@material/button/button' as mat; + @use '@material/button/button'; + + @include button.core-styles; `, 'src/app/app.component.scss': ` - @use '@material/button/button' as mat; + @use '@material/button/button'; + + @include button.core-styles; `, });