using System; using System.Collections.Generic; using System.Web; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Documents; using Avalonia.Layout; using Avalonia.Media; using HtmlAgilityPack; namespace Saradomin.Utilities { public class HtmlRenderer { private int _listDescent = 0; private string _prefix; private InlineCollection _inlines; private HtmlNode _rootNode; public HtmlRenderer(HtmlNode rootNode) { _rootNode = rootNode; } public InlineCollection Render() { _inlines = new(); { Visit(_rootNode); } return _inlines; } private void InNewBlockDo(Action action) { action(); _inlines.Add(new LineBreak()); } private void CreateNewInlineTextElement( string text, FontWeight weight = FontWeight.Normal, double fontSize = 12 ) { _inlines.Add(new Run(text) { FontWeight = weight, FontSize = fontSize, }); } private void VisitBold(HtmlNode htmlNode) { CreateNewInlineTextElement( HttpUtility.HtmlDecode( htmlNode.GetDirectInnerText() ), FontWeight.Bold ); } private void VisitList(HtmlNode htmlNode) { _listDescent++; { InNewBlockDo(() => { foreach (var child in htmlNode.ChildNodes) { Visit(child); } }); } _listDescent--; } private void VisitListEntry(HtmlNode htmlNode) { _inlines.Add(new Run("• ")); for (var i = 0; i < htmlNode.ChildNodes.Count; i++) { var child = htmlNode.ChildNodes[i]; if (i != 0) { _prefix = " "; } Visit(child); _prefix = null; } _prefix = null; _inlines.Add(new LineBreak()); } private void VisitParagraph(HtmlNode htmlNode) { InNewBlockDo(() => { foreach (var child in htmlNode.ChildNodes) { Visit(child); } }); } private void Visit(HtmlNode htmlNode) { switch (htmlNode.Name) { case "#text": var text = HttpUtility.HtmlDecode( htmlNode.GetDirectInnerText().Trim(' ').Trim('\n') ); CreateNewInlineTextElement($"{_prefix}{text}"); break; case "br": _inlines.Add(new LineBreak()); break; case "b": VisitBold(htmlNode); break; case "ul": VisitList(htmlNode); break; case "li": VisitListEntry(htmlNode); break; case "p": VisitParagraph(htmlNode); break; default: foreach (var child in htmlNode.ChildNodes) { Visit(child); } break; } } } }