processDeclaration method

void processDeclaration(
  1. CSSStyleDeclaration style
)

Implementation

void processDeclaration(CSSStyleDeclaration style) {
  // IDENT ':' expr '!important'?
  if (TokenKind.isIdentifier(_peekToken.kind)) {
    var propertyIdent = camelize(identifier().name);

    var resetProperty = false;
    var keepGoing = true;
    while (keepGoing) {
      switch (_peek()) {
        case TokenKind.COLON:
          _eat(TokenKind.COLON);
          keepGoing = false;
          break;
        case TokenKind.SEMICOLON:
        case TokenKind.NEWLINE:
          resetProperty = true;
          _next();
          break;
        case TokenKind.IDENTIFIER:
          if (resetProperty) {
            propertyIdent = identifier().name;
          } else {
            keepGoing = false;
          }
          break;
        default:
          keepGoing = false;
      }
    }

    var expr = processExpr();
    if (expr != null) {
      // Handle !important (prio)
      var importantPriority = _maybeEat(TokenKind.IMPORTANT);

      // CSS only allows a single `!important` marker. If we see another
      // `!important` (or any other trailing token) before `;`/`}` then the
      // whole declaration is invalid and must be ignored, but we should
      // recover to continue parsing subsequent declarations.
      //
      // This matters for custom properties, e.g.:
      //   --a: var(--b) !important !important;
      // which must be dropped per spec.
      final trailingToken = _peek();
      final hasUnexpectedTrailingToken = trailingToken != TokenKind.SEMICOLON &&
          trailingToken != TokenKind.RBRACE &&
          trailingToken != TokenKind.END_OF_FILE;
      if ((importantPriority && trailingToken == TokenKind.IMPORTANT) || hasUnexpectedTrailingToken) {
        _skipToDeclarationEnd();
        return;
      }

      style.setProperty(propertyIdent, expr, isImportant: importantPriority, baseHref: href);
    }
  } else if (_peekToken.kind == TokenKind.VAR_DEFINITION) {
    _next();
  } else if (_peekToken.kind == TokenKind.DIRECTIVE_INCLUDE) {
    // TODO @include mixinName in the declaration area.
  } else if (_peekToken.kind == TokenKind.DIRECTIVE_EXTEND) {
    _next();
  }
}