From 4c000592606ecd7d5f621c586c65541d3a1547bd Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Tue, 15 Jan 2019 13:35:28 -0800 Subject: [PATCH] feat(compiler-cli): resolve generated Sass/Less files to .css inputs (#28166) Users might have run the CSS Preprocessor tool *before* the Angular compiler. For example, we do it that way under Bazel. This means that the design-time reference is different from the compile-time one - the input to the Angular compiler is a plain .css file. We assume that the preprocessor does a trivial 1:1 mapping using the same basename with a different extension. PR Close #28166 --- .../src/transformers/compiler_host.ts | 10 +++++++++- .../test/transformers/compiler_host_spec.ts | 16 +++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/compiler-cli/src/transformers/compiler_host.ts b/packages/compiler-cli/src/transformers/compiler_host.ts index bf5f4e8e642bb4..284c96db55c1f4 100644 --- a/packages/compiler-cli/src/transformers/compiler_host.ts +++ b/packages/compiler-cli/src/transformers/compiler_host.ts @@ -19,6 +19,7 @@ import {DTS, GENERATED_FILES, isInRootDir, relativeToRootDirs} from './util'; const NODE_MODULES_PACKAGE_NAME = /node_modules\/((\w|-|\.)+|(@(\w|-|\.)+\/(\w|-|\.)+))/; const EXT = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/; +const CSS_PREPROCESSOR_EXT = /(\.scss|\.less|\.styl)$/; export function createCompilerHost( {options, tsHost = ts.createCompilerHost(options, true)}: @@ -270,8 +271,15 @@ export class TsCompilerAotCompilerTypeCheckHostAdapter implements ts.CompilerHos } else if (firstChar !== '.') { resourceName = `./${resourceName}`; } - const filePathWithNgResource = + let filePathWithNgResource = this.moduleNameToFileName(addNgResourceSuffix(resourceName), containingFile); + // If the user specified styleUrl pointing to *.scss, but the Sass compiler was run before + // Angular, then the resource may have been generated as *.css. Simply try the resolution again. + if (!filePathWithNgResource && CSS_PREPROCESSOR_EXT.test(resourceName)) { + const fallbackResourceName = resourceName.replace(CSS_PREPROCESSOR_EXT, '.css'); + filePathWithNgResource = + this.moduleNameToFileName(addNgResourceSuffix(fallbackResourceName), containingFile); + } const result = filePathWithNgResource ? stripNgResourceSuffix(filePathWithNgResource) : null; // Used under Bazel to report more specific error with remediation advice if (!result && (this.context as any).reportMissingResource) { diff --git a/packages/compiler-cli/test/transformers/compiler_host_spec.ts b/packages/compiler-cli/test/transformers/compiler_host_spec.ts index 357bdc543f3623..c411a638ac6efd 100644 --- a/packages/compiler-cli/test/transformers/compiler_host_spec.ts +++ b/packages/compiler-cli/test/transformers/compiler_host_spec.ts @@ -196,7 +196,21 @@ describe('NgCompilerHost', () => { const host = createHost({ngHost}); expect(host.resourceNameToFileName('a', 'b')).toBe('someResult'); }); - + it('should resolve Sass imports to generated .css files', () => { + const host = createHost({files: {'tmp': {'src': {'a': {'style.css': 'h1: bold'}}}}}); + expect(host.resourceNameToFileName('./a/style.scss', '/tmp/src/index.ts')) + .toBe('/tmp/src/a/style.css'); + }); + it('should resolve Less imports to generated .css files', () => { + const host = createHost({files: {'tmp': {'src': {'a': {'style.css': 'h1: bold'}}}}}); + expect(host.resourceNameToFileName('./a/style.less', '/tmp/src/index.ts')) + .toBe('/tmp/src/a/style.css'); + }); + it('should resolve Stylus imports to generated .css files', () => { + const host = createHost({files: {'tmp': {'src': {'a': {'style.css': 'h1: bold'}}}}}); + expect(host.resourceNameToFileName('./a/style.styl', '/tmp/src/index.ts')) + .toBe('/tmp/src/a/style.css'); + }); }); describe('getSourceFile', () => {