private string CleanAttributeValue(MarkupParsingContext context, HtmlTag tag, HtmlAttribute attribute)
{
string attributeValue = attribute.Value;
if (attributeValue.Length == 0)
{
return attributeValue;
}
string processedAttributeValue = attributeValue;
string tagNameInLowercase = tag.NameInLowercase;
IList<HtmlAttribute> attributes = tag.Attributes;
string attributeNameInLowercase = attribute.NameInLowercase;
HtmlAttributeType attributeType = attribute.Type;
switch (attributeType)
{
case HtmlAttributeType.Uri:
processedAttributeValue = processedAttributeValue.Trim();
if (processedAttributeValue.StartsWith(HTTP_PROTOCOL, StringComparison.OrdinalIgnoreCase))
{
if (_settings.RemoveHttpProtocolFromAttributes && !ContainsRelExternalAttribute(attributes))
{
int httpProtocolLength = HTTP_PROTOCOL.Length;
processedAttributeValue = processedAttributeValue.Substring(httpProtocolLength);
}
}
else if (processedAttributeValue.StartsWith(HTTPS_PROTOCOL, StringComparison.OrdinalIgnoreCase))
{
if (_settings.RemoveHttpsProtocolFromAttributes && !ContainsRelExternalAttribute(attributes))
{
int httpsProtocolLength = HTTPS_PROTOCOL.Length;
processedAttributeValue = processedAttributeValue.Substring(httpsProtocolLength);
}
}
else if (attributeNameInLowercase == "href"
&& processedAttributeValue.StartsWith(JS_PROTOCOL, StringComparison.OrdinalIgnoreCase))
{
processedAttributeValue = ProcessInlineScriptContent(context, attribute);
}
break;
case HtmlAttributeType.Numeric:
processedAttributeValue = processedAttributeValue.Trim();
break;
case HtmlAttributeType.ClassName:
if (AngularHelpers.IsClassDirective(processedAttributeValue))
{
// Processing of Angular class directives
string ngOriginalDirectiveName = string.Empty;
string ngNormalizedDirectiveName = string.Empty;
string ngExpression;
var ngDirectives = new Dictionary<string, string>();
AngularHelpers.ParseClassDirective(processedAttributeValue,
(localContext, originalDirectiveName, normalizedDirectiveName) =>
{
ngOriginalDirectiveName = originalDirectiveName;
ngNormalizedDirectiveName = normalizedDirectiveName;
ngExpression = null;
ngDirectives.Add(ngOriginalDirectiveName, ngExpression);
},
(localContext, expression) =>
{
ngExpression = expression;
if (_settings.MinifyAngularBindingExpressions
&& ContainsAngularBindingExpression(ngNormalizedDirectiveName))
{
ngExpression = MinifyAngularBindingExpression(context,
attribute.ValueCoordinates, localContext.NodeCoordinates,
expression);
}
ngDirectives[ngOriginalDirectiveName] = ngExpression;
},
localContext =>
{
if (ngDirectives[ngOriginalDirectiveName] == null)
{
ngDirectives[ngOriginalDirectiveName] = string.Empty;
}
}
);
int directiveCount = ngDirectives.Count;
if (directiveCount > 0)
{
StringBuilder directiveBuilder = StringBuilderPool.GetBuilder();
int directiveIndex = 0;
int lastDirectiveIndex = directiveCount - 1;
string previousExpression = null;
foreach (var directive in ngDirectives)
{
string directiveName = directive.Key;
string expression = directive.Value;
if (directiveIndex > 0 && (expression == null || previousExpression == null))
{
directiveBuilder.Append(" ");
}
directiveBuilder.Append(directiveName);
if (!string.IsNullOrWhiteSpace(expression))
{
directiveBuilder.AppendFormat(":{0}", expression);
}
if (directiveIndex < lastDirectiveIndex && expression != null)
{
directiveBuilder.Append(";");
}
previousExpression = expression;
directiveIndex++;
}
processedAttributeValue = directiveBuilder.ToString();
StringBuilderPool.ReleaseBuilder(directiveBuilder);
}
else
{
processedAttributeValue = string.Empty;
}
}
else
{
processedAttributeValue = processedAttributeValue.Trim();
processedAttributeValue = Utils.CollapseWhitespace(processedAttributeValue);
}
break;
case HtmlAttributeType.Style:
processedAttributeValue = ProcessInlineStyleContent(context, attribute);
break;
case HtmlAttributeType.Event:
processedAttributeValue = ProcessInlineScriptContent(context, attribute);
break;
default:
if (attributeNameInLowercase == "data-bind" && _settings.MinifyKnockoutBindingExpressions)
{
processedAttributeValue = MinifyKnockoutBindingExpression(context, attribute);
}
else if (tagNameInLowercase == "meta" && attributeNameInLowercase == "content"
&& attributes.Any(a => a.NameInLowercase == "name" && a.Value.Trim().IgnoreCaseEquals("keywords")))
{
processedAttributeValue = processedAttributeValue.Trim();
processedAttributeValue = Utils.CollapseWhitespace(processedAttributeValue);
processedAttributeValue = _separatingCommaWithSpacesRegex.Replace(processedAttributeValue, ",");
processedAttributeValue = _endingCommaWithSpacesRegex.Replace(processedAttributeValue, string.Empty);
}
else
{
if (_settings.MinifyAngularBindingExpressions
&& CanMinifyAngularBindingExpressionInAttribute(tag, attribute))
{
processedAttributeValue = MinifyAngularBindingExpression(context, attribute.ValueCoordinates,
processedAttributeValue);
}
}
break;
}
return processedAttributeValue;
}