public async Task ProcessAsync_Sha512SriNotCached_CachesSriAndReturnsIt() { var expectedSri = "sha512-NhX4DJ0pPtdAJof5SyLVjlKbjMeRb4+sf933+9WvTPd309eVp6AKFr9+fz+5Vh7puq5IDan+ehh2nnGIawPzFQ=="; this.tagHelper.Source = "/foo.js"; var attributes = new TagHelperAttributeList { { "src", "/foo.js" } }; var context = new TagHelperContext(attributes, new Dictionary <object, object>(), Guid.NewGuid().ToString()); var output = new TagHelperOutput("script", attributes, (x, y) => throw new ArgumentException()); this.distributedCacheMock .Setup(x => x.GetAsync("SRI:/foo.js", CancellationToken.None)) .ReturnsAsync((byte[])null); this.webHostEnvironmentMock.SetupGet(x => x.ContentRootPath).Returns(@"C:\Foo\wwwroot"); this.urlHelperMock.Setup(x => x.Content("/foo.js")).Returns(@"C:\Foo\wwwroot\foo.js"); this.distributedCacheMock .Setup(x => x.SetAsync( "SRI:/foo.js", It.Is <byte[]>(y => string.Equals(Encoding.UTF8.GetString(y), expectedSri, StringComparison.Ordinal)), It.IsAny <DistributedCacheEntryOptions>(), CancellationToken.None)) .Returns(Task.CompletedTask); await this.tagHelper.ProcessAsync(context, output); Assert.True(attributes.ContainsName("crossorigin")); Assert.Equal("anonymous", attributes["crossorigin"].Value); Assert.True(attributes.ContainsName("integrity")); var htmlString = Assert.IsType <HtmlString>(attributes["integrity"].Value); Assert.Equal(expectedSri, htmlString.Value); }
protected virtual TagHelperAttributeList GetInputAttributes(TagHelperContext context, TagHelperOutput output) { var groupPrefix = "group-"; var tagHelperAttributes = output.Attributes.Where(a => !a.Name.StartsWith(groupPrefix)).ToList(); var attrList = new TagHelperAttributeList(); foreach (var tagHelperAttribute in tagHelperAttributes) { attrList.Add(tagHelperAttribute); } if (!TagHelper.InputTypeName.IsNullOrEmpty() && !attrList.ContainsName("type")) { attrList.Add("type", TagHelper.InputTypeName); } if (!TagHelper.Name.IsNullOrEmpty() && !attrList.ContainsName("name")) { attrList.Add("name", TagHelper.Name); } if (!TagHelper.Value.IsNullOrEmpty() && !attrList.ContainsName("value")) { attrList.Add("value", TagHelper.Value); } return(attrList); }
private void BuildFallbackBlock(TagHelperAttributeList attributes, DefaultTagHelperContent builder) { EnsureGlobbingUrlBuilder(); var fallbackSrcs = GlobbingUrlBuilder.BuildUrlList(FallbackSrc, FallbackSrcInclude, FallbackSrcExclude); if (fallbackSrcs.Any()) { // Build the <script> tag that checks the test method and if it fails, renders the extra script. builder.Append(Environment.NewLine) .Append("<script>(") .Append(FallbackTestExpression) .Append("||document.write(\""); // May have no "src" attribute in the dictionary e.g. if Src and SrcInclude were not bound. if (!attributes.ContainsName(SrcAttributeName)) { // Need this entry to place each fallback source. attributes.Add(new TagHelperAttribute(SrcAttributeName, value: null)); } foreach (var src in fallbackSrcs) { // Fallback "src" values come from bound attributes and globbing. Must always be non-null. Debug.Assert(src != null); builder.Append("<script"); foreach (var attribute in attributes) { if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase)) { var encodedKey = JavaScriptEncoder.JavaScriptStringEncode(attribute.Name); var attributeValue = attribute.Value.ToString(); var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue); AppendAttribute(builder, encodedKey, encodedValue, escapeQuotes: true); } else { // Ignore attribute.Value; use src instead. var attributeValue = src; if (AppendVersion == true) { attributeValue = _fileVersionProvider.AddFileVersionToPath(attributeValue); } // attribute.Key ("src") does not need to be JavaScript-encoded. var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue); AppendAttribute(builder, attribute.Name, encodedValue, escapeQuotes: true); } } builder.Append("><\\/script>"); } builder.Append("\"));</script>"); } }
/// <summary> /// Sets an attribute value by name to 'value.ToString()'. If 'replace' is false, the attribute is only set if not /// already set. If 'value' is null, the entry is removed from the list instead. /// </summary> /// <exception cref="ArgumentException"> Thrown if 'name' is null or empty. </exception> /// <param name="list"> The TagHelperAttributeList to merge an attribute value with. </param> /// <param name="name"> The key to set a value for. </param> /// <param name="value"> /// The value to set for the specified key, which will be converted to a string first. If null, any existing entry is /// removed instead (if 'replace' is true). /// </param> /// <param name="replace"> /// (Optional) If true (the default) adds a new entry or replaces an existing entry, otherwise the request is ignored. /// If this is false, nothing is removed, and any merge requests with existing keys will be ignored. /// </param> /// <param name="removeOnEmptyOrWhitespace"> /// (Optional) If true (default) any empty or whitespace-only values will remove the attribute. This is in addition to /// 'null', which always removes values. /// </param> /// <param name="replaceIfValueNotEmpty"> /// (Optional) If true, any existing entry is only replaced if the given value is not empty or whitespace only. Default /// is false. This setting has no affect if the 'replace' parameter is false. /// </param> public static void MergeAttribute(this TagHelperAttributeList list, string name, object value, bool replace = true, bool removeOnEmptyOrWhitespace = true, bool replaceIfValueNotEmpty = false) { if (name == null) { throw new ArgumentException("Value cannot be null.", nameof(name)); } else if (name is string && string.IsNullOrEmpty((string)(object)name)) { throw new ArgumentException("Value cannot be null or empty.", nameof(name)); } if (replace || value != null && !list.ContainsName(name)) { var valueStr = value?.ToString().Trim(); var isEmpty = string.IsNullOrWhiteSpace(valueStr); if (valueStr == null || removeOnEmptyOrWhitespace && isEmpty) { list.RemoveAll(name); } else if (!replaceIfValueNotEmpty || !isEmpty) { list.Add(name, valueStr); } } }
public static void AddIfNotContains(this TagHelperAttributeList attributes, string name, object value) { if (!attributes.ContainsName("method")) { attributes.Add("method", "post"); } }
public static void AddIfNotContains(this TagHelperAttributeList attributes, string name, object value) { if (!attributes.ContainsName(name)) { attributes.Add(name, value); } }
public static void AddClass(this TagHelperAttributeList attrs, string append_class) { if (attrs.ContainsName("class")) { append_class += " " + attrs["class"].Value; } attrs.SetAttribute("class", append_class); }
/// <summary> /// Adds a <see cref="TagHelperAttribute"/> with <paramref name="name"/> and the value of <paramref name="valueAccessor"/> to the end of the collection, /// but only if the attribute does not exist. /// </summary> /// <param name="name"> /// The <see cref="TagHelperAttribute.Name"/> of the <see cref="TagHelperAttribute"/> to set. /// </param> /// <param name="valueAccessor"> /// The <see cref="TagHelperAttribute.Value"/> to set. /// </param> /// <remarks><paramref name="name"/> is compared case-insensitively.</remarks> public static void SetAttributeNoReplace(this TagHelperAttributeList attributes, string name, Func <object> valueAccessor) { Guard.NotEmpty(name, nameof(name)); if (!attributes.ContainsName(name)) { attributes.SetAttribute(name, valueAccessor()); } }
/// <summary> /// Adds a <see cref="TagHelperAttribute"/> with <paramref name="name"/> and <paramref name="value"/> to the end of the collection, /// but only if the attribute does not exist. /// </summary> /// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the <see cref="TagHelperAttribute"/> to set.</param> /// <param name="value">The <see cref="TagHelperAttribute.Value"/> to set.</param> /// <param name="ignoreNull"><c>false</c> = don't render attribute if value is null.</param> /// <remarks><paramref name="name"/> is compared case-insensitively.</remarks> public static void SetAttributeNoReplace(this TagHelperAttributeList attributes, string name, object value, bool ignoreNull = true) { Guard.NotEmpty(name, nameof(name)); if (!attributes.ContainsName(name) && (value != null || !ignoreNull)) { attributes.SetAttribute(name, value); } }
public static void AddOrIgnore(this TagHelperAttributeList attrs, string name, object value) { if (attrs.ContainsName(name)) { return; } attrs.Add(name, value); }
public static void MergeClassAttributeValue(this TagHelperAttributeList attributes, string newClassValue) { string classValue = newClassValue; if (attributes.ContainsName("class")) { classValue = $"{attributes["class"].Value} {classValue}"; } attributes.SetAttribute("class", classValue); }
public static void AddOrUpdate(this TagHelperAttributeList attributes, string name, object value) { if (attributes.ContainsName(name)) { attributes.SetAttribute(name, value); } else { attributes.Add(name, value); } }
public async Task ProcessAsync_Sha256And384And512SriNotCached_CachesSriAndReturnsIt() { var expectedSri = "sha256-GF+NsyJx/iX1Yab8k4suJkMG7DBO2lGAB9F2SCY4GWk= " + "sha384-NRn+WtLFlu/j4nam81G4/AsD24YXgkkNRfdZjr0Ktf1VIO0QLzjEpeyDTphmgDX8 " + "sha512-NhX4DJ0pPtdAJof5SyLVjlKbjMeRb4+sf933+9WvTPd309eVp6AKFr9+fz+5Vh7puq5IDan+ehh2nnGIawPzFQ=="; this.tagHelper.HashAlgorithms = SubresourceIntegrityHashAlgorithm.SHA256 | SubresourceIntegrityHashAlgorithm.SHA384 | SubresourceIntegrityHashAlgorithm.SHA512; this.tagHelper.Source = "/foo.js"; var attributes = new TagHelperAttributeList { { "src", "/foo.js" } }; var context = new TagHelperContext(attributes, new Dictionary <object, object>(), Guid.NewGuid().ToString()); var output = new TagHelperOutput("script", attributes, (x, y) => throw new ArgumentException()); this.distributedCacheMock .Setup(x => x.GetAsync("SRI:/foo.js", CancellationToken.None)) .ReturnsAsync((byte[])null); this.hostingEnvironmentMock.SetupGet(x => x.WebRootPath).Returns(@"C:\Foo\wwwroot"); this.urlHelperMock.Setup(x => x.Content("/foo.js")).Returns(@"C:\Foo\wwwroot\foo.js"); this.distributedCacheMock .Setup(x => x.SetAsync( "SRI:/foo.js", It.Is <byte[]>(y => string.Equals(Encoding.UTF8.GetString(y), expectedSri, StringComparison.Ordinal)), It.IsAny <DistributedCacheEntryOptions>(), CancellationToken.None)) .Returns(Task.CompletedTask); await this.tagHelper.ProcessAsync(context, output); Assert.True(attributes.ContainsName("crossorigin")); Assert.Equal("anonymous", attributes["crossorigin"].Value); Assert.True(attributes.ContainsName("integrity")); var htmlString = Assert.IsType <HtmlString>(attributes["integrity"].Value); Assert.Equal(expectedSri, htmlString.Value); }
/// <summary> /// Adds a <see cref="TagHelperAttribute"/> with <paramref name="name"/> and the value of <paramref name="valueAccessor"/> to the end of the collection, /// but only if the attribute does not exist. /// </summary> /// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the <see cref="TagHelperAttribute"/> to set.</param> /// <param name="valueAccessor">The <see cref="TagHelperAttribute.Value"/> to set.</param> /// <param name="ignoreNull"><c>false</c> = don't render attribute if value is null.</param> /// <remarks><paramref name="name"/> is compared case-insensitively.</remarks> public static void SetAttributeNoReplace(this TagHelperAttributeList attributes, string name, Func <object> valueAccessor, bool ignoreNull = true) { Guard.NotEmpty(name, nameof(name)); if (!attributes.ContainsName(name)) { var value = valueAccessor(); if (value != null || !ignoreNull) { attributes.SetAttribute(name, valueAccessor()); } } }
public void ContainsName_ReturnsExpectedResult( IEnumerable <TagHelperAttribute> initialAttributes, string nameToLookup, bool expected) { // Arrange var attributes = new TagHelperAttributeList(initialAttributes); // Act var contains = attributes.ContainsName(nameToLookup); // Assert Assert.Equal(expected, contains); }
public async Task ProcessAsync_SriAlreadyCached_ReturnsCachedSri() { this.tagHelper.Source = "/foo.js"; var attributes = new TagHelperAttributeList { { "src", "/foo.js" } }; var context = new TagHelperContext(attributes, new Dictionary <object, object>(), Guid.NewGuid().ToString()); var output = new TagHelperOutput("script", attributes, (x, y) => throw new ArgumentException()); this.distributedCacheMock .Setup(x => x.GetAsync("SRI:/foo.js", CancellationToken.None)) .ReturnsAsync(Encoding.UTF8.GetBytes("SRI Value")); await this.tagHelper.ProcessAsync(context, output); Assert.True(attributes.ContainsName("crossorigin")); Assert.Equal("anonymous", attributes["crossorigin"].Value); Assert.True(attributes.ContainsName("integrity")); var htmlString = Assert.IsType <HtmlString>(attributes["integrity"].Value); Assert.Equal("SRI Value", htmlString.Value); }
public static void AddOrUpdate(this TagHelperAttributeList attributes, string name, Func <object, object> valueFunc) { object value; if (attributes.ContainsName(name)) { value = valueFunc(attributes[name].Value); attributes.SetAttribute(name, value); } else { value = valueFunc(null); attributes.Add(name, value); } }
public static TagHelperContext CreateTagHelperContext(this IWebPackObject webPack, ReadOnlyTagHelperAttributeList allAttributes, IDictionary <object, object> items, string uniqueId) { var customAttributeList = new TagHelperAttributeList(); var attributes = webPack.Resolve(); foreach (KeyValuePair <string, object> entry in attributes) { customAttributeList.Add(new TagHelperAttribute(entry.Key, entry.Value)); } foreach (var item in allAttributes) { if (!customAttributeList.ContainsName(item.Name)) { customAttributeList.Add(new TagHelperAttribute(item.Name, item.Value)); } } return(new TagHelperContext(customAttributeList, new Dictionary <object, object>(), uniqueId)); }
private bool CanBeActive(TagHelperAttributeList attributes) => ActiveClass != null && attributes.ContainsName("href") && attributes["href"].Value != null;
private void BuildFallbackBlock(TagHelperAttributeList attributes, DefaultTagHelperContent builder) { EnsureGlobbingUrlBuilder(); var fallbackSrcs = GlobbingUrlBuilder.BuildUrlList(FallbackSrc, FallbackSrcInclude, FallbackSrcExclude); if (fallbackSrcs.Any()) { // Build the <script> tag that checks the test method and if it fails, renders the extra script. builder.AppendHtml(Environment.NewLine) .AppendHtml("<script>(") .AppendHtml(FallbackTestExpression) .AppendHtml("||document.write(\""); // May have no "src" attribute in the dictionary e.g. if Src and SrcInclude were not bound. if (!attributes.ContainsName(SrcAttributeName)) { // Need this entry to place each fallback source. attributes.Add(new TagHelperAttribute(SrcAttributeName, value: null)); } foreach (var src in fallbackSrcs) { // Fallback "src" values come from bound attributes and globbing. Must always be non-null. Debug.Assert(src != null); builder.AppendHtml("<script"); foreach (var attribute in attributes) { if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase)) { var encodedKey = JavaScriptEncoder.JavaScriptStringEncode(attribute.Name); var attributeValue = attribute.Value.ToString(); var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue); AppendAttribute(builder, encodedKey, encodedValue, escapeQuotes: true); } else { // Ignore attribute.Value; use src instead. var attributeValue = src; if (AppendVersion == true) { attributeValue = _fileVersionProvider.AddFileVersionToPath(attributeValue); } // attribute.Key ("src") does not need to be JavaScript-encoded. var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue); AppendAttribute(builder, attribute.Name, encodedValue, escapeQuotes: true); } } builder.AppendHtml("><\\/script>"); } builder.AppendHtml("\"));</script>"); } }
public void ContainsName_ReturnsExpectedResult( IEnumerable<TagHelperAttribute> initialAttributes, string nameToLookup, bool expected) { // Arrange var attributes = new TagHelperAttributeList(initialAttributes); // Act var contains = attributes.ContainsName(nameToLookup); // Assert Assert.Equal(expected, contains); }