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:
parent
6568de38d1
commit
08c8f9f7ba
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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>"))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 >")));
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
}))
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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/>
|
||||
Loading…
Reference in New Issue