From 93f552112c2bbd10bc0cee4afcae5b012242636c Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Wed, 13 Nov 2024 09:38:27 -0800 Subject: [PATCH] fix(@angular/build): improve URL rebasing for hyphenated Sass namespaced variables Sass variable namespaces can contain either a hyphen or underscore in the namespace identifier. The URL rebasing support within the Angular CLI will now account for these type of namespaces and rebase the evaluated URL as expected. (cherry picked from commit f96bb86c4e7b4d9c3185230bba11eeb8ab625d81) --- .../stylesheet-url-resolution_spec.ts | 54 +++++++++++++++++++ .../build/src/tools/sass/rebasing-importer.ts | 3 +- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/packages/angular/build/src/builders/application/tests/behavior/stylesheet-url-resolution_spec.ts b/packages/angular/build/src/builders/application/tests/behavior/stylesheet-url-resolution_spec.ts index 229636f0b8f8..0adc77b5311a 100644 --- a/packages/angular/build/src/builders/application/tests/behavior/stylesheet-url-resolution_spec.ts +++ b/packages/angular/build/src/builders/application/tests/behavior/stylesheet-url-resolution_spec.ts @@ -243,6 +243,60 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { harness.expectFile('dist/browser/media/logo.svg').toExist(); }); + it('should rebase a URL with a hyphen-namespaced Sass variable referencing a local resource', async () => { + await harness.writeFiles({ + 'src/styles.scss': `@use 'theme/a';`, + 'src/theme/a.scss': ` + @use './b' as named-hyphen; + .a { + background-image: url(named-hyphen.$my-var) + } + `, + 'src/theme/b.scss': `@forward './c.scss' show $my-var;`, + 'src/theme/c.scss': `$my-var: "./images/logo.svg";`, + 'src/theme/images/logo.svg': ``, + }); + + harness.useTarget('build', { + ...BASE_OPTIONS, + outputHashing: OutputHashing.None, + styles: ['src/styles.scss'], + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + + harness.expectFile('dist/browser/styles.css').content.toContain(`url("./media/logo.svg")`); + harness.expectFile('dist/browser/media/logo.svg').toExist(); + }); + + it('should rebase a URL with a underscore-namespaced Sass variable referencing a local resource', async () => { + await harness.writeFiles({ + 'src/styles.scss': `@use 'theme/a';`, + 'src/theme/a.scss': ` + @use './b' as named_underscore; + .a { + background-image: url(named_underscore.$my-var) + } + `, + 'src/theme/b.scss': `@forward './c.scss' show $my-var;`, + 'src/theme/c.scss': `$my-var: "./images/logo.svg";`, + 'src/theme/images/logo.svg': ``, + }); + + harness.useTarget('build', { + ...BASE_OPTIONS, + outputHashing: OutputHashing.None, + styles: ['src/styles.scss'], + }); + + const { result } = await harness.executeOnce(); + expect(result?.success).toBeTrue(); + + harness.expectFile('dist/browser/styles.css').content.toContain(`url("./media/logo.svg")`); + harness.expectFile('dist/browser/media/logo.svg').toExist(); + }); + it('should rebase a URL with a Sass variable referencing a local resource', async () => { await harness.writeFiles({ 'src/styles.scss': `@use 'theme/a';`, diff --git a/packages/angular/build/src/tools/sass/rebasing-importer.ts b/packages/angular/build/src/tools/sass/rebasing-importer.ts index c51c352ca274..d5ade8b6cf54 100644 --- a/packages/angular/build/src/tools/sass/rebasing-importer.ts +++ b/packages/angular/build/src/tools/sass/rebasing-importer.ts @@ -77,7 +77,8 @@ abstract class UrlRebasingImporter implements Importer<'sync'> { } // Sass variable usage either starts with a `$` or contains a namespace and a `.$` - const valueNormalized = value[0] === '$' || /^\w+\.\$/.test(value) ? `#{${value}}` : value; + const valueNormalized = + value[0] === '$' || /^\w[\w_-]*\.\$/.test(value) ? `#{${value}}` : value; const rebasedPath = relative(this.entryDirectory, stylesheetDirectory); // Normalize path separators and escape characters