You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			388 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			388 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Text;
 | |
| using UnityEngine;
 | |
| 
 | |
| namespace FairyGUI.Utils
 | |
| {
 | |
|     /// <summary>
 | |
|     /// 
 | |
|     /// </summary>
 | |
|     public class HtmlParser
 | |
|     {
 | |
|         public static HtmlParser inst = new HtmlParser();
 | |
| 
 | |
|         protected class TextFormat2 : TextFormat
 | |
|         {
 | |
|             public bool colorChanged;
 | |
|         }
 | |
| 
 | |
|         protected List<TextFormat2> _textFormatStack;
 | |
|         protected int _textFormatStackTop;
 | |
|         protected TextFormat2 _format;
 | |
|         protected List<HtmlElement> _elements;
 | |
|         protected HtmlParseOptions _defaultOptions;
 | |
| 
 | |
|         static List<string> sHelperList1 = new List<string>();
 | |
|         static List<string> sHelperList2 = new List<string>();
 | |
| 
 | |
|         public HtmlParser()
 | |
|         {
 | |
|             _textFormatStack = new List<TextFormat2>();
 | |
|             _format = new TextFormat2();
 | |
|             _defaultOptions = new HtmlParseOptions();
 | |
|         }
 | |
| 
 | |
|         virtual public void Parse(string aSource, TextFormat defaultFormat, List<HtmlElement> elements, HtmlParseOptions parseOptions)
 | |
|         {
 | |
|             if (parseOptions == null)
 | |
|                 parseOptions = _defaultOptions;
 | |
| 
 | |
|             _elements = elements;
 | |
|             _textFormatStackTop = 0;
 | |
|             _format.CopyFrom(defaultFormat);
 | |
|             _format.colorChanged = false;
 | |
|             int skipText = 0;
 | |
|             bool ignoreWhiteSpace = parseOptions.ignoreWhiteSpace;
 | |
|             bool skipNextCR = false;
 | |
|             string text;
 | |
| 
 | |
|             XMLIterator.Begin(aSource, true);
 | |
|             while (XMLIterator.NextTag())
 | |
|             {
 | |
|                 if (skipText == 0)
 | |
|                 {
 | |
|                     text = XMLIterator.GetText(ignoreWhiteSpace);
 | |
|                     if (text.Length > 0)
 | |
|                     {
 | |
|                         if (skipNextCR && text[0] == '\n')
 | |
|                             text = text.Substring(1);
 | |
|                         AppendText(text);
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 skipNextCR = false;
 | |
|                 switch (XMLIterator.tagName)
 | |
|                 {
 | |
|                     case "b":
 | |
|                         if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                         {
 | |
|                             PushTextFormat();
 | |
|                             _format.bold = true;
 | |
|                         }
 | |
|                         else
 | |
|                             PopTextFormat();
 | |
|                         break;
 | |
| 
 | |
|                     case "i":
 | |
|                         if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                         {
 | |
|                             PushTextFormat();
 | |
|                             _format.italic = true;
 | |
|                         }
 | |
|                         else
 | |
|                             PopTextFormat();
 | |
|                         break;
 | |
| 
 | |
|                     case "u":
 | |
|                         if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                         {
 | |
|                             PushTextFormat();
 | |
|                             _format.underline = true;
 | |
|                         }
 | |
|                         else
 | |
|                             PopTextFormat();
 | |
|                         break;
 | |
| 
 | |
|                     case "strike":
 | |
|                         if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                         {
 | |
|                             PushTextFormat();
 | |
|                             _format.strikethrough = true;
 | |
|                         }
 | |
|                         else
 | |
|                             PopTextFormat();
 | |
|                         break;
 | |
| 
 | |
|                     case "sub":
 | |
|                         {
 | |
|                             if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                             {
 | |
|                                 PushTextFormat();
 | |
|                                 _format.specialStyle = TextFormat.SpecialStyle.Subscript;
 | |
|                             }
 | |
|                             else
 | |
|                                 PopTextFormat();
 | |
|                         }
 | |
|                         break;
 | |
| 
 | |
|                     case "sup":
 | |
|                         {
 | |
|                             if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                             {
 | |
|                                 PushTextFormat();
 | |
|                                 _format.specialStyle = TextFormat.SpecialStyle.Superscript;
 | |
|                             }
 | |
|                             else
 | |
|                                 PopTextFormat();
 | |
|                         }
 | |
|                         break;
 | |
| 
 | |
|                     case "font":
 | |
|                         if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                         {
 | |
|                             PushTextFormat();
 | |
| 
 | |
|                             _format.size = XMLIterator.GetAttributeInt("size", _format.size);
 | |
|                             string color = XMLIterator.GetAttribute("color");
 | |
|                             if (color != null)
 | |
|                             {
 | |
|                                 string[] parts = color.Split(',');
 | |
|                                 if (parts.Length == 1)
 | |
|                                 {
 | |
|                                     _format.color = ToolSet.ConvertFromHtmlColor(color);
 | |
|                                     _format.gradientColor = null;
 | |
|                                     _format.colorChanged = true;
 | |
|                                 }
 | |
|                                 else
 | |
|                                 {
 | |
|                                     if (_format.gradientColor == null)
 | |
|                                         _format.gradientColor = new Color32[4];
 | |
|                                     _format.gradientColor[0] = ToolSet.ConvertFromHtmlColor(parts[0]);
 | |
|                                     _format.gradientColor[1] = ToolSet.ConvertFromHtmlColor(parts[1]);
 | |
|                                     if (parts.Length > 2)
 | |
|                                     {
 | |
|                                         _format.gradientColor[2] = ToolSet.ConvertFromHtmlColor(parts[2]);
 | |
|                                         if (parts.Length > 3)
 | |
|                                             _format.gradientColor[3] = ToolSet.ConvertFromHtmlColor(parts[3]);
 | |
|                                         else
 | |
|                                             _format.gradientColor[3] = _format.gradientColor[2];
 | |
|                                     }
 | |
|                                     else
 | |
|                                     {
 | |
|                                         _format.gradientColor[2] = _format.gradientColor[0];
 | |
|                                         _format.gradientColor[3] = _format.gradientColor[1];
 | |
|                                     }
 | |
|                                 }
 | |
|                             }
 | |
|                         }
 | |
|                         else if (XMLIterator.tagType == XMLTagType.End)
 | |
|                             PopTextFormat();
 | |
|                         break;
 | |
| 
 | |
|                     case "br":
 | |
|                         AppendText("\n");
 | |
|                         break;
 | |
| 
 | |
|                     case "img":
 | |
|                         if (XMLIterator.tagType == XMLTagType.Start || XMLIterator.tagType == XMLTagType.Void)
 | |
|                         {
 | |
|                             HtmlElement element = HtmlElement.GetElement(HtmlElementType.Image);
 | |
|                             element.FetchAttributes();
 | |
|                             element.name = element.GetString("name");
 | |
|                             element.format.align = _format.align;
 | |
|                             _elements.Add(element);
 | |
|                         }
 | |
|                         break;
 | |
| 
 | |
|                     case "a":
 | |
|                         if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                         {
 | |
|                             PushTextFormat();
 | |
| 
 | |
|                             _format.underline = _format.underline || parseOptions.linkUnderline;
 | |
|                             if (!_format.colorChanged && parseOptions.linkColor.a != 0)
 | |
|                                 _format.color = parseOptions.linkColor;
 | |
| 
 | |
|                             HtmlElement element = HtmlElement.GetElement(HtmlElementType.Link);
 | |
|                             element.FetchAttributes();
 | |
|                             element.name = element.GetString("name");
 | |
|                             element.format.align = _format.align;
 | |
|                             _elements.Add(element);
 | |
|                         }
 | |
|                         else if (XMLIterator.tagType == XMLTagType.End)
 | |
|                         {
 | |
|                             PopTextFormat();
 | |
| 
 | |
|                             HtmlElement element = HtmlElement.GetElement(HtmlElementType.LinkEnd);
 | |
|                             _elements.Add(element);
 | |
|                         }
 | |
|                         break;
 | |
| 
 | |
|                     case "input":
 | |
|                         {
 | |
|                             HtmlElement element = HtmlElement.GetElement(HtmlElementType.Input);
 | |
|                             element.FetchAttributes();
 | |
|                             element.name = element.GetString("name");
 | |
|                             element.format.CopyFrom(_format);
 | |
|                             _elements.Add(element);
 | |
|                         }
 | |
|                         break;
 | |
| 
 | |
|                     case "select":
 | |
|                         {
 | |
|                             if (XMLIterator.tagType == XMLTagType.Start || XMLIterator.tagType == XMLTagType.Void)
 | |
|                             {
 | |
|                                 HtmlElement element = HtmlElement.GetElement(HtmlElementType.Select);
 | |
|                                 element.FetchAttributes();
 | |
|                                 if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                                 {
 | |
|                                     sHelperList1.Clear();
 | |
|                                     sHelperList2.Clear();
 | |
|                                     while (XMLIterator.NextTag())
 | |
|                                     {
 | |
|                                         if (XMLIterator.tagName == "select")
 | |
|                                             break;
 | |
| 
 | |
|                                         if (XMLIterator.tagName == "option")
 | |
|                                         {
 | |
|                                             if (XMLIterator.tagType == XMLTagType.Start || XMLIterator.tagType == XMLTagType.Void)
 | |
|                                                 sHelperList2.Add(XMLIterator.GetAttribute("value", string.Empty));
 | |
|                                             else
 | |
|                                                 sHelperList1.Add(XMLIterator.GetText());
 | |
|                                         }
 | |
|                                     }
 | |
|                                     element.Set("items", sHelperList1.ToArray());
 | |
|                                     element.Set("values", sHelperList2.ToArray());
 | |
|                                 }
 | |
|                                 element.name = element.GetString("name");
 | |
|                                 element.format.CopyFrom(_format);
 | |
|                                 _elements.Add(element);
 | |
|                             }
 | |
|                         }
 | |
|                         break;
 | |
| 
 | |
|                     case "p":
 | |
|                         if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                         {
 | |
|                             PushTextFormat();
 | |
|                             string align = XMLIterator.GetAttribute("align");
 | |
|                             switch (align)
 | |
|                             {
 | |
|                                 case "center":
 | |
|                                     _format.align = AlignType.Center;
 | |
|                                     break;
 | |
|                                 case "right":
 | |
|                                     _format.align = AlignType.Right;
 | |
|                                     break;
 | |
|                             }
 | |
|                             if (!IsNewLine())
 | |
|                                 AppendText("\n");
 | |
|                         }
 | |
|                         else if (XMLIterator.tagType == XMLTagType.End)
 | |
|                         {
 | |
|                             AppendText("\n");
 | |
|                             skipNextCR = true;
 | |
| 
 | |
|                             PopTextFormat();
 | |
|                         }
 | |
|                         break;
 | |
| 
 | |
|                     case "ui":
 | |
|                     case "div":
 | |
|                     case "li":
 | |
|                         if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                         {
 | |
|                             if (!IsNewLine())
 | |
|                                 AppendText("\n");
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             AppendText("\n");
 | |
|                             skipNextCR = true;
 | |
|                         }
 | |
|                         break;
 | |
| 
 | |
|                     case "html":
 | |
|                     case "body":
 | |
|                         //full html
 | |
|                         ignoreWhiteSpace = true;
 | |
|                         break;
 | |
| 
 | |
|                     case "head":
 | |
|                     case "style":
 | |
|                     case "script":
 | |
|                     case "form":
 | |
|                         if (XMLIterator.tagType == XMLTagType.Start)
 | |
|                             skipText++;
 | |
|                         else if (XMLIterator.tagType == XMLTagType.End)
 | |
|                             skipText--;
 | |
|                         break;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (skipText == 0)
 | |
|             {
 | |
|                 text = XMLIterator.GetText(ignoreWhiteSpace);
 | |
|                 if (text.Length > 0)
 | |
|                 {
 | |
|                     if (skipNextCR && text[0] == '\n')
 | |
|                         text = text.Substring(1);
 | |
|                     AppendText(text);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             _elements = null;
 | |
|         }
 | |
| 
 | |
|         protected void PushTextFormat()
 | |
|         {
 | |
|             TextFormat2 tf;
 | |
|             if (_textFormatStack.Count <= _textFormatStackTop)
 | |
|             {
 | |
|                 tf = new TextFormat2();
 | |
|                 _textFormatStack.Add(tf);
 | |
|             }
 | |
|             else
 | |
|                 tf = _textFormatStack[_textFormatStackTop];
 | |
|             tf.CopyFrom(_format);
 | |
|             tf.colorChanged = _format.colorChanged;
 | |
|             _textFormatStackTop++;
 | |
|         }
 | |
| 
 | |
|         protected void PopTextFormat()
 | |
|         {
 | |
|             if (_textFormatStackTop > 0)
 | |
|             {
 | |
|                 TextFormat2 tf = _textFormatStack[_textFormatStackTop - 1];
 | |
|                 _format.CopyFrom(tf);
 | |
|                 _format.colorChanged = tf.colorChanged;
 | |
|                 _textFormatStackTop--;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         protected bool IsNewLine()
 | |
|         {
 | |
|             if (_elements.Count > 0)
 | |
|             {
 | |
|                 HtmlElement element = _elements[_elements.Count - 1];
 | |
|                 if (element != null && element.type == HtmlElementType.Text)
 | |
|                     return element.text.EndsWith("\n");
 | |
|                 else
 | |
|                     return false;
 | |
|             }
 | |
| 
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         protected void AppendText(string text)
 | |
|         {
 | |
|             HtmlElement element;
 | |
|             if (_elements.Count > 0)
 | |
|             {
 | |
|                 element = _elements[_elements.Count - 1];
 | |
|                 if (element.type == HtmlElementType.Text && element.format.EqualStyle(_format))
 | |
|                 {
 | |
|                     element.text += text;
 | |
|                     return;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             element = HtmlElement.GetElement(HtmlElementType.Text);
 | |
|             element.text = text;
 | |
|             element.format.CopyFrom(_format);
 | |
|             _elements.Add(element);
 | |
|         }
 | |
|     }
 | |
| }
 |