shimShadowCss function

String shimShadowCss(
  1. String css,
  2. String contentClass,
  3. String hostClass, {
  4. bool useLegacyEncapsulation = false,
})

This is a limited shim for Shadow DOM CSS styling.

Shimmed features:

  • Shadow Host Selectors

    Allows styling of the shadow host element using :host, :host(), and :host-context() selectors. To shim this feature, these selectors are reformatted and scoped with a host specific class.

    :host => .host :host(div) => div.host :host-context(div) => div.host, div .host

  • Encapsulation

    Styles defined within a shadow tree apply only to its contents. To shim this feature, all selectors except those preceding or containing shadow host selectors are scoped with a host specific content class.

    div => div.content :host(.foo) .bar => .foo.host .bar.content :global-context(.foo) .bar => .foo .bar.content

  • Shadow Piercing Combinators

    The ::ng-deep combinator allows a selector to pierce shadow boundaries and target nodes within a child host's shadow tree. To shim this feature, the combinator is replaced by the descendant combinator, and the following selectors aren't scoped with the host specific content class.

    .x ::ng-deep .y => .x.content .y

  • Polyfill Selectors - DO NOT USE, SUPPORTED FOR LEGACY ONLY

    The 'polyfill-unscoped-rule' selector indicates that the rule set's styles should not be encapsulated.

    For example,

    polyfill-unscoped-rule {
      content: '.menu > .menu-item';
      font-size: 12px;
    }
    

    becomes

    .menu > .menu-item {
      font-size: 12px;
    }
    

    The 'polyfill-next-selector' selector allows for application of a separate selector to a rule set only when this shim is applied. This is useful if the native Shadow DOM CSS selector is unsupported by the shim.

    For example,

    polyfill-next-selector { content: ':host .menu'; }
    ::slotted(.menu) {
      font-size: 12px;
    }
    

    becomes

    .host .menu.content {
      font-size: 12px;
    }
    

Implementation

String shimShadowCss(
  String css,
  String contentClass,
  String hostClass, {
  bool useLegacyEncapsulation = false,
}) {
  var errors = <Message>[];
  var styleSheet = parse(css, errors: errors);

  if (errors.isNotEmpty) {
    logWarning('Errors parsing CSS:\n${errors.join('\n')}');
  }

  var shadowTransformer = useLegacyEncapsulation
      ? _LegacyShadowTransformer(contentClass, hostClass)
      : _ShadowTransformer(contentClass, hostClass);
  shadowTransformer.visitTree(styleSheet);
  var printer = CssPrinter();
  printer.visitTree(styleSheet);
  return printer.toString();
}