using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Web; using HtmlAgilityPack; namespace Umbraco.Web { /// /// Utility class for working with strings and HTML in views /// /// /// The UmbracoHelper uses this class for it's string methods /// public sealed class HtmlStringUtilities { /// /// Replaces text line breaks with html line breaks /// /// The text. /// The text with text line breaks replaced with html linebreaks (
)
public string ReplaceLineBreaksForHtml(string text) { return text.Replace("\n", "
\n"); } public HtmlString StripHtmlTags(string html, params string[] tags) { var doc = new HtmlDocument(); doc.LoadHtml("

" + html + "

"); var targets = new List(); var nodes = doc.DocumentNode.FirstChild.SelectNodes(".//*"); if (nodes != null) { foreach (var node in nodes) { //is element if (node.NodeType != HtmlNodeType.Element) continue; var filterAllTags = (tags == null || !tags.Any()); if (filterAllTags || tags.Any(tag => string.Equals(tag, node.Name, StringComparison.CurrentCultureIgnoreCase))) { targets.Add(node); } } foreach (var target in targets) { HtmlNode content = doc.CreateTextNode(target.InnerText); target.ParentNode.ReplaceChild(content, target); } } else { return new HtmlString(html); } return new HtmlString(doc.DocumentNode.FirstChild.InnerHtml); } internal string Join(string seperator, params object[] args) { var results = args.Where(arg => arg != null && arg.GetType() != typeof(TIgnore)).Select(arg => string.Format("{0}", arg)).Where(sArg => !string.IsNullOrWhiteSpace(sArg)).ToList(); return string.Join(seperator, results); } internal string Concatenate(params object[] args) { var result = new StringBuilder(); foreach (var sArg in args.Where(arg => arg != null && arg.GetType() != typeof(TIgnore)).Select(arg => string.Format("{0}", arg)).Where(sArg => !string.IsNullOrWhiteSpace(sArg))) { result.Append(sArg); } return result.ToString(); } internal string Coalesce(params object[] args) { foreach (var sArg in args.Where(arg => arg != null && arg.GetType() != typeof(TIgnore)).Select(arg => string.Format("{0}", arg)).Where(sArg => !string.IsNullOrWhiteSpace(sArg))) { return sArg; } return string.Empty; } public IHtmlString Truncate(string html, int length, bool addElipsis, bool treatTagsAsContent) { using (var outputms = new MemoryStream()) { using (var outputtw = new StreamWriter(outputms)) { using (var ms = new MemoryStream()) { using (var tw = new StreamWriter(ms)) { tw.Write(html); tw.Flush(); ms.Position = 0; var tagStack = new Stack(); using (TextReader tr = new StreamReader(ms)) { bool isInsideElement = false, lengthReached = false, insideTagSpaceEncountered = false, isTagClose = false; int ic = 0, currentLength = 0, currentTextLength = 0; string currentTag = string.Empty, tagContents = string.Empty; while ((ic = tr.Read()) != -1) { bool write = true; switch ((char)ic) { case '<': if (!lengthReached) { isInsideElement = true; } insideTagSpaceEncountered = false; currentTag = string.Empty; tagContents = string.Empty; isTagClose = false; if (tr.Peek() == (int)'/') { isTagClose = true; } break; case '>': isInsideElement = false; if (isTagClose && tagStack.Count > 0) { string thisTag = tagStack.Pop(); outputtw.Write(""); } if (!isTagClose && currentTag.Length > 0) { if (!lengthReached) { tagStack.Push(currentTag); outputtw.Write("<" + currentTag); if (!string.IsNullOrEmpty(tagContents)) { if (tagContents.EndsWith("/")) { // No end tag e.g.
. tagStack.Pop(); } outputtw.Write(tagContents); write = true; insideTagSpaceEncountered = false; } outputtw.Write(">"); } } // Continue to next iteration of the text reader. continue; default: if (isInsideElement) { if (ic == (int)' ') { if (!insideTagSpaceEncountered) { insideTagSpaceEncountered = true; } } if (!insideTagSpaceEncountered) { currentTag += (char)ic; } } break; } if (isInsideElement || insideTagSpaceEncountered) { write = false; if (insideTagSpaceEncountered) { tagContents += (char)ic; } } if (!isInsideElement || treatTagsAsContent) { currentTextLength++; } if (currentTextLength <= length || (lengthReached && isInsideElement)) { if (write) { var charToWrite = (char)ic; outputtw.Write(charToWrite); currentLength++; } } if (!lengthReached && currentTextLength >= length) { // Reached truncate limit. if (addElipsis) { outputtw.Write("…"); } lengthReached = true; } } } } } outputtw.Flush(); outputms.Position = 0; using (TextReader outputtr = new StreamReader(outputms)) { return new HtmlString(outputtr.ReadToEnd().Replace(" ", " ").Trim()); } } } } } }