From 33b6f0f57db7acebc168b33d79d41af2573fdc9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20=C3=87elik?= Date: Thu, 4 Sep 2025 10:42:35 +0300 Subject: [PATCH] Refactor TOC heading handling with Heading record Introduces a Heading record to replace tuple usage for TOC headings, improving code readability and maintainability. Updates related logic in TocGeneratorService to use the new Heading type and adds constants for heading levels. --- .../TableOfContents/TocGeneratorService.cs | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Web/TableOfContents/TocGeneratorService.cs b/modules/docs/src/Volo.Docs.Web/TableOfContents/TocGeneratorService.cs index d53bb0f91b..668147820b 100644 --- a/modules/docs/src/Volo.Docs.Web/TableOfContents/TocGeneratorService.cs +++ b/modules/docs/src/Volo.Docs.Web/TableOfContents/TocGeneratorService.cs @@ -11,6 +11,7 @@ namespace Volo.Docs.TableOfContents; public class TocGeneratorService : ITocGeneratorService, ITransientDependency { private readonly HashSet _generatedIds = []; + public record Heading(int Level, string Text, string Id); public (string TocHtml, string ProcessedContent) GenerateTocAndProcessHeadings(string content) { @@ -20,7 +21,7 @@ public class TocGeneratorService : ITocGeneratorService, ITransientDependency } _generatedIds.Clear(); - var tocHeadings = new List<(int Level, string Text, string Id)>(); + var tocHeadings = new List(); var doc = new HtmlDocument(); doc.LoadHtml(content); @@ -50,7 +51,7 @@ public class TocGeneratorService : ITocGeneratorService, ITransientDependency var level = int.Parse(node.Name.Substring(1)); if (level == 2 || level == 3) { - tocHeadings.Add((level, node.InnerText.Trim(), id)); + tocHeadings.Add(new Heading(level, node.InnerText.Trim(), id)); } } } @@ -91,13 +92,16 @@ public class TocGeneratorService : ITocGeneratorService, ITransientDependency return finalId; } - private static string BuildTocHtml(List<(int Level, string Text, string Id)> headings) + private static string BuildTocHtml(List headings) { if (headings == null || headings.Count == 0) { return string.Empty; } + const int H2Level = 2; + const int H3Level = 3; + var tocBuilder = new StringBuilder(); tocBuilder.Append("
    "); @@ -107,47 +111,47 @@ public class TocGeneratorService : ITocGeneratorService, ITransientDependency foreach (var (index, heading) in headings.Select((h, i) => (i, h))) { var isLastItem = index == headings.Count - 1; - var nextHeading = isLastItem ? default : headings[index + 1]; - var hasChildren = nextHeading.Level == 3 && heading.Level == 2; + var nextHeading = isLastItem ? null : headings[index + 1]; + + var hasChildren = nextHeading?.Level == H3Level && heading.Level == H2Level; if (heading.Level < currentLevel) { tocBuilder.Append("
"); } - else if (!isFirstH2 && heading.Level == 2 && currentLevel == 2) + else if (heading.Level == currentLevel && heading.Level == H2Level && !isFirstH2) { tocBuilder.Append(""); } - if (heading.Level == 2) + if (heading.Level == H2Level) { var liClass = hasChildren ? "nav-item toc-item-has-children" : "nav-item"; tocBuilder.Append($"
  • {heading.Text}"); isFirstH2 = false; } - else if (heading.Level == 3) + else if (heading.Level == H3Level) { - if (currentLevel != 3) + if (currentLevel < H3Level) { tocBuilder.Append("
      "); } - tocBuilder.Append($"
    • {heading.Text}
    • "); } currentLevel = heading.Level; } - if (currentLevel == 3) + if (currentLevel == H3Level) { - tocBuilder.Append("
  • "); + tocBuilder.Append(""); } - else if (currentLevel == 2 && !isFirstH2) + else if (currentLevel == H2Level) { tocBuilder.Append(""); } - tocBuilder.Append(""); + tocBuilder.Append(""); return tocBuilder.ToString(); }