From 6222eeb9c4aad3e4c743cf5d83adbe45366c89af Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Wed, 19 Mar 2025 13:30:13 +0100 Subject: [PATCH 1/3] Add ability to set canonical base url --- src/Elastic.Markdown/BuildContext.cs | 3 +++ src/Elastic.Markdown/Slices/HtmlWriter.cs | 1 + src/Elastic.Markdown/Slices/Index.cshtml | 1 + src/Elastic.Markdown/Slices/Layout/_Head.cshtml | 7 ++++++- src/Elastic.Markdown/Slices/_ViewModels.cs | 2 ++ src/docs-builder/Cli/Commands.cs | 9 +++++++-- 6 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Elastic.Markdown/BuildContext.cs b/src/Elastic.Markdown/BuildContext.cs index 8eb18e002..19d4c36c7 100644 --- a/src/Elastic.Markdown/BuildContext.cs +++ b/src/Elastic.Markdown/BuildContext.cs @@ -34,6 +34,9 @@ public record BuildContext // This property is used to determine if the site should be indexed by search engines public bool AllowIndexing { get; init; } + // This property is used for the canonical URL + public string? CanonicalBaseUrl { get; init; } + private readonly string? _urlPathPrefix; public string? UrlPathPrefix { diff --git a/src/Elastic.Markdown/Slices/HtmlWriter.cs b/src/Elastic.Markdown/Slices/HtmlWriter.cs index 7fde86872..dce2eed9f 100644 --- a/src/Elastic.Markdown/Slices/HtmlWriter.cs +++ b/src/Elastic.Markdown/Slices/HtmlWriter.cs @@ -103,6 +103,7 @@ public async Task RenderLayout(MarkdownFile markdown, MarkdownDocument d Applies = markdown.YamlFrontMatter?.AppliesTo, GithubEditUrl = editUrl, AllowIndexing = DocumentationSet.Build.AllowIndexing && !markdown.Hidden, + CanonicalBaseUrl = DocumentationSet.Build.CanonicalBaseUrl?.TrimEnd('/'), Features = DocumentationSet.Configuration.Features, StaticFileContentHashProvider = StaticFileContentHashProvider }); diff --git a/src/Elastic.Markdown/Slices/Index.cshtml b/src/Elastic.Markdown/Slices/Index.cshtml index 6a181cc02..756bc9a57 100644 --- a/src/Elastic.Markdown/Slices/Index.cshtml +++ b/src/Elastic.Markdown/Slices/Index.cshtml @@ -15,6 +15,7 @@ UrlPathPrefix = Model.UrlPathPrefix, GithubEditUrl = Model.GithubEditUrl, AllowIndexing = Model.AllowIndexing, + CanonicalBaseUrl = Model.CanonicalBaseUrl, Features = Model.Features, StaticFileContentHashProvider = Model.StaticFileContentHashProvider }; diff --git a/src/Elastic.Markdown/Slices/Layout/_Head.cshtml b/src/Elastic.Markdown/Slices/Layout/_Head.cshtml index 92f2585d9..2cdf40766 100644 --- a/src/Elastic.Markdown/Slices/Layout/_Head.cshtml +++ b/src/Elastic.Markdown/Slices/Layout/_Head.cshtml @@ -1,12 +1,17 @@ @inherits RazorSlice @using Elastic.Markdown.Helpers - @Model.Title @foreach (var fontFile in await FontPreloader.GetFontUrisAsync(@Model.UrlPathPrefix)) { } + @Model.Title + + @if (Model.CanonicalBaseUrl is not null) + { + + } @await RenderPartialAsync(_Favicon.Create()) diff --git a/src/Elastic.Markdown/Slices/_ViewModels.cs b/src/Elastic.Markdown/Slices/_ViewModels.cs index 68c40a0c9..5df1df580 100644 --- a/src/Elastic.Markdown/Slices/_ViewModels.cs +++ b/src/Elastic.Markdown/Slices/_ViewModels.cs @@ -26,6 +26,7 @@ public class IndexViewModel public required string? GithubEditUrl { get; init; } public required ApplicableTo? Applies { get; init; } public required bool AllowIndexing { get; init; } + public required string? CanonicalBaseUrl { get; init; } public required FeatureFlags Features { get; init; } public required StaticFileContentHashProvider StaticFileContentHashProvider { get; init; } } @@ -48,6 +49,7 @@ public class LayoutViewModel public required string? UrlPathPrefix { get; init; } public required string? GithubEditUrl { get; init; } public required bool AllowIndexing { get; init; } + public required string? CanonicalBaseUrl { get; init; } public required FeatureFlags Features { get; init; } public required DocumentationGroup[] TopLevelNavigationItems { get; init; } diff --git a/src/docs-builder/Cli/Commands.cs b/src/docs-builder/Cli/Commands.cs index 0f5b03bdd..13b71acda 100644 --- a/src/docs-builder/Cli/Commands.cs +++ b/src/docs-builder/Cli/Commands.cs @@ -76,6 +76,7 @@ public async Task ServeStatic(string? path = null, int port = 4000, Cancel ctx = /// Treat warnings as errors and fail the build on warnings /// Allow indexing and following of html files /// Only emit documentation metadata to output + /// The base URL for the canonical url tag /// [Command("generate")] [ConsoleAppFilter] @@ -89,6 +90,7 @@ public async Task Generate( bool? strict = null, bool? allowIndexing = null, bool? metadataOnly = null, + string? canonicalBaseUrl = null, Cancel ctx = default ) { @@ -105,7 +107,8 @@ public async Task Generate( { UrlPathPrefix = pathPrefix, Force = force ?? false, - AllowIndexing = allowIndexing ?? false + AllowIndexing = allowIndexing ?? false, + CanonicalBaseUrl = canonicalBaseUrl }; } // On CI, we are running on merge commit which may have changes against an older @@ -156,6 +159,7 @@ public async Task Generate( /// Treat warnings as errors and fail the build on warnings /// Allow indexing and following of html files /// Only emit documentation metadata to output + /// The base URL for the canonical url tag /// [Command("")] [ConsoleAppFilter] @@ -169,9 +173,10 @@ public async Task GenerateDefault( bool? strict = null, bool? allowIndexing = null, bool? metadataOnly = null, + string? canonicalBaseUrl = null, Cancel ctx = default ) => - await Generate(path, output, pathPrefix, force, strict, allowIndexing, metadataOnly, ctx); + await Generate(path, output, pathPrefix, force, strict, allowIndexing, metadataOnly, canonicalBaseUrl, ctx); /// From bb378c177a577aba1b2a052a43cb79f7156d7b6f Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Wed, 19 Mar 2025 22:15:04 +0100 Subject: [PATCH 2/3] Refactor to Uri --- src/Elastic.Markdown/BuildContext.cs | 2 +- src/Elastic.Markdown/Slices/HtmlWriter.cs | 2 +- src/Elastic.Markdown/Slices/Layout/_Head.cshtml | 2 +- src/Elastic.Markdown/Slices/_ViewModels.cs | 4 ++-- src/docs-builder/Cli/Commands.cs | 6 +++++- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Elastic.Markdown/BuildContext.cs b/src/Elastic.Markdown/BuildContext.cs index 19d4c36c7..4586cf1e1 100644 --- a/src/Elastic.Markdown/BuildContext.cs +++ b/src/Elastic.Markdown/BuildContext.cs @@ -35,7 +35,7 @@ public record BuildContext public bool AllowIndexing { get; init; } // This property is used for the canonical URL - public string? CanonicalBaseUrl { get; init; } + public Uri? CanonicalBaseUrl { get; init; } private readonly string? _urlPathPrefix; public string? UrlPathPrefix diff --git a/src/Elastic.Markdown/Slices/HtmlWriter.cs b/src/Elastic.Markdown/Slices/HtmlWriter.cs index dce2eed9f..457e50475 100644 --- a/src/Elastic.Markdown/Slices/HtmlWriter.cs +++ b/src/Elastic.Markdown/Slices/HtmlWriter.cs @@ -103,7 +103,7 @@ public async Task RenderLayout(MarkdownFile markdown, MarkdownDocument d Applies = markdown.YamlFrontMatter?.AppliesTo, GithubEditUrl = editUrl, AllowIndexing = DocumentationSet.Build.AllowIndexing && !markdown.Hidden, - CanonicalBaseUrl = DocumentationSet.Build.CanonicalBaseUrl?.TrimEnd('/'), + CanonicalBaseUrl = DocumentationSet.Build.CanonicalBaseUrl, Features = DocumentationSet.Configuration.Features, StaticFileContentHashProvider = StaticFileContentHashProvider }); diff --git a/src/Elastic.Markdown/Slices/Layout/_Head.cshtml b/src/Elastic.Markdown/Slices/Layout/_Head.cshtml index 2cdf40766..f11e9c891 100644 --- a/src/Elastic.Markdown/Slices/Layout/_Head.cshtml +++ b/src/Elastic.Markdown/Slices/Layout/_Head.cshtml @@ -10,7 +10,7 @@ @if (Model.CanonicalBaseUrl is not null) { - + } diff --git a/src/Elastic.Markdown/Slices/_ViewModels.cs b/src/Elastic.Markdown/Slices/_ViewModels.cs index 5df1df580..3d26c1a99 100644 --- a/src/Elastic.Markdown/Slices/_ViewModels.cs +++ b/src/Elastic.Markdown/Slices/_ViewModels.cs @@ -26,7 +26,7 @@ public class IndexViewModel public required string? GithubEditUrl { get; init; } public required ApplicableTo? Applies { get; init; } public required bool AllowIndexing { get; init; } - public required string? CanonicalBaseUrl { get; init; } + public required Uri? CanonicalBaseUrl { get; init; } public required FeatureFlags Features { get; init; } public required StaticFileContentHashProvider StaticFileContentHashProvider { get; init; } } @@ -49,7 +49,7 @@ public class LayoutViewModel public required string? UrlPathPrefix { get; init; } public required string? GithubEditUrl { get; init; } public required bool AllowIndexing { get; init; } - public required string? CanonicalBaseUrl { get; init; } + public required Uri? CanonicalBaseUrl { get; init; } public required FeatureFlags Features { get; init; } public required DocumentationGroup[] TopLevelNavigationItems { get; init; } diff --git a/src/docs-builder/Cli/Commands.cs b/src/docs-builder/Cli/Commands.cs index 13b71acda..c62c6ac1d 100644 --- a/src/docs-builder/Cli/Commands.cs +++ b/src/docs-builder/Cli/Commands.cs @@ -101,6 +101,10 @@ public async Task Generate( var runningOnCi = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GITHUB_ACTIONS")); BuildContext context; + + if (!Uri.TryCreate(canonicalBaseUrl, UriKind.Absolute, out var canonicalBaseUri)) + throw new ArgumentException($"The canonical base url '{canonicalBaseUrl}' is not a valid absolute uri"); + try { context = new BuildContext(collector, fileSystem, fileSystem, path, output) @@ -108,7 +112,7 @@ public async Task Generate( UrlPathPrefix = pathPrefix, Force = force ?? false, AllowIndexing = allowIndexing ?? false, - CanonicalBaseUrl = canonicalBaseUrl + CanonicalBaseUrl = canonicalBaseUri }; } // On CI, we are running on merge commit which may have changes against an older From a31049b3fd687284f86bebce2b975cd78c979ae4 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Wed, 19 Mar 2025 22:41:31 +0100 Subject: [PATCH 3/3] Fix --- src/docs-builder/Cli/Commands.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/docs-builder/Cli/Commands.cs b/src/docs-builder/Cli/Commands.cs index c62c6ac1d..e045a5629 100644 --- a/src/docs-builder/Cli/Commands.cs +++ b/src/docs-builder/Cli/Commands.cs @@ -102,7 +102,9 @@ public async Task Generate( var runningOnCi = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GITHUB_ACTIONS")); BuildContext context; - if (!Uri.TryCreate(canonicalBaseUrl, UriKind.Absolute, out var canonicalBaseUri)) + Uri? canonicalBaseUri = null; + + if (canonicalBaseUrl != null && !Uri.TryCreate(canonicalBaseUrl, UriKind.Absolute, out canonicalBaseUri)) throw new ArgumentException($"The canonical base url '{canonicalBaseUrl}' is not a valid absolute uri"); try