From 76a3efbda97479526785ff91aa77fbdc211064c7 Mon Sep 17 00:00:00 2001 From: filzrev <103790468+filzrev@users.noreply.github.com> Date: Sun, 14 Apr 2024 12:28:06 +0900 Subject: [PATCH] fix: Xrefmap baseUrl problem reported at #9866 (#9869) fix: xrefmap baseurl problems --- .../XRefMaps/XRefArchiveBuilder.cs | 10 ---- src/Docfx.Build/XRefMaps/XRefMapDownloader.cs | 32 ++++++----- .../XRefMapDownloaderTest.cs | 54 +++++++++++++++++++ test/docfx.Tests/Api.verified.cs | 1 - 4 files changed, 69 insertions(+), 28 deletions(-) diff --git a/src/Docfx.Build/XRefMaps/XRefArchiveBuilder.cs b/src/Docfx.Build/XRefMaps/XRefArchiveBuilder.cs index 9542058fa96..515cec49607 100644 --- a/src/Docfx.Build/XRefMaps/XRefArchiveBuilder.cs +++ b/src/Docfx.Build/XRefMaps/XRefArchiveBuilder.cs @@ -47,16 +47,6 @@ private async Task DownloadCoreAsync(Uri uri, XRefArchive xa) return null; } - // If BaseUrl is not set. Use xrefmap file download url as basePath. - if (string.IsNullOrEmpty(map.BaseUrl)) - { - var baseUrl = uri.GetLeftPart(UriPartial.Path); - baseUrl = baseUrl.Substring(0, baseUrl.LastIndexOf('/') + 1); - map.BaseUrl = baseUrl; - map.UpdateHref(new Uri(baseUrl)); // Update hrefs from relative to absolute url. - map.HrefUpdated = null; // Don't save this flag for downloaded XRefMap. - } - // Enforce XRefMap's references are sorted by uid. // Note: // Sort is not needed if `map.Sorted == true`. diff --git a/src/Docfx.Build/XRefMaps/XRefMapDownloader.cs b/src/Docfx.Build/XRefMaps/XRefMapDownloader.cs index 55d477394b5..de8c576951b 100644 --- a/src/Docfx.Build/XRefMaps/XRefMapDownloader.cs +++ b/src/Docfx.Build/XRefMaps/XRefMapDownloader.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Diagnostics; using System.Net; using Docfx.Common; @@ -152,33 +154,29 @@ protected static async Task DownloadFromWebAsync(Uri uri) case ".json": { using var sr = new StreamReader(stream, bufferSize: 81920); // Default :1024 byte - return JsonUtility.Deserialize(sr); + var xrefMap = JsonUtility.Deserialize(sr); + xrefMap.BaseUrl = ResolveBaseUrl(xrefMap, uri); + return xrefMap; } case ".yml": default: { using var sr = new StreamReader(stream, bufferSize: 81920); // Default :1024 byte - return YamlUtility.Deserialize(sr); + var xrefMap = YamlUtility.Deserialize(sr); + xrefMap.BaseUrl = ResolveBaseUrl(xrefMap, uri); + return xrefMap; } } } - public static void UpdateHref(XRefMap map, Uri uri) + private static string ResolveBaseUrl(XRefMap map, Uri uri) { if (!string.IsNullOrEmpty(map.BaseUrl)) - { - if (!Uri.TryCreate(map.BaseUrl, UriKind.Absolute, out Uri baseUri)) - { - throw new InvalidDataException($"Xref map file (from {uri.AbsoluteUri}) has an invalid base url: {map.BaseUrl}."); - } - map.UpdateHref(baseUri); - return; - } - if (uri.Scheme == "http" || uri.Scheme == "https") - { - map.UpdateHref(uri); - return; - } - throw new InvalidDataException($"Xref map file (from {uri.AbsoluteUri}) missing base url."); + return map.BaseUrl; + + // If downloaded xrefmap has no baseUrl. + // Use xrefmap file download url as basePath. + var baseUrl = uri.GetLeftPart(UriPartial.Path); + return baseUrl.Substring(0, baseUrl.LastIndexOf('/') + 1); } } diff --git a/test/Docfx.Build.Tests/XRefMapDownloaderTest.cs b/test/Docfx.Build.Tests/XRefMapDownloaderTest.cs index c8ae4b7ec57..50b389263f4 100644 --- a/test/Docfx.Build.Tests/XRefMapDownloaderTest.cs +++ b/test/Docfx.Build.Tests/XRefMapDownloaderTest.cs @@ -50,4 +50,58 @@ public async Task ReadLocalXRefMapJsonFileTest() xrefMap.Should().NotBeNull(); xrefMap.References.Should().HaveCount(1); } + + /// + /// XrefmapDownloader test for xrefmap that has no baseUrl and href is defined by relative path. + /// + [Fact(Skip = "Has dependency to external site content.")] + public async Task ReadRemoteXRefMapYamlFileTest1() + { + // Arrange + var path = "https://horizongir.github.io/ZedGraph/xrefmap.yml"; + + XRefMapDownloader downloader = new XRefMapDownloader(); + var xrefMap = await downloader.DownloadAsync(new Uri(path)) as XRefMap; + + // Assert + xrefMap.Sorted.Should().BeTrue(); + xrefMap.HrefUpdated.Should().BeNull(); + + // If baseUrl is not exists. Set download URL is set automatically. + xrefMap.BaseUrl.Should().Be("https://horizongir.github.io/ZedGraph/"); + + // Test relative URL is preserved. + xrefMap.References[0].Href.Should().Be("api/ZedGraph.html"); + xrefMap.References[0].Href = "https://horizongir.github.io/ZedGraph/api/ZedGraph.html"; + xrefMap.BaseUrl = "http://localhost"; + + // Test url is resolved as absolute URL. + var reader = xrefMap.GetReader(); + reader.Find("ZedGraph").Href.Should().Be("https://horizongir.github.io/ZedGraph/api/ZedGraph.html"); + } + + /// + /// XrefmapDownloader test for xrefmap that has no baseUrl, and href is defined by absolute path. + /// + [Fact(Skip = "Has dependency to external site content.")] + public async Task ReadRemoteXRefMapJsonFileTest2() + { + // Arrange + var path = "https://normanderwan.github.io/UnityXrefMaps/xrefmap.yml"; + + XRefMapDownloader downloader = new XRefMapDownloader(); + var xrefMap = await downloader.DownloadAsync(new Uri(path)) as XRefMap; + + // Assert + xrefMap.Sorted.Should().BeTrue(); + xrefMap.HrefUpdated.Should().BeNull(); + + // If baseUrl is not exists. XrefMap download URL is set automatically. + xrefMap.BaseUrl.Should().Be("https://normanderwan.github.io/UnityXrefMaps/"); + + // If href is absolute URL. baseURL is ignored. + var xrefSpec = xrefMap.References[0]; + xrefSpec.Href.Should().Be("https://docs.unity3d.com/ScriptReference/index.html"); + xrefMap.GetReader().Find(xrefSpec.Uid).Href.Should().Be("https://docs.unity3d.com/ScriptReference/index.html"); + } } diff --git a/test/docfx.Tests/Api.verified.cs b/test/docfx.Tests/Api.verified.cs index 5293d77ab65..1b018280980 100644 --- a/test/docfx.Tests/Api.verified.cs +++ b/test/docfx.Tests/Api.verified.cs @@ -476,7 +476,6 @@ public XRefMapDownloader(string baseFolder = null, System.Collections.Generic.IR protected virtual System.Threading.Tasks.Task DownloadBySchemeAsync(System.Uri uri) { } protected static Docfx.Build.Engine.IXRefContainer DownloadFromLocal(System.Uri uri) { } protected static System.Threading.Tasks.Task DownloadFromWebAsync(System.Uri uri) { } - public static void UpdateHref(Docfx.Build.Engine.XRefMap map, System.Uri uri) { } } public sealed class XRefMapReader : Docfx.Build.Engine.XRefRedirectionReader {