private void StartTagHandler(MarkupParsingContext context, HtmlTag tag)
{
HtmlNodeType previousNodeType = _currentNodeType;
HtmlTag previousTag = _currentTag ?? HtmlTag.Empty;
if (_settings.UseMetaCharsetTag && IsMetaContentTypeTag(tag))
{
tag = UpgradeToMetaCharsetTag(tag);
}
string tagName = tag.Name;
string tagNameInLowercase = tag.NameInLowercase;
HtmlTagFlags tagFlags = tag.Flags;
IList<HtmlAttribute> attributes = tag.Attributes;
_currentNodeType = HtmlNodeType.StartTag;
_currentTag = tag;
_currentText = string.Empty;
// Set whitespace flags for nested tags (for example <span> within a <pre>)
WhitespaceMinificationMode whitespaceMinificationMode = _settings.WhitespaceMinificationMode;
if (whitespaceMinificationMode != WhitespaceMinificationMode.None)
{
if (_tagsWithNotRemovableWhitespaceQueue.Count == 0)
{
// Processing of whitespace, that followed before the start tag
bool allowTrimEnd = false;
if (tagFlags.HasFlag(HtmlTagFlags.Invisible)
|| (tagFlags.HasFlag(HtmlTagFlags.NonIndependent)
&& CanRemoveWhitespaceBetweenNonIndependentTags(previousTag, tag)))
{
allowTrimEnd = true;
}
else
{
if (whitespaceMinificationMode == WhitespaceMinificationMode.Medium
|| whitespaceMinificationMode == WhitespaceMinificationMode.Aggressive)
{
allowTrimEnd = tagFlags.HasFlag(HtmlTagFlags.Block);
}
}
if (allowTrimEnd)
{
TrimEndLastBufferItem();
}
}
if (!CanMinifyWhitespace(tag))
{
_tagsWithNotRemovableWhitespaceQueue.Enqueue(tagNameInLowercase);
}
}
if (previousNodeType != HtmlNodeType.StartTag)
{
if (_settings.RemoveOptionalEndTags
&& previousTag.Flags.HasFlag(HtmlTagFlags.Optional)
&& CanRemoveOptionalEndTagByNextTag(previousTag, tag))
{
RemoveLastEndTagFromBuffer(previousTag);
}
FlushBuffer();
}
_buffer.Add("<");
_buffer.Add(CanPreserveCase() ? tagName : tagNameInLowercase);
int attributeCount = attributes.Count;
bool unsafeLastAttribute = false;
if (attributeCount > 0)
{
for (int attributeIndex = 0; attributeIndex < attributeCount; attributeIndex++)
{
HtmlAttributeViewModel attributeViewModel = BuildAttributeViewModel(context, tag, attributes[attributeIndex]);
if (!attributeViewModel.IsEmpty)
{
_buffer.Add(" ");
_buffer.Add(attributeViewModel.Name);
if (attributeViewModel.HasValue)
{
_buffer.Add("=");
if (attributeViewModel.HasQuotes)
{
_buffer.Add("\"");
}
_buffer.Add(attributeViewModel.Value);
if (attributeViewModel.HasQuotes)
{
_buffer.Add("\"");
}
}
unsafeLastAttribute = attributeViewModel.HasValue && !attributeViewModel.HasQuotes;
}
}
}
if (tagFlags.HasFlag(HtmlTagFlags.Empty))
{
HtmlEmptyTagRenderMode emptyTagRenderMode = _settings.EmptyTagRenderMode;
if (emptyTagRenderMode == HtmlEmptyTagRenderMode.NoSlash && tagFlags.HasFlag(HtmlTagFlags.Xml))
{
emptyTagRenderMode = HtmlEmptyTagRenderMode.SpaceAndSlash;
}
if (emptyTagRenderMode == HtmlEmptyTagRenderMode.Slash && unsafeLastAttribute)
{
emptyTagRenderMode = HtmlEmptyTagRenderMode.SpaceAndSlash;
}
if (emptyTagRenderMode == HtmlEmptyTagRenderMode.Slash)
{
_buffer.Add("/");
}
else if (emptyTagRenderMode == HtmlEmptyTagRenderMode.SpaceAndSlash)
{
_buffer.Add(" /");
}
}
_buffer.Add(">");
}