diff --git a/components/editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs b/components/editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs index 5af8d9ba84..325cea5963 100644 --- a/components/editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs +++ b/components/editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs @@ -70,7 +70,7 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol base.Attributes.Add("style", "visibility: hidden"); config.Add("mode", "exact"); config.Add("theme", "umbraco"); - config.Add("umbraco_path", IOHelper.ResolveUrl( SystemDirectories.Umbraco )); + config.Add("umbraco_path", IOHelper.ResolveUrl(SystemDirectories.Umbraco)); CssClass = "tinymceContainer"; plugin.ConfigSection configSection = (plugin.ConfigSection)System.Web.HttpContext.Current.GetSection("TinyMCE"); @@ -117,89 +117,89 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol } protected override void OnLoad(EventArgs args) - { - if (!IsInLiveEditingMode) - this.config["elements"] = this.ClientID; + { + if (!IsInLiveEditingMode) + this.config["elements"] = this.ClientID; - bool first = true; + bool first = true; - // Render HTML for TinyMCE instance - // in the liveediting mode we're always preloading tinymce script - if (!IsInLiveEditingMode) - { - //TinyMCE uses it's own compressor so leave it up to ScriptManager to render - ScriptManager.RegisterClientScriptInclude(this, this.GetType(), _versionId.ToString(), this.ScriptURI); - } - else - { - //We're in live edit mode so add the base js file to the dependency list - ClientDependencyLoader.Instance.RegisterDependency("tinymce3/tiny_mce_src.js", - "UmbracoClient", ClientDependencyType.Javascript); - } + // Render HTML for TinyMCE instance + // in the liveediting mode we're always preloading tinymce script + if (!IsInLiveEditingMode) + { + //TinyMCE uses it's own compressor so leave it up to ScriptManager to render + ScriptManager.RegisterClientScriptInclude(this, this.GetType(), _versionId.ToString(), this.ScriptURI); + } + else + { + //We're in live edit mode so add the base js file to the dependency list + ClientDependencyLoader.Instance.RegisterDependency("tinymce3/tiny_mce_src.js", + "UmbracoClient", ClientDependencyType.Javascript); + } - // Write script tag start - m_scriptInitBlock.Append(HtmlTextWriter.TagLeftChar.ToString()); - m_scriptInitBlock.Append("script"); - m_scriptInitBlock.Append(" type=\"text/javascript\""); - m_scriptInitBlock.Append(HtmlTextWriter.TagRightChar.ToString()); - m_scriptInitBlock.Append("\n"); + // Write script tag start + m_scriptInitBlock.Append(HtmlTextWriter.TagLeftChar.ToString()); + m_scriptInitBlock.Append("script"); + m_scriptInitBlock.Append(" type=\"text/javascript\""); + m_scriptInitBlock.Append(HtmlTextWriter.TagRightChar.ToString()); + m_scriptInitBlock.Append("\n"); - m_scriptInitBlock.Append("tinyMCE.init({\n"); + m_scriptInitBlock.Append("tinyMCE.init({\n"); - // Write options - foreach (string key in this.config.Keys) - { - //TODO: This is a hack to test if we can prevent tinymce from automatically download languages - if (!IsInLiveEditingMode || (key != "language")) - { - string val = this.config[key]; + // Write options + foreach (string key in this.config.Keys) + { + //TODO: This is a hack to test if we can prevent tinymce from automatically download languages + if (!IsInLiveEditingMode || (key != "language")) + { + string val = this.config[key]; - if (!first) - m_scriptInitBlock.Append(",\n"); - else - first = false; + if (!first) + m_scriptInitBlock.Append(",\n"); + else + first = false; - // Is boolean state or string - if (val == "true" || val == "false") - m_scriptInitBlock.Append(key + ":" + this.config[key]); - else - m_scriptInitBlock.Append(key + ":'" + this.config[key] + "'"); - } - } + // Is boolean state or string + if (val == "true" || val == "false") + m_scriptInitBlock.Append(key + ":" + this.config[key]); + else + m_scriptInitBlock.Append(key + ":'" + this.config[key] + "'"); + } + } - m_scriptInitBlock.Append("\n});\n"); - // we're wrapping the tinymce init call in a load function when in live editing, - // so we'll need to close that function declaration - if (IsInLiveEditingMode) - { - m_scriptInitBlock.Append(@"(function() { var f = + m_scriptInitBlock.Append("\n});\n"); + // we're wrapping the tinymce init call in a load function when in live editing, + // so we'll need to close that function declaration + if (IsInLiveEditingMode) + { + m_scriptInitBlock.Append(@"(function() { var f = function() { if(document.getElementById('__umbraco_tinyMCE')) tinyMCE.execCommand('mceAddControl',false,'").Append(ClientID).Append(@"'); ItemEditing.remove_startEdit(f); } ItemEditing.add_startEdit(f);})();"); - m_scriptInitBlock.Append(@"(function() { var f = + m_scriptInitBlock.Append(@"(function() { var f = function() { tinyMCE.execCommand('mceRemoveControl',false,'").Append(ClientID).Append(@"'); ItemEditing.remove_stopEdit(f); } ItemEditing.add_stopEdit(f);})();"); - } + } - // Write script tag end - m_scriptInitBlock.Append(HtmlTextWriter.EndTagLeftChars); - m_scriptInitBlock.Append("script"); - m_scriptInitBlock.Append(HtmlTextWriter.TagRightChar.ToString()); + // Write script tag end + m_scriptInitBlock.Append(HtmlTextWriter.EndTagLeftChars); + m_scriptInitBlock.Append("script"); + m_scriptInitBlock.Append(HtmlTextWriter.TagRightChar.ToString()); - // add to script manager - if (IsInLiveEditingMode) - { - ScriptManager.RegisterClientScriptBlock(this, this.GetType(), new Guid().ToString(), - m_scriptInitBlock.ToString(), false); - } + // add to script manager + if (IsInLiveEditingMode) + { + ScriptManager.RegisterClientScriptBlock(this, this.GetType(), new Guid().ToString(), + m_scriptInitBlock.ToString(), false); + } - } + } string ScriptURI @@ -306,11 +306,17 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol Regex.Matches(tag.Value.Replace(">", " >"), "(?\\S*)=\"(?[^\"]*)\"|(?\\S*)=(?[^\"|\\s]*)\\s", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + //GE: Add ContainsKey check and expand the ifs for readability foreach (Match attributeSet in m) { if (attributeSet.Groups["attributeName"].Value.ToString().ToLower() != "src") - ht.Add(attributeSet.Groups["attributeName"].Value.ToString(), - attributeSet.Groups["attributeValue"].Value.ToString()); + { + if (!ht.ContainsKey(attributeSet.Groups["attributeName"].Value.ToString())) + { + ht.Add(attributeSet.Groups["attributeName"].Value.ToString(), attributeSet.Groups["attributeValue"].Value.ToString()); + } + } } // build the element @@ -429,7 +435,7 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol { string[] umbracoPathSplit = IOHelper.ResolveUrl(SystemDirectories.Umbraco).Split('/'); string umbracoPath = ""; - + for (int i = 0; i < umbracoPathSplit.Length - 1; i++) umbracoPath += umbracoPathSplit[i] + "/"; @@ -449,7 +455,7 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol Regex.Matches(content, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); // Page for macro rendering -// page p = new page(nodeId, versionId); + // page p = new page(nodeId, versionId); System.Web.HttpContext.Current.Items["macrosAdded"] = 0; diff --git a/components/editorControls/tinymce/tinyMCEImageHelper.cs b/components/editorControls/tinymce/tinyMCEImageHelper.cs index 9dc1660091..9deec46585 100644 --- a/components/editorControls/tinymce/tinyMCEImageHelper.cs +++ b/components/editorControls/tinymce/tinyMCEImageHelper.cs @@ -67,7 +67,8 @@ namespace umbraco.editorControls.tinymce Log.Add(LogTypes.Error, User.GetUser(0), -1, "Error resizing image in editor: " + err.ToString()); } - } else + } + else { cleanTag = StripSrc(cleanTag, ht); @@ -76,7 +77,7 @@ namespace umbraco.editorControls.tinymce cleanTag += " width=\"" + helper.FindAttribute(ht, "width") + "\""; cleanTag += " height=\"" + helper.FindAttribute(ht, "height") + "\""; } - + } } else @@ -142,13 +143,13 @@ namespace umbraco.editorControls.tinymce if (orgHeight > 0 && orgWidth > 0 && resizeDim != "" && orgSrc != "") { // Check dimensions - if (Math.Abs(orgWidth/newWidth) > Math.Abs(orgHeight/newHeight)) + if (Math.Abs(orgWidth / newWidth) > Math.Abs(orgHeight / newHeight)) { - newHeight = (int) Math.Round((float) newWidth*(orgHeight/orgWidth)); + newHeight = (int)Math.Round((float)newWidth * (orgHeight / orgWidth)); } else { - newWidth = (int) Math.Round((float) newHeight*(orgWidth/orgHeight)); + newWidth = (int)Math.Round((float)newHeight * (orgWidth / orgHeight)); } // update orgSrc to remove umbraco reference @@ -156,6 +157,7 @@ namespace umbraco.editorControls.tinymce if (IOHelper.ResolveUrl(orgSrc).IndexOf(resolvedMedia) > -1) { orgSrc = SystemDirectories.Media + orgSrc.Substring(orgSrc.IndexOf(resolvedMedia) + resolvedMedia.Length); //, orgSrc.Length - orgSrc.IndexOf(String.Format("/media/", SystemDirectories.Media))); + } string ext = orgSrc.Substring(orgSrc.LastIndexOf(".") + 1, orgSrc.Length - orgSrc.LastIndexOf(".") - 1); newSrc = orgSrc.Replace("." + ext, "_" + newWidth.ToString() + "x" + newHeight.ToString() + ".jpg"); @@ -199,8 +201,13 @@ namespace umbraco.editorControls.tinymce finalWidth = newWidth; finalHeight = newHeight; + //GE: When the SystemDirectories.Media contains a ~, newSrc will also contain this and hasn't been resolved. + //This causes the editor to save content which contains a virtual url, and thus the image doesn't serve + //the admin editor successfully displays the image because the HTML is rewritten, but when you get the RTE content in the template + //it hasn't been replaced + //2011-08-12 added a IOHelper.ResolveUrl call around newSrc return - " src=\"" + newSrc + "\" width=\"" + newWidth.ToString() + "\" height=\"" + newHeight.ToString() + + " src=\"" + IOHelper.ResolveUrl(newSrc) + "\" width=\"" + newWidth.ToString() + "\" height=\"" + newHeight.ToString() + "\""; } } diff --git a/config templates/config/umbracoSettings.config b/config templates/config/umbracoSettings.config index 7939ac1b70..c5371c0ddc 100644 --- a/config templates/config/umbracoSettings.config +++ b/config templates/config/umbracoSettings.config @@ -103,6 +103,8 @@ ae oe + + true diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicBackingItem.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicBackingItem.cs index 1f3e7b5d4a..28c03d909b 100644 --- a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicBackingItem.cs +++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicBackingItem.cs @@ -30,16 +30,32 @@ namespace umbraco.MacroEngines public DynamicBackingItem(int Id) { NodeFactory.Node baseNode = new NodeFactory.Node(Id); - //todo: trace this with media - if (baseNode == null) + this.content = baseNode; + this.Type = DynamicBackingItemType.Content; + if (baseNode.Id == 0 && Id != 0) { this.media = ExamineBackedMedia.GetUmbracoMedia(Id); this.Type = DynamicBackingItemType.Media; + if (this.media == null) + { + this.Type = DynamicBackingItemType.Content; + } + return; + } + + } + public DynamicBackingItem(int Id, DynamicBackingItemType Type) + { + NodeFactory.Node baseNode = new NodeFactory.Node(Id); + if (Type == DynamicBackingItemType.Media) + { + this.media = ExamineBackedMedia.GetUmbracoMedia(Id); + this.Type = Type; } else { this.content = baseNode; - this.Type = DynamicBackingItemType.Content; + this.Type = Type; } } diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicGrouping.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicGrouping.cs index 2d98dc8b21..99187a94bc 100644 --- a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicGrouping.cs +++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicGrouping.cs @@ -20,16 +20,24 @@ namespace umbraco.MacroEngines Inner = list .Items - .GroupBy(item => - { - object result = null; - item.TryGetMember(new DynamicQueryableGetMemberBinder(groupBy, false), out result); - return result; - }) + .Select(node => + { + string predicate = groupBy; + var internalList = new DynamicNodeList(new DynamicNode[] { node }); + var query = (IQueryable)internalList.Select(predicate, new object[] { }); + var key = query.FirstOrDefault(); + return new + { + Key = key, + Node = node + }; + }) + .Where(item => item.Key != null) + .GroupBy(item => item.Key) .Select(item => new Grouping() { Key = item.Key, - Elements = item.Select(inner => inner) + Elements = item.Select(inner => inner.Node) }); } public DynamicGrouping(IEnumerable> source) diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs index 9fc6dab932..95ef5122e9 100644 --- a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs +++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicNode.cs @@ -19,7 +19,6 @@ using umbraco.MacroEngines.Library; using umbraco.BusinessLogic.Utils; - namespace umbraco.MacroEngines { public class DynamicNode : DynamicObject @@ -47,6 +46,10 @@ namespace umbraco.MacroEngines { this.n = new DynamicBackingItem(NodeId); } + public DynamicNode(int NodeId, DynamicBackingItemType ItemType) + { + this.n = new DynamicBackingItem(NodeId, ItemType); + } public DynamicNode(string NodeId) { int DynamicBackingItemId = 0; @@ -411,41 +414,99 @@ namespace umbraco.MacroEngines //contextAlias is the node which the property data was returned from Guid dataType = ContentType.GetDataType(data.ContextAlias, data.Alias); - + HttpContext.Current.Trace.Write(string.Format("RazorDynamicNode got datatype {0} for {1} on {2}", dataType, data.Alias, data.ContextAlias)); if (RazorDataTypeModelTypes == null) { - RazorDataTypeModelTypes = new Dictionary(); + HttpContext.Current.Trace.Write("RazorDataTypeModelTypes cache is empty, populating cache using TypeFinder..."); + try + { + RazorDataTypeModelTypes = new Dictionary(); - TypeFinder.FindClassesMarkedWithAttribute(typeof(RazorDataTypeModel)) - .ToList() - .FindAll(type => typeof(IRazorDataTypeModel).IsAssignableFrom(type)) - .ConvertAll(type => - { - RazorDataTypeModel RazorDataTypeModelAttribute = (RazorDataTypeModel)Attribute.GetCustomAttribute(type, typeof(RazorDataTypeModel)); - Guid g = RazorDataTypeModelAttribute.DataTypeEditorId; - return new KeyValuePair(g, type); - }) - .ForEach(item => - { - if (!RazorDataTypeModelTypes.ContainsKey(item.Key)) + TypeFinder.FindClassesMarkedWithAttribute(typeof(RazorDataTypeModel)) + .ToList() + .FindAll(type => typeof(IRazorDataTypeModel).IsAssignableFrom(type)) + .ConvertAll(type => { - RazorDataTypeModelTypes.Add(item.Key, item.Value); + RazorDataTypeModel RazorDataTypeModelAttribute = (RazorDataTypeModel)Attribute.GetCustomAttribute(type, typeof(RazorDataTypeModel)); + Guid g = RazorDataTypeModelAttribute.DataTypeEditorId; + return new KeyValuePair(g, type); + }) + .ForEach(item => + { + if (!RazorDataTypeModelTypes.ContainsKey(item.Key)) + { + RazorDataTypeModelTypes.Add(item.Key, item.Value); + } + }); + HttpContext.Current.Trace.Write(string.Format("{0} items added to cache...", RazorDataTypeModelTypes.Count)); + int i = 1; + foreach (KeyValuePair item in RazorDataTypeModelTypes) + { + HttpContext.Current.Trace.Write(string.Format("{0}/{1}: {2} => {3}", i, RazorDataTypeModelTypes.Count, item.Key, item.Value.FullName)); + i++; } - }); + } + catch (Exception ex) + { + HttpContext.Current.Trace.Warn("Exception occurred while populating cache, Will set RazorDataTypeModelTypes to null so that this error remains visible and you don't end up with an empty cache with silent failure."); + HttpContext.Current.Trace.Warn(string.Format("The exception was {0} and the message was {1}. {2}", ex.GetType().FullName, ex.Message, ex.StackTrace)); + RazorDataTypeModelTypes = null; + } } - if (RazorDataTypeModelTypes.ContainsKey(dataType)) + HttpContext.Current.Trace.Write(string.Format("Checking the RazorDataTypeModelTypes cache to see if the GUID {0} has a Model...", dataType)); + if (RazorDataTypeModelTypes != null && RazorDataTypeModelTypes.ContainsKey(dataType)) { Type dataTypeType = RazorDataTypeModelTypes[dataType]; + HttpContext.Current.Trace.Write(string.Format("Found dataType {0} for GUID {1}", dataTypeType.FullName, dataType)); IRazorDataTypeModel razorDataTypeModel = Activator.CreateInstance(dataTypeType, false) as IRazorDataTypeModel; + HttpContext.Current.Trace.Write(string.Format("Instantiating {0}...", dataTypeType.FullName)); if (razorDataTypeModel != null) { + HttpContext.Current.Trace.Write("Success"); object instance = null; + HttpContext.Current.Trace.Write("Calling Init on razorDataTypeModel"); if (razorDataTypeModel.Init(n.Id, data.Value, out instance)) { + if (instance != null) + { + HttpContext.Current.Trace.Write(string.Format("razorDataTypeModel successfully instantiated and returned a valid instance of type {0}", instance.GetType().FullName)); + } + else + { + HttpContext.Current.Trace.Warn("razorDataTypeModel successfully instantiated but returned null for instance"); + } result = instance; return true; } + else + { + if (instance != null) + { + HttpContext.Current.Trace.Write(string.Format("razorDataTypeModel returned false but returned a valid instance of type {0}", instance.GetType().FullName)); + } + else + { + HttpContext.Current.Trace.Warn("razorDataTypeModel successfully instantiated but returned null for instance"); + } + } } + else + { + HttpContext.Current.Trace.Write("Failed"); + HttpContext.Current.Trace.Warn(string.Format("DataTypeModel {0} failed to instantiate, perhaps it is lacking a parameterless constructor or doesn't implement IRazorDataTypeModel?", dataTypeType.FullName)); + } + } + else + { + if (RazorDataTypeModelTypes == null) + { + HttpContext.Current.Trace.Write(string.Format("RazorDataTypeModelTypes is null, probably an exception while building the cache, falling back to ConvertPropertyValueByDataType", dataType)); + } + else + { + HttpContext.Current.Trace.Write(string.Format("GUID {0} does not have a DataTypeModel, falling back to ConvertPropertyValueByDataType", dataType)); + } + } //convert the string value to a known type diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs index 4d73b67d3f..47f456ec45 100644 --- a/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs +++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicQueryable.cs @@ -10,6 +10,7 @@ using System.Reflection.Emit; using System.Threading; using System.Dynamic; using umbraco.MacroEngines; +using System.Diagnostics; namespace System.Linq.Dynamic { @@ -73,8 +74,9 @@ namespace System.Linq.Dynamic } return false; } - catch (Exception) + catch (Exception ex) { + Trace.WriteLine(ex.Message); return false; } }).AsQueryable(); @@ -1557,6 +1559,36 @@ namespace System.Linq.Dynamic LambdaExpression lax = Expression.Lambda>(block, instanceExpression); return lax; } + if (typeof(Func).IsAssignableFrom(type)) + { + //accessing a property off an already resolved DynamicNode TryGetMember call + //e.g. uBlogsyPostDate.Date + MethodInfo ReflectPropertyValue = this.GetType().GetMethod("ReflectPropertyValue", BindingFlags.NonPublic | BindingFlags.Static); + + ParameterExpression result = Expression.Parameter(typeof(object), "result"); + ParameterExpression idParam = Expression.Parameter(typeof(string), "id"); + ParameterExpression lambdaResult = Expression.Parameter(typeof(object), "lambdaResult"); + ParameterExpression lambdaInstanceExpression = Expression.Parameter(typeof(DynamicNode), "lambdaInstanceExpression"); + ParameterExpression instanceExpression = Expression.Parameter(typeof(Func), "instance"); + LabelTarget blockReturnLabel = Expression.Label(typeof(object)); + + BlockExpression block = Expression.Block( + typeof(object), + new[] { lambdaResult, result, idParam }, + Expression.Assign(lambdaResult, Expression.Invoke(instance, lambdaInstanceExpression)), + Expression.Assign(result, Expression.Call(ReflectPropertyValue, lambdaResult, Expression.Constant(id))), + Expression.IfThen( + Expression.TypeEqual(result, typeof(DynamicNull)), + Expression.Assign(result, + Expression.Constant(false, typeof(object)) + ) + ), + Expression.Return(blockReturnLabel, result), + Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object))) + ); + LambdaExpression lax = Expression.Lambda>(block, lambdaInstanceExpression); + return lax; + } } else { @@ -1569,7 +1601,16 @@ namespace System.Linq.Dynamic } } - + static object ReflectPropertyValue(object o, string name) + { + PropertyInfo propertyInfo = o.GetType().GetProperty(name); + if (propertyInfo != null) + { + object result = propertyInfo.GetValue(o, null); + return result; + } + return null; + } private static Expression CallMethodOnDynamicNode(Expression instance, Expression[] args, LambdaExpression instanceAsString, ParameterExpression instanceExpression, MethodInfo method, bool isStatic) { ConstantExpression defaultReturnValue = Expression.Constant(null, typeof(object)); diff --git a/umbraco.MacroEngines.Juno/RazorDynamicNode/RazorLibraryCore.cs b/umbraco.MacroEngines.Juno/RazorDynamicNode/RazorLibraryCore.cs index 8c3624c051..c5b6e2c9f3 100644 --- a/umbraco.MacroEngines.Juno/RazorDynamicNode/RazorLibraryCore.cs +++ b/umbraco.MacroEngines.Juno/RazorDynamicNode/RazorLibraryCore.cs @@ -52,6 +52,13 @@ namespace umbraco.MacroEngines.Library nodes.Add(new DynamicNode(eachId)); return new DynamicNodeList(nodes); } + public dynamic NodesById(List Ids, DynamicBackingItemType ItemType) + { + List nodes = new List(); + foreach (int eachId in Ids) + nodes.Add(new DynamicNode(eachId, ItemType)); + return new DynamicNodeList(nodes); + } public dynamic NodesById(params object[] Ids) { return NodesById(Ids.ToList()); @@ -397,7 +404,7 @@ namespace umbraco.MacroEngines.Library insideTagSpaceEncountered = true; //if (!isTagClose) //{ - // tagStack.Push(currentTag); + // tagStack.Push(currentTag); //} } } @@ -453,22 +460,52 @@ namespace umbraco.MacroEngines.Library } - public string StripHtml(IHtmlString html) + public HtmlString StripHtml(IHtmlString html) { - return StripHtml(html.ToHtmlString()); + return StripHtml(html.ToHtmlString(), (List)null); } - public string StripHtml(DynamicNull html) + public HtmlString StripHtml(DynamicNull html) { - return string.Empty; + return new HtmlString(string.Empty); } - public string StripHtml(string html) + public HtmlString StripHtml(string html) { - return StripHtmlTags(html); + return StripHtmlTags(html, (List)null); + } + + public HtmlString StripHtml(IHtmlString html, List tags) + { + return StripHtml(html.ToHtmlString(), tags); + } + public HtmlString StripHtml(DynamicNull html, List tags) + { + return new HtmlString(string.Empty); + } + public HtmlString StripHtml(string html, List tags) + { + return StripHtmlTags(html, tags); + } + + public HtmlString StripHtml(IHtmlString html, params string[] tags) + { + return StripHtml(html.ToHtmlString(), tags.ToList()); + } + public HtmlString StripHtml(DynamicNull html, params string[] tags) + { + return new HtmlString(string.Empty); + } + public HtmlString StripHtml(string html, params string[] tags) + { + return StripHtmlTags(html, tags.ToList()); } //ge: this method won't deal with