private HtmlAttributeViewModel BuildAttributeViewModel(MarkupParsingContext context, HtmlTag tag, HtmlAttribute attribute)
{
string tagNameInLowercase = tag.NameInLowercase;
HtmlAttributeViewModel attributeViewModel;
string attributeName = attribute.Name;
string attributeNameInLowercase = attribute.NameInLowercase;
string attributeValue = attribute.Value;
bool attributeHasValue = attribute.HasValue;
bool attributeHasEmptyValue = !attributeHasValue || attributeValue.Length == 0;
HtmlAttributeType attributeType = attribute.Type;
bool useHtmlSyntax = !_settings.UseXhtmlSyntax;
if (useHtmlSyntax && attributeType == HtmlAttributeType.Xml && attributeNameInLowercase != "xmlns")
{
string sourceCode = context.SourceCode;
SourceCodeNodeCoordinates attributeCoordinates = attribute.NameCoordinates;
WriteWarning(LogCategoryConstants.HtmlMinificationWarning,
string.Format(Strings.WarningMessage_XmlBasedAttributeNotAllowed, attributeName), _fileContext,
attributeCoordinates.LineNumber, attributeCoordinates.ColumnNumber,
SourceCodeNavigator.GetSourceFragment(sourceCode, attributeCoordinates));
}
if ((_settings.RemoveRedundantAttributes && IsAttributeRedundant(tag, attribute))
|| (_settings.RemoveJsTypeAttributes && IsJavaScriptTypeAttribute(tag, attribute))
|| (_settings.RemoveCssTypeAttributes && IsCssTypeAttribute(tag, attribute))
|| (useHtmlSyntax && CanRemoveXmlNamespaceAttribute(tag, attribute)))
{
if (CanRemoveAttribute(tag, attribute))
{
attributeViewModel = HtmlAttributeViewModel.Empty;
return attributeViewModel;
}
}
bool isCustomBooleanAttribute = !attributeHasValue && attributeType == HtmlAttributeType.Text;
if (isCustomBooleanAttribute)
{
if (useHtmlSyntax)
{
attributeViewModel = InnerBuildAttributeViewModel(attribute, true, false);
return attributeViewModel;
}
attribute.Value = string.Empty;
}
else if (attributeType != HtmlAttributeType.Event
&& !attributeHasEmptyValue
&& TemplateTagHelpers.ContainsTag(attributeValue))
{
// Processing of template tags
StringBuilder attributeValueBuilder = StringBuilderPool.GetBuilder();
TemplateTagHelpers.ParseMarkup(attributeValue,
(localContext, expression, startDelimiter, endDelimiter) =>
{
string processedExpression = expression;
if (_settings.MinifyAngularBindingExpressions && startDelimiter == "{{" && endDelimiter == "}}")
{
processedExpression = MinifyAngularBindingExpression(context, attribute.ValueCoordinates,
localContext.NodeCoordinates, expression);
}
attributeValueBuilder.Append(startDelimiter);
attributeValueBuilder.Append(processedExpression);
attributeValueBuilder.Append(endDelimiter);
},
(localContext, textValue) =>
{
string processedTextValue = textValue;
if (attributeType == HtmlAttributeType.ClassName)
{
processedTextValue = Utils.CollapseWhitespace(textValue);
}
attributeValueBuilder.Append(processedTextValue);
}
);
string processedAttributeValue = attributeValueBuilder.ToString();
StringBuilderPool.ReleaseBuilder(attributeValueBuilder);
switch (attributeType)
{
case HtmlAttributeType.Uri:
case HtmlAttributeType.Numeric:
case HtmlAttributeType.ClassName:
processedAttributeValue = processedAttributeValue.Trim();
break;
case HtmlAttributeType.Style:
processedAttributeValue = processedAttributeValue.Trim();
processedAttributeValue = Utils.RemoveEndingSemicolon(processedAttributeValue);
break;
default:
if (_settings.MinifyAngularBindingExpressions && tag.Flags.HasFlag(HtmlTagFlags.Custom))
{
string elementDirectiveName = AngularHelpers.NormalizeDirectiveName(tagNameInLowercase);
if (elementDirectiveName == "ngPluralize" && attributeNameInLowercase == "when")
{
processedAttributeValue = MinifyAngularBindingExpression(context, attribute.ValueCoordinates,
processedAttributeValue);
}
}
break;
}
attribute.Value = processedAttributeValue;
}
else if (attributeType == HtmlAttributeType.Boolean)
{
if (_settings.CollapseBooleanAttributes)
{
attributeViewModel = InnerBuildAttributeViewModel(attribute, true, false);
return attributeViewModel;
}
attribute.Value = attributeName;
}
else
{
if (!attributeHasEmptyValue)
{
attribute.Value = CleanAttributeValue(context, tag, attribute);
}
if (_settings.RemoveEmptyAttributes && CanRemoveEmptyAttribute(tag, attribute))
{
if (CanRemoveAttribute(tag, attribute))
{
attributeViewModel = HtmlAttributeViewModel.Empty;
return attributeViewModel;
}
}
}
bool addQuotes = !CanRemoveAttributeQuotes(attribute, _settings.AttributeQuotesRemovalMode);
attributeViewModel = InnerBuildAttributeViewModel(attribute, false, addQuotes);
return attributeViewModel;
}