Correct HTML and JavaScript encoding of `<link>` and `<script>` attribute values
- #4083 - `<link>` tag helper did not HTML encode `href` values in fallback elements - `<script>` tag helper did not correctly encode any attribute value in fallback elements - e.g. double quotes in literal strings would slip through - only needed to change one existing unit test (!!); so added a bunch nit: use `Process()`, not `ProcessAsync()` in `<script>` tag helper tests
This commit is contained in:
parent
f1fa1bd8f4
commit
ffe2d2609a
|
|
@ -4,14 +4,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
using Microsoft.AspNetCore.Mvc.TagHelpers.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
|
|
@ -362,15 +360,21 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
firstAdded = true;
|
||||
}
|
||||
|
||||
// fallbackHrefs come from bound attributes and globbing. Must always be non-null.
|
||||
// fallbackHrefs come from bound attributes (a C# context) and globbing. Must always be non-null.
|
||||
Debug.Assert(fallbackHrefs[i] != null);
|
||||
|
||||
var valueToWrite = fallbackHrefs[i];
|
||||
if (AppendVersion == true)
|
||||
{
|
||||
valueToWrite = _fileVersionProvider.AddFileVersionToPath(fallbackHrefs[i]);
|
||||
}
|
||||
|
||||
builder.AppendHtml(JavaScriptEncoder.Encode(valueToWrite));
|
||||
// Must HTML-encode the href attribute value to ensure the written <link/> element is valid. Must also
|
||||
// JavaScript-encode that value to ensure the doc.write() statement is valid.
|
||||
valueToWrite = HtmlEncoder.Encode(valueToWrite);
|
||||
valueToWrite = JavaScriptEncoder.Encode(valueToWrite);
|
||||
|
||||
builder.AppendHtml(valueToWrite);
|
||||
builder.AppendHtml("\"");
|
||||
}
|
||||
builder.AppendHtml("]);");
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@
|
|||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
|
|
@ -39,6 +42,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
private const string AppendVersionAttributeName = "asp-append-version";
|
||||
private static readonly Func<Mode, Mode, int> Compare = (a, b) => a - b;
|
||||
private FileVersionProvider _fileVersionProvider;
|
||||
private StringWriter _stringWriter;
|
||||
|
||||
private static readonly ModeAttributes<Mode>[] ModeDetails = new[] {
|
||||
// Regular src with file version alone
|
||||
|
|
@ -174,6 +178,20 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
// Internal for ease of use when testing.
|
||||
protected internal GlobbingUrlBuilder GlobbingUrlBuilder { get; set; }
|
||||
|
||||
// Shared writer for determining the string content of a TagHelperAttribute's Value.
|
||||
private StringWriter StringWriter
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_stringWriter == null)
|
||||
{
|
||||
_stringWriter = new StringWriter();
|
||||
}
|
||||
|
||||
return _stringWriter;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
|
|
@ -300,7 +318,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var encodedKey = JavaScriptEncoder.Encode(attribute.Name);
|
||||
var attributeValue = attribute.Value.ToString();
|
||||
var attributeValue = GetAttributeValue(attribute.Value);
|
||||
var encodedValue = JavaScriptEncoder.Encode(attributeValue);
|
||||
|
||||
AppendAttribute(builder, encodedKey, encodedValue, escapeQuotes: true);
|
||||
|
|
@ -324,6 +342,34 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
}
|
||||
}
|
||||
|
||||
private string GetAttributeValue(object value)
|
||||
{
|
||||
string stringValue;
|
||||
var htmlEncodedString = value as HtmlEncodedString;
|
||||
if (htmlEncodedString != 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 = htmlEncodedString.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 HtmlEncodedStrings are not re-encoded.
|
||||
var builder = writer.GetStringBuilder();
|
||||
builder.Replace("\"", """);
|
||||
|
||||
stringValue = builder.ToString();
|
||||
builder.Clear();
|
||||
}
|
||||
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
private void AppendEncodedVersionedSrc(
|
||||
string srcName,
|
||||
string srcValue,
|
||||
|
|
@ -337,6 +383,10 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
|
||||
if (generateForDocumentWrite)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,63 +39,63 @@
|
|||
|
||||
<!-- Fallback to static href -->
|
||||
<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[[/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 -->
|
||||
|
||||
<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[[/styles/site.css]]"]);</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]]]]"]);</script>
|
||||
|
||||
<!-- Fallback from globbed href with exclude to static href -->
|
||||
|
||||
<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[[/styles/site.css]]"]);</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]]]]"]);</script>
|
||||
|
||||
<!-- Fallback from globbed and static href to static href -->
|
||||
<link href="HtmlEncode[[styles/site.min.css]]" rel="stylesheet" data-extra="test" /><link href="HtmlEncode[[/styles/site.css]]" rel="stylesheet" data-extra="test" />
|
||||
<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[[/styles/site.css]]"]);</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]]]]"]);</script>
|
||||
|
||||
<!-- Fallback from globbed and static href with exclude to static href -->
|
||||
<link href="HtmlEncode[[styles/site.min.css]]" rel="stylesheet" data-extra="test" />
|
||||
<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[[/styles/site.css]]"]);</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]]]]"]);</script>
|
||||
|
||||
<!-- Fallback to static href with no primary href -->
|
||||
<link rel="stylesheet" data-extra="test">
|
||||
<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[[/styles/site.css]]"]);</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]]]]"]);</script>
|
||||
|
||||
<!-- Fallback to globbed href -->
|
||||
<link href="HtmlEncode[[/styles/site.min.css]]" rel="stylesheet" data-extra="test" />
|
||||
<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[[/styles/site.css]]"]);</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]]]]"]);</script>
|
||||
|
||||
<!-- Fallback to static and globbed href -->
|
||||
<link href="HtmlEncode[[/styles/site.min.css]]" rel="stylesheet" data-extra="test" />
|
||||
<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[[/styles/site.css]]","JavaScriptEncode[[/styles/sub/site2.css]]"]);</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]]]]","JavaScriptEncode[[HtmlEncode[[/styles/sub/site2.css]]]]"]);</script>
|
||||
|
||||
<!-- Fallback to static and globbed href should dedupe -->
|
||||
<link href="HtmlEncode[[/styles/site.min.css]]" rel="stylesheet" data-extra="test" />
|
||||
<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[[/styles/site.css]]"]);</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]]]]"]);</script>
|
||||
|
||||
<!-- Fallback to static and globbed href with exclude -->
|
||||
<link href="HtmlEncode[[/styles/site.min.css]]" rel="stylesheet" data-extra="test" />
|
||||
<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[[/styles/site.css]]","JavaScriptEncode[[/styles/sub/site2.css]]"]);</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]]]]","JavaScriptEncode[[HtmlEncode[[/styles/sub/site2.css]]]]"]);</script>
|
||||
|
||||
<!-- Fallback from globbed href to glbobed href -->
|
||||
|
||||
<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[[/styles/site.css]]"]);</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]]]]"]);</script>
|
||||
|
||||
<!-- Fallback from globbed href with exclude to globbed href -->
|
||||
|
||||
<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[[/styles/site.css]]"]);</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]]]]"]);</script>
|
||||
|
||||
<!-- Fallback from globbed and static href to globbed href -->
|
||||
<link href="HtmlEncode[[styles/site.min.css]]" rel="stylesheet" data-extra="test" /><link href="HtmlEncode[[/styles/site.css]]" rel="stylesheet" data-extra="test" />
|
||||
<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[[/styles/site.css]]"]);</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]]]]"]);</script>
|
||||
|
||||
<!-- Fallback from globbed and static href with exclude to globbed href -->
|
||||
<link href="HtmlEncode[[styles/site.min.css]]" rel="stylesheet" data-extra="test">
|
||||
<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[[/styles/site.css]]"]);</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]]]]"]);</script>
|
||||
|
||||
<!-- Kitchen sink, all the attributes -->
|
||||
<link href="HtmlEncode[[styles/site.min.css]]" rel="stylesheet" data-extra="test" />
|
||||
<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[[/styles/site.css]]","JavaScriptEncode[[/styles/sub/site2.css]]"]);</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]]]]","JavaScriptEncode[[HtmlEncode[[/styles/sub/site2.css]]]]"]);</script>
|
||||
|
||||
<!-- Fallback to globbed href that doesn't exist -->
|
||||
<link href="HtmlEncode[[/styles/site.min.css]]" rel="stylesheet" data-extra="test" />
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
|
||||
<!-- Fallback with file version -->
|
||||
<link href="HtmlEncode[[/styles/site.min.css]]" rel="stylesheet" data-extra="test">
|
||||
<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[[/styles/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc]]"]);</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?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc]]]]"]);</script>
|
||||
|
||||
<!-- Globbed link tag with existing file, static href and file version -->
|
||||
<link href="HtmlEncode[[/styles/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc]]" rel="stylesheet" /><link href="HtmlEncode[[/styles/sub/site2.css?v=30cxPex0tA9xEatW7f1Qhnn8tVLAHgE6xwIZhESq0y0]]" rel="stylesheet" /><link href="HtmlEncode[[/styles/sub/site3.css?v=fSxxOr1Q4Dq2uPuzlju5UYGuK0SKABI-ghvaIGEsZDc]]" rel="stylesheet" /><link href="HtmlEncode[[/styles/sub/site3.min.css?v=s8JMmAZxBn0dzuhRtQ0wgOvNBK4XRJRWEC2wfzsVF9M]]" rel="stylesheet" />
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
<!-- Fallback to static href -->
|
||||
<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\u0026c=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 -->
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
|
@ -13,27 +13,27 @@
|
|||
<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.
|
||||
</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[/styles/site.js?a=b&c=d]]\" JavaScriptEncode[[data-foo]]=\"JavaScriptEncode[[foo-data2]]\" JavaScriptEncode[[title]]=\"JavaScriptEncode[[<the title>]]\"><\/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 src="HtmlEncode[[/blank.js]]" title=""the" title">
|
||||
// Fallback to globbed src
|
||||
</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[/styles/site.js]]\" JavaScriptEncode[[title]]=\"JavaScriptEncode[["the" title]]\"><\/script>"));</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js]]]]\" JavaScriptEncode[[title]]=\"JavaScriptEncode[["the" title]]\"><\/script>"));</script>
|
||||
|
||||
<script src="HtmlEncode[[/blank.js]]">
|
||||
// Fallback to globbed src with exclude
|
||||
</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[/styles/site.js]]\"><\/script><script src=\"JavaScriptEncode[[/styles/sub/site2.js]]\"><\/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 src="HtmlEncode[[/blank.js]]">
|
||||
// Fallback to globbed and static src
|
||||
</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[/styles/site.js]]\"><\/script><script src=\"JavaScriptEncode[[/styles/sub/site2.js]]\"><\/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 src="HtmlEncode[[/blank.js]]">
|
||||
// Fallback to globbed and static src should de-dupe
|
||||
</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[/styles/site.js]]\"><\/script>"));</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js]]]]\"><\/script>"));</script>
|
||||
|
||||
<script src="HtmlEncode[[/blank.js]]">
|
||||
// Fallback to globbed src with missing include
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
<script src="HtmlEncode[[/blank.js]]">
|
||||
// Fallback to static and globbed src with missing include
|
||||
</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[/styles/site.js]]\"><\/script>"));</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js]]]]\"><\/script>"));</script>
|
||||
|
||||
<script src="HtmlEncode[[/blank.js]]">
|
||||
// Fallback to globbed src outside of webroot
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
<script data-foo="foo-data3">
|
||||
// Valid TagHelper (although no src is provided) script with comment in body, and extra properties.
|
||||
</script>
|
||||
<script>(false||document.write("<script JavaScriptEncode[[data-foo]]=\"JavaScriptEncode[[foo-data3]]\" src=\"JavaScriptEncode[[/styles/site.js]]\"><\/script>"));</script>
|
||||
<script>(false||document.write("<script JavaScriptEncode[[data-foo]]=\"JavaScriptEncode[[foo-data3]]\" src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js]]]]\"><\/script>"));</script>
|
||||
|
||||
<script src="HtmlEncode[[/blank.js]]">
|
||||
// Invalid TagHelper script with comment in body.
|
||||
|
|
@ -98,12 +98,12 @@
|
|||
<script src="HtmlEncode[[/blank.js]]">
|
||||
// TagHelper script with comment in body, and file version.
|
||||
</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]\"><\/script>"));</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]]]\"><\/script>"));</script>
|
||||
|
||||
<script src="HtmlEncode[[/blank.js]]">
|
||||
// Fallback to globbed src with file version.
|
||||
</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]\"><\/script>"));</script>
|
||||
<script>(false||document.write("<script src=\"JavaScriptEncode[[HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]]]\"><\/script>"));</script>
|
||||
|
||||
<script src="HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]">
|
||||
// Regular script with comment in body, and file version.
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@
|
|||
<script src="/blank.js?a=b&c=d" data-foo="foo-data2" title="<the title>">
|
||||
// TagHelper script with comment in body, and extra properties.
|
||||
</script>
|
||||
<script>(false||document.write("<script src=\"\/styles\/site.js?a=b\u0026c=d\" data-foo=\"foo-data2\" title=\"\u0026lt;the title\u003E\"><\/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 src="/blank.js" title=""the" title">
|
||||
// Fallback to globbed src
|
||||
</script>
|
||||
<script>(false||document.write("<script src=\"\/styles\/site.js\" title=\"\u0022the\u0022 title\"><\/script>"));</script>
|
||||
<script>(false||document.write("<script src=\"\/styles\/site.js\" title=\"\u0026quot;the\u0026quot; title\"><\/script>"));</script>
|
||||
|
||||
<script src="/blank.js">
|
||||
// Fallback to globbed src with exclude
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Mvc.Razor;
|
|||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
using Microsoft.AspNetCore.Mvc.TagHelpers.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.TestCommon;
|
||||
using Microsoft.AspNetCore.Mvc.ViewEngines;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
|
|
@ -403,6 +404,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
// Assert
|
||||
Assert.Null(output.TagName);
|
||||
Assert.True(output.IsContentModified);
|
||||
Assert.True(output.Content.IsEmpty);
|
||||
Assert.True(output.PostElement.IsModified);
|
||||
}
|
||||
|
||||
|
|
@ -595,6 +597,8 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
public void RendersLinkTagsForGlobbedHrefResults()
|
||||
{
|
||||
// Arrange
|
||||
var expectedContent = "<link rel=\"stylesheet\" href=\"HtmlEncode[[/css/site.css]]\" />" +
|
||||
"<link rel=\"stylesheet\" href=\"HtmlEncode[[/base.css]]\" />";
|
||||
var context = MakeTagHelperContext(
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
|
|
@ -634,24 +638,41 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
// Assert
|
||||
Assert.Equal("link", output.TagName);
|
||||
Assert.Equal("/css/site.css", output.Attributes["href"].Value);
|
||||
Assert.Equal("<link rel=\"stylesheet\" href=\"HtmlEncode[[/base.css]]\" />", output.PostElement.GetContent());
|
||||
var content = HtmlContentUtilities.HtmlContentToString(output, new HtmlTestEncoder());
|
||||
Assert.Equal(expectedContent, content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RendersLinkTagsForGlobbedHrefResults_UsingProvidedEncoder()
|
||||
public void RendersLinkTagsForGlobbedHrefResults_EncodesAsExpected()
|
||||
{
|
||||
// Arrange
|
||||
var expectedContent =
|
||||
"<link encoded=\"contains "quotes"\" href=\"HtmlEncode[[/css/site.css]]\" " +
|
||||
"literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" />" +
|
||||
"<link encoded=\"contains "quotes"\" href=\"HtmlEncode[[/base.css]]\" " +
|
||||
"literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" />";
|
||||
var mixed = new DefaultTagHelperContent();
|
||||
mixed.Append("HTML encoded");
|
||||
mixed.AppendHtml(" and contains \"quotes\"");
|
||||
var context = MakeTagHelperContext(
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
new TagHelperAttribute("rel", "stylesheet"),
|
||||
new TagHelperAttribute("href", "/css/site.css"),
|
||||
new TagHelperAttribute("asp-href-include", "**/*.css")
|
||||
{ "asp-href-include", "**/*.css" },
|
||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
||||
{ "href", "/css/site.css" },
|
||||
{ "literal", "all HTML encoded" },
|
||||
{ "mixed", mixed },
|
||||
});
|
||||
var output = MakeTagHelperOutput(
|
||||
"link",
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
||||
{ "literal", "all HTML encoded" },
|
||||
{ "mixed", mixed },
|
||||
});
|
||||
var output = MakeTagHelperOutput("link", attributes: new TagHelperAttributeList
|
||||
{
|
||||
new TagHelperAttribute("rel", "stylesheet"),
|
||||
});
|
||||
var hostingEnvironment = MakeHostingEnvironment();
|
||||
var viewContext = MakeViewContext();
|
||||
var globbingUrlBuilder = new Mock<GlobbingUrlBuilder>(
|
||||
|
|
@ -669,9 +690,9 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
MakeUrlHelperFactory())
|
||||
{
|
||||
GlobbingUrlBuilder = globbingUrlBuilder.Object,
|
||||
ViewContext = viewContext,
|
||||
Href = "/css/site.css",
|
||||
HrefInclude = "**/*.css",
|
||||
ViewContext = viewContext,
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
@ -680,12 +701,12 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
// Assert
|
||||
Assert.Equal("link", output.TagName);
|
||||
Assert.Equal("/css/site.css", output.Attributes["href"].Value);
|
||||
Assert.Equal("<link rel=\"HtmlEncode[[stylesheet]]\" href=\"HtmlEncode[[/base.css]]\" />",
|
||||
output.PostElement.GetContent());
|
||||
var content = HtmlContentUtilities.HtmlContentToString(output, new HtmlTestEncoder());
|
||||
Assert.Equal(expectedContent, content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RendersLinkTags_AddsFileVersion()
|
||||
public void RendersLinkTags_WithFileVersion()
|
||||
{
|
||||
// Arrange
|
||||
var context = MakeTagHelperContext(
|
||||
|
|
@ -723,7 +744,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void RendersLinkTags_AddsFileVersion_WithRequestPathBase()
|
||||
public void RendersLinkTags_WithFileVersion_AndRequestPathBase()
|
||||
{
|
||||
// Arrange
|
||||
var context = MakeTagHelperContext(
|
||||
|
|
@ -761,7 +782,143 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void RendersLinkTags_GlobbedHref_AddsFileVersion()
|
||||
public void RenderLinkTags_FallbackHref_WithFileVersion()
|
||||
{
|
||||
// Arrange
|
||||
var expectedPostElement = Environment.NewLine +
|
||||
"<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]+'\"/>')}(" +
|
||||
"\"JavaScriptEncode[[visibility]]\",\"JavaScriptEncode[[hidden]]\"," +
|
||||
"[\"JavaScriptEncode[[HtmlEncode[[/fallback.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]]]\"]);" +
|
||||
"</script>";
|
||||
var context = MakeTagHelperContext(
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
{ "asp-append-version", "true" },
|
||||
{ "asp-fallback-href-include", "**/fallback.css" },
|
||||
{ "asp-fallback-test-class", "hidden" },
|
||||
{ "asp-fallback-test-property", "visibility" },
|
||||
{ "asp-fallback-test-value", "hidden" },
|
||||
{ "href", "/css/site.css" },
|
||||
});
|
||||
var output = MakeTagHelperOutput("link", attributes: new TagHelperAttributeList());
|
||||
var hostingEnvironment = MakeHostingEnvironment();
|
||||
var viewContext = MakeViewContext();
|
||||
var globbingUrlBuilder = new Mock<GlobbingUrlBuilder>(
|
||||
new TestFileProvider(),
|
||||
Mock.Of<IMemoryCache>(),
|
||||
PathString.Empty);
|
||||
globbingUrlBuilder.Setup(g => g.BuildUrlList(null, "**/fallback.css", null))
|
||||
.Returns(new[] { "/fallback.css" });
|
||||
|
||||
var helper = new LinkTagHelper(
|
||||
MakeHostingEnvironment(),
|
||||
MakeCache(),
|
||||
new HtmlTestEncoder(),
|
||||
new JavaScriptTestEncoder(),
|
||||
MakeUrlHelperFactory())
|
||||
{
|
||||
AppendVersion = true,
|
||||
Href = "/css/site.css",
|
||||
FallbackHrefInclude = "**/fallback.css",
|
||||
FallbackTestClass = "hidden",
|
||||
FallbackTestProperty = "visibility",
|
||||
FallbackTestValue = "hidden",
|
||||
GlobbingUrlBuilder = globbingUrlBuilder.Object,
|
||||
ViewContext = viewContext,
|
||||
};
|
||||
|
||||
// Act
|
||||
helper.Process(context, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("link", output.TagName);
|
||||
Assert.Equal("/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk", output.Attributes["href"].Value);
|
||||
Assert.Equal(expectedPostElement, output.PostElement.GetContent());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderLinkTags_FallbackHref_WithFileVersion_EncodesAsExpected()
|
||||
{
|
||||
// Arrange
|
||||
var expectedContent = "<link encoded=\"contains "quotes"\" " +
|
||||
"href=\"HtmlEncode[[/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\" " +
|
||||
"literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" />" +
|
||||
Environment.NewLine +
|
||||
"<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[[/fallback.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]]]\"]);" +
|
||||
"</script>";
|
||||
var mixed = new DefaultTagHelperContent();
|
||||
mixed.Append("HTML encoded");
|
||||
mixed.AppendHtml(" and contains \"quotes\"");
|
||||
var context = MakeTagHelperContext(
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
{ "asp-append-version", "true" },
|
||||
{ "asp-fallback-href-include", "**/fallback.css" },
|
||||
{ "asp-fallback-test-class", "hidden" },
|
||||
{ "asp-fallback-test-property", "visibility" },
|
||||
{ "asp-fallback-test-value", "hidden" },
|
||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
||||
{ "href", "/css/site.css" },
|
||||
{ "literal", "all HTML encoded" },
|
||||
{ "mixed", mixed },
|
||||
});
|
||||
var output = MakeTagHelperOutput(
|
||||
"link",
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
||||
{ "literal", "all HTML encoded" },
|
||||
{ "mixed", mixed },
|
||||
});
|
||||
var hostingEnvironment = MakeHostingEnvironment();
|
||||
var viewContext = MakeViewContext();
|
||||
var globbingUrlBuilder = new Mock<GlobbingUrlBuilder>(
|
||||
new TestFileProvider(),
|
||||
Mock.Of<IMemoryCache>(),
|
||||
PathString.Empty);
|
||||
globbingUrlBuilder.Setup(g => g.BuildUrlList(null, "**/fallback.css", null))
|
||||
.Returns(new[] { "/fallback.css" });
|
||||
|
||||
var helper = new LinkTagHelper(
|
||||
MakeHostingEnvironment(),
|
||||
MakeCache(),
|
||||
new HtmlTestEncoder(),
|
||||
new JavaScriptTestEncoder(),
|
||||
MakeUrlHelperFactory())
|
||||
{
|
||||
AppendVersion = true,
|
||||
FallbackHrefInclude = "**/fallback.css",
|
||||
FallbackTestClass = "hidden",
|
||||
FallbackTestProperty = "visibility",
|
||||
FallbackTestValue = "hidden",
|
||||
GlobbingUrlBuilder = globbingUrlBuilder.Object,
|
||||
Href = "/css/site.css",
|
||||
ViewContext = viewContext,
|
||||
};
|
||||
|
||||
// Act
|
||||
helper.Process(context, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("link", output.TagName);
|
||||
Assert.Equal("/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk", output.Attributes["href"].Value);
|
||||
var content = HtmlContentUtilities.HtmlContentToString(output, new HtmlTestEncoder());
|
||||
Assert.Equal(expectedContent, content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RendersLinkTags_GlobbedHref_WithFileVersion()
|
||||
{
|
||||
// Arrange
|
||||
var context = MakeTagHelperContext(
|
||||
|
|
@ -848,7 +1005,10 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
tagName,
|
||||
attributes,
|
||||
getChildContentAsync: (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(
|
||||
new DefaultTagHelperContent()));
|
||||
new DefaultTagHelperContent()))
|
||||
{
|
||||
TagMode = TagMode.SelfClosing,
|
||||
};
|
||||
}
|
||||
|
||||
private static IHostingEnvironment MakeHostingEnvironment()
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Mvc.Razor;
|
|||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
using Microsoft.AspNetCore.Mvc.TagHelpers.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.TestCommon;
|
||||
using Microsoft.AspNetCore.Mvc.ViewEngines;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
|
|
@ -95,7 +96,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(LinkTagHelperTest.MultiAttributeSameNameData), MemberType = typeof(LinkTagHelperTest))]
|
||||
public async Task HandlesMultipleAttributesSameNameCorrectly(TagHelperAttributeList outputAttributes)
|
||||
public void HandlesMultipleAttributesSameNameCorrectly(TagHelperAttributeList outputAttributes)
|
||||
{
|
||||
// Arrange
|
||||
var allAttributes = new TagHelperAttributeList(
|
||||
|
|
@ -134,7 +135,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
expectedAttributes.Add(new TagHelperAttribute("src", "/blank.js"));
|
||||
|
||||
// Act
|
||||
await helper.ProcessAsync(tagHelperContext, output);
|
||||
helper.Process(tagHelperContext, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedAttributes, output.Attributes);
|
||||
|
|
@ -265,7 +266,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(RunsWhenRequiredAttributesArePresent_Data))]
|
||||
public async Task RunsWhenRequiredAttributesArePresent(
|
||||
public void RunsWhenRequiredAttributesArePresent(
|
||||
TagHelperAttributeList attributes,
|
||||
Action<ScriptTagHelper> setProperties)
|
||||
{
|
||||
|
|
@ -294,7 +295,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
setProperties(helper);
|
||||
|
||||
// Act
|
||||
await helper.ProcessAsync(context, output);
|
||||
helper.Process(context, output);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(output.TagName);
|
||||
|
|
@ -362,7 +363,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(RunsWhenRequiredAttributesArePresent_NoSrc_Data))]
|
||||
public async Task RunsWhenRequiredAttributesArePresent_NoSrc(
|
||||
public void RunsWhenRequiredAttributesArePresent_NoSrc(
|
||||
TagHelperAttributeList attributes,
|
||||
Action<ScriptTagHelper> setProperties)
|
||||
{
|
||||
|
|
@ -391,11 +392,12 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
setProperties(helper);
|
||||
|
||||
// Act
|
||||
await helper.ProcessAsync(context, output);
|
||||
helper.Process(context, output);
|
||||
|
||||
// Assert
|
||||
Assert.Null(output.TagName);
|
||||
Assert.True(output.IsContentModified);
|
||||
Assert.True(output.Content.IsEmpty);
|
||||
Assert.True(output.PostElement.IsModified);
|
||||
}
|
||||
|
||||
|
|
@ -498,7 +500,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DoesNotRunWhenAllRequiredAttributesAreMissing()
|
||||
public void DoesNotRunWhenAllRequiredAttributesAreMissing()
|
||||
{
|
||||
// Arrange
|
||||
var tagHelperContext = MakeTagHelperContext();
|
||||
|
|
@ -516,7 +518,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
};
|
||||
|
||||
// Act
|
||||
await helper.ProcessAsync(tagHelperContext, output);
|
||||
helper.Process(tagHelperContext, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("script", output.TagName);
|
||||
|
|
@ -526,7 +528,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PreservesOrderOfNonSrcAttributes()
|
||||
public void PreservesOrderOfNonSrcAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var tagHelperContext = MakeTagHelperContext(
|
||||
|
|
@ -564,7 +566,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
};
|
||||
|
||||
// Act
|
||||
await helper.ProcessAsync(tagHelperContext, output);
|
||||
helper.Process(tagHelperContext, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("data-extra", output.Attributes[0].Name);
|
||||
|
|
@ -573,9 +575,11 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RendersScriptTagsForGlobbedSrcResults()
|
||||
public void RendersScriptTagsForGlobbedSrcResults()
|
||||
{
|
||||
// Arrange
|
||||
var expectedContent = "<script src=\"HtmlEncode[[/js/site.js]]\"></script>" +
|
||||
"<script src=\"HtmlEncode[[/common.js]]\"></script>";
|
||||
var context = MakeTagHelperContext(
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
|
|
@ -606,25 +610,46 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
};
|
||||
|
||||
// Act
|
||||
await helper.ProcessAsync(context, output);
|
||||
helper.Process(context, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("script", output.TagName);
|
||||
Assert.Equal("/js/site.js", output.Attributes["src"].Value);
|
||||
Assert.Equal("<script src=\"HtmlEncode[[/common.js]]\"></script>", output.PostElement.GetContent());
|
||||
var content = HtmlContentUtilities.HtmlContentToString(output, new HtmlTestEncoder());
|
||||
Assert.Equal(expectedContent, content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RendersScriptTagsForGlobbedSrcResults_UsesProvidedEncoder()
|
||||
public void RendersScriptTagsForGlobbedSrcResults_EncodesAsExpected()
|
||||
{
|
||||
// Arrange
|
||||
var expectedContent =
|
||||
"<script encoded=\"contains "quotes"\" literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" " +
|
||||
"src=\"HtmlEncode[[/js/site.js]]\"></script>" +
|
||||
"<script encoded=\"contains "quotes"\" literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" " +
|
||||
"src=\"HtmlEncode[[/common.js]]\"></script>";
|
||||
var mixed = new DefaultTagHelperContent();
|
||||
mixed.Append("HTML encoded");
|
||||
mixed.AppendHtml(" and contains \"quotes\"");
|
||||
var context = MakeTagHelperContext(
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
new TagHelperAttribute("src", "/js/site.js"),
|
||||
new TagHelperAttribute("asp-src-include", "**/*.js")
|
||||
{ "asp-src-include", "**/*.js" },
|
||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
||||
{ "literal", "all HTML encoded" },
|
||||
{ "mixed", mixed },
|
||||
{ "src", "/js/site.js" },
|
||||
});
|
||||
var output = MakeTagHelperOutput(
|
||||
"script",
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
||||
{ "literal", "all HTML encoded"},
|
||||
{ "mixed", mixed},
|
||||
});
|
||||
var output = MakeTagHelperOutput("script", attributes: new TagHelperAttributeList());
|
||||
var hostingEnvironment = MakeHostingEnvironment();
|
||||
var viewContext = MakeViewContext();
|
||||
var globbingUrlBuilder = new Mock<GlobbingUrlBuilder>(
|
||||
|
|
@ -642,22 +667,23 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
MakeUrlHelperFactory())
|
||||
{
|
||||
GlobbingUrlBuilder = globbingUrlBuilder.Object,
|
||||
ViewContext = viewContext,
|
||||
Src = "/js/site.js",
|
||||
SrcInclude = "**/*.js",
|
||||
ViewContext = viewContext,
|
||||
};
|
||||
|
||||
// Act
|
||||
await helper.ProcessAsync(context, output);
|
||||
helper.Process(context, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("script", output.TagName);
|
||||
Assert.Equal("/js/site.js", output.Attributes["src"].Value);
|
||||
Assert.Equal("<script src=\"HtmlEncode[[/common.js]]\"></script>", output.PostElement.GetContent());
|
||||
var content = HtmlContentUtilities.HtmlContentToString(output, new HtmlTestEncoder());
|
||||
Assert.Equal(expectedContent, content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RenderScriptTags_WithFileVersion()
|
||||
public void RenderScriptTags_WithFileVersion()
|
||||
{
|
||||
// Arrange
|
||||
var context = MakeTagHelperContext(
|
||||
|
|
@ -684,7 +710,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
};
|
||||
|
||||
// Act
|
||||
await helper.ProcessAsync(context, output);
|
||||
helper.Process(context, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("script", output.TagName);
|
||||
|
|
@ -692,7 +718,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RenderScriptTags_WithFileVersion_AndRequestPathBase()
|
||||
public void RenderScriptTags_WithFileVersion_AndRequestPathBase()
|
||||
{
|
||||
// Arrange
|
||||
var context = MakeTagHelperContext(
|
||||
|
|
@ -718,7 +744,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
};
|
||||
|
||||
// Act
|
||||
await helper.ProcessAsync(context, output);
|
||||
helper.Process(context, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("script", output.TagName);
|
||||
|
|
@ -726,7 +752,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RenderScriptTags_FallbackSrc_WithFileVersion()
|
||||
public void RenderScriptTags_FallbackSrc_WithFileVersion()
|
||||
{
|
||||
// Arrange
|
||||
var context = MakeTagHelperContext(
|
||||
|
|
@ -756,20 +782,87 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
};
|
||||
|
||||
// Act
|
||||
await helper.ProcessAsync(context, output);
|
||||
helper.Process(context, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("script", output.TagName);
|
||||
Assert.Equal("/js/site.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk", output.Attributes["src"].Value);
|
||||
Assert.Equal(Environment.NewLine + "<script>(isavailable()||document.write(\"<script " +
|
||||
"src=\\\"JavaScriptEncode[[fallback.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\\\">" +
|
||||
"<\\/script>\"));</script>", output.PostElement.GetContent());
|
||||
Assert.Equal(Environment.NewLine + "<script>(isavailable()||document.write(\"<script src=" +
|
||||
"\\\"JavaScriptEncode[[HtmlEncode[[fallback.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]]]\\\"" +
|
||||
"><\\/script>\"));</script>", output.PostElement.GetContent());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RenderScriptTags_GlobbedSrc_WithFileVersion()
|
||||
public void RenderScriptTags_FallbackSrc_WithFileVersion_EncodesAsExpected()
|
||||
{
|
||||
// Arrange
|
||||
var expectedContent =
|
||||
"<script encoded=\"contains "quotes"\" literal=\"HtmlEncode[[all HTML encoded]]\" " +
|
||||
"mixed=\"HtmlEncode[[HTML encoded]] and contains "quotes"\" " +
|
||||
"src=\"HtmlEncode[[/js/site.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\"></script>" +
|
||||
Environment.NewLine +
|
||||
"<script>(isavailable()||document.write(\"<script " +
|
||||
"JavaScriptEncode[[encoded]]=\\\"JavaScriptEncode[[contains "quotes"]]\\\" " +
|
||||
"JavaScriptEncode[[literal]]=\\\"JavaScriptEncode[[HtmlEncode[[all HTML encoded]]]]\\\" " +
|
||||
"JavaScriptEncode[[mixed]]=\\\"JavaScriptEncode[[HtmlEncode[[HTML encoded]] and contains "quotes"]]\\\" " +
|
||||
"src=\\\"JavaScriptEncode[[HtmlEncode[[fallback.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]]]\\\">" +
|
||||
"<\\/script>\"));</script>";
|
||||
var mixed = new DefaultTagHelperContent();
|
||||
mixed.Append("HTML encoded");
|
||||
mixed.AppendHtml(" and contains \"quotes\"");
|
||||
var context = MakeTagHelperContext(
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
{ "asp-append-version", "true" },
|
||||
{ "asp-fallback-src-include", "fallback.js" },
|
||||
{ "asp-fallback-test", "isavailable()" },
|
||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
||||
{ "literal", "all HTML encoded" },
|
||||
{ "mixed", mixed },
|
||||
{ "src", "/js/site.js" },
|
||||
});
|
||||
var output = MakeTagHelperOutput(
|
||||
"script",
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
{ "encoded", new HtmlString("contains \"quotes\"") },
|
||||
{ "literal", "all HTML encoded" },
|
||||
{ "mixed", mixed },
|
||||
});
|
||||
var hostingEnvironment = MakeHostingEnvironment();
|
||||
var viewContext = MakeViewContext();
|
||||
|
||||
var helper = new ScriptTagHelper(
|
||||
MakeHostingEnvironment(),
|
||||
MakeCache(),
|
||||
new HtmlTestEncoder(),
|
||||
new JavaScriptTestEncoder(),
|
||||
MakeUrlHelperFactory())
|
||||
{
|
||||
AppendVersion = true,
|
||||
FallbackSrc = "fallback.js",
|
||||
FallbackTestExpression = "isavailable()",
|
||||
Src = "/js/site.js",
|
||||
ViewContext = viewContext,
|
||||
};
|
||||
|
||||
// Act
|
||||
helper.Process(context, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("script", output.TagName);
|
||||
Assert.Equal("/js/site.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk", output.Attributes["src"].Value);
|
||||
var content = HtmlContentUtilities.HtmlContentToString(output, new HtmlTestEncoder());
|
||||
Assert.Equal(expectedContent, content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderScriptTags_GlobbedSrc_WithFileVersion()
|
||||
{
|
||||
// Arrange
|
||||
var expectedContent = "<script " +
|
||||
"src=\"HtmlEncode[[/js/site.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\"></script>" +
|
||||
"<script src=\"HtmlEncode[[/common.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\"></script>";
|
||||
var context = MakeTagHelperContext(
|
||||
attributes: new TagHelperAttributeList
|
||||
{
|
||||
|
|
@ -802,13 +895,13 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
};
|
||||
|
||||
// Act
|
||||
await helper.ProcessAsync(context, output);
|
||||
helper.Process(context, output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("script", output.TagName);
|
||||
Assert.Equal("/js/site.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk", output.Attributes["src"].Value);
|
||||
Assert.Equal("<script src=\"HtmlEncode[[/common.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\">" +
|
||||
"</script>", output.PostElement.GetContent());
|
||||
var content = HtmlContentUtilities.HtmlContentToString(output, new HtmlTestEncoder());
|
||||
Assert.Equal(expectedContent, content);
|
||||
}
|
||||
|
||||
private TagHelperContext MakeTagHelperContext(
|
||||
|
|
|
|||
Loading…
Reference in New Issue