From d04fe33025e34e8e7a15f8476e467824ff98cc69 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 26 Mar 2025 09:49:42 +0100 Subject: [PATCH] Add navigation build commands to assembler: 'validate' and 'validate-link-reference' --- .../DocumentationGenerator.cs | 2 +- src/Elastic.Markdown/IO/DocumentationSet.cs | 2 +- src/Elastic.Markdown/IO/MarkdownFile.cs | 2 +- .../ConfigurationCrossLinkFetcher.cs | 2 +- .../CrossLinks/CrossLinkFetcher.cs | 2 +- .../CrossLinks/CrossLinkResolver.cs | 2 +- .../CrossLinks/IUriEnvironmentResolver.cs | 2 +- .../InboundLinks/LinkIndexCrossLinkFetcher.cs | 4 +- .../InboundLinks/LinkIndexLinkChecker.cs | 8 +- .../LinkGlobalNamespaceChecker.cs | 94 +++++++++++++++++++ src/Elastic.Markdown/Myst/ParserContext.cs | 2 +- .../SourceGenerationContext.cs | 2 +- src/docs-assembler/AssembleSources.cs | 2 +- .../Building/AssemblerCrossLinkFetcher.cs | 2 +- .../Building/PublishEnvironmentUriResolver.cs | 2 +- src/docs-assembler/Cli/InboundLinkCommands.cs | 2 +- src/docs-assembler/Cli/NavigationCommands.cs | 85 +++++++++++++++++ .../Cli/PathPrefixCollisionCommand.cs | 41 -------- .../Navigation/AssemblerDocumentationSet.cs | 2 +- .../Navigation/GlobalNavigationFile.cs | 2 +- src/docs-assembler/Program.cs | 1 + src/docs-builder/Cli/InboundLinkCommands.cs | 2 +- .../docs-lambda-index-publisher/Program.cs | 2 +- .../TestCrossLinkResolver.cs | 2 +- tests/authoring/Framework/Setup.fs | 1 - .../Framework/TestCrossLinkResolver.fs | 2 +- 26 files changed, 204 insertions(+), 68 deletions(-) rename src/Elastic.Markdown/{ => Links}/CrossLinks/ConfigurationCrossLinkFetcher.cs (97%) rename src/Elastic.Markdown/{ => Links}/CrossLinks/CrossLinkFetcher.cs (99%) rename src/Elastic.Markdown/{ => Links}/CrossLinks/CrossLinkResolver.cs (99%) rename src/Elastic.Markdown/{ => Links}/CrossLinks/IUriEnvironmentResolver.cs (95%) rename src/Elastic.Markdown/{ => Links}/InboundLinks/LinkIndexCrossLinkFetcher.cs (93%) rename src/Elastic.Markdown/{ => Links}/InboundLinks/LinkIndexLinkChecker.cs (96%) create mode 100644 src/Elastic.Markdown/Links/LinkNamespaces/LinkGlobalNamespaceChecker.cs create mode 100644 src/docs-assembler/Cli/NavigationCommands.cs delete mode 100644 src/docs-assembler/Cli/PathPrefixCollisionCommand.cs diff --git a/src/Elastic.Markdown/DocumentationGenerator.cs b/src/Elastic.Markdown/DocumentationGenerator.cs index 97c0b4138..ae33cb3fb 100644 --- a/src/Elastic.Markdown/DocumentationGenerator.cs +++ b/src/Elastic.Markdown/DocumentationGenerator.cs @@ -5,10 +5,10 @@ using System.IO.Abstractions; using System.Reflection; using System.Text.Json; -using Elastic.Markdown.CrossLinks; using Elastic.Markdown.Exporters; using Elastic.Markdown.IO; using Elastic.Markdown.IO.State; +using Elastic.Markdown.Links.CrossLinks; using Elastic.Markdown.Slices; using Markdig.Syntax; using Microsoft.Extensions.Logging; diff --git a/src/Elastic.Markdown/IO/DocumentationSet.cs b/src/Elastic.Markdown/IO/DocumentationSet.cs index c734106e2..148e9ed2c 100644 --- a/src/Elastic.Markdown/IO/DocumentationSet.cs +++ b/src/Elastic.Markdown/IO/DocumentationSet.cs @@ -5,12 +5,12 @@ using System.Collections.Frozen; using System.IO.Abstractions; using System.Runtime.InteropServices; -using Elastic.Markdown.CrossLinks; using Elastic.Markdown.Diagnostics; using Elastic.Markdown.Extensions; using Elastic.Markdown.IO.Configuration; using Elastic.Markdown.IO.Discovery; using Elastic.Markdown.IO.Navigation; +using Elastic.Markdown.Links.CrossLinks; using Elastic.Markdown.Myst; using Microsoft.Extensions.Logging; diff --git a/src/Elastic.Markdown/IO/MarkdownFile.cs b/src/Elastic.Markdown/IO/MarkdownFile.cs index accd104ac..7f08b8ad8 100644 --- a/src/Elastic.Markdown/IO/MarkdownFile.cs +++ b/src/Elastic.Markdown/IO/MarkdownFile.cs @@ -4,11 +4,11 @@ using System.IO.Abstractions; using System.Runtime.InteropServices; -using Elastic.Markdown.CrossLinks; using Elastic.Markdown.Diagnostics; using Elastic.Markdown.Helpers; using Elastic.Markdown.IO.Configuration; using Elastic.Markdown.IO.Navigation; +using Elastic.Markdown.Links.CrossLinks; using Elastic.Markdown.Myst; using Elastic.Markdown.Myst.Directives; using Elastic.Markdown.Myst.FrontMatter; diff --git a/src/Elastic.Markdown/CrossLinks/ConfigurationCrossLinkFetcher.cs b/src/Elastic.Markdown/Links/CrossLinks/ConfigurationCrossLinkFetcher.cs similarity index 97% rename from src/Elastic.Markdown/CrossLinks/ConfigurationCrossLinkFetcher.cs rename to src/Elastic.Markdown/Links/CrossLinks/ConfigurationCrossLinkFetcher.cs index f01f06048..f7bde0eb0 100644 --- a/src/Elastic.Markdown/CrossLinks/ConfigurationCrossLinkFetcher.cs +++ b/src/Elastic.Markdown/Links/CrossLinks/ConfigurationCrossLinkFetcher.cs @@ -7,7 +7,7 @@ using Elastic.Markdown.IO.State; using Microsoft.Extensions.Logging; -namespace Elastic.Markdown.CrossLinks; +namespace Elastic.Markdown.Links.CrossLinks; public class ConfigurationCrossLinkFetcher(ConfigurationFile configuration, ILoggerFactory logger) : CrossLinkFetcher(logger) { diff --git a/src/Elastic.Markdown/CrossLinks/CrossLinkFetcher.cs b/src/Elastic.Markdown/Links/CrossLinks/CrossLinkFetcher.cs similarity index 99% rename from src/Elastic.Markdown/CrossLinks/CrossLinkFetcher.cs rename to src/Elastic.Markdown/Links/CrossLinks/CrossLinkFetcher.cs index 05cf6d661..80b52b0b0 100644 --- a/src/Elastic.Markdown/CrossLinks/CrossLinkFetcher.cs +++ b/src/Elastic.Markdown/Links/CrossLinks/CrossLinkFetcher.cs @@ -8,7 +8,7 @@ using Elastic.Markdown.IO.State; using Microsoft.Extensions.Logging; -namespace Elastic.Markdown.CrossLinks; +namespace Elastic.Markdown.Links.CrossLinks; public record FetchedCrossLinks { diff --git a/src/Elastic.Markdown/CrossLinks/CrossLinkResolver.cs b/src/Elastic.Markdown/Links/CrossLinks/CrossLinkResolver.cs similarity index 99% rename from src/Elastic.Markdown/CrossLinks/CrossLinkResolver.cs rename to src/Elastic.Markdown/Links/CrossLinks/CrossLinkResolver.cs index e238d549d..1acd2cc56 100644 --- a/src/Elastic.Markdown/CrossLinks/CrossLinkResolver.cs +++ b/src/Elastic.Markdown/Links/CrossLinks/CrossLinkResolver.cs @@ -8,7 +8,7 @@ using System.Text.Json.Serialization; using Elastic.Markdown.IO.State; -namespace Elastic.Markdown.CrossLinks; +namespace Elastic.Markdown.Links.CrossLinks; public record LinkIndex { diff --git a/src/Elastic.Markdown/CrossLinks/IUriEnvironmentResolver.cs b/src/Elastic.Markdown/Links/CrossLinks/IUriEnvironmentResolver.cs similarity index 95% rename from src/Elastic.Markdown/CrossLinks/IUriEnvironmentResolver.cs rename to src/Elastic.Markdown/Links/CrossLinks/IUriEnvironmentResolver.cs index d95e0deaa..cc9212392 100644 --- a/src/Elastic.Markdown/CrossLinks/IUriEnvironmentResolver.cs +++ b/src/Elastic.Markdown/Links/CrossLinks/IUriEnvironmentResolver.cs @@ -2,7 +2,7 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information -namespace Elastic.Markdown.CrossLinks; +namespace Elastic.Markdown.Links.CrossLinks; public interface IUriEnvironmentResolver { diff --git a/src/Elastic.Markdown/InboundLinks/LinkIndexCrossLinkFetcher.cs b/src/Elastic.Markdown/Links/InboundLinks/LinkIndexCrossLinkFetcher.cs similarity index 93% rename from src/Elastic.Markdown/InboundLinks/LinkIndexCrossLinkFetcher.cs rename to src/Elastic.Markdown/Links/InboundLinks/LinkIndexCrossLinkFetcher.cs index bcfda1d0a..4371ef6ab 100644 --- a/src/Elastic.Markdown/InboundLinks/LinkIndexCrossLinkFetcher.cs +++ b/src/Elastic.Markdown/Links/InboundLinks/LinkIndexCrossLinkFetcher.cs @@ -3,11 +3,11 @@ // See the LICENSE file in the project root for more information using System.Collections.Frozen; -using Elastic.Markdown.CrossLinks; using Elastic.Markdown.IO.State; +using Elastic.Markdown.Links.CrossLinks; using Microsoft.Extensions.Logging; -namespace Elastic.Markdown.InboundLinks; +namespace Elastic.Markdown.Links.InboundLinks; public class LinksIndexCrossLinkFetcher(ILoggerFactory logger) : CrossLinkFetcher(logger) { diff --git a/src/Elastic.Markdown/InboundLinks/LinkIndexLinkChecker.cs b/src/Elastic.Markdown/Links/InboundLinks/LinkIndexLinkChecker.cs similarity index 96% rename from src/Elastic.Markdown/InboundLinks/LinkIndexLinkChecker.cs rename to src/Elastic.Markdown/Links/InboundLinks/LinkIndexLinkChecker.cs index d88aa695b..9c0684eb5 100644 --- a/src/Elastic.Markdown/InboundLinks/LinkIndexLinkChecker.cs +++ b/src/Elastic.Markdown/Links/InboundLinks/LinkIndexLinkChecker.cs @@ -2,13 +2,13 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information -using Elastic.Markdown.CrossLinks; using Elastic.Markdown.Diagnostics; using Elastic.Markdown.IO; using Elastic.Markdown.IO.State; +using Elastic.Markdown.Links.CrossLinks; using Microsoft.Extensions.Logging; -namespace Elastic.Markdown.InboundLinks; +namespace Elastic.Markdown.Links.InboundLinks; public class LinkIndexLinkChecker(ILoggerFactory logger) { @@ -47,9 +47,7 @@ public async Task CheckRepository(DiagnosticsCollector collector, string? t return await ValidateCrossLinks(collector, crossLinks, resolver, filter, ctx); } - public async Task CheckWithLocalLinksJson(DiagnosticsCollector collector, string repository, - string localLinksJson, - Cancel ctx) + public async Task CheckWithLocalLinksJson(DiagnosticsCollector collector, string repository, string localLinksJson, Cancel ctx) { var fetcher = new LinksIndexCrossLinkFetcher(logger); var resolver = new CrossLinkResolver(fetcher); diff --git a/src/Elastic.Markdown/Links/LinkNamespaces/LinkGlobalNamespaceChecker.cs b/src/Elastic.Markdown/Links/LinkNamespaces/LinkGlobalNamespaceChecker.cs new file mode 100644 index 000000000..9eeebe613 --- /dev/null +++ b/src/Elastic.Markdown/Links/LinkNamespaces/LinkGlobalNamespaceChecker.cs @@ -0,0 +1,94 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using Elastic.Markdown.Diagnostics; +using Elastic.Markdown.IO; +using Elastic.Markdown.IO.State; +using Microsoft.Extensions.Logging; + +namespace Elastic.Markdown.Links.LinkNamespaces; + +/// +/// Validates paths don't conflict with global navigation namespaces. +/// For example if the global navigation defines: +/// +/// - toc: elasticsearch://reference/elasticsearch +/// path_prefix: reference/elasticsearch +/// +/// - toc: docs-content://reference/elasticsearch/clients +/// path_prefix: reference/elasticsearch/clients +/// +/// +/// This will validate `elasticsearch://` does not create a `elasticsearch://reference/elasticsearch/clients` folder +/// since that is already claimed by `docs-content://reference/elasticsearch/clients` +/// +/// +public class LinkGlobalNamespaceChecker(ILoggerFactory logger, ImmutableHashSet namespaces) +{ + private readonly Dictionary _pathPrefixes = namespaces + .ToDictionary(n => $"{n.Host}/{n.AbsolutePath.Trim('/')}/", n => n.Scheme); + + private readonly ILogger _logger = logger.CreateLogger(); + + public async Task CheckWithLocalLinksJson(DiagnosticsCollector collector, string repository, string? localLinksJson, CancellationToken ctx) + { + if (string.IsNullOrEmpty(repository)) + throw new ArgumentNullException(nameof(repository)); + if (string.IsNullOrEmpty(localLinksJson)) + throw new ArgumentNullException(nameof(localLinksJson)); + + _logger.LogInformation("Checking '{Repository}' with local '{LocalLinksJson}'", repository, localLinksJson); + + if (!Path.IsPathRooted(localLinksJson)) + localLinksJson = Path.Combine(Paths.WorkingDirectoryRoot.FullName, localLinksJson); + + var linkReference = await ReadLocalLinksJsonAsync(localLinksJson, ctx); + + foreach (var (relativeLink, _) in linkReference.Links) + { + if (!TryGetReservedPathPrefix(relativeLink, out var reservedPathPrefix, out var byRepository)) + continue; + if (byRepository == repository) + continue; + + collector.EmitError(repository, $"'{relativeLink}' lives in path_prefix already claimed by '{byRepository}://{reservedPathPrefix}' in global navigation.yml"); + } + } + + private bool TryGetReservedPathPrefix( + string path, + [NotNullWhen(true)] out string? reservedPathPrefix, + [NotNullWhen(true)] out string? reservedByRepository + ) + { + reservedPathPrefix = null; + reservedByRepository = null; + foreach (var (prefix, repository) in _pathPrefixes) + { + if (!path.StartsWith(prefix)) + continue; + reservedPathPrefix = prefix; + reservedByRepository = repository; + return true; + } + + return false; + } + + private async Task ReadLocalLinksJsonAsync(string localLinksJson, CancellationToken ctx) + { + try + { + var json = await File.ReadAllTextAsync(localLinksJson, ctx); + return LinkReference.Deserialize(json); + } + catch (Exception e) + { + _logger.LogError(e, "Failed to read {LocalLinksJson}", localLinksJson); + throw; + } + } +} diff --git a/src/Elastic.Markdown/Myst/ParserContext.cs b/src/Elastic.Markdown/Myst/ParserContext.cs index bcf05dbd0..eefd87dcd 100644 --- a/src/Elastic.Markdown/Myst/ParserContext.cs +++ b/src/Elastic.Markdown/Myst/ParserContext.cs @@ -3,10 +3,10 @@ // See the LICENSE file in the project root for more information using System.IO.Abstractions; -using Elastic.Markdown.CrossLinks; using Elastic.Markdown.Diagnostics; using Elastic.Markdown.IO; using Elastic.Markdown.IO.Configuration; +using Elastic.Markdown.Links.CrossLinks; using Elastic.Markdown.Myst.FrontMatter; using Markdig; using Markdig.Parsers; diff --git a/src/Elastic.Markdown/SourceGenerationContext.cs b/src/Elastic.Markdown/SourceGenerationContext.cs index 7b07758b8..3a1b47d5b 100644 --- a/src/Elastic.Markdown/SourceGenerationContext.cs +++ b/src/Elastic.Markdown/SourceGenerationContext.cs @@ -3,9 +3,9 @@ // See the LICENSE file in the project root for more information using System.Text.Json.Serialization; -using Elastic.Markdown.CrossLinks; using Elastic.Markdown.IO.Discovery; using Elastic.Markdown.IO.State; +using Elastic.Markdown.Links.CrossLinks; namespace Elastic.Markdown; diff --git a/src/docs-assembler/AssembleSources.cs b/src/docs-assembler/AssembleSources.cs index 810a3f863..709276e39 100644 --- a/src/docs-assembler/AssembleSources.cs +++ b/src/docs-assembler/AssembleSources.cs @@ -8,9 +8,9 @@ using Documentation.Assembler.Configuration; using Documentation.Assembler.Navigation; using Documentation.Assembler.Sourcing; -using Elastic.Markdown.CrossLinks; using Elastic.Markdown.IO.Configuration; using Elastic.Markdown.IO.Navigation; +using Elastic.Markdown.Links.CrossLinks; using Microsoft.Extensions.Logging.Abstractions; using YamlDotNet.RepresentationModel; diff --git a/src/docs-assembler/Building/AssemblerCrossLinkFetcher.cs b/src/docs-assembler/Building/AssemblerCrossLinkFetcher.cs index 4f9ac338f..1d958832a 100644 --- a/src/docs-assembler/Building/AssemblerCrossLinkFetcher.cs +++ b/src/docs-assembler/Building/AssemblerCrossLinkFetcher.cs @@ -4,8 +4,8 @@ using System.Collections.Frozen; using Documentation.Assembler.Configuration; -using Elastic.Markdown.CrossLinks; using Elastic.Markdown.IO.State; +using Elastic.Markdown.Links.CrossLinks; using Microsoft.Extensions.Logging; namespace Documentation.Assembler.Building; diff --git a/src/docs-assembler/Building/PublishEnvironmentUriResolver.cs b/src/docs-assembler/Building/PublishEnvironmentUriResolver.cs index c7f434b3b..d1269491f 100644 --- a/src/docs-assembler/Building/PublishEnvironmentUriResolver.cs +++ b/src/docs-assembler/Building/PublishEnvironmentUriResolver.cs @@ -4,7 +4,7 @@ using System.Collections.Frozen; using Documentation.Assembler.Configuration; -using Elastic.Markdown.CrossLinks; +using Elastic.Markdown.Links.CrossLinks; namespace Documentation.Assembler.Building; diff --git a/src/docs-assembler/Cli/InboundLinkCommands.cs b/src/docs-assembler/Cli/InboundLinkCommands.cs index bbac6f010..631ee891b 100644 --- a/src/docs-assembler/Cli/InboundLinkCommands.cs +++ b/src/docs-assembler/Cli/InboundLinkCommands.cs @@ -7,9 +7,9 @@ using Actions.Core.Services; using ConsoleAppFramework; using Elastic.Documentation.Tooling.Diagnostics.Console; -using Elastic.Markdown.InboundLinks; using Elastic.Markdown.IO; using Elastic.Markdown.IO.Discovery; +using Elastic.Markdown.Links.InboundLinks; using Microsoft.Extensions.Logging; namespace Documentation.Assembler.Cli; diff --git a/src/docs-assembler/Cli/NavigationCommands.cs b/src/docs-assembler/Cli/NavigationCommands.cs new file mode 100644 index 000000000..deb4775fd --- /dev/null +++ b/src/docs-assembler/Cli/NavigationCommands.cs @@ -0,0 +1,85 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Diagnostics.CodeAnalysis; +using System.IO.Abstractions; +using Actions.Core.Services; +using ConsoleAppFramework; +using Documentation.Assembler.Navigation; +using Elastic.Documentation.Tooling.Diagnostics.Console; +using Elastic.Documentation.Tooling.Filters; +using Elastic.Markdown.IO; +using Elastic.Markdown.IO.Discovery; +using Elastic.Markdown.Links.InboundLinks; +using Elastic.Markdown.Links.LinkNamespaces; +using Microsoft.Extensions.Logging; + +namespace Documentation.Assembler.Cli; + +internal sealed class NavigationCommands(ILoggerFactory logger, ICoreService githubActionsService) +{ + private readonly LinkIndexLinkChecker _linkIndexLinkChecker = new(logger); + + [SuppressMessage("Usage", "CA2254:Template should be a static expression")] + private void AssignOutputLogger() + { + var log = logger.CreateLogger(); + ConsoleApp.Log = msg => log.LogInformation(msg); + ConsoleApp.LogError = msg => log.LogError(msg); + } + + /// Validates navigation.yml does not contain colliding path prefixes + /// + [Command("validate")] + [ConsoleAppFilter] + [ConsoleAppFilter] + public async Task Validate(Cancel ctx = default) + { + AssignOutputLogger(); + await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService); + var assembleContext = new AssembleContext("dev", collector, new FileSystem(), new FileSystem(), null, null); + _ = collector.StartAsync(ctx); + + // this validates all path prefixes are unique, early exit if duplicates are detected + if (!GlobalNavigationFile.ValidatePathPrefixes(assembleContext) || assembleContext.Collector.Errors > 0) + { + assembleContext.Collector.Channel.TryComplete(); + await assembleContext.Collector.StopAsync(ctx); + return 1; + } + + return 0; + } + + /// Validate all published links in links.json do not collide with navigation path_prefixes. + /// Path to `links.json` defaults to '.artifacts/docs/html/links.json' + /// + [Command("validate-link-reference")] + [ConsoleAppFilter] + [ConsoleAppFilter] + public async Task ValidateLocalLinkReference([Argument] string? file = null, Cancel ctx = default) + { + AssignOutputLogger(); + file ??= ".artifacts/docs/html/links.json"; + + await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService); + _ = collector.StartAsync(ctx); + + var assembleContext = new AssembleContext("dev", collector, new FileSystem(), new FileSystem(), null, null); + + var fs = new FileSystem(); + var root = fs.DirectoryInfo.New(Paths.WorkingDirectoryRoot.FullName); + var repository = GitCheckoutInformation.Create(root, new FileSystem(), logger.CreateLogger(nameof(GitCheckoutInformation))).RepositoryName + ?? throw new Exception("Unable to determine repository name"); + + var prefixes = GlobalNavigationFile.GetAllPathPrefixes(assembleContext); + + var namespaceChecker = new LinkGlobalNamespaceChecker(logger, prefixes); + + await namespaceChecker.CheckWithLocalLinksJson(assembleContext.Collector, repository, file, ctx); + + return await _linkIndexLinkChecker.CheckAll(collector, ctx); + } + +} diff --git a/src/docs-assembler/Cli/PathPrefixCollisionCommand.cs b/src/docs-assembler/Cli/PathPrefixCollisionCommand.cs deleted file mode 100644 index 666f7a3a9..000000000 --- a/src/docs-assembler/Cli/PathPrefixCollisionCommand.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Licensed to Elasticsearch B.V under one or more agreements. -// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. -// See the LICENSE file in the project root for more information - -using System.Diagnostics.CodeAnalysis; -using System.IO.Abstractions; -using Actions.Core.Services; -using ConsoleAppFramework; -using Elastic.Documentation.Tooling.Diagnostics.Console; -using Elastic.Markdown.InboundLinks; -using Elastic.Markdown.IO; -using Elastic.Markdown.IO.Discovery; -using Microsoft.Extensions.Logging; - -namespace Documentation.Assembler.Cli; - -internal sealed class PathPrefixCollisionCommand(ILoggerFactory logger, ICoreService githubActionsService) -{ - private readonly LinkIndexLinkChecker _linkIndexLinkChecker = new(logger); - - [SuppressMessage("Usage", "CA2254:Template should be a static expression")] - private void AssignOutputLogger() - { - var log = logger.CreateLogger(); - ConsoleApp.Log = msg => log.LogInformation(msg); - ConsoleApp.LogError = msg => log.LogError(msg); - } - - /// Validate all published cross_links in all published links.json files. - /// - [Command("")] - public async Task DetectCollisions(Cancel ctx = default) - { - AssignOutputLogger(); - await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService); - - var assembleContext = new AssembleContext("dev", collector, new FileSystem(), new FileSystem(), null, null); - return await _linkIndexLinkChecker.CheckAll(collector, ctx); - } - -} diff --git a/src/docs-assembler/Navigation/AssemblerDocumentationSet.cs b/src/docs-assembler/Navigation/AssemblerDocumentationSet.cs index 5b4299796..3531d7669 100644 --- a/src/docs-assembler/Navigation/AssemblerDocumentationSet.cs +++ b/src/docs-assembler/Navigation/AssemblerDocumentationSet.cs @@ -4,10 +4,10 @@ using Documentation.Assembler.Sourcing; using Elastic.Markdown; -using Elastic.Markdown.CrossLinks; using Elastic.Markdown.IO; using Elastic.Markdown.IO.Discovery; using Elastic.Markdown.IO.Navigation; +using Elastic.Markdown.Links.CrossLinks; using Microsoft.Extensions.Logging; namespace Documentation.Assembler.Navigation; diff --git a/src/docs-assembler/Navigation/GlobalNavigationFile.cs b/src/docs-assembler/Navigation/GlobalNavigationFile.cs index 44f9aabed..e85cb87d2 100644 --- a/src/docs-assembler/Navigation/GlobalNavigationFile.cs +++ b/src/docs-assembler/Navigation/GlobalNavigationFile.cs @@ -36,7 +36,7 @@ public static bool ValidatePathPrefixes(AssembleContext context) var valid = true; foreach (var pathPrefix in sourcePathPrefixes) { - var prefix = $"{pathPrefix.Host}/{pathPrefix.AbsolutePath.TrimStart('/')}/"; + var prefix = $"{pathPrefix.Host}/{pathPrefix.AbsolutePath.Trim('/')}/"; if (pathPrefixSet.Add(prefix)) continue; var duplicateOf = sourcePathPrefixes.First(p => p.Host == pathPrefix.Host && p.AbsolutePath == pathPrefix.AbsolutePath); diff --git a/src/docs-assembler/Program.cs b/src/docs-assembler/Program.cs index 05928660d..6cce8258d 100644 --- a/src/docs-assembler/Program.cs +++ b/src/docs-assembler/Program.cs @@ -23,6 +23,7 @@ app.Add("inbound-links"); app.Add("repo"); +app.Add("navigation"); var githubActions = ConsoleApp.ServiceProvider.GetService(); var command = githubActions?.GetInput("COMMAND") ?? Environment.GetEnvironmentVariable("INPUT_COMMAND"); diff --git a/src/docs-builder/Cli/InboundLinkCommands.cs b/src/docs-builder/Cli/InboundLinkCommands.cs index 6e65dddc7..6c07ea930 100644 --- a/src/docs-builder/Cli/InboundLinkCommands.cs +++ b/src/docs-builder/Cli/InboundLinkCommands.cs @@ -8,9 +8,9 @@ using ConsoleAppFramework; using Elastic.Documentation.Tooling.Diagnostics.Console; using Elastic.Documentation.Tooling.Filters; -using Elastic.Markdown.InboundLinks; using Elastic.Markdown.IO; using Elastic.Markdown.IO.Discovery; +using Elastic.Markdown.Links.InboundLinks; using Microsoft.Extensions.Logging; namespace Documentation.Builder.Cli; diff --git a/src/infra/docs-lambda-index-publisher/Program.cs b/src/infra/docs-lambda-index-publisher/Program.cs index c265f9bac..56e3518da 100644 --- a/src/infra/docs-lambda-index-publisher/Program.cs +++ b/src/infra/docs-lambda-index-publisher/Program.cs @@ -8,7 +8,7 @@ using Amazon.Lambda.RuntimeSupport; using Amazon.S3; using Amazon.S3.Model; -using Elastic.Markdown.CrossLinks; +using Elastic.Markdown.Links.CrossLinks; await LambdaBootstrapBuilder.Create(Handler) .Build() diff --git a/tests/Elastic.Markdown.Tests/TestCrossLinkResolver.cs b/tests/Elastic.Markdown.Tests/TestCrossLinkResolver.cs index 2b6d63736..2e2aaf287 100644 --- a/tests/Elastic.Markdown.Tests/TestCrossLinkResolver.cs +++ b/tests/Elastic.Markdown.Tests/TestCrossLinkResolver.cs @@ -4,8 +4,8 @@ using System.Collections.Frozen; using System.Diagnostics.CodeAnalysis; -using Elastic.Markdown.CrossLinks; using Elastic.Markdown.IO.State; +using Elastic.Markdown.Links.CrossLinks; using Xunit.Internal; namespace Elastic.Markdown.Tests; diff --git a/tests/authoring/Framework/Setup.fs b/tests/authoring/Framework/Setup.fs index ae0aaa0c5..682091fa8 100644 --- a/tests/authoring/Framework/Setup.fs +++ b/tests/authoring/Framework/Setup.fs @@ -11,7 +11,6 @@ open System.IO open System.IO.Abstractions.TestingHelpers open System.Threading.Tasks open Elastic.Markdown -open Elastic.Markdown.CrossLinks open Elastic.Markdown.IO open JetBrains.Annotations open Xunit diff --git a/tests/authoring/Framework/TestCrossLinkResolver.fs b/tests/authoring/Framework/TestCrossLinkResolver.fs index f8bd344fc..51b455b99 100644 --- a/tests/authoring/Framework/TestCrossLinkResolver.fs +++ b/tests/authoring/Framework/TestCrossLinkResolver.fs @@ -10,7 +10,7 @@ open System.Collections.Frozen open System.Runtime.InteropServices open System.Threading.Tasks open System.Linq -open Elastic.Markdown.CrossLinks +open Elastic.Markdown.Links.CrossLinks open Elastic.Markdown.IO.Configuration open Elastic.Markdown.IO.State