feat(compiler): add support `::ng-deep`

- /deep/ is deprecated and being removed from Chrome
- >>> is semantically invalid in a stylesheet
- sass will no longer support either in any version of sass

-> use ::ng-deep in emulated shadow DOM mode

Because the deep combinator is deprecated in the CSS spec,
`/deep/`, `>>>` and `::ng-deep` are also deprecated in emulated shadow DOM mode
and will be removed in the future.

see https://www.chromestatus.com/features/6750456638341120
This commit is contained in:
Victor Berchet 2017-06-21 16:53:37 -07:00 committed by Matias Niemelä
parent 81734cf7b6
commit b754e600e3
3 changed files with 32 additions and 7 deletions

View File

@ -119,12 +119,13 @@ if some ancestor element has the CSS class `theme-light`.
### /deep/ ### (deprecated) `/deep/`, `>>>`, and `::ng-deep`
Component styles normally apply only to the HTML in the component's own template. Component styles normally apply only to the HTML in the component's own template.
Use the `/deep/` selector to force a style down through the child component tree into all the child component views. Use the `/deep/` shadow-piercing descendant combinator to force a style down through the child
The `/deep/` selector works to any depth of nested components, and it applies to both the view component tree into all the child component views.
The `/deep/` combinator works to any depth of nested components, and it applies to both the view
children and content children of the component. children and content children of the component.
The following example targets all `<h3>` elements, from the host element down The following example targets all `<h3>` elements, from the host element down
@ -134,17 +135,24 @@ through this component to all of its child elements in the DOM.
</code-example> </code-example>
The `/deep/` selector also has the alias `>>>`. You can use either interchangeably. The `/deep/` combinator also has the aliases `>>>`, and `::ng-deep`.
<div class="alert is-important"> <div class="alert is-important">
Use the `/deep/` and `>>>` selectors only with *emulated* view encapsulation. Use `/deep/`, `>>>` and `::ng-deep` only with *emulated* view encapsulation.
Emulated is the default and most commonly used view encapsulation. For more information, see the Emulated is the default and most commonly used view encapsulation. For more information, see the
[Controlling view encapsulation](guide/component-styles#view-encapsulation) section. [Controlling view encapsulation](guide/component-styles#view-encapsulation) section.
</div> </div>
<div class="alert is-important">
The shadow-piercing descendant combinator is deprecated and [support is being removed from major browsers](https://www.chromestatus.com/features/6750456638341120) and tools.
As such we plan to drop support in Angular (for all 3 of `/deep/`, `>>>` and `::ng-deep`).
Until then `::ng-deep` should be preferred for a broader compatibility with the tools.
</div>
{@a loading-styles} {@a loading-styles}
## Loading component styles ## Loading component styles

View File

@ -513,7 +513,11 @@ const _shadowDOMSelectorsRe = [
/\/shadow-deep\//g, /\/shadow-deep\//g,
/\/shadow\//g, /\/shadow\//g,
]; ];
const _shadowDeepSelectors = /(?:>>>)|(?:\/deep\/)/g;
// The deep combinator is deprecated in the CSS spec
// Support for `>>>`, `deep`, `::ng-deep` is then also deprecated and will be removed in the future.
// see https://github.com/angular/angular/pull/17677
const _shadowDeepSelectors = /(?:>>>)|(?:\/deep\/)|(?:::ng-deep)/g;
const _selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$'; const _selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$';
const _polyfillHostRe = /-shadowcsshost/gim; const _polyfillHostRe = /-shadowcsshost/gim;
const _colonHostRe = /:host/gim; const _colonHostRe = /:host/gim;

View File

@ -231,6 +231,19 @@ export function main() {
expect(css).toEqual('x[a] y {}'); expect(css).toEqual('x[a] y {}');
}); });
it('should handle ::ng-deep', () => {
let css = '::ng-deep y {}';
expect(s(css, 'a')).toEqual('y {}');
css = 'x ::ng-deep y {}';
expect(s(css, 'a')).toEqual('x[a] y {}');
css = ':host > ::ng-deep .x {}';
expect(s(css, 'a', 'h')).toEqual('[h] > .x {}');
css = ':host ::ng-deep > .x {}';
expect(s(css, 'a', 'h')).toEqual('[h] > .x {}');
css = ':host > ::ng-deep > .x {}';
expect(s(css, 'a', 'h')).toEqual('[h] > > .x {}');
});
it('should pass through @import directives', () => { it('should pass through @import directives', () => {
const styleStr = '@import url("https://fonts.googleapis.com/css?family=Roboto");'; const styleStr = '@import url("https://fonts.googleapis.com/css?family=Roboto");';
const css = s(styleStr, 'a'); const css = s(styleStr, 'a');