processLayerDirective method

List<CSSRule>? processLayerDirective()

Parses @layer ... and returns rules.

Note: layer blocks are represented as CSSLayerBlockRule (with nested cssRules) instead of being flattened into top-level CSSStyleRules.

Supported:

  • @layer { ... } (anonymous layer block)
  • @layer name { ... } (named layer block)
  • @layer a, b; (layer order statement)
  • @layer a.b; / @layer a.b { ... } (nested layer names)

Implementation

List<CSSRule>? processLayerDirective() {
  _eat(TokenKind.DIRECTIVE_LAYER);

  // `@layer { ... }`
  if (_peekKind(TokenKind.LBRACE)) {
    final anon = _resolveLayerPath(<String>[_createAnonymousLayerSegment()]);
    final nodes = <CSSRule>[];

    final prev = List<String>.from(_layerStack);
    _layerStack
      ..clear()
      ..addAll(anon);

    _eat(TokenKind.LBRACE);
    nodes.addAll(processGroupRuleBody());
    _eat(TokenKind.RBRACE);

    _layerStack
      ..clear()
      ..addAll(prev);

    return <CSSRule>[
      CSSLayerBlockRule(
        name: '',
        layerNamePath: anon,
        cssRules: nodes,
      )
    ];
  }

  final rawNames = _processLayerNameList();

  // `@layer a, b;`
  if (_maybeEat(TokenKind.SEMICOLON)) {
    if (rawNames.isEmpty) return null;
    final resolved = rawNames.map(_resolveLayerPath).toList(growable: false);
    return <CSSRule>[CSSLayerStatementRule(resolved)];
  }

  // `@layer name { ... }`
  if (_peekKind(TokenKind.LBRACE)) {
    final List<String> layerName = rawNames.isEmpty
        ? <String>[_createAnonymousLayerSegment()]
        : rawNames.first;
    final fullPath = _resolveLayerPath(layerName);

    final nodes = <CSSRule>[];

    final prev = List<String>.from(_layerStack);
    _layerStack
      ..clear()
      ..addAll(fullPath);

    _eat(TokenKind.LBRACE);
    nodes.addAll(processGroupRuleBody());
    _eat(TokenKind.RBRACE);

    _layerStack
      ..clear()
      ..addAll(prev);

    final String nameText = rawNames.isEmpty ? '' : rawNames.first.join('.');
    return <CSSRule>[
      CSSLayerBlockRule(
        name: nameText,
        layerNamePath: fullPath,
        cssRules: nodes,
      )
    ];
  }

  return null;
}