Fix empty attribute projections for TagHelpers.
- Added TagHelperParseTreeRewriter tests, attempted to cover all empty attribute edge cases. - Added Codegen tests to validate output and DesignTimeLineMappings. #271
This commit is contained in:
parent
efab52c082
commit
7afd78b36a
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNet.Razor.Generator;
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
|
|
@ -90,10 +91,15 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
EditHandler = span.EditHandler,
|
EditHandler = span.EditHandler,
|
||||||
Kind = span.Kind
|
Kind = span.Kind
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Will contain symbols that represent a single attribute value: <input| class="btn"| />
|
||||||
var htmlSymbols = span.Symbols.OfType<HtmlSymbol>().ToArray();
|
var htmlSymbols = span.Symbols.OfType<HtmlSymbol>().ToArray();
|
||||||
var capturedAttributeValueStart = false;
|
var capturedAttributeValueStart = false;
|
||||||
var attributeValueStartLocation = span.Start;
|
var attributeValueStartLocation = span.Start;
|
||||||
var symbolOffset = 1;
|
|
||||||
|
// The symbolOffset is initialized to 0 to expect worst case: "class=". If a quote is found later on for
|
||||||
|
// the attribute value the symbolOffset is adjusted accordingly.
|
||||||
|
var symbolOffset = 0;
|
||||||
string name = null;
|
string name = null;
|
||||||
|
|
||||||
// Iterate down through the symbols to find the name and the start of the value.
|
// Iterate down through the symbols to find the name and the start of the value.
|
||||||
|
|
@ -104,6 +110,11 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
|
|
||||||
if (afterEquals)
|
if (afterEquals)
|
||||||
{
|
{
|
||||||
|
// We've captured all leading whitespace, the attribute name, and an equals with an optional
|
||||||
|
// quote/double quote. We're now at: " asp-for='|...'" or " asp-for=|..."
|
||||||
|
// The goal here is to capture all symbols until the end of the attribute. Note this will not
|
||||||
|
// consume an ending quote due to the symbolOffset.
|
||||||
|
|
||||||
// When symbols are accepted into SpanBuilders, their locations get altered to be offset by the
|
// When symbols are accepted into SpanBuilders, their locations get altered to be offset by the
|
||||||
// parent which is why we need to mark our start location prior to adding the symbol.
|
// parent which is why we need to mark our start location prior to adding the symbol.
|
||||||
// This is needed to know the location of the attribute value start within the document.
|
// This is needed to know the location of the attribute value start within the document.
|
||||||
|
|
@ -118,13 +129,24 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
}
|
}
|
||||||
else if (name == null && symbol.Type == HtmlSymbolType.Text)
|
else if (name == null && symbol.Type == HtmlSymbolType.Text)
|
||||||
{
|
{
|
||||||
|
// We've captured all leading whitespace prior to the attribute name.
|
||||||
|
// We're now at: " |asp-for='...'" or " |asp-for=..."
|
||||||
|
// The goal here is to capture the attribute name.
|
||||||
|
|
||||||
name = symbol.Content;
|
name = symbol.Content;
|
||||||
attributeValueStartLocation = SourceLocation.Advance(span.Start, name);
|
attributeValueStartLocation = SourceLocation.Advance(attributeValueStartLocation, name);
|
||||||
}
|
}
|
||||||
else if (symbol.Type == HtmlSymbolType.Equals)
|
else if (symbol.Type == HtmlSymbolType.Equals)
|
||||||
{
|
{
|
||||||
// We've found an '=' symbol, this means that the coming symbols will either be a quote
|
Debug.Assert(
|
||||||
// or value (in the case that the value is unquoted).
|
name != null,
|
||||||
|
"Name should never be null here. The parser should guaruntee an attribute has a name.");
|
||||||
|
|
||||||
|
// We've captured all leading whitespace and the attribute name.
|
||||||
|
// We're now at: " asp-for|='...'" or " asp-for|=..."
|
||||||
|
// The goal here is to consume the equal sign and the optional single/double-quote.
|
||||||
|
|
||||||
|
// The coming symbols will either be a quote or value (in the case that the value is unquoted).
|
||||||
// Spaces after/before the equal symbol are not yet supported:
|
// Spaces after/before the equal symbol are not yet supported:
|
||||||
// https://github.com/aspnet/Razor/issues/123
|
// https://github.com/aspnet/Razor/issues/123
|
||||||
|
|
||||||
|
|
@ -134,27 +156,38 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
SourceLocation symbolStartLocation;
|
SourceLocation symbolStartLocation;
|
||||||
|
|
||||||
// Check for attribute start values, aka single or double quote
|
// Check for attribute start values, aka single or double quote
|
||||||
if (IsQuote(htmlSymbols[i + 1]))
|
if ((i + 1) < htmlSymbols.Length && IsQuote(htmlSymbols[i + 1]))
|
||||||
{
|
{
|
||||||
// Move past the attribute start so we can accept the true value.
|
// Move past the attribute start so we can accept the true value.
|
||||||
i++;
|
i++;
|
||||||
symbolStartLocation = htmlSymbols[i + 1].Start;
|
symbolStartLocation = htmlSymbols[i].Start;
|
||||||
|
|
||||||
|
// If there's a start quote then there must be an end quote to be valid, skip it.
|
||||||
|
symbolOffset = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
symbolStartLocation = symbol.Start;
|
symbolStartLocation = symbol.Start;
|
||||||
|
|
||||||
// Set the symbol offset to 0 so we don't attempt to skip an end quote that doesn't exist.
|
|
||||||
symbolOffset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attributeValueStartLocation = symbolStartLocation +
|
attributeValueStartLocation =
|
||||||
span.Start +
|
span.Start +
|
||||||
new SourceLocation(absoluteIndex: 1,
|
symbolStartLocation +
|
||||||
lineIndex: 0,
|
new SourceLocation(absoluteIndex: 1, lineIndex: 0, characterIndex: 1);
|
||||||
characterIndex: 1);
|
|
||||||
afterEquals = true;
|
afterEquals = true;
|
||||||
}
|
}
|
||||||
|
else if (symbol.Type == HtmlSymbolType.WhiteSpace)
|
||||||
|
{
|
||||||
|
// We're at the start of the attribute, this branch may be hit on the first iterations of
|
||||||
|
// the loop since the parser separates attributes with their spaces included as symbols.
|
||||||
|
// We're at: "| asp-for='...'" or "| asp-for=..."
|
||||||
|
// Note: This will not be hit even for situations like asp-for ="..." because the core Razor
|
||||||
|
// parser currently does not know how to handle attributes in that format. This will be addressed
|
||||||
|
// by https://github.com/aspnet/Razor/issues/123.
|
||||||
|
|
||||||
|
attributeValueStartLocation = SourceLocation.Advance(attributeValueStartLocation, symbol.Content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// After all symbols have been added we need to set the builders start position so we do not indirectly
|
// After all symbols have been added we need to set the builders start position so we do not indirectly
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,41 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
BuildLineMapping(1094, 30, 18, 5179, 187, 19, 29),
|
BuildLineMapping(1094, 30, 18, 5179, 187, 19, 29),
|
||||||
BuildLineMapping(1231, 34, 5279, 192, 0, 1),
|
BuildLineMapping(1231, 34, 5279, 192, 0, 1),
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"EmptyAttributeTagHelpers",
|
||||||
|
"EmptyAttributeTagHelpers.DesignTime",
|
||||||
|
PAndInputTagHelperDescriptors,
|
||||||
|
new List<LineMapping>
|
||||||
|
{
|
||||||
|
BuildLineMapping(documentAbsoluteIndex: 14,
|
||||||
|
documentLineIndex: 0,
|
||||||
|
generatedAbsoluteIndex: 493,
|
||||||
|
generatedLineIndex: 15,
|
||||||
|
characterOffsetIndex: 14,
|
||||||
|
contentLength: 11),
|
||||||
|
BuildLineMapping(documentAbsoluteIndex: 62,
|
||||||
|
documentLineIndex: 3,
|
||||||
|
documentCharacterOffsetIndex: 26,
|
||||||
|
generatedAbsoluteIndex: 1289,
|
||||||
|
generatedLineIndex: 39,
|
||||||
|
generatedCharacterOffsetIndex: 28,
|
||||||
|
contentLength: 0),
|
||||||
|
BuildLineMapping(documentAbsoluteIndex: 122,
|
||||||
|
documentLineIndex: 5,
|
||||||
|
generatedAbsoluteIndex: 1634,
|
||||||
|
generatedLineIndex: 48,
|
||||||
|
characterOffsetIndex: 30,
|
||||||
|
contentLength: 0),
|
||||||
|
BuildLineMapping(documentAbsoluteIndex: 88,
|
||||||
|
documentLineIndex: 4,
|
||||||
|
documentCharacterOffsetIndex: 12,
|
||||||
|
generatedAbsoluteIndex: 1789,
|
||||||
|
generatedLineIndex: 54,
|
||||||
|
generatedCharacterOffsetIndex: 19,
|
||||||
|
contentLength: 0)
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -245,6 +279,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
{ "BasicTagHelpers", PAndInputTagHelperDescriptors },
|
{ "BasicTagHelpers", PAndInputTagHelperDescriptors },
|
||||||
{ "BasicTagHelpers.RemoveTagHelper", PAndInputTagHelperDescriptors },
|
{ "BasicTagHelpers.RemoveTagHelper", PAndInputTagHelperDescriptors },
|
||||||
{ "ComplexTagHelpers", PAndInputTagHelperDescriptors },
|
{ "ComplexTagHelpers", PAndInputTagHelperDescriptors },
|
||||||
|
{ "EmptyAttributeTagHelpers", PAndInputTagHelperDescriptors },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,77 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
{
|
{
|
||||||
public class TagHelperParseTreeRewriterTest : CsHtmlMarkupParserTestBase
|
public class TagHelperParseTreeRewriterTest : CsHtmlMarkupParserTestBase
|
||||||
{
|
{
|
||||||
|
public static TheoryData EmptyAttributeTagHelperData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var factory = CreateDefaultSpanFactory();
|
||||||
|
|
||||||
|
// documentContent, expectedOutput
|
||||||
|
return new TheoryData<string, MarkupBlock>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"<p class=\"\"></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "class", new MarkupBlock() }
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class=''></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "class", new MarkupBlock() }
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class=></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
// We expected a markup node here because attribute values without quotes can only ever
|
||||||
|
// be a single item, hence don't need to be enclosed by a block.
|
||||||
|
{ "class", factory.Markup("").With(SpanCodeGenerator.Null) },
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class1='' class2= class3=\"\" />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "class1", new MarkupBlock() },
|
||||||
|
{ "class2", factory.Markup("").With(SpanCodeGenerator.Null) },
|
||||||
|
{ "class3", new MarkupBlock() },
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class1=''class2=\"\"class3= />",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "class1", new MarkupBlock() },
|
||||||
|
{ "class2", new MarkupBlock() },
|
||||||
|
{ "class3", factory.Markup("").With(SpanCodeGenerator.Null) },
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(EmptyAttributeTagHelperData))]
|
||||||
|
public void Rewrite_UnderstandsEmptyAttributeTagHelpers(string documentContent, MarkupBlock expectedOutput)
|
||||||
|
{
|
||||||
|
RunParseTreeRewriterTest(documentContent, expectedOutput, new RazorError[0], "p");
|
||||||
|
}
|
||||||
|
|
||||||
public static TheoryData<string, MarkupBlock, RazorError[]> MalformedTagHelperAttributeBlockData
|
public static TheoryData<string, MarkupBlock, RazorError[]> MalformedTagHelperAttributeBlockData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
namespace TestOutput
|
||||||
|
{
|
||||||
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class EmptyAttributeTagHelpers
|
||||||
|
{
|
||||||
|
private static object @__o;
|
||||||
|
private void @__RazorDesignTimeHelpers__()
|
||||||
|
{
|
||||||
|
#pragma warning disable 219
|
||||||
|
string __tagHelperDirectiveSyntaxHelper = null;
|
||||||
|
__tagHelperDirectiveSyntaxHelper =
|
||||||
|
#line 1 "EmptyAttributeTagHelpers.cshtml"
|
||||||
|
"something"
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
;
|
||||||
|
#pragma warning restore 219
|
||||||
|
}
|
||||||
|
#line hidden
|
||||||
|
private InputTagHelper __InputTagHelper = null;
|
||||||
|
private InputTagHelper2 __InputTagHelper2 = null;
|
||||||
|
private PTagHelper __PTagHelper = null;
|
||||||
|
#line hidden
|
||||||
|
public EmptyAttributeTagHelpers()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable 1998
|
||||||
|
public override async Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__InputTagHelper.Type = "";
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
|
#line 4 "EmptyAttributeTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = ;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__InputTagHelper.Type = "";
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
|
#line 6 "EmptyAttributeTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = ;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
#line 5 "EmptyAttributeTagHelpers.cshtml"
|
||||||
|
__PTagHelper.Age = ;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
}
|
||||||
|
#pragma warning restore 1998
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
#pragma checksum "EmptyAttributeTagHelpers.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "828f744feb52d497814b7a018f817f31d92085ce"
|
||||||
|
namespace TestOutput
|
||||||
|
{
|
||||||
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class EmptyAttributeTagHelpers
|
||||||
|
{
|
||||||
|
#line hidden
|
||||||
|
#pragma warning disable 0414
|
||||||
|
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||||
|
#pragma warning restore 0414
|
||||||
|
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||||
|
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||||
|
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||||
|
private InputTagHelper __InputTagHelper = null;
|
||||||
|
private InputTagHelper2 __InputTagHelper2 = null;
|
||||||
|
private PTagHelper __PTagHelper = null;
|
||||||
|
#line hidden
|
||||||
|
public EmptyAttributeTagHelpers()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable 1998
|
||||||
|
public override async Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
Instrumentation.BeginContext(27, 13, true);
|
||||||
|
WriteLiteral("\r\n<div>\r\n ");
|
||||||
|
Instrumentation.EndContext();
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper.Type = "";
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
|
#line 4 "EmptyAttributeTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = ;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
||||||
|
__tagHelperExecutionContext.AddHtmlAttribute("class", "");
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
Instrumentation.BeginContext(74, 6, true);
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
Instrumentation.EndContext();
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper.Type = "";
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
|
#line 6 "EmptyAttributeTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = ;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
||||||
|
__tagHelperExecutionContext.AddHtmlAttribute("class", "");
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
|
#line 5 "EmptyAttributeTagHelpers.cshtml"
|
||||||
|
__PTagHelper.Age = ;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
Instrumentation.BeginContext(144, 8, true);
|
||||||
|
WriteLiteral("\r\n</div>");
|
||||||
|
Instrumentation.EndContext();
|
||||||
|
}
|
||||||
|
#pragma warning restore 1998
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
@addtaghelper "something"
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<input type= checked=""class="" />
|
||||||
|
<p age=''>
|
||||||
|
<input type=""checked= class="" />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
Loading…
Reference in New Issue