React to aspnet/Razor#705
- Updated `ScriptTagHelper` and `LinkTagHelper` to maintain their quotes on generated script tags. - Removed `TagHelperOutputExtensions`. It's no longer needed. - We no longer string replace quotes directly. We rely on encoding and the initial representation of an attribute to ensure quotes don't break generated attributes. - Updated tests.
This commit is contained in:
parent
5eed7b9b88
commit
cfd58f1747
|
|
@ -88,8 +88,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
ExecutionContextAddTagHelperAttributeMethodName =
|
ExecutionContextAddTagHelperAttributeMethodName =
|
||||||
nameof(TagHelperExecutionContext.AddTagHelperAttribute),
|
nameof(TagHelperExecutionContext.AddTagHelperAttribute),
|
||||||
ExecutionContextAddHtmlAttributeMethodName = nameof(TagHelperExecutionContext.AddHtmlAttribute),
|
ExecutionContextAddHtmlAttributeMethodName = nameof(TagHelperExecutionContext.AddHtmlAttribute),
|
||||||
ExecutionContextAddMinimizedHtmlAttributeMethodName =
|
|
||||||
nameof(TagHelperExecutionContext.AddMinimizedHtmlAttribute),
|
|
||||||
ExecutionContextOutputPropertyName = nameof(TagHelperExecutionContext.Output),
|
ExecutionContextOutputPropertyName = nameof(TagHelperExecutionContext.Output),
|
||||||
|
|
||||||
RunnerTypeName = typeof(TagHelperRunner).FullName,
|
RunnerTypeName = typeof(TagHelperRunner).FullName,
|
||||||
|
|
|
||||||
|
|
@ -572,9 +572,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
public void BeginAddHtmlAttributeValues(
|
public void BeginAddHtmlAttributeValues(
|
||||||
TagHelperExecutionContext executionContext,
|
TagHelperExecutionContext executionContext,
|
||||||
string attributeName,
|
string attributeName,
|
||||||
int attributeValuesCount)
|
int attributeValuesCount,
|
||||||
|
HtmlAttributeValueStyle attributeValueStyle)
|
||||||
{
|
{
|
||||||
_tagHelperAttributeInfo = new TagHelperAttributeInfo(executionContext, attributeName, attributeValuesCount);
|
_tagHelperAttributeInfo = new TagHelperAttributeInfo(
|
||||||
|
executionContext,
|
||||||
|
attributeName,
|
||||||
|
attributeValuesCount,
|
||||||
|
attributeValueStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddHtmlAttributeValue(
|
public void AddHtmlAttributeValue(
|
||||||
|
|
@ -596,7 +601,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
// attribute was removed from TagHelperOutput.Attributes).
|
// attribute was removed from TagHelperOutput.Attributes).
|
||||||
_tagHelperAttributeInfo.ExecutionContext.AddTagHelperAttribute(
|
_tagHelperAttributeInfo.ExecutionContext.AddTagHelperAttribute(
|
||||||
_tagHelperAttributeInfo.Name,
|
_tagHelperAttributeInfo.Name,
|
||||||
value?.ToString() ?? string.Empty);
|
value?.ToString() ?? string.Empty,
|
||||||
|
_tagHelperAttributeInfo.AttributeValueStyle);
|
||||||
_tagHelperAttributeInfo.Suppressed = true;
|
_tagHelperAttributeInfo.Suppressed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -604,7 +610,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
{
|
{
|
||||||
_tagHelperAttributeInfo.ExecutionContext.AddHtmlAttribute(
|
_tagHelperAttributeInfo.ExecutionContext.AddHtmlAttribute(
|
||||||
_tagHelperAttributeInfo.Name,
|
_tagHelperAttributeInfo.Name,
|
||||||
_tagHelperAttributeInfo.Name);
|
_tagHelperAttributeInfo.Name,
|
||||||
|
_tagHelperAttributeInfo.AttributeValueStyle);
|
||||||
_tagHelperAttributeInfo.Suppressed = true;
|
_tagHelperAttributeInfo.Suppressed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -637,7 +644,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
var content = _valueBuffer == null ? HtmlString.Empty : new HtmlString(_valueBuffer.ToString());
|
var content = _valueBuffer == null ? HtmlString.Empty : new HtmlString(_valueBuffer.ToString());
|
||||||
_valueBuffer?.GetStringBuilder().Clear();
|
_valueBuffer?.GetStringBuilder().Clear();
|
||||||
|
|
||||||
executionContext.AddHtmlAttribute(_tagHelperAttributeInfo.Name, content);
|
executionContext.AddHtmlAttribute(_tagHelperAttributeInfo.Name, content, _tagHelperAttributeInfo.AttributeValueStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1081,11 +1088,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
public TagHelperAttributeInfo(
|
public TagHelperAttributeInfo(
|
||||||
TagHelperExecutionContext tagHelperExecutionContext,
|
TagHelperExecutionContext tagHelperExecutionContext,
|
||||||
string name,
|
string name,
|
||||||
int attributeValuesCount)
|
int attributeValuesCount,
|
||||||
|
HtmlAttributeValueStyle attributeValueStyle)
|
||||||
{
|
{
|
||||||
ExecutionContext = tagHelperExecutionContext;
|
ExecutionContext = tagHelperExecutionContext;
|
||||||
Name = name;
|
Name = name;
|
||||||
AttributeValuesCount = attributeValuesCount;
|
AttributeValuesCount = attributeValuesCount;
|
||||||
|
AttributeValueStyle = attributeValueStyle;
|
||||||
|
|
||||||
Suppressed = false;
|
Suppressed = false;
|
||||||
}
|
}
|
||||||
|
|
@ -1096,6 +1105,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
|
|
||||||
public int AttributeValuesCount { get; }
|
public int AttributeValuesCount { get; }
|
||||||
|
|
||||||
|
public HtmlAttributeValueStyle AttributeValueStyle { get; }
|
||||||
|
|
||||||
public bool Suppressed { get; set; }
|
public bool Suppressed { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -422,7 +422,8 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AppendAttribute(attribute.Name, attribute.Value, builder);
|
attribute.CopyTo(builder);
|
||||||
|
builder.AppendHtml(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -441,15 +442,10 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
hrefValue = _fileVersionProvider.AddFileVersionToPath(hrefValue);
|
hrefValue = _fileVersionProvider.AddFileVersionToPath(hrefValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendAttribute(hrefName, hrefValue, builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AppendAttribute(string key, object value, TagHelperContent builder)
|
|
||||||
{
|
|
||||||
builder
|
builder
|
||||||
.AppendHtml(key)
|
.AppendHtml(hrefName)
|
||||||
.AppendHtml("=\"")
|
.AppendHtml("=\"")
|
||||||
.Append(HtmlEncoder, value)
|
.Append(hrefValue)
|
||||||
.AppendHtml("\" ");
|
.AppendHtml("\" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
using System.Text.Encodings.Web;
|
using System.Text.Encodings.Web;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Html;
|
using Microsoft.AspNetCore.Html;
|
||||||
|
|
@ -235,7 +236,8 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
var index = output.Attributes.IndexOfName(SrcAttributeName);
|
var index = output.Attributes.IndexOfName(SrcAttributeName);
|
||||||
output.Attributes[index] = new TagHelperAttribute(
|
output.Attributes[index] = new TagHelperAttribute(
|
||||||
SrcAttributeName,
|
SrcAttributeName,
|
||||||
_fileVersionProvider.AddFileVersionToPath(Src));
|
_fileVersionProvider.AddFileVersionToPath(Src),
|
||||||
|
output.Attributes[index].ValueStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -306,7 +308,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
// Fallback "src" values come from bound attributes and globbing. Must always be non-null.
|
// Fallback "src" values come from bound attributes and globbing. Must always be non-null.
|
||||||
Debug.Assert(src != null);
|
Debug.Assert(src != null);
|
||||||
|
|
||||||
builder.AppendHtml("<script");
|
StringWriter.Write("<script");
|
||||||
|
|
||||||
var addSrc = true;
|
var addSrc = true;
|
||||||
|
|
||||||
|
|
@ -316,80 +318,68 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
var attribute = attributes[i];
|
var attribute = attributes[i];
|
||||||
if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
|
if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var encodedKey = JavaScriptEncoder.Encode(attribute.Name);
|
StringWriter.Write(' ');
|
||||||
var attributeValue = GetAttributeValue(attribute.Value);
|
attribute.WriteTo(StringWriter, HtmlEncoder);
|
||||||
var encodedValue = JavaScriptEncoder.Encode(attributeValue);
|
|
||||||
|
|
||||||
AppendAttribute(builder, encodedKey, encodedValue, escapeQuotes: true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addSrc = false;
|
addSrc = false;
|
||||||
AppendEncodedVersionedSrc(attribute.Name, src, builder, generateForDocumentWrite: true);
|
WriteVersionedSrc(attribute.Name, src, attribute.ValueStyle, StringWriter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addSrc)
|
if (addSrc)
|
||||||
{
|
{
|
||||||
AppendEncodedVersionedSrc(SrcAttributeName, src, builder, generateForDocumentWrite: true);
|
WriteVersionedSrc(SrcAttributeName, src, HtmlAttributeValueStyle.DoubleQuotes, StringWriter);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.AppendHtml("><\\/script>");
|
StringWriter.Write("></script>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stringBuilder = StringWriter.GetStringBuilder();
|
||||||
|
var scriptTags = stringBuilder.ToString();
|
||||||
|
stringBuilder.Clear();
|
||||||
|
var encodedScriptTags = JavaScriptEncoder.Encode(scriptTags);
|
||||||
|
builder.AppendHtml(encodedScriptTags);
|
||||||
|
|
||||||
builder.AppendHtml("\"));</script>");
|
builder.AppendHtml("\"));</script>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetAttributeValue(object value)
|
private string GetVersionedSrc(string srcValue)
|
||||||
{
|
|
||||||
string stringValue;
|
|
||||||
var htmlString = value as HtmlString;
|
|
||||||
if (htmlString != null)
|
|
||||||
{
|
|
||||||
// Value likely came from an HTML context in the .cshtml file but may still contain double quotes
|
|
||||||
// since attribute could have been enclosed in single quotes.
|
|
||||||
stringValue = htmlString.Value;
|
|
||||||
stringValue = stringValue.Replace("\"", """);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var writer = StringWriter;
|
|
||||||
RazorPage.WriteTo(writer, HtmlEncoder, value);
|
|
||||||
|
|
||||||
// Value is now correctly HTML-encoded but may still contain double quotes since attribute could
|
|
||||||
// have been enclosed in single quotes and portions that were HtmlStrings are not re-encoded.
|
|
||||||
var builder = writer.GetStringBuilder();
|
|
||||||
builder.Replace("\"", """);
|
|
||||||
|
|
||||||
stringValue = builder.ToString();
|
|
||||||
builder.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return stringValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AppendEncodedVersionedSrc(
|
|
||||||
string srcName,
|
|
||||||
string srcValue,
|
|
||||||
TagHelperContent builder,
|
|
||||||
bool generateForDocumentWrite)
|
|
||||||
{
|
{
|
||||||
if (AppendVersion == true)
|
if (AppendVersion == true)
|
||||||
{
|
{
|
||||||
srcValue = _fileVersionProvider.AddFileVersionToPath(srcValue);
|
srcValue = _fileVersionProvider.AddFileVersionToPath(srcValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (generateForDocumentWrite)
|
return srcValue;
|
||||||
{
|
}
|
||||||
// srcValue comes from a C# context and globbing. Must HTML-encode it to ensure the
|
|
||||||
// written <script/> element is valid. Must also JavaScript-encode that value to ensure
|
|
||||||
// the document.write() statement is valid.
|
|
||||||
srcValue = HtmlEncoder.Encode(srcValue);
|
|
||||||
srcValue = JavaScriptEncoder.Encode(srcValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppendAttribute(builder, srcName, srcValue, escapeQuotes: generateForDocumentWrite);
|
private void AppendVersionedSrc(
|
||||||
|
string srcName,
|
||||||
|
string srcValue,
|
||||||
|
HtmlAttributeValueStyle valueStyle,
|
||||||
|
IHtmlContentBuilder builder)
|
||||||
|
{
|
||||||
|
srcValue = GetVersionedSrc(srcValue);
|
||||||
|
|
||||||
|
builder.AppendHtml(" ");
|
||||||
|
var attribute = new TagHelperAttribute(srcName, srcValue, valueStyle);
|
||||||
|
attribute.CopyTo(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteVersionedSrc(
|
||||||
|
string srcName,
|
||||||
|
string srcValue,
|
||||||
|
HtmlAttributeValueStyle valueStyle,
|
||||||
|
TextWriter writer)
|
||||||
|
{
|
||||||
|
srcValue = GetVersionedSrc(srcValue);
|
||||||
|
|
||||||
|
writer.Write(' ');
|
||||||
|
var attribute = new TagHelperAttribute(srcName, srcValue, valueStyle);
|
||||||
|
attribute.WriteTo(writer, HtmlEncoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureGlobbingUrlBuilder()
|
private void EnsureGlobbingUrlBuilder()
|
||||||
|
|
@ -429,46 +419,24 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
var attribute = attributes[i];
|
var attribute = attributes[i];
|
||||||
if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
|
if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
AppendAttribute(builder, attribute.Name, attribute.Value, escapeQuotes: false);
|
builder.AppendHtml(" ");
|
||||||
|
attribute.CopyTo(builder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addSrc = false;
|
addSrc = false;
|
||||||
AppendEncodedVersionedSrc(attribute.Name, src, builder, generateForDocumentWrite: false);
|
AppendVersionedSrc(attribute.Name, src, attribute.ValueStyle, builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addSrc)
|
if (addSrc)
|
||||||
{
|
{
|
||||||
AppendEncodedVersionedSrc(SrcAttributeName, src, builder, generateForDocumentWrite: false);
|
AppendVersionedSrc(SrcAttributeName, src, HtmlAttributeValueStyle.DoubleQuotes, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.AppendHtml("></script>");
|
builder.AppendHtml("></script>");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AppendAttribute(TagHelperContent content, string key, object value, bool escapeQuotes)
|
|
||||||
{
|
|
||||||
content
|
|
||||||
.AppendHtml(" ")
|
|
||||||
.AppendHtml(key);
|
|
||||||
if (escapeQuotes)
|
|
||||||
{
|
|
||||||
// Passed only JavaScript-encoded strings in this case. Do not perform HTML-encoding as well.
|
|
||||||
content
|
|
||||||
.AppendHtml("=\\\"")
|
|
||||||
.AppendHtml((string)value)
|
|
||||||
.AppendHtml("\\\"");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// HTML-encode the given value if necessary.
|
|
||||||
content
|
|
||||||
.AppendHtml("=\"")
|
|
||||||
.Append(HtmlEncoder, value)
|
|
||||||
.AppendHtml("\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum Mode
|
private enum Mode
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
// 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 System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text.Encodings.Web;
|
|
||||||
using Microsoft.AspNetCore.Html;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Razor;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
||||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for <see cref="TagHelperContent"/>.
|
|
||||||
/// </summary>
|
|
||||||
public static class TagHelperContentExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Writes the specified <paramref name="value"/> with HTML encoding to given <paramref name="content"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="content">The <see cref="TagHelperContent"/> to write to.</param>
|
|
||||||
/// <param name="encoder">The <see cref="HtmlEncoder"/> to use when encoding <paramref name="value"/>.</param>
|
|
||||||
/// <param name="value">The <see cref="object"/> to write.</param>
|
|
||||||
/// <returns><paramref name="content"/> after the write operation has completed.</returns>
|
|
||||||
/// <remarks>
|
|
||||||
/// <paramref name="value"/>s of type <see cref="Html.IHtmlContent"/> are written using
|
|
||||||
/// <see cref="Html.IHtmlContent.WriteTo(TextWriter, HtmlEncoder)"/>.
|
|
||||||
/// For all other types, the encoded result of <see cref="object.ToString"/>
|
|
||||||
/// is written to the <paramref name="content"/>.
|
|
||||||
/// </remarks>
|
|
||||||
public static TagHelperContent Append(this TagHelperContent content, HtmlEncoder encoder, object value)
|
|
||||||
{
|
|
||||||
if (content == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(content));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (encoder == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(encoder));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
// No real action but touch content to ensure IsModified is true.
|
|
||||||
content.Append((string)null);
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
string stringValue;
|
|
||||||
var htmlString = value as HtmlString;
|
|
||||||
if (htmlString != null)
|
|
||||||
{
|
|
||||||
// No need for a StringWriter in this case.
|
|
||||||
stringValue = htmlString.ToString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
using (var stringWriter = new StringWriter())
|
|
||||||
{
|
|
||||||
RazorPage.WriteTo(stringWriter, encoder, value);
|
|
||||||
stringValue = stringWriter.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In this case the text likely came directly from the Razor source. Since the original string is
|
|
||||||
// an attribute value that may have been quoted with single quotes, must handle any double quotes
|
|
||||||
// in the value. Writing the value out surrounded by double quotes.
|
|
||||||
content.AppendHtml(stringValue.Replace("\"", """));
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -158,10 +158,6 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
TagHelperContext context)
|
TagHelperContext context)
|
||||||
{
|
{
|
||||||
var existingAttribute = context.AllAttributes[allAttributeIndex];
|
var existingAttribute = context.AllAttributes[allAttributeIndex];
|
||||||
var copiedAttribute = new TagHelperAttribute(
|
|
||||||
existingAttribute.Name,
|
|
||||||
existingAttribute.Value,
|
|
||||||
existingAttribute.Minimized);
|
|
||||||
|
|
||||||
// Move backwards through context.AllAttributes from the provided index until we find a familiar attribute
|
// Move backwards through context.AllAttributes from the provided index until we find a familiar attribute
|
||||||
// in tagHelperOutput where we can insert the copied value after the familiar one.
|
// in tagHelperOutput where we can insert the copied value after the familiar one.
|
||||||
|
|
@ -171,7 +167,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
var index = IndexOfFirstMatch(previousName, tagHelperOutput.Attributes);
|
var index = IndexOfFirstMatch(previousName, tagHelperOutput.Attributes);
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
{
|
{
|
||||||
tagHelperOutput.Attributes.Insert(index + 1, copiedAttribute);
|
tagHelperOutput.Attributes.Insert(index + 1, existingAttribute);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -184,13 +180,13 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
var index = IndexOfFirstMatch(nextName, tagHelperOutput.Attributes);
|
var index = IndexOfFirstMatch(nextName, tagHelperOutput.Attributes);
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
{
|
{
|
||||||
tagHelperOutput.Attributes.Insert(index, copiedAttribute);
|
tagHelperOutput.Attributes.Insert(index, existingAttribute);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Couldn't determine the attribute's location, add it to the end.
|
// Couldn't determine the attribute's location, add it to the end.
|
||||||
tagHelperOutput.Attributes.Add(copiedAttribute);
|
tagHelperOutput.Attributes.Add(existingAttribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int IndexOfFirstMatch(string name, TagHelperAttributeList attributes)
|
private static int IndexOfFirstMatch(string name, TagHelperAttributeList attributes)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<a title="<the title>" href="HtmlEncode[[/UrlEncode[[HtmlGeneration_Product]]]]">Product Index</a>
|
<a title="<the title>" href="HtmlEncode[[/UrlEncode[[HtmlGeneration_Product]]]]">Product Index</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a title=""the" title" href="HtmlEncode[[/UrlEncode[[HtmlGeneration_Product]]/UrlEncode[[List]]]]">Product List</a>
|
<a title='"the" title' href="HtmlEncode[[/UrlEncode[[HtmlGeneration_Product]]/UrlEncode[[List]]]]">Product List</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a id="HtmlGenerationWebSite_Index">HtmlGenerationWebSite Index</a>
|
<a id="HtmlGenerationWebSite_Index">HtmlGenerationWebSite Index</a>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<a title="<the title>" href="/HtmlGeneration_Product">Product Index</a>
|
<a title="<the title>" href="/HtmlGeneration_Product">Product Index</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a title=""the" title" href="/HtmlGeneration_Product/List">Product List</a>
|
<a title='"the" title' href="/HtmlGeneration_Product/List">Product List</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a id="HtmlGenerationWebSite_Index">HtmlGenerationWebSite Index</a>
|
<a id="HtmlGenerationWebSite_Index">HtmlGenerationWebSite Index</a>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
<link rel="stylesheet" title="<the title" href="HtmlEncode[[/styles/site.css]]" /><link rel="stylesheet" title="<the title" href="HtmlEncode[[/styles/sub/site2.css]]" /><link rel="stylesheet" title="<the title" href="HtmlEncode[[/styles/sub/site3.css]]" /><link rel="stylesheet" title="<the title" href="HtmlEncode[[/styles/sub/site3.min.css]]" />
|
<link rel="stylesheet" title="<the title" href="HtmlEncode[[/styles/site.css]]" /><link rel="stylesheet" title="<the title" href="HtmlEncode[[/styles/sub/site2.css]]" /><link rel="stylesheet" title="<the title" href="HtmlEncode[[/styles/sub/site3.css]]" /><link rel="stylesheet" title="<the title" href="HtmlEncode[[/styles/sub/site3.min.css]]" />
|
||||||
|
|
||||||
<!-- Globbed link tag with existing file and exclude -->
|
<!-- Globbed link tag with existing file and exclude -->
|
||||||
<link rel="stylesheet" title=""the" title" href="HtmlEncode[[/styles/site.css]]" /><link rel="stylesheet" title=""the" title" href="HtmlEncode[[/styles/sub/site2.css]]" />
|
<link rel="stylesheet" title='"the" title' href="HtmlEncode[[/styles/site.css]]" /><link rel="stylesheet" title='"the" title' href="HtmlEncode[[/styles/sub/site2.css]]" />
|
||||||
|
|
||||||
<!-- Globbed link tag missing include -->
|
<!-- Globbed link tag missing include -->
|
||||||
<link rel="stylesheet">
|
<link rel="stylesheet">
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
<link href="HtmlEncode[[/styles/site.css]]" rel="stylesheet" />
|
<link href="HtmlEncode[[/styles/site.css]]" rel="stylesheet" />
|
||||||
|
|
||||||
<!-- Fallback to static href -->
|
<!-- Fallback to static href -->
|
||||||
<link href="HtmlEncode[[/styles/site.min.css?a=b&c=d]]" rel="stylesheet" data-extra="test" title=""the" title" />
|
<link href="HtmlEncode[[/styles/site.min.css?a=b&c=d]]" rel="stylesheet" data-extra="test" title='"the" title' />
|
||||||
<meta name="x-stylesheet-fallback-test" content="" class="HtmlEncode[[hidden]]" /><script>!function(a,b,c){var d,e=document,f=e.getElementsByTagName("SCRIPT"),g=f[f.length-1].previousElementSibling,h=e.defaultView&&e.defaultView.getComputedStyle?e.defaultView.getComputedStyle(g):g.currentStyle;if(h&&h[a]!==b)for(d=0;d<c.length;d++)e.write('<link rel="stylesheet" href="'+c[d]+'"/>')}("JavaScriptEncode[[visibility]]","JavaScriptEncode[[hidden]]",["JavaScriptEncode[[HtmlEncode[[/styles/site.css?a=b&c=d]]]]"]);</script>
|
<meta name="x-stylesheet-fallback-test" content="" class="HtmlEncode[[hidden]]" /><script>!function(a,b,c){var d,e=document,f=e.getElementsByTagName("SCRIPT"),g=f[f.length-1].previousElementSibling,h=e.defaultView&&e.defaultView.getComputedStyle?e.defaultView.getComputedStyle(g):g.currentStyle;if(h&&h[a]!==b)for(d=0;d<c.length;d++)e.write('<link rel="stylesheet" href="'+c[d]+'"/>')}("JavaScriptEncode[[visibility]]","JavaScriptEncode[[hidden]]",["JavaScriptEncode[[HtmlEncode[[/styles/site.css?a=b&c=d]]]]"]);</script>
|
||||||
|
|
||||||
<!-- Fallback from globbed href to static href -->
|
<!-- Fallback from globbed href to static href -->
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
<link rel="stylesheet" title="<the title" href="/styles/site.css" /><link rel="stylesheet" title="<the title" href="/styles/sub/site2.css" /><link rel="stylesheet" title="<the title" href="/styles/sub/site3.css" /><link rel="stylesheet" title="<the title" href="/styles/sub/site3.min.css" />
|
<link rel="stylesheet" title="<the title" href="/styles/site.css" /><link rel="stylesheet" title="<the title" href="/styles/sub/site2.css" /><link rel="stylesheet" title="<the title" href="/styles/sub/site3.css" /><link rel="stylesheet" title="<the title" href="/styles/sub/site3.min.css" />
|
||||||
|
|
||||||
<!-- Globbed link tag with existing file and exclude -->
|
<!-- Globbed link tag with existing file and exclude -->
|
||||||
<link rel="stylesheet" title=""the" title" href="/styles/site.css" /><link rel="stylesheet" title=""the" title" href="/styles/sub/site2.css" />
|
<link rel="stylesheet" title='"the" title' href="/styles/site.css" /><link rel="stylesheet" title='"the" title' href="/styles/sub/site2.css" />
|
||||||
|
|
||||||
<!-- Globbed link tag missing include -->
|
<!-- Globbed link tag missing include -->
|
||||||
<link rel="stylesheet">
|
<link rel="stylesheet">
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
<link href="/styles/site.css" rel="stylesheet" />
|
<link href="/styles/site.css" rel="stylesheet" />
|
||||||
|
|
||||||
<!-- Fallback to static href -->
|
<!-- Fallback to static href -->
|
||||||
<link href="/styles/site.min.css?a=b&c=d" rel="stylesheet" data-extra="test" title=""the" title" />
|
<link href="/styles/site.min.css?a=b&c=d" rel="stylesheet" data-extra="test" title='"the" title' />
|
||||||
<meta name="x-stylesheet-fallback-test" content="" class="hidden" /><script>!function(a,b,c){var d,e=document,f=e.getElementsByTagName("SCRIPT"),g=f[f.length-1].previousElementSibling,h=e.defaultView&&e.defaultView.getComputedStyle?e.defaultView.getComputedStyle(g):g.currentStyle;if(h&&h[a]!==b)for(d=0;d<c.length;d++)e.write('<link rel="stylesheet" href="'+c[d]+'"/>')}("visibility","hidden",["\/styles\/site.css?a=b\u0026amp;c=d"]);</script>
|
<meta name="x-stylesheet-fallback-test" content="" class="hidden" /><script>!function(a,b,c){var d,e=document,f=e.getElementsByTagName("SCRIPT"),g=f[f.length-1].previousElementSibling,h=e.defaultView&&e.defaultView.getComputedStyle?e.defaultView.getComputedStyle(g):g.currentStyle;if(h&&h[a]!==b)for(d=0;d<c.length;d++)e.write('<link rel="stylesheet" href="'+c[d]+'"/>')}("visibility","hidden",["\/styles\/site.css?a=b\u0026amp;c=d"]);</script>
|
||||||
|
|
||||||
<!-- Fallback from globbed href to static href -->
|
<!-- Fallback from globbed href to static href -->
|
||||||
|
|
|
||||||
|
|
@ -13,27 +13,27 @@
|
||||||
<script src="HtmlEncode[[/blank.js?a=b&c=d]]" data-foo="foo-data2" title="<the title>">
|
<script src="HtmlEncode[[/blank.js?a=b&c=d]]" data-foo="foo-data2" title="<the title>">
|
||||||
// TagHelper script with comment in body, and extra properties.
|
// TagHelper script with comment in body, and extra properties.
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js?a=b&c=d]]]]\" JavaScriptEncode[[data-foo]]=\"JavaScriptEncode[[foo-data2]]\" JavaScriptEncode[[title]]=\"JavaScriptEncode[[<the title>]]\"><\/script>"));</script>
|
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js?a=b&c=d]]" data-foo="foo-data2" title="<the title>"></script>]]"));</script>
|
||||||
|
|
||||||
<script src="HtmlEncode[[/blank.js]]" title=""the" title">
|
<script src="HtmlEncode[[/blank.js]]" title='"the" title'>
|
||||||
// Fallback to globbed src
|
// Fallback to globbed src
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js]]]]\" JavaScriptEncode[[title]]=\"JavaScriptEncode[["the" title]]\"><\/script>"));</script>
|
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js]]" title='"the" title'></script>]]"));</script>
|
||||||
|
|
||||||
<script src="HtmlEncode[[/blank.js]]">
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
// Fallback to globbed src with exclude
|
// Fallback to globbed src with exclude
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js]]]]\"><\/script><script src=\"JavaScriptEncode[[HtmlEncode[[/styles/sub/site2.js]]]]\"><\/script>"));</script>
|
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js]]"></script><script src="HtmlEncode[[/styles/sub/site2.js]]"></script>]]"));</script>
|
||||||
|
|
||||||
<script src="HtmlEncode[[/blank.js]]">
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
// Fallback to globbed and static src
|
// Fallback to globbed and static src
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js]]]]\"><\/script><script src=\"JavaScriptEncode[[HtmlEncode[[/styles/sub/site2.js]]]]\"><\/script>"));</script>
|
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js]]"></script><script src="HtmlEncode[[/styles/sub/site2.js]]"></script>]]"));</script>
|
||||||
|
|
||||||
<script src="HtmlEncode[[/blank.js]]">
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
// Fallback to globbed and static src should de-dupe
|
// Fallback to globbed and static src should de-dupe
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js]]]]\"><\/script>"));</script>
|
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js]]"></script>]]"));</script>
|
||||||
|
|
||||||
<script src="HtmlEncode[[/blank.js]]">
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
// Fallback to globbed src with missing include
|
// Fallback to globbed src with missing include
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
<script src="HtmlEncode[[/blank.js]]">
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
// Fallback to static and globbed src with missing include
|
// Fallback to static and globbed src with missing include
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js]]]]\"><\/script>"));</script>
|
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js]]"></script>]]"));</script>
|
||||||
|
|
||||||
<script src="HtmlEncode[[/blank.js]]">
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
// Fallback to globbed src outside of webroot
|
// Fallback to globbed src outside of webroot
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
<script data-foo="foo-data3">
|
<script data-foo="foo-data3">
|
||||||
// Valid TagHelper (although no src is provided) script with comment in body, and extra properties.
|
// Valid TagHelper (although no src is provided) script with comment in body, and extra properties.
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script JavaScriptEncode[[data-foo]]=\"JavaScriptEncode[[foo-data3]]\" src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js]]]]\"><\/script>"));</script>
|
<script>(false||document.write("JavaScriptEncode[[<script data-foo="foo-data3" src="HtmlEncode[[/styles/site.js]]"></script>]]"));</script>
|
||||||
|
|
||||||
<script src="HtmlEncode[[/blank.js]]">
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
// Invalid TagHelper script with comment in body.
|
// Invalid TagHelper script with comment in body.
|
||||||
|
|
@ -98,12 +98,12 @@
|
||||||
<script src="HtmlEncode[[/blank.js]]">
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
// TagHelper script with comment in body, and file version.
|
// TagHelper script with comment in body, and file version.
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]]]\"><\/script>"));</script>
|
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]"></script>]]"));</script>
|
||||||
|
|
||||||
<script src="HtmlEncode[[/blank.js]]">
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
// Fallback to globbed src with file version.
|
// Fallback to globbed src with file version.
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]]]\"><\/script>"));</script>
|
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]"></script>]]"));</script>
|
||||||
|
|
||||||
<script src="HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]">
|
<script src="HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]">
|
||||||
// Regular script with comment in body, and file version.
|
// Regular script with comment in body, and file version.
|
||||||
|
|
|
||||||
|
|
@ -13,27 +13,27 @@
|
||||||
<script src="/blank.js?a=b&c=d" data-foo="foo-data2" title="<the title>">
|
<script src="/blank.js?a=b&c=d" data-foo="foo-data2" title="<the title>">
|
||||||
// TagHelper script with comment in body, and extra properties.
|
// TagHelper script with comment in body, and extra properties.
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"\/styles\/site.js?a=b\u0026amp;c=d\" data-foo=\"foo-data2\" title=\"\u0026lt;the title\u003E\"><\/script>"));</script>
|
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js?a=b\u0026amp;c=d\u0022 data-foo=\u0022foo-data2\u0022 title=\u0022\u0026lt;the title\u003E\u0022\u003E\u003C\/script\u003E"));</script>
|
||||||
|
|
||||||
<script src="/blank.js" title=""the" title">
|
<script src="/blank.js" title='"the" title'>
|
||||||
// Fallback to globbed src
|
// Fallback to globbed src
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"\/styles\/site.js\" title=\"\u0026quot;the\u0026quot; title\"><\/script>"));</script>
|
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js\u0022 title=\u0027\u0022the\u0022 title\u0027\u003E\u003C\/script\u003E"));</script>
|
||||||
|
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// Fallback to globbed src with exclude
|
// Fallback to globbed src with exclude
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"\/styles\/site.js\"><\/script><script src=\"\/styles\/sub\/site2.js\"><\/script>"));</script>
|
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js\u0022\u003E\u003C\/script\u003E\u003Cscript src=\u0022\/styles\/sub\/site2.js\u0022\u003E\u003C\/script\u003E"));</script>
|
||||||
|
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// Fallback to globbed and static src
|
// Fallback to globbed and static src
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"\/styles\/site.js\"><\/script><script src=\"\/styles\/sub\/site2.js\"><\/script>"));</script>
|
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js\u0022\u003E\u003C\/script\u003E\u003Cscript src=\u0022\/styles\/sub\/site2.js\u0022\u003E\u003C\/script\u003E"));</script>
|
||||||
|
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// Fallback to globbed and static src should de-dupe
|
// Fallback to globbed and static src should de-dupe
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"\/styles\/site.js\"><\/script>"));</script>
|
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js\u0022\u003E\u003C\/script\u003E"));</script>
|
||||||
|
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// Fallback to globbed src with missing include
|
// Fallback to globbed src with missing include
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// Fallback to static and globbed src with missing include
|
// Fallback to static and globbed src with missing include
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"\/styles\/site.js\"><\/script>"));</script>
|
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js\u0022\u003E\u003C\/script\u003E"));</script>
|
||||||
|
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// Fallback to globbed src outside of webroot
|
// Fallback to globbed src outside of webroot
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
<script data-foo="foo-data3">
|
<script data-foo="foo-data3">
|
||||||
// Valid TagHelper (although no src is provided) script with comment in body, and extra properties.
|
// Valid TagHelper (although no src is provided) script with comment in body, and extra properties.
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script data-foo=\"foo-data3\" src=\"\/styles\/site.js\"><\/script>"));</script>
|
<script>(false||document.write("\u003Cscript data-foo=\u0022foo-data3\u0022 src=\u0022\/styles\/site.js\u0022\u003E\u003C\/script\u003E"));</script>
|
||||||
|
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// Invalid TagHelper script with comment in body.
|
// Invalid TagHelper script with comment in body.
|
||||||
|
|
@ -98,12 +98,12 @@
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// TagHelper script with comment in body, and file version.
|
// TagHelper script with comment in body, and file version.
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"\/styles\/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I\"><\/script>"));</script>
|
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I\u0022\u003E\u003C\/script\u003E"));</script>
|
||||||
|
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// Fallback to globbed src with file version.
|
// Fallback to globbed src with file version.
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"\/styles\/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I\"><\/script>"));</script>
|
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I\u0022\u003E\u003C\/script\u003E"));</script>
|
||||||
|
|
||||||
<script src="/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I">
|
<script src="/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I">
|
||||||
// Regular script with comment in body, and file version.
|
// Regular script with comment in body, and file version.
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,3 @@
|
||||||
<form action="/Employee/DuplicateAntiforgeryTokenRegistration" method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>
|
<form action="/Employee/DuplicateAntiforgeryTokenRegistration" method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ __Microsoft_AspNetCore_Mvc_Razor_InputTestTagHelper.For = ModelExpressionProvide
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNetCore_Mvc_Razor_InputTestTagHelper.For);
|
__tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNetCore_Mvc_Razor_InputTestTagHelper.For, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
|
||||||
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||||
BeginContext(128, 24, false);
|
BeginContext(128, 24, false);
|
||||||
Write(__tagHelperExecutionContext.Output);
|
Write(__tagHelperExecutionContext.Output);
|
||||||
|
|
@ -74,7 +74,7 @@ __Microsoft_AspNetCore_Mvc_Razor_InputTestTagHelper.For = ModelExpressionProvide
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNetCore_Mvc_Razor_InputTestTagHelper.For);
|
__tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNetCore_Mvc_Razor_InputTestTagHelper.For, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
|
||||||
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||||
BeginContext(154, 27, false);
|
BeginContext(154, 27, false);
|
||||||
Write(__tagHelperExecutionContext.Output);
|
Write(__tagHelperExecutionContext.Output);
|
||||||
|
|
|
||||||
|
|
@ -1248,7 +1248,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
endTagHelperWritingScope: () => new DefaultTagHelperContent());
|
endTagHelperWritingScope: () => new DefaultTagHelperContent());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
page.BeginAddHtmlAttributeValues(executionContext, "someattr", attributeValues.Length);
|
page.BeginAddHtmlAttributeValues(executionContext, "someattr", attributeValues.Length, HtmlAttributeValueStyle.SingleQuotes);
|
||||||
foreach (var value in attributeValues)
|
foreach (var value in attributeValues)
|
||||||
{
|
{
|
||||||
page.AddHtmlAttributeValue(value.Item1, value.Item2, value.Item3, value.Item4, 0, value.Item5);
|
page.AddHtmlAttributeValue(value.Item1, value.Item2, value.Item3, value.Item4, 0, value.Item5);
|
||||||
|
|
@ -1261,14 +1261,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
Assert.Equal("someattr", htmlAttribute.Name, StringComparer.Ordinal);
|
Assert.Equal("someattr", htmlAttribute.Name, StringComparer.Ordinal);
|
||||||
var htmlContent = Assert.IsAssignableFrom<IHtmlContent>(htmlAttribute.Value);
|
var htmlContent = Assert.IsAssignableFrom<IHtmlContent>(htmlAttribute.Value);
|
||||||
Assert.Equal(expectedValue, HtmlContentUtilities.HtmlContentToString(htmlContent), StringComparer.Ordinal);
|
Assert.Equal(expectedValue, HtmlContentUtilities.HtmlContentToString(htmlContent), StringComparer.Ordinal);
|
||||||
Assert.False(htmlAttribute.Minimized);
|
Assert.Equal(HtmlAttributeValueStyle.SingleQuotes, htmlAttribute.ValueStyle);
|
||||||
|
|
||||||
var context = executionContext.Context;
|
var context = executionContext.Context;
|
||||||
var allAttribute = Assert.Single(context.AllAttributes);
|
var allAttribute = Assert.Single(context.AllAttributes);
|
||||||
Assert.Equal("someattr", allAttribute.Name, StringComparer.Ordinal);
|
Assert.Equal("someattr", allAttribute.Name, StringComparer.Ordinal);
|
||||||
htmlContent = Assert.IsAssignableFrom<IHtmlContent>(allAttribute.Value);
|
htmlContent = Assert.IsAssignableFrom<IHtmlContent>(allAttribute.Value);
|
||||||
Assert.Equal(expectedValue, HtmlContentUtilities.HtmlContentToString(htmlContent), StringComparer.Ordinal);
|
Assert.Equal(expectedValue, HtmlContentUtilities.HtmlContentToString(htmlContent), StringComparer.Ordinal);
|
||||||
Assert.False(allAttribute.Minimized);
|
Assert.Equal(HtmlAttributeValueStyle.SingleQuotes, allAttribute.ValueStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
|
@ -1291,7 +1291,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
endTagHelperWritingScope: () => new DefaultTagHelperContent());
|
endTagHelperWritingScope: () => new DefaultTagHelperContent());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
page.BeginAddHtmlAttributeValues(executionContext, "someattr", 1);
|
page.BeginAddHtmlAttributeValues(executionContext, "someattr", 1, HtmlAttributeValueStyle.DoubleQuotes);
|
||||||
page.AddHtmlAttributeValue(string.Empty, 9, attributeValue, 9, valueLength: 0, isLiteral: false);
|
page.AddHtmlAttributeValue(string.Empty, 9, attributeValue, 9, valueLength: 0, isLiteral: false);
|
||||||
page.EndAddHtmlAttributeValues(executionContext);
|
page.EndAddHtmlAttributeValues(executionContext);
|
||||||
|
|
||||||
|
|
@ -1302,7 +1302,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
var attribute = Assert.Single(context.AllAttributes);
|
var attribute = Assert.Single(context.AllAttributes);
|
||||||
Assert.Equal("someattr", attribute.Name, StringComparer.Ordinal);
|
Assert.Equal("someattr", attribute.Name, StringComparer.Ordinal);
|
||||||
Assert.Equal(expectedValue, (string)attribute.Value, StringComparer.Ordinal);
|
Assert.Equal(expectedValue, (string)attribute.Value, StringComparer.Ordinal);
|
||||||
Assert.False(attribute.Minimized);
|
Assert.Equal(HtmlAttributeValueStyle.DoubleQuotes, attribute.ValueStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1321,7 +1321,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
endTagHelperWritingScope: () => new DefaultTagHelperContent());
|
endTagHelperWritingScope: () => new DefaultTagHelperContent());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
page.BeginAddHtmlAttributeValues(executionContext, "someattr", 1);
|
page.BeginAddHtmlAttributeValues(executionContext, "someattr", 1, HtmlAttributeValueStyle.NoQuotes);
|
||||||
page.AddHtmlAttributeValue(string.Empty, 9, true, 9, valueLength: 0, isLiteral: false);
|
page.AddHtmlAttributeValue(string.Empty, 9, true, 9, valueLength: 0, isLiteral: false);
|
||||||
page.EndAddHtmlAttributeValues(executionContext);
|
page.EndAddHtmlAttributeValues(executionContext);
|
||||||
|
|
||||||
|
|
@ -1330,12 +1330,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
var htmlAttribute = Assert.Single(output.Attributes);
|
var htmlAttribute = Assert.Single(output.Attributes);
|
||||||
Assert.Equal("someattr", htmlAttribute.Name, StringComparer.Ordinal);
|
Assert.Equal("someattr", htmlAttribute.Name, StringComparer.Ordinal);
|
||||||
Assert.Equal("someattr", (string)htmlAttribute.Value, StringComparer.Ordinal);
|
Assert.Equal("someattr", (string)htmlAttribute.Value, StringComparer.Ordinal);
|
||||||
Assert.False(htmlAttribute.Minimized);
|
Assert.Equal(HtmlAttributeValueStyle.NoQuotes, htmlAttribute.ValueStyle);
|
||||||
var context = executionContext.Context;
|
var context = executionContext.Context;
|
||||||
var allAttribute = Assert.Single(context.AllAttributes);
|
var allAttribute = Assert.Single(context.AllAttributes);
|
||||||
Assert.Equal("someattr", allAttribute.Name, StringComparer.Ordinal);
|
Assert.Equal("someattr", allAttribute.Name, StringComparer.Ordinal);
|
||||||
Assert.Equal("someattr", (string)allAttribute.Value, StringComparer.Ordinal);
|
Assert.Equal("someattr", (string)allAttribute.Value, StringComparer.Ordinal);
|
||||||
Assert.False(allAttribute.Minimized);
|
Assert.Equal(HtmlAttributeValueStyle.NoQuotes, allAttribute.ValueStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TheoryData WriteAttributeData
|
public static TheoryData WriteAttributeData
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
|
||||||
Assert.Equal("href", attribute.Name, StringComparer.Ordinal);
|
Assert.Equal("href", attribute.Name, StringComparer.Ordinal);
|
||||||
var attributeValue = Assert.IsType<string>(attribute.Value);
|
var attributeValue = Assert.IsType<string>(attribute.Value);
|
||||||
Assert.Equal(expectedHref, attributeValue, StringComparer.Ordinal);
|
Assert.Equal(expectedHref, attributeValue, StringComparer.Ordinal);
|
||||||
Assert.False(attribute.Minimized);
|
Assert.Equal(HtmlAttributeValueStyle.DoubleQuotes, attribute.ValueStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TheoryData ResolvableUrlHtmlStringData
|
public static TheoryData ResolvableUrlHtmlStringData
|
||||||
|
|
@ -157,7 +157,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
|
||||||
Assert.Equal("href", attribute.Name, StringComparer.Ordinal);
|
Assert.Equal("href", attribute.Name, StringComparer.Ordinal);
|
||||||
var htmlContent = Assert.IsAssignableFrom<IHtmlContent>(attribute.Value);
|
var htmlContent = Assert.IsAssignableFrom<IHtmlContent>(attribute.Value);
|
||||||
Assert.Equal(expectedHref, HtmlContentUtilities.HtmlContentToString(htmlContent), StringComparer.Ordinal);
|
Assert.Equal(expectedHref, HtmlContentUtilities.HtmlContentToString(htmlContent), StringComparer.Ordinal);
|
||||||
Assert.False(attribute.Minimized);
|
Assert.Equal(HtmlAttributeValueStyle.DoubleQuotes, attribute.ValueStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TheoryData UnresolvableUrlData
|
public static TheoryData UnresolvableUrlData
|
||||||
|
|
@ -212,7 +212,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
|
||||||
Assert.Equal("href", attribute.Name, StringComparer.Ordinal);
|
Assert.Equal("href", attribute.Name, StringComparer.Ordinal);
|
||||||
var attributeValue = Assert.IsType<string>(attribute.Value);
|
var attributeValue = Assert.IsType<string>(attribute.Value);
|
||||||
Assert.Equal(url, attributeValue, StringComparer.Ordinal);
|
Assert.Equal(url, attributeValue, StringComparer.Ordinal);
|
||||||
Assert.False(attribute.Minimized);
|
Assert.Equal(HtmlAttributeValueStyle.DoubleQuotes, attribute.ValueStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TheoryData UnresolvableUrlHtmlStringData
|
public static TheoryData UnresolvableUrlHtmlStringData
|
||||||
|
|
@ -267,7 +267,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
|
||||||
Assert.Equal("href", attribute.Name, StringComparer.Ordinal);
|
Assert.Equal("href", attribute.Name, StringComparer.Ordinal);
|
||||||
var attributeValue = Assert.IsType<HtmlString>(attribute.Value);
|
var attributeValue = Assert.IsType<HtmlString>(attribute.Value);
|
||||||
Assert.Equal(url.ToString(), attributeValue.ToString(), StringComparer.Ordinal);
|
Assert.Equal(url.ToString(), attributeValue.ToString(), StringComparer.Ordinal);
|
||||||
Assert.False(attribute.Minimized);
|
Assert.Equal(HtmlAttributeValueStyle.DoubleQuotes, attribute.ValueStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -296,7 +296,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
|
||||||
var attribute = Assert.Single(tagHelperOutput.Attributes);
|
var attribute = Assert.Single(tagHelperOutput.Attributes);
|
||||||
Assert.Equal("href", attribute.Name, StringComparer.Ordinal);
|
Assert.Equal("href", attribute.Name, StringComparer.Ordinal);
|
||||||
Assert.Equal(true, attribute.Value);
|
Assert.Equal(true, attribute.Value);
|
||||||
Assert.False(attribute.Minimized);
|
Assert.Equal(HtmlAttributeValueStyle.DoubleQuotes, attribute.ValueStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -646,12 +646,12 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedContent =
|
var expectedContent =
|
||||||
"<link encoded=\"contains "quotes"\" href=\"HtmlEncode[[/css/site.css]]\" " +
|
"<link encoded='contains \"quotes\"' href=\"HtmlEncode[[/css/site.css]]\" " +
|
||||||
"literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
"literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" />" +
|
"mixed='HtmlEncode[[HTML encoded]] and contains \"quotes\"' />" +
|
||||||
"<link encoded=\"contains "quotes"\" href=\"HtmlEncode[[/base.css]]\" " +
|
"<link encoded='contains \"quotes\"' href=\"HtmlEncode[[/base.css]]\" " +
|
||||||
"literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
"literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" />";
|
"mixed='HtmlEncode[[HTML encoded]] and contains \"quotes\"' />";
|
||||||
var mixed = new DefaultTagHelperContent();
|
var mixed = new DefaultTagHelperContent();
|
||||||
mixed.Append("HTML encoded");
|
mixed.Append("HTML encoded");
|
||||||
mixed.AppendHtml(" and contains \"quotes\"");
|
mixed.AppendHtml(" and contains \"quotes\"");
|
||||||
|
|
@ -659,18 +659,18 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
attributes: new TagHelperAttributeList
|
attributes: new TagHelperAttributeList
|
||||||
{
|
{
|
||||||
{ "asp-href-include", "**/*.css" },
|
{ "asp-href-include", "**/*.css" },
|
||||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
{ new TagHelperAttribute("encoded", new HtmlString("contains \"quotes\""), HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
{ "href", "/css/site.css" },
|
{ "href", "/css/site.css" },
|
||||||
{ "literal", "all HTML encoded" },
|
{ "literal", "all HTML encoded" },
|
||||||
{ "mixed", mixed },
|
{ new TagHelperAttribute("mixed", mixed, HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput(
|
var output = MakeTagHelperOutput(
|
||||||
"link",
|
"link",
|
||||||
attributes: new TagHelperAttributeList
|
attributes: new TagHelperAttributeList
|
||||||
{
|
{
|
||||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
{ new TagHelperAttribute("encoded", new HtmlString("contains \"quotes\""), HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
{ "literal", "all HTML encoded" },
|
{ "literal", "all HTML encoded" },
|
||||||
{ "mixed", mixed },
|
{ new TagHelperAttribute("mixed", mixed, HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
});
|
});
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
var viewContext = MakeViewContext();
|
var viewContext = MakeViewContext();
|
||||||
|
|
@ -843,10 +843,10 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
public void RenderLinkTags_FallbackHref_WithFileVersion_EncodesAsExpected()
|
public void RenderLinkTags_FallbackHref_WithFileVersion_EncodesAsExpected()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedContent = "<link encoded=\"contains "quotes"\" " +
|
var expectedContent = "<link encoded=\"contains \"quotes\"\" " +
|
||||||
"href=\"HtmlEncode[[/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\" " +
|
"href=\"HtmlEncode[[/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\" " +
|
||||||
"literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
"literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" />" +
|
"mixed=\"HtmlEncode[[HTML encoded]] and contains \"quotes\"\" />" +
|
||||||
Environment.NewLine +
|
Environment.NewLine +
|
||||||
"<meta name=\"x-stylesheet-fallback-test\" content=\"\" class=\"HtmlEncode[[hidden]]\" />" +
|
"<meta name=\"x-stylesheet-fallback-test\" content=\"\" class=\"HtmlEncode[[hidden]]\" />" +
|
||||||
"<script>!function(a,b,c){var d,e=document,f=e.getElementsByTagName(\"SCRIPT\")," +
|
"<script>!function(a,b,c){var d,e=document,f=e.getElementsByTagName(\"SCRIPT\")," +
|
||||||
|
|
@ -961,8 +961,10 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("link", output.TagName);
|
Assert.Equal("link", output.TagName);
|
||||||
Assert.Equal("/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk", output.Attributes["href"].Value);
|
Assert.Equal("/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk", output.Attributes["href"].Value);
|
||||||
Assert.Equal("<link rel=\"stylesheet\" href=\"HtmlEncode[[/base.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\" />",
|
var content = HtmlContentUtilities.HtmlContentToString(output.PostElement, new HtmlTestEncoder());
|
||||||
output.PostElement.GetContent());
|
Assert.Equal(
|
||||||
|
"<link rel=\"stylesheet\" href=\"HtmlEncode[[/base.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\" />",
|
||||||
|
content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ViewContext MakeViewContext(string requestPathBase = null)
|
private static ViewContext MakeViewContext(string requestPathBase = null)
|
||||||
|
|
|
||||||
|
|
@ -623,11 +623,11 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedContent =
|
var expectedContent =
|
||||||
"<script encoded=\"contains "quotes"\" literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
"<script encoded='contains \"quotes\"' literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" " +
|
"mixed='HtmlEncode[[HTML encoded]] and contains \"quotes\"' " +
|
||||||
"src=\"HtmlEncode[[/js/site.js]]\"></script>" +
|
"src=\"HtmlEncode[[/js/site.js]]\"></script>" +
|
||||||
"<script encoded=\"contains "quotes"\" literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
"<script encoded='contains \"quotes\"' literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" " +
|
"mixed='HtmlEncode[[HTML encoded]] and contains \"quotes\"' " +
|
||||||
"src=\"HtmlEncode[[/common.js]]\"></script>";
|
"src=\"HtmlEncode[[/common.js]]\"></script>";
|
||||||
var mixed = new DefaultTagHelperContent();
|
var mixed = new DefaultTagHelperContent();
|
||||||
mixed.Append("HTML encoded");
|
mixed.Append("HTML encoded");
|
||||||
|
|
@ -636,18 +636,18 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
attributes: new TagHelperAttributeList
|
attributes: new TagHelperAttributeList
|
||||||
{
|
{
|
||||||
{ "asp-src-include", "**/*.js" },
|
{ "asp-src-include", "**/*.js" },
|
||||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
{ new TagHelperAttribute("encoded", new HtmlString("contains \"quotes\""), HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
{ "literal", "all HTML encoded" },
|
{ "literal", "all HTML encoded" },
|
||||||
{ "mixed", mixed },
|
{ new TagHelperAttribute("mixed", mixed, HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
{ "src", "/js/site.js" },
|
{ "src", "/js/site.js" },
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput(
|
var output = MakeTagHelperOutput(
|
||||||
"script",
|
"script",
|
||||||
attributes: new TagHelperAttributeList
|
attributes: new TagHelperAttributeList
|
||||||
{
|
{
|
||||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
{ new TagHelperAttribute("encoded", new HtmlString("contains \"quotes\""), HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
{ "literal", "all HTML encoded"},
|
{ "literal", "all HTML encoded"},
|
||||||
{ "mixed", mixed},
|
{ new TagHelperAttribute("mixed", mixed, HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
});
|
});
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
var viewContext = MakeViewContext();
|
var viewContext = MakeViewContext();
|
||||||
|
|
@ -786,9 +786,9 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("script", output.TagName);
|
Assert.Equal("script", output.TagName);
|
||||||
Assert.Equal("/js/site.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk", output.Attributes["src"].Value);
|
Assert.Equal("/js/site.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk", output.Attributes["src"].Value);
|
||||||
Assert.Equal(Environment.NewLine + "<script>(isavailable()||document.write(\"<script src=" +
|
Assert.Equal(Environment.NewLine + "<script>(isavailable()||document.write(\"JavaScriptEncode[[<script " +
|
||||||
"\\\"JavaScriptEncode[[HtmlEncode[[fallback.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]]]\\\"" +
|
"src=\"HtmlEncode[[fallback.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\">" +
|
||||||
"><\\/script>\"));</script>", output.PostElement.GetContent());
|
"</script>]]\"));</script>", output.PostElement.GetContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -796,16 +796,14 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedContent =
|
var expectedContent =
|
||||||
"<script encoded=\"contains "quotes"\" literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
"<script encoded='contains \"quotes\"' literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" " +
|
"mixed='HtmlEncode[[HTML encoded]] and contains \"quotes\"' " +
|
||||||
"src=\"HtmlEncode[[/js/site.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\"></script>" +
|
"src=\"HtmlEncode[[/js/site.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\"></script>" +
|
||||||
Environment.NewLine +
|
Environment.NewLine +
|
||||||
"<script>(isavailable()||document.write(\"<script " +
|
"<script>(isavailable()||document.write(\"JavaScriptEncode[[<script encoded=\'contains \"quotes\"\' " +
|
||||||
"JavaScriptEncode[[encoded]]=\\\"JavaScriptEncode[[contains "quotes"]]\\\" " +
|
"literal=\"HtmlEncode[[all HTML encoded]]\" mixed=\'HtmlEncode[[HTML encoded]] and contains " +
|
||||||
"JavaScriptEncode[[literal]]=\\\"JavaScriptEncode[[HtmlEncode[[all HTML encoded]]]]\\\" " +
|
"\"quotes\"' src=\"HtmlEncode[[fallback.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\">" +
|
||||||
"JavaScriptEncode[[mixed]]=\\\"JavaScriptEncode[[HtmlEncode[[HTML encoded]] and contains "quotes"]]\\\" " +
|
"</script>]]\"));</script>";
|
||||||
"src=\\\"JavaScriptEncode[[HtmlEncode[[fallback.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]]]\\\">" +
|
|
||||||
"<\\/script>\"));</script>";
|
|
||||||
var mixed = new DefaultTagHelperContent();
|
var mixed = new DefaultTagHelperContent();
|
||||||
mixed.Append("HTML encoded");
|
mixed.Append("HTML encoded");
|
||||||
mixed.AppendHtml(" and contains \"quotes\"");
|
mixed.AppendHtml(" and contains \"quotes\"");
|
||||||
|
|
@ -815,18 +813,18 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
{ "asp-append-version", "true" },
|
{ "asp-append-version", "true" },
|
||||||
{ "asp-fallback-src-include", "fallback.js" },
|
{ "asp-fallback-src-include", "fallback.js" },
|
||||||
{ "asp-fallback-test", "isavailable()" },
|
{ "asp-fallback-test", "isavailable()" },
|
||||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
{ new TagHelperAttribute("encoded", new HtmlString("contains \"quotes\""), HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
{ "literal", "all HTML encoded" },
|
{ "literal", "all HTML encoded" },
|
||||||
{ "mixed", mixed },
|
{ new TagHelperAttribute("mixed", mixed, HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
{ "src", "/js/site.js" },
|
{ "src", "/js/site.js" },
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput(
|
var output = MakeTagHelperOutput(
|
||||||
"script",
|
"script",
|
||||||
attributes: new TagHelperAttributeList
|
attributes: new TagHelperAttributeList
|
||||||
{
|
{
|
||||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
{ new TagHelperAttribute("encoded", new HtmlString("contains \"quotes\""), HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
{ "literal", "all HTML encoded" },
|
{ "literal", "all HTML encoded" },
|
||||||
{ "mixed", mixed },
|
{ new TagHelperAttribute("mixed", mixed, HtmlAttributeValueStyle.SingleQuotes) },
|
||||||
});
|
});
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
var viewContext = MakeViewContext();
|
var viewContext = MakeViewContext();
|
||||||
|
|
|
||||||
|
|
@ -979,13 +979,21 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
// Normal comparer (TagHelperAttribute.Equals()) doesn't care about the Name case, in tests we do.
|
// Normal comparer (TagHelperAttribute.Equals()) doesn't care about the Name case, in tests we do.
|
||||||
return attributeX != null &&
|
return attributeX != null &&
|
||||||
string.Equals(attributeX.Name, attributeY.Name, StringComparison.Ordinal) &&
|
string.Equals(attributeX.Name, attributeY.Name, StringComparison.Ordinal) &&
|
||||||
attributeX.Minimized == attributeY.Minimized &&
|
attributeX.ValueStyle == attributeY.ValueStyle &&
|
||||||
(attributeX.Minimized || Equals(attributeX.Value, attributeY.Value));
|
(attributeX.ValueStyle == HtmlAttributeValueStyle.Minimized || Equals(attributeX.Value, attributeY.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetHashCode(TagHelperAttribute attribute)
|
public int GetHashCode(TagHelperAttribute attribute)
|
||||||
{
|
{
|
||||||
return attribute.GetHashCode();
|
// Manually combine hash codes here. We can't reference HashCodeCombiner because we have internals visible
|
||||||
|
// from Mvc.Core and Mvc.TagHelpers; both of which reference HashCodeCombiner.
|
||||||
|
var baseHashCode = 0x1505L;
|
||||||
|
var attributeHashCode = attribute.GetHashCode();
|
||||||
|
var combinedHash = ((baseHashCode << 5) + baseHashCode) ^ attributeHashCode;
|
||||||
|
var nameHashCode = StringComparer.Ordinal.GetHashCode(attribute.Name);
|
||||||
|
combinedHash = ((combinedHash << 5) + combinedHash) ^ nameHashCode;
|
||||||
|
|
||||||
|
return combinedHash.GetHashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue