2016-06-23 12:47:54 -04:00
|
|
|
/**
|
|
|
|
* @license
|
|
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
*/
|
|
|
|
|
2016-12-15 12:12:40 -05:00
|
|
|
import {ViewEncapsulation} from '@angular/core';
|
2016-11-23 12:42:19 -05:00
|
|
|
|
|
|
|
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileStylesheetMetadata, identifierModuleUrl, identifierName} from './compile_metadata';
|
2016-12-15 12:12:40 -05:00
|
|
|
import {CompilerInjectable} from './injectable';
|
2016-01-06 17:13:44 -05:00
|
|
|
import * as o from './output/output_ast';
|
2016-04-28 20:50:03 -04:00
|
|
|
import {ShadowCss} from './shadow_css';
|
2016-06-08 19:38:52 -04:00
|
|
|
import {UrlResolver} from './url_resolver';
|
2015-12-02 13:35:51 -05:00
|
|
|
|
|
|
|
const COMPONENT_VARIABLE = '%COMP%';
|
2016-07-13 14:01:32 -04:00
|
|
|
const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
|
|
|
|
const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
|
2015-09-02 18:07:31 -04:00
|
|
|
|
2016-01-06 17:13:44 -05:00
|
|
|
export class StylesCompileDependency {
|
2016-06-08 19:38:52 -04:00
|
|
|
constructor(
|
2016-11-23 12:42:19 -05:00
|
|
|
public name: string, public moduleUrl: string, public isShimmed: boolean,
|
2016-06-08 19:38:52 -04:00
|
|
|
public valuePlaceholder: CompileIdentifierMetadata) {}
|
2016-01-06 17:13:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
export class StylesCompileResult {
|
2016-06-24 11:46:43 -04:00
|
|
|
constructor(
|
|
|
|
public componentStylesheet: CompiledStylesheet,
|
|
|
|
public externalStylesheets: CompiledStylesheet[]) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class CompiledStylesheet {
|
2016-06-08 19:38:52 -04:00
|
|
|
constructor(
|
|
|
|
public statements: o.Statement[], public stylesVar: string,
|
2016-06-24 11:46:43 -04:00
|
|
|
public dependencies: StylesCompileDependency[], public isShimmed: boolean,
|
|
|
|
public meta: CompileStylesheetMetadata) {}
|
2016-01-06 17:13:44 -05:00
|
|
|
}
|
|
|
|
|
2016-12-15 12:12:40 -05:00
|
|
|
@CompilerInjectable()
|
2015-09-02 18:07:31 -04:00
|
|
|
export class StyleCompiler {
|
|
|
|
private _shadowCss: ShadowCss = new ShadowCss();
|
|
|
|
|
2016-01-06 17:13:44 -05:00
|
|
|
constructor(private _urlResolver: UrlResolver) {}
|
2015-09-02 18:07:31 -04:00
|
|
|
|
2016-01-06 17:13:44 -05:00
|
|
|
compileComponent(comp: CompileDirectiveMetadata): StylesCompileResult {
|
2017-03-24 12:59:58 -04:00
|
|
|
const template = comp.template !;
|
2016-07-09 13:12:39 -04:00
|
|
|
const externalStylesheets: CompiledStylesheet[] = [];
|
|
|
|
const componentStylesheet: CompiledStylesheet = this._compileStyles(
|
2016-06-24 11:46:43 -04:00
|
|
|
comp, new CompileStylesheetMetadata({
|
2017-03-24 12:59:58 -04:00
|
|
|
styles: template.styles,
|
|
|
|
styleUrls: template.styleUrls,
|
2016-11-23 12:42:19 -05:00
|
|
|
moduleUrl: identifierModuleUrl(comp.type)
|
2016-06-24 11:46:43 -04:00
|
|
|
}),
|
|
|
|
true);
|
2017-03-24 12:59:58 -04:00
|
|
|
template.externalStylesheets.forEach((stylesheetMeta) => {
|
2016-07-09 13:12:39 -04:00
|
|
|
const compiledStylesheet = this._compileStyles(comp, stylesheetMeta, false);
|
2016-06-24 11:46:43 -04:00
|
|
|
externalStylesheets.push(compiledStylesheet);
|
|
|
|
});
|
|
|
|
return new StylesCompileResult(componentStylesheet, externalStylesheets);
|
2015-09-02 18:07:31 -04:00
|
|
|
}
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
private _compileStyles(
|
2016-06-24 11:46:43 -04:00
|
|
|
comp: CompileDirectiveMetadata, stylesheet: CompileStylesheetMetadata,
|
|
|
|
isComponentStylesheet: boolean): CompiledStylesheet {
|
2017-03-24 12:59:58 -04:00
|
|
|
const shim = comp.template !.encapsulation === ViewEncapsulation.Emulated;
|
2016-07-09 13:12:39 -04:00
|
|
|
const styleExpressions =
|
2016-06-24 11:46:43 -04:00
|
|
|
stylesheet.styles.map(plainStyle => o.literal(this._shimIfNeeded(plainStyle, shim)));
|
2016-07-09 13:12:39 -04:00
|
|
|
const dependencies: StylesCompileDependency[] = [];
|
|
|
|
for (let i = 0; i < stylesheet.styleUrls.length; i++) {
|
2016-11-30 13:52:51 -05:00
|
|
|
const identifier: CompileIdentifierMetadata = {reference: null};
|
2016-11-23 12:42:19 -05:00
|
|
|
dependencies.push(new StylesCompileDependency(
|
|
|
|
getStylesVarName(null), stylesheet.styleUrls[i], shim, identifier));
|
2016-01-06 17:13:44 -05:00
|
|
|
styleExpressions.push(new o.ExternalExpr(identifier));
|
2015-09-02 18:07:31 -04:00
|
|
|
}
|
2016-01-06 17:13:44 -05:00
|
|
|
// styles variable contains plain strings and arrays of other styles arrays (recursive),
|
|
|
|
// so we set its type to dynamic.
|
2016-07-09 13:12:39 -04:00
|
|
|
const stylesVar = getStylesVarName(isComponentStylesheet ? comp : null);
|
|
|
|
const stmt = o.variable(stylesVar)
|
|
|
|
.set(o.literalArr(
|
|
|
|
styleExpressions, new o.ArrayType(o.DYNAMIC_TYPE, [o.TypeModifier.Const])))
|
|
|
|
.toDeclStmt(null, [o.StmtModifier.Final]);
|
2016-06-24 11:46:43 -04:00
|
|
|
return new CompiledStylesheet([stmt], stylesVar, dependencies, shim, stylesheet);
|
2015-09-02 18:07:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
private _shimIfNeeded(style: string, shim: boolean): string {
|
|
|
|
return shim ? this._shadowCss.shimCssText(style, CONTENT_ATTR, HOST_ATTR) : style;
|
|
|
|
}
|
2016-01-06 17:13:44 -05:00
|
|
|
}
|
2015-09-02 18:07:31 -04:00
|
|
|
|
2017-03-24 12:59:58 -04:00
|
|
|
function getStylesVarName(component: CompileDirectiveMetadata | null): string {
|
2016-07-09 13:12:39 -04:00
|
|
|
let result = `styles`;
|
2016-06-24 11:46:43 -04:00
|
|
|
if (component) {
|
2016-11-23 12:42:19 -05:00
|
|
|
result += `_${identifierName(component.type)}`;
|
2015-09-02 18:07:31 -04:00
|
|
|
}
|
2016-01-06 17:13:44 -05:00
|
|
|
return result;
|
2016-04-28 20:50:03 -04:00
|
|
|
}
|