using AngleSharp; using AngleSharp.Dom; using YaeBlog.Core.Abstractions; using YaeBlog.Core.Models; using YaeBlog.Core.Services; namespace YaeBlog.Core.Processors; public class HeadlinePostRenderProcessor( IConfiguration angleConfiguration, TableOfContentService tableOfContentService) : IPostRenderProcessor { public async Task ProcessAsync(BlogEssay essay) { BrowsingContext browsingContext = new(angleConfiguration); IDocument document = await browsingContext.OpenAsync(req => req.Content(essay.HtmlContent)); IEnumerable elements = from item in document.All where item.LocalName is "h2" or "h3" or "h4" select item; BlogHeadline topHeadline = new(essay.Title, "#title"); List level2List = []; List level3List = []; List level4List = []; foreach (IElement element in elements) { switch (element.LocalName) { case "h2": { FindParentHeadline(topHeadline, level2List, level3List).Children.AddRange(level4List); level4List.Clear(); FindParentHeadline(topHeadline, level2List).Children.AddRange(level3List); level3List.Clear(); BlogHeadline headline = ParserHeadlineElement(element); level2List.Add(headline); break; } case "h3": { FindParentHeadline(topHeadline, level2List, level3List).Children.AddRange(level4List); level4List.Clear(); BlogHeadline headline = ParserHeadlineElement(element); level3List.Add(headline); break; } case "h4": { BlogHeadline headline = ParserHeadlineElement(element); level4List.Add(headline); break; } } } // 太抽象了((( FindParentHeadline(topHeadline, level2List, level3List).Children.AddRange(level4List); FindParentHeadline(topHeadline, level2List).Children.AddRange(level3List); topHeadline.Children.AddRange(level2List); tableOfContentService.AddHeadline(essay.FileName, topHeadline); return essay.WithNewHtmlContent(document.DocumentElement.OuterHtml); } private static BlogHeadline ParserHeadlineElement(IElement element) { element.Id ??= element.TextContent; return new BlogHeadline(element.TextContent, element.Id); } /// /// 找到h4标题的父级标题 /// /// /// /// /// private static BlogHeadline FindParentHeadline(BlogHeadline topHeadline, List level2, List level3) { BlogHeadline? result = level3.LastOrDefault(); if (result is not null) { return result; } return level2.LastOrDefault() ?? topHeadline; } /// /// 找到h3标题的父级标题 /// /// /// /// private static BlogHeadline FindParentHeadline(BlogHeadline topHeadline, List level2) => FindParentHeadline(topHeadline, level2, []); public string Name => nameof(HeadlinePostRenderProcessor); }