257 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Text;
 | |
| using System.IO;
 | |
| using System.Xml;
 | |
| using System.Collections;
 | |
| using System.Text.RegularExpressions;
 | |
| 
 | |
| #if AdvTree
 | |
| namespace DevComponents.Tree.TextMarkup
 | |
| #elif DOTNETBAR
 | |
| namespace DevComponents.DotNetBar.TextMarkup
 | |
| #elif SUPERGRID
 | |
| namespace DevComponents.SuperGrid.TextMarkup
 | |
| #elif LAYOUT
 | |
| namespace DevComponents.DotNetBar.Layout.TextMarkup
 | |
| #endif
 | |
| {
 | |
|     internal class MarkupParser
 | |
|     {
 | |
|         #region Private Variables
 | |
|         private static string TextElementName = "text";
 | |
|         private static string BodyTag = "body";
 | |
|         #endregion
 | |
| 
 | |
|         #region Internal Implementation
 | |
|         public static BodyElement Parse(string text)
 | |
|         {
 | |
|             StringBuilder plainText = new StringBuilder(text.Length);
 | |
|             BodyElement root = new BodyElement();
 | |
|             root.HasExpandElement = false;
 | |
|             MarkupElement currentParent = root;
 | |
|             Stack openTags = new Stack();
 | |
|             openTags.Push(root);
 | |
|             // Input text is not wrapped into the container tag so we wrap it here
 | |
|             text = text.Replace(" ", "{ent_nbsp}");
 | |
|             text = text.Replace("&zwsp;", "{ent_zwsp}");
 | |
|             text = text.Replace("<", "{ent_lt}");
 | |
|             text = text.Replace(">", "{ent_gt}");
 | |
|             text = text.Replace("&", "{ent_amp}");
 | |
|             text = text.Replace("|", "{ent_l}");
 | |
|             text = text.Replace("&", "|");
 | |
|             text = text.Replace("{ent_nbsp}", " ");
 | |
|             text = text.Replace("{ent_zwsp}", "&zwsp;"); 
 | |
|             text = text.Replace("{ent_lt}", "<");
 | |
|             text = text.Replace("{ent_gt}", ">");
 | |
|             StringReader sr = new StringReader("<"+BodyTag+">" + text + "</"+BodyTag+">");
 | |
| #if !DEBUG
 | |
|             try
 | |
| #endif
 | |
|             {
 | |
|                 XmlTextReader reader = new XmlTextReader(sr);
 | |
|                 //reader.EntityHandling = EntityHandling.ExpandCharEntities;
 | |
|                 while (reader.Read())
 | |
|                 {
 | |
|                     if (reader.NodeType == XmlNodeType.Element)
 | |
|                     {
 | |
|                         if (reader.Name == BodyTag)
 | |
|                             continue;
 | |
|                         MarkupElement el = CreateMarkupElement(reader.Name);
 | |
|                         if (el == null)
 | |
|                         {
 | |
|                             reader.Skip();
 | |
|                             continue;
 | |
|                         }
 | |
|                         else if (el is ExpandElement)
 | |
|                             root.HasExpandElement = true;
 | |
| 
 | |
|                         if (el is IActiveMarkupElement)
 | |
|                             root.ActiveElements.Add(el);
 | |
| 
 | |
|                         // Parse any attributes here
 | |
|                         if (reader.AttributeCount > 0)
 | |
|                         {
 | |
|                             el.ReadAttributes(reader);
 | |
|                             reader.MoveToElement();
 | |
|                         }
 | |
| 
 | |
|                         currentParent.Elements.Add(el);
 | |
| 
 | |
|                         if (el is ContainerElement)
 | |
|                             currentParent = el;
 | |
| 
 | |
|                         if (!reader.IsEmptyElement)
 | |
|                             openTags.Push(el);
 | |
|                     }
 | |
|                     else if (reader.NodeType == XmlNodeType.Text)
 | |
|                     {
 | |
|                         if (reader.Value.Length == 1)
 | |
|                         {
 | |
|                             TextElement el = CreateMarkupElement(TextElementName) as TextElement;
 | |
|                             if (reader.Value == " ")
 | |
|                             {
 | |
|                                 el.TrailingSpace = true;
 | |
|                                 plainText.Append(' ');
 | |
|                             }
 | |
|                             else
 | |
|                             {
 | |
|                                 el.Text = reader.Value;
 | |
|                                 el.Text = el.Text.Replace("|", "&");
 | |
|                                 el.Text = el.Text.Replace("{ent_l}", "|");
 | |
|                                 el.Text = el.Text.Replace("{ent_amp}", "&&");
 | |
|                                 plainText.Append(el.Text+" ");
 | |
|                             }
 | |
|                             currentParent.Elements.Add(el);
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             string s = reader.Value;
 | |
|                             if (s.StartsWith("\r\n"))
 | |
|                                 s = s.TrimStart(new char[] { '\r', '\n' });
 | |
|                             s = s.Replace("\r\n", " ");
 | |
|                             string[] words = s.Split(' ');
 | |
|                             bool space = false;
 | |
|                             if (currentParent.Elements.Count > 0 && currentParent.Elements[currentParent.Elements.Count - 1] is NewLine)
 | |
|                                 space = true;
 | |
|                             for (int i = 0; i < words.Length; i++)
 | |
|                             {
 | |
|                                 if (words[i].Length == 0)
 | |
|                                 {
 | |
|                                     if (space)
 | |
|                                         continue;
 | |
|                                     space = true;
 | |
|                                 }
 | |
|                                 else
 | |
|                                     space = false;
 | |
| 
 | |
|                                 TextElement el = CreateMarkupElement(TextElementName) as TextElement;
 | |
|                                 el.Text = words[i].Replace("|","&");
 | |
|                                 el.Text = el.Text.Replace("{ent_l}", "|");
 | |
|                                 el.Text = el.Text.Replace("{ent_amp}", "&&");
 | |
|                                 plainText.Append(el.Text + " ");
 | |
|                                 if (i < words.Length - 1)
 | |
|                                 {
 | |
|                                     el.TrailingSpace = true;
 | |
|                                     space = true;
 | |
|                                 }
 | |
| 
 | |
|                                 currentParent.Elements.Add(el);
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                     else if (reader.NodeType == XmlNodeType.Whitespace)
 | |
|                     {
 | |
|                         if (reader.Value.IndexOf(' ') >= 0)
 | |
|                         {
 | |
|                             TextElement el = CreateMarkupElement(TextElementName) as TextElement;
 | |
|                             el.TrailingSpace = true;
 | |
|                             currentParent.Elements.Add(el);
 | |
|                         }
 | |
|                     }
 | |
|                     else if (reader.NodeType == XmlNodeType.EntityReference)
 | |
|                     {
 | |
|                         TextElement el = CreateMarkupElement(TextElementName) as TextElement;
 | |
|                         if (reader.Name == "nbsp")
 | |
|                         {
 | |
|                             el.TrailingSpace = true;
 | |
|                         }
 | |
|                         else if (reader.Name == "zwsp")
 | |
|                         {
 | |
|                             el.TrailingSpace = false;
 | |
|                         }
 | |
|                         else
 | |
|                             el.Text = reader.Name;
 | |
|                         el.EnablePrefixHandling = false;
 | |
|                         currentParent.Elements.Add(el);
 | |
|                     }
 | |
|                     else if (reader.NodeType == XmlNodeType.EndElement)
 | |
|                     {
 | |
|                         MarkupElement el = openTags.Pop() as MarkupElement;
 | |
|                         if (el != currentParent)
 | |
|                         {
 | |
|                             currentParent.Elements.Add(new EndMarkupElement(el));
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             if (currentParent != root)
 | |
|                                 currentParent = currentParent.Parent;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| #if !DEBUG
 | |
|             catch
 | |
|             {
 | |
|                 return null;
 | |
|             }
 | |
| #endif
 | |
|             root.PlainText = plainText.ToString();
 | |
|             return root;
 | |
|         }
 | |
| 
 | |
|         public static MarkupElement CreateMarkupElement(string elementName)
 | |
|         {
 | |
|             if (elementName == "b" || elementName == "strong")
 | |
|                 return new Strong();
 | |
|             else if (elementName == "i" || elementName == "em")
 | |
|                 return new Italic();
 | |
|             else if (elementName == "u")
 | |
|                 return new Underline();
 | |
|             else if (elementName == "br")
 | |
|                 return new NewLine();
 | |
|             else if (elementName == "expand")
 | |
|                 return new ExpandElement();
 | |
|             else if (elementName == "a")
 | |
|                 return new HyperLink();
 | |
|             else if (elementName == "p")
 | |
|                 return new Paragraph();
 | |
|             else if (elementName == "div")
 | |
|                 return new Div();
 | |
|             else if (elementName == "span")
 | |
|                 return new Span();
 | |
|             else if (elementName == "img")
 | |
|                 return new ImageElement();
 | |
|             else if (elementName == "h1")
 | |
|                 return new Heading();
 | |
|             else if (elementName == "h2")
 | |
|                 return new Heading(2);
 | |
|             else if (elementName == "h3")
 | |
|                 return new Heading(3);
 | |
|             else if (elementName == "h4")
 | |
|                 return new Heading(4);
 | |
|             else if (elementName == "h5")
 | |
|                 return new Heading(5);
 | |
|             else if (elementName == "h6")
 | |
|                 return new Heading(6);
 | |
|             else if (elementName == "font")
 | |
|                 return new FontElement();
 | |
|             else if (elementName == "s" || elementName == "strike")
 | |
|                 return new Strike();
 | |
|             else if (elementName == TextElementName)
 | |
|                 return new TextElement();
 | |
|             else if (elementName == "symbol")
 | |
|                 return new SymbolElement();
 | |
| 
 | |
|             return null;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Tests whether input text could be markup text.
 | |
|         /// </summary>
 | |
|         /// <param name="text">Text to test.</param>
 | |
|         /// <returns>true if text could be markup, otherwise false</returns>
 | |
|         public static bool IsMarkup(ref string text)
 | |
|         {
 | |
|             if (text.IndexOf("</") < 0 && text.IndexOf("/>") < 0)
 | |
|                 return false;
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         internal static string RemoveExpand(string text)
 | |
|         {
 | |
|             return Regex.Replace(text, "<expand.*?>", "", RegexOptions.IgnoreCase);
 | |
|         }
 | |
|         #endregion
 | |
|     }
 | |
| }
 |