MVC portion of aspnet/Razor#335
- set correct `MarkAsHtmlEncodedMethodName` value in `MvcRazorHost` - handle `HtmlString` values in `TagHelperOutput.Attributes` in `RazorPage` - special-case double-quotes in `HtmlString` values - add `static WriteTo()` method for use in tag helpers - handle non-`string` `output.Attributes` values in tag helpers - make `TagHelperContentWrapperTextWriter` a `public` class - provide a `TagHelperContent.Append(object, ...)` extension method - add `LinkTagHelper.Href` and `ScriptTagHelper.Src` properties - avoid Razor HTML-encoding these attribute values before their use - add `JavaScriptEncoder` properties in `LinkTagHelper` and `ScriptTagHelper` - allow encoding testing without unit testing the default encoder - handle MVC and Razor changes for this bug in existing tests - add functional tests of encodings - add test encoders to TestCommon project nits: - correct `InputTagHelper` to pass `type=""` through unchanged - set correct `TagHelperContentTypeName` value in `MvcRazorHost` - remove unnecessary `FormTagHelper.Method` and `OptionTagHelper.Selected` properties - remove complex ternaries and `ShouldAddFileVersion()` methods - add a few debug assertions - fix some odd wrapping - remove or `#if`-out unused `using`s - remove trailing whitespace
This commit is contained in:
parent
9402f1485c
commit
5882cdb03f
|
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
#if NET45
|
||||||
using Microsoft.AspNet.FileProviders;
|
using Microsoft.AspNet.FileProviders;
|
||||||
|
#endif
|
||||||
using Microsoft.AspNet.Mvc.Razor.Directives;
|
using Microsoft.AspNet.Mvc.Razor.Directives;
|
||||||
using Microsoft.AspNet.Mvc.Razor.Internal;
|
using Microsoft.AspNet.Mvc.Razor.Internal;
|
||||||
using Microsoft.AspNet.Razor;
|
using Microsoft.AspNet.Razor;
|
||||||
|
|
@ -18,6 +20,8 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
public class MvcRazorHost : RazorEngineHost, IMvcRazorHost
|
public class MvcRazorHost : RazorEngineHost, IMvcRazorHost
|
||||||
{
|
{
|
||||||
private const string BaseType = "Microsoft.AspNet.Mvc.Razor.RazorPage";
|
private const string BaseType = "Microsoft.AspNet.Mvc.Razor.RazorPage";
|
||||||
|
private const string HtmlHelperPropertyName = "Html";
|
||||||
|
|
||||||
private static readonly string[] _defaultNamespaces = new[]
|
private static readonly string[] _defaultNamespaces = new[]
|
||||||
{
|
{
|
||||||
"System",
|
"System",
|
||||||
|
|
@ -28,7 +32,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
};
|
};
|
||||||
private static readonly Chunk[] _defaultInheritedChunks = new[]
|
private static readonly Chunk[] _defaultInheritedChunks = new[]
|
||||||
{
|
{
|
||||||
new InjectChunk("Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<TModel>", "Html"),
|
new InjectChunk("Microsoft.AspNet.Mvc.Rendering.IHtmlHelper<TModel>", HtmlHelperPropertyName),
|
||||||
new InjectChunk("Microsoft.AspNet.Mvc.IViewComponentHelper", "Component"),
|
new InjectChunk("Microsoft.AspNet.Mvc.IViewComponentHelper", "Component"),
|
||||||
new InjectChunk("Microsoft.AspNet.Mvc.IUrlHelper", "Url"),
|
new InjectChunk("Microsoft.AspNet.Mvc.IUrlHelper", "Url"),
|
||||||
};
|
};
|
||||||
|
|
@ -76,6 +80,8 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
ScopeManagerBeginMethodName = nameof(TagHelperScopeManager.Begin),
|
ScopeManagerBeginMethodName = nameof(TagHelperScopeManager.Begin),
|
||||||
ScopeManagerEndMethodName = nameof(TagHelperScopeManager.End),
|
ScopeManagerEndMethodName = nameof(TagHelperScopeManager.End),
|
||||||
|
|
||||||
|
TagHelperContentTypeName = nameof(TagHelperContent),
|
||||||
|
|
||||||
// Can't use nameof because RazorPage is not accessible here.
|
// Can't use nameof because RazorPage is not accessible here.
|
||||||
CreateTagHelperMethodName = "CreateTagHelper",
|
CreateTagHelperMethodName = "CreateTagHelper",
|
||||||
StartTagHelperWritingScopeMethodName = "StartTagHelperWritingScope",
|
StartTagHelperWritingScopeMethodName = "StartTagHelperWritingScope",
|
||||||
|
|
@ -83,6 +89,9 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
|
||||||
WriteTagHelperAsyncMethodName = "WriteTagHelperAsync",
|
WriteTagHelperAsyncMethodName = "WriteTagHelperAsync",
|
||||||
WriteTagHelperToAsyncMethodName = "WriteTagHelperToAsync",
|
WriteTagHelperToAsyncMethodName = "WriteTagHelperToAsync",
|
||||||
|
|
||||||
|
// Can't use nameof because IHtmlHelper is (also) not accessible here.
|
||||||
|
MarkAsHtmlEncodedMethodName = HtmlHelperPropertyName + ".Raw",
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
ResolveUrlMethodName = "Href",
|
ResolveUrlMethodName = "Href",
|
||||||
|
|
|
||||||
|
|
@ -294,11 +294,10 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
|
||||||
foreach (var attribute in tagHelperOutput.Attributes)
|
foreach (var attribute in tagHelperOutput.Attributes)
|
||||||
{
|
{
|
||||||
var value = HtmlEncoder.HtmlEncode(attribute.Value);
|
|
||||||
writer.Write(' ');
|
writer.Write(' ');
|
||||||
writer.Write(attribute.Key);
|
writer.Write(attribute.Key);
|
||||||
writer.Write("=\"");
|
writer.Write("=\"");
|
||||||
writer.Write(value);
|
WriteTo(writer, HtmlEncoder, attribute.Value, escapeQuotes: true);
|
||||||
writer.Write('"');
|
writer.Write('"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -366,26 +365,67 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public virtual void WriteTo([NotNull] TextWriter writer, object value)
|
public virtual void WriteTo([NotNull] TextWriter writer, object value)
|
||||||
{
|
{
|
||||||
if (value != null && value != HtmlString.Empty)
|
WriteTo(writer, HtmlEncoder, value, escapeQuotes: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the specified <paramref name="value"/> with HTML encoding to given <paramref name="writer"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter"/> instance to write to.</param>
|
||||||
|
/// <param name="encoder">The <see cref="IHtmlEncoder"/> to use when encoding <paramref name="value"/>.</param>
|
||||||
|
/// <param name="value">The <see cref="object"/> to write.</param>
|
||||||
|
/// <param name="escapeQuotes">
|
||||||
|
/// If <c>true</c> escapes double quotes in a <paramref name="value"/> of type <see cref="HtmlString"/>.
|
||||||
|
/// Otherwise writes <see cref="HtmlString"/> values as-is.
|
||||||
|
/// </param>
|
||||||
|
/// <remarks>
|
||||||
|
/// <paramref name="value"/>s of type <see cref="HtmlString"/> are written without encoding and the
|
||||||
|
/// <see cref="HelperResult.WriteTo(TextWriter)"/> is invoked for <see cref="HelperResult"/> types.
|
||||||
|
/// For all other types, the encoded result of <see cref="object.ToString"/> is written to the
|
||||||
|
/// <paramref name="writer"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public static void WriteTo(
|
||||||
|
[NotNull] TextWriter writer,
|
||||||
|
[NotNull] IHtmlEncoder encoder,
|
||||||
|
object value,
|
||||||
|
bool escapeQuotes)
|
||||||
|
{
|
||||||
|
if (value == null || value == HtmlString.Empty)
|
||||||
{
|
{
|
||||||
var helperResult = value as HelperResult;
|
return;
|
||||||
if (helperResult != null)
|
|
||||||
{
|
|
||||||
helperResult.WriteTo(writer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var htmlString = value as HtmlString;
|
|
||||||
if (htmlString != null)
|
|
||||||
{
|
|
||||||
writer.Write(htmlString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteTo(writer, value.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var helperResult = value as HelperResult;
|
||||||
|
if (helperResult != null)
|
||||||
|
{
|
||||||
|
helperResult.WriteTo(writer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var htmlString = value as HtmlString;
|
||||||
|
if (htmlString != null)
|
||||||
|
{
|
||||||
|
if (escapeQuotes)
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Do not combine following condition with check of escapeQuotes; htmlString.ToString() can be
|
||||||
|
// expensive when the HtmlString is created with a StringCollectionTextWriter.
|
||||||
|
var stringValue = htmlString.ToString();
|
||||||
|
if (stringValue.Contains("\""))
|
||||||
|
{
|
||||||
|
writer.Write(stringValue.Replace("\"", """));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
htmlString.WriteTo(writer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteTo(writer, encoder, value.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -394,10 +434,15 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
/// <param name="writer">The <see cref="TextWriter"/> instance to write to.</param>
|
/// <param name="writer">The <see cref="TextWriter"/> instance to write to.</param>
|
||||||
/// <param name="value">The <see cref="string"/> to write.</param>
|
/// <param name="value">The <see cref="string"/> to write.</param>
|
||||||
public virtual void WriteTo([NotNull] TextWriter writer, string value)
|
public virtual void WriteTo([NotNull] TextWriter writer, string value)
|
||||||
|
{
|
||||||
|
WriteTo(writer, HtmlEncoder, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteTo(TextWriter writer, IHtmlEncoder encoder, string value)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(value))
|
if (!string.IsNullOrEmpty(value))
|
||||||
{
|
{
|
||||||
HtmlEncoder.HtmlEncode(value, writer);
|
encoder.HtmlEncode(value, writer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -766,33 +811,5 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
throw new InvalidOperationException(Resources.FormatRazorPage_MethodCannotBeCalled(methodName));
|
throw new InvalidOperationException(Resources.FormatRazorPage_MethodCannotBeCalled(methodName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TagHelperContentWrapperTextWriter : TextWriter
|
|
||||||
{
|
|
||||||
public TagHelperContentWrapperTextWriter(Encoding encoding)
|
|
||||||
{
|
|
||||||
Content = new DefaultTagHelperContent();
|
|
||||||
Encoding = encoding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TagHelperContent Content { get; }
|
|
||||||
|
|
||||||
public override Encoding Encoding { get; }
|
|
||||||
|
|
||||||
public override void Write(string value)
|
|
||||||
{
|
|
||||||
Content.Append(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Write(char value)
|
|
||||||
{
|
|
||||||
Content.Append(value.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Content.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
using Microsoft.Framework.Internal;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="TextWriter"/> implementation which writes to a <see cref="TagHelperContent"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
public class TagHelperContentWrapperTextWriter : TextWriter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="TagHelperContentWrapperTextWriter"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encoding">The <see cref="Encoding"/> in which output is written.</param>
|
||||||
|
public TagHelperContentWrapperTextWriter([NotNull] Encoding encoding)
|
||||||
|
: this(encoding, new DefaultTagHelperContent())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="TagHelperContentWrapperTextWriter"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encoding">The <see cref="Encoding"/> in which output is written.</param>
|
||||||
|
/// <param name="content">The <see cref="TagHelperContent"/> to write to.</param>
|
||||||
|
public TagHelperContentWrapperTextWriter([NotNull] Encoding encoding, [NotNull] TagHelperContent content)
|
||||||
|
{
|
||||||
|
Content = content;
|
||||||
|
Encoding = encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="TagHelperContent"/> this <see cref="TagHelperContentWrapperTextWriter"/> writes to.
|
||||||
|
/// </summary>
|
||||||
|
public TagHelperContent Content { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Encoding Encoding { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(string value)
|
||||||
|
{
|
||||||
|
Content.Append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(char value)
|
||||||
|
{
|
||||||
|
Content.Append(value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Content.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -153,7 +153,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
||||||
// TODO: https://github.com/aspnet/Razor/issues/89 - We will not need this method once #89 is completed.
|
// TODO: https://github.com/aspnet/Razor/issues/89 - We will not need this method once #89 is completed.
|
||||||
private static Dictionary<string, object> GetRouteValues(
|
private static Dictionary<string, object> GetRouteValues(
|
||||||
TagHelperOutput output, IEnumerable<KeyValuePair<string, string>> routePrefixedAttributes)
|
TagHelperOutput output,
|
||||||
|
IEnumerable<KeyValuePair<string, object>> routePrefixedAttributes)
|
||||||
{
|
{
|
||||||
Dictionary<string, object> routeValues = null;
|
Dictionary<string, object> routeValues = null;
|
||||||
if (routePrefixedAttributes.Any())
|
if (routePrefixedAttributes.Any())
|
||||||
|
|
@ -161,10 +162,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Prefixed values should be treated as bound attributes, remove them from the output.
|
// Prefixed values should be treated as bound attributes, remove them from the output.
|
||||||
output.RemoveRange(routePrefixedAttributes);
|
output.RemoveRange(routePrefixedAttributes);
|
||||||
|
|
||||||
// Generator.GenerateForm does not accept a Dictionary<string, string> for route values.
|
// Remove prefix from keys and convert all values to strings. HtmlString and similar classes are not
|
||||||
|
// meaningful to routing.
|
||||||
routeValues = routePrefixedAttributes.ToDictionary(
|
routeValues = routePrefixedAttributes.ToDictionary(
|
||||||
attribute => attribute.Key.Substring(RouteAttributePrefix.Length),
|
attribute => attribute.Key.Substring(RouteAttributePrefix.Length),
|
||||||
attribute => (object)attribute.Value);
|
attribute => (object)attribute.Value.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return routeValues;
|
return routeValues;
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
[HtmlAttributeName(ControllerAttributeName)]
|
[HtmlAttributeName(ControllerAttributeName)]
|
||||||
public string Controller { get; set; }
|
public string Controller { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The HTTP method for processing the form, either GET or POST.
|
|
||||||
/// </summary>
|
|
||||||
public string Method { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the anti-forgery token should be generated.
|
/// Whether the anti-forgery token should be generated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -84,12 +79,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// User is using the FormTagHelper like a normal <form> tag. Anti-forgery default should be false to
|
// User is using the FormTagHelper like a normal <form> tag. Anti-forgery default should be false to
|
||||||
// not force the anti-forgery token on the user.
|
// not force the anti-forgery token on the user.
|
||||||
antiForgeryDefault = false;
|
antiForgeryDefault = false;
|
||||||
|
|
||||||
// Restore method attribute.
|
|
||||||
if (Method != null)
|
|
||||||
{
|
|
||||||
output.CopyHtmlAttribute(nameof(Method), context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -98,7 +87,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Action,
|
Action,
|
||||||
Controller,
|
Controller,
|
||||||
routeValues,
|
routeValues,
|
||||||
Method,
|
method: null,
|
||||||
htmlAttributes: null);
|
htmlAttributes: null);
|
||||||
|
|
||||||
if (tagBuilder != null)
|
if (tagBuilder != null)
|
||||||
|
|
@ -120,7 +109,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
||||||
// TODO: https://github.com/aspnet/Razor/issues/89 - We will not need this method once #89 is completed.
|
// TODO: https://github.com/aspnet/Razor/issues/89 - We will not need this method once #89 is completed.
|
||||||
private static Dictionary<string, object> GetRouteValues(
|
private static Dictionary<string, object> GetRouteValues(
|
||||||
TagHelperOutput output, IEnumerable<KeyValuePair<string, string>> routePrefixedAttributes)
|
TagHelperOutput output,
|
||||||
|
IEnumerable<KeyValuePair<string, object>> routePrefixedAttributes)
|
||||||
{
|
{
|
||||||
Dictionary<string, object> routeValues = null;
|
Dictionary<string, object> routeValues = null;
|
||||||
if (routePrefixedAttributes.Any())
|
if (routePrefixedAttributes.Any())
|
||||||
|
|
@ -128,10 +118,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Prefixed values should be treated as bound attributes, remove them from the output.
|
// Prefixed values should be treated as bound attributes, remove them from the output.
|
||||||
output.RemoveRange(routePrefixedAttributes);
|
output.RemoveRange(routePrefixedAttributes);
|
||||||
|
|
||||||
// Generator.GenerateForm does not accept a Dictionary<string, string> for route values.
|
// Remove prefix from keys and convert all values to strings. HtmlString and similar classes are not
|
||||||
|
// meaningful to routing.
|
||||||
routeValues = routePrefixedAttributes.ToDictionary(
|
routeValues = routePrefixedAttributes.ToDictionary(
|
||||||
attribute => attribute.Key.Substring(RouteAttributePrefix.Length),
|
attribute => attribute.Key.Substring(RouteAttributePrefix.Length),
|
||||||
attribute => (object)attribute.Value);
|
attribute => (object)attribute.Value.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return routeValues;
|
return routeValues;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ using System.Linq;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
|
|
@ -112,7 +111,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
// Pass through attributes that are also well-known HTML attributes. Must be done prior to any copying
|
// Pass through attributes that are also well-known HTML attributes. Must be done prior to any copying
|
||||||
// from a TagBuilder.
|
// from a TagBuilder.
|
||||||
if (!string.IsNullOrEmpty(InputTypeName))
|
if (InputTypeName != null)
|
||||||
{
|
{
|
||||||
output.CopyHtmlAttribute("type", context);
|
output.CopyHtmlAttribute("type", context);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNet.Hosting;
|
using Microsoft.AspNet.Hosting;
|
||||||
|
|
@ -10,7 +11,6 @@ using Microsoft.AspNet.Mvc.TagHelpers.Internal;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.Framework.Caching.Memory;
|
using Microsoft.Framework.Caching.Memory;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
using Microsoft.Framework.Runtime;
|
|
||||||
using Microsoft.Framework.WebEncoders;
|
using Microsoft.Framework.WebEncoders;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
@ -98,6 +98,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Fallback = 2,
|
Fallback = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Address of the linked resource.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Passed through to the generated HTML in all cases.
|
||||||
|
/// </remarks>
|
||||||
|
[HtmlAttributeName(HrefAttributeName)]
|
||||||
|
public string Href { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A comma separated list of globbed file patterns of CSS stylesheets to load.
|
/// A comma separated list of globbed file patterns of CSS stylesheets to load.
|
||||||
/// The glob patterns are assessed relative to the application's 'webroot' setting.
|
/// The glob patterns are assessed relative to the application's 'webroot' setting.
|
||||||
|
|
@ -189,12 +198,21 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
[Activate]
|
[Activate]
|
||||||
protected internal IHtmlEncoder HtmlEncoder { get; set; }
|
protected internal IHtmlEncoder HtmlEncoder { get; set; }
|
||||||
|
|
||||||
|
[Activate]
|
||||||
|
protected internal IJavaScriptStringEncoder JavaScriptEncoder { get; set; }
|
||||||
|
|
||||||
// Internal for ease of use when testing.
|
// Internal for ease of use when testing.
|
||||||
protected internal GlobbingUrlBuilder GlobbingUrlBuilder { get; set; }
|
protected internal GlobbingUrlBuilder GlobbingUrlBuilder { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||||
{
|
{
|
||||||
|
// Pass through attribute that is also a well-known HTML attribute.
|
||||||
|
if (Href != null)
|
||||||
|
{
|
||||||
|
output.CopyHtmlAttribute(HrefAttributeName, context);
|
||||||
|
}
|
||||||
|
|
||||||
var modeResult = AttributeMatcher.DetermineMode(context, ModeDetails);
|
var modeResult = AttributeMatcher.DetermineMode(context, ModeDetails);
|
||||||
|
|
||||||
var logger = Logger ?? LoggerFactory.CreateLogger<LinkTagHelper>();
|
var logger = Logger ?? LoggerFactory.CreateLogger<LinkTagHelper>();
|
||||||
|
|
@ -210,8 +228,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Get the highest matched mode
|
// Get the highest matched mode
|
||||||
var mode = modeResult.FullMatches.Select(match => match.Mode).Max();
|
var mode = modeResult.FullMatches.Select(match => match.Mode).Max();
|
||||||
|
|
||||||
// NOTE: Values in TagHelperOutput.Attributes are already HtmlEncoded
|
// NOTE: Values in TagHelperOutput.Attributes may already be HTML-encoded.
|
||||||
var attributes = new Dictionary<string, string>(output.Attributes);
|
var attributes = new Dictionary<string, object>(output.Attributes);
|
||||||
|
|
||||||
var builder = new DefaultTagHelperContent();
|
var builder = new DefaultTagHelperContent();
|
||||||
|
|
||||||
|
|
@ -236,17 +254,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
output.Content.SetContent(builder);
|
output.Content.SetContent(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildGlobbedLinkTags(IDictionary<string, string> attributes, TagHelperContent builder)
|
private void BuildGlobbedLinkTags(IDictionary<string, object> attributes, TagHelperContent builder)
|
||||||
{
|
{
|
||||||
// Build a <link /> tag for each matched href as well as the original one in the source file
|
|
||||||
string staticHref;
|
|
||||||
attributes.TryGetValue(HrefAttributeName, out staticHref);
|
|
||||||
|
|
||||||
EnsureGlobbingUrlBuilder();
|
EnsureGlobbingUrlBuilder();
|
||||||
var urls = GlobbingUrlBuilder.BuildUrlList(staticHref, HrefInclude, HrefExclude);
|
|
||||||
|
|
||||||
|
// Build a <link /> tag for each matched href as well as the original one in the source file
|
||||||
|
var urls = GlobbingUrlBuilder.BuildUrlList(Href, HrefInclude, HrefExclude);
|
||||||
foreach (var url in urls)
|
foreach (var url in urls)
|
||||||
{
|
{
|
||||||
|
// "url" values come from bound attributes and globbing. Must always be non-null.
|
||||||
|
Debug.Assert(url != null);
|
||||||
|
|
||||||
attributes[HrefAttributeName] = url;
|
attributes[HrefAttributeName] = url;
|
||||||
BuildLinkTag(attributes, builder);
|
BuildLinkTag(attributes, builder);
|
||||||
}
|
}
|
||||||
|
|
@ -260,10 +278,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
||||||
if (fallbackHrefs.Length > 0)
|
if (fallbackHrefs.Length > 0)
|
||||||
{
|
{
|
||||||
if (ShouldAddFileVersion())
|
if (FileVersion == true)
|
||||||
{
|
{
|
||||||
for (var i=0; i < fallbackHrefs.Length; i++)
|
for (var i=0; i < fallbackHrefs.Length; i++)
|
||||||
{
|
{
|
||||||
|
// fallbackHrefs come from bound attributes and globbing. Must always be non-null.
|
||||||
|
Debug.Assert(fallbackHrefs[i] != null);
|
||||||
|
|
||||||
fallbackHrefs[i] = _fileVersionProvider.AddFileVersionToPath(fallbackHrefs[i]);
|
fallbackHrefs[i] = _fileVersionProvider.AddFileVersionToPath(fallbackHrefs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -279,13 +300,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Build the <script /> tag that checks the effective style of <meta /> tag above and renders the extra
|
// Build the <script /> tag that checks the effective style of <meta /> tag above and renders the extra
|
||||||
// <link /> tag to load the fallback stylesheet if the test CSS property value is found to be false,
|
// <link /> tag to load the fallback stylesheet if the test CSS property value is found to be false,
|
||||||
// indicating that the primary stylesheet failed to load.
|
// indicating that the primary stylesheet failed to load.
|
||||||
builder.Append("<script>")
|
builder
|
||||||
.Append(string.Format(CultureInfo.InvariantCulture,
|
.Append("<script>")
|
||||||
JavaScriptResources.GetEmbeddedJavaScript(FallbackJavaScriptResourceName),
|
.Append(string.Format(
|
||||||
JavaScriptStringEncoder.Default.JavaScriptStringEncode(FallbackTestProperty),
|
CultureInfo.InvariantCulture,
|
||||||
JavaScriptStringEncoder.Default.JavaScriptStringEncode(FallbackTestValue),
|
JavaScriptResources.GetEmbeddedJavaScript(FallbackJavaScriptResourceName),
|
||||||
JavaScriptStringArrayEncoder.Encode(JavaScriptStringEncoder.Default, fallbackHrefs)))
|
JavaScriptEncoder.JavaScriptStringEncode(FallbackTestProperty),
|
||||||
.Append("</script>");
|
JavaScriptEncoder.JavaScriptStringEncode(FallbackTestValue),
|
||||||
|
JavaScriptStringArrayEncoder.Encode(JavaScriptEncoder, fallbackHrefs)))
|
||||||
|
.Append("</script>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -311,7 +334,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildLinkTag(IDictionary<string, string> attributes, TagHelperContent builder)
|
private void BuildLinkTag(IDictionary<string, object> attributes, TagHelperContent builder)
|
||||||
{
|
{
|
||||||
EnsureFileVersionProvider();
|
EnsureFileVersionProvider();
|
||||||
builder.Append("<link ");
|
builder.Append("<link ");
|
||||||
|
|
@ -319,27 +342,27 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
foreach (var attribute in attributes)
|
foreach (var attribute in attributes)
|
||||||
{
|
{
|
||||||
var attributeValue = attribute.Value;
|
var attributeValue = attribute.Value;
|
||||||
if (string.Equals(attribute.Key, HrefAttributeName, StringComparison.OrdinalIgnoreCase))
|
if (FileVersion == true &&
|
||||||
|
string.Equals(attribute.Key, HrefAttributeName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
attributeValue = HtmlEncoder.HtmlEncode(
|
// "href" values come from bound attributes and globbing. So anything but a non-null string is
|
||||||
ShouldAddFileVersion() ?
|
// unexpected but could happen if another helper targeting the same element does something odd.
|
||||||
_fileVersionProvider.AddFileVersionToPath(attributeValue) :
|
// Pass through existing value in that case.
|
||||||
attributeValue);
|
var attributeStringValue = attributeValue as string;
|
||||||
|
if (attributeStringValue != null)
|
||||||
|
{
|
||||||
|
attributeValue = _fileVersionProvider.AddFileVersionToPath(attributeStringValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.Append(attribute.Key)
|
.Append(attribute.Key)
|
||||||
.Append("=\"")
|
.Append("=\"")
|
||||||
.Append(attributeValue)
|
.Append(HtmlEncoder, ViewContext.Writer.Encoding, attributeValue)
|
||||||
.Append("\" ");
|
.Append("\" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Append("/>");
|
builder.Append("/>");
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ShouldAddFileVersion()
|
|
||||||
{
|
|
||||||
return FileVersion ?? false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
|
|
@ -28,14 +27,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
[Activate]
|
[Activate]
|
||||||
protected internal ViewContext ViewContext { get; set; }
|
protected internal ViewContext ViewContext { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies that this <option> is pre-selected.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Passed through to the generated HTML in all cases.
|
|
||||||
/// </remarks>
|
|
||||||
public string Selected { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies a value for the <option> element.
|
/// Specifies a value for the <option> element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -59,12 +50,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
output.CopyHtmlAttribute(nameof(Value), context);
|
output.CopyHtmlAttribute(nameof(Value), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Selected != null)
|
// Nothing to do if this <option/> is already selected.
|
||||||
{
|
if (!output.Attributes.ContainsKey("selected"))
|
||||||
// This <option/> will always be selected.
|
|
||||||
output.CopyHtmlAttribute(nameof(Selected), context);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// Is this <option/> element a child of a <select/> element the SelectTagHelper targeted?
|
// Is this <option/> element a child of a <select/> element the SelectTagHelper targeted?
|
||||||
object formDataEntry;
|
object formDataEntry;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Hosting;
|
using Microsoft.AspNet.Hosting;
|
||||||
|
|
@ -10,7 +11,6 @@ using Microsoft.AspNet.Mvc.TagHelpers.Internal;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.Framework.Caching.Memory;
|
using Microsoft.Framework.Caching.Memory;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
using Microsoft.Framework.Runtime;
|
|
||||||
using Microsoft.Framework.WebEncoders;
|
using Microsoft.Framework.WebEncoders;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
@ -87,6 +87,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Fallback = 2
|
Fallback = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Address of the external script to use.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Passed through to the generated HTML in all cases.
|
||||||
|
/// </remarks>
|
||||||
|
[HtmlAttributeName(SrcAttributeName)]
|
||||||
|
public string Src { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A comma separated list of globbed file patterns of JavaScript scripts to load.
|
/// A comma separated list of globbed file patterns of JavaScript scripts to load.
|
||||||
/// The glob patterns are assessed relative to the application's 'webroot' setting.
|
/// The glob patterns are assessed relative to the application's 'webroot' setting.
|
||||||
|
|
@ -159,12 +168,21 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
[Activate]
|
[Activate]
|
||||||
protected internal IHtmlEncoder HtmlEncoder { get; set; }
|
protected internal IHtmlEncoder HtmlEncoder { get; set; }
|
||||||
|
|
||||||
|
[Activate]
|
||||||
|
protected internal IJavaScriptStringEncoder JavaScriptEncoder { get; set; }
|
||||||
|
|
||||||
// Internal for ease of use when testing.
|
// Internal for ease of use when testing.
|
||||||
protected internal GlobbingUrlBuilder GlobbingUrlBuilder { get; set; }
|
protected internal GlobbingUrlBuilder GlobbingUrlBuilder { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
||||||
{
|
{
|
||||||
|
// Pass through attribute that is also a well-known HTML attribute.
|
||||||
|
if (Src != null)
|
||||||
|
{
|
||||||
|
output.CopyHtmlAttribute(SrcAttributeName, context);
|
||||||
|
}
|
||||||
|
|
||||||
var modeResult = AttributeMatcher.DetermineMode(context, ModeDetails);
|
var modeResult = AttributeMatcher.DetermineMode(context, ModeDetails);
|
||||||
|
|
||||||
var logger = Logger ?? LoggerFactory.CreateLogger<ScriptTagHelper>();
|
var logger = Logger ?? LoggerFactory.CreateLogger<ScriptTagHelper>();
|
||||||
|
|
@ -180,8 +198,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Get the highest matched mode
|
// Get the highest matched mode
|
||||||
var mode = modeResult.FullMatches.Select(match => match.Mode).Max();
|
var mode = modeResult.FullMatches.Select(match => match.Mode).Max();
|
||||||
|
|
||||||
// NOTE: Values in TagHelperOutput.Attributes are already HtmlEncoded
|
// NOTE: Values in TagHelperOutput.Attributes may already be HTML-encoded.
|
||||||
var attributes = new Dictionary<string, string>(output.Attributes);
|
var attributes = new Dictionary<string, object>(output.Attributes);
|
||||||
|
|
||||||
var builder = new DefaultTagHelperContent();
|
var builder = new DefaultTagHelperContent();
|
||||||
var originalContent = await context.GetChildContentAsync();
|
var originalContent = await context.GetChildContentAsync();
|
||||||
|
|
@ -209,32 +227,36 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
||||||
private void BuildGlobbedScriptTags(
|
private void BuildGlobbedScriptTags(
|
||||||
TagHelperContent originalContent,
|
TagHelperContent originalContent,
|
||||||
IDictionary<string, string> attributes,
|
IDictionary<string, object> attributes,
|
||||||
TagHelperContent builder)
|
TagHelperContent builder)
|
||||||
{
|
{
|
||||||
// Build a <script> tag for each matched src as well as the original one in the source file
|
|
||||||
string staticSrc;
|
|
||||||
attributes.TryGetValue(SrcAttributeName, out staticSrc);
|
|
||||||
|
|
||||||
EnsureGlobbingUrlBuilder();
|
EnsureGlobbingUrlBuilder();
|
||||||
var urls = GlobbingUrlBuilder.BuildUrlList(staticSrc, SrcInclude, SrcExclude);
|
|
||||||
|
|
||||||
|
// Build a <script> tag for each matched src as well as the original one in the source file
|
||||||
|
var urls = GlobbingUrlBuilder.BuildUrlList(Src, SrcInclude, SrcExclude);
|
||||||
foreach (var url in urls)
|
foreach (var url in urls)
|
||||||
{
|
{
|
||||||
|
// "url" values come from bound attributes and globbing. Must always be non-null.
|
||||||
|
Debug.Assert(url != null);
|
||||||
|
|
||||||
|
var content = originalContent;
|
||||||
|
if (!string.Equals(url, Src, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// Do not copy content into added <script/> elements.
|
||||||
|
content = null;
|
||||||
|
}
|
||||||
|
|
||||||
attributes[SrcAttributeName] = url;
|
attributes[SrcAttributeName] = url;
|
||||||
var content =
|
|
||||||
string.Equals(url, staticSrc, StringComparison.OrdinalIgnoreCase) ? originalContent : null;
|
|
||||||
BuildScriptTag(content, attributes, builder);
|
BuildScriptTag(content, attributes, builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildFallbackBlock(IDictionary<string, string> attributes, DefaultTagHelperContent builder)
|
private void BuildFallbackBlock(IDictionary<string, object> attributes, DefaultTagHelperContent builder)
|
||||||
{
|
{
|
||||||
EnsureGlobbingUrlBuilder();
|
EnsureGlobbingUrlBuilder();
|
||||||
EnsureFileVersionProvider();
|
EnsureFileVersionProvider();
|
||||||
|
|
||||||
var fallbackSrcs = GlobbingUrlBuilder.BuildUrlList(FallbackSrc, FallbackSrcInclude, FallbackSrcExclude);
|
var fallbackSrcs = GlobbingUrlBuilder.BuildUrlList(FallbackSrc, FallbackSrcInclude, FallbackSrcExclude);
|
||||||
|
|
||||||
if (fallbackSrcs.Any())
|
if (fallbackSrcs.Any())
|
||||||
{
|
{
|
||||||
// Build the <script> tag that checks the test method and if it fails, renders the extra script.
|
// Build the <script> tag that checks the test method and if it fails, renders the extra script.
|
||||||
|
|
@ -243,36 +265,43 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
.Append(FallbackTestExpression)
|
.Append(FallbackTestExpression)
|
||||||
.Append("||document.write(\"");
|
.Append("||document.write(\"");
|
||||||
|
|
||||||
|
// May have no "src" attribute in the dictionary e.g. if Src and SrcInclude were not bound.
|
||||||
|
if (!attributes.ContainsKey(SrcAttributeName))
|
||||||
|
{
|
||||||
|
// Need this entry to place each fallback source.
|
||||||
|
attributes.Add(SrcAttributeName, null);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var src in fallbackSrcs)
|
foreach (var src in fallbackSrcs)
|
||||||
{
|
{
|
||||||
builder.Append("<script");
|
// Fallback "src" values come from bound attributes and globbing. Must always be non-null.
|
||||||
|
Debug.Assert(src != null);
|
||||||
|
|
||||||
if (!attributes.ContainsKey(SrcAttributeName))
|
builder.Append("<script");
|
||||||
{
|
|
||||||
AppendAttribute(
|
|
||||||
builder,
|
|
||||||
SrcAttributeName,
|
|
||||||
HtmlEncoder.HtmlEncode(ShouldAddFileVersion() ? _fileVersionProvider.AddFileVersionToPath(src) : src),
|
|
||||||
escapteQuotes: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var attribute in attributes)
|
foreach (var attribute in attributes)
|
||||||
{
|
{
|
||||||
if (!attribute.Key.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
|
if (!attribute.Key.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var encodedKey = JavaScriptStringEncoder.Default.JavaScriptStringEncode(attribute.Key);
|
var encodedKey = JavaScriptEncoder.JavaScriptStringEncode(attribute.Key);
|
||||||
var encodedValue = JavaScriptStringEncoder.Default.JavaScriptStringEncode(attribute.Value);
|
var attributeValue = attribute.Value.ToString();
|
||||||
|
var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue);
|
||||||
|
|
||||||
AppendAttribute(builder, encodedKey, encodedValue, escapteQuotes: true);
|
AppendAttribute(builder, encodedKey, encodedValue, escapeQuotes: true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AppendAttribute(
|
// Ignore attribute.Value; use src instead.
|
||||||
builder,
|
var attributeValue = src;
|
||||||
attribute.Key,
|
if (FileVersion == true)
|
||||||
HtmlEncoder.HtmlEncode(
|
{
|
||||||
ShouldAddFileVersion() ? _fileVersionProvider.AddFileVersionToPath(src) : src),
|
attributeValue = _fileVersionProvider.AddFileVersionToPath(attributeValue);
|
||||||
escapteQuotes: true);
|
}
|
||||||
|
|
||||||
|
// attribute.Key ("src") does not need to be JavaScript-encoded.
|
||||||
|
var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue);
|
||||||
|
|
||||||
|
AppendAttribute(builder, attribute.Key, encodedValue, escapeQuotes: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,7 +336,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
||||||
private void BuildScriptTag(
|
private void BuildScriptTag(
|
||||||
TagHelperContent content,
|
TagHelperContent content,
|
||||||
IDictionary<string, string> attributes,
|
IDictionary<string, object> attributes,
|
||||||
TagHelperContent builder)
|
TagHelperContent builder)
|
||||||
{
|
{
|
||||||
EnsureFileVersionProvider();
|
EnsureFileVersionProvider();
|
||||||
|
|
@ -315,16 +344,21 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
||||||
foreach (var attribute in attributes)
|
foreach (var attribute in attributes)
|
||||||
{
|
{
|
||||||
string attributeValue = attribute.Value;
|
var attributeValue = attribute.Value;
|
||||||
if (string.Equals(attribute.Key, SrcAttributeName, StringComparison.OrdinalIgnoreCase))
|
if (FileVersion == true &&
|
||||||
|
string.Equals(attribute.Key, SrcAttributeName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
attributeValue = HtmlEncoder.HtmlEncode(
|
// "src" values come from bound attributes and globbing. So anything but a non-null string is
|
||||||
ShouldAddFileVersion() ?
|
// unexpected but could happen if another helper targeting the same element does something odd.
|
||||||
_fileVersionProvider.AddFileVersionToPath(attribute.Value) :
|
// Pass through existing value in that case.
|
||||||
attributeValue);
|
var attributeStringValue = attributeValue as string;
|
||||||
|
if (attributeStringValue != null)
|
||||||
|
{
|
||||||
|
attributeValue = _fileVersionProvider.AddFileVersionToPath(attributeStringValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendAttribute(builder, attribute.Key, attributeValue, escapteQuotes: false);
|
AppendAttribute(builder, attribute.Key, attributeValue, escapeQuotes: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Append(">")
|
builder.Append(">")
|
||||||
|
|
@ -332,20 +366,27 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
.Append("</script>");
|
.Append("</script>");
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ShouldAddFileVersion()
|
private void AppendAttribute(TagHelperContent content, string key, object value, bool escapeQuotes)
|
||||||
{
|
|
||||||
return FileVersion ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AppendAttribute(TagHelperContent content, string key, string value, bool escapteQuotes)
|
|
||||||
{
|
{
|
||||||
content
|
content
|
||||||
.Append(" ")
|
.Append(" ")
|
||||||
.Append(key)
|
.Append(key);
|
||||||
.Append(escapteQuotes ? "=\\\"" : "=\"")
|
if (escapeQuotes)
|
||||||
.Append(value)
|
{
|
||||||
.Append(escapteQuotes ? "\\\"" : "\"");
|
// Passed only JavaScript-encoded strings in this case. Do not perform HTML-encoding as well.
|
||||||
|
content
|
||||||
|
.Append("=\\\"")
|
||||||
|
.Append((string)value)
|
||||||
|
.Append("\\\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// HTML-encoded the given value if necessary.
|
||||||
|
content
|
||||||
|
.Append("=\"")
|
||||||
|
.Append(HtmlEncoder, ViewContext.Writer.Encoding, value)
|
||||||
|
.Append("\"");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNet.Mvc.Razor;
|
||||||
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
using Microsoft.Framework.Internal;
|
||||||
|
using Microsoft.Framework.WebEncoders;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.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="IHtmlEncoder"/> to use when encoding <paramref name="value"/>.</param>
|
||||||
|
/// <param name="encoding">The character encoding in which the <paramref name="value"/> is written.</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="Rendering.HtmlString"/> are written without encoding and
|
||||||
|
/// <see cref="HelperResult.WriteTo"/> is invoked for <see cref="HelperResult"/> types. For all other types,
|
||||||
|
/// the encoded result of <see cref="object.ToString"/> is written to the <paramref name="content"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public static TagHelperContent Append(
|
||||||
|
[NotNull] this TagHelperContent content,
|
||||||
|
[NotNull] IHtmlEncoder encoder,
|
||||||
|
[NotNull] Encoding encoding,
|
||||||
|
object value)
|
||||||
|
{
|
||||||
|
using (var writer = new TagHelperContentWrapperTextWriter(encoding, content))
|
||||||
|
{
|
||||||
|
RazorPage.WriteTo(writer, encoder, value, escapeQuotes: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
using Microsoft.Framework.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
|
|
@ -24,18 +25,19 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
/// <param name="context">The <see cref="TagHelperContext"/>.</param>
|
/// <param name="context">The <see cref="TagHelperContext"/>.</param>
|
||||||
/// <remarks>Only copies the attribute if <paramref name="tagHelperOutput"/>'s
|
/// <remarks>Only copies the attribute if <paramref name="tagHelperOutput"/>'s
|
||||||
/// <see cref="TagHelperOutput.Attributes"/> does not contain an attribute with the given
|
/// <see cref="TagHelperOutput.Attributes"/> does not contain an attribute with the given
|
||||||
/// <paramref name="attributeName"/></remarks>
|
/// <paramref name="attributeName"/>.</remarks>
|
||||||
public static void CopyHtmlAttribute(this TagHelperOutput tagHelperOutput,
|
public static void CopyHtmlAttribute(
|
||||||
string attributeName,
|
[NotNull] this TagHelperOutput tagHelperOutput,
|
||||||
TagHelperContext context)
|
[NotNull] string attributeName,
|
||||||
|
[NotNull] TagHelperContext context)
|
||||||
{
|
{
|
||||||
// We look for the original attribute so we can restore the exact attribute name the user typed.
|
if (!tagHelperOutput.Attributes.ContainsKey(attributeName))
|
||||||
var entry = context.AllAttributes.First(attribute =>
|
|
||||||
attribute.Key.Equals(attributeName, StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
if (!tagHelperOutput.Attributes.ContainsKey(entry.Key))
|
|
||||||
{
|
{
|
||||||
tagHelperOutput.Attributes.Add(entry.Key, entry.Value.ToString());
|
// We look for the original attribute so we can restore the exact attribute name the user typed.
|
||||||
|
// Approach also ignores changes made to tagHelperOutput[attributeName].
|
||||||
|
var entry = context.AllAttributes.First(
|
||||||
|
attribute => attribute.Key.Equals(attributeName, StringComparison.OrdinalIgnoreCase));
|
||||||
|
tagHelperOutput.Attributes.Add(entry.Key, entry.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,8 +49,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
/// <param name="prefix">A prefix to look for.</param>
|
/// <param name="prefix">A prefix to look for.</param>
|
||||||
/// <returns><see cref="KeyValuePair{string, string}"/>s with <see cref="KeyValuePair{string, string}.Key"/>
|
/// <returns><see cref="KeyValuePair{string, string}"/>s with <see cref="KeyValuePair{string, string}.Key"/>
|
||||||
/// starting with the given <paramref name="prefix"/>.</returns>
|
/// starting with the given <paramref name="prefix"/>.</returns>
|
||||||
public static IEnumerable<KeyValuePair<string, string>> FindPrefixedAttributes(
|
public static IEnumerable<KeyValuePair<string, object>> FindPrefixedAttributes(
|
||||||
this TagHelperOutput tagHelperOutput, string prefix)
|
[NotNull] this TagHelperOutput tagHelperOutput,
|
||||||
|
[NotNull] string prefix)
|
||||||
{
|
{
|
||||||
// TODO: https://github.com/aspnet/Razor/issues/89 - We will not need this method once #89 is completed.
|
// TODO: https://github.com/aspnet/Razor/issues/89 - We will not need this method once #89 is completed.
|
||||||
|
|
||||||
|
|
@ -68,7 +71,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
/// <param name="tagBuilder">The <see cref="TagBuilder"/> to merge attributes from.</param>
|
/// <param name="tagBuilder">The <see cref="TagBuilder"/> to merge attributes from.</param>
|
||||||
/// <remarks>Existing <see cref="TagHelperOutput.Attributes"/> on the given <paramref name="tagHelperOutput"/>
|
/// <remarks>Existing <see cref="TagHelperOutput.Attributes"/> on the given <paramref name="tagHelperOutput"/>
|
||||||
/// are not overridden; "class" attributes are merged with spaces.</remarks>
|
/// are not overridden; "class" attributes are merged with spaces.</remarks>
|
||||||
public static void MergeAttributes(this TagHelperOutput tagHelperOutput, TagBuilder tagBuilder)
|
public static void MergeAttributes(
|
||||||
|
[NotNull] this TagHelperOutput tagHelperOutput,
|
||||||
|
[NotNull] TagBuilder tagBuilder)
|
||||||
{
|
{
|
||||||
foreach (var attribute in tagBuilder.Attributes)
|
foreach (var attribute in tagBuilder.Attributes)
|
||||||
{
|
{
|
||||||
|
|
@ -90,7 +95,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
/// <param name="tagHelperOutput">The <see cref="TagHelperOutput"/> this method extends.</param>
|
/// <param name="tagHelperOutput">The <see cref="TagHelperOutput"/> this method extends.</param>
|
||||||
/// <param name="attributes">Attributes to remove.</param>
|
/// <param name="attributes">Attributes to remove.</param>
|
||||||
public static void RemoveRange(
|
public static void RemoveRange(
|
||||||
this TagHelperOutput tagHelperOutput, IEnumerable<KeyValuePair<string, string>> attributes)
|
[NotNull] this TagHelperOutput tagHelperOutput,
|
||||||
|
[NotNull] IEnumerable<KeyValuePair<string, object>> attributes)
|
||||||
{
|
{
|
||||||
foreach (var attribute in attributes)
|
foreach (var attribute in attributes)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
{
|
{
|
||||||
return RetrieveAntiForgeryTokens(
|
return RetrieveAntiForgeryTokens(
|
||||||
htmlContent,
|
htmlContent,
|
||||||
attribute => attribute.Value.EndsWith(actionUrl, StringComparison.OrdinalIgnoreCase))
|
attribute => attribute.Value.EndsWith(actionUrl, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
attribute.Value.EndsWith($"HtmlEncode[[{ actionUrl }]]", StringComparison.OrdinalIgnoreCase))
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,8 +41,10 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
{
|
{
|
||||||
if (input.Attribute("name") != null &&
|
if (input.Attribute("name") != null &&
|
||||||
input.Attribute("type") != null &&
|
input.Attribute("type") != null &&
|
||||||
input.Attribute("name").Value == "__RequestVerificationToken" &&
|
(input.Attribute("name").Value == "__RequestVerificationToken" &&
|
||||||
input.Attribute("type").Value == "hidden")
|
input.Attribute("type").Value == "hidden" ||
|
||||||
|
input.Attribute("name").Value == "HtmlEncode[[__RequestVerificationToken]]" &&
|
||||||
|
input.Attribute("type").Value == "HtmlEncode[[hidden]]"))
|
||||||
{
|
{
|
||||||
yield return input.Attributes("value").First().Value;
|
yield return input.Attributes("value").First().Value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
<a href="">Product Index</a>
|
<a title="<the title>" href="">Product Index</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a href="">Product List</a>
|
<a title=""the" title" href="">Product List</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a id="MvcTagHelperTestIndex" href="/">MvcTagHelperTest Index</a>
|
<a id="MvcTagHelperTestIndex" href="/">MvcTagHelperTest Index</a>
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,19 @@
|
||||||
<title>Link</title>
|
<title>Link</title>
|
||||||
|
|
||||||
<!-- Plain link tag -->
|
<!-- Plain link tag -->
|
||||||
<link href="/site.css" rel="stylesheet" />
|
<link href="/site.css" rel="stylesheet" title="<the title>" />
|
||||||
|
|
||||||
<!-- Globbed link tag with existing file -->
|
<!-- Globbed link tag with existing file -->
|
||||||
<link rel="stylesheet" href="/site.css" />
|
<link rel="stylesheet" title="<the title>" href="/site.css" />
|
||||||
|
|
||||||
<!-- Globbed link tag with existing file and exclude -->
|
<!-- Globbed link tag with existing file and exclude -->
|
||||||
<link rel="stylesheet" href="/site.css" /><link rel="stylesheet" href="/sub/site2.css" />
|
<link rel="stylesheet" title=""the" title" href="/site.css" /><link rel="stylesheet" title=""the" title" href="/sub/site2.css" />
|
||||||
|
|
||||||
<!-- Globbed link tag missing include -->
|
<!-- Globbed link tag missing include -->
|
||||||
<link rel="stylesheet" />
|
<link rel="stylesheet" />
|
||||||
|
|
||||||
<!-- Globbed link tag missing include but with static href -->
|
<!-- Globbed link tag missing include but with static href -->
|
||||||
<link href="/site.css" rel="stylesheet" />
|
<link rel="stylesheet" href="/site.css" />
|
||||||
|
|
||||||
<!-- Globbed link tag with missing file -->
|
<!-- Globbed link tag with missing file -->
|
||||||
|
|
||||||
|
|
@ -31,14 +31,14 @@
|
||||||
|
|
||||||
|
|
||||||
<!-- Globbed link tag with existing file and static href -->
|
<!-- Globbed link tag with existing file and static href -->
|
||||||
<link href="/site.css" rel="stylesheet" /><link href="/sub/site2.css" rel="stylesheet" />
|
<link rel="stylesheet" href="/site.css" /><link rel="stylesheet" href="/sub/site2.css" />
|
||||||
|
|
||||||
<!-- Globbed link tag with existing file and static href should dedupe -->
|
<!-- Globbed link tag with existing file and static href should dedupe -->
|
||||||
<link href="/site.css" rel="stylesheet" />
|
<link rel="stylesheet" href="/site.css" />
|
||||||
|
|
||||||
<!-- Fallback to static href -->
|
<!-- Fallback to static href -->
|
||||||
<link href="/site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" title=""the" title" href="/site.min.css?a=b&c=d" />
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css?a=b\u0026c=d"]);</script>
|
||||||
|
|
||||||
<!-- Fallback from globbed href to static href -->
|
<!-- Fallback from globbed href to static href -->
|
||||||
|
|
||||||
|
|
@ -49,11 +49,11 @@
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
||||||
|
|
||||||
<!-- Fallback from globbed and static href to static href -->
|
<!-- Fallback from globbed and static href to static href -->
|
||||||
<link href="site.min.css" rel="stylesheet" data-extra="test" /><link href="/site.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="site.min.css" /><link rel="stylesheet" data-extra="test" href="/site.css" />
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
||||||
|
|
||||||
<!-- Fallback from globbed and static href with exclude to static href -->
|
<!-- Fallback from globbed and static href with exclude to static href -->
|
||||||
<link href="site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="site.min.css" />
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
||||||
|
|
||||||
<!-- Fallback to static href with no primary href -->
|
<!-- Fallback to static href with no primary href -->
|
||||||
|
|
@ -61,19 +61,19 @@
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
||||||
|
|
||||||
<!-- Fallback to globbed href -->
|
<!-- Fallback to globbed href -->
|
||||||
<link href="/site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="/site.min.css" />
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
||||||
|
|
||||||
<!-- Fallback to static and globbed href -->
|
<!-- Fallback to static and globbed href -->
|
||||||
<link href="/site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="/site.min.css" />
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css","\/sub\/site2.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css","\/sub\/site2.css"]);</script>
|
||||||
|
|
||||||
<!-- Fallback to static and globbed href should dedupe -->
|
<!-- Fallback to static and globbed href should dedupe -->
|
||||||
<link href="/site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="/site.min.css" />
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
||||||
|
|
||||||
<!-- Fallback to static and globbed href with exclude -->
|
<!-- Fallback to static and globbed href with exclude -->
|
||||||
<link href="/site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="/site.min.css" />
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css","\/sub\/site2.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css","\/sub\/site2.css"]);</script>
|
||||||
|
|
||||||
<!-- Fallback from globbed href to glbobed href -->
|
<!-- Fallback from globbed href to glbobed href -->
|
||||||
|
|
@ -85,44 +85,44 @@
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
||||||
|
|
||||||
<!-- Fallback from globbed and static href to globbed href -->
|
<!-- Fallback from globbed and static href to globbed href -->
|
||||||
<link href="site.min.css" rel="stylesheet" data-extra="test" /><link href="/site.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="site.min.css" /><link rel="stylesheet" data-extra="test" href="/site.css" />
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
||||||
|
|
||||||
<!-- Fallback from globbed and static href with exclude to globbed href -->
|
<!-- Fallback from globbed and static href with exclude to globbed href -->
|
||||||
<link href="site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="site.min.css" />
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css"]);</script>
|
||||||
|
|
||||||
<!-- Kitchen sink, all the attributes -->
|
<!-- Kitchen sink, all the attributes -->
|
||||||
<link href="site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="site.min.css" />
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css","\/sub\/site2.css"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css","\/sub\/site2.css"]);</script>
|
||||||
|
|
||||||
<!-- Fallback to globbed href that doesn't exist -->
|
<!-- Fallback to globbed href that doesn't exist -->
|
||||||
<link href="/site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="/site.min.css" />
|
||||||
|
|
||||||
<!-- Fallback to globbed href outside webroot -->
|
<!-- Fallback to globbed href outside webroot -->
|
||||||
<link href="/site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="/site.min.css" />
|
||||||
|
|
||||||
<!-- Fallback with missing attribute -->
|
<!-- Fallback with missing attribute -->
|
||||||
<link href="/site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="/site.min.css" />
|
||||||
|
|
||||||
<!-- Fallback with missing attribute -->
|
<!-- Fallback with missing attribute -->
|
||||||
<link href="/site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="/site.min.css" />
|
||||||
|
|
||||||
<!-- Fallback with missing attribute -->
|
<!-- Fallback with missing attribute -->
|
||||||
<link href="/site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="/site.min.css" />
|
||||||
|
|
||||||
<!-- Plain link tag with file version -->
|
<!-- Plain link tag with file version -->
|
||||||
<link href="/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc" rel="stylesheet" />
|
<link rel="stylesheet" href="/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc" />
|
||||||
|
|
||||||
<!-- Globbed link tag with existing file and file version -->
|
<!-- Globbed link tag with existing file and file version -->
|
||||||
<link rel="stylesheet" href="/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc" />
|
<link rel="stylesheet" href="/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc" />
|
||||||
|
|
||||||
<!-- Fallback with file version -->
|
<!-- Fallback with file version -->
|
||||||
<link href="/site.min.css" rel="stylesheet" data-extra="test" />
|
<link rel="stylesheet" data-extra="test" href="/site.min.css" />
|
||||||
<meta name="x-stylesheet-fallback-test" 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",["\/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc"]);</script>
|
<meta name="x-stylesheet-fallback-test" 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",["\/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc"]);</script>
|
||||||
|
|
||||||
<!-- Globbed link tag with existing file, static href and file version -->
|
<!-- Globbed link tag with existing file, static href and file version -->
|
||||||
<link href="/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc" rel="stylesheet" /><link href="/sub/site2.css?v=30cxPex0tA9xEatW7f1Qhnn8tVLAHgE6xwIZhESq0y0" rel="stylesheet" /><link href="/sub/site3.css?v=fSxxOr1Q4Dq2uPuzlju5UYGuK0SKABI-ghvaIGEsZDc" rel="stylesheet" /><link href="/sub/site3.min.css?v=s8JMmAZxBn0dzuhRtQ0wgOvNBK4XRJRWEC2wfzsVF9M" rel="stylesheet" />
|
<link rel="stylesheet" href="/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc" /><link rel="stylesheet" href="/sub/site2.css?v=30cxPex0tA9xEatW7f1Qhnn8tVLAHgE6xwIZhESq0y0" /><link rel="stylesheet" href="/sub/site3.css?v=fSxxOr1Q4Dq2uPuzlju5UYGuK0SKABI-ghvaIGEsZDc" /><link rel="stylesheet" href="/sub/site3.min.css?v=s8JMmAZxBn0dzuhRtQ0wgOvNBK4XRJRWEC2wfzsVF9M" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,34 +7,34 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>Script tag helper test</h2>
|
<h2>Script tag helper test</h2>
|
||||||
<script src="/site.js" data-foo="foo-data1">
|
<script src="/site.js" data-foo="foo-data1" title="<the title>">
|
||||||
// Regular script with comment in body, and extra properties.
|
// Regular script with comment in body, and extra properties.
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="/blank.js" data-foo="foo-data2">
|
<script data-foo="foo-data2" title="<the title>" src="/blank.js?a=b&c=d">
|
||||||
// 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=\"/site.js\" data-foo=\"foo-data2\"><\/script>"));</script>
|
<script>(false||document.write("<script data-foo=\"foo-data2\" title=\"\u0026lt;the title\u003E\" src=\"\/site.js?a=b\u0026c=d\"><\/script>"));</script>
|
||||||
|
|
||||||
<script src="/blank.js">
|
<script title=""the" title" src="/blank.js">
|
||||||
// Fallback to globbed src
|
// Fallback to globbed src
|
||||||
</script>
|
</script>
|
||||||
<script>(false||document.write("<script src=\"/site.js\"><\/script>"));</script>
|
<script>(false||document.write("<script title=\"\u0022the\u0022 title\" src=\"\/site.js\"><\/script>"));</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=\"/site.js\"><\/script><script src=\"/sub/site2.js\"><\/script>"));</script>
|
<script>(false||document.write("<script src=\"\/site.js\"><\/script><script src=\"\/sub\/site2.js\"><\/script>"));</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=\"/site.js\"><\/script><script src=\"/sub/site2.js\"><\/script>"));</script>
|
<script>(false||document.write("<script src=\"\/site.js\"><\/script><script src=\"\/sub\/site2.js\"><\/script>"));</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=\"/site.js\"><\/script>"));</script>
|
<script>(false||document.write("<script src=\"\/site.js\"><\/script>"));</script>
|
||||||
|
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// Fallback to globbed src with missing include
|
// Fallback to globbed src with missing include
|
||||||
|
|
@ -43,7 +43,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=\"/site.js\"><\/script>"));</script>
|
<script>(false||document.write("<script src=\"\/site.js\"><\/script>"));</script>
|
||||||
|
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// Fallback to globbed src outside of webroot
|
// Fallback to globbed src outside of webroot
|
||||||
|
|
@ -56,7 +56,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 src=\"/site.js\" data-foo=\"foo-data3\"><\/script>"));</script>
|
<script>(false||document.write("<script data-foo=\"foo-data3\" src=\"\/site.js\"><\/script>"));</script>
|
||||||
|
|
||||||
<script src="/blank.js">
|
<script src="/blank.js">
|
||||||
// Invalid TagHelper script with comment in body.
|
// Invalid TagHelper script with comment in body.
|
||||||
|
|
@ -96,12 +96,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=\"/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I\"><\/script>"));</script>
|
<script>(false||document.write("<script src=\"\/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I\"><\/script>"));</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=\"/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I\"><\/script>"));</script>
|
<script>(false||document.write("<script src=\"\/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I\"><\/script>"));</script>
|
||||||
|
|
||||||
<script src="/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I">
|
<script src="/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I">
|
||||||
// Regular script with comment in body, and file version.
|
// Regular script with comment in body, and file version.
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
using Microsoft.AspNet.Mvc.TagHelpers;
|
using Microsoft.AspNet.Mvc.TagHelpers;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.WebEncoders;
|
||||||
using MvcTagHelpersWebSite;
|
using MvcTagHelpersWebSite;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -76,6 +77,50 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
Assert.Equal(expectedContent.Trim(), responseContent.Trim());
|
Assert.Equal(expectedContent.Trim(), responseContent.Trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("EditWarehouse", null)]
|
||||||
|
[InlineData("Index", null)]
|
||||||
|
[InlineData("Link", null)]
|
||||||
|
[InlineData("Order", "/MvcTagHelper_Order/Submit")]
|
||||||
|
[InlineData("OrderUsingHtmlHelpers", "/MvcTagHelper_Order/Submit")]
|
||||||
|
[InlineData("Product", null)]
|
||||||
|
[InlineData("Script", null)]
|
||||||
|
public async Task MvcTagHelpers_GenerateEncodedResults(string action, string antiForgeryPath)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestHelper.CreateServer(_app, SiteName, services =>
|
||||||
|
{
|
||||||
|
_configureServices(services);
|
||||||
|
services.AddTransient<IHtmlEncoder, TestHtmlEncoder>();
|
||||||
|
services.AddTransient<IJavaScriptStringEncoder, TestJavaScriptEncoder>();
|
||||||
|
services.AddTransient<IUrlEncoder, TestUrlEncoder>();
|
||||||
|
});
|
||||||
|
var client = server.CreateClient();
|
||||||
|
var expectedMediaType = MediaTypeHeaderValue.Parse("text/html; charset=utf-8");
|
||||||
|
|
||||||
|
// The K runtime compiles every file under compiler/resources as a resource at runtime with the same name
|
||||||
|
// as the file name, in order to update a baseline you just need to change the file in that folder.
|
||||||
|
var expectedContent = await _resourcesAssembly.ReadResourceAsStringAsync(
|
||||||
|
"compiler/resources/MvcTagHelpersWebSite.MvcTagHelper_Home." + action + ".Encoded.html");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// The host is not important as everything runs in memory and tests are isolated from each other.
|
||||||
|
var response = await client.GetAsync("http://localhost/MvcTagHelper_Home/" + action);
|
||||||
|
var responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal(expectedMediaType, response.Content.Headers.ContentType);
|
||||||
|
|
||||||
|
if (antiForgeryPath != null)
|
||||||
|
{
|
||||||
|
var forgeryToken = AntiForgeryTestHelper.RetrieveAntiForgeryToken(responseContent, antiForgeryPath);
|
||||||
|
expectedContent = string.Format(expectedContent, forgeryToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Equal(expectedContent.Trim(), responseContent.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ValidationTagHelpers_GeneratesExpectedSpansAndDivs()
|
public async Task ValidationTagHelpers_GeneratesExpectedSpansAndDivs()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<form action="HtmlEncode[[/MvcTagHelper_Home/EditWarehouse]]" method="HtmlEncode[[post]]">
|
||||||
|
<div>
|
||||||
|
HtmlEncode[[City_1]]
|
||||||
|
<input type="HtmlEncode[[text]]" data-val="HtmlEncode[[true]]" data-val-minlength="HtmlEncode[[The field City must be a string or array type with a minimum length of '2'.]]" data-val-minlength-min="HtmlEncode[[2]]" id="HtmlEncode[[City]]" name="HtmlEncode[[City]]" value="HtmlEncode[[City_1]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>HtmlEncode[[Address]]</label>
|
||||||
|
<textarea id="HtmlEncode[[Employee_Address]]" name="HtmlEncode[[Employee.Address]]">
|
||||||
|
HtmlEncode[[Address_1]]</textarea>;
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="HtmlEncode[[Employee_Password]]">HtmlEncode[[Password]]</label>
|
||||||
|
<input data-val="HtmlEncode[[true]]" data-val-required="HtmlEncode[[The Password field is required.]]" id="HtmlEncode[[Employee_Password]]" name="HtmlEncode[[Employee.Password]]" type="HtmlEncode[[password]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>HtmlEncode[[PhoneNumber]]</label>
|
||||||
|
<input id="HtmlEncode[[Employee_PhoneNumber]]" name="HtmlEncode[[Employee.PhoneNumber]]" type="HtmlEncode[[text]]" value="HtmlEncode[[PhoneNumber_1]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="HtmlEncode[[Employee_Name]]">HtmlEncode[[Employee.Name]]</label>
|
||||||
|
<input type="HtmlEncode[[text]]" id="HtmlEncode[[Employee_Name]]" name="HtmlEncode[[Employee.Name]]" value="HtmlEncode[[EmployeeName_1]]" />
|
||||||
|
<span class="HtmlEncode[[field-validation-valid]]" data-valmsg-for="HtmlEncode[[Employee.Name]]" data-valmsg-replace="HtmlEncode[[true]]"></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="HtmlEncode[[Employee_Gender]]">HtmlEncode[[Gender]]</label>
|
||||||
|
<input checked="HtmlEncode[[checked]]" id="HtmlEncode[[Employee_Gender]]" name="HtmlEncode[[Employee.Gender]]" type="HtmlEncode[[radio]]" value="HtmlEncode[[Female]]" /> Female
|
||||||
|
<input id="HtmlEncode[[Employee_Gender]]" name="HtmlEncode[[Employee.Gender]]" type="HtmlEncode[[radio]]" value="HtmlEncode[[Male]]" /> Male
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="HtmlEncode[[Employee_OfficeNumber]]">HtmlEncode[[OfficeNumber]]</label>
|
||||||
|
|
||||||
|
<select id="HtmlEncode[[Employee_OfficeNumber]]" name="HtmlEncode[[Employee.OfficeNumber]]"><option>HtmlEncode[[1001]]</option>
|
||||||
|
<option>HtmlEncode[[1002]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<input data-val="HtmlEncode[[true]]" data-val-range="HtmlEncode[[The field Number must be between 1 and 100.]]" data-val-range-max="HtmlEncode[[100]]" data-val-range-min="HtmlEncode[[1]]" id="HtmlEncode[[Employee_Number]]" name="HtmlEncode[[Employee.Number]]" type="HtmlEncode[[hidden]]" value="HtmlEncode[[1]]" />
|
||||||
|
<div class="HtmlEncode[[validation-summary-valid]]" data-valmsg-summary="HtmlEncode[[true]]"><ul><li style="display:none"></li>
|
||||||
|
</ul></div>
|
||||||
|
<input type="submit" />
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<a title="<the title>" href="">Product Index</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a title=""the" title" href="">Product List</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a id="MvcTagHelperTestIndex" href="HtmlEncode[[/]]">MvcTagHelperTest Index</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="HtmlEncode[[/]]">Default Controller</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="">Product Index Fragment</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="">Produt Submit Fragment</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a id="MvcTagHelperTestIndexFragment" href="HtmlEncode[[/#fragment]]">
|
||||||
|
MvcTagHelperTest Index Fragment
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="HtmlEncode[[ftp://localhost/#fragment]]">
|
||||||
|
FTP MvcTagHelperTest Index Fragment
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="">
|
||||||
|
Unknown Protocol Product List
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a id="MvcTagHelperTestIndexProtocol" href="HtmlEncode[[/]]">
|
||||||
|
Empty Protocol MvcTagHelperTest Index
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="">Customer Area Customer Index</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="/Order/List">Href Order List</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="">Non-existent Controller</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="">
|
||||||
|
Non-existent Controller Fragment
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="">Non-existent Action</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a id="Id" href="HtmlEncode[[http://somewhere/]]">Some Where</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="">
|
||||||
|
Unknown Protocol Non-existent Controller Fragment
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="">Product Route Non-existent Area Parameter</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="">Non-existent Area</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Link</title>
|
||||||
|
|
||||||
|
<!-- Plain link tag -->
|
||||||
|
<link href="HtmlEncode[[/site.css]]" rel="stylesheet" title="<the title>" />
|
||||||
|
|
||||||
|
<!-- Globbed link tag with existing file -->
|
||||||
|
<link rel="stylesheet" title="<the title>" href="HtmlEncode[[/site.css]]" />
|
||||||
|
|
||||||
|
<!-- Globbed link tag with existing file and exclude -->
|
||||||
|
<link rel="stylesheet" title=""the" title" href="HtmlEncode[[/site.css]]" /><link rel="stylesheet" title=""the" title" href="HtmlEncode[[/sub/site2.css]]" />
|
||||||
|
|
||||||
|
<!-- Globbed link tag missing include -->
|
||||||
|
<link rel="stylesheet" />
|
||||||
|
|
||||||
|
<!-- Globbed link tag missing include but with static href -->
|
||||||
|
<link rel="stylesheet" href="HtmlEncode[[/site.css]]" />
|
||||||
|
|
||||||
|
<!-- Globbed link tag with missing file -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Globbed link tag with file outside of webroot -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Globbed link tag with file outside of webroot -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Globbed link tag with existing file and static href -->
|
||||||
|
<link rel="stylesheet" href="HtmlEncode[[/site.css]]" /><link rel="stylesheet" href="HtmlEncode[[/sub/site2.css]]" />
|
||||||
|
|
||||||
|
<!-- Globbed link tag with existing file and static href should dedupe -->
|
||||||
|
<link rel="stylesheet" href="HtmlEncode[[/site.css]]" />
|
||||||
|
|
||||||
|
<!-- Fallback to static href -->
|
||||||
|
<link rel="stylesheet" data-extra="test" title=""the" title" href="HtmlEncode[[/site.min.css?a=b&c=d]]" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css?a=b&c=d]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback from globbed href to static href -->
|
||||||
|
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback from globbed href with exclude to static href -->
|
||||||
|
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback from globbed and static href to static href -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[site.min.css]]" /><link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.css]]" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback from globbed and static href with exclude to static href -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[site.min.css]]" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback to static href with no primary href -->
|
||||||
|
<link rel="stylesheet" data-extra="test" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback to globbed href -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.min.css]]" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback to static and globbed href -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.min.css]]" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]","JavaScriptEncode[[/sub/site2.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback to static and globbed href should dedupe -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.min.css]]" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback to static and globbed href with exclude -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.min.css]]" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]","JavaScriptEncode[[/sub/site2.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback from globbed href to glbobed href -->
|
||||||
|
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback from globbed href with exclude to globbed href -->
|
||||||
|
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback from globbed and static href to globbed href -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[site.min.css]]" /><link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.css]]" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback from globbed and static href with exclude to globbed href -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[site.min.css]]" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Kitchen sink, all the attributes -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[site.min.css]]" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css]]","JavaScriptEncode[[/sub/site2.css]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Fallback to globbed href that doesn't exist -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.min.css]]" />
|
||||||
|
|
||||||
|
<!-- Fallback to globbed href outside webroot -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.min.css]]" />
|
||||||
|
|
||||||
|
<!-- Fallback with missing attribute -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.min.css]]" />
|
||||||
|
|
||||||
|
<!-- Fallback with missing attribute -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.min.css]]" />
|
||||||
|
|
||||||
|
<!-- Fallback with missing attribute -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.min.css]]" />
|
||||||
|
|
||||||
|
<!-- Plain link tag with file version -->
|
||||||
|
<link rel="stylesheet" href="HtmlEncode[[/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc]]" />
|
||||||
|
|
||||||
|
<!-- Globbed link tag with existing file and file version -->
|
||||||
|
<link rel="stylesheet" href="HtmlEncode[[/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc]]" />
|
||||||
|
|
||||||
|
<!-- Fallback with file version -->
|
||||||
|
<link rel="stylesheet" data-extra="test" href="HtmlEncode[[/site.min.css]]" />
|
||||||
|
<meta name="x-stylesheet-fallback-test" 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[[/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc]]"]);</script>
|
||||||
|
|
||||||
|
<!-- Globbed link tag with existing file, static href and file version -->
|
||||||
|
<link rel="stylesheet" href="HtmlEncode[[/site.css?v=XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh-pQc]]" /><link rel="stylesheet" href="HtmlEncode[[/sub/site2.css?v=30cxPex0tA9xEatW7f1Qhnn8tVLAHgE6xwIZhESq0y0]]" /><link rel="stylesheet" href="HtmlEncode[[/sub/site3.css?v=fSxxOr1Q4Dq2uPuzlju5UYGuK0SKABI-ghvaIGEsZDc]]" /><link rel="stylesheet" href="HtmlEncode[[/sub/site3.min.css?v=s8JMmAZxBn0dzuhRtQ0wgOvNBK4XRJRWEC2wfzsVF9M]]" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h2>Link Tag Helper Test</h2>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form action="HtmlEncode[[/MvcTagHelper_Order/Submit]]" method="HtmlEncode[[post]]">
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[Shipping]]">HtmlEncode[[Shipping]]</label>
|
||||||
|
<input size="50" type="HtmlEncode[[text]]" id="HtmlEncode[[Shipping]]" name="HtmlEncode[[Shipping]]" value="HtmlEncode[[Your shipping method is UPSP]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[ShippingDateTime]]">HtmlEncode[[ShippingDateTime]]</label>
|
||||||
|
<input type="HtmlEncode[[datetime-local]]" id="HtmlEncode[[ShippingDateTime]]" name="HtmlEncode[[ShippingDateTime]]" value="HtmlEncode[[01/01/0001 00:00:00]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[Products]]">HtmlEncode[[Products]]</label>
|
||||||
|
|
||||||
|
<select multiple="HtmlEncode[[multiple]]" id="HtmlEncode[[Products]]" name="HtmlEncode[[Products]]"><option selected="HtmlEncode[[selected]]" value="HtmlEncode[[0]]">HtmlEncode[[Product_0]]</option>
|
||||||
|
<option selected="HtmlEncode[[selected]]" value="HtmlEncode[[1]]">HtmlEncode[[Product_1]]</option>
|
||||||
|
<option value="HtmlEncode[[2]]">HtmlEncode[[Product_2]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[SubstituteProducts]]">HtmlEncode[[SubstituteProducts]]</label>
|
||||||
|
|
||||||
|
<select id="HtmlEncode[[SubstituteProducts]]" multiple="HtmlEncode[[multiple]]" name="HtmlEncode[[SubstituteProducts]]"><option value="HtmlEncode[[0]]">HtmlEncode[[Product_0]]</option>
|
||||||
|
<option value="HtmlEncode[[1]]">HtmlEncode[[Product_1]]</option>
|
||||||
|
<option selected="HtmlEncode[[selected]]" value="HtmlEncode[[2]]">HtmlEncode[[Product_2]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[OrderDate]]">HtmlEncode[[OrderDate]]</label>
|
||||||
|
<input type="HtmlEncode[[datetime]]" id="HtmlEncode[[OrderDate]]" name="HtmlEncode[[OrderDate]]" value="HtmlEncode[[0001/01/01/ A.D.]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[NeedSpecialHandle]]">HtmlEncode[[NeedSpecialHandle]]</label>
|
||||||
|
<input checked="HtmlEncode[[checked]]" id="HtmlEncode[[NeedSpecialHandle]]" name="HtmlEncode[[NeedSpecialHandle]]" type="HtmlEncode[[checkbox]]" value="HtmlEncode[[true]]" /><input name="HtmlEncode[[NeedSpecialHandle]]" type="HtmlEncode[[hidden]]" value="HtmlEncode[[false]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[PaymentMethod]]">HtmlEncode[[PaymentMethod]]</label>
|
||||||
|
<select id="HtmlEncode[[PaymentMethod]]" multiple="HtmlEncode[[multiple]]" name="HtmlEncode[[PaymentMethod]]">
|
||||||
|
<option value="HtmlEncode[[Credit]]">Credit</option>
|
||||||
|
<option value="HtmlEncode[[Check]]" selected="HtmlEncode[[selected]]">Check</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[Customer_Number]]">HtmlEncode[[Number]]</label>
|
||||||
|
<input class="form-control" type="HtmlEncode[[number]]" data-val="HtmlEncode[[true]]" data-val-range="HtmlEncode[[The field Number must be between 1 and 100.]]" data-val-range-max="HtmlEncode[[100]]" data-val-range-min="HtmlEncode[[1]]" id="HtmlEncode[[Customer_Number]]" name="HtmlEncode[[Customer.Number]]" value="HtmlEncode[[1]]" />
|
||||||
|
<span class="HtmlEncode[[field-validation-valid]]" data-valmsg-for="HtmlEncode[[Customer.Number]]" data-valmsg-replace="HtmlEncode[[true]]"></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[Customer_Name]]">HtmlEncode[[Name]]</label>
|
||||||
|
<input type="HtmlEncode[[text]]" id="HtmlEncode[[Customer_Name]]" name="HtmlEncode[[Customer.Name]]" value="HtmlEncode[[NameStringValue]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[Customer_Email]]">HtmlEncode[[Email]]</label>
|
||||||
|
<input type="HtmlEncode[[email]]" id="HtmlEncode[[Customer_Email]]" name="HtmlEncode[[Customer.Email]]" value="" />
|
||||||
|
<span class="HtmlEncode[[field-validation-valid]]" data-valmsg-for="HtmlEncode[[Customer.Email]]" data-valmsg-replace="HtmlEncode[[true]]"></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[Customer_PhoneNumber]]">HtmlEncode[[PhoneNumber]]</label>
|
||||||
|
<input type="HtmlEncode[[tel]]" id="HtmlEncode[[Customer_PhoneNumber]]" name="HtmlEncode[[Customer.PhoneNumber]]" value="" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[Customer_Password]]">HtmlEncode[[Password]]</label>
|
||||||
|
<input class="form-control" type="HtmlEncode[[password]]" data-val="HtmlEncode[[true]]" data-val-required="HtmlEncode[[The Password field is required.]]" id="HtmlEncode[[Customer_Password]]" name="HtmlEncode[[Customer.Password]]" />
|
||||||
|
<span class="HtmlEncode[[field-validation-valid]]" data-valmsg-for="HtmlEncode[[Customer.Password]]" data-valmsg-replace="HtmlEncode[[true]]"></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="order" for="HtmlEncode[[Customer_Gender]]">HtmlEncode[[Gender]]</label>
|
||||||
|
<input type="HtmlEncode[[radio]]" value="HtmlEncode[[Male]]" id="HtmlEncode[[Customer_Gender]]" name="HtmlEncode[[Customer.Gender]]" /> Male
|
||||||
|
<input type="HtmlEncode[[radio]]" value="HtmlEncode[[Female]]" checked="HtmlEncode[[checked]]" id="HtmlEncode[[Customer_Gender]]" name="HtmlEncode[[Customer.Gender]]" /> Female
|
||||||
|
<span class="HtmlEncode[[field-validation-valid]]" data-valmsg-for="HtmlEncode[[Customer.Gender]]" data-valmsg-replace="HtmlEncode[[true]]"></span>
|
||||||
|
</div>
|
||||||
|
<div class="HtmlEncode[[order validation-summary-valid]]" data-valmsg-summary="HtmlEncode[[true]]"><ul><li style="display:none"></li>
|
||||||
|
</ul></div>
|
||||||
|
<input type="HtmlEncode[[hidden]]" id="HtmlEncode[[Customer_Key]]" name="HtmlEncode[[Customer.Key]]" value="HtmlEncode[[KeyA]]" />
|
||||||
|
<input type="submit" />
|
||||||
|
<input name="HtmlEncode[[__RequestVerificationToken]]" type="HtmlEncode[[hidden]]" value="{0}" /></form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form action="HtmlEncode[[/MvcTagHelper_Order/Submit]]" method="HtmlEncode[[post]]">
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[Shipping]]">HtmlEncode[[Shipping]]</label>
|
||||||
|
<input id="HtmlEncode[[Shipping]]" name="HtmlEncode[[Shipping]]" size="HtmlEncode[[50]]" type="HtmlEncode[[text]]" value="HtmlEncode[[Your shipping method is UPSP]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[ShippingDateTime]]">HtmlEncode[[ShippingDateTime]]</label>
|
||||||
|
<input id="HtmlEncode[[ShippingDateTime]]" name="HtmlEncode[[ShippingDateTime]]" type="HtmlEncode[[datetime-local]]" value="HtmlEncode[[01/01/0001 00:00:00]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[Products]]">HtmlEncode[[Products]]</label>
|
||||||
|
|
||||||
|
<select id="HtmlEncode[[Products]]" multiple="HtmlEncode[[multiple]]" name="HtmlEncode[[Products]]"><option selected="HtmlEncode[[selected]]" value="HtmlEncode[[0]]">HtmlEncode[[Product_0]]</option>
|
||||||
|
<option selected="HtmlEncode[[selected]]" value="HtmlEncode[[1]]">HtmlEncode[[Product_1]]</option>
|
||||||
|
<option value="HtmlEncode[[2]]">HtmlEncode[[Product_2]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[SubstituteProducts]]">HtmlEncode[[SubstituteProducts]]</label>
|
||||||
|
|
||||||
|
<select id="HtmlEncode[[SubstituteProducts]]" multiple="HtmlEncode[[multiple]]" name="HtmlEncode[[SubstituteProducts]]"><option value="HtmlEncode[[0]]">HtmlEncode[[Product_0]]</option>
|
||||||
|
<option value="HtmlEncode[[1]]">HtmlEncode[[Product_1]]</option>
|
||||||
|
<option selected="HtmlEncode[[selected]]" value="HtmlEncode[[2]]">HtmlEncode[[Product_2]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[OrderDate]]">HtmlEncode[[OrderDate]]</label>
|
||||||
|
<input id="HtmlEncode[[OrderDate]]" name="HtmlEncode[[OrderDate]]" type="HtmlEncode[[datetime]]" value="HtmlEncode[[0001/01/01/ A.D.]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[NeedSpecialHandle]]">HtmlEncode[[NeedSpecialHandle]]</label>
|
||||||
|
<input checked="HtmlEncode[[checked]]" id="HtmlEncode[[NeedSpecialHandle]]" name="HtmlEncode[[NeedSpecialHandle]]" type="HtmlEncode[[checkbox]]" value="HtmlEncode[[true]]" /><input name="HtmlEncode[[NeedSpecialHandle]]" type="HtmlEncode[[hidden]]" value="HtmlEncode[[false]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[PaymentMethod]]">HtmlEncode[[PaymentMethod]]</label>
|
||||||
|
<select id="HtmlEncode[[PaymentMethod]]" multiple="HtmlEncode[[multiple]]" name="HtmlEncode[[PaymentMethod]]"><option value="HtmlEncode[[Credit]]">HtmlEncode[[Credit]]</option>
|
||||||
|
<option selected="HtmlEncode[[selected]]" value="HtmlEncode[[Check]]">HtmlEncode[[Check]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[Customer_Number]]">HtmlEncode[[Number]]</label>
|
||||||
|
<input class="HtmlEncode[[form-control]]" data-val="HtmlEncode[[true]]" data-val-range="HtmlEncode[[The field Number must be between 1 and 100.]]" data-val-range-max="HtmlEncode[[100]]" data-val-range-min="HtmlEncode[[1]]" id="HtmlEncode[[Customer_Number]]" name="HtmlEncode[[Customer.Number]]" type="HtmlEncode[[number]]" value="HtmlEncode[[1]]" />
|
||||||
|
<span class="HtmlEncode[[field-validation-valid]]" data-valmsg-for="HtmlEncode[[Customer.Number]]" data-valmsg-replace="HtmlEncode[[true]]"></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[Customer_Name]]">HtmlEncode[[Name]]</label>
|
||||||
|
<input id="HtmlEncode[[Customer_Name]]" name="HtmlEncode[[Customer.Name]]" type="HtmlEncode[[text]]" value="HtmlEncode[[NameStringValue]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[Customer_Email]]">HtmlEncode[[Email]]</label>
|
||||||
|
<input id="HtmlEncode[[Customer_Email]]" name="HtmlEncode[[Customer.Email]]" type="HtmlEncode[[email]]" value="" />
|
||||||
|
<span class="HtmlEncode[[field-validation-valid]]" data-valmsg-for="HtmlEncode[[Customer.Email]]" data-valmsg-replace="HtmlEncode[[true]]"></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[Customer_PhoneNumber]]">HtmlEncode[[PhoneNumber]]</label>
|
||||||
|
<input id="HtmlEncode[[Customer_PhoneNumber]]" name="HtmlEncode[[Customer.PhoneNumber]]" type="HtmlEncode[[tel]]" value="" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[Customer_Password]]">HtmlEncode[[Password]]</label>
|
||||||
|
<input class="HtmlEncode[[form-control]]" data-val="HtmlEncode[[true]]" data-val-required="HtmlEncode[[The Password field is required.]]" id="HtmlEncode[[Customer_Password]]" name="HtmlEncode[[Customer.Password]]" type="HtmlEncode[[password]]" />
|
||||||
|
<span class="HtmlEncode[[field-validation-valid]]" data-valmsg-for="HtmlEncode[[Customer.Password]]" data-valmsg-replace="HtmlEncode[[true]]"></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="HtmlEncode[[order]]" for="HtmlEncode[[Customer_Gender]]">HtmlEncode[[Gender]]</label>
|
||||||
|
<input id="HtmlEncode[[Customer_Gender]]" name="HtmlEncode[[Customer.Gender]]" type="HtmlEncode[[radio]]" value="HtmlEncode[[Male]]" /> Male
|
||||||
|
<input checked="HtmlEncode[[checked]]" id="HtmlEncode[[Customer_Gender]]" name="HtmlEncode[[Customer.Gender]]" type="HtmlEncode[[radio]]" value="HtmlEncode[[Female]]" /> Female
|
||||||
|
<span class="HtmlEncode[[field-validation-valid]]" data-valmsg-for="HtmlEncode[[Customer.Gender]]" data-valmsg-replace="HtmlEncode[[true]]"></span>
|
||||||
|
</div>
|
||||||
|
<div class="HtmlEncode[[validation-summary-valid order]]" data-valmsg-summary="HtmlEncode[[true]]"><ul><li style="display:none"></li>
|
||||||
|
</ul></div>
|
||||||
|
<input id="HtmlEncode[[Customer_Key]]" name="HtmlEncode[[Customer.Key]]" type="HtmlEncode[[hidden]]" value="HtmlEncode[[KeyA]]" />
|
||||||
|
<input type="submit"/>
|
||||||
|
<input name="HtmlEncode[[__RequestVerificationToken]]" type="HtmlEncode[[hidden]]" value="{0}" /></form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form action="HtmlEncode[[/MvcTagHelper_Home/ProductSubmit]]" method="get">
|
||||||
|
<div>
|
||||||
|
<label class="product" for="HtmlEncode[[HomePage]]">HtmlEncode[[HomePage]]</label>
|
||||||
|
<input size="50" type="HtmlEncode[[url]]" id="HtmlEncode[[HomePage]]" name="HtmlEncode[[HomePage]]" value="HtmlEncode[[http://www.contoso.com/]]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="product" for="HtmlEncode[[Description]]">HtmlEncode[[Description]]</label>
|
||||||
|
<textarea rows="4" cols="50" class="product" id="HtmlEncode[[Description]]" name="HtmlEncode[[Description]]">
|
||||||
|
HtmlEncode[[Type the product description]]</textarea>
|
||||||
|
</div>
|
||||||
|
<input type="submit" />
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Script</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Script tag helper test</h2>
|
||||||
|
<script src="HtmlEncode[[/site.js]]" data-foo="foo-data1" title="<the title>">
|
||||||
|
// Regular script with comment in body, and extra properties.
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script data-foo="foo-data2" title="<the title>" src="HtmlEncode[[/blank.js?a=b&c=d]]">
|
||||||
|
// TagHelper script with comment in body, and extra properties.
|
||||||
|
</script>
|
||||||
|
<script>(false||document.write("<script JavaScriptEncode[[data-foo]]=\"JavaScriptEncode[[foo-data2]]\" JavaScriptEncode[[title]]=\"JavaScriptEncode[[<the title>]]\" src=\"JavaScriptEncode[[/site.js?a=b&c=d]]\"><\/script>"));</script>
|
||||||
|
|
||||||
|
<script title=""the" title" src="HtmlEncode[[/blank.js]]">
|
||||||
|
// Fallback to globbed src
|
||||||
|
</script>
|
||||||
|
<script>(false||document.write("<script JavaScriptEncode[[title]]=\"JavaScriptEncode[["the" title]]\" src=\"JavaScriptEncode[[/site.js]]\"><\/script>"));</script>
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
|
// Fallback to globbed src with exclude
|
||||||
|
</script>
|
||||||
|
<script>(false||document.write("<script src=\"JavaScriptEncode[[/site.js]]\"><\/script><script src=\"JavaScriptEncode[[/sub/site2.js]]\"><\/script>"));</script>
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
|
// Fallback to globbed and static src
|
||||||
|
</script>
|
||||||
|
<script>(false||document.write("<script src=\"JavaScriptEncode[[/site.js]]\"><\/script><script src=\"JavaScriptEncode[[/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[[/site.js]]\"><\/script>"));</script>
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
|
// Fallback to globbed src with missing include
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
|
// Fallback to static and globbed src with missing include
|
||||||
|
</script>
|
||||||
|
<script>(false||document.write("<script src=\"JavaScriptEncode[[/site.js]]\"><\/script>"));</script>
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
|
// Fallback to globbed src outside of webroot
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
|
// Fallback to globbed src outside of webroot
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<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[[/site.js]]\"><\/script>"));</script>
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
|
// Invalid TagHelper script with comment in body.
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Globbed script tag with existing file -->
|
||||||
|
<script src="HtmlEncode[[/site.js]]"></script>
|
||||||
|
|
||||||
|
<!-- Globbed script tag with existing file and exclude -->
|
||||||
|
<script src="HtmlEncode[[/site.js]]"></script><script src="HtmlEncode[[/sub/site2.js]]"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Globbed script tag missing include
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/site.js]]">
|
||||||
|
// Globbed script tag missing include but with static src
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Globbed script tag with missing file -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Globbed script tag with file outside of webroot -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Globbed script tag with file outside of webroot -->
|
||||||
|
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/site.js]]">
|
||||||
|
// Globbed script tag with existing file and static src
|
||||||
|
</script><script src="HtmlEncode[[/sub/site2.js]]"></script>
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/site.js]]">
|
||||||
|
// Globbed script tag with existing file and static src should dedupe
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/blank.js]]">
|
||||||
|
// TagHelper script with comment in body, and file version.
|
||||||
|
</script>
|
||||||
|
<script>(false||document.write("<script src=\"JavaScriptEncode[[/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[[/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]\"><\/script>"));</script>
|
||||||
|
|
||||||
|
<script src="HtmlEncode[[/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]">
|
||||||
|
// Regular script with comment in body, and file version.
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Globbed script tag with existing files and version -->
|
||||||
|
<script src="HtmlEncode[[/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]"></script><script src="HtmlEncode[[/sub/site2.js?v=pwJaxaQxnb-rPAdF2JlAp4xiPNq1XuJFd6TyOOfNF-0]]"></script><script src="HtmlEncode[[/sub/site3.js?v=lmeAMiqm76lnGyqHhu6PIBHAC0Vt46mgVB_KaG_gGdA]]"></script>
|
||||||
|
|
||||||
|
<!-- Globbed script tag with existing file, exclude and version -->
|
||||||
|
<script src="HtmlEncode[[/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]"></script><script src="HtmlEncode[[/sub/site2.js?v=pwJaxaQxnb-rPAdF2JlAp4xiPNq1XuJFd6TyOOfNF-0]]"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
"LoggingWebSite": "1.0.0",
|
"LoggingWebSite": "1.0.0",
|
||||||
"LowercaseUrlsWebSite": "1.0.0-*",
|
"LowercaseUrlsWebSite": "1.0.0-*",
|
||||||
"Microsoft.AspNet.Mvc": "6.0.0-*",
|
"Microsoft.AspNet.Mvc": "6.0.0-*",
|
||||||
|
"Microsoft.AspNet.Mvc.TestCommon": { "version": "6.0.0-*", "type": "build" },
|
||||||
"Microsoft.AspNet.Mvc.TestConfiguration": "1.0.0",
|
"Microsoft.AspNet.Mvc.TestConfiguration": "1.0.0",
|
||||||
"Microsoft.AspNet.Mvc.Xml": "6.0.0-*",
|
"Microsoft.AspNet.Mvc.Xml": "6.0.0-*",
|
||||||
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
||||||
|
|
|
||||||
|
|
@ -658,9 +658,10 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var buffer = writer.BufferedWriter.Buffer;
|
var buffer = writer.BufferedWriter.Buffer;
|
||||||
Assert.Equal(2, buffer.BufferEntries.Count);
|
Assert.Equal(3, buffer.BufferEntries.Count);
|
||||||
Assert.Equal("Hello world", buffer.BufferEntries[0]);
|
Assert.Equal("Hello world", buffer.BufferEntries[0]);
|
||||||
Assert.Same(stringCollectionWriter.Buffer.BufferEntries, buffer.BufferEntries[1]);
|
Assert.Equal("text1", buffer.BufferEntries[1]);
|
||||||
|
Assert.Equal("text2", buffer.BufferEntries[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TheoryData<TagHelperOutput, string> WriteTagHelper_InputData
|
public static TheoryData<TagHelperOutput, string> WriteTagHelper_InputData
|
||||||
|
|
@ -672,21 +673,21 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
// parameters: TagName, Attributes, SelfClosing, PreContent, Content, PostContent
|
// parameters: TagName, Attributes, SelfClosing, PreContent, Content, PostContent
|
||||||
GetTagHelperOutput("div", new Dictionary<string, string>(), false, null, "Hello World!", null),
|
GetTagHelperOutput("div", new Dictionary<string, object>(), false, null, "Hello World!", null),
|
||||||
"<div>Hello World!</div>"
|
"<div>Hello World!</div>"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
GetTagHelperOutput(null, new Dictionary<string, string>(), false, null, "Hello World!", null),
|
GetTagHelperOutput(null, new Dictionary<string, object>(), false, null, "Hello World!", null),
|
||||||
"Hello World!"
|
"Hello World!"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
GetTagHelperOutput(" ", new Dictionary<string, string>(), false, null, "Hello World!", null),
|
GetTagHelperOutput(" ", new Dictionary<string, object>(), false, null, "Hello World!", null),
|
||||||
"Hello World!"
|
"Hello World!"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
new Dictionary<string, string>() { { "test", "testVal" } },
|
new Dictionary<string, object>() { { "test", "testVal" } },
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
"Hello World!",
|
"Hello World!",
|
||||||
|
|
@ -696,7 +697,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{
|
{
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
new Dictionary<string, string>() { { "test", "testVal" }, { "something", " spaced " } },
|
new Dictionary<string, object>() { { "test", "testVal" }, { "something", " spaced " } },
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
"Hello World!",
|
"Hello World!",
|
||||||
|
|
@ -706,7 +707,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{
|
{
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
new Dictionary<string, string>() { { "test", "testVal" } },
|
new Dictionary<string, object>() { { "test", "testVal" } },
|
||||||
true,
|
true,
|
||||||
null,
|
null,
|
||||||
"Hello World!",
|
"Hello World!",
|
||||||
|
|
@ -716,7 +717,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{
|
{
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
new Dictionary<string, string>() { { "test", "testVal" }, { "something", " spaced " } },
|
new Dictionary<string, object>() { { "test", "testVal" }, { "something", " spaced " } },
|
||||||
true,
|
true,
|
||||||
null,
|
null,
|
||||||
"Hello World!",
|
"Hello World!",
|
||||||
|
|
@ -724,31 +725,31 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
"<p test=\"testVal\" something=\" spaced \" />"
|
"<p test=\"testVal\" something=\" spaced \" />"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
GetTagHelperOutput("p", new Dictionary<string, string>(), false, "Hello World!", null, null),
|
GetTagHelperOutput("p", new Dictionary<string, object>(), false, "Hello World!", null, null),
|
||||||
"<p>Hello World!</p>"
|
"<p>Hello World!</p>"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
GetTagHelperOutput("p", new Dictionary<string, string>(), false, null, "Hello World!", null),
|
GetTagHelperOutput("p", new Dictionary<string, object>(), false, null, "Hello World!", null),
|
||||||
"<p>Hello World!</p>"
|
"<p>Hello World!</p>"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
GetTagHelperOutput("p", new Dictionary<string, string>(), false, null, null, "Hello World!"),
|
GetTagHelperOutput("p", new Dictionary<string, object>(), false, null, null, "Hello World!"),
|
||||||
"<p>Hello World!</p>"
|
"<p>Hello World!</p>"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
GetTagHelperOutput("p", new Dictionary<string, string>(), false, "Hello", "Test", "World!"),
|
GetTagHelperOutput("p", new Dictionary<string, object>(), false, "Hello", "Test", "World!"),
|
||||||
"<p>HelloTestWorld!</p>"
|
"<p>HelloTestWorld!</p>"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
GetTagHelperOutput("p", new Dictionary<string, string>(), true, "Hello", "Test", "World!"),
|
GetTagHelperOutput("p", new Dictionary<string, object>(), true, "Hello", "Test", "World!"),
|
||||||
"<p />"
|
"<p />"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
GetTagHelperOutput("custom", new Dictionary<string, string>(), false, "Hello", "Test", "World!"),
|
GetTagHelperOutput("custom", new Dictionary<string, object>(), false, "Hello", "Test", "World!"),
|
||||||
"<custom>HelloTestWorld!</custom>"
|
"<custom>HelloTestWorld!</custom>"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
GetTagHelperOutput("random", new Dictionary<string, string>(), true, "Hello", "Test", "World!"),
|
GetTagHelperOutput("random", new Dictionary<string, object>(), true, "Hello", "Test", "World!"),
|
||||||
"<random />"
|
"<random />"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -807,8 +808,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
},
|
},
|
||||||
startTagHelperWritingScope: () => { },
|
startTagHelperWritingScope: () => { },
|
||||||
endTagHelperWritingScope: () => defaultTagHelperContent);
|
endTagHelperWritingScope: () => defaultTagHelperContent);
|
||||||
tagHelperExecutionContext.Output =
|
tagHelperExecutionContext.Output = new TagHelperOutput("p", new Dictionary<string, object>());
|
||||||
new TagHelperOutput("p", new Dictionary<string, string>());
|
|
||||||
if (childContentRetrieved)
|
if (childContentRetrieved)
|
||||||
{
|
{
|
||||||
await tagHelperExecutionContext.GetChildContentAsync();
|
await tagHelperExecutionContext.GetChildContentAsync();
|
||||||
|
|
@ -840,8 +840,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
executeChildContentAsync: () => { return Task.FromResult(result: true); },
|
executeChildContentAsync: () => { return Task.FromResult(result: true); },
|
||||||
startTagHelperWritingScope: () => { },
|
startTagHelperWritingScope: () => { },
|
||||||
endTagHelperWritingScope: () => new DefaultTagHelperContent());
|
endTagHelperWritingScope: () => new DefaultTagHelperContent());
|
||||||
tagHelperExecutionContext.Output =
|
tagHelperExecutionContext.Output = new TagHelperOutput("p", new Dictionary<string, object>());
|
||||||
new TagHelperOutput("p", new Dictionary<string, string>());
|
|
||||||
tagHelperExecutionContext.Output.Content.SetContent("Hello World!");
|
tagHelperExecutionContext.Output.Content.SetContent("Hello World!");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -886,7 +885,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
|
||||||
private static TagHelperOutput GetTagHelperOutput(
|
private static TagHelperOutput GetTagHelperOutput(
|
||||||
string tagName,
|
string tagName,
|
||||||
IDictionary<string, string> attributes,
|
IDictionary<string, object> attributes,
|
||||||
bool selfClosing,
|
bool selfClosing,
|
||||||
string preContent,
|
string preContent,
|
||||||
string content,
|
string content,
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
expectedTagName,
|
expectedTagName,
|
||||||
attributes: new Dictionary<string, string>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "id", "myanchor" },
|
{ "id", "myanchor" },
|
||||||
{ "asp-route-foo", "bar" },
|
{ "asp-route-foo", "bar" },
|
||||||
|
|
@ -97,7 +97,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"a",
|
"a",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
output.Content.SetContent(string.Empty);
|
output.Content.SetContent(string.Empty);
|
||||||
|
|
||||||
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
||||||
|
|
@ -139,7 +139,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"a",
|
"a",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
output.Content.SetContent(string.Empty);
|
output.Content.SetContent(string.Empty);
|
||||||
|
|
||||||
var generator = new Mock<IHtmlGenerator>();
|
var generator = new Mock<IHtmlGenerator>();
|
||||||
|
|
@ -180,7 +180,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var anchorTagHelper = new AnchorTagHelper();
|
var anchorTagHelper = new AnchorTagHelper();
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"a",
|
"a",
|
||||||
attributes: new Dictionary<string, string>()
|
attributes: new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
{ "href", "http://www.contoso.com" }
|
{ "href", "http://www.contoso.com" }
|
||||||
});
|
});
|
||||||
|
|
@ -218,7 +218,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
typeof(AnchorTagHelper).GetProperty(propertyName).SetValue(anchorTagHelper, "Home");
|
typeof(AnchorTagHelper).GetProperty(propertyName).SetValue(anchorTagHelper, "Home");
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"a",
|
"a",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
var expectedErrorMessage = "Cannot determine an 'href' attribute for <a>. An <a> with a specified " +
|
var expectedErrorMessage = "Cannot determine an 'href' attribute for <a>. An <a> with a specified " +
|
||||||
"'asp-route' must not have an 'asp-action' or 'asp-controller' attribute.";
|
"'asp-route' must not have an 'asp-action' or 'asp-controller' attribute.";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ using Microsoft.AspNet.Routing;
|
||||||
using Microsoft.Framework.Caching.Memory;
|
using Microsoft.Framework.Caching.Memory;
|
||||||
using Microsoft.Framework.Caching.Memory.Infrastructure;
|
using Microsoft.Framework.Caching.Memory.Infrastructure;
|
||||||
using Microsoft.Framework.Expiration.Interfaces;
|
using Microsoft.Framework.Expiration.Interfaces;
|
||||||
using Microsoft.Framework.WebEncoders;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -245,7 +244,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var childContent = "original-child-content";
|
var childContent = "original-child-content";
|
||||||
var cache = new MemoryCache(new MemoryCacheOptions());
|
var cache = new MemoryCache(new MemoryCacheOptions());
|
||||||
var tagHelperContext1 = GetTagHelperContext(id, childContent);
|
var tagHelperContext1 = GetTagHelperContext(id, childContent);
|
||||||
var tagHelperOutput1 = new TagHelperOutput("cache", new Dictionary<string, string>());
|
var tagHelperOutput1 = new TagHelperOutput("cache", new Dictionary<string, object>());
|
||||||
var cacheTagHelper1 = new CacheTagHelper
|
var cacheTagHelper1 = new CacheTagHelper
|
||||||
{
|
{
|
||||||
VaryByQuery = "key1,key2",
|
VaryByQuery = "key1,key2",
|
||||||
|
|
@ -266,7 +265,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
||||||
// Arrange - 2
|
// Arrange - 2
|
||||||
var tagHelperContext2 = GetTagHelperContext(id, "different-content");
|
var tagHelperContext2 = GetTagHelperContext(id, "different-content");
|
||||||
var tagHelperOutput2 = new TagHelperOutput("cache", new Dictionary<string, string>());
|
var tagHelperOutput2 = new TagHelperOutput("cache", new Dictionary<string, object>());
|
||||||
var cacheTagHelper2 = new CacheTagHelper
|
var cacheTagHelper2 = new CacheTagHelper
|
||||||
{
|
{
|
||||||
VaryByQuery = "key1,key2",
|
VaryByQuery = "key1,key2",
|
||||||
|
|
@ -295,7 +294,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var cache = new MemoryCache(new MemoryCacheOptions());
|
var cache = new MemoryCache(new MemoryCacheOptions());
|
||||||
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
|
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
|
||||||
var tagHelperOutput1 = new TagHelperOutput("cache",
|
var tagHelperOutput1 = new TagHelperOutput("cache",
|
||||||
new Dictionary<string, string> { { "attr", "value" } });
|
new Dictionary<string, object> { { "attr", "value" } });
|
||||||
tagHelperOutput1.PreContent.Append("<cache>");
|
tagHelperOutput1.PreContent.Append("<cache>");
|
||||||
tagHelperOutput1.PostContent.SetContent("</cache>");
|
tagHelperOutput1.PostContent.SetContent("</cache>");
|
||||||
var cacheTagHelper1 = new CacheTagHelper
|
var cacheTagHelper1 = new CacheTagHelper
|
||||||
|
|
@ -320,7 +319,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
|
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
|
||||||
var tagHelperOutput2 = new TagHelperOutput(
|
var tagHelperOutput2 = new TagHelperOutput(
|
||||||
"cache",
|
"cache",
|
||||||
new Dictionary<string, string> { { "attr", "value" } });
|
new Dictionary<string, object> { { "attr", "value" } });
|
||||||
tagHelperOutput2.PreContent.SetContent("<cache>");
|
tagHelperOutput2.PreContent.SetContent("<cache>");
|
||||||
tagHelperOutput2.PostContent.SetContent("</cache>");
|
tagHelperOutput2.PostContent.SetContent("</cache>");
|
||||||
var cacheTagHelper2 = new CacheTagHelper
|
var cacheTagHelper2 = new CacheTagHelper
|
||||||
|
|
@ -530,7 +529,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
|
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
|
||||||
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
|
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
|
||||||
var tagHelperOutput1 = new TagHelperOutput("cache",
|
var tagHelperOutput1 = new TagHelperOutput("cache",
|
||||||
new Dictionary<string, string> { { "attr", "value" } });
|
new Dictionary<string, object> { { "attr", "value" } });
|
||||||
tagHelperOutput1.PreContent.SetContent("<cache>");
|
tagHelperOutput1.PreContent.SetContent("<cache>");
|
||||||
tagHelperOutput1.PostContent.SetContent("</cache>");
|
tagHelperOutput1.PostContent.SetContent("</cache>");
|
||||||
var cacheTagHelper1 = new CacheTagHelper
|
var cacheTagHelper1 = new CacheTagHelper
|
||||||
|
|
@ -553,7 +552,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var childContent2 = "different-content";
|
var childContent2 = "different-content";
|
||||||
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
|
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
|
||||||
var tagHelperOutput2 = new TagHelperOutput("cache",
|
var tagHelperOutput2 = new TagHelperOutput("cache",
|
||||||
new Dictionary<string, string> { { "attr", "value" } });
|
new Dictionary<string, object> { { "attr", "value" } });
|
||||||
tagHelperOutput2.PreContent.SetContent("<cache>");
|
tagHelperOutput2.PreContent.SetContent("<cache>");
|
||||||
tagHelperOutput2.PostContent.SetContent("</cache>");
|
tagHelperOutput2.PostContent.SetContent("</cache>");
|
||||||
var cacheTagHelper2 = new CacheTagHelper
|
var cacheTagHelper2 = new CacheTagHelper
|
||||||
|
|
@ -587,7 +586,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
|
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
|
||||||
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
|
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
|
||||||
var tagHelperOutput1 = new TagHelperOutput("cache",
|
var tagHelperOutput1 = new TagHelperOutput("cache",
|
||||||
new Dictionary<string, string> { { "attr", "value" } });
|
new Dictionary<string, object> { { "attr", "value" } });
|
||||||
tagHelperOutput1.PreContent.SetContent("<cache>");
|
tagHelperOutput1.PreContent.SetContent("<cache>");
|
||||||
tagHelperOutput1.PostContent.SetContent("</cache>");
|
tagHelperOutput1.PostContent.SetContent("</cache>");
|
||||||
var cacheTagHelper1 = new CacheTagHelper
|
var cacheTagHelper1 = new CacheTagHelper
|
||||||
|
|
@ -611,7 +610,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var childContent2 = "different-content";
|
var childContent2 = "different-content";
|
||||||
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
|
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
|
||||||
var tagHelperOutput2 = new TagHelperOutput("cache",
|
var tagHelperOutput2 = new TagHelperOutput("cache",
|
||||||
new Dictionary<string, string> { { "attr", "value" } });
|
new Dictionary<string, object> { { "attr", "value" } });
|
||||||
tagHelperOutput2.PreContent.SetContent("<cache>");
|
tagHelperOutput2.PreContent.SetContent("<cache>");
|
||||||
tagHelperOutput2.PostContent.SetContent("</cache>");
|
tagHelperOutput2.PostContent.SetContent("</cache>");
|
||||||
var cacheTagHelper2 = new CacheTagHelper
|
var cacheTagHelper2 = new CacheTagHelper
|
||||||
|
|
@ -644,7 +643,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
|
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
|
||||||
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
|
var tagHelperContext1 = GetTagHelperContext(id, childContent1);
|
||||||
var tagHelperOutput1 = new TagHelperOutput("cache",
|
var tagHelperOutput1 = new TagHelperOutput("cache",
|
||||||
new Dictionary<string, string> { { "attr", "value" } });
|
new Dictionary<string, object> { { "attr", "value" } });
|
||||||
tagHelperOutput1.PreContent.SetContent("<cache>");
|
tagHelperOutput1.PreContent.SetContent("<cache>");
|
||||||
tagHelperOutput1.PostContent.SetContent("</cache>");
|
tagHelperOutput1.PostContent.SetContent("</cache>");
|
||||||
var cacheTagHelper1 = new CacheTagHelper
|
var cacheTagHelper1 = new CacheTagHelper
|
||||||
|
|
@ -668,7 +667,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var childContent2 = "different-content";
|
var childContent2 = "different-content";
|
||||||
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
|
var tagHelperContext2 = GetTagHelperContext(id, childContent2);
|
||||||
var tagHelperOutput2 = new TagHelperOutput("cache",
|
var tagHelperOutput2 = new TagHelperOutput("cache",
|
||||||
new Dictionary<string, string> { { "attr", "value" } });
|
new Dictionary<string, object> { { "attr", "value" } });
|
||||||
tagHelperOutput2.PreContent.SetContent("<cache>");
|
tagHelperOutput2.PreContent.SetContent("<cache>");
|
||||||
tagHelperOutput2.PostContent.SetContent("</cache>");
|
tagHelperOutput2.PostContent.SetContent("</cache>");
|
||||||
var cacheTagHelper2 = new CacheTagHelper
|
var cacheTagHelper2 = new CacheTagHelper
|
||||||
|
|
@ -712,7 +711,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
return Task.FromResult<TagHelperContent>(expectedContent);
|
return Task.FromResult<TagHelperContent>(expectedContent);
|
||||||
});
|
});
|
||||||
var tagHelperOutput = new TagHelperOutput("cache",
|
var tagHelperOutput = new TagHelperOutput("cache",
|
||||||
new Dictionary<string, string> { { "attr", "value" } });
|
new Dictionary<string, object> { { "attr", "value" } });
|
||||||
tagHelperOutput.PreContent.SetContent("<cache>");
|
tagHelperOutput.PreContent.SetContent("<cache>");
|
||||||
tagHelperOutput.PostContent.SetContent("</cache>");
|
tagHelperOutput.PostContent.SetContent("</cache>");
|
||||||
var cacheTagHelper = new CacheTagHelper
|
var cacheTagHelper = new CacheTagHelper
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Hosting;
|
using Microsoft.AspNet.Hosting;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.Framework.WebEncoders;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -147,9 +146,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Test
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private TagHelperOutput MakeTagHelperOutput(string tagName, IDictionary<string, string> attributes = null)
|
private TagHelperOutput MakeTagHelperOutput(string tagName, IDictionary<string, object> attributes = null)
|
||||||
{
|
{
|
||||||
attributes = attributes ?? new Dictionary<string, string>();
|
attributes = attributes ?? new Dictionary<string, object>();
|
||||||
|
|
||||||
return new TagHelperOutput(tagName, attributes);
|
return new TagHelperOutput(tagName, attributes);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.AspNet.Routing;
|
using Microsoft.AspNet.Routing;
|
||||||
using Microsoft.Framework.OptionsModel;
|
|
||||||
using Microsoft.Framework.WebEncoders;
|
using Microsoft.Framework.WebEncoders;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -45,7 +44,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
expectedTagName,
|
expectedTagName,
|
||||||
attributes: new Dictionary<string, string>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "id", "myform" },
|
{ "id", "myform" },
|
||||||
{ "asp-route-foo", "bar" },
|
{ "asp-route-foo", "bar" },
|
||||||
|
|
@ -67,7 +66,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
AntiForgery = true,
|
AntiForgery = true,
|
||||||
Controller = "home",
|
Controller = "home",
|
||||||
Generator = htmlGenerator,
|
Generator = htmlGenerator,
|
||||||
Method = "post",
|
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -110,7 +108,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"form",
|
"form",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
||||||
generator
|
generator
|
||||||
.Setup(mock => mock.GenerateForm(
|
.Setup(mock => mock.GenerateForm(
|
||||||
|
|
@ -159,10 +157,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
tagHelperContent.SetContent("Something");
|
tagHelperContent.SetContent("Something");
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
||||||
});
|
});
|
||||||
var expectedAttribute = new KeyValuePair<string, string>("asp-ROUTEE-NotRoute", "something");
|
var expectedAttribute = new KeyValuePair<string, object>("asp-ROUTEE-NotRoute", "something");
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"form",
|
"form",
|
||||||
attributes: new Dictionary<string, string>()
|
attributes: new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
{ "asp-route-val", "hello" },
|
{ "asp-route-val", "hello" },
|
||||||
{ "asp-roUte--Foo", "bar" }
|
{ "asp-roUte--Foo", "bar" }
|
||||||
|
|
@ -232,10 +230,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"form",
|
"form",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
||||||
generator
|
generator
|
||||||
.Setup(mock => mock.GenerateForm(viewContext, "Index", "Home", null, "POST", null))
|
.Setup(mock => mock.GenerateForm(viewContext, "Index", "Home", null, null, null))
|
||||||
.Returns(new TagBuilder("form", new HtmlEncoder()))
|
.Returns(new TagBuilder("form", new HtmlEncoder()))
|
||||||
.Verifiable();
|
.Verifiable();
|
||||||
var formTagHelper = new FormTagHelper
|
var formTagHelper = new FormTagHelper
|
||||||
|
|
@ -244,7 +242,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
AntiForgery = false,
|
AntiForgery = false,
|
||||||
Controller = "Home",
|
Controller = "Home",
|
||||||
Generator = generator.Object,
|
Generator = generator.Object,
|
||||||
Method = "POST",
|
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -260,52 +257,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Assert.Empty(output.PostContent.GetContent());
|
Assert.Empty(output.PostContent.GetContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("my-action")]
|
|
||||||
[InlineData("http://www.contoso.com")]
|
|
||||||
[InlineData("my/action")]
|
|
||||||
public async Task ProcessAsync_RestoresBoundAttributesIfActionIsSpecified(string htmlAction)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var formTagHelper = new FormTagHelper
|
|
||||||
{
|
|
||||||
Method = "POST"
|
|
||||||
};
|
|
||||||
var output = new TagHelperOutput("form",
|
|
||||||
attributes: new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{ "aCTiON", htmlAction },
|
|
||||||
});
|
|
||||||
|
|
||||||
var context = new TagHelperContext(
|
|
||||||
allAttributes: new Dictionary<string, object>()
|
|
||||||
{
|
|
||||||
{ "METhod", "POST" }
|
|
||||||
},
|
|
||||||
items: new Dictionary<object, object>(),
|
|
||||||
uniqueId: "test",
|
|
||||||
getChildContentAsync: () =>
|
|
||||||
{
|
|
||||||
var tagHelperContent = new DefaultTagHelperContent();
|
|
||||||
tagHelperContent.SetContent("Something");
|
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Act
|
|
||||||
await formTagHelper.ProcessAsync(context, output);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal("form", output.TagName);
|
|
||||||
Assert.Equal(2, output.Attributes.Count);
|
|
||||||
var attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("aCTiON"));
|
|
||||||
Assert.Equal(htmlAction, attribute.Value);
|
|
||||||
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("METhod"));
|
|
||||||
Assert.Equal("POST", attribute.Value);
|
|
||||||
Assert.Empty(output.PreContent.GetContent());
|
|
||||||
Assert.True(output.Content.IsEmpty);
|
|
||||||
Assert.Empty(output.PostContent.GetContent());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(true, "<input />")]
|
[InlineData(true, "<input />")]
|
||||||
[InlineData(false, "")]
|
[InlineData(false, "")]
|
||||||
|
|
@ -328,7 +279,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
};
|
};
|
||||||
|
|
||||||
var output = new TagHelperOutput("form",
|
var output = new TagHelperOutput("form",
|
||||||
attributes: new Dictionary<string, string>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "aCTiON", "my-action" },
|
{ "aCTiON", "my-action" },
|
||||||
});
|
});
|
||||||
|
|
@ -351,7 +302,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Assert.Equal("form", output.TagName);
|
Assert.Equal("form", output.TagName);
|
||||||
Assert.False(output.SelfClosing);
|
Assert.False(output.SelfClosing);
|
||||||
var attribute = Assert.Single(output.Attributes);
|
var attribute = Assert.Single(output.Attributes);
|
||||||
Assert.Equal(new KeyValuePair<string, string>("aCTiON", "my-action"), attribute);
|
Assert.Equal(new KeyValuePair<string, object>("aCTiON", "my-action"), attribute);
|
||||||
Assert.Empty(output.PreContent.GetContent());
|
Assert.Empty(output.PreContent.GetContent());
|
||||||
Assert.True(output.Content.IsEmpty);
|
Assert.True(output.Content.IsEmpty);
|
||||||
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
|
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
|
||||||
|
|
@ -364,13 +315,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
public async Task ProcessAsync_ThrowsIfActionConflictsWithBoundAttributes(string propertyName)
|
public async Task ProcessAsync_ThrowsIfActionConflictsWithBoundAttributes(string propertyName)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var formTagHelper = new FormTagHelper
|
var formTagHelper = new FormTagHelper();
|
||||||
{
|
|
||||||
Method = "POST"
|
|
||||||
};
|
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"form",
|
"form",
|
||||||
attributes: new Dictionary<string, string>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "action", "my-action" },
|
{ "action", "my-action" },
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string expectedValue)
|
string expectedValue)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedAttributes = new Dictionary<string, string>
|
var expectedAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
{ "type", "text" },
|
{ "type", "text" },
|
||||||
|
|
@ -105,7 +105,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
tagHelperContent.SetContent("Something");
|
tagHelperContent.SetContent("Something");
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
||||||
});
|
});
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
|
|
@ -166,7 +166,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
tagHelperContent.SetContent("Something");
|
tagHelperContent.SetContent("Something");
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
||||||
});
|
});
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
|
|
@ -242,7 +242,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedAttributes = new Dictionary<string, string>
|
var expectedAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control hidden-control" },
|
{ "class", "form-control hidden-control" },
|
||||||
{ "type", inputTypeName ?? "hidden" }, // Generator restores type attribute; adds "hidden" if none.
|
{ "type", inputTypeName ?? "hidden" }, // Generator restores type attribute; adds "hidden" if none.
|
||||||
|
|
@ -262,7 +262,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
tagHelperContent.SetContent("Something");
|
tagHelperContent.SetContent("Something");
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
||||||
});
|
});
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
|
|
@ -341,7 +341,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedAttributes = new Dictionary<string, string>
|
var expectedAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control password-control" },
|
{ "class", "form-control password-control" },
|
||||||
{ "type", inputTypeName ?? "password" }, // Generator restores type attribute; adds "password" if none.
|
{ "type", inputTypeName ?? "password" }, // Generator restores type attribute; adds "password" if none.
|
||||||
|
|
@ -361,7 +361,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
tagHelperContent.SetContent("Something");
|
tagHelperContent.SetContent("Something");
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
||||||
});
|
});
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
|
|
@ -436,7 +436,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedAttributes = new Dictionary<string, string>
|
var expectedAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control radio-control" },
|
{ "class", "form-control radio-control" },
|
||||||
{ "type", inputTypeName ?? "radio" }, // Generator restores type attribute; adds "radio" if none.
|
{ "type", inputTypeName ?? "radio" }, // Generator restores type attribute; adds "radio" if none.
|
||||||
|
|
@ -457,7 +457,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
tagHelperContent.SetContent("Something");
|
tagHelperContent.SetContent("Something");
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
||||||
});
|
});
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
|
|
@ -542,7 +542,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedAttributes = new Dictionary<string, string>
|
var expectedAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control text-control" },
|
{ "class", "form-control text-control" },
|
||||||
{ "type", inputTypeName ?? "text" }, // Generator restores type attribute; adds "text" if none.
|
{ "type", inputTypeName ?? "text" }, // Generator restores type attribute; adds "text" if none.
|
||||||
|
|
@ -562,7 +562,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
tagHelperContent.SetContent("Something");
|
tagHelperContent.SetContent("Something");
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
||||||
});
|
});
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.Framework.WebEncoders;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
@ -165,7 +164,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedTagName = "not-label";
|
var expectedTagName = "not-label";
|
||||||
var expectedAttributes = new Dictionary<string, string>
|
var expectedAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
{ "for", tagHelperOutputContent.ExpectedId }
|
{ "for", tagHelperOutputContent.ExpectedId }
|
||||||
|
|
@ -196,7 +195,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
tagHelperContent.SetContent(tagHelperOutputContent.OriginalChildContent);
|
tagHelperContent.SetContent(tagHelperOutputContent.OriginalChildContent);
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
||||||
});
|
});
|
||||||
var htmlAttributes = new Dictionary<string, string>
|
var htmlAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var helper = new LinkTagHelper
|
var helper = new LinkTagHelper
|
||||||
{
|
{
|
||||||
HtmlEncoder = new HtmlEncoder(),
|
HtmlEncoder = new HtmlEncoder(),
|
||||||
|
JavaScriptEncoder = new JavaScriptStringEncoder(),
|
||||||
Logger = logger.Object,
|
Logger = logger.Object,
|
||||||
HostingEnvironment = hostingEnvironment,
|
HostingEnvironment = hostingEnvironment,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
|
|
@ -202,8 +203,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var context = MakeTagHelperContext(
|
var context = MakeTagHelperContext(
|
||||||
attributes: new Dictionary<string, object>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["rel"] = "stylesheet",
|
["rel"] = new HtmlString("stylesheet"),
|
||||||
["data-extra"] = "something",
|
["data-extra"] = new HtmlString("something"),
|
||||||
["href"] = "test.css",
|
["href"] = "test.css",
|
||||||
["asp-fallback-href"] = "test.css",
|
["asp-fallback-href"] = "test.css",
|
||||||
["asp-fallback-test-class"] = "hidden",
|
["asp-fallback-test-class"] = "hidden",
|
||||||
|
|
@ -211,11 +212,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
["asp-fallback-test-value"] = "hidden"
|
["asp-fallback-test-value"] = "hidden"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("link",
|
var output = MakeTagHelperOutput("link",
|
||||||
attributes: new Dictionary<string, string>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["rel"] = "stylesheet",
|
["rel"] = new HtmlString("stylesheet"),
|
||||||
["data-extra"] = "something",
|
["data-extra"] = new HtmlString("something"),
|
||||||
["href"] = "test.css"
|
|
||||||
});
|
});
|
||||||
var logger = new Mock<ILogger<LinkTagHelper>>();
|
var logger = new Mock<ILogger<LinkTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
|
|
@ -223,6 +223,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var helper = new LinkTagHelper
|
var helper = new LinkTagHelper
|
||||||
{
|
{
|
||||||
HtmlEncoder = new HtmlEncoder(),
|
HtmlEncoder = new HtmlEncoder(),
|
||||||
|
JavaScriptEncoder = new JavaScriptStringEncoder(),
|
||||||
Logger = logger.Object,
|
Logger = logger.Object,
|
||||||
HostingEnvironment = hostingEnvironment,
|
HostingEnvironment = hostingEnvironment,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
|
|
@ -230,6 +231,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
FallbackTestClass = "hidden",
|
FallbackTestClass = "hidden",
|
||||||
FallbackTestProperty = "visibility",
|
FallbackTestProperty = "visibility",
|
||||||
FallbackTestValue = "hidden",
|
FallbackTestValue = "hidden",
|
||||||
|
Href = "test.css",
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -374,14 +376,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var context = MakeTagHelperContext(
|
var context = MakeTagHelperContext(
|
||||||
attributes: new Dictionary<string, object>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
|
["rel"] = new HtmlString("stylesheet"),
|
||||||
["href"] = "/css/site.css",
|
["href"] = "/css/site.css",
|
||||||
["rel"] = "stylesheet",
|
|
||||||
["asp-href-include"] = "**/*.css"
|
["asp-href-include"] = "**/*.css"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, string>
|
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["href"] = "/css/site.css",
|
["rel"] = new HtmlString("stylesheet"),
|
||||||
["rel"] = "stylesheet"
|
|
||||||
});
|
});
|
||||||
var logger = new Mock<ILogger<LinkTagHelper>>();
|
var logger = new Mock<ILogger<LinkTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
|
|
@ -396,6 +397,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Logger = logger.Object,
|
Logger = logger.Object,
|
||||||
HostingEnvironment = hostingEnvironment,
|
HostingEnvironment = hostingEnvironment,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
|
Href = "/css/site.css",
|
||||||
HrefInclude = "**/*.css",
|
HrefInclude = "**/*.css",
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
};
|
};
|
||||||
|
|
@ -404,8 +406,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
helper.Process(context, output);
|
helper.Process(context, output);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("<link href=\"/css/site.css\" rel=\"stylesheet\" />" +
|
Assert.Equal(
|
||||||
"<link href=\"/base.css\" rel=\"stylesheet\" />", output.Content.GetContent());
|
"<link rel=\"stylesheet\" href=\"/css/site.css\" />" +
|
||||||
|
"<link rel=\"stylesheet\" href=\"/base.css\" />",
|
||||||
|
output.Content.GetContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -415,14 +419,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var context = MakeTagHelperContext(
|
var context = MakeTagHelperContext(
|
||||||
attributes: new Dictionary<string, object>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["href"] = "/css/site.css",
|
|
||||||
["rel"] = "stylesheet",
|
["rel"] = "stylesheet",
|
||||||
|
["href"] = "/css/site.css",
|
||||||
["asp-href-include"] = "**/*.css"
|
["asp-href-include"] = "**/*.css"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, string>
|
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["href"] = "/css/site.css",
|
["rel"] = "stylesheet",
|
||||||
["rel"] = "stylesheet"
|
|
||||||
});
|
});
|
||||||
var logger = new Mock<ILogger<LinkTagHelper>>();
|
var logger = new Mock<ILogger<LinkTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
|
|
@ -437,6 +440,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Logger = logger.Object,
|
Logger = logger.Object,
|
||||||
HostingEnvironment = hostingEnvironment,
|
HostingEnvironment = hostingEnvironment,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
|
Href = "/css/site.css",
|
||||||
HrefInclude = "**/*.css",
|
HrefInclude = "**/*.css",
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
};
|
};
|
||||||
|
|
@ -445,8 +449,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
helper.Process(context, output);
|
helper.Process(context, output);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("<link href=\"HtmlEncode[[/css/site.css]]\" rel=\"stylesheet\" />" +
|
Assert.Equal(
|
||||||
"<link href=\"HtmlEncode[[/base.css]]\" rel=\"stylesheet\" />", output.Content.GetContent());
|
"<link rel=\"HtmlEncode[[stylesheet]]\" href=\"HtmlEncode[[/css/site.css]]\" />" +
|
||||||
|
"<link rel=\"HtmlEncode[[stylesheet]]\" href=\"HtmlEncode[[/base.css]]\" />",
|
||||||
|
output.Content.GetContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -456,14 +462,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var context = MakeTagHelperContext(
|
var context = MakeTagHelperContext(
|
||||||
attributes: new Dictionary<string, object>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
|
["rel"] = new HtmlString("stylesheet"),
|
||||||
["href"] = "/css/site.css",
|
["href"] = "/css/site.css",
|
||||||
["rel"] = "stylesheet",
|
|
||||||
["asp-file-version"] = "true"
|
["asp-file-version"] = "true"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, string>
|
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["href"] = "/css/site.css",
|
["rel"] = new HtmlString("stylesheet"),
|
||||||
["rel"] = "stylesheet"
|
|
||||||
});
|
});
|
||||||
var logger = new Mock<ILogger<LinkTagHelper>>();
|
var logger = new Mock<ILogger<LinkTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
|
|
@ -474,6 +479,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Logger = logger.Object,
|
Logger = logger.Object,
|
||||||
HostingEnvironment = hostingEnvironment,
|
HostingEnvironment = hostingEnvironment,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
|
Href = "/css/site.css",
|
||||||
HrefInclude = "**/*.css",
|
HrefInclude = "**/*.css",
|
||||||
FileVersion = true,
|
FileVersion = true,
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
|
|
@ -483,8 +489,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
helper.Process(context, output);
|
helper.Process(context, output);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("<link href=\"HtmlEncode[[/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\"" +
|
Assert.Equal(
|
||||||
" rel=\"stylesheet\" />", output.Content.GetContent());
|
"<link rel=\"stylesheet\" href=\"HtmlEncode[[/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\" />",
|
||||||
|
output.Content.GetContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -494,14 +501,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var context = MakeTagHelperContext(
|
var context = MakeTagHelperContext(
|
||||||
attributes: new Dictionary<string, object>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
|
["rel"] = new HtmlString("stylesheet"),
|
||||||
["href"] = "/bar/css/site.css",
|
["href"] = "/bar/css/site.css",
|
||||||
["rel"] = "stylesheet",
|
|
||||||
["asp-file-version"] = "true"
|
["asp-file-version"] = "true"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, string>
|
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["href"] = "/bar/css/site.css",
|
["rel"] = new HtmlString("stylesheet"),
|
||||||
["rel"] = "stylesheet"
|
|
||||||
});
|
});
|
||||||
var logger = new Mock<ILogger<LinkTagHelper>>();
|
var logger = new Mock<ILogger<LinkTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
|
|
@ -512,6 +518,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Logger = logger.Object,
|
Logger = logger.Object,
|
||||||
HostingEnvironment = hostingEnvironment,
|
HostingEnvironment = hostingEnvironment,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
|
Href = "/bar/css/site.css",
|
||||||
HrefInclude = "**/*.css",
|
HrefInclude = "**/*.css",
|
||||||
FileVersion = true,
|
FileVersion = true,
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
|
|
@ -521,8 +528,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
helper.Process(context, output);
|
helper.Process(context, output);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("<link href=\"HtmlEncode[[/bar/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-" +
|
Assert.Equal(
|
||||||
"j1ncoSt3SABJtkGk]]\" rel=\"stylesheet\" />", output.Content.GetContent());
|
"<link rel=\"stylesheet\" href=\"HtmlEncode[[/bar/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\" />",
|
||||||
|
output.Content.GetContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -532,15 +540,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var context = MakeTagHelperContext(
|
var context = MakeTagHelperContext(
|
||||||
attributes: new Dictionary<string, object>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
|
["rel"] = new HtmlString("stylesheet"),
|
||||||
["href"] = "/css/site.css",
|
["href"] = "/css/site.css",
|
||||||
["rel"] = "stylesheet",
|
|
||||||
["asp-href-include"] = "**/*.css",
|
["asp-href-include"] = "**/*.css",
|
||||||
["asp-file-version"] = "true"
|
["asp-file-version"] = "true"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, string>
|
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["href"] = "/css/site.css",
|
["rel"] = new HtmlString("stylesheet"),
|
||||||
["rel"] = "stylesheet"
|
|
||||||
});
|
});
|
||||||
var logger = new Mock<ILogger<LinkTagHelper>>();
|
var logger = new Mock<ILogger<LinkTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
|
|
@ -555,6 +562,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Logger = logger.Object,
|
Logger = logger.Object,
|
||||||
HostingEnvironment = hostingEnvironment,
|
HostingEnvironment = hostingEnvironment,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
|
Href = "/css/site.css",
|
||||||
HrefInclude = "**/*.css",
|
HrefInclude = "**/*.css",
|
||||||
FileVersion = true,
|
FileVersion = true,
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
|
|
@ -564,9 +572,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
helper.Process(context, output);
|
helper.Process(context, output);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("<link href=\"HtmlEncode[[/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\"" +
|
Assert.Equal(
|
||||||
" rel=\"stylesheet\" /><link href=\"HtmlEncode[[/base.css" +
|
"<link rel=\"stylesheet\" href=\"HtmlEncode[[/css/site.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\" />" +
|
||||||
"?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\" rel=\"stylesheet\" />", output.Content.GetContent());
|
"<link rel=\"stylesheet\" href=\"HtmlEncode[[/base.css?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\" />",
|
||||||
|
output.Content.GetContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ViewContext MakeViewContext(string requestPathBase = null)
|
private static ViewContext MakeViewContext(string requestPathBase = null)
|
||||||
|
|
@ -607,9 +616,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TagHelperOutput MakeTagHelperOutput(string tagName, IDictionary<string, string> attributes = null)
|
private static TagHelperOutput MakeTagHelperOutput(string tagName, IDictionary<string, object> attributes = null)
|
||||||
{
|
{
|
||||||
attributes = attributes ?? new Dictionary<string, string>();
|
attributes = attributes ?? new Dictionary<string, object>();
|
||||||
|
|
||||||
return new TagHelperOutput(tagName, attributes);
|
return new TagHelperOutput(tagName, attributes);
|
||||||
}
|
}
|
||||||
|
|
@ -671,27 +680,5 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
return cache.Object;
|
return cache.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestHtmlEncoder : IHtmlEncoder
|
|
||||||
{
|
|
||||||
public string HtmlEncode(string value)
|
|
||||||
{
|
|
||||||
return "HtmlEncode[[" + value + "]]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HtmlEncode(string value, int startIndex, int charCount, TextWriter output)
|
|
||||||
{
|
|
||||||
output.Write("HtmlEncode[[");
|
|
||||||
output.Write(value.Substring(startIndex, charCount));
|
|
||||||
output.Write("]]");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HtmlEncode(char[] value, int startIndex, int charCount, TextWriter output)
|
|
||||||
{
|
|
||||||
output.Write("HtmlEncode[[");
|
|
||||||
output.Write(value, startIndex, charCount);
|
|
||||||
output.Write("]]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
null, null, null, null,
|
null, null, null, null,
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }
|
{ "label", "my-label" }
|
||||||
},
|
},
|
||||||
|
|
@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
null, string.Empty, "value", null,
|
null, string.Empty, "value", null,
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
|
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
|
||||||
},
|
},
|
||||||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
null, "selected", "value", null,
|
null, "selected", "value", null,
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
|
|
@ -56,7 +56,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
null, null, "value", Enumerable.Empty<string>(),
|
null, null, "value", Enumerable.Empty<string>(),
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }
|
{ "label", "my-label" }, { "value", "value" }
|
||||||
},
|
},
|
||||||
|
|
@ -66,7 +66,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
null, null, "value", new [] { string.Empty, },
|
null, null, "value", new [] { string.Empty, },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }
|
{ "label", "my-label" }, { "value", "value" }
|
||||||
},
|
},
|
||||||
|
|
@ -76,7 +76,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
null, string.Empty, "value", new [] { string.Empty, },
|
null, string.Empty, "value", new [] { string.Empty, },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
|
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
|
||||||
},
|
},
|
||||||
|
|
@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
null, null, "value", new [] { "value", },
|
null, null, "value", new [] { "value", },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
|
|
@ -96,7 +96,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
null, null, "value", new [] { string.Empty, "value", },
|
null, null, "value", new [] { string.Empty, "value", },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
|
|
@ -106,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string.Empty, null, null, null,
|
string.Empty, null, null, null,
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }
|
{ "label", "my-label" }
|
||||||
},
|
},
|
||||||
|
|
@ -116,7 +116,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string.Empty, string.Empty, null, null,
|
string.Empty, string.Empty, null, null,
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "selected", "" }
|
{ "label", "my-label" }, { "selected", "" }
|
||||||
},
|
},
|
||||||
|
|
@ -126,7 +126,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string.Empty, "selected", null, null,
|
string.Empty, "selected", null, null,
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
|
|
@ -136,7 +136,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string.Empty, null, null, Enumerable.Empty<string>(),
|
string.Empty, null, null, Enumerable.Empty<string>(),
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }
|
{ "label", "my-label" }
|
||||||
},
|
},
|
||||||
|
|
@ -146,7 +146,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string.Empty, null, null, new [] { string.Empty, },
|
string.Empty, null, null, new [] { string.Empty, },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
|
|
@ -156,7 +156,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string.Empty, string.Empty, null, new [] { string.Empty, },
|
string.Empty, string.Empty, null, new [] { string.Empty, },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "selected", "" }
|
{ "label", "my-label" }, { "selected", "" }
|
||||||
},
|
},
|
||||||
|
|
@ -166,7 +166,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string.Empty, null, null, new [] { "text", },
|
string.Empty, null, null, new [] { "text", },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }
|
{ "label", "my-label" }
|
||||||
},
|
},
|
||||||
|
|
@ -176,18 +176,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string.Empty, null, null, new [] { string.Empty, "text", },
|
string.Empty, null, null, new [] { string.Empty, "text", },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
"")
|
"")
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"text", null, null, null,
|
"text", null, null, null,
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }
|
{ "label", "my-label" }
|
||||||
},
|
},
|
||||||
|
|
@ -197,7 +196,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", string.Empty, null, null,
|
"text", string.Empty, null, null,
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "selected", "" }
|
{ "label", "my-label" }, { "selected", "" }
|
||||||
},
|
},
|
||||||
|
|
@ -207,7 +206,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", "selected", null, null,
|
"text", "selected", null, null,
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
|
|
@ -217,7 +216,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", null, null, Enumerable.Empty<string>(),
|
"text", null, null, Enumerable.Empty<string>(),
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }
|
{ "label", "my-label" }
|
||||||
},
|
},
|
||||||
|
|
@ -227,7 +226,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", null, null, new [] { string.Empty, },
|
"text", null, null, new [] { string.Empty, },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }
|
{ "label", "my-label" }
|
||||||
},
|
},
|
||||||
|
|
@ -237,7 +236,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", null, null, new [] { "text", },
|
"text", null, null, new [] { "text", },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
|
|
@ -247,7 +246,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", string.Empty, null, new [] { "text", },
|
"text", string.Empty, null, new [] { "text", },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "selected", "" }
|
{ "label", "my-label" }, { "selected", "" }
|
||||||
},
|
},
|
||||||
|
|
@ -257,18 +256,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", null, null, new [] { string.Empty, "text", },
|
"text", null, null, new [] { string.Empty, "text", },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
"text")
|
"text")
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"text", string.Empty, "value", null,
|
"text", string.Empty, "value", null,
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
|
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
|
||||||
},
|
},
|
||||||
|
|
@ -278,7 +276,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", "selected", "value", null,
|
"text", "selected", "value", null,
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
|
|
@ -288,7 +286,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", null, "value", Enumerable.Empty<string>(),
|
"text", null, "value", Enumerable.Empty<string>(),
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }
|
{ "label", "my-label" }, { "value", "value" }
|
||||||
},
|
},
|
||||||
|
|
@ -298,7 +296,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", null, "value", new [] { string.Empty, },
|
"text", null, "value", new [] { string.Empty, },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }
|
{ "label", "my-label" }, { "value", "value" }
|
||||||
},
|
},
|
||||||
|
|
@ -308,7 +306,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", string.Empty, "value", new [] { string.Empty, },
|
"text", string.Empty, "value", new [] { string.Empty, },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
|
{ "label", "my-label" }, { "value", "value" }, { "selected", "" }
|
||||||
},
|
},
|
||||||
|
|
@ -318,7 +316,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", null, "value", new [] { "text", },
|
"text", null, "value", new [] { "text", },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }
|
{ "label", "my-label" }, { "value", "value" }
|
||||||
},
|
},
|
||||||
|
|
@ -328,7 +326,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", null, "value", new [] { "value", },
|
"text", null, "value", new [] { "value", },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
|
|
@ -338,7 +336,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
"text", null, "value", new [] { string.Empty, "value", },
|
"text", null, "value", new [] { string.Empty, "value", },
|
||||||
GetTagHelperOutput(
|
GetTagHelperOutput(
|
||||||
"not-option",
|
"not-option",
|
||||||
new Dictionary<string, string>
|
new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
{ "label", "my-label" }, { "value", "value" }, { "selected", "selected" }
|
||||||
},
|
},
|
||||||
|
|
@ -381,17 +379,21 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
TagHelperOutput expectedTagHelperOutput)
|
TagHelperOutput expectedTagHelperOutput)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" },
|
{ "label", "my-label" },
|
||||||
};
|
};
|
||||||
|
if (selected != null)
|
||||||
|
{
|
||||||
|
originalAttributes.Add("selected", selected);
|
||||||
|
}
|
||||||
|
|
||||||
var contextAttributes = new Dictionary<string, object>
|
var contextAttributes = new Dictionary<string, object>(originalAttributes);
|
||||||
|
if (value != null)
|
||||||
{
|
{
|
||||||
{ "label", "my-label" },
|
contextAttributes.Add("value", value);
|
||||||
{ "selected", selected },
|
}
|
||||||
{ "value", value },
|
|
||||||
};
|
|
||||||
var tagHelperContext = new TagHelperContext(
|
var tagHelperContext = new TagHelperContext(
|
||||||
contextAttributes,
|
contextAttributes,
|
||||||
items: new Dictionary<object, object>(),
|
items: new Dictionary<object, object>(),
|
||||||
|
|
@ -402,6 +404,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
tagHelperContent.SetContent(originalContent);
|
tagHelperContent.SetContent(originalContent);
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
||||||
});
|
});
|
||||||
|
|
||||||
var output = new TagHelperOutput(expectedTagHelperOutput.TagName, originalAttributes)
|
var output = new TagHelperOutput(expectedTagHelperOutput.TagName, originalAttributes)
|
||||||
{
|
{
|
||||||
SelfClosing = false,
|
SelfClosing = false,
|
||||||
|
|
@ -418,7 +421,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var tagHelper = new OptionTagHelper
|
var tagHelper = new OptionTagHelper
|
||||||
{
|
{
|
||||||
Generator = htmlGenerator,
|
Generator = htmlGenerator,
|
||||||
Selected = selected,
|
|
||||||
Value = value,
|
Value = value,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
};
|
};
|
||||||
|
|
@ -446,9 +448,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
TagHelperOutput ignored)
|
TagHelperOutput ignored)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" },
|
{ "label", "my-label" },
|
||||||
|
{ "selected", selected },
|
||||||
};
|
};
|
||||||
var originalTagName = "not-option";
|
var originalTagName = "not-option";
|
||||||
|
|
||||||
|
|
@ -487,7 +490,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
viewContext.FormContext.FormData[SelectTagHelper.SelectedValuesFormDataKey] = selectedValues;
|
viewContext.FormContext.FormData[SelectTagHelper.SelectedValuesFormDataKey] = selectedValues;
|
||||||
var tagHelper = new OptionTagHelper
|
var tagHelper = new OptionTagHelper
|
||||||
{
|
{
|
||||||
Selected = selected,
|
|
||||||
Value = value,
|
Value = value,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
};
|
};
|
||||||
|
|
@ -507,9 +509,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
TagHelperOutput ignoredOutput)
|
TagHelperOutput ignoredOutput)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "label", "my-label" },
|
{ "label", "my-label" },
|
||||||
|
{ "selected", selected },
|
||||||
};
|
};
|
||||||
var originalTagName = "not-option";
|
var originalTagName = "not-option";
|
||||||
|
|
||||||
|
|
@ -541,7 +544,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
||||||
var tagHelper = new OptionTagHelper
|
var tagHelper = new OptionTagHelper
|
||||||
{
|
{
|
||||||
Selected = selected,
|
|
||||||
Value = value,
|
Value = value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -551,7 +553,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TagHelperOutput GetTagHelperOutput(
|
private static TagHelperOutput GetTagHelperOutput(
|
||||||
string tagName, IDictionary<string, string> attributes, string content)
|
string tagName, IDictionary<string, object> attributes, string content)
|
||||||
{
|
{
|
||||||
var tagHelperOutput = new TagHelperOutput(tagName, attributes);
|
var tagHelperOutput = new TagHelperOutput(tagName, attributes);
|
||||||
tagHelperOutput.Content.SetContent(content);
|
tagHelperOutput.Content.SetContent(content);
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var helper = new ScriptTagHelper
|
var helper = new ScriptTagHelper
|
||||||
{
|
{
|
||||||
HtmlEncoder = new HtmlEncoder(),
|
HtmlEncoder = new HtmlEncoder(),
|
||||||
|
JavaScriptEncoder = new JavaScriptStringEncoder(),
|
||||||
Logger = logger,
|
Logger = logger,
|
||||||
HostingEnvironment = hostingEnvironment,
|
HostingEnvironment = hostingEnvironment,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
|
|
@ -441,10 +442,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var viewContext = MakeViewContext();
|
var viewContext = MakeViewContext();
|
||||||
|
|
||||||
var output = MakeTagHelperOutput("src",
|
var output = MakeTagHelperOutput("src",
|
||||||
attributes: new Dictionary<string, string>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["data-extra"] = "something",
|
["data-extra"] = "something",
|
||||||
["src"] = "/blank.js",
|
|
||||||
["data-more"] = "else",
|
["data-more"] = "else",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -454,11 +454,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var helper = new ScriptTagHelper
|
var helper = new ScriptTagHelper
|
||||||
{
|
{
|
||||||
HtmlEncoder = new HtmlEncoder(),
|
HtmlEncoder = new HtmlEncoder(),
|
||||||
|
JavaScriptEncoder = new JavaScriptStringEncoder(),
|
||||||
Logger = logger,
|
Logger = logger,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
HostingEnvironment = hostingEnvironment,
|
HostingEnvironment = hostingEnvironment,
|
||||||
FallbackSrc = "~/blank.js",
|
FallbackSrc = "~/blank.js",
|
||||||
FallbackTestExpression = "http://www.example.com/blank.js",
|
FallbackTestExpression = "http://www.example.com/blank.js",
|
||||||
|
Src = "/blank.js",
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -467,7 +469,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.StartsWith(
|
Assert.StartsWith(
|
||||||
"<script data-extra=\"something\" src=\"/blank.js\" data-more=\"else\"", output.Content.GetContent());
|
"<script data-extra=\"something\" data-more=\"else\" src=\"/blank.js\"", output.Content.GetContent());
|
||||||
Assert.Empty(logger.Logged);
|
Assert.Empty(logger.Logged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -481,10 +483,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
["src"] = "/js/site.js",
|
["src"] = "/js/site.js",
|
||||||
["asp-src-include"] = "**/*.js"
|
["asp-src-include"] = "**/*.js"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, string>
|
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
|
||||||
{
|
|
||||||
["src"] = "/js/site.js"
|
|
||||||
});
|
|
||||||
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
var viewContext = MakeViewContext();
|
var viewContext = MakeViewContext();
|
||||||
|
|
@ -497,6 +496,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Logger = logger.Object,
|
Logger = logger.Object,
|
||||||
HostingEnvironment = hostingEnvironment,
|
HostingEnvironment = hostingEnvironment,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
|
Src = "/js/site.js",
|
||||||
SrcInclude = "**/*.js",
|
SrcInclude = "**/*.js",
|
||||||
HtmlEncoder = new HtmlEncoder(),
|
HtmlEncoder = new HtmlEncoder(),
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
|
|
@ -519,10 +519,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
["src"] = "/js/site.js",
|
["src"] = "/js/site.js",
|
||||||
["asp-src-include"] = "**/*.js"
|
["asp-src-include"] = "**/*.js"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, string>
|
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
|
||||||
{
|
|
||||||
["src"] = "/js/site.js"
|
|
||||||
});
|
|
||||||
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
var viewContext = MakeViewContext();
|
var viewContext = MakeViewContext();
|
||||||
|
|
@ -535,8 +532,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Logger = logger.Object,
|
Logger = logger.Object,
|
||||||
HostingEnvironment = hostingEnvironment,
|
HostingEnvironment = hostingEnvironment,
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
|
Src = "/js/site.js",
|
||||||
SrcInclude = "**/*.js",
|
SrcInclude = "**/*.js",
|
||||||
HtmlEncoder = new TestHtmlEncoder(),
|
HtmlEncoder = new TestHtmlEncoder(),
|
||||||
|
JavaScriptEncoder = new TestJavaScriptEncoder(),
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -558,10 +557,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
["src"] = "/js/site.js",
|
["src"] = "/js/site.js",
|
||||||
["asp-file-version"] = "true"
|
["asp-file-version"] = "true"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, string>
|
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
|
||||||
{
|
|
||||||
["src"] = "/js/site.js"
|
|
||||||
});
|
|
||||||
|
|
||||||
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
|
|
@ -574,6 +570,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
FileVersion = true,
|
FileVersion = true,
|
||||||
HtmlEncoder = new TestHtmlEncoder(),
|
HtmlEncoder = new TestHtmlEncoder(),
|
||||||
|
JavaScriptEncoder = new TestJavaScriptEncoder(),
|
||||||
|
Src = "/js/site.js",
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -596,10 +594,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
["src"] = "/bar/js/site.js",
|
["src"] = "/bar/js/site.js",
|
||||||
["asp-file-version"] = "true"
|
["asp-file-version"] = "true"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, string>
|
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
|
||||||
{
|
|
||||||
["src"] = "/bar/js/site.js"
|
|
||||||
});
|
|
||||||
|
|
||||||
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
|
|
@ -612,6 +607,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
ViewContext = viewContext,
|
ViewContext = viewContext,
|
||||||
FileVersion = true,
|
FileVersion = true,
|
||||||
HtmlEncoder = new TestHtmlEncoder(),
|
HtmlEncoder = new TestHtmlEncoder(),
|
||||||
|
JavaScriptEncoder = new TestJavaScriptEncoder(),
|
||||||
|
Src = "/bar/js/site.js",
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -636,10 +633,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
["asp-fallback-test"] = "isavailable()",
|
["asp-fallback-test"] = "isavailable()",
|
||||||
["asp-file-version"] = "true"
|
["asp-file-version"] = "true"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, string>
|
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
|
||||||
{
|
|
||||||
["src"] = "/js/site.js"
|
|
||||||
});
|
|
||||||
|
|
||||||
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
|
|
@ -654,6 +648,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
FallbackTestExpression = "isavailable()",
|
FallbackTestExpression = "isavailable()",
|
||||||
FileVersion = true,
|
FileVersion = true,
|
||||||
HtmlEncoder = new TestHtmlEncoder(),
|
HtmlEncoder = new TestHtmlEncoder(),
|
||||||
|
JavaScriptEncoder = new TestJavaScriptEncoder(),
|
||||||
|
Src = "/js/site.js",
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -663,7 +659,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
"<script src=\"HtmlEncode[[/js/site.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\">" +
|
"<script src=\"HtmlEncode[[/js/site.js?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\">" +
|
||||||
"</script>\r\n<script>(isavailable()||document.write(\"<script src=\\\"HtmlEncode[[fallback.js" +
|
"</script>\r\n<script>(isavailable()||document.write(\"<script src=\\\"JavaScriptEncode[[fallback.js" +
|
||||||
"?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\\\"><\\/script>\"));</script>",
|
"?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk]]\\\"><\\/script>\"));</script>",
|
||||||
output.Content.GetContent());
|
output.Content.GetContent());
|
||||||
}
|
}
|
||||||
|
|
@ -679,10 +675,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
["asp-src-include"] = "*.js",
|
["asp-src-include"] = "*.js",
|
||||||
["asp-file-version"] = "true"
|
["asp-file-version"] = "true"
|
||||||
});
|
});
|
||||||
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, string>
|
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, object>());
|
||||||
{
|
|
||||||
["src"] = "/js/site.js"
|
|
||||||
});
|
|
||||||
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
var logger = new Mock<ILogger<ScriptTagHelper>>();
|
||||||
var hostingEnvironment = MakeHostingEnvironment();
|
var hostingEnvironment = MakeHostingEnvironment();
|
||||||
var viewContext = MakeViewContext();
|
var viewContext = MakeViewContext();
|
||||||
|
|
@ -698,6 +691,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
SrcInclude = "*.js",
|
SrcInclude = "*.js",
|
||||||
FileVersion = true,
|
FileVersion = true,
|
||||||
HtmlEncoder = new TestHtmlEncoder(),
|
HtmlEncoder = new TestHtmlEncoder(),
|
||||||
|
JavaScriptEncoder = new TestJavaScriptEncoder(),
|
||||||
|
Src = "/js/site.js",
|
||||||
Cache = MakeCache(),
|
Cache = MakeCache(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -748,9 +743,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
return viewContext;
|
return viewContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TagHelperOutput MakeTagHelperOutput(string tagName, IDictionary<string, string> attributes = null)
|
private TagHelperOutput MakeTagHelperOutput(string tagName, IDictionary<string, object> attributes = null)
|
||||||
{
|
{
|
||||||
attributes = attributes ?? new Dictionary<string, string>();
|
attributes = attributes ?? new Dictionary<string, object>();
|
||||||
|
|
||||||
return new TagHelperOutput(tagName, attributes);
|
return new TagHelperOutput(tagName, attributes);
|
||||||
}
|
}
|
||||||
|
|
@ -817,27 +812,5 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
return cache.Object;
|
return cache.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestHtmlEncoder : IHtmlEncoder
|
|
||||||
{
|
|
||||||
public string HtmlEncode(string value)
|
|
||||||
{
|
|
||||||
return "HtmlEncode[[" + value + "]]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HtmlEncode(string value, int startIndex, int charCount, TextWriter output)
|
|
||||||
{
|
|
||||||
output.Write("HtmlEncode[[");
|
|
||||||
output.Write(value.Substring(startIndex, charCount));
|
|
||||||
output.Write("]]");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HtmlEncode(char[] value, int startIndex, int charCount, TextWriter output)
|
|
||||||
{
|
|
||||||
output.Write("HtmlEncode[[");
|
|
||||||
output.Write(value, startIndex, charCount);
|
|
||||||
output.Write("]]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,7 +9,6 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.Framework.WebEncoders;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -172,13 +171,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string ignored)
|
string ignored)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
var originalPostContent = "original content";
|
var originalPostContent = "original content";
|
||||||
|
|
||||||
var expectedAttributes = new Dictionary<string, string>(originalAttributes)
|
var expectedAttributes = new Dictionary<string, object>(originalAttributes)
|
||||||
{
|
{
|
||||||
{ "id", nameAndId.Id },
|
{ "id", nameAndId.Id },
|
||||||
{ "name", nameAndId.Name },
|
{ "name", nameAndId.Name },
|
||||||
|
|
@ -258,13 +257,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string expectedOptions)
|
string expectedOptions)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
var originalPostContent = "original content";
|
var originalPostContent = "original content";
|
||||||
|
|
||||||
var expectedAttributes = new Dictionary<string, string>(originalAttributes)
|
var expectedAttributes = new Dictionary<string, object>(originalAttributes)
|
||||||
{
|
{
|
||||||
{ "id", nameAndId.Id },
|
{ "id", nameAndId.Id },
|
||||||
{ "name", nameAndId.Name },
|
{ "name", nameAndId.Name },
|
||||||
|
|
@ -359,13 +358,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string expectedOptions)
|
string expectedOptions)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
var originalPostContent = "original content";
|
var originalPostContent = "original content";
|
||||||
|
|
||||||
var expectedAttributes = new Dictionary<string, string>(originalAttributes)
|
var expectedAttributes = new Dictionary<string, object>(originalAttributes)
|
||||||
{
|
{
|
||||||
{ "id", nameAndId.Id },
|
{ "id", nameAndId.Id },
|
||||||
{ "name", nameAndId.Name },
|
{ "name", nameAndId.Name },
|
||||||
|
|
@ -465,7 +464,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Provided for completeness. Select tag helper does not confirm AllAttributes set is consistent.
|
// Provided for completeness. Select tag helper does not confirm AllAttributes set is consistent.
|
||||||
{ attributeName, attributeValue },
|
{ attributeName, attributeValue },
|
||||||
};
|
};
|
||||||
var originalAttributes = new Dictionary<string, string>
|
var originalAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ attributeName, attributeValue },
|
{ attributeName, attributeValue },
|
||||||
};
|
};
|
||||||
|
|
@ -547,7 +546,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var contextAttributes = new Dictionary<string, object>();
|
var contextAttributes = new Dictionary<string, object>();
|
||||||
var originalAttributes = new Dictionary<string, string>();
|
var originalAttributes = new Dictionary<string, object>();
|
||||||
var propertyName = "Property1";
|
var propertyName = "Property1";
|
||||||
var tagName = "select";
|
var tagName = "select";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
var tagHelperContext = new TagHelperContext(
|
var tagHelperContext = new TagHelperContext(
|
||||||
allAttributes: new Dictionary<string, object>(StringComparer.Ordinal)
|
allAttributes: new Dictionary<string, object>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
tagHelperContent.Append("Something");
|
tagHelperContent.Append("Something");
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
||||||
});
|
});
|
||||||
var expectedAttribute = new KeyValuePair<string, string>(attributeName, attributeValue);
|
var expectedAttribute = new KeyValuePair<string, object>(attributeName, attributeValue);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
tagHelperOutput.CopyHtmlAttribute("hello", tagHelperContext);
|
tagHelperOutput.CopyHtmlAttribute("hello", tagHelperContext);
|
||||||
|
|
@ -52,11 +52,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var attributeName = "hello";
|
var attributeName = "hello";
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
attributes: new Dictionary<string, string>()
|
attributes: new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
{ attributeName, "world2" }
|
{ attributeName, "world2" }
|
||||||
});
|
});
|
||||||
var expectedAttribute = new KeyValuePair<string, string>(attributeName, "world2");
|
var expectedAttribute = new KeyValuePair<string, object>(attributeName, "world2");
|
||||||
var tagHelperContext = new TagHelperContext(
|
var tagHelperContext = new TagHelperContext(
|
||||||
allAttributes: new Dictionary<string, object>(StringComparer.Ordinal)
|
allAttributes: new Dictionary<string, object>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
|
|
@ -85,12 +85,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
attributes: new Dictionary<string, string>()
|
attributes: new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
{ "route-Hello", "World" },
|
{ "route-Hello", "World" },
|
||||||
{ "Route-I", "Am" }
|
{ "Route-I", "Am" }
|
||||||
});
|
});
|
||||||
var expectedAttribute = new KeyValuePair<string, string>("type", "btn");
|
var expectedAttribute = new KeyValuePair<string, object>("type", "btn");
|
||||||
tagHelperOutput.Attributes.Add(expectedAttribute);
|
tagHelperOutput.Attributes.Add(expectedAttribute);
|
||||||
var attributes = tagHelperOutput.FindPrefixedAttributes("route-");
|
var attributes = tagHelperOutput.FindPrefixedAttributes("route-");
|
||||||
|
|
||||||
|
|
@ -108,7 +108,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
attributes: new Dictionary<string, string>()
|
attributes: new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
{ "routeHello", "World" },
|
{ "routeHello", "World" },
|
||||||
{ "Routee-I", "Am" }
|
{ "Routee-I", "Am" }
|
||||||
|
|
@ -131,8 +131,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
var expectedAttribute = new KeyValuePair<string, string>("type", "btn");
|
var expectedAttribute = new KeyValuePair<string, object>("type", "btn");
|
||||||
tagHelperOutput.Attributes.Add(expectedAttribute);
|
tagHelperOutput.Attributes.Add(expectedAttribute);
|
||||||
|
|
||||||
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
||||||
|
|
@ -152,13 +152,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
tagHelperOutput.Attributes.Add("class", "Hello");
|
tagHelperOutput.Attributes.Add("class", "Hello");
|
||||||
|
|
||||||
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
||||||
tagBuilder.Attributes.Add("class", "btn");
|
tagBuilder.Attributes.Add("class", "btn");
|
||||||
|
|
||||||
var expectedAttribute = new KeyValuePair<string, string>("class", "Hello btn");
|
var expectedAttribute = new KeyValuePair<string, object>("class", "Hello btn");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
tagHelperOutput.MergeAttributes(tagBuilder);
|
tagHelperOutput.MergeAttributes(tagBuilder);
|
||||||
|
|
@ -178,7 +178,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
tagHelperOutput.Attributes.Add(originalName, "Hello");
|
tagHelperOutput.Attributes.Add(originalName, "Hello");
|
||||||
|
|
||||||
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
||||||
|
|
@ -189,7 +189,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var attribute = Assert.Single(tagHelperOutput.Attributes);
|
var attribute = Assert.Single(tagHelperOutput.Attributes);
|
||||||
Assert.Equal(new KeyValuePair<string, string>(originalName, "Hello btn"), attribute);
|
Assert.Equal(new KeyValuePair<string, object>(originalName, "Hello btn"), attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -198,11 +198,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
|
|
||||||
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
||||||
var expectedAttribute = new KeyValuePair<string, string>("visible", "val < 3");
|
var expectedAttribute = new KeyValuePair<string, object>("visible", "val < 3");
|
||||||
tagBuilder.Attributes.Add(expectedAttribute);
|
tagBuilder.Attributes.Add("visible", "val < 3");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
tagHelperOutput.MergeAttributes(tagBuilder);
|
tagHelperOutput.MergeAttributes(tagBuilder);
|
||||||
|
|
@ -218,13 +218,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
|
|
||||||
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
||||||
var expectedAttribute1 = new KeyValuePair<string, string>("class", "btn");
|
var expectedAttribute1 = new KeyValuePair<string, object>("class", "btn");
|
||||||
var expectedAttribute2 = new KeyValuePair<string, string>("class2", "btn");
|
var expectedAttribute2 = new KeyValuePair<string, object>("class2", "btn");
|
||||||
tagBuilder.Attributes.Add(expectedAttribute1);
|
tagBuilder.Attributes.Add("class", "btn");
|
||||||
tagBuilder.Attributes.Add(expectedAttribute2);
|
tagBuilder.Attributes.Add("class2", "btn");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
tagHelperOutput.MergeAttributes(tagBuilder);
|
tagHelperOutput.MergeAttributes(tagBuilder);
|
||||||
|
|
@ -243,8 +243,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
var expectedAttribute = new KeyValuePair<string, string>("class", "btn");
|
var expectedAttribute = new KeyValuePair<string, object>("class", "btn");
|
||||||
tagHelperOutput.Attributes.Add(expectedAttribute);
|
tagHelperOutput.Attributes.Add(expectedAttribute);
|
||||||
|
|
||||||
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
||||||
|
|
@ -263,13 +263,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = new TagHelperOutput(
|
||||||
"p",
|
"p",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
var expectedOutputAttribute = new KeyValuePair<string, string>("class", "btn");
|
var expectedOutputAttribute = new KeyValuePair<string, object>("class", "btn");
|
||||||
tagHelperOutput.Attributes.Add(expectedOutputAttribute);
|
tagHelperOutput.Attributes.Add(expectedOutputAttribute);
|
||||||
|
|
||||||
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
var tagBuilder = new TagBuilder("p", new HtmlEncoder());
|
||||||
var expectedBuilderAttribute = new KeyValuePair<string, string>("for", "hello");
|
var expectedBuilderAttribute = new KeyValuePair<string, object>("for", "hello");
|
||||||
tagBuilder.Attributes.Add(expectedBuilderAttribute);
|
tagBuilder.Attributes.Add("for", "hello");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
tagHelperOutput.MergeAttributes(tagBuilder);
|
tagHelperOutput.MergeAttributes(tagBuilder);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Microsoft.Framework.WebEncoders;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
|
|
@ -89,7 +88,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
string expectedContent)
|
string expectedContent)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedAttributes = new Dictionary<string, string>
|
var expectedAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
{ "id", nameAndId.Id },
|
{ "id", nameAndId.Id },
|
||||||
|
|
@ -123,7 +122,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
tagHelperContent.SetContent("Something");
|
tagHelperContent.SetContent("Something");
|
||||||
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
return Task.FromResult<TagHelperContent>(tagHelperContent);
|
||||||
});
|
});
|
||||||
var htmlAttributes = new Dictionary<string, string>
|
var htmlAttributes = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
expectedTagName,
|
expectedTagName,
|
||||||
attributes: new Dictionary<string, string>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "id", "myvalidationmessage" }
|
{ "id", "myvalidationmessage" }
|
||||||
});
|
});
|
||||||
|
|
@ -105,7 +105,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"span",
|
"span",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
output.PreContent.SetContent(expectedPreContent);
|
output.PreContent.SetContent(expectedPreContent);
|
||||||
output.Content.SetContent(expectedContent);
|
output.Content.SetContent(expectedContent);
|
||||||
output.PostContent.SetContent(expectedPostContent);
|
output.PostContent.SetContent(expectedPostContent);
|
||||||
|
|
@ -145,7 +145,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
};
|
};
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"span",
|
"span",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
output.Content.SetContent(outputContent);
|
output.Content.SetContent(outputContent);
|
||||||
|
|
||||||
var context = new TagHelperContext(
|
var context = new TagHelperContext(
|
||||||
|
|
@ -204,7 +204,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
};
|
};
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"span",
|
"span",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
|
|
||||||
var context = new TagHelperContext(
|
var context = new TagHelperContext(
|
||||||
allAttributes: new Dictionary<string, object>(),
|
allAttributes: new Dictionary<string, object>(),
|
||||||
|
|
@ -259,7 +259,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var expectedPostContent = "original post-content";
|
var expectedPostContent = "original post-content";
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"span",
|
"span",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
output.PreContent.SetContent(expectedPreContent);
|
output.PreContent.SetContent(expectedPreContent);
|
||||||
output.Content.SetContent(expectedContent);
|
output.Content.SetContent(expectedContent);
|
||||||
output.PostContent.SetContent(expectedPostContent);
|
output.PostContent.SetContent(expectedPostContent);
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
});
|
});
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
expectedTagName,
|
expectedTagName,
|
||||||
attributes: new Dictionary<string, string>
|
attributes: new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "class", "form-control" }
|
{ "class", "form-control" }
|
||||||
});
|
});
|
||||||
|
|
@ -102,7 +102,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var expectedPostContent = "original post-content";
|
var expectedPostContent = "original post-content";
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"div",
|
"div",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
output.PreContent.SetContent(expectedPreContent);
|
output.PreContent.SetContent(expectedPreContent);
|
||||||
output.Content.SetContent(expectedContent);
|
output.Content.SetContent(expectedContent);
|
||||||
output.PostContent.SetContent(expectedPostContent);
|
output.PostContent.SetContent(expectedPostContent);
|
||||||
|
|
@ -144,7 +144,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var expectedContent = "original content";
|
var expectedContent = "original content";
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"div",
|
"div",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
output.PreContent.SetContent(expectedPreContent);
|
output.PreContent.SetContent(expectedPreContent);
|
||||||
output.Content.SetContent(expectedContent);
|
output.Content.SetContent(expectedContent);
|
||||||
output.PostContent.SetContent("Content of validation summary");
|
output.PostContent.SetContent("Content of validation summary");
|
||||||
|
|
@ -201,7 +201,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var expectedPostContent = "original post-content";
|
var expectedPostContent = "original post-content";
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"div",
|
"div",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
output.PreContent.SetContent(expectedPreContent);
|
output.PreContent.SetContent(expectedPreContent);
|
||||||
output.Content.SetContent(expectedContent);
|
output.Content.SetContent(expectedContent);
|
||||||
output.PostContent.SetContent(expectedPostContent);
|
output.PostContent.SetContent(expectedPostContent);
|
||||||
|
|
@ -236,7 +236,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var expectedContent = "original content";
|
var expectedContent = "original content";
|
||||||
var output = new TagHelperOutput(
|
var output = new TagHelperOutput(
|
||||||
"div",
|
"div",
|
||||||
attributes: new Dictionary<string, string>());
|
attributes: new Dictionary<string, object>());
|
||||||
output.PreContent.SetContent(expectedPreContent);
|
output.PreContent.SetContent(expectedPreContent);
|
||||||
output.Content.SetContent(expectedContent);
|
output.Content.SetContent(expectedContent);
|
||||||
output.PostContent.SetContent("Content of validation message");
|
output.PostContent.SetContent("Content of validation message");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Microsoft.Framework.WebEncoders
|
||||||
|
{
|
||||||
|
internal class TestHtmlEncoder : IHtmlEncoder
|
||||||
|
{
|
||||||
|
public string HtmlEncode(string value)
|
||||||
|
{
|
||||||
|
return $"HtmlEncode[[{ value }]]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HtmlEncode(string value, int startIndex, int charCount, TextWriter output)
|
||||||
|
{
|
||||||
|
output.Write($"HtmlEncode[[{ value.Substring(startIndex, charCount) }]]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HtmlEncode(char[] value, int startIndex, int charCount, TextWriter output)
|
||||||
|
{
|
||||||
|
output.Write("HtmlEncode[[");
|
||||||
|
output.Write(value, startIndex, charCount);
|
||||||
|
output.Write("]]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Microsoft.Framework.WebEncoders
|
||||||
|
{
|
||||||
|
internal class TestJavaScriptEncoder : IJavaScriptStringEncoder
|
||||||
|
{
|
||||||
|
public string JavaScriptStringEncode(string value)
|
||||||
|
{
|
||||||
|
return $"JavaScriptEncode[[{ value }]]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void JavaScriptStringEncode(string value, int startIndex, int charCount, TextWriter output)
|
||||||
|
{
|
||||||
|
output.Write($"JavaScriptEncode[[{ value.Substring(startIndex, charCount) }]]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void JavaScriptStringEncode(char[] value, int startIndex, int charCount, TextWriter output)
|
||||||
|
{
|
||||||
|
output.Write("JavaScriptEncode[[");
|
||||||
|
output.Write(value, startIndex, charCount);
|
||||||
|
output.Write("]]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Microsoft.Framework.WebEncoders
|
||||||
|
{
|
||||||
|
internal class TestUrlEncoder : IUrlEncoder
|
||||||
|
{
|
||||||
|
public string UrlEncode(string value)
|
||||||
|
{
|
||||||
|
return $"UrlEncode[[{ value }]]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UrlEncode(string value, int startIndex, int charCount, TextWriter output)
|
||||||
|
{
|
||||||
|
output.Write($"UrlEncode[[{ value.Substring(startIndex, charCount) }]]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UrlEncode(char[] value, int startIndex, int charCount, TextWriter output)
|
||||||
|
{
|
||||||
|
output.Write("UrlEncode[[");
|
||||||
|
output.Write(value, startIndex, charCount);
|
||||||
|
output.Write("]]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,10 +7,10 @@
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
<a asp-controller="Product">Product Index</a>
|
<a asp-controller="Product" title="<the title>">Product Index</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a asp-controller="Product" asp-action="List">Product List</a>
|
<a asp-controller="Product" asp-action="List" title='"the" title'>Product List</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a id="MvcTagHelperTestIndex">MvcTagHelperTest Index</a>
|
<a id="MvcTagHelperTestIndex">MvcTagHelperTest Index</a>
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,13 @@
|
||||||
<title>Link</title>
|
<title>Link</title>
|
||||||
|
|
||||||
<!-- Plain link tag -->
|
<!-- Plain link tag -->
|
||||||
<link href="~/site.css" rel="stylesheet" />
|
<link href="~/site.css" rel="stylesheet" title="<the title>" />
|
||||||
|
|
||||||
<!-- Globbed link tag with existing file -->
|
<!-- Globbed link tag with existing file -->
|
||||||
<link asp-href-include="**/site.css" rel="stylesheet" />
|
<link asp-href-include="**/site.css" rel="stylesheet" title="<the title>" />
|
||||||
|
|
||||||
<!-- Globbed link tag with existing file and exclude -->
|
<!-- Globbed link tag with existing file and exclude -->
|
||||||
<link asp-href-include="**/*.css" asp-href-exclude="**/site3*.css" rel="stylesheet" />
|
<link asp-href-include="**/*.css" asp-href-exclude="**/site3*.css" rel="stylesheet" title='"the" title' />
|
||||||
|
|
||||||
<!-- Globbed link tag missing include -->
|
<!-- Globbed link tag missing include -->
|
||||||
<link asp-href-exclude="**/site2.css" rel="stylesheet" />
|
<link asp-href-exclude="**/site2.css" rel="stylesheet" />
|
||||||
|
|
@ -37,8 +37,8 @@
|
||||||
<link href="~/site.css" asp-href-include="**/site.css" rel="stylesheet" />
|
<link href="~/site.css" asp-href-include="**/site.css" rel="stylesheet" />
|
||||||
|
|
||||||
<!-- Fallback to static href -->
|
<!-- Fallback to static href -->
|
||||||
<link href="~/site.min.css" rel="stylesheet" data-extra="test"
|
<link href="~/site.min.css?a=b&c=d" rel="stylesheet" data-extra="test" title='"the" title'
|
||||||
asp-fallback-href="~/site.css"
|
asp-fallback-href="~/site.css?a=b&c=d"
|
||||||
asp-fallback-test-class="hidden"
|
asp-fallback-test-class="hidden"
|
||||||
asp-fallback-test-property="visibility"
|
asp-fallback-test-property="visibility"
|
||||||
asp-fallback-test-value="hidden" />
|
asp-fallback-test-value="hidden" />
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,15 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>Script tag helper test</h2>
|
<h2>Script tag helper test</h2>
|
||||||
<script src="~/site.js" data-foo="foo-data1">
|
<script src="~/site.js" data-foo="foo-data1" title="<the title>">
|
||||||
// Regular script with comment in body, and extra properties.
|
// Regular script with comment in body, and extra properties.
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="~/blank.js" asp-fallback-src="~/site.js" asp-fallback-test="false" data-foo="foo-data2">
|
<script src="~/blank.js?a=b&c=d" asp-fallback-src="~/site.js?a=b&c=d" asp-fallback-test="false" 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 src="~/blank.js" asp-fallback-src-include="**/site.js" asp-fallback-test="false">
|
<script src="~/blank.js" asp-fallback-src-include="**/site.js" asp-fallback-test="false" title='"the" title'>
|
||||||
// Fallback to globbed src
|
// Fallback to globbed src
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ namespace TagHelpersWebSite.TagHelpers
|
||||||
|
|
||||||
public bool? MakePretty { get; set; }
|
public bool? MakePretty { get; set; }
|
||||||
|
|
||||||
|
public string Style { get; set; }
|
||||||
|
|
||||||
[Activate]
|
[Activate]
|
||||||
public ViewContext ViewContext { get; set; }
|
public ViewContext ViewContext { get; set; }
|
||||||
|
|
||||||
|
|
@ -40,9 +42,8 @@ namespace TagHelpersWebSite.TagHelpers
|
||||||
|
|
||||||
if (PrettyTagStyles.TryGetValue(output.TagName, out prettyStyle))
|
if (PrettyTagStyles.TryGetValue(output.TagName, out prettyStyle))
|
||||||
{
|
{
|
||||||
var style = string.Empty;
|
var style = Style ?? string.Empty;
|
||||||
|
if (!string.IsNullOrEmpty(style))
|
||||||
if (output.Attributes.TryGetValue("style", out style))
|
|
||||||
{
|
{
|
||||||
style += ";";
|
style += ";";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue