Uri? relativizeUri()

in lib/src/util.dart [171:228]


Uri? relativizeUri(Uri? uri, Uri? baseUri) {
  if (baseUri == null) return uri;
  assert(baseUri.isAbsolute);
  if (uri!.hasQuery || uri.hasFragment) {
    uri = Uri(
        scheme: uri.scheme,
        userInfo: uri.hasAuthority ? uri.userInfo : null,
        host: uri.hasAuthority ? uri.host : null,
        port: uri.hasAuthority ? uri.port : null,
        path: uri.path);
  }

  // Already relative. We assume the caller knows what they are doing.
  if (!uri.isAbsolute) return uri;

  if (baseUri.scheme != uri.scheme) {
    return uri;
  }

  // If authority differs, we could remove the scheme, but it's not worth it.
  if (uri.hasAuthority != baseUri.hasAuthority) return uri;
  if (uri.hasAuthority) {
    if (uri.userInfo != baseUri.userInfo ||
        uri.host.toLowerCase() != baseUri.host.toLowerCase() ||
        uri.port != baseUri.port) {
      return uri;
    }
  }

  baseUri = baseUri.normalizePath();
  var base = [...baseUri.pathSegments];
  if (base.isNotEmpty) base.removeLast();
  uri = uri.normalizePath();
  var target = [...uri.pathSegments];
  if (target.isNotEmpty && target.last.isEmpty) target.removeLast();
  var index = 0;
  while (index < base.length && index < target.length) {
    if (base[index] != target[index]) {
      break;
    }
    index++;
  }
  if (index == base.length) {
    if (index == target.length) {
      return Uri(path: './');
    }
    return Uri(path: target.skip(index).join('/'));
  } else if (index > 0) {
    var buffer = StringBuffer();
    for (var n = base.length - index; n > 0; --n) {
      buffer.write('../');
    }
    buffer.writeAll(target.skip(index), '/');
    return Uri(path: buffer.toString());
  } else {
    return uri;
  }
}