public function resolveRelativeUri(string $uri): string
    {
        $parts = parse_url($uri);
        if (isset($parts['scheme'])) {
            // absolute URL
            return $uri;
        }

        $baseUri = $this->getUri();
        if (strncmp($baseUri, 'file://', 7) === 0) {
            if (isset($parts['path'][0]) && $parts['path'][0] === '/') {
                // absolute path
                return 'file://' . $parts['path'];
            }
            if (isset($parts['path'])) {
                // relative path
                return dirname($baseUri) . '/' . $parts['path'];
            }

            throw new UnresolvableReferenceException("Invalid URI: '$uri'");
        }

        $baseParts = parse_url($baseUri);
        $absoluteUri = implode('', [
            $baseParts['scheme'],
            '://',
            isset($baseParts['username']) ? $baseParts['username'] . (
                isset($baseParts['password']) ? ':' . $baseParts['password'] : ''
            ) . '@' : '',
            $baseParts['host'] ?? '',
            isset($baseParts['port']) ? ':' . $baseParts['port'] : '',
        ]);
        if (isset($parts['path'][0]) && $parts['path'][0] === '/') {
            $absoluteUri .= $parts['path'];
        } elseif (isset($parts['path'])) {
            $absoluteUri .= rtrim(dirname($baseParts['path'] ?? ''), '/') . '/' . $parts['path'];
        }
        return $absoluteUri
            . (isset($parts['query']) ? '?' . $parts['query'] : '')
            . (isset($parts['fragment']) ? '#' . $parts['fragment'] : '');
    }