From 5bced3768c065133a915c2da5ce2557347beca33 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 2 Oct 2018 18:19:10 +0200 Subject: [PATCH] fix(@angular-devkit/build-angular): resolve assets in styles relative to importee Closes #12430 --- .../plugins/postcss-cli-resources.ts | 18 ++++++++++++------ .../test/browser/styles_spec_large.ts | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/postcss-cli-resources.ts b/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/postcss-cli-resources.ts index 7192ca92efea..b97e1184f050 100644 --- a/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/postcss-cli-resources.ts +++ b/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/postcss-cli-resources.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ import { interpolateName } from 'loader-utils'; +import * as path from 'path'; import * as postcss from 'postcss'; import * as url from 'url'; import * as webpack from 'webpack'; @@ -52,7 +53,7 @@ export default postcss.plugin('postcss-cli-resources', (options: PostcssCliResou const dedupeSlashes = (url: string) => url.replace(/\/\/+/g, '/'); - const process = async (inputUrl: string, resourceCache: Map) => { + const process = async (inputUrl: string, context: string, resourceCache: Map) => { // If root-relative or absolute, leave as is if (inputUrl.match(/^(?:\w+:\/\/|data:|chrome:|#)/)) { return inputUrl; @@ -63,7 +64,8 @@ export default postcss.plugin('postcss-cli-resources', (options: PostcssCliResou return inputUrl.substr(1); } - const cachedUrl = resourceCache.get(inputUrl); + const cacheKey = path.resolve(context, inputUrl); + const cachedUrl = resourceCache.get(cacheKey); if (cachedUrl) { return cachedUrl; } @@ -85,7 +87,7 @@ export default postcss.plugin('postcss-cli-resources', (options: PostcssCliResou outputUrl = dedupeSlashes(`/${baseHref}/${deployUrl}/${inputUrl}`); } - resourceCache.set(inputUrl, outputUrl); + resourceCache.set(cacheKey, outputUrl); return outputUrl; } @@ -102,7 +104,7 @@ export default postcss.plugin('postcss-cli-resources', (options: PostcssCliResou }); }); - const result = await resolve(pathname as string, loader.context, resolver); + const result = await resolve(pathname as string, context, resolver); return new Promise((resolve, reject) => { loader.fs.readFile(result, (err: Error, content: Buffer) => { @@ -130,7 +132,7 @@ export default postcss.plugin('postcss-cli-resources', (options: PostcssCliResou outputUrl = url.resolve(deployUrl, outputUrl); } - resourceCache.set(inputUrl, outputUrl); + resourceCache.set(cacheKey, outputUrl); resolve(outputUrl); }); }); @@ -158,12 +160,16 @@ export default postcss.plugin('postcss-cli-resources', (options: PostcssCliResou let match; let lastIndex = 0; let modified = false; + + // We want to load it relative to the file that imports + const context = path.dirname(decl.source.input.file); + // tslint:disable-next-line:no-conditional-assignment while (match = urlRegex.exec(value)) { const originalUrl = match[1] || match[2] || match[3]; let processedUrl; try { - processedUrl = await process(originalUrl, resourceCache); + processedUrl = await process(originalUrl, context, resourceCache); } catch (err) { loader.emitError(decl.error(err.message, { word: originalUrl }).toString()); continue; diff --git a/packages/angular_devkit/build_angular/test/browser/styles_spec_large.ts b/packages/angular_devkit/build_angular/test/browser/styles_spec_large.ts index 774e1ae96752..4f76dae06977 100644 --- a/packages/angular_devkit/build_angular/test/browser/styles_spec_large.ts +++ b/packages/angular_devkit/build_angular/test/browser/styles_spec_large.ts @@ -293,6 +293,20 @@ describe('Browser Builder styles', () => { ).toPromise().then(done, done.fail); }, 30000); + it(`supports font-awesome imports without extractCss`, (done) => { + host.writeMultipleFiles({ + 'src/styles.scss': ` + @import "~font-awesome/css/font-awesome.css"; + `, + }); + + const overrides = { extractCss: false, styles: [`src/styles.scss`] }; + + runTargetSpec(host, browserTargetSpec, overrides).pipe( + tap((buildEvent) => expect(buildEvent.success).toBe(true)), + ).toPromise().then(done, done.fail); + }, 30000); + it(`uses autoprefixer`, (done) => { host.writeMultipleFiles({ 'src/styles.css': tags.stripIndents`