diff --git a/src/Microsoft.AspNetCore.Razor.Runtime/Runtime/TagHelpers/TagHelperExecutionContext.cs b/src/Microsoft.AspNetCore.Razor.Runtime/Runtime/TagHelpers/TagHelperExecutionContext.cs index fda0854e62..e299b051ce 100644 --- a/src/Microsoft.AspNetCore.Razor.Runtime/Runtime/TagHelpers/TagHelperExecutionContext.cs +++ b/src/Microsoft.AspNetCore.Razor.Runtime/Runtime/TagHelpers/TagHelperExecutionContext.cs @@ -138,34 +138,20 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers _tagHelpers.Add(tagHelper); } - /// - /// Tracks the minimized HTML attribute. - /// - /// The minimized HTML attribute name. - public void AddMinimizedHtmlAttribute(string name) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - var attribute = new TagHelperAttribute(name); - AddHtmlAttribute(attribute); - } - /// /// Tracks the HTML attribute. /// /// The HTML attribute name. /// The HTML attribute value. - public void AddHtmlAttribute(string name, object value) + /// The value style of the attribute. + public void AddHtmlAttribute(string name, object value, HtmlAttributeValueStyle valueStyle) { if (name == null) { throw new ArgumentNullException(nameof(name)); } - var attribute = new TagHelperAttribute(name, value); + var attribute = new TagHelperAttribute(name, value, valueStyle); AddHtmlAttribute(attribute); } @@ -189,15 +175,16 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers /// /// The bound attribute name. /// The attribute value. - public void AddTagHelperAttribute(string name, object value) + /// The value style of the attribute. + public void AddTagHelperAttribute(string name, object value, HtmlAttributeValueStyle valueStyle) { if (name == null) { throw new ArgumentNullException(nameof(name)); } - - _allAttributes.Add(name, value); + var attribute = new TagHelperAttribute(name, value, valueStyle); + _allAttributes.Add(attribute); } /// diff --git a/src/Microsoft.AspNetCore.Razor.Runtime/TagHelpers/TagHelperAttribute.cs b/src/Microsoft.AspNetCore.Razor.Runtime/TagHelpers/TagHelperAttribute.cs index 259e428d54..f23318041a 100644 --- a/src/Microsoft.AspNetCore.Razor.Runtime/TagHelpers/TagHelperAttribute.cs +++ b/src/Microsoft.AspNetCore.Razor.Runtime/TagHelpers/TagHelperAttribute.cs @@ -2,6 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.IO; +using System.Text.Encodings.Web; +using Microsoft.AspNetCore.Html; using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Razor.TagHelpers @@ -9,39 +12,40 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers /// /// An HTML tag helper attribute. /// - public class TagHelperAttribute + public class TagHelperAttribute : IHtmlContentContainer { /// /// Instantiates a new instance of with the specified . - /// is set to true and to null. + /// is set to and to + /// null. /// /// The of the attribute. public TagHelperAttribute(string name) - : this(name, value: null, minimized: true) + : this(name, value: null, valueStyle: HtmlAttributeValueStyle.Minimized) { } /// /// Instantiates a new instance of with the specified - /// and . is set to false. + /// and . is set to . /// /// The of the attribute. /// The of the attribute. public TagHelperAttribute(string name, object value) - : this(name, value, minimized: false) + : this(name, value, valueStyle: HtmlAttributeValueStyle.DoubleQuotes) { } /// /// Instantiates a new instance of with the specified , - /// and . + /// and . /// /// The of the new instance. /// The of the new instance. - /// The value of the new instance. - /// If is true, is ignored when this - /// instance is rendered. - public TagHelperAttribute(string name, object value, bool minimized) + /// The of the new instance. + /// If is , + /// is ignored when this instance is rendered. + public TagHelperAttribute(string name, object value, HtmlAttributeValueStyle valueStyle) { if (name == null) { @@ -50,7 +54,7 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers Name = name; Value = value; - Minimized = minimized; + ValueStyle = valueStyle; } /// @@ -64,11 +68,9 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers public object Value { get; } /// - /// Gets an indication whether the attribute is minimized or not. + /// Gets the value style of the attribute. /// - /// If true, will be ignored. - public bool Minimized { get; } - + public HtmlAttributeValueStyle ValueStyle { get; } /// /// is compared case-insensitively. @@ -77,8 +79,147 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers return other != null && string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase) && - Minimized == other.Minimized && - (Minimized || Equals(Value, other.Value)); + ValueStyle == other.ValueStyle && + (ValueStyle == HtmlAttributeValueStyle.Minimized || Equals(Value, other.Value)); + } + + /// + public void WriteTo(TextWriter writer, HtmlEncoder encoder) + { + if (writer == null) + { + throw new ArgumentNullException(nameof(writer)); + } + + if (encoder == null) + { + throw new ArgumentNullException(nameof(encoder)); + } + + writer.Write(Name); + + if (ValueStyle == HtmlAttributeValueStyle.Minimized) + { + return; + } + + var valuePrefix = GetAttributeValuePrefix(ValueStyle); + if (valuePrefix != null) + { + writer.Write(valuePrefix); + } + + var htmlContent = Value as IHtmlContent; + if (htmlContent != null) + { + htmlContent.WriteTo(writer, encoder); + } + else if (Value != null) + { + encoder.Encode(writer, Value.ToString()); + } + + var valueSuffix = GetAttributeValueSuffix(ValueStyle); + if (valueSuffix != null) + { + writer.Write(valueSuffix); + } + } + + /// + public void CopyTo(IHtmlContentBuilder destination) + { + if (destination == null) + { + throw new ArgumentNullException(nameof(destination)); + } + + destination.AppendHtml(Name); + + if (ValueStyle == HtmlAttributeValueStyle.Minimized) + { + return; + } + + var valuePrefix = GetAttributeValuePrefix(ValueStyle); + if (valuePrefix != null) + { + destination.AppendHtml(valuePrefix); + } + + string valueAsString; + IHtmlContentContainer valueAsHtmlContainer; + IHtmlContent valueAsHtmlContent; + if ((valueAsString = Value as string) != null) + { + destination.Append(valueAsString); + } + else if ((valueAsHtmlContainer = Value as IHtmlContentContainer) != null) + { + valueAsHtmlContainer.CopyTo(destination); + } + else if ((valueAsHtmlContent = Value as IHtmlContent) != null) + { + destination.AppendHtml(valueAsHtmlContent); + } + else if (Value != null) + { + destination.Append(Value.ToString()); + } + + var valueSuffix = GetAttributeValueSuffix(ValueStyle); + if (valueSuffix != null) + { + destination.AppendHtml(valueSuffix); + } + } + + /// + public void MoveTo(IHtmlContentBuilder destination) + { + if (destination == null) + { + throw new ArgumentNullException(nameof(destination)); + } + + destination.AppendHtml(Name); + + if (ValueStyle == HtmlAttributeValueStyle.Minimized) + { + return; + } + + var valuePrefix = GetAttributeValuePrefix(ValueStyle); + if (valuePrefix != null) + { + destination.AppendHtml(valuePrefix); + } + + string valueAsString; + IHtmlContentContainer valueAsHtmlContainer; + IHtmlContent valueAsHtmlContent; + if ((valueAsString = Value as string) != null) + { + destination.Append(valueAsString); + } + else if ((valueAsHtmlContainer = Value as IHtmlContentContainer) != null) + { + valueAsHtmlContainer.MoveTo(destination); + } + else if ((valueAsHtmlContent = Value as IHtmlContent) != null) + { + destination.AppendHtml(valueAsHtmlContent); + } + else if (Value != null) + { + destination.Append(Value.ToString()); + } + + var valueSuffix = GetAttributeValueSuffix(ValueStyle); + if (valueSuffix != null) + { + destination.AppendHtml(valueSuffix); + } } /// @@ -94,10 +235,43 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers { var hashCodeCombiner = HashCodeCombiner.Start(); hashCodeCombiner.Add(Name, StringComparer.Ordinal); - hashCodeCombiner.Add(Value); - hashCodeCombiner.Add(Minimized); + + if (ValueStyle != HtmlAttributeValueStyle.Minimized) + { + hashCodeCombiner.Add(Value); + } + + hashCodeCombiner.Add(ValueStyle); return hashCodeCombiner.CombinedHash; } + + private static string GetAttributeValuePrefix(HtmlAttributeValueStyle valueStyle) + { + switch (valueStyle) + { + case HtmlAttributeValueStyle.DoubleQuotes: + return "=\""; + case HtmlAttributeValueStyle.SingleQuotes: + return "='"; + case HtmlAttributeValueStyle.NoQuotes: + return "="; + } + + return null; + } + + private static string GetAttributeValueSuffix(HtmlAttributeValueStyle valueStyle) + { + switch (valueStyle) + { + case HtmlAttributeValueStyle.DoubleQuotes: + return "\""; + case HtmlAttributeValueStyle.SingleQuotes: + return "'"; + } + + return null; + } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Runtime/TagHelpers/TagHelperOutput.cs b/src/Microsoft.AspNetCore.Razor.Runtime/TagHelpers/TagHelperOutput.cs index b49718bca0..14de474670 100644 --- a/src/Microsoft.AspNetCore.Razor.Runtime/TagHelpers/TagHelperOutput.cs +++ b/src/Microsoft.AspNetCore.Razor.Runtime/TagHelpers/TagHelperOutput.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Diagnostics; using System.IO; using System.Text.Encodings.Web; using System.Threading.Tasks; @@ -305,7 +306,13 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers destination.AppendHtml("<"); destination.AppendHtml(TagName); - CopyAttributesTo(destination); + // Perf: Avoid allocating enumerator + for (var i = 0; i < Attributes.Count; i++) + { + var attribute = Attributes[i]; + destination.AppendHtml(" "); + attribute.CopyTo(destination); + } if (TagMode == TagMode.SelfClosing) { @@ -350,7 +357,13 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers destination.AppendHtml("<"); destination.AppendHtml(TagName); - CopyAttributesTo(destination); + // Perf: Avoid allocating enumerator + for (var i = 0; i < Attributes.Count; i++) + { + var attribute = Attributes[i]; + destination.AppendHtml(" "); + attribute.MoveTo(destination); + } if (TagMode == TagMode.SelfClosing) { @@ -405,49 +418,11 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers writer.Write(TagName); // Perf: Avoid allocating enumerator - for (var i = 0; i < (Attributes.Count); i++) + for (var i = 0; i < Attributes.Count; i++) { var attribute = Attributes[i]; writer.Write(" "); - writer.Write(attribute.Name); - - if (attribute.Minimized) - { - continue; - } - - writer.Write("=\""); - var value = attribute.Value; - var htmlContent = value as IHtmlContent; - if (htmlContent != null) - { - // Perf: static text in a bound attribute go down this path. Avoid allocating if possible (common case). - var htmlString = value as HtmlString; - if (htmlString != null && !htmlString.Value.Contains("\"")) - { - writer.Write(htmlString.Value); - } - else - { - // There's no way of tracking the attribute value quotations in the Razor source. Therefore, we - // must escape any IHtmlContent double quote values in the case that a user wrote: - // - using (var stringWriter = new StringWriter()) - { - htmlContent.WriteTo(stringWriter, encoder); - stringWriter.GetStringBuilder().Replace("\"", """); - - var stringValue = stringWriter.ToString(); - writer.Write(stringValue); - } - } - } - else if (value != null) - { - encoder.Encode(writer, value.ToString()); - } - - writer.Write("\""); + attribute.WriteTo(writer, encoder); } if (TagMode == TagMode.SelfClosing) @@ -476,76 +451,5 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers _postElement?.WriteTo(writer, encoder); } - - private void CopyAttributesTo(IHtmlContentBuilder destination) - { - StringWriter stringWriter = null; - - // Perf: Avoid allocating enumerator - for (var i = 0; i < (Attributes.Count); i++) - { - var attribute = Attributes[i]; - destination.AppendHtml(" "); - destination.AppendHtml(attribute.Name); - - if (attribute.Minimized) - { - continue; - } - - destination.AppendHtml("=\""); - var value = attribute.Value; - var htmlContent = value as IHtmlContent; - if (htmlContent != null) - { - // Perf: static text in a bound attribute go down this path. Avoid allocating if possible (common case). - var htmlString = value as HtmlString; - if (htmlString != null && !htmlString.Value.Contains("\"")) - { - destination.AppendHtml(htmlString); - } - else - { - // Perf: We'll share this writer implementation for all attributes since - // they can't nest. - stringWriter = stringWriter ?? new StringWriter(); - - destination.AppendHtml(new AttributeContent(htmlContent, stringWriter)); - } - } - else if (value != null) - { - destination.Append(value.ToString()); - } - - destination.AppendHtml("\""); - } - } - - private class AttributeContent : IHtmlContent - { - private readonly IHtmlContent _inner; - private readonly StringWriter _stringWriter; - - public AttributeContent(IHtmlContent inner, StringWriter stringWriter) - { - _inner = inner; - _stringWriter = stringWriter; - } - - public void WriteTo(TextWriter writer, HtmlEncoder encoder) - { - // There's no way of tracking the attribute value quotations in the Razor source. Therefore, we - // must escape any IHtmlContent double quote values in the case that a user wrote: - // - _inner.WriteTo(_stringWriter, encoder); - _stringWriter.GetStringBuilder().Replace("\"", """); - - var stringValue = _stringWriter.ToString(); - writer.Write(stringValue); - - _stringWriter.GetStringBuilder().Clear(); - } - } } } diff --git a/src/Microsoft.AspNetCore.Razor/Chunks/Generators/TagHelperChunkGenerator.cs b/src/Microsoft.AspNetCore.Razor/Chunks/Generators/TagHelperChunkGenerator.cs index b59baafc18..87b8d1789d 100644 --- a/src/Microsoft.AspNetCore.Razor/Chunks/Generators/TagHelperChunkGenerator.cs +++ b/src/Microsoft.AspNetCore.Razor/Chunks/Generators/TagHelperChunkGenerator.cs @@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators tagHelperBlock != null, $"A {nameof(TagHelperChunkGenerator)} must only be used with {nameof(TagHelperBlock)}s."); - var attributes = new List>(); + var attributes = new List(); // We need to create a chunk generator to create chunks for each of the attributes. var chunkGenerator = context.Host.CreateChunkGenerator( @@ -72,7 +72,12 @@ namespace Microsoft.AspNetCore.Razor.Chunks.Generators }; } - attributes.Add(new KeyValuePair(attribute.Key, attributeChunkValue)); + var attributeChunk = new TagHelperAttributeTracker( + attribute.Name, + attributeChunkValue, + attribute.ValueStyle); + + attributes.Add(attributeChunk); // Reset the chunk tree builder so we can build a new one for the next attribute chunkGenerator.Context.ChunkTreeBuilder = new ChunkTreeBuilder(); diff --git a/src/Microsoft.AspNetCore.Razor/Chunks/TagHelperAttributeChunk.cs b/src/Microsoft.AspNetCore.Razor/Chunks/TagHelperAttributeChunk.cs new file mode 100644 index 0000000000..a19d61f252 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor/Chunks/TagHelperAttributeChunk.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Razor.TagHelpers; + +namespace Microsoft.AspNetCore.Razor.Chunks +{ + public struct TagHelperAttributeTracker + { + public TagHelperAttributeTracker(string name, Chunk value, HtmlAttributeValueStyle valueStyle) + { + Name = name; + Value = value; + ValueStyle = valueStyle; + } + + public string Name { get; } + + public Chunk Value { get; } + + public HtmlAttributeValueStyle ValueStyle { get; } + } +} diff --git a/src/Microsoft.AspNetCore.Razor/Chunks/TagHelperChunk.cs b/src/Microsoft.AspNetCore.Razor/Chunks/TagHelperChunk.cs index 87564839ac..1cb4c69033 100644 --- a/src/Microsoft.AspNetCore.Razor/Chunks/TagHelperChunk.cs +++ b/src/Microsoft.AspNetCore.Razor/Chunks/TagHelperChunk.cs @@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks public TagHelperChunk( string tagName, TagMode tagMode, - IList> attributes, + IList attributes, IEnumerable descriptors) { TagName = tagName; @@ -36,11 +36,7 @@ namespace Microsoft.AspNetCore.Razor.Chunks /// /// The HTML attributes. /// - /// - /// These attributes are => so attribute values can consist - /// of all sorts of Razor specific pieces. - /// - public IList> Attributes { get; set; } + public IList Attributes { get; set; } /// /// The s that are associated with the tag helpers HTML element. diff --git a/src/Microsoft.AspNetCore.Razor/CodeGenerators/CSharpTagHelperCodeRenderer.cs b/src/Microsoft.AspNetCore.Razor/CodeGenerators/CSharpTagHelperCodeRenderer.cs index f365f1124e..65e54819e9 100644 --- a/src/Microsoft.AspNetCore.Razor/CodeGenerators/CSharpTagHelperCodeRenderer.cs +++ b/src/Microsoft.AspNetCore.Razor/CodeGenerators/CSharpTagHelperCodeRenderer.cs @@ -227,7 +227,7 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators foreach (var chunkAttribute in chunk.Attributes) { var associatedAttributeDescriptor = tagHelperDescriptor.Attributes.FirstOrDefault( - attributeDescriptor => attributeDescriptor.IsNameMatch(chunkAttribute.Key)); + attributeDescriptor => attributeDescriptor.IsNameMatch(chunkAttribute.Name)); if (associatedAttributeDescriptor != null && associatedAttributeDescriptor.IsIndexer && @@ -248,7 +248,7 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators .Write("throw ") .WriteStartNewObject(nameof(InvalidOperationException)) .WriteStartMethodInvocation(_tagHelperContext.FormatInvalidIndexerAssignmentMethodName) - .WriteStringLiteral(chunkAttribute.Key) + .WriteStringLiteral(chunkAttribute.Name) .WriteParameterSeparator() .WriteStringLiteral(tagHelperDescriptor.TypeName) .WriteParameterSeparator() @@ -262,7 +262,7 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators } private void RenderAttributes( - IList> chunkAttributes, + IList chunkAttributes, IEnumerable tagHelperDescriptors) { var renderedBoundAttributeNames = new HashSet(StringComparer.OrdinalIgnoreCase); @@ -271,14 +271,13 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators // TagHelperExecutionContext.HtmlAttributes' as we go. foreach (var attribute in chunkAttributes) { - var attributeName = attribute.Key; var attributeValueChunk = attribute.Value; var associatedDescriptors = tagHelperDescriptors.Where(descriptor => - descriptor.Attributes.Any(attributeDescriptor => attributeDescriptor.IsNameMatch(attributeName))); + descriptor.Attributes.Any(attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Name))); // Bound attributes have associated descriptors. First attribute value wins if there are duplicates; // later values of duplicate bound attributes are treated as if they were unbound. - if (associatedDescriptors.Any() && renderedBoundAttributeNames.Add(attributeName)) + if (associatedDescriptors.Any() && renderedBoundAttributeNames.Add(attribute.Name)) { if (attributeValueChunk == null) { @@ -294,12 +293,11 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators foreach (var associatedDescriptor in associatedDescriptors) { var associatedAttributeDescriptor = associatedDescriptor.Attributes.First( - attributeDescriptor => attributeDescriptor.IsNameMatch(attributeName)); + attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Name)); var tagHelperVariableName = GetVariableName(associatedDescriptor); valueAccessor = RenderBoundAttribute( - attributeName, - attributeValueChunk, + attribute, tagHelperVariableName, valueAccessor, associatedAttributeDescriptor); @@ -307,14 +305,13 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators } else { - RenderUnboundAttribute(attributeName, attributeValueChunk); + RenderUnboundAttribute(attribute); } } } private string RenderBoundAttribute( - string attributeName, - Chunk attributeValueChunk, + TagHelperAttributeTracker attribute, string tagHelperVariableName, string previousValueAccessor, TagHelperAttributeDescriptor attributeDescriptor) @@ -327,7 +324,7 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators if (attributeDescriptor.IsIndexer) { - var dictionaryKey = attributeName.Substring(attributeDescriptor.Name.Length); + var dictionaryKey = attribute.Name.Substring(attributeDescriptor.Name.Length); currentValueAccessor += $"[\"{dictionaryKey}\"]"; } @@ -342,7 +339,7 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators RenderNewAttributeValueAssignment( attributeDescriptor, bufferableAttribute, - attributeValueChunk, + attribute.Value, currentValueAccessor); if (_designTimeMode) @@ -356,9 +353,11 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators .WriteStartInstanceMethodInvocation( ExecutionContextVariableName, _tagHelperContext.ExecutionContextAddTagHelperAttributeMethodName) - .WriteStringLiteral(attributeName) + .WriteStringLiteral(attribute.Name) .WriteParameterSeparator() .Write(currentValueAccessor) + .WriteParameterSeparator() + .Write($"global::{typeof(HtmlAttributeValueStyle).FullName}.{attribute.ValueStyle}") .WriteEndMethodInvocation(); return currentValueAccessor; @@ -450,112 +449,93 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators } } - private void RenderUnboundAttribute(string attributeName, Chunk attributeValueChunk) + private void RenderUnboundAttribute(TagHelperAttributeTracker attribute) { // Render children to provide IntelliSense at design time. No need for the execution context logic, it's // a runtime feature. if (_designTimeMode) { - if (attributeValueChunk != null) + if (attribute.Value != null) { - _bodyVisitor.Accept(attributeValueChunk); + _bodyVisitor.Accept(attribute.Value); } return; } - // If we have a minimized attribute there is no value - if (attributeValueChunk == null) - { - _writer - .WriteStartInstanceMethodInvocation( - ExecutionContextVariableName, - _tagHelperContext.ExecutionContextAddMinimizedHtmlAttributeMethodName) - .WriteStringLiteral(attributeName) - .WriteEndMethodInvocation(); - } - else if (attributeValueChunk is PreallocatedTagHelperAttributeChunk) + Debug.Assert(attribute.Value != null); + + var attributeValueStyleParameter = $"global::{typeof(HtmlAttributeValueStyle).FullName}.{attribute.ValueStyle}"; + + // All simple text and minimized attributes will be pre-allocated. + var preallocatedValue = attribute.Value as PreallocatedTagHelperAttributeChunk; + if (preallocatedValue != null) { _writer .WriteStartInstanceMethodInvocation( ExecutionContextVariableName, _tagHelperContext.ExecutionContextAddHtmlAttributeMethodName) - .Write(((PreallocatedTagHelperAttributeChunk)attributeValueChunk).AttributeVariableAccessor) + .Write(preallocatedValue.AttributeVariableAccessor) .WriteEndMethodInvocation(); } + else if (IsDynamicAttributeValue(attribute.Value)) + { + // Dynamic attribute value should be run through the conditional attribute removal system. It's + // unbound and contains C#. + + // TagHelper attribute rendering is buffered by default. We do not want to write to the current + // writer. + var currentTargetWriter = _context.TargetWriterName; + var currentWriteAttributeMethodName = _context.Host.GeneratedClassContext.WriteAttributeValueMethodName; + _context.TargetWriterName = null; + + Debug.Assert(attribute.Value is ParentChunk); + var children = ((ParentChunk)attribute.Value).Children; + var attributeCount = children.Count(c => c is DynamicCodeAttributeChunk || c is LiteralCodeAttributeChunk); + + _writer + .WriteStartMethodInvocation(_tagHelperContext.BeginAddHtmlAttributeValuesMethodName) + .Write(ExecutionContextVariableName) + .WriteParameterSeparator() + .WriteStringLiteral(attribute.Name) + .WriteParameterSeparator() + .Write(attributeCount.ToString(CultureInfo.InvariantCulture)) + .WriteParameterSeparator() + .Write(attributeValueStyleParameter) + .WriteEndMethodInvocation(); + + _attributeCodeVisitor.Accept(attribute.Value); + + _writer.WriteMethodInvocation( + _tagHelperContext.EndAddHtmlAttributeValuesMethodName, + ExecutionContextVariableName); + + _context.TargetWriterName = currentTargetWriter; + } else { - string textValue = null; - var isPlainTextValue = TryGetPlainTextValue(attributeValueChunk, out textValue); + // This is a data-* attribute which includes C#. Do not perform the conditional attribute removal or + // other special cases used when IsDynamicAttributeValue(). But the attribute must still be buffered to + // determine its final value. - if (isPlainTextValue) - { - // If it's a plain text value then we need to surround the value with quotes. - _writer - .WriteStartInstanceMethodInvocation( - ExecutionContextVariableName, - _tagHelperContext.ExecutionContextAddHtmlAttributeMethodName) - .WriteStringLiteral(attributeName) - .WriteParameterSeparator() - .WriteStartMethodInvocation(_tagHelperContext.MarkAsHtmlEncodedMethodName) - .WriteStringLiteral(textValue) - .WriteEndMethodInvocation(endLine: false) - .WriteEndMethodInvocation(); - } - else if (IsDynamicAttributeValue(attributeValueChunk)) - { - // Dynamic attribute value should be run through the conditional attribute removal system. It's - // unbound and contains C#. + // Attribute value is not plain text, must be buffered to determine its final value. + BuildBufferedWritingScope(attribute.Value, htmlEncodeValues: true); - // TagHelper attribute rendering is buffered by default. We do not want to write to the current - // writer. - var currentTargetWriter = _context.TargetWriterName; - var currentWriteAttributeMethodName = _context.Host.GeneratedClassContext.WriteAttributeValueMethodName; - _context.TargetWriterName = null; + _writer + .WriteStartInstanceMethodInvocation( + ExecutionContextVariableName, + _tagHelperContext.ExecutionContextAddHtmlAttributeMethodName) + .WriteStringLiteral(attribute.Name) + .WriteParameterSeparator() + .WriteStartMethodInvocation(_tagHelperContext.MarkAsHtmlEncodedMethodName); - Debug.Assert(attributeValueChunk is ParentChunk); - var children = ((ParentChunk)attributeValueChunk).Children; - var attributeCount = children.Count(c => c is DynamicCodeAttributeChunk || c is LiteralCodeAttributeChunk); + RenderBufferedAttributeValueAccessor(_writer); - _writer - .WriteStartMethodInvocation(_tagHelperContext.BeginAddHtmlAttributeValuesMethodName) - .Write(ExecutionContextVariableName) - .WriteParameterSeparator() - .WriteStringLiteral(attributeName) - .WriteParameterSeparator() - .Write(attributeCount.ToString(CultureInfo.InvariantCulture)) - .WriteEndMethodInvocation(); - - _attributeCodeVisitor.Accept(attributeValueChunk); - - _writer.WriteMethodInvocation( - _tagHelperContext.EndAddHtmlAttributeValuesMethodName, - ExecutionContextVariableName); - - _context.TargetWriterName = currentTargetWriter; - } - else - { - // HTML attributes are always strings. This attribute contains C# but is not dynamic. This occurs - // when the attribute is a data-* attribute. - - // Attribute value is not plain text, must be buffered to determine its final value. - BuildBufferedWritingScope(attributeValueChunk, htmlEncodeValues: true); - - _writer - .WriteStartInstanceMethodInvocation( - ExecutionContextVariableName, - _tagHelperContext.ExecutionContextAddHtmlAttributeMethodName) - .WriteStringLiteral(attributeName) - .WriteParameterSeparator() - .WriteStartMethodInvocation(_tagHelperContext.MarkAsHtmlEncodedMethodName); - - RenderBufferedAttributeValueAccessor(_writer); - - _writer - .WriteEndMethodInvocation(endLine: false) - .WriteEndMethodInvocation(); - } + _writer + .WriteEndMethodInvocation(endLine: false) + .WriteParameterSeparator() + .Write(attributeValueStyleParameter) + .WriteEndMethodInvocation(); } } diff --git a/src/Microsoft.AspNetCore.Razor/CodeGenerators/GeneratedTagHelperContext.cs b/src/Microsoft.AspNetCore.Razor/CodeGenerators/GeneratedTagHelperContext.cs index c63dd81b1d..df9b481585 100644 --- a/src/Microsoft.AspNetCore.Razor/CodeGenerators/GeneratedTagHelperContext.cs +++ b/src/Microsoft.AspNetCore.Razor/CodeGenerators/GeneratedTagHelperContext.cs @@ -22,7 +22,6 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators ScopeManagerEndMethodName = "End"; ExecutionContextAddMethodName = "Add"; ExecutionContextAddTagHelperAttributeMethodName = "AddTagHelperAttribute"; - ExecutionContextAddMinimizedHtmlAttributeMethodName = "AddMinimizedHtmlAttribute"; ExecutionContextAddHtmlAttributeMethodName = "AddHtmlAttribute"; ExecutionContextOutputPropertyName = "Output"; FormatInvalidIndexerAssignmentMethodName = "FormatInvalidIndexerAssignment"; @@ -113,11 +112,6 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators /// public string ExecutionContextAddTagHelperAttributeMethodName { get; set; } - /// - /// The name of the method used to add minimized HTML attributes. - /// - public string ExecutionContextAddMinimizedHtmlAttributeMethodName { get; set; } - /// /// The name of the method used to add HTML attributes. /// diff --git a/src/Microsoft.AspNetCore.Razor/CodeGenerators/Visitors/CSharpTagHelperFieldDeclarationVisitor.cs b/src/Microsoft.AspNetCore.Razor/CodeGenerators/Visitors/CSharpTagHelperFieldDeclarationVisitor.cs index 8f4f7c97b0..24333817a3 100644 --- a/src/Microsoft.AspNetCore.Razor/CodeGenerators/Visitors/CSharpTagHelperFieldDeclarationVisitor.cs +++ b/src/Microsoft.AspNetCore.Razor/CodeGenerators/Visitors/CSharpTagHelperFieldDeclarationVisitor.cs @@ -3,8 +3,10 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Microsoft.AspNetCore.Razor.Chunks; +using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Razor.CodeGenerators.Visitors @@ -107,16 +109,18 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators.Visitors { var attribute = chunk.Attributes[i]; var hasAssociatedDescriptors = chunk.Descriptors.Any(descriptor => - descriptor.Attributes.Any(attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Key))); + descriptor.Attributes.Any(attributeDescriptor => attributeDescriptor.IsNameMatch(attribute.Name))); // If there's no descriptors associated or we're hitting a bound attribute a second time. - if (!hasAssociatedDescriptors || !boundAttributes.Add(attribute.Key)) + if (!hasAssociatedDescriptors || !boundAttributes.Add(attribute.Name)) { string preAllocatedAttributeVariableName = null; - if (attribute.Value == null) + if (attribute.ValueStyle == HtmlAttributeValueStyle.Minimized) { - var preAllocatedAttributeKey = new TagHelperAttributeKey(attribute.Key, value: null); + Debug.Assert(attribute.Value == null); + + var preAllocatedAttributeKey = new TagHelperAttributeKey(attribute.Name, value: null, valueStyle: attribute.ValueStyle); if (TryCachePreallocatedVariableName(preAllocatedAttributeKey, out preAllocatedAttributeVariableName)) { Writer @@ -126,16 +130,18 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators.Visitors .Write(preAllocatedAttributeVariableName) .Write(" = ") .WriteStartNewObject("global::" + _tagHelperContext.TagHelperAttributeTypeName) - .WriteStringLiteral(attribute.Key) + .WriteStringLiteral(attribute.Name) .WriteEndMethodInvocation(); } } else { + Debug.Assert(attribute.Value != null); + string plainText; if (CSharpTagHelperCodeRenderer.TryGetPlainTextValue(attribute.Value, out plainText)) { - var preAllocatedAttributeKey = new TagHelperAttributeKey(attribute.Key, plainText); + var preAllocatedAttributeKey = new TagHelperAttributeKey(attribute.Name, plainText, attribute.ValueStyle); if (TryCachePreallocatedVariableName(preAllocatedAttributeKey, out preAllocatedAttributeVariableName)) { Writer @@ -145,11 +151,13 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators.Visitors .Write(preAllocatedAttributeVariableName) .Write(" = ") .WriteStartNewObject("global::" + _tagHelperContext.TagHelperAttributeTypeName) - .WriteStringLiteral(attribute.Key) + .WriteStringLiteral(attribute.Name) .WriteParameterSeparator() .WriteStartNewObject("global::" + _tagHelperContext.EncodedHtmlStringTypeName) .WriteStringLiteral(plainText) .WriteEndMethodInvocation(endLine: false) + .WriteParameterSeparator() + .Write($"global::{typeof(HtmlAttributeValueStyle).FullName}.{attribute.ValueStyle}") .WriteEndMethodInvocation(); } } @@ -157,12 +165,13 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators.Visitors if (preAllocatedAttributeVariableName != null) { - chunk.Attributes[i] = new KeyValuePair( - attribute.Key, + chunk.Attributes[i] = new TagHelperAttributeTracker( + attribute.Name, new PreallocatedTagHelperAttributeChunk { AttributeVariableAccessor = preAllocatedAttributeVariableName - }); + }, + attribute.ValueStyle); } } } @@ -215,21 +224,25 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators.Visitors private struct TagHelperAttributeKey : IEquatable { - public TagHelperAttributeKey(string name, string value) + public TagHelperAttributeKey(string name, string value, HtmlAttributeValueStyle valueStyle) { Name = name; Value = value; + ValueStyle = valueStyle; } public string Name { get; } public string Value { get; } + public HtmlAttributeValueStyle ValueStyle { get; } + public override int GetHashCode() { var hashCodeCombiner = HashCodeCombiner.Start(); hashCodeCombiner.Add(Name, StringComparer.Ordinal); hashCodeCombiner.Add(Value, StringComparer.Ordinal); + hashCodeCombiner.Add(ValueStyle); return hashCodeCombiner.CombinedHash; } @@ -249,7 +262,8 @@ namespace Microsoft.AspNetCore.Razor.CodeGenerators.Visitors public bool Equals(TagHelperAttributeKey other) { return string.Equals(Name, other.Name, StringComparison.Ordinal) && - string.Equals(Value, other.Value, StringComparison.Ordinal); + string.Equals(Value, other.Value, StringComparison.Ordinal) && + ValueStyle == other.ValueStyle; } } } diff --git a/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperAttributeNode.cs b/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperAttributeNode.cs new file mode 100644 index 0000000000..22a69eb0b5 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperAttributeNode.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Razor.Parser.SyntaxTree; +using Microsoft.AspNetCore.Razor.TagHelpers; + +namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers +{ + public class TagHelperAttributeNode + { + public TagHelperAttributeNode(string name, SyntaxTreeNode value, HtmlAttributeValueStyle valueStyle) + { + Name = name; + Value = value; + ValueStyle = valueStyle; + } + + // Internal for testing + internal TagHelperAttributeNode(string name, SyntaxTreeNode value) + : this(name, value, HtmlAttributeValueStyle.DoubleQuotes) + { + } + + public string Name { get; } + + public SyntaxTreeNode Value { get; } + + public HtmlAttributeValueStyle ValueStyle { get; } + } +} diff --git a/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlock.cs b/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlock.cs index bb81f252c3..b43a2fd326 100644 --- a/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlock.cs +++ b/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlock.cs @@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers { TagName = source.TagName; Descriptors = source.Descriptors; - Attributes = new List>(source.Attributes); + Attributes = new List(source.Attributes); _start = source.Start; TagMode = source.TagMode; SourceStartTag = source.SourceStartTag; @@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers /// /// The HTML attributes. /// - public IList> Attributes { get; } + public IList Attributes { get; } /// public override SourceLocation Start diff --git a/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlockBuilder.cs b/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlockBuilder.cs index 6d71b3011e..3063c315ae 100644 --- a/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlockBuilder.cs +++ b/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlockBuilder.cs @@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers { TagName = original.TagName; Descriptors = original.Descriptors; - Attributes = new List>(original.Attributes); + Attributes = new List(original.Attributes); } /// @@ -41,14 +41,14 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers string tagName, TagMode tagMode, SourceLocation start, - IList> attributes, + IList attributes, IEnumerable descriptors) { TagName = tagName; TagMode = tagMode; Start = start; Descriptors = descriptors; - Attributes = new List>(attributes); + Attributes = new List(attributes); Type = BlockType.Tag; ChunkGenerator = new TagHelperChunkGenerator(descriptors); } @@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers internal TagHelperBlockBuilder( string tagName, TagMode tagMode, - IList> attributes, + IList attributes, IEnumerable children) { TagName = tagName; @@ -98,7 +98,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers /// /// The HTML attributes. /// - public IList> Attributes { get; } + public IList Attributes { get; } /// /// The HTML tag name. diff --git a/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlockRewriter.cs b/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlockRewriter.cs index 1659736df4..8fefd92e56 100644 --- a/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlockRewriter.cs +++ b/src/Microsoft.AspNetCore.Razor/Parser/TagHelpers/TagHelperBlockRewriter.cs @@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal return new TagHelperBlockBuilder(tagName, tagMode, start, attributes, descriptors); } - private static IList> GetTagAttributes( + private static IList GetTagAttributes( string tagName, bool validStructure, Block tagBlock, @@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal // contained TagHelperAttributeDescriptor's. descriptors = descriptors.Distinct(TypeBasedTagHelperDescriptorComparer.Default); - var attributes = new List>(); + var attributes = new List(); // We skip the first child "" or "/>". // The -2 accounts for both the start and end tags. If the tag does not have a valid structure then there's @@ -102,8 +102,12 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal result.AttributeName.Length); } - attributes.Add( - new KeyValuePair(result.AttributeName, result.AttributeValueNode)); + var attributeNode = new TagHelperAttributeNode( + result.AttributeName, + result.AttributeValueNode, + result.AttributeValueStyle); + + attributes.Add(attributeNode); } else { @@ -161,6 +165,10 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal var capturedAttributeValueStart = false; var attributeValueStartLocation = span.Start; + // Default to DoubleQuotes. We purposefully do not persist NoQuotes ValueStyle to stay consistent with the + // TryParseBlock() variation of attribute parsing. + var attributeValueStyle = HtmlAttributeValueStyle.DoubleQuotes; + // 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; @@ -229,6 +237,11 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal // Check for attribute start values, aka single or double quote if (i < htmlSymbols.Length && IsQuote(htmlSymbols[i])) { + if (htmlSymbols[i].Type == HtmlSymbolType.SingleQuote) + { + attributeValueStyle = HtmlAttributeValueStyle.SingleQuotes; + } + symbolStartLocation = htmlSymbols[i].Start; // If there's a start quote then there must be an end quote to be valid, skip it. @@ -290,8 +303,13 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal { attributeValue = CreateMarkupAttribute(builder, result.IsBoundNonStringAttribute); } + else + { + attributeValueStyle = HtmlAttributeValueStyle.Minimized; + } result.AttributeValueNode = attributeValue; + result.AttributeValueStyle = attributeValueStyle; return result; } @@ -347,6 +365,30 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal // Have a name now. Able to determine correct isBoundNonStringAttribute value. var result = CreateTryParseResult(name, descriptors); + var firstChild = builder.Children[0] as Span; + if (firstChild != null && firstChild.Symbols[0] is HtmlSymbol) + { + var htmlSymbol = firstChild.Symbols[firstChild.Symbols.Count - 1] as HtmlSymbol; + switch (htmlSymbol.Type) + { + // Treat NoQuotes and DoubleQuotes equivalently. We purposefully do not persist NoQuotes + // ValueStyles at code generation time to protect users from rendering dynamic content with spaces + // that can break attributes. + // Ex: where @value results in the test "hello world". + // This way, the above code would render . + case HtmlSymbolType.Equals: + case HtmlSymbolType.DoubleQuote: + result.AttributeValueStyle = HtmlAttributeValueStyle.DoubleQuotes; + break; + case HtmlSymbolType.SingleQuote: + result.AttributeValueStyle = HtmlAttributeValueStyle.SingleQuotes; + break; + default: + result.AttributeValueStyle = HtmlAttributeValueStyle.Minimized; + break; + } + } + // Remove first child i.e. foo=" builder.Children.RemoveAt(0); @@ -664,6 +706,8 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal public SyntaxTreeNode AttributeValueNode { get; set; } + public HtmlAttributeValueStyle AttributeValueStyle { get; set; } + public bool IsBoundAttribute { get; set; } public bool IsBoundNonStringAttribute { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor/TagHelpers/HtmlAttributeValueStyle.cs b/src/Microsoft.AspNetCore.Razor/TagHelpers/HtmlAttributeValueStyle.cs new file mode 100644 index 0000000000..7ac198567f --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor/TagHelpers/HtmlAttributeValueStyle.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.Razor.TagHelpers +{ + public enum HtmlAttributeValueStyle + { + DoubleQuotes, + SingleQuotes, + NoQuotes, + Minimized, + } +} diff --git a/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/CaseSensitiveTagHelperAttributeComparer.cs b/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/CaseSensitiveTagHelperAttributeComparer.cs index 9943d38e51..926252ff32 100644 --- a/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/CaseSensitiveTagHelperAttributeComparer.cs +++ b/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/CaseSensitiveTagHelperAttributeComparer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Razor.TagHelpers { @@ -25,13 +26,17 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers // Normal comparer (TagHelperAttribute.Equals()) doesn't care about the Name case, in tests we do. return attributeX != null && string.Equals(attributeX.Name, attributeY.Name, StringComparison.Ordinal) && - attributeX.Minimized == attributeY.Minimized && - (attributeX.Minimized || Equals(attributeX.Value, attributeY.Value)); + attributeX.ValueStyle == attributeY.ValueStyle && + (attributeX.ValueStyle == HtmlAttributeValueStyle.Minimized || Equals(attributeX.Value, attributeY.Value)); } public int GetHashCode(TagHelperAttribute attribute) { - return attribute.GetHashCode(); + var combiner = HashCodeCombiner.Start(); + combiner.Add(attribute.Name, StringComparer.Ordinal); + combiner.Add(attribute.GetHashCode()); + + return combiner.CombinedHash; } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperExecutionContextTest.cs b/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperExecutionContextTest.cs index d246b3556b..a06f7c28b6 100644 --- a/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperExecutionContextTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperExecutionContextTest.cs @@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers updatedCallCount++; return Task.FromResult(true); }; - executionContext.AddMinimizedHtmlAttribute("something"); + executionContext.AddHtmlAttribute(new TagHelperAttribute("something")); // Act - 1 executionContext.Reinitialize( @@ -80,7 +80,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers items: new Dictionary(), uniqueId: string.Empty, executeChildContentAsync: updatedExecuteChildContentAsync); - executionContext.AddMinimizedHtmlAttribute("Another attribute"); + executionContext.AddHtmlAttribute(new TagHelperAttribute("Another attribute")); // Assert - 1 var output = executionContext.Output; @@ -123,7 +123,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers endWritingScope); var updatedItems = new Dictionary(); var updatedUniqueId = "another unique id"; - executionContext.AddMinimizedHtmlAttribute("something"); + executionContext.AddHtmlAttribute(new TagHelperAttribute("something")); // Act executionContext.Reinitialize( @@ -132,7 +132,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers updatedItems, updatedUniqueId, executeChildContentAsync); - executionContext.AddMinimizedHtmlAttribute("Another attribute"); + executionContext.AddHtmlAttribute(new TagHelperAttribute("Another attribute")); // Assert var context = executionContext.Context; @@ -409,12 +409,12 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers var expectedAttributes = new TagHelperAttributeList { { "class", "btn" }, - { "foo", "bar" } }; + expectedAttributes.Add(new TagHelperAttribute("type", "text", HtmlAttributeValueStyle.SingleQuotes)); // Act - executionContext.AddHtmlAttribute("class", "btn"); - executionContext.AddHtmlAttribute("foo", "bar"); + executionContext.AddHtmlAttribute("class", "btn", HtmlAttributeValueStyle.DoubleQuotes); + executionContext.AddHtmlAttribute("type", "text", HtmlAttributeValueStyle.SingleQuotes); var output = executionContext.Output; // Assert @@ -425,7 +425,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers } [Fact] - public void AddMinimizedHtmlAttribute_MaintainsHtmlAttributes() + public void AddHtmlAttribute_MaintainsMinimizedHtmlAttributes() { // Arrange var executionContext = new TagHelperExecutionContext("input", tagMode: TagMode.StartTagOnly); @@ -436,8 +436,8 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers }; // Act - executionContext.AddMinimizedHtmlAttribute("checked"); - executionContext.AddMinimizedHtmlAttribute("visible"); + executionContext.AddHtmlAttribute(new TagHelperAttribute("checked")); + executionContext.AddHtmlAttribute(new TagHelperAttribute("visible")); var output = executionContext.Output; // Assert @@ -448,7 +448,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers } [Fact] - public void AddMinimizedHtmlAttribute_MaintainsHtmlAttributes_SomeMinimized() + public void AddHtmlAttribute_MaintainsHtmlAttributes_VariousStyles() { // Arrange var executionContext = new TagHelperExecutionContext("input", tagMode: TagMode.SelfClosing); @@ -457,14 +457,18 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers { "class", "btn" }, { "foo", "bar" } }; + expectedAttributes.Add(new TagHelperAttribute("valid", "true", HtmlAttributeValueStyle.NoQuotes)); + expectedAttributes.Add(new TagHelperAttribute("type", "text", HtmlAttributeValueStyle.SingleQuotes)); expectedAttributes.Add(new TagHelperAttribute(name: "checked")); expectedAttributes.Add(new TagHelperAttribute(name: "visible")); // Act - executionContext.AddHtmlAttribute("class", "btn"); - executionContext.AddHtmlAttribute("foo", "bar"); - executionContext.AddMinimizedHtmlAttribute("checked"); - executionContext.AddMinimizedHtmlAttribute("visible"); + executionContext.AddHtmlAttribute("class", "btn", HtmlAttributeValueStyle.DoubleQuotes); + executionContext.AddHtmlAttribute("foo", "bar", HtmlAttributeValueStyle.DoubleQuotes); + executionContext.AddHtmlAttribute("valid", "true", HtmlAttributeValueStyle.NoQuotes); + executionContext.AddHtmlAttribute("type", "text", HtmlAttributeValueStyle.SingleQuotes); + executionContext.AddHtmlAttribute(new TagHelperAttribute("checked")); + executionContext.AddHtmlAttribute(new TagHelperAttribute("visible")); var output = executionContext.Output; // Assert @@ -482,14 +486,14 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers var expectedAttributes = new TagHelperAttributeList { { "class", "btn" }, - { "something", true }, - { "foo", "bar" } }; + expectedAttributes.Add(new TagHelperAttribute("something", true, HtmlAttributeValueStyle.SingleQuotes)); + expectedAttributes.Add(new TagHelperAttribute("type", "text", HtmlAttributeValueStyle.NoQuotes)); // Act - executionContext.AddHtmlAttribute("class", "btn"); - executionContext.AddTagHelperAttribute("something", true); - executionContext.AddHtmlAttribute("foo", "bar"); + executionContext.AddHtmlAttribute("class", "btn", HtmlAttributeValueStyle.DoubleQuotes); + executionContext.AddTagHelperAttribute("something", true, HtmlAttributeValueStyle.SingleQuotes); + executionContext.AddHtmlAttribute("type", "text", HtmlAttributeValueStyle.NoQuotes); var context = executionContext.Context; // Assert diff --git a/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperRunnerTest.cs b/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperRunnerTest.cs index d318d8889b..af59c20ded 100644 --- a/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperRunnerTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperRunnerTest.cs @@ -124,7 +124,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers var tagHelper = new TagHelperContextTouchingTagHelper(); executionContext.Add(tagHelper); - executionContext.AddTagHelperAttribute("foo", true); + executionContext.AddTagHelperAttribute("foo", true, HtmlAttributeValueStyle.DoubleQuotes); // Act await runner.RunAsync(executionContext); @@ -162,7 +162,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers // Act executionContext.Add(executableTagHelper); - executionContext.AddHtmlAttribute("class", "btn"); + executionContext.AddHtmlAttribute("class", "btn", HtmlAttributeValueStyle.DoubleQuotes); await runner.RunAsync(executionContext); // Assert @@ -183,7 +183,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers // Act executionContext.Add(tagHelper); - executionContext.AddTagHelperAttribute("foo", true); + executionContext.AddTagHelperAttribute("foo", true, HtmlAttributeValueStyle.DoubleQuotes); await runner.RunAsync(executionContext); // Assert diff --git a/test/Microsoft.AspNetCore.Razor.Runtime.Test/TagHelpers/TagHelperOutputTest.cs b/test/Microsoft.AspNetCore.Razor.Runtime.Test/TagHelpers/TagHelperOutputTest.cs index 04c947137a..e114fb7f19 100644 --- a/test/Microsoft.AspNetCore.Razor.Runtime.Test/TagHelpers/TagHelperOutputTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Runtime.Test/TagHelpers/TagHelperOutputTest.cs @@ -478,6 +478,22 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers postElement: null), "Hello World!" }, + { + GetTagHelperOutput( + tagName: "p", + attributes: new TagHelperAttributeList() + { + { new TagHelperAttribute("test", "testVal", HtmlAttributeValueStyle.NoQuotes) }, + { new TagHelperAttribute("something", " spaced ", HtmlAttributeValueStyle.SingleQuotes) }, + }, + tagMode: TagMode.StartTagAndEndTag, + preElement: null, + preContent: null, + content: "Hello World!", + postContent: null, + postElement: null), + "Hello World!" + }, { GetTagHelperOutput( tagName: "p", @@ -531,7 +547,7 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers attributes: new TagHelperAttributeList() { new TagHelperAttribute("test"), - new TagHelperAttribute("last", "unminimized"), + new TagHelperAttribute("last", "unminimized", HtmlAttributeValueStyle.NoQuotes), }, tagMode: TagMode.StartTagAndEndTag, preElement: null, @@ -539,7 +555,7 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers content: "Hello World!", postContent: null, postElement: null), - "Hello World!" + "Hello World!" }, { GetTagHelperOutput( @@ -572,14 +588,17 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers { GetTagHelperOutput( tagName: "p", - attributes: new TagHelperAttributeList() { { "test", "testVal" } }, + attributes: new TagHelperAttributeList() + { + { new TagHelperAttribute("test", "testVal", HtmlAttributeValueStyle.SingleQuotes) } + }, tagMode: TagMode.StartTagOnly, preElement: null, preContent: null, content: "Hello World!", postContent: null, postElement: null), - "" + "" }, { GetTagHelperOutput( @@ -777,6 +796,21 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers postElement: null), "Before" }, + { + GetTagHelperOutput( + tagName: string.Empty, + attributes: new TagHelperAttributeList + { + { new TagHelperAttribute("test", "testVal", HtmlAttributeValueStyle.SingleQuotes) } + }, + tagMode: TagMode.StartTagOnly, + preElement: "Before", + preContent: null, + content: null, + postContent: null, + postElement: null), + "Before" + }, { GetTagHelperOutput( tagName: "custom", diff --git a/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs b/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs index 01a18aa0e2..0647192014 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs @@ -1307,12 +1307,20 @@ namespace Microsoft.AspNetCore.Razor.Test.Generator generatedLineIndex: 36, generatedCharacterOffsetIndex: 42, contentLength: 4), + BuildLineMapping( + documentAbsoluteIndex: 220, + documentLineIndex: 5, + documentCharacterOffsetIndex: 34, + generatedAbsoluteIndex: 2234, + generatedLineIndex: 45, + generatedCharacterOffsetIndex: 42, + contentLength: 4), BuildLineMapping( documentAbsoluteIndex: 41, documentLineIndex: 2, documentCharacterOffsetIndex: 8, - generatedAbsoluteIndex: 1962, - generatedLineIndex: 42, + generatedAbsoluteIndex: 2447, + generatedLineIndex: 51, generatedCharacterOffsetIndex: 33, contentLength: 1), } diff --git a/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingUnitTest.cs b/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingUnitTest.cs index 63b088fdcd..e69b435682 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingUnitTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingUnitTest.cs @@ -241,14 +241,14 @@ namespace Microsoft.AspNetCore.Razor.Test.Generator return new TagHelperChunk( tagName, tagMode: TagMode.StartTagAndEndTag, - attributes: new List>(), + attributes: new List(), descriptors: tagHelperDescriptors) { Association = new TagHelperBlock( new TagHelperBlockBuilder( tagName, tagMode: TagMode.StartTagAndEndTag, - attributes: new List>(), + attributes: new List(), children: Enumerable.Empty())), Children = new List(), }; diff --git a/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockFactory.cs b/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockFactory.cs index fa702bd055..8d65d4dbfe 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockFactory.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockFactory.cs @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework var builder = new TagHelperBlockBuilder( tagName, tagMode, - attributes: new List>(), + attributes: new List(), children: children) { Start = start, diff --git a/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockTypes.cs b/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockTypes.cs index 62bfbaa7ac..c64aeffd5c 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockTypes.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockTypes.cs @@ -132,18 +132,18 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework public class MarkupTagHelperBlock : TagHelperBlock { public MarkupTagHelperBlock(string tagName) - : this(tagName, tagMode: TagMode.StartTagAndEndTag, attributes: new List>()) + : this(tagName, tagMode: TagMode.StartTagAndEndTag, attributes: new List()) { } public MarkupTagHelperBlock(string tagName, TagMode tagMode) - : this(tagName, tagMode, new List>()) + : this(tagName, tagMode, new List()) { } public MarkupTagHelperBlock( string tagName, - IList> attributes) + IList attributes) : this(tagName, TagMode.StartTagAndEndTag, attributes, children: new SyntaxTreeNode[0]) { } @@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework public MarkupTagHelperBlock( string tagName, TagMode tagMode, - IList> attributes) + IList attributes) : this(tagName, tagMode, attributes, new SyntaxTreeNode[0]) { } @@ -160,19 +160,19 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework : this( tagName, TagMode.StartTagAndEndTag, - attributes: new List>(), + attributes: new List(), children: children) { } public MarkupTagHelperBlock(string tagName, TagMode tagMode, params SyntaxTreeNode[] children) - : this(tagName, tagMode, new List>(), children) + : this(tagName, tagMode, new List(), children) { } public MarkupTagHelperBlock( string tagName, - IList> attributes, + IList attributes, params SyntaxTreeNode[] children) : base(new TagHelperBlockBuilder( tagName, @@ -185,7 +185,7 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework public MarkupTagHelperBlock( string tagName, TagMode tagMode, - IList> attributes, + IList attributes, params SyntaxTreeNode[] children) : base(new TagHelperBlockBuilder(tagName, tagMode, attributes, children)) { diff --git a/test/Microsoft.AspNetCore.Razor.Test/Framework/ParserTestBase.cs b/test/Microsoft.AspNetCore.Razor.Test/Framework/ParserTestBase.cs index 8c05f43810..eb83a9926b 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/Framework/ParserTestBase.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/Framework/ParserTestBase.cs @@ -324,24 +324,30 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework } } - private static void EvaluateTagHelperAttribute(ErrorCollector collector, - KeyValuePair actual, - KeyValuePair expected) + private static void EvaluateTagHelperAttribute( + ErrorCollector collector, + TagHelperAttributeNode actual, + TagHelperAttributeNode expected) { - if (actual.Key != expected.Key) + if (actual.Name != expected.Name) { - collector.AddError("{0} - FAILED :: Attribute names do not match", expected.Key); + collector.AddError("{0} - FAILED :: Attribute names do not match", expected.Name); } else { - collector.AddMessage("{0} - PASSED :: Attribute names match", expected.Key); + collector.AddMessage("{0} - PASSED :: Attribute names match", expected.Name); } - if (actual.Value == null && expected.Value == null) + if (actual.ValueStyle != expected.ValueStyle) { - collector.AddMessage("{0} - PASSED :: Minimized attribute values match", expected.Key); + collector.AddError("{0} - FAILED :: Attribute value styles do not match", expected.ValueStyle.ToString()); } else + { + collector.AddMessage("{0} - PASSED :: Attribute value style match", expected.ValueStyle); + } + + if (actual.ValueStyle != HtmlAttributeValueStyle.Minimized) { EvaluateSyntaxTreeNode(collector, actual.Value, expected.Value); } @@ -435,7 +441,7 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework } while (actualAttributes.MoveNext()) { - collector.AddError("End of Attributes - FAILED :: Found Attribute: {0}", actualAttributes.Current.Key); + collector.AddError("End of Attributes - FAILED :: Found Attribute: {0}", actualAttributes.Current.Name); } } } diff --git a/test/Microsoft.AspNetCore.Razor.Test/TagHelpers/TagHelperBlockRewriterTest.cs b/test/Microsoft.AspNetCore.Razor.Test/TagHelpers/TagHelperBlockRewriterTest.cs index e3359b911b..9a159fe254 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/TagHelpers/TagHelperBlockRewriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/TagHelpers/TagHelperBlockRewriterTest.cs @@ -8,6 +8,7 @@ using System.Linq; using Microsoft.AspNetCore.Razor.Chunks.Generators; using Microsoft.AspNetCore.Razor.Parser; using Microsoft.AspNetCore.Razor.Parser.SyntaxTree; +using Microsoft.AspNetCore.Razor.Parser.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.Test.Framework; using Microsoft.AspNetCore.Razor.Test.TagHelpers; @@ -30,32 +31,33 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("ul", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair("[item]", factory.CodeMarkup("items")) + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("[item]", factory.CodeMarkup("items"), HtmlAttributeValueStyle.SingleQuotes) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("ul", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair("[(item)]", factory.CodeMarkup("items")) + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("[(item)]", factory.CodeMarkup("items"), HtmlAttributeValueStyle.SingleQuotes) })) }, { "Click Me", new MarkupBlock( new MarkupTagHelperBlock("button", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair( + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode( "(click)", - factory.CodeMarkup("doSomething()")) + factory.CodeMarkup("doSomething()"), + HtmlAttributeValueStyle.SingleQuotes) }, children: factory.Markup("Click Me"))) }, @@ -63,12 +65,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "Click Me", new MarkupBlock( new MarkupTagHelperBlock("button", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair( + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode( "(^click)", - factory.CodeMarkup("doSomething()")) + factory.CodeMarkup("doSomething()"), + HtmlAttributeValueStyle.SingleQuotes) }, children: factory.Markup("Click Me"))) }, @@ -76,30 +79,33 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("template", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair("*something", factory.Markup("value")) + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode( + "*something", + factory.Markup("value"), + HtmlAttributeValueStyle.SingleQuotes) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("div", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair("#localminimized", null) + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("#localminimized", null, HtmlAttributeValueStyle.Minimized) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("div", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair("#local", factory.Markup("value")) + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("#local", factory.Markup("value"), HtmlAttributeValueStyle.SingleQuotes) })) }, }; @@ -186,9 +192,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "input", TagMode.StartTagOnly, - attributes: new List> + attributes: new List { - new KeyValuePair("type", factory.Markup("text")) + new TagHelperAttributeNode("type", factory.Markup("text"), HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -203,9 +209,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "input", TagMode.StartTagOnly, - attributes: new List> + attributes: new List { - new KeyValuePair("type", factory.Markup("text")) + new TagHelperAttributeNode("type", factory.Markup("text"), HtmlAttributeValueStyle.SingleQuotes) }), new MarkupTagHelperBlock("input", TagMode.StartTagOnly)) }, @@ -272,9 +278,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "input", TagMode.StartTagOnly, - attributes: new List> + attributes: new List { - new KeyValuePair("type", factory.Markup("text")) + new TagHelperAttributeNode("type", factory.Markup("text"), HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -293,9 +299,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "input", TagMode.StartTagAndEndTag, - attributes: new List> + attributes: new List { - new KeyValuePair("type", factory.Markup("text")) + new TagHelperAttributeNode("type", factory.Markup("text"), HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -380,11 +386,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", - new MarkupBlock(factory.Markup("false"), factory.Markup(" "))) + new MarkupBlock(factory.Markup("false"), factory.Markup(" ")), + HtmlAttributeValueStyle.SingleQuotes) })), new [] { @@ -440,13 +448,14 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", new MarkupBlock( factory.Markup("false"), - factory.Markup(" > + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", - factory.Markup("false")) + factory.Markup("false"), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -490,9 +500,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", factory.Markup("false'")) })), @@ -512,9 +522,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", new MarkupBlock( factory.Markup("false'"), @@ -536,10 +546,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("foo", null), - new KeyValuePair("bar", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("bar", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -562,9 +572,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -578,9 +588,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -594,12 +604,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -622,12 +632,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null), + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), })), new RazorError[0] }, @@ -657,9 +667,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( @@ -672,7 +682,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -686,9 +697,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", createInvalidDoBlock(string.Empty)) })), @@ -711,9 +722,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", createInvalidDoBlock("\">")) + new TagHelperAttributeNode("class", createInvalidDoBlock("\">")) })), new [] { @@ -762,9 +773,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("some")) + new TagHelperAttributeNode("class", factory.Markup("some")) })), new [] { @@ -972,9 +983,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")) + new TagHelperAttributeNode("age", factory.CodeMarkup("12")) })) }, { @@ -982,9 +993,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")) })) @@ -994,9 +1005,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1013,9 +1024,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1036,9 +1047,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("name", factory.Markup("John")) + new TagHelperAttributeNode("name", factory.Markup("John")) })) }, { @@ -1046,9 +1057,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1058,9 +1069,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( factory.CodeMarkup("1"), @@ -1078,7 +1089,7 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.NonWhiteSpace))), factory.CodeMarkup(" +"), factory.CodeMarkup(" 2"))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", new MarkupBlock( factory.CodeMarkup("(bool)"), @@ -1110,8 +1121,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory .Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))) - )) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -1119,13 +1130,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1135,13 +1146,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( factory.Markup("Time:"), @@ -1158,13 +1169,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( new MarkupBlock( @@ -1180,9 +1191,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1207,10 +1218,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.None) .As(SpanKind.Code) .With(new MarkupChunkGenerator()))))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1280,10 +1291,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode( "dynamic", new MarkupBlock( new MarkupBlock( @@ -1296,8 +1307,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))), - new KeyValuePair("style", factory.Markup("color:red;")) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }, new MarkupTagHelperBlock("strong")), blockFactory.MarkupTagBlock("")), @@ -1353,15 +1365,15 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "Hello World", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("foo")) + new TagHelperAttributeNode("class", factory.Markup("foo")) }, factory.Markup("Hello "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }, factory.Markup("World")))), new RazorError[] @@ -1397,10 +1409,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup(" foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup(" foo")), + new TagHelperAttributeNode( "style", new MarkupBlock( factory.Markup(" color"), @@ -1415,10 +1427,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "Hello World", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup(" foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup(" foo")), + new TagHelperAttributeNode( "style", new MarkupBlock( factory.Markup(" color"), @@ -1434,18 +1446,18 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "Hello World", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup(" foo"), factory.Markup(" "))) }, factory.Markup("Hello")), factory.Markup(" "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "style", new MarkupBlock(factory.Markup(" color:red;"), factory.Markup(" "))) }, @@ -1512,10 +1524,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)), - new KeyValuePair("style", dateTimeNow(32)) + new TagHelperAttributeNode("class", dateTimeNow(10)), + new TagHelperAttributeNode("style", dateTimeNow(32), HtmlAttributeValueStyle.SingleQuotes) })) }; yield return new object[] @@ -1523,10 +1535,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, doWhileString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", doWhile(10)), - new KeyValuePair("style", doWhile(83)) + new TagHelperAttributeNode("class", doWhile(10)), + new TagHelperAttributeNode("style", doWhile(83), HtmlAttributeValueStyle.SingleQuotes) })) }; @@ -1536,10 +1548,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)), - new KeyValuePair("style", dateTimeNow(32)) + new TagHelperAttributeNode("class", dateTimeNow(10)), + new TagHelperAttributeNode("style", dateTimeNow(32), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("Hello World"))) }; @@ -1548,10 +1560,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, doWhileString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", doWhile(10)), - new KeyValuePair("style", doWhile(83)) + new TagHelperAttributeNode("class", doWhile(10)), + new TagHelperAttributeNode("style", doWhile(83), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("Hello World"))) }; @@ -1562,16 +1574,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)) + new TagHelperAttributeNode("class", dateTimeNow(10)) }, factory.Markup("Hello")), factory.Markup(" "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("style", dateTimeNow(45)) + new TagHelperAttributeNode("style", dateTimeNow(45), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("World"))) }; @@ -1580,16 +1592,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, doWhileString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", doWhile(10)) + new TagHelperAttributeNode("class", doWhile(10)) }, factory.Markup("Hello")), factory.Markup(" "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("style", doWhile(96)) + new TagHelperAttributeNode("style", doWhile(96), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("World"))) }; @@ -1601,10 +1613,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)), - new KeyValuePair("style", dateTimeNow(32)) + new TagHelperAttributeNode("class", dateTimeNow(10)), + new TagHelperAttributeNode("style", dateTimeNow(32), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("Hello World "), new MarkupTagBlock( @@ -1894,31 +1906,32 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", new MarkupBlock()) + new TagHelperAttributeNode("class", new MarkupBlock()) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", new MarkupBlock()) + new TagHelperAttributeNode("class", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { // 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. - new KeyValuePair( + new TagHelperAttributeNode( "class", - factory.Markup("").With(SpanChunkGenerator.Null)), + factory.Markup("").With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), })) }, { @@ -1926,13 +1939,14 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class1", new MarkupBlock()), - new KeyValuePair( + new TagHelperAttributeNode("class1", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode( "class2", - factory.Markup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("class3", new MarkupBlock()), + factory.Markup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("class3", new MarkupBlock()), })) }, { @@ -1940,13 +1954,14 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class1", new MarkupBlock()), - new KeyValuePair("class2", new MarkupBlock()), - new KeyValuePair( + new TagHelperAttributeNode("class1", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("class2", new MarkupBlock()), + new TagHelperAttributeNode( "class3", - factory.Markup(string.Empty).With(SpanChunkGenerator.Null)), + factory.Markup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), })) }, }; @@ -1979,9 +1994,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", new MarkupBlock()) + new TagHelperAttributeNode("bound", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -1996,9 +2011,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup(" true")) + new TagHelperAttributeNode("bound", factory.CodeMarkup(" true"), HtmlAttributeValueStyle.SingleQuotes) })), new RazorError[0] }, @@ -2008,9 +2023,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup(" ")) + new TagHelperAttributeNode("bound", factory.CodeMarkup(" "), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2025,10 +2040,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", new MarkupBlock()), - new KeyValuePair("bound", new MarkupBlock()) + new TagHelperAttributeNode("bound", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("bound", new MarkupBlock()) })), new[] { @@ -2046,10 +2061,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup(" ")), - new KeyValuePair("bound", factory.CodeMarkup(" ")) + new TagHelperAttributeNode("bound", factory.CodeMarkup(" "), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("bound", factory.CodeMarkup(" ")) })), new[] { @@ -2067,12 +2082,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup("true")), - new KeyValuePair( + new TagHelperAttributeNode("bound", factory.CodeMarkup("true"), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes) })), new[] { @@ -2087,12 +2103,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("name", new MarkupBlock()) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("name", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2107,12 +2124,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("name", factory.Markup(" ")) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("name", factory.Markup(" "), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2127,16 +2145,18 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup("true")), - new KeyValuePair("name", factory.Markup("john")), - new KeyValuePair( + new TagHelperAttributeNode("bound", factory.CodeMarkup("true"), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("name", factory.Markup("john"), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair( + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode( "name", - factory.Markup(string.Empty).With(SpanChunkGenerator.Null)) + factory.Markup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes) })), new[] { @@ -2151,9 +2171,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("BouND", new MarkupBlock()) + new TagHelperAttributeNode("BouND", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2168,10 +2188,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("BOUND", new MarkupBlock()), - new KeyValuePair("bOUnd", new MarkupBlock()) + new TagHelperAttributeNode("BOUND", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("bOUnd", new MarkupBlock()) })), new[] { @@ -2188,12 +2208,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock( "myth", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "BOUND", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("nAMe", factory.Markup("john")) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("nAMe", factory.Markup("john"), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2208,10 +2229,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { { - new KeyValuePair( + new TagHelperAttributeNode( "bound", new MarkupBlock( new MarkupBlock( @@ -2223,7 +2244,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.Code("true") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) .Accepts(AcceptedCharacters.NonWhiteSpace))), - factory.CodeMarkup(" "))) + factory.CodeMarkup(" ")), + HtmlAttributeValueStyle.SingleQuotes) } })), new RazorError[0] @@ -2234,10 +2256,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { { - new KeyValuePair( + new TagHelperAttributeNode( "bound", new MarkupBlock( new MarkupBlock( @@ -2255,7 +2277,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.None) .As(SpanKind.Code) .With(new MarkupChunkGenerator()))), - factory.CodeMarkup(" "))) + factory.CodeMarkup(" ")), + HtmlAttributeValueStyle.SingleQuotes) } })), new RazorError[0] @@ -2350,10 +2373,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("script", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) })) }; yield return new object[] @@ -2363,10 +2386,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock("p", factory.Markup("Hello "), new MarkupTagHelperBlock("script", - new List> + new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }), factory.Markup(" World"))) }; @@ -2377,16 +2400,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock("p", factory.Markup("Hello "), new MarkupTagHelperBlock("script", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( factory.Markup("@").Accepts(AcceptedCharacters.None), factory.Markup("@").With(SpanChunkGenerator.Null).Accepts(AcceptedCharacters.None)), factory.Markup("foo@bar.com"))), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }), factory.Markup(" World"))) }; @@ -2414,10 +2437,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) })) }; yield return new object[] @@ -2433,10 +2456,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode( "style", factory.Markup("color:red;")) }), @@ -2450,16 +2473,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.Markup("Hello"), new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List
Hello World!
" + "
" }, { GetTagHelperOutput( @@ -777,6 +796,21 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers postElement: null), "Before" }, + { + GetTagHelperOutput( + tagName: string.Empty, + attributes: new TagHelperAttributeList + { + { new TagHelperAttribute("test", "testVal", HtmlAttributeValueStyle.SingleQuotes) } + }, + tagMode: TagMode.StartTagOnly, + preElement: "Before", + preContent: null, + content: null, + postContent: null, + postElement: null), + "Before" + }, { GetTagHelperOutput( tagName: "custom", diff --git a/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs b/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs index 01a18aa0e2..0647192014 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs @@ -1307,12 +1307,20 @@ namespace Microsoft.AspNetCore.Razor.Test.Generator generatedLineIndex: 36, generatedCharacterOffsetIndex: 42, contentLength: 4), + BuildLineMapping( + documentAbsoluteIndex: 220, + documentLineIndex: 5, + documentCharacterOffsetIndex: 34, + generatedAbsoluteIndex: 2234, + generatedLineIndex: 45, + generatedCharacterOffsetIndex: 42, + contentLength: 4), BuildLineMapping( documentAbsoluteIndex: 41, documentLineIndex: 2, documentCharacterOffsetIndex: 8, - generatedAbsoluteIndex: 1962, - generatedLineIndex: 42, + generatedAbsoluteIndex: 2447, + generatedLineIndex: 51, generatedCharacterOffsetIndex: 33, contentLength: 1), } diff --git a/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingUnitTest.cs b/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingUnitTest.cs index 63b088fdcd..e69b435682 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingUnitTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/CodeGenerators/CSharpTagHelperRenderingUnitTest.cs @@ -241,14 +241,14 @@ namespace Microsoft.AspNetCore.Razor.Test.Generator return new TagHelperChunk( tagName, tagMode: TagMode.StartTagAndEndTag, - attributes: new List>(), + attributes: new List(), descriptors: tagHelperDescriptors) { Association = new TagHelperBlock( new TagHelperBlockBuilder( tagName, tagMode: TagMode.StartTagAndEndTag, - attributes: new List>(), + attributes: new List(), children: Enumerable.Empty())), Children = new List(), }; diff --git a/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockFactory.cs b/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockFactory.cs index fa702bd055..8d65d4dbfe 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockFactory.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockFactory.cs @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework var builder = new TagHelperBlockBuilder( tagName, tagMode, - attributes: new List>(), + attributes: new List(), children: children) { Start = start, diff --git a/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockTypes.cs b/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockTypes.cs index 62bfbaa7ac..c64aeffd5c 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockTypes.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/Framework/BlockTypes.cs @@ -132,18 +132,18 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework public class MarkupTagHelperBlock : TagHelperBlock { public MarkupTagHelperBlock(string tagName) - : this(tagName, tagMode: TagMode.StartTagAndEndTag, attributes: new List>()) + : this(tagName, tagMode: TagMode.StartTagAndEndTag, attributes: new List()) { } public MarkupTagHelperBlock(string tagName, TagMode tagMode) - : this(tagName, tagMode, new List>()) + : this(tagName, tagMode, new List()) { } public MarkupTagHelperBlock( string tagName, - IList> attributes) + IList attributes) : this(tagName, TagMode.StartTagAndEndTag, attributes, children: new SyntaxTreeNode[0]) { } @@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework public MarkupTagHelperBlock( string tagName, TagMode tagMode, - IList> attributes) + IList attributes) : this(tagName, tagMode, attributes, new SyntaxTreeNode[0]) { } @@ -160,19 +160,19 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework : this( tagName, TagMode.StartTagAndEndTag, - attributes: new List>(), + attributes: new List(), children: children) { } public MarkupTagHelperBlock(string tagName, TagMode tagMode, params SyntaxTreeNode[] children) - : this(tagName, tagMode, new List>(), children) + : this(tagName, tagMode, new List(), children) { } public MarkupTagHelperBlock( string tagName, - IList> attributes, + IList attributes, params SyntaxTreeNode[] children) : base(new TagHelperBlockBuilder( tagName, @@ -185,7 +185,7 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework public MarkupTagHelperBlock( string tagName, TagMode tagMode, - IList> attributes, + IList attributes, params SyntaxTreeNode[] children) : base(new TagHelperBlockBuilder(tagName, tagMode, attributes, children)) { diff --git a/test/Microsoft.AspNetCore.Razor.Test/Framework/ParserTestBase.cs b/test/Microsoft.AspNetCore.Razor.Test/Framework/ParserTestBase.cs index 8c05f43810..eb83a9926b 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/Framework/ParserTestBase.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/Framework/ParserTestBase.cs @@ -324,24 +324,30 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework } } - private static void EvaluateTagHelperAttribute(ErrorCollector collector, - KeyValuePair actual, - KeyValuePair expected) + private static void EvaluateTagHelperAttribute( + ErrorCollector collector, + TagHelperAttributeNode actual, + TagHelperAttributeNode expected) { - if (actual.Key != expected.Key) + if (actual.Name != expected.Name) { - collector.AddError("{0} - FAILED :: Attribute names do not match", expected.Key); + collector.AddError("{0} - FAILED :: Attribute names do not match", expected.Name); } else { - collector.AddMessage("{0} - PASSED :: Attribute names match", expected.Key); + collector.AddMessage("{0} - PASSED :: Attribute names match", expected.Name); } - if (actual.Value == null && expected.Value == null) + if (actual.ValueStyle != expected.ValueStyle) { - collector.AddMessage("{0} - PASSED :: Minimized attribute values match", expected.Key); + collector.AddError("{0} - FAILED :: Attribute value styles do not match", expected.ValueStyle.ToString()); } else + { + collector.AddMessage("{0} - PASSED :: Attribute value style match", expected.ValueStyle); + } + + if (actual.ValueStyle != HtmlAttributeValueStyle.Minimized) { EvaluateSyntaxTreeNode(collector, actual.Value, expected.Value); } @@ -435,7 +441,7 @@ namespace Microsoft.AspNetCore.Razor.Test.Framework } while (actualAttributes.MoveNext()) { - collector.AddError("End of Attributes - FAILED :: Found Attribute: {0}", actualAttributes.Current.Key); + collector.AddError("End of Attributes - FAILED :: Found Attribute: {0}", actualAttributes.Current.Name); } } } diff --git a/test/Microsoft.AspNetCore.Razor.Test/TagHelpers/TagHelperBlockRewriterTest.cs b/test/Microsoft.AspNetCore.Razor.Test/TagHelpers/TagHelperBlockRewriterTest.cs index e3359b911b..9a159fe254 100644 --- a/test/Microsoft.AspNetCore.Razor.Test/TagHelpers/TagHelperBlockRewriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Test/TagHelpers/TagHelperBlockRewriterTest.cs @@ -8,6 +8,7 @@ using System.Linq; using Microsoft.AspNetCore.Razor.Chunks.Generators; using Microsoft.AspNetCore.Razor.Parser; using Microsoft.AspNetCore.Razor.Parser.SyntaxTree; +using Microsoft.AspNetCore.Razor.Parser.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.Test.Framework; using Microsoft.AspNetCore.Razor.Test.TagHelpers; @@ -30,32 +31,33 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("ul", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair("[item]", factory.CodeMarkup("items")) + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("[item]", factory.CodeMarkup("items"), HtmlAttributeValueStyle.SingleQuotes) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("ul", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair("[(item)]", factory.CodeMarkup("items")) + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("[(item)]", factory.CodeMarkup("items"), HtmlAttributeValueStyle.SingleQuotes) })) }, { "Click Me", new MarkupBlock( new MarkupTagHelperBlock("button", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair( + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode( "(click)", - factory.CodeMarkup("doSomething()")) + factory.CodeMarkup("doSomething()"), + HtmlAttributeValueStyle.SingleQuotes) }, children: factory.Markup("Click Me"))) }, @@ -63,12 +65,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "Click Me", new MarkupBlock( new MarkupTagHelperBlock("button", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair( + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode( "(^click)", - factory.CodeMarkup("doSomething()")) + factory.CodeMarkup("doSomething()"), + HtmlAttributeValueStyle.SingleQuotes) }, children: factory.Markup("Click Me"))) }, @@ -76,30 +79,33 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("template", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair("*something", factory.Markup("value")) + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode( + "*something", + factory.Markup("value"), + HtmlAttributeValueStyle.SingleQuotes) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("div", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair("#localminimized", null) + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("#localminimized", null, HtmlAttributeValueStyle.Minimized) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("div", - attributes: new List> + attributes: new List { - new KeyValuePair("bound", null), - new KeyValuePair("#local", factory.Markup("value")) + new TagHelperAttributeNode("bound", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("#local", factory.Markup("value"), HtmlAttributeValueStyle.SingleQuotes) })) }, }; @@ -186,9 +192,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "input", TagMode.StartTagOnly, - attributes: new List> + attributes: new List { - new KeyValuePair("type", factory.Markup("text")) + new TagHelperAttributeNode("type", factory.Markup("text"), HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -203,9 +209,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "input", TagMode.StartTagOnly, - attributes: new List> + attributes: new List { - new KeyValuePair("type", factory.Markup("text")) + new TagHelperAttributeNode("type", factory.Markup("text"), HtmlAttributeValueStyle.SingleQuotes) }), new MarkupTagHelperBlock("input", TagMode.StartTagOnly)) }, @@ -272,9 +278,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "input", TagMode.StartTagOnly, - attributes: new List> + attributes: new List { - new KeyValuePair("type", factory.Markup("text")) + new TagHelperAttributeNode("type", factory.Markup("text"), HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -293,9 +299,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "input", TagMode.StartTagAndEndTag, - attributes: new List> + attributes: new List { - new KeyValuePair("type", factory.Markup("text")) + new TagHelperAttributeNode("type", factory.Markup("text"), HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -380,11 +386,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", - new MarkupBlock(factory.Markup("false"), factory.Markup(" "))) + new MarkupBlock(factory.Markup("false"), factory.Markup(" ")), + HtmlAttributeValueStyle.SingleQuotes) })), new [] { @@ -440,13 +448,14 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", new MarkupBlock( factory.Markup("false"), - factory.Markup(" > + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", - factory.Markup("false")) + factory.Markup("false"), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -490,9 +500,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", factory.Markup("false'")) })), @@ -512,9 +522,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", new MarkupBlock( factory.Markup("false'"), @@ -536,10 +546,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("foo", null), - new KeyValuePair("bar", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("bar", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -562,9 +572,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -578,9 +588,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -594,12 +604,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -622,12 +632,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null), + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), })), new RazorError[0] }, @@ -657,9 +667,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( @@ -672,7 +682,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -686,9 +697,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", createInvalidDoBlock(string.Empty)) })), @@ -711,9 +722,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", createInvalidDoBlock("\">")) + new TagHelperAttributeNode("class", createInvalidDoBlock("\">")) })), new [] { @@ -762,9 +773,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("some")) + new TagHelperAttributeNode("class", factory.Markup("some")) })), new [] { @@ -972,9 +983,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")) + new TagHelperAttributeNode("age", factory.CodeMarkup("12")) })) }, { @@ -982,9 +993,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")) })) @@ -994,9 +1005,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1013,9 +1024,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1036,9 +1047,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("name", factory.Markup("John")) + new TagHelperAttributeNode("name", factory.Markup("John")) })) }, { @@ -1046,9 +1057,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1058,9 +1069,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( factory.CodeMarkup("1"), @@ -1078,7 +1089,7 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.NonWhiteSpace))), factory.CodeMarkup(" +"), factory.CodeMarkup(" 2"))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", new MarkupBlock( factory.CodeMarkup("(bool)"), @@ -1110,8 +1121,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory .Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))) - )) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -1119,13 +1130,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1135,13 +1146,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( factory.Markup("Time:"), @@ -1158,13 +1169,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( new MarkupBlock( @@ -1180,9 +1191,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1207,10 +1218,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.None) .As(SpanKind.Code) .With(new MarkupChunkGenerator()))))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1280,10 +1291,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode( "dynamic", new MarkupBlock( new MarkupBlock( @@ -1296,8 +1307,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))), - new KeyValuePair("style", factory.Markup("color:red;")) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }, new MarkupTagHelperBlock("strong")), blockFactory.MarkupTagBlock("")), @@ -1353,15 +1365,15 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "Hello World", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("foo")) + new TagHelperAttributeNode("class", factory.Markup("foo")) }, factory.Markup("Hello "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }, factory.Markup("World")))), new RazorError[] @@ -1397,10 +1409,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup(" foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup(" foo")), + new TagHelperAttributeNode( "style", new MarkupBlock( factory.Markup(" color"), @@ -1415,10 +1427,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "Hello World", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup(" foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup(" foo")), + new TagHelperAttributeNode( "style", new MarkupBlock( factory.Markup(" color"), @@ -1434,18 +1446,18 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "Hello World", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup(" foo"), factory.Markup(" "))) }, factory.Markup("Hello")), factory.Markup(" "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "style", new MarkupBlock(factory.Markup(" color:red;"), factory.Markup(" "))) }, @@ -1512,10 +1524,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)), - new KeyValuePair("style", dateTimeNow(32)) + new TagHelperAttributeNode("class", dateTimeNow(10)), + new TagHelperAttributeNode("style", dateTimeNow(32), HtmlAttributeValueStyle.SingleQuotes) })) }; yield return new object[] @@ -1523,10 +1535,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, doWhileString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", doWhile(10)), - new KeyValuePair("style", doWhile(83)) + new TagHelperAttributeNode("class", doWhile(10)), + new TagHelperAttributeNode("style", doWhile(83), HtmlAttributeValueStyle.SingleQuotes) })) }; @@ -1536,10 +1548,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)), - new KeyValuePair("style", dateTimeNow(32)) + new TagHelperAttributeNode("class", dateTimeNow(10)), + new TagHelperAttributeNode("style", dateTimeNow(32), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("Hello World"))) }; @@ -1548,10 +1560,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, doWhileString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", doWhile(10)), - new KeyValuePair("style", doWhile(83)) + new TagHelperAttributeNode("class", doWhile(10)), + new TagHelperAttributeNode("style", doWhile(83), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("Hello World"))) }; @@ -1562,16 +1574,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)) + new TagHelperAttributeNode("class", dateTimeNow(10)) }, factory.Markup("Hello")), factory.Markup(" "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("style", dateTimeNow(45)) + new TagHelperAttributeNode("style", dateTimeNow(45), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("World"))) }; @@ -1580,16 +1592,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, doWhileString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", doWhile(10)) + new TagHelperAttributeNode("class", doWhile(10)) }, factory.Markup("Hello")), factory.Markup(" "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("style", doWhile(96)) + new TagHelperAttributeNode("style", doWhile(96), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("World"))) }; @@ -1601,10 +1613,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)), - new KeyValuePair("style", dateTimeNow(32)) + new TagHelperAttributeNode("class", dateTimeNow(10)), + new TagHelperAttributeNode("style", dateTimeNow(32), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("Hello World "), new MarkupTagBlock( @@ -1894,31 +1906,32 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", new MarkupBlock()) + new TagHelperAttributeNode("class", new MarkupBlock()) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", new MarkupBlock()) + new TagHelperAttributeNode("class", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { // 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. - new KeyValuePair( + new TagHelperAttributeNode( "class", - factory.Markup("").With(SpanChunkGenerator.Null)), + factory.Markup("").With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), })) }, { @@ -1926,13 +1939,14 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class1", new MarkupBlock()), - new KeyValuePair( + new TagHelperAttributeNode("class1", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode( "class2", - factory.Markup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("class3", new MarkupBlock()), + factory.Markup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("class3", new MarkupBlock()), })) }, { @@ -1940,13 +1954,14 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class1", new MarkupBlock()), - new KeyValuePair("class2", new MarkupBlock()), - new KeyValuePair( + new TagHelperAttributeNode("class1", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("class2", new MarkupBlock()), + new TagHelperAttributeNode( "class3", - factory.Markup(string.Empty).With(SpanChunkGenerator.Null)), + factory.Markup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), })) }, }; @@ -1979,9 +1994,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", new MarkupBlock()) + new TagHelperAttributeNode("bound", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -1996,9 +2011,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup(" true")) + new TagHelperAttributeNode("bound", factory.CodeMarkup(" true"), HtmlAttributeValueStyle.SingleQuotes) })), new RazorError[0] }, @@ -2008,9 +2023,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup(" ")) + new TagHelperAttributeNode("bound", factory.CodeMarkup(" "), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2025,10 +2040,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", new MarkupBlock()), - new KeyValuePair("bound", new MarkupBlock()) + new TagHelperAttributeNode("bound", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("bound", new MarkupBlock()) })), new[] { @@ -2046,10 +2061,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup(" ")), - new KeyValuePair("bound", factory.CodeMarkup(" ")) + new TagHelperAttributeNode("bound", factory.CodeMarkup(" "), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("bound", factory.CodeMarkup(" ")) })), new[] { @@ -2067,12 +2082,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup("true")), - new KeyValuePair( + new TagHelperAttributeNode("bound", factory.CodeMarkup("true"), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes) })), new[] { @@ -2087,12 +2103,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("name", new MarkupBlock()) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("name", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2107,12 +2124,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("name", factory.Markup(" ")) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("name", factory.Markup(" "), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2127,16 +2145,18 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup("true")), - new KeyValuePair("name", factory.Markup("john")), - new KeyValuePair( + new TagHelperAttributeNode("bound", factory.CodeMarkup("true"), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("name", factory.Markup("john"), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair( + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode( "name", - factory.Markup(string.Empty).With(SpanChunkGenerator.Null)) + factory.Markup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes) })), new[] { @@ -2151,9 +2171,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("BouND", new MarkupBlock()) + new TagHelperAttributeNode("BouND", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2168,10 +2188,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("BOUND", new MarkupBlock()), - new KeyValuePair("bOUnd", new MarkupBlock()) + new TagHelperAttributeNode("BOUND", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("bOUnd", new MarkupBlock()) })), new[] { @@ -2188,12 +2208,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock( "myth", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "BOUND", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("nAMe", factory.Markup("john")) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("nAMe", factory.Markup("john"), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2208,10 +2229,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { { - new KeyValuePair( + new TagHelperAttributeNode( "bound", new MarkupBlock( new MarkupBlock( @@ -2223,7 +2244,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.Code("true") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) .Accepts(AcceptedCharacters.NonWhiteSpace))), - factory.CodeMarkup(" "))) + factory.CodeMarkup(" ")), + HtmlAttributeValueStyle.SingleQuotes) } })), new RazorError[0] @@ -2234,10 +2256,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { { - new KeyValuePair( + new TagHelperAttributeNode( "bound", new MarkupBlock( new MarkupBlock( @@ -2255,7 +2277,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.None) .As(SpanKind.Code) .With(new MarkupChunkGenerator()))), - factory.CodeMarkup(" "))) + factory.CodeMarkup(" ")), + HtmlAttributeValueStyle.SingleQuotes) } })), new RazorError[0] @@ -2350,10 +2373,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("script", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) })) }; yield return new object[] @@ -2363,10 +2386,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock("p", factory.Markup("Hello "), new MarkupTagHelperBlock("script", - new List> + new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }), factory.Markup(" World"))) }; @@ -2377,16 +2400,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock("p", factory.Markup("Hello "), new MarkupTagHelperBlock("script", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( factory.Markup("@").Accepts(AcceptedCharacters.None), factory.Markup("@").With(SpanChunkGenerator.Null).Accepts(AcceptedCharacters.None)), factory.Markup("foo@bar.com"))), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }), factory.Markup(" World"))) }; @@ -2414,10 +2437,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) })) }; yield return new object[] @@ -2433,10 +2456,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode( "style", factory.Markup("color:red;")) }), @@ -2450,16 +2473,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.Markup("Hello"), new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List
", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", - new MarkupBlock(factory.Markup("false"), factory.Markup(" "))) + new MarkupBlock(factory.Markup("false"), factory.Markup(" ")), + HtmlAttributeValueStyle.SingleQuotes) })), new [] { @@ -440,13 +448,14 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", new MarkupBlock( factory.Markup("false"), - factory.Markup(" > + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", - factory.Markup("false")) + factory.Markup("false"), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -490,9 +500,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", factory.Markup("false'")) })), @@ -512,9 +522,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", new MarkupBlock( factory.Markup("false'"), @@ -536,10 +546,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("foo", null), - new KeyValuePair("bar", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("bar", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -562,9 +572,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -578,9 +588,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -594,12 +604,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -622,12 +632,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null), + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), })), new RazorError[0] }, @@ -657,9 +667,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( @@ -672,7 +682,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -686,9 +697,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", createInvalidDoBlock(string.Empty)) })), @@ -711,9 +722,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", createInvalidDoBlock("\">")) + new TagHelperAttributeNode("class", createInvalidDoBlock("\">")) })), new [] { @@ -762,9 +773,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("some")) + new TagHelperAttributeNode("class", factory.Markup("some")) })), new [] { @@ -972,9 +983,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")) + new TagHelperAttributeNode("age", factory.CodeMarkup("12")) })) }, { @@ -982,9 +993,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")) })) @@ -994,9 +1005,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1013,9 +1024,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1036,9 +1047,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("name", factory.Markup("John")) + new TagHelperAttributeNode("name", factory.Markup("John")) })) }, { @@ -1046,9 +1057,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1058,9 +1069,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( factory.CodeMarkup("1"), @@ -1078,7 +1089,7 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.NonWhiteSpace))), factory.CodeMarkup(" +"), factory.CodeMarkup(" 2"))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", new MarkupBlock( factory.CodeMarkup("(bool)"), @@ -1110,8 +1121,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory .Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))) - )) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -1119,13 +1130,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1135,13 +1146,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( factory.Markup("Time:"), @@ -1158,13 +1169,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( new MarkupBlock( @@ -1180,9 +1191,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1207,10 +1218,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.None) .As(SpanKind.Code) .With(new MarkupChunkGenerator()))))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1280,10 +1291,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode( "dynamic", new MarkupBlock( new MarkupBlock( @@ -1296,8 +1307,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))), - new KeyValuePair("style", factory.Markup("color:red;")) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }, new MarkupTagHelperBlock("strong")), blockFactory.MarkupTagBlock("")), @@ -1353,15 +1365,15 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "Hello World", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("foo")) + new TagHelperAttributeNode("class", factory.Markup("foo")) }, factory.Markup("Hello "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }, factory.Markup("World")))), new RazorError[] @@ -1397,10 +1409,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup(" foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup(" foo")), + new TagHelperAttributeNode( "style", new MarkupBlock( factory.Markup(" color"), @@ -1415,10 +1427,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "Hello World", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup(" foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup(" foo")), + new TagHelperAttributeNode( "style", new MarkupBlock( factory.Markup(" color"), @@ -1434,18 +1446,18 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "Hello World", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup(" foo"), factory.Markup(" "))) }, factory.Markup("Hello")), factory.Markup(" "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "style", new MarkupBlock(factory.Markup(" color:red;"), factory.Markup(" "))) }, @@ -1512,10 +1524,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)), - new KeyValuePair("style", dateTimeNow(32)) + new TagHelperAttributeNode("class", dateTimeNow(10)), + new TagHelperAttributeNode("style", dateTimeNow(32), HtmlAttributeValueStyle.SingleQuotes) })) }; yield return new object[] @@ -1523,10 +1535,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, doWhileString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", doWhile(10)), - new KeyValuePair("style", doWhile(83)) + new TagHelperAttributeNode("class", doWhile(10)), + new TagHelperAttributeNode("style", doWhile(83), HtmlAttributeValueStyle.SingleQuotes) })) }; @@ -1536,10 +1548,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)), - new KeyValuePair("style", dateTimeNow(32)) + new TagHelperAttributeNode("class", dateTimeNow(10)), + new TagHelperAttributeNode("style", dateTimeNow(32), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("Hello World"))) }; @@ -1548,10 +1560,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, doWhileString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", doWhile(10)), - new KeyValuePair("style", doWhile(83)) + new TagHelperAttributeNode("class", doWhile(10)), + new TagHelperAttributeNode("style", doWhile(83), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("Hello World"))) }; @@ -1562,16 +1574,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)) + new TagHelperAttributeNode("class", dateTimeNow(10)) }, factory.Markup("Hello")), factory.Markup(" "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("style", dateTimeNow(45)) + new TagHelperAttributeNode("style", dateTimeNow(45), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("World"))) }; @@ -1580,16 +1592,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, doWhileString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", doWhile(10)) + new TagHelperAttributeNode("class", doWhile(10)) }, factory.Markup("Hello")), factory.Markup(" "), new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("style", doWhile(96)) + new TagHelperAttributeNode("style", doWhile(96), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("World"))) }; @@ -1601,10 +1613,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers string.Format(currentFormattedString, dateTimeNowString), new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", dateTimeNow(10)), - new KeyValuePair("style", dateTimeNow(32)) + new TagHelperAttributeNode("class", dateTimeNow(10)), + new TagHelperAttributeNode("style", dateTimeNow(32), HtmlAttributeValueStyle.SingleQuotes) }, factory.Markup("Hello World "), new MarkupTagBlock( @@ -1894,31 +1906,32 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", new MarkupBlock()) + new TagHelperAttributeNode("class", new MarkupBlock()) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", new MarkupBlock()) + new TagHelperAttributeNode("class", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })) }, { "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { // 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. - new KeyValuePair( + new TagHelperAttributeNode( "class", - factory.Markup("").With(SpanChunkGenerator.Null)), + factory.Markup("").With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), })) }, { @@ -1926,13 +1939,14 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class1", new MarkupBlock()), - new KeyValuePair( + new TagHelperAttributeNode("class1", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode( "class2", - factory.Markup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("class3", new MarkupBlock()), + factory.Markup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("class3", new MarkupBlock()), })) }, { @@ -1940,13 +1954,14 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class1", new MarkupBlock()), - new KeyValuePair("class2", new MarkupBlock()), - new KeyValuePair( + new TagHelperAttributeNode("class1", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("class2", new MarkupBlock()), + new TagHelperAttributeNode( "class3", - factory.Markup(string.Empty).With(SpanChunkGenerator.Null)), + factory.Markup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), })) }, }; @@ -1979,9 +1994,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", new MarkupBlock()) + new TagHelperAttributeNode("bound", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -1996,9 +2011,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup(" true")) + new TagHelperAttributeNode("bound", factory.CodeMarkup(" true"), HtmlAttributeValueStyle.SingleQuotes) })), new RazorError[0] }, @@ -2008,9 +2023,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup(" ")) + new TagHelperAttributeNode("bound", factory.CodeMarkup(" "), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2025,10 +2040,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", new MarkupBlock()), - new KeyValuePair("bound", new MarkupBlock()) + new TagHelperAttributeNode("bound", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("bound", new MarkupBlock()) })), new[] { @@ -2046,10 +2061,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup(" ")), - new KeyValuePair("bound", factory.CodeMarkup(" ")) + new TagHelperAttributeNode("bound", factory.CodeMarkup(" "), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("bound", factory.CodeMarkup(" ")) })), new[] { @@ -2067,12 +2082,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup("true")), - new KeyValuePair( + new TagHelperAttributeNode("bound", factory.CodeMarkup("true"), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes) })), new[] { @@ -2087,12 +2103,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("name", new MarkupBlock()) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("name", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2107,12 +2124,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("name", factory.Markup(" ")) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("name", factory.Markup(" "), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2127,16 +2145,18 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("bound", factory.CodeMarkup("true")), - new KeyValuePair("name", factory.Markup("john")), - new KeyValuePair( + new TagHelperAttributeNode("bound", factory.CodeMarkup("true"), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("name", factory.Markup("john"), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode( "bound", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair( + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode( "name", - factory.Markup(string.Empty).With(SpanChunkGenerator.Null)) + factory.Markup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes) })), new[] { @@ -2151,9 +2171,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("BouND", new MarkupBlock()) + new TagHelperAttributeNode("BouND", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2168,10 +2188,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("BOUND", new MarkupBlock()), - new KeyValuePair("bOUnd", new MarkupBlock()) + new TagHelperAttributeNode("BOUND", new MarkupBlock(), HtmlAttributeValueStyle.SingleQuotes), + new TagHelperAttributeNode("bOUnd", new MarkupBlock()) })), new[] { @@ -2188,12 +2208,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock( "myth", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "BOUND", - factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null)), - new KeyValuePair("nAMe", factory.Markup("john")) + factory.CodeMarkup(string.Empty).With(SpanChunkGenerator.Null), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("nAMe", factory.Markup("john"), HtmlAttributeValueStyle.SingleQuotes) })), new[] { @@ -2208,10 +2229,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { { - new KeyValuePair( + new TagHelperAttributeNode( "bound", new MarkupBlock( new MarkupBlock( @@ -2223,7 +2244,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.Code("true") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) .Accepts(AcceptedCharacters.NonWhiteSpace))), - factory.CodeMarkup(" "))) + factory.CodeMarkup(" ")), + HtmlAttributeValueStyle.SingleQuotes) } })), new RazorError[0] @@ -2234,10 +2256,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "myth", TagMode.SelfClosing, - attributes: new List> + attributes: new List { { - new KeyValuePair( + new TagHelperAttributeNode( "bound", new MarkupBlock( new MarkupBlock( @@ -2255,7 +2277,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.None) .As(SpanKind.Code) .With(new MarkupChunkGenerator()))), - factory.CodeMarkup(" "))) + factory.CodeMarkup(" ")), + HtmlAttributeValueStyle.SingleQuotes) } })), new RazorError[0] @@ -2350,10 +2373,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("script", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) })) }; yield return new object[] @@ -2363,10 +2386,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock("p", factory.Markup("Hello "), new MarkupTagHelperBlock("script", - new List> + new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }), factory.Markup(" World"))) }; @@ -2377,16 +2400,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock("p", factory.Markup("Hello "), new MarkupTagHelperBlock("script", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( factory.Markup("@").Accepts(AcceptedCharacters.None), factory.Markup("@").With(SpanChunkGenerator.Null).Accepts(AcceptedCharacters.None)), factory.Markup("foo@bar.com"))), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }), factory.Markup(" World"))) }; @@ -2414,10 +2437,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair("style", factory.Markup("color:red;")) + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) })) }; yield return new object[] @@ -2433,10 +2456,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupTagHelperBlock( "p", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode( "style", factory.Markup("color:red;")) }), @@ -2450,16 +2473,16 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.Markup("Hello"), new MarkupTagHelperBlock("p", TagMode.SelfClosing, - attributes: new List> + attributes: new List
> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", new MarkupBlock( factory.Markup("false"), - factory.Markup(" > + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", - factory.Markup("false")) + factory.Markup("false"), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -490,9 +500,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", factory.Markup("false'")) })), @@ -512,9 +522,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", new MarkupBlock( factory.Markup("false'"), @@ -536,10 +546,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("foo", null), - new KeyValuePair("bar", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("bar", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -562,9 +572,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -578,9 +588,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -594,12 +604,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -622,12 +632,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null), + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), })), new RazorError[0] }, @@ -657,9 +667,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( @@ -672,7 +682,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -686,9 +697,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", createInvalidDoBlock(string.Empty)) })), @@ -711,9 +722,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", createInvalidDoBlock("\">")) + new TagHelperAttributeNode("class", createInvalidDoBlock("\">")) })), new [] { @@ -762,9 +773,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("some")) + new TagHelperAttributeNode("class", factory.Markup("some")) })), new [] { @@ -972,9 +983,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")) + new TagHelperAttributeNode("age", factory.CodeMarkup("12")) })) }, { @@ -982,9 +993,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")) })) @@ -994,9 +1005,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1013,9 +1024,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1036,9 +1047,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("name", factory.Markup("John")) + new TagHelperAttributeNode("name", factory.Markup("John")) })) }, { @@ -1046,9 +1057,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1058,9 +1069,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( factory.CodeMarkup("1"), @@ -1078,7 +1089,7 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.NonWhiteSpace))), factory.CodeMarkup(" +"), factory.CodeMarkup(" 2"))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", new MarkupBlock( factory.CodeMarkup("(bool)"), @@ -1110,8 +1121,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory .Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))) - )) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -1119,13 +1130,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1135,13 +1146,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( factory.Markup("Time:"), @@ -1158,13 +1169,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( new MarkupBlock( @@ -1180,9 +1191,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1207,10 +1218,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.None) .As(SpanKind.Code) .With(new MarkupChunkGenerator()))))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1280,10 +1291,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("foo")), - new KeyValuePair( + new TagHelperAttributeNode("class", factory.Markup("foo")), + new TagHelperAttributeNode( "dynamic", new MarkupBlock( new MarkupBlock( @@ -1296,8 +1307,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))), - new KeyValuePair("style", factory.Markup("color:red;")) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes), + new TagHelperAttributeNode("style", factory.Markup("color:red;")) }, new MarkupTagHelperBlock("strong")), blockFactory.MarkupTagBlock("
> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", factory.Markup("false'")) })), @@ -512,9 +522,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "bar", new MarkupBlock( factory.Markup("false'"), @@ -536,10 +546,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("foo", null), - new KeyValuePair("bar", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("bar", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -562,9 +572,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -578,9 +588,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -594,12 +604,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -622,12 +632,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null), + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), })), new RazorError[0] }, @@ -657,9 +667,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( @@ -672,7 +682,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -686,9 +697,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", createInvalidDoBlock(string.Empty)) })), @@ -711,9 +722,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", createInvalidDoBlock("\">")) + new TagHelperAttributeNode("class", createInvalidDoBlock("\">")) })), new [] { @@ -762,9 +773,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("some")) + new TagHelperAttributeNode("class", factory.Markup("some")) })), new [] { @@ -972,9 +983,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")) + new TagHelperAttributeNode("age", factory.CodeMarkup("12")) })) }, { @@ -982,9 +993,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")) })) @@ -994,9 +1005,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1013,9 +1024,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1036,9 +1047,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("name", factory.Markup("John")) + new TagHelperAttributeNode("name", factory.Markup("John")) })) }, { @@ -1046,9 +1057,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1058,9 +1069,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( factory.CodeMarkup("1"), @@ -1078,7 +1089,7 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.NonWhiteSpace))), factory.CodeMarkup(" +"), factory.CodeMarkup(" 2"))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", new MarkupBlock( factory.CodeMarkup("(bool)"), @@ -1110,8 +1121,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory .Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))) - )) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -1119,13 +1130,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1135,13 +1146,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( factory.Markup("Time:"), @@ -1158,13 +1169,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( new MarkupBlock( @@ -1180,9 +1191,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1207,10 +1218,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.None) .As(SpanKind.Code) .With(new MarkupChunkGenerator()))))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1280,10 +1291,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "
", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("foo", null), - new KeyValuePair("bar", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), + new TagHelperAttributeNode("bar", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -562,9 +572,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -578,9 +588,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -594,12 +604,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -622,12 +632,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null), + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), })), new RazorError[0] }, @@ -657,9 +667,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( @@ -672,7 +682,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -686,9 +697,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", createInvalidDoBlock(string.Empty)) })), @@ -711,9 +722,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", createInvalidDoBlock("\">")) + new TagHelperAttributeNode("class", createInvalidDoBlock("\">")) })), new [] { @@ -762,9 +773,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("some")) + new TagHelperAttributeNode("class", factory.Markup("some")) })), new [] { @@ -972,9 +983,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")) + new TagHelperAttributeNode("age", factory.CodeMarkup("12")) })) }, { @@ -982,9 +993,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")) })) @@ -994,9 +1005,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1013,9 +1024,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1036,9 +1047,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("name", factory.Markup("John")) + new TagHelperAttributeNode("name", factory.Markup("John")) })) }, { @@ -1046,9 +1057,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1058,9 +1069,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( factory.CodeMarkup("1"), @@ -1078,7 +1089,7 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.NonWhiteSpace))), factory.CodeMarkup(" +"), factory.CodeMarkup(" 2"))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", new MarkupBlock( factory.CodeMarkup("(bool)"), @@ -1110,8 +1121,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory .Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))) - )) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -1119,13 +1130,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1135,13 +1146,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( factory.Markup("Time:"), @@ -1158,13 +1169,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( new MarkupBlock( @@ -1180,9 +1191,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1207,10 +1218,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.None) .As(SpanKind.Code) .With(new MarkupChunkGenerator()))))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1280,10 +1291,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "
", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -578,9 +588,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -594,12 +604,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -622,12 +632,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null), + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), })), new RazorError[0] }, @@ -657,9 +667,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( @@ -672,7 +682,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -686,9 +697,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", createInvalidDoBlock(string.Empty)) })), @@ -711,9 +722,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", createInvalidDoBlock("\">")) + new TagHelperAttributeNode("class", createInvalidDoBlock("\">")) })), new [] { @@ -762,9 +773,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("some")) + new TagHelperAttributeNode("class", factory.Markup("some")) })), new [] { @@ -972,9 +983,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")) + new TagHelperAttributeNode("age", factory.CodeMarkup("12")) })) }, { @@ -982,9 +993,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")) })) @@ -994,9 +1005,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1013,9 +1024,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1036,9 +1047,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("name", factory.Markup("John")) + new TagHelperAttributeNode("name", factory.Markup("John")) })) }, { @@ -1046,9 +1057,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1058,9 +1069,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( factory.CodeMarkup("1"), @@ -1078,7 +1089,7 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.NonWhiteSpace))), factory.CodeMarkup(" +"), factory.CodeMarkup(" 2"))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", new MarkupBlock( factory.CodeMarkup("(bool)"), @@ -1110,8 +1121,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory .Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))) - )) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -1119,13 +1130,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1135,13 +1146,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( factory.Markup("Time:"), @@ -1158,13 +1169,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( new MarkupBlock( @@ -1180,9 +1191,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1207,10 +1218,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.None) .As(SpanKind.Code) .With(new MarkupChunkGenerator()))))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1280,10 +1291,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "
", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("btn")) + new TagHelperAttributeNode("class", factory.Markup("btn")) })), new [] { @@ -594,12 +604,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -622,12 +632,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null), + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), })), new RazorError[0] }, @@ -657,9 +667,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( @@ -672,7 +682,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -686,9 +697,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", createInvalidDoBlock(string.Empty)) })), @@ -711,9 +722,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", createInvalidDoBlock("\">")) + new TagHelperAttributeNode("class", createInvalidDoBlock("\">")) })), new [] { @@ -762,9 +773,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", factory.Markup("some")) + new TagHelperAttributeNode("class", factory.Markup("some")) })), new [] { @@ -972,9 +983,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")) + new TagHelperAttributeNode("age", factory.CodeMarkup("12")) })) }, { @@ -982,9 +993,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")) })) @@ -994,9 +1005,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1013,9 +1024,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1036,9 +1047,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("name", factory.Markup("John")) + new TagHelperAttributeNode("name", factory.Markup("John")) })) }, { @@ -1046,9 +1057,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1058,9 +1069,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( factory.CodeMarkup("1"), @@ -1078,7 +1089,7 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.NonWhiteSpace))), factory.CodeMarkup(" +"), factory.CodeMarkup(" 2"))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", new MarkupBlock( factory.CodeMarkup("(bool)"), @@ -1110,8 +1121,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory .Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))) - )) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.SingleQuotes) })) }, { @@ -1119,13 +1130,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1135,13 +1146,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( factory.Markup("Time:"), @@ -1158,13 +1169,13 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair("age", factory.CodeMarkup("12")), - new KeyValuePair( + new TagHelperAttributeNode("age", factory.CodeMarkup("12")), + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock( new MarkupBlock( @@ -1180,9 +1191,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers new MarkupBlock( new MarkupTagHelperBlock("person", TagMode.SelfClosing, - attributes: new List> + attributes: new List { - new KeyValuePair( + new TagHelperAttributeNode( "age", new MarkupBlock( new MarkupBlock( @@ -1207,10 +1218,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers .Accepts(AcceptedCharacters.None) .As(SpanKind.Code) .With(new MarkupChunkGenerator()))))), - new KeyValuePair( + new TagHelperAttributeNode( "birthday", factory.CodeMarkup("DateTime.Now")), - new KeyValuePair( + new TagHelperAttributeNode( "name", new MarkupBlock(factory.Markup("Time:"), dateTimeNow)) })) @@ -1280,10 +1291,10 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "
", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null) + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized) }, new MarkupTagHelperBlock("strong"))), new [] @@ -622,12 +632,12 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar="))), - new KeyValuePair("foo", null), + new TagHelperAttributeNode("foo", null, HtmlAttributeValueStyle.Minimized), })), new RazorError[0] }, @@ -657,9 +667,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", new MarkupBlock( new MarkupBlock( @@ -672,7 +682,8 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers factory.CodeTransition(), factory.Code("DateTime.Now") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords) - .Accepts(AcceptedCharacters.NonWhiteSpace))))) + .Accepts(AcceptedCharacters.NonWhiteSpace)))), + HtmlAttributeValueStyle.DoubleQuotes) })), new [] { @@ -686,9 +697,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", createInvalidDoBlock(string.Empty)) })), @@ -711,9 +722,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", createInvalidDoBlock("\">")) + new TagHelperAttributeNode("class", createInvalidDoBlock("\">
> + new List { - new KeyValuePair( + new TagHelperAttributeNode( "class", createInvalidDoBlock(string.Empty)) })), @@ -711,9 +722,9 @@ namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers "", new MarkupBlock( new MarkupTagHelperBlock("p", - new List> + new List { - new KeyValuePair("class", createInvalidDoBlock("\">
Hello
World
Hello World