Parse the whitespace surrounding equals in attribute correctly

- #123
 - Handled the corresponding cases in tag helper scenarios
 - Added unit and code generation tests
This commit is contained in:
Ajay Bhargav Baaskaran 2015-08-28 17:26:35 -07:00
parent 6568de38d1
commit 08c8f9f7ba
8 changed files with 339 additions and 66 deletions

View File

@ -463,6 +463,7 @@ namespace Microsoft.AspNet.Razor.Parser
// http://dev.w3.org/html5/spec/tokenization.html#attribute-name-state
// Read the 'name' (i.e. read until the '=' or whitespace/newline)
var name = Enumerable.Empty<HtmlSymbol>();
var whitespaceAfterAttributeName = Enumerable.Empty<HtmlSymbol>();
if (At(HtmlSymbolType.Text))
{
name = ReadWhile(sym =>
@ -472,6 +473,10 @@ namespace Microsoft.AspNet.Razor.Parser
sym.Type != HtmlSymbolType.CloseAngle &&
sym.Type != HtmlSymbolType.OpenAngle &&
(sym.Type != HtmlSymbolType.ForwardSlash || !NextIs(HtmlSymbolType.CloseAngle)));
// capture whitespace after attribute name (if any)
whitespaceAfterAttributeName = ReadWhile(
sym => sym.Type == HtmlSymbolType.WhiteSpace || sym.Type == HtmlSymbolType.NewLine);
}
else
{
@ -485,6 +490,10 @@ namespace Microsoft.AspNet.Razor.Parser
{
// Minimized attribute
// We are at the prefix of the next attribute or the end of tag. Put it back so it is parsed later.
PutCurrentBack();
PutBack(whitespaceAfterAttributeName);
// Output anything prior to the attribute, in most cases this will be the tag name:
// |<input| checked />. If in-between other attributes this will noop or output malformed attribute
// content (if the previous attribute was malformed).
@ -507,11 +516,14 @@ namespace Microsoft.AspNet.Razor.Parser
// Start a new markup block for the attribute
using (Context.StartBlock(BlockType.Markup))
{
AttributePrefix(whitespace, name);
AttributePrefix(whitespace, name, whitespaceAfterAttributeName);
}
}
private void AttributePrefix(IEnumerable<HtmlSymbol> whitespace, IEnumerable<HtmlSymbol> nameSymbols)
private void AttributePrefix(
IEnumerable<HtmlSymbol> whitespace,
IEnumerable<HtmlSymbol> nameSymbols,
IEnumerable<HtmlSymbol> whitespaceAfterAttributeName)
{
// First, determine if this is a 'data-' attribute (since those can't use conditional attributes)
var name = nameSymbols.GetContent(Span.Start);
@ -520,14 +532,27 @@ namespace Microsoft.AspNet.Razor.Parser
// Accept the whitespace and name
Accept(whitespace);
Accept(nameSymbols);
// Since this is not a minimized attribute, the whitespace after attribute name belongs to this attribute.
Accept(whitespaceAfterAttributeName);
Assert(HtmlSymbolType.Equals); // We should be at "="
AcceptAndMoveNext();
var whitespaceAfterEquals = ReadWhile(sym => sym.Type == HtmlSymbolType.WhiteSpace || sym.Type == HtmlSymbolType.NewLine);
var quote = HtmlSymbolType.Unknown;
if (At(HtmlSymbolType.SingleQuote) || At(HtmlSymbolType.DoubleQuote))
{
// Found a quote, the whitespace belongs to this attribute.
Accept(whitespaceAfterEquals);
quote = CurrentSymbol.Type;
AcceptAndMoveNext();
}
else if (whitespaceAfterEquals.Any())
{
// No quotes found after the whitespace. Put it back so that it can be parsed later.
PutCurrentBack();
PutBack(whitespaceAfterEquals);
}
// We now have the prefix: (i.e. ' foo="')
var prefix = Span.GetContent();
@ -537,10 +562,15 @@ namespace Microsoft.AspNet.Razor.Parser
Span.ChunkGenerator = SpanChunkGenerator.Null; // The block chunk generator will render the prefix
Output(SpanKind.Markup);
// Read the values
while (!EndOfFile && !IsEndOfAttributeValue(quote, CurrentSymbol))
// Read the attribute value only if the value is quoted
// or if there is no whitespace between '=' and the unquoted value.
if (quote != HtmlSymbolType.Unknown || !whitespaceAfterEquals.Any())
{
AttributeValue(quote);
// Read the attribute value.
while (!EndOfFile && !IsEndOfAttributeValue(quote, CurrentSymbol))
{
AttributeValue(quote);
}
}
// Capture the suffix
@ -567,6 +597,11 @@ namespace Microsoft.AspNet.Razor.Parser
// Output the attribute name, the equals and optional quote. Ex: foo="
Output(SpanKind.Markup);
if (quote == HtmlSymbolType.Unknown && whitespaceAfterEquals.Any())
{
return;
}
// Not a "conditional" attribute, so just read the value
SkipToAndParseCode(sym => IsEndOfAttributeValue(quote, sym));

View File

@ -206,23 +206,32 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
// 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:
// https://github.com/aspnet/Razor/issues/123
// TODO: Handle malformed tags, if there's an '=' then there MUST be a value.
// https://github.com/aspnet/Razor/issues/104
SourceLocation symbolStartLocation;
// Skip the whitespace preceding the start of the attribute value.
var valueStartIndex = i + 1; // Start from the symbol after '='.
while (valueStartIndex < htmlSymbols.Length &&
(htmlSymbols[valueStartIndex].Type == HtmlSymbolType.WhiteSpace ||
htmlSymbols[valueStartIndex].Type == HtmlSymbolType.NewLine))
{
valueStartIndex++;
}
// Check for attribute start values, aka single or double quote
if ((i + 1) < htmlSymbols.Length && IsQuote(htmlSymbols[i + 1]))
if (valueStartIndex < htmlSymbols.Length && IsQuote(htmlSymbols[valueStartIndex]))
{
// Move past the attribute start so we can accept the true value.
i++;
symbolStartLocation = htmlSymbols[i].Start;
valueStartIndex++;
symbolStartLocation = htmlSymbols[valueStartIndex].Start;
// If there's a start quote then there must be an end quote to be valid, skip it.
symbolOffset = 1;
i = valueStartIndex - 1;
}
else
{

View File

@ -848,32 +848,36 @@ namespace Microsoft.AspNet.Razor.Test.Generator
DefaultPAndInputTagHelperDescriptors,
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)
BuildLineMapping(
documentAbsoluteIndex: 14,
documentLineIndex: 0,
generatedAbsoluteIndex: 493,
generatedLineIndex: 15,
characterOffsetIndex: 14,
contentLength: 11),
BuildLineMapping(
documentAbsoluteIndex: 63,
documentLineIndex: 3,
documentCharacterOffsetIndex: 27,
generatedAbsoluteIndex: 1289,
generatedLineIndex: 39,
generatedCharacterOffsetIndex: 28,
contentLength: 0),
BuildLineMapping(
documentAbsoluteIndex: 122,
documentLineIndex: 5,
generatedAbsoluteIndex: 1634,
generatedLineIndex: 48,
characterOffsetIndex: 30,
contentLength: 0),
BuildLineMapping(
documentAbsoluteIndex: 89,
documentLineIndex: 4,
documentCharacterOffsetIndex: 13,
generatedAbsoluteIndex: 1789,
generatedLineIndex: 54,
generatedCharacterOffsetIndex: 19,
contentLength: 0),
}
},
{
@ -1484,6 +1488,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
{
{ "SingleTagHelper", null, DefaultPAndInputTagHelperDescriptors },
{ "SingleTagHelperWithNewlineBeforeAttributes", null, DefaultPAndInputTagHelperDescriptors },
{ "TagHelpersWithWeirdlySpacedAttributes", null, DefaultPAndInputTagHelperDescriptors },
{ "BasicTagHelpers", null, DefaultPAndInputTagHelperDescriptors },
{ "BasicTagHelpers.RemoveTagHelper", null, DefaultPAndInputTagHelperDescriptors },
{ "BasicTagHelpers.Prefixed", null, PrefixedPAndInputTagHelperDescriptors },

View File

@ -21,9 +21,56 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("<a"),
new MarkupBlock(new AttributeBlockChunkGenerator(name: "href", prefix: new LocationTagged<string>(" href='", 2, 0, 2), suffix: new LocationTagged<string>("'", 12, 0, 12)),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "href", prefix: new LocationTagged<string>(" href='", 2, 0, 2), suffix: new LocationTagged<string>("'", 12, 0, 12)),
Factory.Markup(" href='").With(SpanChunkGenerator.Null),
Factory.Markup("Foo").With(new LiteralAttributeChunkGenerator(prefix: new LocationTagged<string>(string.Empty, 9, 0, 9), value: new LocationTagged<string>("Foo", 9, 0, 9))),
Factory.Markup("Foo").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 9, 0, 9), value: new LocationTagged<string>("Foo", 9, 0, 9))),
Factory.Markup("'").With(SpanChunkGenerator.Null)),
Factory.Markup(" />").Accepts(AcceptedCharacters.None))));
}
[Fact]
public void SimpleLiteralAttributeWithWhitespaceSurroundingEquals()
{
ParseBlockTest("<a href \f\r\n= \t\n'Foo' />",
new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("<a"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "href",
prefix: new LocationTagged<string>(" href \f\r\n= \t\n'", 2, 0, 2),
suffix: new LocationTagged<string>("'", 19, 2, 4)),
Factory.Markup(" href \f\r\n= \t\n'").With(SpanChunkGenerator.Null),
Factory.Markup("Foo").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 16, 2, 1), value: new LocationTagged<string>("Foo", 16, 2, 1))),
Factory.Markup("'").With(SpanChunkGenerator.Null)),
Factory.Markup(" />").Accepts(AcceptedCharacters.None))));
}
[Fact]
public void DynamicAttributeWithWhitespaceSurroundingEquals()
{
ParseBlockTest("<a href \n= \r\n'@Foo' />",
new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("<a"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "href",
prefix: new LocationTagged<string>(" href \n= \r\n'", 2, 0, 2),
suffix: new LocationTagged<string>("'", 18, 2, 5)),
Factory.Markup(" href \n= \r\n'").With(SpanChunkGenerator.Null),
new MarkupBlock(new DynamicAttributeBlockChunkGenerator(new LocationTagged<string>(string.Empty, 14, 2, 1), 14, 2, 1),
new ExpressionBlock(
Factory.CodeTransition(),
Factory.Code("Foo")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace))),
Factory.Markup("'").With(SpanChunkGenerator.Null)),
Factory.Markup(" />").Accepts(AcceptedCharacters.None))));
}
@ -63,20 +110,20 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
[Fact]
public void NewLinePrecedingAttribute()
{
ParseBlockTest($"<a{Environment.NewLine}href='Foo' />",
ParseBlockTest("<a\r\nhref='Foo' />",
new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("<a"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "href",
prefix: new LocationTagged<string>(Environment.NewLine + "href='", 2, 0, 2),
suffix: new LocationTagged<string>("'", 11 + Environment.NewLine.Length, 1, 9)),
Factory.Markup(Environment.NewLine + "href='").With(SpanChunkGenerator.Null),
prefix: new LocationTagged<string>("\r\nhref='", 2, 0, 2),
suffix: new LocationTagged<string>("'", 13, 1, 9)),
Factory.Markup("\r\nhref='").With(SpanChunkGenerator.Null),
Factory.Markup("Foo").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 8 + Environment.NewLine.Length, 1, 6),
value: new LocationTagged<string>("Foo", 8 + Environment.NewLine.Length, 1, 6))),
prefix: new LocationTagged<string>(string.Empty, 10, 1, 6),
value: new LocationTagged<string>("Foo", 10, 1, 6))),
Factory.Markup("'").With(SpanChunkGenerator.Null)),
Factory.Markup(" />").Accepts(AcceptedCharacters.None))));
}
@ -84,30 +131,30 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
[Fact]
public void NewLineBetweenAttributes()
{
ParseBlockTest($"<a{Environment.NewLine}href='Foo'{Environment.NewLine}abcd='Bar' />",
ParseBlockTest("<a\nhref='Foo'\r\nabcd='Bar' />",
new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("<a"),
new MarkupBlock(new AttributeBlockChunkGenerator(
name: "href",
prefix: new LocationTagged<string>(Environment.NewLine + "href='", 2, 0, 2),
suffix: new LocationTagged<string>("'", 11 + Environment.NewLine.Length, 1, 9)),
Factory.Markup(Environment.NewLine + "href='").With(SpanChunkGenerator.Null),
prefix: new LocationTagged<string>("\nhref='", 2, 0, 2),
suffix: new LocationTagged<string>("'", 12, 1, 9)),
Factory.Markup("\nhref='").With(SpanChunkGenerator.Null),
Factory.Markup("Foo").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 8 + Environment.NewLine.Length, 1, 6),
value: new LocationTagged<string>("Foo", 8 + Environment.NewLine.Length, 1, 6))),
prefix: new LocationTagged<string>(string.Empty, 9, 1, 6),
value: new LocationTagged<string>("Foo", 9, 1, 6))),
Factory.Markup("'").With(SpanChunkGenerator.Null)),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "abcd",
prefix: new LocationTagged<string>(Environment.NewLine + "abcd='", 12 + Environment.NewLine.Length, 1, 10),
suffix: new LocationTagged<string>("'", 21 + Environment.NewLine.Length * 2, 2, 9)),
Factory.Markup(Environment.NewLine + "abcd='").With(SpanChunkGenerator.Null),
prefix: new LocationTagged<string>("\r\nabcd='", 13, 1, 10),
suffix: new LocationTagged<string>("'", 24, 2, 9)),
Factory.Markup("\r\nabcd='").With(SpanChunkGenerator.Null),
Factory.Markup("Bar").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 18 + Environment.NewLine.Length * 2, 2, 6),
value: new LocationTagged<string>("Bar", 18 + Environment.NewLine.Length * 2, 2, 6))),
prefix: new LocationTagged<string>(string.Empty, 21, 2, 6),
value: new LocationTagged<string>("Bar", 21, 2, 6))),
Factory.Markup("'").With(SpanChunkGenerator.Null)),
Factory.Markup(" />").Accepts(AcceptedCharacters.None))));
}
@ -115,20 +162,20 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
[Fact]
public void WhitespaceAndNewLinePrecedingAttribute()
{
ParseBlockTest($"<a {Environment.NewLine}href='Foo' />",
ParseBlockTest("<a \t\r\nhref='Foo' />",
new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("<a"),
new MarkupBlock(
new AttributeBlockChunkGenerator(
name: "href",
prefix: new LocationTagged<string>(" " + Environment.NewLine + "href='", 2, 0, 2),
suffix: new LocationTagged<string>("'", 12 + Environment.NewLine.Length, 1, 9)),
Factory.Markup(" " + Environment.NewLine + "href='").With(SpanChunkGenerator.Null),
prefix: new LocationTagged<string>(" \t\r\nhref='", 2, 0, 2),
suffix: new LocationTagged<string>("'", 15, 1, 9)),
Factory.Markup(" \t\r\nhref='").With(SpanChunkGenerator.Null),
Factory.Markup("Foo").With(
new LiteralAttributeChunkGenerator(
prefix: new LocationTagged<string>(string.Empty, 9 + Environment.NewLine.Length, 1, 6),
value: new LocationTagged<string>("Foo", 9 + Environment.NewLine.Length, 1, 6))),
prefix: new LocationTagged<string>(string.Empty, 12, 1, 6),
value: new LocationTagged<string>("Foo", 12, 1, 6))),
Factory.Markup("'").With(SpanChunkGenerator.Null)),
Factory.Markup(" />").Accepts(AcceptedCharacters.None))));
}
@ -373,6 +420,26 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
Factory.Markup("</span>").Accepts(AcceptedCharacters.None))));
}
[Fact]
public void ConditionalAttributesWithWeirdSpacingAreDisabledForDataAttributesInBlock()
{
ParseBlockTest("<span data-foo = '@foo'></span>",
new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("<span"),
new MarkupBlock(
Factory.Markup(" data-foo = '"),
new ExpressionBlock(
Factory.CodeTransition(),
Factory.Code("foo")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace)),
Factory.Markup("'")),
Factory.Markup(">").Accepts(AcceptedCharacters.None)),
new MarkupTagBlock(
Factory.Markup("</span>").Accepts(AcceptedCharacters.None))));
}
[Fact]
public void ConditionalAttributesAreDisabledForDataAttributesInDocument()
{
@ -392,5 +459,24 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
new MarkupTagBlock(
Factory.Markup("</span>"))));
}
[Fact]
public void ConditionalAttributesWithWeirdSpacingAreDisabledForDataAttributesInDocument()
{
ParseDocumentTest("<span data-foo=@foo ></span>",
new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("<span"),
new MarkupBlock(
Factory.Markup(" data-foo="),
new ExpressionBlock(
Factory.CodeTransition(),
Factory.Code("foo")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace))),
Factory.Markup(" >")),
new MarkupTagBlock(
Factory.Markup("</span>"))));
}
}
}

View File

@ -104,9 +104,11 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
BlockFactory.MarkupTagBlock("<div >"),
new MarkupTagBlock(
Factory.Markup("<p"),
new MarkupBlock(
Factory.Markup(" class")),
Factory.Markup(" = 'bar'>")),
new MarkupBlock(new AttributeBlockChunkGenerator(name: "class", prefix: new LocationTagged<string>(" class = '", 8, 0, 8), suffix: new LocationTagged<string>("'", 21, 0, 21)),
Factory.Markup(" class = '").With(SpanChunkGenerator.Null),
Factory.Markup("bar").With(new LiteralAttributeChunkGenerator(prefix: new LocationTagged<string>(string.Empty, 18, 0, 18), value: new LocationTagged<string>("bar", 18, 0, 18))),
Factory.Markup("'").With(SpanChunkGenerator.Null)),
Factory.Markup(">")),
Factory.Markup(" Foo "),
BlockFactory.MarkupTagBlock("</p>"),
BlockFactory.MarkupTagBlock("</div >")));

View File

@ -1761,7 +1761,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
new KeyValuePair<string, SyntaxTreeNode>("class1", new MarkupBlock()),
new KeyValuePair<string, SyntaxTreeNode>(
"class2",
factory.Markup("").With(SpanChunkGenerator.Null)),
factory.Markup(string.Empty).With(SpanChunkGenerator.Null)),
new KeyValuePair<string, SyntaxTreeNode>("class3", new MarkupBlock()),
}))
},
@ -1776,7 +1776,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
new KeyValuePair<string, SyntaxTreeNode>("class2", new MarkupBlock()),
new KeyValuePair<string, SyntaxTreeNode>(
"class3",
factory.Markup("").With(SpanChunkGenerator.Null)),
factory.Markup(string.Empty).With(SpanChunkGenerator.Null)),
}))
},
};

View File

@ -0,0 +1,121 @@
#pragma checksum "TagHelpersWithWeirdlySpacedAttributes.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "61ec0611b60d88357a6c3b6551513ebf6223f6ee"
namespace TestOutput
{
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using System;
using System.Threading.Tasks;
public class TagHelpersWithWeirdlySpacedAttributes
{
#line hidden
#pragma warning disable 0414
private TagHelperContent __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private PTagHelper __PTagHelper = null;
private InputTagHelper __InputTagHelper = null;
private InputTagHelper2 __InputTagHelper2 = null;
#line hidden
public TagHelpersWithWeirdlySpacedAttributes()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner();
Instrumentation.BeginContext(33, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", TagMode.StartTagAndEndTag, "test", async() => {
Instrumentation.BeginContext(105, 11, true);
WriteLiteral("Body of Tag");
Instrumentation.EndContext();
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("Hello World"));
#line 6 "TagHelpersWithWeirdlySpacedAttributes.cshtml"
__PTagHelper.Age = 1337;
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
StartTagHelperWritingScope();
#line 7 "TagHelpersWithWeirdlySpacedAttributes.cshtml"
Write(true);
#line default
#line hidden
__tagHelperStringValueBuffer = EndTagHelperWritingScope();
__tagHelperExecutionContext.AddHtmlAttribute("data-content", Html.Raw(__tagHelperStringValueBuffer.ToString()));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(35, 85, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(120, 4, true);
WriteLiteral("\r\n\r\n");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", TagMode.SelfClosing, "test", async() => {
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__InputTagHelper = CreateTagHelper<InputTagHelper>();
__tagHelperExecutionContext.Add(__InputTagHelper);
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
__tagHelperExecutionContext.Add(__InputTagHelper2);
__InputTagHelper.Type = "text";
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
__InputTagHelper2.Type = __InputTagHelper.Type;
__tagHelperExecutionContext.AddHtmlAttribute("data-content", Html.Raw("hello"));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(124, 47, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(171, 4, true);
WriteLiteral("\r\n\r\n");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", TagMode.StartTagAndEndTag, "test", async() => {
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
#line 11 "TagHelpersWithWeirdlySpacedAttributes.cshtml"
__PTagHelper.Age = 1234;
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
__tagHelperExecutionContext.AddHtmlAttribute("data-content", Html.Raw("hello2"));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(175, 46, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(221, 4, true);
WriteLiteral("\r\n\r\n");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", TagMode.SelfClosing, "test", async() => {
}
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__InputTagHelper = CreateTagHelper<InputTagHelper>();
__tagHelperExecutionContext.Add(__InputTagHelper);
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
__tagHelperExecutionContext.Add(__InputTagHelper2);
__InputTagHelper.Type = "password";
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
__InputTagHelper2.Type = __InputTagHelper.Type;
__tagHelperExecutionContext.AddHtmlAttribute("data-content", Html.Raw("blah"));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
Instrumentation.BeginContext(225, 51, false);
await WriteTagHelperAsync(__tagHelperExecutionContext);
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.End();
}
#pragma warning restore 1998
}
}

View File

@ -0,0 +1,15 @@
@addTagHelper "something, nice"
<p
class
=
"Hello World" age =1337
data-content= "@true">Body of Tag</p>
<input type = 'text' data-content= "hello" />
<p age= "1234" data-content
= 'hello2'></p>
<input type
=password data-content =blah/>