();
}
@@ -41,7 +41,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
CodeGenerator = input.CodeGenerator
});
- var activeTagHelpers = _tagStack.Count;
+ var activeTagHelpers = _trackerStack.Count;
foreach (var child in input.Children)
{
@@ -76,14 +76,14 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
// We captured the number of active tag helpers at the start of our logic, it should be the same. If not
// it means that there are malformed tag helpers at the top of our stack.
- if (activeTagHelpers != _tagStack.Count)
+ if (activeTagHelpers != _trackerStack.Count)
{
// Malformed tag helpers built here will be tag helpers that do not have end tags in the current block
// scope. Block scopes are special cases in Razor such as @ would cause an error because there's no
// matching end
tag in the template block scope and therefore doesn't make sense as a tag helper.
- BuildMalformedTagHelpers(_tagStack.Count - activeTagHelpers, context);
+ BuildMalformedTagHelpers(_trackerStack.Count - activeTagHelpers, context);
- Debug.Assert(activeTagHelpers == _tagStack.Count);
+ Debug.Assert(activeTagHelpers == _trackerStack.Count);
}
BuildCurrentlyTrackedBlock();
@@ -91,8 +91,6 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
private bool TryRewriteTagHelper(Block tagBlock, RewritingContext context)
{
- // TODO: Fully handle malformed tags: https://github.com/aspnet/Razor/issues/104
-
// Get tag name of the current block (doesn't matter if it's an end or start tag)
var tagName = GetTagName(tagBlock);
@@ -104,22 +102,39 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
var descriptors = Enumerable.Empty();
- if (IsPotentialTagHelper(tagName, tagBlock))
- {
- descriptors = _provider.GetTagHelpers(tagName);
- }
-
- // If there aren't any TagHelperDescriptors registered then we aren't a TagHelper
- if (!descriptors.Any())
+ if (!IsPotentialTagHelper(tagName, tagBlock))
{
return false;
}
+ var tracker = _trackerStack.Count > 0 ? _trackerStack.Peek() : null;
+ var tagNameScope = tracker?.Builder.TagName ?? string.Empty;
+
if (!IsEndTag(tagBlock))
{
- // We're in a begin tag helper block
+ // We're now in a start tag block, we first need to see if the tag block is a tag helper.
+ var providedAttributes = GetAttributeNames(tagBlock);
- var validTagStructure = ValidTagStructure(tagName, tagBlock, context);
+ descriptors = _provider.GetDescriptors(tagName, providedAttributes);
+
+ // If there aren't any TagHelperDescriptors registered then we aren't a TagHelper
+ if (!descriptors.Any())
+ {
+ // If the current tag matches the current TagHelper scope it means the parent TagHelper matched
+ // all the required attributes but the current one did not; therefore, we need to increment the
+ // OpenMatchingTags counter for current the TagHelperBlock so we don't end it too early.
+ // ex: We don't want the first myth to close on the inside
+ // tag.
+ if (string.Equals(tagNameScope, tagName, StringComparison.OrdinalIgnoreCase))
+ {
+ tracker.OpenMatchingTags++;
+ }
+
+ return false;
+ }
+
+ // We're in a start TagHelper block.
+ var validTagStructure = ValidateTagStructure(tagName, tagBlock, context);
var builder = TagHelperBlockRewriter.Rewrite(
tagName,
@@ -144,32 +159,43 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
}
else
{
- // We're in an end tag helper block.
-
- var tagNameScope = _tagStack.Count > 0 ? _tagStack.Peek().TagName : string.Empty;
-
- // Validate that our end tag helper matches the currently scoped tag helper, if not we
- // need to error.
+ // Validate that our end tag matches the currently scoped tag, if not we may need to error.
if (tagNameScope.Equals(tagName, StringComparison.OrdinalIgnoreCase))
{
- ValidTagStructure(tagName, tagBlock, context);
+ // If there are additional end tags required before we can build our block it means we're in a
+ // situation like this: where we're at the inside