diff --git a/src/Elastic.Documentation/Exporter.cs b/src/Elastic.Documentation/Exporter.cs index 6af9ed524..4853304bf 100644 --- a/src/Elastic.Documentation/Exporter.cs +++ b/src/Elastic.Documentation/Exporter.cs @@ -16,6 +16,7 @@ public enum Exporter DocumentationState, LinkMetadata, Redirects, + MarkdownValidation } public static class ExportOptions { diff --git a/src/Elastic.Markdown/Exporters/ExporterExtensions.cs b/src/Elastic.Markdown/Exporters/ExporterExtensions.cs index c544d887a..a89fd9aa4 100644 --- a/src/Elastic.Markdown/Exporters/ExporterExtensions.cs +++ b/src/Elastic.Markdown/Exporters/ExporterExtensions.cs @@ -27,6 +27,7 @@ string indexNamespace markdownExporters.Add(new ElasticsearchMarkdownSemanticExporter(logFactory, context.Collector, indexNamespace, context.Endpoints)); if (exportOptions.Contains(Exporter.ElasticsearchNoSemantic)) markdownExporters.Add(new ElasticsearchMarkdownExporter(logFactory, context.Collector, indexNamespace, context.Endpoints)); + markdownExporters.Add(new MarkdownValidationExporter()); return markdownExporters; } } diff --git a/src/Elastic.Markdown/Exporters/MarkdownValidationExporter.cs b/src/Elastic.Markdown/Exporters/MarkdownValidationExporter.cs new file mode 100644 index 000000000..6f13764b2 --- /dev/null +++ b/src/Elastic.Markdown/Exporters/MarkdownValidationExporter.cs @@ -0,0 +1,57 @@ +// 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.IO.Abstractions; +using Elastic.Markdown.Exporters; +using Elastic.Markdown.IO; + +namespace Elastic.Markdown.Exporters; + +public class MarkdownValidationExporter : IMarkdownExporter +{ + private readonly List _files = []; + + /// + public ValueTask StartAsync(Cancel ctx = default) => default; + + /// + public ValueTask StopAsync(Cancel ctx = default) + { + var titleMap = new Dictionary>(StringComparer.OrdinalIgnoreCase); + foreach (var file in _files) + { + if (string.IsNullOrWhiteSpace(file.Title)) + { + Console.WriteLine($"Error: File {file.FilePath} has no title"); + continue; + } + if (!titleMap.TryGetValue(file.Title, out var list)) + titleMap[file.Title] = []; + titleMap[file.Title].Add(file); + } + foreach (var kv in titleMap) + { + var files = kv.Value; + if (files.Count > 1) + { + var title = kv.Key; + var filePaths = string.Join(", ", files.Select(f => f.FilePath)); + Console.WriteLine($"Error: Title '{title}' is used in multiple files: {filePaths}"); + } + } + return default; + } + + /// + public ValueTask ExportAsync(MarkdownExportFileContext fileContext, Cancel ctx) + { + var markdownFile = fileContext.SourceFile; + _files.Add(markdownFile); + Console.WriteLine($"+++ MarkdownValidationExporter: document.Title: {markdownFile.Title}"); + return ValueTask.FromResult(true); + } + + /// + public ValueTask FinishExportAsync(IDirectoryInfo outputFolder, Cancel ctx) => ValueTask.FromResult(true); +}