This repository has been archived by the owner on Dec 19, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 224
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add CSS attribute selectors for
TagHelper
attributes.
- Added the ability for users to opt into CSS `TagHelper` selectors in their required attributes by surrounding the value with `[` and `]`. Added operators `^`, `$` and `=`. - Added tests to cover code paths used when determining CSS selectors. #684
- Loading branch information
1 parent
e6d4d6c
commit 5f40497
Showing
19 changed files
with
1,603 additions
and
211 deletions.
There are no files selected for viewing
384 changes: 345 additions & 39 deletions
384
src/Microsoft.AspNetCore.Razor.Runtime/Runtime/TagHelpers/TagHelperDescriptorFactory.cs
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
...spNetCore.Razor.Test.Sources/CaseSensitiveTagHelperRequiredAttributeDescriptorComparer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers; | ||
using Microsoft.Extensions.Internal; | ||
using Xunit; | ||
|
||
namespace Microsoft.AspNetCore.Razor.Test.Internal | ||
{ | ||
internal class CaseSensitiveTagHelperRequiredAttributeDescriptorComparer : TagHelperRequiredAttributeDescriptorComparer | ||
{ | ||
public new static readonly CaseSensitiveTagHelperRequiredAttributeDescriptorComparer Default = | ||
new CaseSensitiveTagHelperRequiredAttributeDescriptorComparer(); | ||
|
||
private CaseSensitiveTagHelperRequiredAttributeDescriptorComparer() | ||
: base() | ||
{ | ||
} | ||
|
||
public override bool Equals(TagHelperRequiredAttributeDescriptor descriptorX, TagHelperRequiredAttributeDescriptor descriptorY) | ||
{ | ||
if (descriptorX == descriptorY) | ||
{ | ||
return true; | ||
} | ||
|
||
Assert.True(base.Equals(descriptorX, descriptorY)); | ||
|
||
Assert.Equal(descriptorX.Name, descriptorY.Name, StringComparer.Ordinal); | ||
|
||
return true; | ||
} | ||
|
||
public override int GetHashCode(TagHelperRequiredAttributeDescriptor descriptor) | ||
{ | ||
var hashCodeCombiner = HashCodeCombiner.Start(); | ||
hashCodeCombiner.Add(base.GetHashCode(descriptor)); | ||
hashCodeCombiner.Add(descriptor.Name, StringComparer.Ordinal); | ||
|
||
return hashCodeCombiner.CombinedHash; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
...Microsoft.AspNetCore.Razor/Compilation/TagHelpers/TagHelperRequiredAttributeDescriptor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
|
||
namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers | ||
{ | ||
/// <summary> | ||
/// A metadata class describing a required tag helper attribute. | ||
/// </summary> | ||
public class TagHelperRequiredAttributeDescriptor | ||
{ | ||
/// <summary> | ||
/// The HTML attribute name. | ||
/// </summary> | ||
public string Name { get; set; } | ||
|
||
/// <summary> | ||
/// The HTML attribute selector value. If <see cref="IsCSSSelector"/> is not <c>true</c>, this field is | ||
/// ignored. | ||
/// </summary> | ||
public string Value { get; set; } | ||
|
||
/// <summary> | ||
/// An operator that modifies how a required attribute is applied to an HTML attribute value or name. | ||
/// </summary> | ||
public char Operator { get; set; } | ||
|
||
/// <summary> | ||
/// Indicates if the <see cref="TagHelperRequiredAttributeDescriptor"/> represents a CSS selector. | ||
/// </summary> | ||
public bool IsCSSSelector { get; set; } | ||
|
||
/// <summary> | ||
/// Determines if the current <see cref="TagHelperRequiredAttributeDescriptor"/> matches the given | ||
/// <paramref name="attributeName"/> and <paramref name="attributeValue"/>. | ||
/// </summary> | ||
/// <param name="attributeName">An HTML attribute name.</param> | ||
/// <param name="attributeValue">An HTML attribute value.</param> | ||
/// <returns></returns> | ||
public bool Matches(string attributeName, string attributeValue) | ||
{ | ||
if (IsCSSSelector) | ||
{ | ||
var nameMatches = string.Equals(Name, attributeName, StringComparison.OrdinalIgnoreCase); | ||
|
||
if (!nameMatches) | ||
{ | ||
return false; | ||
} | ||
|
||
var valueMatches = false; | ||
switch (Operator) | ||
{ | ||
case '^': // Value starts with | ||
valueMatches = attributeValue.StartsWith(Value, StringComparison.Ordinal); | ||
break; | ||
case '$': // Value ends with | ||
valueMatches = attributeValue.EndsWith(Value, StringComparison.Ordinal); | ||
break; | ||
case '=': // Value equals | ||
valueMatches = string.Equals(attributeValue, Value, StringComparison.Ordinal); | ||
break; | ||
default: // No value selector, force true because at least the attribute name matched. | ||
valueMatches = true; | ||
break; | ||
} | ||
|
||
return valueMatches; | ||
} | ||
else if (Operator == '*') | ||
{ | ||
return attributeName.Length != Name.Length & | ||
attributeName.StartsWith(Name, StringComparison.OrdinalIgnoreCase); | ||
} | ||
else | ||
{ | ||
return string.Equals(Name, attributeName, StringComparison.OrdinalIgnoreCase); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Determines whether the provided <paramref name="op"/> is a supported CSS value operator. | ||
/// </summary> | ||
/// <param name="op">The CSS value operator</param> | ||
/// <returns><c>true</c> if <paramref name="op"/> is <c>=</c>, <c>^</c> or <c>$</c>; <c>false</c> otherwise. | ||
/// </returns> | ||
public static bool IsSupportedCSSValueOperator(char op) | ||
{ | ||
return op == '=' || op == '^' || op == '$'; | ||
} | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
...t.AspNetCore.Razor/Compilation/TagHelpers/TagHelperRequiredAttributeDescriptorComparer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using Microsoft.Extensions.Internal; | ||
|
||
namespace Microsoft.AspNetCore.Razor.Compilation.TagHelpers | ||
{ | ||
/// <summary> | ||
/// An <see cref="IEqualityComparer{TagHelperRequiredAttributeDescriptor}"/> used to check equality between | ||
/// two <see cref="TagHelperRequiredAttributeDescriptor"/>s. | ||
/// </summary> | ||
public class TagHelperRequiredAttributeDescriptorComparer : IEqualityComparer<TagHelperRequiredAttributeDescriptor> | ||
{ | ||
/// <summary> | ||
/// A default instance of the <see cref="TagHelperRequiredAttributeDescriptor"/>. | ||
/// </summary> | ||
public static readonly TagHelperRequiredAttributeDescriptorComparer Default = new TagHelperRequiredAttributeDescriptorComparer(); | ||
|
||
/// <summary> | ||
/// Initializes a new <see cref="TagHelperRequiredAttributeDescriptor"/> instance. | ||
/// </summary> | ||
protected TagHelperRequiredAttributeDescriptorComparer() | ||
{ | ||
} | ||
|
||
/// <inheritdoc /> | ||
public virtual bool Equals(TagHelperRequiredAttributeDescriptor descriptorX, TagHelperRequiredAttributeDescriptor descriptorY) | ||
{ | ||
if (descriptorX == descriptorY) | ||
{ | ||
return true; | ||
} | ||
|
||
return descriptorX != null && | ||
descriptorX.Operator == descriptorY.Operator && | ||
descriptorX.IsCSSSelector == descriptorY.IsCSSSelector && | ||
string.Equals(descriptorX.Name, descriptorY.Name, StringComparison.OrdinalIgnoreCase) && | ||
string.Equals(descriptorX.Value, descriptorY.Value, StringComparison.Ordinal); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public virtual int GetHashCode(TagHelperRequiredAttributeDescriptor descriptor) | ||
{ | ||
var hashCodeCombiner = HashCodeCombiner.Start(); | ||
hashCodeCombiner.Add(descriptor.Operator); | ||
hashCodeCombiner.Add(descriptor.IsCSSSelector); | ||
hashCodeCombiner.Add(descriptor.Name, StringComparer.OrdinalIgnoreCase); | ||
hashCodeCombiner.Add(descriptor.Value, StringComparer.Ordinal); | ||
|
||
return hashCodeCombiner.CombinedHash; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.