fix(css): when compiling CSS, leave absolute imports alone

Closes #4592
This commit is contained in:
Yegor Jbanov
2015-10-07 13:37:56 -07:00
committed by Yegor
parent 6b00b60488
commit 04b3dee667
7 changed files with 68 additions and 6 deletions

View File

@ -24,6 +24,11 @@ function extractUrls(resolver: UrlResolver, baseUrl: string, cssText: string, fo
string {
return StringWrapper.replaceAllMapped(cssText, _cssImportRe, (m) => {
var url = isPresent(m[1]) ? m[1] : m[2];
var schemeMatch = RegExpWrapper.firstMatch(_urlWithSchemaRe, url);
if (isPresent(schemeMatch) && schemeMatch[1] != 'package') {
// Do not attempt to resolve non-package absolute URLs with URI scheme
return m[0];
}
foundUrls.push(resolver.resolve(baseUrl, url));
return '';
});
@ -50,3 +55,6 @@ var _cssUrlRe = /(url\()([^)]*)(\))/g;
var _cssImportRe = /@import\s+(?:url\()?\s*(?:(?:['"]([^'"]*))|([^;\)\s]*))[^;]*;?/g;
var _quoteRe = /['"]/g;
var _dataUrlRe = /^['"]?data:/g;
// TODO: can't use /^[^:/?#.]+:/g due to clang-format bug:
// https://github.com/angular/angular/issues/4596
var _urlWithSchemaRe = /^['"]?([a-zA-Z\-\+\.]+):/g;

View File

@ -28,6 +28,8 @@ List<EmulatedCssRule> emulateRules(Iterable<cssv.TreeNode> rules) {
return new EmulatedCssStyleRule(node);
} else if (node is cssv.MediaDirective) {
return new EmulatedCssMedialRule(node);
} else if (node is cssv.ImportDirective) {
return new EmulatedCssImportRule(node);
}
})
.where((r) => r != null)
@ -100,3 +102,12 @@ class EmulatedMediaList {
.map((q) => q.span.text).join(' and ');
}
}
/// Emulates [CSSImportRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSImportRule)
class EmulatedCssImportRule extends EmulatedCssRule {
EmulatedCssImportRule(cssv.ImportDirective directive) {
this
..type = 3
..cssText = '@${directive.span.text};';
}
}

View File

@ -154,5 +154,11 @@ export function main() {
var css = s('x >>> y {}', 'a');
expect(css).toEqual('x[a] y[a] {}');
});
it('should pass through @import directives', () => {
var styleStr = '@import url("https://fonts.googleapis.com/css?family=Roboto");';
var css = s(styleStr, 'a');
expect(css).toEqual(styleStr);
});
});
}

View File

@ -88,5 +88,26 @@ export function main() {
.toEqual(['http://ng.io/print1.css', 'http://ng.io/print2.css']);
});
it('should leave absolute non-package @import urls intact', () => {
var css = `@import url('http://server.com/some.css');`;
var styleWithImports = resolveStyleUrls(urlResolver, 'http://ng.io', css);
expect(styleWithImports.style.trim()).toEqual(`@import url('http://server.com/some.css');`);
expect(styleWithImports.styleUrls).toEqual([]);
});
it('should resolve package @import urls', () => {
var css = `@import url('package:a/b/some.css');`;
var styleWithImports = resolveStyleUrls(new FakeUrlResolver(), 'http://ng.io', css);
expect(styleWithImports.style.trim()).toEqual(``);
expect(styleWithImports.styleUrls).toEqual(['fake_resolved_url']);
});
});
}
/// The real thing behaves differently between Dart and JS for package URIs.
class FakeUrlResolver extends UrlResolver {
constructor() { super(); }
resolve(baseUrl: string, url: string): string { return 'fake_resolved_url'; }
}