tryResolveUrl method

String? tryResolveUrl(
  1. String reference, {
  2. String? branch,
  3. String? relativeFrom,
  4. bool? isEmbeddedObject,
})

Resolves a reference in relationship with the repository, and returns:

  • the same URL if the reference is absolute,
  • the same URL if the reference is in-page anchor,
  • a new URL if the reference is relative and valid

If branch is specified, it will override the Repository's default branch.

When present, relativeFrom specifies the file that is being rendered, and relative reference will be resolved from that location.

When reference is used inside <img> or similar tag, isEmbeddedObject should be set to true. On compatible providers the resolved URL will use the raw reference to content.

Implementation

String? tryResolveUrl(
  String reference, {
  String? branch,
  String? relativeFrom,
  bool? isEmbeddedObject,
}) {
  isEmbeddedObject ??= false;
  final parsedReference = Uri.tryParse(reference);
  if (parsedReference == null) {
    return null;
  }
  try {
    // trigger exception if there is an issue
    parsedReference.pathSegments;
    parsedReference.queryParameters;
  } on FormatException {
    return null;
  }
  if (parsedReference.hasScheme || parsedReference.path.isEmpty) {
    return reference;
  }
  var referenceIsAbsolute = false;
  var referencePath = p.normalize(parsedReference.path);
  while (referencePath.startsWith('/')) {
    referencePath = referencePath.substring(1);
    referenceIsAbsolute = true;
  }
  if (relativeFrom != null && !referenceIsAbsolute) {
    referencePath = p.normalize(p.joinAll([
      p.dirname(relativeFrom),
      referencePath,
    ]));
    while (referencePath.startsWith('/')) {
      referencePath = referencePath.substring(1);
    }
  }

  late String finalPath;

  // GitHub resolves references only inside the repository.
  if (RepositoryProvider.isGitHubCompatible(provider)) {
    final extension = p.extension(reference).toLowerCase();
    final needsRaw = isEmbeddedObject || _imageExtensions.contains(extension);
    final separator = (needsRaw ? 'raw' : null) ?? 'blob';

    final normalizedPath = referenceIsAbsolute
        ? referencePath
        : p.normalize(p.joinAll([
            if (path != null) path!,
            referencePath,
          ]));
    final parts = p.split(normalizedPath);
    final sanitizedPath = parts.contains('..')
        ? p.joinAll(parts.sublist(parts.lastIndexOf('..') + 1))
        : normalizedPath;

    finalPath = p.normalize(p.joinAll([
      repository,
      separator,
      branch ?? this.branch ?? 'master',
      sanitizedPath
    ].whereType<String>()));
  } else {
    // For unknown providers resolution follows normal URL rules.
    finalPath = referenceIsAbsolute
        ? referencePath
        : p.normalize(p.joinAll([
            repository,
            if (path != null) path!,
            referencePath,
          ].whereType<String>()));
  }

  final queryParametersAll =
      parsedReference.hasQuery && parsedReference.queryParameters.isNotEmpty
          ? parsedReference.queryParametersAll
          : null;
  final fragment = parsedReference.hasFragment &&
          parsedReference.fragment.trim().isNotEmpty
      ? parsedReference.fragment.trim()
      : null;
  return Uri(
    scheme: 'https',
    host: host,
    path: finalPath,
    queryParameters: queryParametersAll,
    fragment: fragment,
  ).toString();
}