| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 | using System;using System.Collections.Generic;using System.Linq;using System.Text.RegularExpressions;using HtmlAgilityPack;namespace InABox.Core{    public static class HTMLUtils    {                /// <summary>        /// Takes a HTML Snippet and converts it to full HTML.        /// This is used to convert Fast-Reports "html-enabled" text to Syncfusion RichTextEditor html.        /// </summary>        /// <param name="text">The html snippet (no <head> or <body> tags, paragraphs represented by line breaks</param>        /// <returns>Properly formed HTM suitable for editing</returns>        public static string TextToHtml(string text)        {            var result = text;            if (!result.Contains("<html>"))            {                var lines = result.Split("\n").Select(l => $"<p>{(string.IsNullOrWhiteSpace(l) ? " " : l)}</p>").ToList();                while (string.Equals(lines.LastOrDefault(),$"<p> </p>"))                    lines.RemoveAt(lines.Count-1);                result = $"<html><body>{string.Join("\n",lines)}</body></html>";            }            var doc = new HtmlDocument();            doc.LoadHtml(result);            HtmlNode? head = null;            var htmlnode = doc.DocumentNode.SelectSingleNode("//html");            if (!htmlnode.ChildNodes.Any(x => string.Equals(x.Name, "head", StringComparison.CurrentCultureIgnoreCase)))            {                head = doc.CreateElement("head");                htmlnode.PrependChild(head);            }            head = doc.DocumentNode.SelectSingleNode("//head");            if (head != null)            {                HtmlNode? style = null;                if (!head.ChildNodes.Any(x =>                        string.Equals(x.Name, "style", StringComparison.CurrentCultureIgnoreCase)))                {                    style = doc.CreateElement("style");                    head.PrependChild(style);                }                else                    style = head.ChildNodes["style"];                style.InnerHtml = "p { margin: 0px 0px 0px 0px; }";            }            return doc.DocumentNode.OuterHtml;        }        /// <summary>        /// Converts HTML data to Fast-Reports compatible "html-enabled" text        /// Will dump tags that Fast-Reports cannot display        /// </summary>        /// <param name="html">The HTML data to be processed</param>        /// <returns>Text Suitable for printing using Fast-Reports</returns>        public static string HtmlToText(string html)        {            Dictionary<string, string> _replacements = new Dictionary<string, string>()            {                { "\n", "" },                { "\r", "" },                { "<p[^>]*>", "" },                { "</p[^>]*>", "\r\n" },            };                            var doc = new HtmlDocument();            doc.LoadHtml(html);            ProcessNode(doc.DocumentNode, (n) => ReplaceAttribute(n, "font-style","italic", "i"));            ProcessNode(doc.DocumentNode, (n) => ReplaceAttribute(n, "text-decoration","underline", "u"));            ProcessNode(doc.DocumentNode, (n) => ReplaceAttribute(n, "font-weight","bold", "b"));            ProcessNode(doc.DocumentNode, (n) => ReplaceAttribute(n, "font-size","(.*?)", ""));            ProcessNode(doc.DocumentNode, (n) => ReplaceAttribute(n, "font-family","(.*?)", ""));            ProcessNode(doc.DocumentNode, (n) => ReplaceAttribute(n, "background","(.*?)", ""));                            string result = doc.DocumentNode.SelectSingleNode("//body").InnerHtml;                             foreach (var _key in _replacements.Keys)                result = Regex.Replace(result, _key, _replacements[_key]);            var lines = result.Split("\r\n").ToList();            while (string.IsNullOrWhiteSpace(lines.LastOrDefault()))                lines.RemoveAt(lines.Count-1);            return string.Join("\r\n", lines);        }                private static void ProcessNode(HtmlNode node, Action<HtmlNode> action)        {            if (node.Name.ToLower() == "span")                action(node);            foreach (var _child in node.ChildNodes)                ProcessNode(_child,action);        }                private static void ReplaceAttribute(HtmlNode node, string attribute, string value, string tag)        {            var _value = $"{attribute}:{value};";            var _style = node.Attributes.Contains("style") ? node.Attributes["style"] : null;            if (_style != null)            {                var _oldvalue = _style.Value;                _style.Value = Regex.Replace(_style.Value, _value, "");                if (!string.Equals(_style.Value, _oldvalue))                {                    if (string.IsNullOrWhiteSpace(_style.Value))                        node.Attributes.Remove("style");                    if (!string.IsNullOrWhiteSpace(tag))                    {                        var text = node.OuterHtml;                        node.Name = tag;                        node.Attributes.RemoveAll();                        node.InnerHtml = text;                    }                }            }        }            }}
 |