From 48c3d8a061fb9f018dc5fe8593bf065cdd2a4a14 Mon Sep 17 00:00:00 2001 From: Martin Tirion Date: Thu, 19 Dec 2024 10:56:09 +0000 Subject: [PATCH] Fixed handling of heading references in the same file --- .../DocAssembler.Test/IssueTests.cs | 72 +++++++++++++++++++ .../DocAssembler/Actions/InventoryAction.cs | 48 ++++++++----- 2 files changed, 101 insertions(+), 19 deletions(-) create mode 100644 src/DocAssembler/DocAssembler.Test/IssueTests.cs diff --git a/src/DocAssembler/DocAssembler.Test/IssueTests.cs b/src/DocAssembler/DocAssembler.Test/IssueTests.cs new file mode 100644 index 0000000..4f036d9 --- /dev/null +++ b/src/DocAssembler/DocAssembler.Test/IssueTests.cs @@ -0,0 +1,72 @@ +// +// Copyright (c) DocFx Companion Tools. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +using Bogus; +using DocAssembler.Actions; +using DocAssembler.Configuration; +using DocAssembler.Test.Helpers; +using FluentAssertions; +using Microsoft.Extensions.Logging; + +namespace DocAssembler.Test; + +public class IssueTests +{ + private Faker _faker = new(); + private MockFileService _fileService = new(); + private MockLogger _mockLogger = new(); + private ILogger _logger; + + private string _workingFolder = string.Empty; + private string _outputFolder = string.Empty; + + public IssueTests() + { + _fileService.FillDemoSet(); + _logger = _mockLogger.Logger; + + _workingFolder = _fileService.Root; + _outputFolder = Path.Combine(_fileService.Root, "out"); + } + + [Fact] + public async void Issue_89_refHeaderInSameFile() + { + _fileService.Files.Clear(); + + string expected = +@"#Documentation Readme + +LINK [title](#documentation-readme)"; + + var folder = _fileService.AddFolder($"docs"); + _fileService.AddFile(folder, "README.md", string.Empty + .AddRaw(expected)); + + // arrange + AssembleConfiguration config = new AssembleConfiguration + { + DestinationFolder = "out", + Content = + [ + new Content + { + SourceFolder = "docs", + DestinationFolder = "general", + Files = { "**" }, + } + ] + }; + + InventoryAction action = new(_workingFolder, config, _fileService, _logger); + + // act + var ret = await action.RunAsync(); + + // assert + ret.Should().Be(ReturnCode.Normal); + var content = _fileService.ReadAllText(_fileService.Files.Last().Key); + content.Should().Be(expected); + } +} diff --git a/src/DocAssembler/DocAssembler/Actions/InventoryAction.cs b/src/DocAssembler/DocAssembler/Actions/InventoryAction.cs index d64b5ac..c4ea005 100644 --- a/src/DocAssembler/DocAssembler/Actions/InventoryAction.cs +++ b/src/DocAssembler/DocAssembler/Actions/InventoryAction.cs @@ -103,33 +103,43 @@ private ReturnCode UpdateLinks() foreach (var link in file.Links) { - var dest = Files.SingleOrDefault(x => x.SourcePath.Equals(link.UrlFullPath, StringComparison.Ordinal)); - if (dest != null) + if (string.IsNullOrEmpty(link.UrlFullPath)) { - // destination found. register and also (new) calculate relative path - link.DestinationFullUrl = dest.DestinationPath; - string dir = Path.GetDirectoryName(file.DestinationPath)!; - link.DestinationRelativeUrl = Path.GetRelativePath(dir, dest.DestinationPath).NormalizePath(); - if (!string.IsNullOrEmpty(link.UrlTopic)) - { - link.DestinationFullUrl += link.UrlTopic; - link.DestinationRelativeUrl += link.UrlTopic; - } + // this is a link to a header in the same file. Just use the original link. + link.DestinationFullUrl = link.OriginalUrl; + link.DestinationRelativeUrl = link.OriginalUrl; } else { - var prefix = file.ContentSet!.ExternalFilePrefix ?? _config.ExternalFilePrefix; - if (string.IsNullOrEmpty(prefix)) + // ignoring empty UrlFullPath, as it is a heading reference in the same file + var dest = Files.SingleOrDefault(x => x.SourcePath.Equals(link.UrlFullPath, StringComparison.Ordinal)); + if (dest != null) { - // ERROR: no solution to fix this reference - _logger.LogCritical($"Error in a file reference. Link '{link.OriginalUrl}' in '{file.SourcePath}' cannot be resolved and no external file prefix was given."); - ret = ReturnCode.Error; + // destination found. register and also (new) calculate relative path + link.DestinationFullUrl = dest.DestinationPath; + string dir = Path.GetDirectoryName(file.DestinationPath)!; + link.DestinationRelativeUrl = Path.GetRelativePath(dir, dest.DestinationPath).NormalizePath(); + if (!string.IsNullOrEmpty(link.UrlTopic)) + { + link.DestinationFullUrl += link.UrlTopic; + link.DestinationRelativeUrl += link.UrlTopic; + } } else { - // we're calculating the link with the external file prefix, usualy a repo web link prefix. - string subpath = link.UrlFullPath.Substring(_workingFolder.Length).TrimStart('/'); - link.DestinationFullUrl = prefix.TrimEnd('/') + "/" + subpath; + var prefix = file.ContentSet!.ExternalFilePrefix ?? _config.ExternalFilePrefix; + if (string.IsNullOrEmpty(prefix)) + { + // ERROR: no solution to fix this reference + _logger.LogCritical($"Error in a file reference. Link '{link.OriginalUrl}' in '{file.SourcePath}' cannot be resolved and no external file prefix was given."); + ret = ReturnCode.Error; + } + else + { + // we're calculating the link with the external file prefix, usualy a repo web link prefix. + string subpath = link.UrlFullPath.Substring(_workingFolder.Length).TrimStart('/'); + link.DestinationFullUrl = prefix.TrimEnd('/') + "/" + subpath; + } } } }