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