From e49742b4a4767e31a22aee95c10396ef110990d9 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 11 Jun 2025 17:57:49 +0200 Subject: [PATCH 1/4] Refactor markdown and layout rendering by decoupling from `GlobalLayoutViewModel`. Streamline layout handling, enhance navigation item visibility logic, and rework documentation file structures for improved maintainability. (#1353) * Refactor markdown and layout rendering by decoupling from `GlobalLayoutViewModel`. Streamline layout handling, enhance navigation item visibility logic, and rework documentation file structures for improved maintainability. `Hidden` is a pure navigation property now as its removed from `MarkdownFile`. `GetCurrentNavigation()` is now non nullable * Ensure NavigationIndex is a navigation property. * Update advertising of landing-page-path * update landing page path output * Add xmldocs for IsPhantom (cherry picked from commit 8df9149187bb96b1478cea9fc69259148439ff15) --- .../Endpoints/ApiEndpoint.cs | 3 + .../Endpoints/EndpointView.cshtml | 9 -- .../Landing/LandingNavigationItem.cs | 2 + .../Landing/LandingView.cshtml | 9 -- .../Operations/OperationNavigationItem.cs | 4 + .../Operations/OperationView.cshtml | 9 -- .../TableOfContents/ITocItem.cs | 16 +++ .../Layout/_Head.cshtml | 7 -- .../Layout/_SecondaryNav.cshtml | 2 +- .../Navigation/INavigationItem.cs | 4 + .../Navigation/_TocTreeNav.cshtml | 4 + .../_GlobalLayout.cshtml | 42 +------ src/Elastic.Documentation.Site/_ViewModels.cs | 34 +++-- src/Elastic.Markdown/IO/DocumentationFile.cs | 1 + src/Elastic.Markdown/IO/DocumentationSet.cs | 119 ++++++++++-------- src/Elastic.Markdown/IO/MarkdownFile.cs | 6 +- .../IO/Navigation/DocumentationGroup.cs | 34 +++-- .../Links/CrossLinks/CrossLinkFetcher.cs | 9 +- .../Myst/FrontMatter/FrontMatterParser.cs | 1 + src/Elastic.Markdown/Slices/HtmlWriter.cs | 2 +- src/Elastic.Markdown/Slices/Index.cshtml | 21 +++- src/Elastic.Markdown/Slices/IndexViewModel.cs | 3 +- .../Slices}/Layout/_Archive.cshtml | 2 +- .../Slices/Layout/_Breadcrumbs.cshtml | 2 +- .../Slices}/Layout/_LandingPage.cshtml | 2 +- .../Slices}/Layout/_NotFound.cshtml | 2 +- .../Slices/Layout/_PrevNextNav.cshtml | 2 +- .../Slices/Layout/_TableOfContents.cshtml | 2 +- .../Slices}/LayoutName.cs | 2 +- .../Slices/MarkdownLayoutViewModel.cs | 32 +++++ src/Elastic.Markdown/Slices/_Layout.cshtml | 87 +++++++++---- .../Slices/_ViewImports.cshtml | 1 + .../Elastic.Documentation.Refactor/Move.cs | 2 +- src/tooling/docs-assembler/AssembleSources.cs | 11 +- .../docs-assembler/Cli/RepositoryCommands.cs | 22 ++-- .../Navigation/GlobalNavigation.cs | 111 +++------------- .../Navigation/GlobalNavigationFile.cs | 5 +- .../Navigation/GlobalNavigationHtmlWriter.cs | 3 + src/tooling/docs-assembler/navigation.yml | 1 + src/tooling/docs-builder/Cli/Commands.cs | 11 +- .../docs-builder/Http/DocumentationWebHost.cs | 20 +-- .../GlobalNavigationTests.cs | 5 +- 42 files changed, 352 insertions(+), 314 deletions(-) rename src/{Elastic.Documentation.Site => Elastic.Markdown/Slices}/Layout/_Archive.cshtml (99%) rename src/{Elastic.Documentation.Site => Elastic.Markdown/Slices}/Layout/_LandingPage.cshtml (99%) rename src/{Elastic.Documentation.Site => Elastic.Markdown/Slices}/Layout/_NotFound.cshtml (88%) rename src/{Elastic.Documentation.Site => Elastic.Markdown/Slices}/LayoutName.cs (91%) create mode 100644 src/Elastic.Markdown/Slices/MarkdownLayoutViewModel.cs diff --git a/src/Elastic.ApiExplorer/Endpoints/ApiEndpoint.cs b/src/Elastic.ApiExplorer/Endpoints/ApiEndpoint.cs index 356e7651c..2c72f93d4 100644 --- a/src/Elastic.ApiExplorer/Endpoints/ApiEndpoint.cs +++ b/src/Elastic.ApiExplorer/Endpoints/ApiEndpoint.cs @@ -58,10 +58,13 @@ public EndpointNavigationItem(int depth, string url, ApiEndpoint apiEndpoint, La public ApiEndpoint Index { get; } public string Url { get; } public string NavigationTitle { get; } + public bool Hidden => false; public IReadOnlyCollection NavigationItems { get; set; } = []; public INodeNavigationItem NavigationRoot { get; } public INodeNavigationItem? Parent { get; set; } + + public int NavigationIndex { get; set; } } diff --git a/src/Elastic.ApiExplorer/Endpoints/EndpointView.cshtml b/src/Elastic.ApiExplorer/Endpoints/EndpointView.cshtml index 023545495..95bc519ec 100644 --- a/src/Elastic.ApiExplorer/Endpoints/EndpointView.cshtml +++ b/src/Elastic.ApiExplorer/Endpoints/EndpointView.cshtml @@ -7,24 +7,15 @@ { DocSetName = "Api Explorer", Description = "", - Layout = null, - PageTocItems = [], CurrentNavigationItem = Model.CurrentNavigationItem, Previous = null, Next = null, NavigationHtml = Model.NavigationHtml, - LegacyPage = null, UrlPathPrefix = null, - GithubEditUrl = null, - ReportIssueUrl = null, AllowIndexing = false, CanonicalBaseUrl = null, GoogleTagManager = new GoogleTagManagerConfiguration(), Features = new FeatureFlags([]), - Parents = - [ - ], - Products = null, StaticFileContentHashProvider = Model.StaticFileContentHashProvider }; } diff --git a/src/Elastic.ApiExplorer/Landing/LandingNavigationItem.cs b/src/Elastic.ApiExplorer/Landing/LandingNavigationItem.cs index 6a1f798a9..f472b58eb 100644 --- a/src/Elastic.ApiExplorer/Landing/LandingNavigationItem.cs +++ b/src/Elastic.ApiExplorer/Landing/LandingNavigationItem.cs @@ -34,8 +34,10 @@ public class LandingNavigationItem : INodeNavigationItem? Parent { get; set; } + public int NavigationIndex { get; set; } public IReadOnlyCollection NavigationItems { get; set; } = []; public string Url { get; } + public bool Hidden => false; //TODO public string NavigationTitle { get; } = "API Documentation"; diff --git a/src/Elastic.ApiExplorer/Landing/LandingView.cshtml b/src/Elastic.ApiExplorer/Landing/LandingView.cshtml index ac0db7b18..d24553791 100644 --- a/src/Elastic.ApiExplorer/Landing/LandingView.cshtml +++ b/src/Elastic.ApiExplorer/Landing/LandingView.cshtml @@ -7,24 +7,15 @@ { DocSetName = "Api Explorer", Description = "", - Layout = null, - PageTocItems = [], CurrentNavigationItem = Model.CurrentNavigationItem, Previous = null, Next = null, NavigationHtml = Model.NavigationHtml, - LegacyPage = null, UrlPathPrefix = null, - GithubEditUrl = null, - ReportIssueUrl = null, AllowIndexing = false, CanonicalBaseUrl = null, GoogleTagManager = new GoogleTagManagerConfiguration(), Features = new FeatureFlags([]), - Parents = - [ - ], - Products = null, StaticFileContentHashProvider = Model.StaticFileContentHashProvider }; } diff --git a/src/Elastic.ApiExplorer/Operations/OperationNavigationItem.cs b/src/Elastic.ApiExplorer/Operations/OperationNavigationItem.cs index 81c040654..fe021ca1e 100644 --- a/src/Elastic.ApiExplorer/Operations/OperationNavigationItem.cs +++ b/src/Elastic.ApiExplorer/Operations/OperationNavigationItem.cs @@ -47,8 +47,12 @@ public OperationNavigationItem(int depth, string url, ApiOperation apiOperation, public int Depth { get; } public ApiOperation Model { get; } public string Url { get; } + public bool Hidden => false; public string NavigationTitle { get; } public INodeNavigationItem? Parent { get; set; } + + public int NavigationIndex { get; set; } + } diff --git a/src/Elastic.ApiExplorer/Operations/OperationView.cshtml b/src/Elastic.ApiExplorer/Operations/OperationView.cshtml index 8404f7fbe..12d821176 100644 --- a/src/Elastic.ApiExplorer/Operations/OperationView.cshtml +++ b/src/Elastic.ApiExplorer/Operations/OperationView.cshtml @@ -7,24 +7,15 @@ { DocSetName = "Api Explorer", Description = "", - Layout = null, - PageTocItems = [], CurrentNavigationItem = Model.CurrentNavigationItem, Previous = null, Next = null, NavigationHtml = Model.NavigationHtml, - LegacyPage = null, UrlPathPrefix = null, - GithubEditUrl = null, - ReportIssueUrl = null, AllowIndexing = false, CanonicalBaseUrl = null, GoogleTagManager = new GoogleTagManagerConfiguration(), Features = new FeatureFlags([]), - Parents = - [ - ], - Products = null, StaticFileContentHashProvider = Model.StaticFileContentHashProvider }; } diff --git a/src/Elastic.Documentation.Configuration/TableOfContents/ITocItem.cs b/src/Elastic.Documentation.Configuration/TableOfContents/ITocItem.cs index 4046135ad..a5f745150 100644 --- a/src/Elastic.Documentation.Configuration/TableOfContents/ITocItem.cs +++ b/src/Elastic.Documentation.Configuration/TableOfContents/ITocItem.cs @@ -22,4 +22,20 @@ public record TocReference(Uri Source, ITableOfContentsScope TableOfContentsScop { public IReadOnlyDictionary TocReferences { get; } = Children.OfType().ToDictionary(kv => kv.Source, kv => kv); + + /// + /// A phantom table of contents is a table of contents that is not rendered in the UI but is used to generate the TOC. + /// This should be used sparingly and needs explicit configuration in navigation.yml. + /// It's typically used for container TOC that holds various other TOC's where its children are rehomed throughout the navigation. + /// Examples of phantom toc's: + /// + /// - toc: elasticsearch://reference + /// - toc: docs-content:// + /// + /// Because navigation.yml does exhaustive checks to ensure all toc.yml files are referenced, marking these containers as phantoms + /// ensures that these skip validation checks + /// + /// + public bool IsPhantom { get; init; } } + diff --git a/src/Elastic.Documentation.Site/Layout/_Head.cshtml b/src/Elastic.Documentation.Site/Layout/_Head.cshtml index 0080c521e..ef3904a60 100644 --- a/src/Elastic.Documentation.Site/Layout/_Head.cshtml +++ b/src/Elastic.Documentation.Site/Layout/_Head.cshtml @@ -1,6 +1,5 @@ @inherits RazorSlice @using FontPreloader = Elastic.Documentation.Site.FileProviders.FontPreloader - @Model.Title @@ -35,9 +34,3 @@ { } - @if (!string.IsNullOrEmpty(Model.Products)) - { - - - } - diff --git a/src/Elastic.Documentation.Site/Layout/_SecondaryNav.cshtml b/src/Elastic.Documentation.Site/Layout/_SecondaryNav.cshtml index 60436170d..49ba93c0b 100644 --- a/src/Elastic.Documentation.Site/Layout/_SecondaryNav.cshtml +++ b/src/Elastic.Documentation.Site/Layout/_SecondaryNav.cshtml @@ -2,7 +2,7 @@