replaceCssVarFunctionsIndexed function

String replaceCssVarFunctionsIndexed(
  1. String input,
  2. String replacer(
    1. String varFunctionText,
    2. int start,
    3. int end
    )
)

Same as replaceCssVarFunctions, but provides the match range as UTF-16 code unit indices: [start, end) in the original input.

Implementation

String replaceCssVarFunctionsIndexed(
  String input,
  String Function(String varFunctionText, int start, int end) replacer,
) {
  if (!input.contains('var(')) return input;
  final int len = input.length;
  final StringBuffer out = StringBuffer();
  int i = 0;

  while (i < len) {
    final int idx = input.indexOf('var(', i);
    if (idx == -1) {
      out.write(input.substring(i));
      break;
    }
    out.write(input.substring(i, idx));

    final int open = idx + 3;
    if (open >= len || input.codeUnitAt(open) != 0x28 /* ( */) {
      out.write('var');
      i = open;
      continue;
    }

    int depth = 0;
    String? quote;
    bool escape = false;
    int j = open;
    for (; j < len; j++) {
      final String ch = input[j];
      final int cu = input.codeUnitAt(j);

      if (quote != null) {
        if (escape) {
          escape = false;
        } else if (ch == '\\') {
          escape = true;
        } else if (ch == quote) {
          quote = null;
        }
        continue;
      }

      if (ch == '"' || ch == '\'') {
        quote = ch;
        continue;
      }

      if (cu == 0x28 /* ( */) {
        depth++;
      } else if (cu == 0x29 /* ) */) {
        depth--;
        if (depth == 0) {
          final int end = j + 1;
          final String varText = input.substring(idx, end);
          out.write(replacer(varText, idx, end));
          i = end;
          break;
        }
      }
    }

    if (j >= len) {
      out.write(input.substring(idx));
      break;
    }
  }

  return out.toString();
}