feat(ivy): bridge component styles into the component renderer (#25255)
PR Close #25255
This commit is contained in:
@ -188,6 +188,7 @@ export class CompileStylesheetMetadata {
|
||||
export interface CompileTemplateSummary {
|
||||
ngContentSelectors: string[];
|
||||
encapsulation: ViewEncapsulation|null;
|
||||
styles: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,6 +244,7 @@ export class CompileTemplateMetadata {
|
||||
return {
|
||||
ngContentSelectors: this.ngContentSelectors,
|
||||
encapsulation: this.encapsulation,
|
||||
styles: this.styles
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ViewEncapsulation} from '../../core';
|
||||
import * as o from '../../output/output_ast';
|
||||
import {ParseSourceSpan} from '../../parse_util';
|
||||
import * as t from '../r3_ast';
|
||||
@ -151,6 +152,22 @@ export interface R3ComponentMetadata extends R3DirectiveMetadata {
|
||||
* This is done when the directives contain forward references.
|
||||
*/
|
||||
wrapDirectivesInClosure: boolean;
|
||||
|
||||
/**
|
||||
* A collection of styling data that will be applied and scoped to the component.
|
||||
*/
|
||||
styles: string[];
|
||||
|
||||
/**
|
||||
* An encapsulation policy for the template and CSS styles. One of:
|
||||
* - `ViewEncapsulation.Native`: Use shadow roots. This works only if natively available on the
|
||||
* platform (note that this is marked the as the "deprecated shadow DOM" as of Angular v6.1.
|
||||
* - `ViewEncapsulation.Emulated`: Use shimmed CSS that emulates the native behavior.
|
||||
* - `ViewEncapsulation.None`: Use global CSS without any encapsulation.
|
||||
* - `ViewEncapsulation.ShadowDom`: Use the latest ShadowDOM API to natively encapsulate styles
|
||||
* into a shadow root.
|
||||
*/
|
||||
encapsulation: ViewEncapsulation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,6 +16,8 @@ import {LifecycleHooks} from '../../lifecycle_reflector';
|
||||
import * as o from '../../output/output_ast';
|
||||
import {typeSourceSpan} from '../../parse_util';
|
||||
import {CssSelector, SelectorMatcher} from '../../selector';
|
||||
import {ShadowCss} from '../../shadow_css';
|
||||
import {CONTENT_ATTR, HOST_ATTR} from '../../style_compiler';
|
||||
import {BindingParser} from '../../template_parser/binding_parser';
|
||||
import {OutputContext, error} from '../../util';
|
||||
import {compileFactoryFunction, dependenciesFromGlobalMetadata} from '../r3_factory';
|
||||
@ -27,6 +29,8 @@ import {R3ComponentDef, R3ComponentMetadata, R3DirectiveDef, R3DirectiveMetadata
|
||||
import {BindingScope, TemplateDefinitionBuilder, renderFlagCheckIfStmt} from './template';
|
||||
import {CONTEXT_NAME, DefinitionMap, RENDER_FLAGS, TEMPORARY_NAME, asLiteral, conditionallyCreateMapObjectLiteral, getQueryPredicate, temporaryAllocator} from './util';
|
||||
|
||||
const EMPTY_ARRAY: any[] = [];
|
||||
|
||||
function baseDirectiveFields(
|
||||
meta: R3DirectiveMetadata, constantPool: ConstantPool,
|
||||
bindingParser: BindingParser): {definitionMap: DefinitionMap, statements: o.Statement[]} {
|
||||
@ -218,6 +222,15 @@ export function compileComponentFromMetadata(
|
||||
definitionMap.set('pipes', o.literalArr(Array.from(pipesUsed)));
|
||||
}
|
||||
|
||||
// e.g. `styles: [str1, str2]`
|
||||
if (meta.styles && meta.styles.length) {
|
||||
const styleValues = meta.encapsulation == core.ViewEncapsulation.Emulated ?
|
||||
compileStyles(meta.styles, CONTENT_ATTR, HOST_ATTR) :
|
||||
meta.styles;
|
||||
const strings = styleValues.map(str => o.literal(str));
|
||||
definitionMap.set('styles', o.literalArr(strings));
|
||||
}
|
||||
|
||||
// On the type side, remove newlines from the selector as it will need to fit into a TypeScript
|
||||
// string literal, which must be on one line.
|
||||
const selectorForType = (meta.selector || '').replace(/\n/g, '');
|
||||
@ -287,6 +300,9 @@ export function compileComponentFromRender2(
|
||||
pipes: typeMapToExpressionMap(pipeTypeByName, outputCtx),
|
||||
viewQueries: queriesFromGlobalMetadata(component.viewQueries, outputCtx),
|
||||
wrapDirectivesInClosure: false,
|
||||
styles: (summary.template && summary.template.styles) || EMPTY_ARRAY,
|
||||
encapsulation:
|
||||
(summary.template && summary.template.encapsulation) || core.ViewEncapsulation.Emulated
|
||||
};
|
||||
const res = compileComponentFromMetadata(meta, outputCtx.constantPool, bindingParser);
|
||||
|
||||
@ -624,3 +640,8 @@ export function parseHostBindings(host: {[key: string]: string}): {
|
||||
|
||||
return {attributes, listeners, properties, animations};
|
||||
}
|
||||
|
||||
function compileStyles(styles: string[], selector: string, hostSelector: string): string[] {
|
||||
const shadowCss = new ShadowCss();
|
||||
return styles.map(style => { return shadowCss !.shimCssText(style, selector, hostSelector); });
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ import {UrlResolver} from './url_resolver';
|
||||
import {OutputContext} from './util';
|
||||
|
||||
const COMPONENT_VARIABLE = '%COMP%';
|
||||
const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
|
||||
const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
|
||||
export const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
|
||||
export const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
|
||||
|
||||
export class StylesCompileDependency {
|
||||
constructor(
|
||||
|
Reference in New Issue
Block a user