declarationsToStyle function

Style declarationsToStyle(
  1. Map<String, List<Expression>> declarations
)

Implementation

Style declarationsToStyle(Map<String, List<css.Expression>> declarations) {
  Style style = Style();
  declarations.forEach((property, value) {
    if (value.isNotEmpty) {
      switch (property) {
        case 'background-color':
          style.backgroundColor = ExpressionMapping.expressionToColor(value.first) ?? style.backgroundColor;
          break;
        case 'border':
          List<css.LiteralTerm?>? borderWidths = value.whereType<css.LiteralTerm>().toList();
          /// List<css.LiteralTerm> might include other values than the ones we want for [BorderSide.width], so make sure to remove those before passing it to [ExpressionMapping]
          borderWidths.removeWhere((element) => element == null || (element.text != "thin"
              && element.text != "medium" && element.text != "thick"
              && element is! css.LengthTerm && element is! css.PercentageTerm
              && element is! css.EmTerm && element is! css.RemTerm
              && element is! css.NumberTerm)
          );
          List<css.Expression?>? borderColors = value.where((element) => ExpressionMapping.expressionToColor(element) != null).toList();
          List<css.LiteralTerm?>? potentialStyles = value.whereType<css.LiteralTerm>().toList();
          /// Currently doesn't matter, as Flutter only supports "solid" or "none", but may support more in the future.
          List<String> possibleBorderValues = ["dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset", "none", "hidden"];
          /// List<css.LiteralTerm> might include other values than the ones we want for [BorderSide.style], so make sure to remove those before passing it to [ExpressionMapping]
          potentialStyles.removeWhere((element) => element == null || !possibleBorderValues.contains(element.text));
          List<css.LiteralTerm?>? borderStyles = potentialStyles;
          style.border = ExpressionMapping.expressionToBorder(borderWidths, borderStyles, borderColors);
          break;
        case 'border-left':
          List<css.LiteralTerm?>? borderWidths = value.whereType<css.LiteralTerm>().toList();
          /// List<css.LiteralTerm> might include other values than the ones we want for [BorderSide.width], so make sure to remove those before passing it to [ExpressionMapping]
          borderWidths.removeWhere((element) => element == null || (element.text != "thin"
              && element.text != "medium" && element.text != "thick"
              && element is! css.LengthTerm && element is! css.PercentageTerm
              && element is! css.EmTerm && element is! css.RemTerm
              && element is! css.NumberTerm)
          );
          css.LiteralTerm? borderWidth = borderWidths.firstWhereOrNull((element) => element != null);
          css.Expression? borderColor = value.firstWhereOrNull((element) => ExpressionMapping.expressionToColor(element) != null);
          List<css.LiteralTerm?>? potentialStyles = value.whereType<css.LiteralTerm>().toList();
          /// Currently doesn't matter, as Flutter only supports "solid" or "none", but may support more in the future.
          List<String> possibleBorderValues = ["dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset", "none", "hidden"];
          /// List<css.LiteralTerm> might include other values than the ones we want for [BorderSide.style], so make sure to remove those before passing it to [ExpressionMapping]
          potentialStyles.removeWhere((element) => element == null || !possibleBorderValues.contains(element.text));
          css.LiteralTerm? borderStyle = potentialStyles.firstOrNull;
          Border newBorder = Border(
            left: style.border?.left.copyWith(
              width: ExpressionMapping.expressionToBorderWidth(borderWidth),
              style: ExpressionMapping.expressionToBorderStyle(borderStyle),
              color: ExpressionMapping.expressionToColor(borderColor),
            ) ?? BorderSide(
              width: ExpressionMapping.expressionToBorderWidth(borderWidth),
              style: ExpressionMapping.expressionToBorderStyle(borderStyle),
              color: ExpressionMapping.expressionToColor(borderColor) ?? Colors.black,
            ),
            right: style.border?.right ?? BorderSide.none,
            top: style.border?.top ?? BorderSide.none,
            bottom: style.border?.bottom ?? BorderSide.none,
          );
          style.border = newBorder;
          break;
        case 'border-right':
          List<css.LiteralTerm?>? borderWidths = value.whereType<css.LiteralTerm>().toList();
          /// List<css.LiteralTerm> might include other values than the ones we want for [BorderSide.width], so make sure to remove those before passing it to [ExpressionMapping]
          borderWidths.removeWhere((element) => element == null || (element.text != "thin"
              && element.text != "medium" && element.text != "thick"
              && element is! css.LengthTerm && element is! css.PercentageTerm
              && element is! css.EmTerm && element is! css.RemTerm
              && element is! css.NumberTerm)
          );
          css.LiteralTerm? borderWidth = borderWidths.firstWhereOrNull((element) => element != null);
          css.Expression? borderColor = value.firstWhereOrNull((element) => ExpressionMapping.expressionToColor(element) != null);
          List<css.LiteralTerm?>? potentialStyles = value.whereType<css.LiteralTerm>().toList();
          /// Currently doesn't matter, as Flutter only supports "solid" or "none", but may support more in the future.
          List<String> possibleBorderValues = ["dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset", "none", "hidden"];
          /// List<css.LiteralTerm> might include other values than the ones we want for [BorderSide.style], so make sure to remove those before passing it to [ExpressionMapping]
          potentialStyles.removeWhere((element) => element == null || !possibleBorderValues.contains(element.text));
          css.LiteralTerm? borderStyle = potentialStyles.firstOrNull;
          Border newBorder = Border(
            left: style.border?.left ?? BorderSide.none,
            right: style.border?.right.copyWith(
              width: ExpressionMapping.expressionToBorderWidth(borderWidth),
              style: ExpressionMapping.expressionToBorderStyle(borderStyle),
              color: ExpressionMapping.expressionToColor(borderColor),
            ) ?? BorderSide(
              width: ExpressionMapping.expressionToBorderWidth(borderWidth),
              style: ExpressionMapping.expressionToBorderStyle(borderStyle),
              color: ExpressionMapping.expressionToColor(borderColor) ?? Colors.black,
            ),
            top: style.border?.top ?? BorderSide.none,
            bottom: style.border?.bottom ?? BorderSide.none,
          );
          style.border = newBorder;
          break;
        case 'border-top':
          List<css.LiteralTerm?>? borderWidths = value.whereType<css.LiteralTerm>().toList();
          /// List<css.LiteralTerm> might include other values than the ones we want for [BorderSide.width], so make sure to remove those before passing it to [ExpressionMapping]
          borderWidths.removeWhere((element) => element == null || (element.text != "thin"
              && element.text != "medium" && element.text != "thick"
              && element is! css.LengthTerm && element is! css.PercentageTerm
              && element is! css.EmTerm && element is! css.RemTerm
              && element is! css.NumberTerm)
          );
          css.LiteralTerm? borderWidth = borderWidths.firstWhereOrNull((element) => element != null);
          css.Expression? borderColor = value.firstWhereOrNull((element) => ExpressionMapping.expressionToColor(element) != null);
          List<css.LiteralTerm?>? potentialStyles = value.whereType<css.LiteralTerm>().toList();
          /// Currently doesn't matter, as Flutter only supports "solid" or "none", but may support more in the future.
          List<String> possibleBorderValues = ["dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset", "none", "hidden"];
          /// List<css.LiteralTerm> might include other values than the ones we want for [BorderSide.style], so make sure to remove those before passing it to [ExpressionMapping]
          potentialStyles.removeWhere((element) => element == null || !possibleBorderValues.contains(element.text));
          css.LiteralTerm? borderStyle = potentialStyles.firstOrNull;
          Border newBorder = Border(
            left: style.border?.left ?? BorderSide.none,
            right: style.border?.right ?? BorderSide.none,
            top: style.border?.top.copyWith(
              width: ExpressionMapping.expressionToBorderWidth(borderWidth),
              style: ExpressionMapping.expressionToBorderStyle(borderStyle),
              color: ExpressionMapping.expressionToColor(borderColor),
            ) ?? BorderSide(
              width: ExpressionMapping.expressionToBorderWidth(borderWidth),
              style: ExpressionMapping.expressionToBorderStyle(borderStyle),
              color: ExpressionMapping.expressionToColor(borderColor) ?? Colors.black,
            ),
            bottom: style.border?.bottom ?? BorderSide.none,
          );
          style.border = newBorder;
          break;
        case 'border-bottom':
          List<css.LiteralTerm?>? borderWidths = value.whereType<css.LiteralTerm>().toList();
          /// List<css.LiteralTerm> might include other values than the ones we want for [BorderSide.width], so make sure to remove those before passing it to [ExpressionMapping]
          borderWidths.removeWhere((element) => element == null || (element.text != "thin"
              && element.text != "medium" && element.text != "thick"
              && element is! css.LengthTerm && element is! css.PercentageTerm
              && element is! css.EmTerm && element is! css.RemTerm
              && element is! css.NumberTerm)
          );
          css.LiteralTerm? borderWidth = borderWidths.firstWhereOrNull((element) => element != null);
          css.Expression? borderColor = value.firstWhereOrNull((element) => ExpressionMapping.expressionToColor(element) != null);
          List<css.LiteralTerm?>? potentialStyles = value.whereType<css.LiteralTerm>().toList();
          /// Currently doesn't matter, as Flutter only supports "solid" or "none", but may support more in the future.
          List<String> possibleBorderValues = ["dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset", "none", "hidden"];
          /// List<css.LiteralTerm> might include other values than the ones we want for [BorderSide.style], so make sure to remove those before passing it to [ExpressionMapping]
          potentialStyles.removeWhere((element) => element == null || !possibleBorderValues.contains(element.text));
          css.LiteralTerm? borderStyle = potentialStyles.firstOrNull;
          Border newBorder = Border(
            left: style.border?.left ?? BorderSide.none,
            right: style.border?.right ?? BorderSide.none,
            top: style.border?.top ?? BorderSide.none,
            bottom: style.border?.bottom.copyWith(
              width: ExpressionMapping.expressionToBorderWidth(borderWidth),
              style: ExpressionMapping.expressionToBorderStyle(borderStyle),
              color: ExpressionMapping.expressionToColor(borderColor),
            ) ?? BorderSide(
              width: ExpressionMapping.expressionToBorderWidth(borderWidth),
              style: ExpressionMapping.expressionToBorderStyle(borderStyle),
              color: ExpressionMapping.expressionToColor(borderColor) ?? Colors.black,
            ),
          );
          style.border = newBorder;
          break;
        case 'color':
          style.color = ExpressionMapping.expressionToColor(value.first) ?? style.color;
          break;
        case 'direction':
          style.direction = ExpressionMapping.expressionToDirection(value.first);
          break;
        case 'display':
          style.display = ExpressionMapping.expressionToDisplay(value.first);
          break;
        case 'line-height':
          style.lineHeight = ExpressionMapping.expressionToLineHeight(value.first);
          break;
        case 'font-family':
          style.fontFamily = ExpressionMapping.expressionToFontFamily(value.first) ?? style.fontFamily;
          break;
        case 'font-feature-settings':
          style.fontFeatureSettings = ExpressionMapping.expressionToFontFeatureSettings(value);
          break;
        case 'font-size':
          style.fontSize = ExpressionMapping.expressionToFontSize(value.first) ?? style.fontSize;
          break;
        case 'font-style':
          style.fontStyle = ExpressionMapping.expressionToFontStyle(value.first);
          break;
        case 'font-weight':
          style.fontWeight = ExpressionMapping.expressionToFontWeight(value.first);
          break;
        case 'list-style':
          css.LiteralTerm? position = value.firstWhereOrNull((e) => e is css.LiteralTerm && (e.text == "outside" || e.text == "inside")) as css.LiteralTerm?;
          css.UriTerm? image = value.firstWhereOrNull((e) => e is css.UriTerm) as css.UriTerm?;
          css.LiteralTerm? type = value.firstWhereOrNull((e) => e is css.LiteralTerm && e.text != "outside" && e.text != "inside") as css.LiteralTerm?;
          if (position != null) {
            switch (position.text) {
              case 'outside':
                style.listStylePosition = ListStylePosition.OUTSIDE;
                break;
              case 'inside':
                style.listStylePosition = ListStylePosition.INSIDE;
                break;
            }
          }
          if (image != null) {
            style.listStyleType = ExpressionMapping.expressionToListStyleType(image) ?? style.listStyleType;
          } else if (type != null) {
            style.listStyleType = ExpressionMapping.expressionToListStyleType(type) ?? style.listStyleType;
          }
          break;
        case 'list-style-image':
          if (value.first is css.UriTerm) {
            style.listStyleType = ExpressionMapping.expressionToListStyleType(value.first as css.UriTerm) ?? style.listStyleType;
          }
          break;
        case 'list-style-position':
          if (value.first is css.LiteralTerm) {
            switch ((value.first as css.LiteralTerm).text) {
              case 'outside':
                style.listStylePosition = ListStylePosition.OUTSIDE;
                break;
              case 'inside':
                style.listStylePosition = ListStylePosition.INSIDE;
                break;
            }
          }
          break;
        case 'height':
          style.height = ExpressionMapping.expressionToPaddingLength(value.first) ?? style.height;
          break;
        case 'list-style-type':
          if (value.first is css.LiteralTerm) {
            style.listStyleType = ExpressionMapping.expressionToListStyleType(value.first as css.LiteralTerm) ?? style.listStyleType;
          }
          break;
        case 'margin':
          List<css.LiteralTerm>? marginLengths = value.whereType<css.LiteralTerm>().toList();
          /// List<css.LiteralTerm> might include other values than the ones we want for margin length, so make sure to remove those before passing it to [ExpressionMapping]
          marginLengths.removeWhere((element) => element is! css.LengthTerm
              && element is! css.EmTerm
              && element is! css.RemTerm
              && element is! css.NumberTerm
          );
          List<double?> margin = ExpressionMapping.expressionToPadding(marginLengths);
          style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
            left: margin[0],
            right: margin[1],
            top: margin[2],
            bottom: margin[3],
          );
          break;
        case 'margin-left':
          style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
              left: ExpressionMapping.expressionToPaddingLength(value.first));
          break;
        case 'margin-right':
          style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
              right: ExpressionMapping.expressionToPaddingLength(value.first));
          break;
        case 'margin-top':
          style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
              top: ExpressionMapping.expressionToPaddingLength(value.first));
          break;
        case 'margin-bottom':
          style.margin = (style.margin ?? EdgeInsets.zero).copyWith(
              bottom: ExpressionMapping.expressionToPaddingLength(value.first));
          break;
        case 'padding':
          List<css.LiteralTerm>? paddingLengths = value.whereType<css.LiteralTerm>().toList();
          /// List<css.LiteralTerm> might include other values than the ones we want for padding length, so make sure to remove those before passing it to [ExpressionMapping]
          paddingLengths.removeWhere((element) => element is! css.LengthTerm
              && element is! css.EmTerm
              && element is! css.RemTerm
              && element is! css.NumberTerm
          );
          List<double?> padding = ExpressionMapping.expressionToPadding(paddingLengths);
          style.padding = (style.padding ?? EdgeInsets.zero).copyWith(
            left: padding[0],
            right: padding[1],
            top: padding[2],
            bottom: padding[3],
          );
          break;
        case 'padding-left':
          style.padding = (style.padding ?? EdgeInsets.zero).copyWith(
              left: ExpressionMapping.expressionToPaddingLength(value.first));
          break;
        case 'padding-right':
          style.padding = (style.padding ?? EdgeInsets.zero).copyWith(
              right: ExpressionMapping.expressionToPaddingLength(value.first));
          break;
        case 'padding-top':
          style.padding = (style.padding ?? EdgeInsets.zero).copyWith(
              top: ExpressionMapping.expressionToPaddingLength(value.first));
          break;
        case 'padding-bottom':
          style.padding = (style.padding ?? EdgeInsets.zero).copyWith(
              bottom: ExpressionMapping.expressionToPaddingLength(value.first));
          break;
        case 'text-align':
          style.textAlign = ExpressionMapping.expressionToTextAlign(value.first);
          break;
        case 'text-decoration':
          List<css.LiteralTerm?>? textDecorationList = value.whereType<css.LiteralTerm>().toList();
          /// List<css.LiteralTerm> might include other values than the ones we want for [textDecorationList], so make sure to remove those before passing it to [ExpressionMapping]
          textDecorationList.removeWhere((element) => element == null || (element.text != "none"
              && element.text != "overline" && element.text != "underline" && element.text != "line-through"));
          List<css.Expression?>? nullableList = value;
          css.Expression? textDecorationColor;
          textDecorationColor = nullableList.firstWhereOrNull(
                  (element) => element is css.HexColorTerm || element is css.FunctionTerm);
          List<css.LiteralTerm?>? potentialStyles = value.whereType<css.LiteralTerm>().toList();
          /// List<css.LiteralTerm> might include other values than the ones we want for [textDecorationStyle], so make sure to remove those before passing it to [ExpressionMapping]
          potentialStyles.removeWhere((element) => element == null || (element.text != "solid"
              && element.text != "double" && element.text != "dashed" && element.text != "dotted" && element.text != "wavy"));
          css.LiteralTerm? textDecorationStyle = potentialStyles.isNotEmpty ? potentialStyles.last : null;
          style.textDecoration = ExpressionMapping.expressionToTextDecorationLine(textDecorationList);
          if (textDecorationColor != null) {
            style.textDecorationColor = ExpressionMapping.expressionToColor(textDecorationColor)
              ?? style.textDecorationColor;
          }
          if (textDecorationStyle != null) style.textDecorationStyle = ExpressionMapping.expressionToTextDecorationStyle(textDecorationStyle);
          break;
        case 'text-decoration-color':
          style.textDecorationColor = ExpressionMapping.expressionToColor(value.first) ?? style.textDecorationColor;
          break;
        case 'text-decoration-line':
          List<css.LiteralTerm?>? textDecorationList = value.whereType<css.LiteralTerm>().toList();
          style.textDecoration = ExpressionMapping.expressionToTextDecorationLine(textDecorationList);
          break;
        case 'text-decoration-style':
          style.textDecorationStyle = ExpressionMapping.expressionToTextDecorationStyle(value.first as css.LiteralTerm);
          break;
        case 'text-shadow':
          style.textShadow = ExpressionMapping.expressionToTextShadow(value);
          break;
        case 'text-transform':
          final val = (value.first as css.LiteralTerm).text;
          if (val == 'uppercase') {
            style.textTransform = TextTransform.uppercase;
          } else if (val == 'lowercase') {
            style.textTransform = TextTransform.lowercase;
          } else if (val == 'capitalize') {
            style.textTransform = TextTransform.capitalize;
          } else {
            style.textTransform = TextTransform.none;
          }
          break;
        case 'width':
          style.width = ExpressionMapping.expressionToPaddingLength(value.first) ?? style.width;
          break;
      }
    }
  });
  return style;
}