expandInlineVars static method

String expandInlineVars(
  1. String input,
  2. RenderStyle renderStyle,
  3. String propertyName
)

Implementation

static String expandInlineVars(String input, RenderStyle renderStyle, String propertyName) {
  if (!input.contains('var(')) return input;
  String result = input;
  int guard = 0;
  while (result.contains('var(') && guard++ < 8) {
    final before = result;
    result = result.replaceAllMapped(_inlineVarFunctionRegExp, (Match match) {
      final String? varString = match[0];
      if (varString == null) return '';
      final CSSVariable? variable = CSSVariable.tryParse(renderStyle, varString);
      if (variable == null) return varString; // keep as-is

      final depKey = propertyName + '_' + input;
      final dynamic raw = renderStyle.getCSSVariable(variable.identifier, depKey);

      if (raw == null || raw == INITIAL) {
        // Use fallback if provided; otherwise preserve var(...) so the
        // property fails to parse and becomes invalid/inherited.
        final fallback = variable.defaultValue;
        return fallback?.toString() ?? varString;
      }
      // Avoid accidental token concatenation per CSS Variables spec: substitution
      // must not re-tokenize. When the replacement's boundary characters and
      // surrounding characters are ident-like, insert whitespace to keep tokens
      // separate (e.g., var(--b)red -> 'orange red', not 'orangered').
      bool isIdentCode(int c) {
        return (c >= 48 && c <= 57) || // 0-9
            (c >= 65 && c <= 90) || // A-Z
            (c >= 97 && c <= 122) || // a-z
            c == 45 || // '-'
            c == 95; // '_'
      }
      final int start = match.start;
      final int end = match.end;
      final int? leftChar = start > 0 ? before.codeUnitAt(start - 1) : null;
      final int? rightChar = end < before.length ? before.codeUnitAt(end) : null;
      String rep = raw.toString();
      String trimmed = rep.trim();
      final int? repFirst = trimmed.isNotEmpty ? trimmed.codeUnitAt(0) : null;
      final int? repLast = trimmed.isNotEmpty ? trimmed.codeUnitAt(trimmed.length - 1) : null;
      final bool addLeftSpace = leftChar != null && repFirst != null && isIdentCode(leftChar) && isIdentCode(repFirst);
      final bool addRightSpace = rightChar != null && repLast != null && isIdentCode(repLast) && isIdentCode(rightChar);
      if (addLeftSpace) rep = ' ' + rep;
      if (addRightSpace) rep = rep + ' ';
      return rep;
    });
    if (result == before) break;
  }

  return result;
}