Add TagHelper registration system.
- This registration system accepts tag descriptors that it then uses to feed requests for tag helpers. - Added some infrastructure pieces that are used to build up valid tag helper descriptors. #70
This commit is contained in:
parent
a9f6a63e7f
commit
555615f60e
|
|
@ -0,0 +1,12 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
|
||||||
|
internal sealed class NotNullAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines how a tag helper will utilize its inner HTML.
|
||||||
|
/// </summary>
|
||||||
|
public enum ContentBehavior
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the tag helper will not modify its inner HTML in any way. This is the default
|
||||||
|
/// <see cref="ContentBehavior"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Children of the current tag helper will execute after the current tag helper.</remarks>
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the tag helper wants anything within its tag builder's inner HTML to be
|
||||||
|
/// appended to content its children generate.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Children of the current tag helper will execute before the current tag helper.</remarks>
|
||||||
|
Append,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the tag helper will modify its HTML content. Therefore this <see cref="ContentBehavior"/>
|
||||||
|
/// enables the tag helper to examine the content its children generate.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Children of the current tag helper will execute before the current tag helper.</remarks>
|
||||||
|
Modify,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the tag helper wants anything within its tag builder's inner HTML to be
|
||||||
|
/// prepended to the content its children generate.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Children of the current tag helper will execute after the current tag helper.</remarks>
|
||||||
|
Prepend,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the tag helper wants anything within its tag builder's inner HTML to
|
||||||
|
/// replace any HTML inside of it.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Children of the current tag helper will not execute.</remarks>
|
||||||
|
Replace,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
// 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.Reflection;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A metadata class describing a tag helper attribute.
|
||||||
|
/// </summary>
|
||||||
|
public class TagHelperAttributeDescriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates a new <see cref="TagHelperAttributeDescriptor"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="attributeName">The HTML attribute name.</param>
|
||||||
|
/// <param name="propertyInfo">The <see cref="System.Reflection.PropertyInfo"/> for the tag
|
||||||
|
/// helper attribute</param>
|
||||||
|
public TagHelperAttributeDescriptor(string attributeName,
|
||||||
|
PropertyInfo propertyInfo)
|
||||||
|
{
|
||||||
|
AttributeName = attributeName;
|
||||||
|
PropertyInfo = propertyInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The HTML attribute name.
|
||||||
|
/// </summary>
|
||||||
|
public string AttributeName { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the CLR property name that corresponds to the HTML attribute name.
|
||||||
|
/// </summary>
|
||||||
|
public string AttributePropertyName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return PropertyInfo.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="System.Reflection.PropertyInfo"/> for the tag helper attribute
|
||||||
|
/// </summary>
|
||||||
|
public PropertyInfo PropertyInfo { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
// 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Internal.Web.Utils;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A metadata class describing a tag helper.
|
||||||
|
/// </summary>
|
||||||
|
public class TagHelperDescriptor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates a new instance of the <see cref="TagHelperDescriptor"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tagName">The tag name that the tag helper targets. '*' indicates a catch-all
|
||||||
|
/// <see cref="TagHelperDescriptor"/> which applies to every HTML tag.</param>
|
||||||
|
/// <param name="tagHelperName">The full name of the tag helper class.</param>
|
||||||
|
/// <param name="contentBehavior">The <see cref="TagHelpers.ContentBehavior"/>
|
||||||
|
/// of the tag helper.</param>
|
||||||
|
public TagHelperDescriptor(string tagName,
|
||||||
|
string tagHelperName,
|
||||||
|
ContentBehavior contentBehavior)
|
||||||
|
{
|
||||||
|
TagName = tagName;
|
||||||
|
TagHelperName = tagHelperName;
|
||||||
|
ContentBehavior = contentBehavior;
|
||||||
|
Attributes = new List<TagHelperAttributeDescriptor>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The tag name that the tag helper should target.
|
||||||
|
/// </summary>
|
||||||
|
public string TagName { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The full name of the tag helper class.
|
||||||
|
/// </summary>
|
||||||
|
public string TagHelperName { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="TagHelpers.ContentBehavior"/> of the tag helper.
|
||||||
|
/// </summary>
|
||||||
|
public ContentBehavior ContentBehavior { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of attributes the tag helper expects.
|
||||||
|
/// </summary>
|
||||||
|
public virtual List<TagHelperAttributeDescriptor> Attributes { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
// 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Internal.Web.Utils;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enables retrieval of <see cref="TagHelperDescriptor"/>'s.
|
||||||
|
/// </summary>
|
||||||
|
public class TagHelperDescriptorProvider
|
||||||
|
{
|
||||||
|
private const string CatchAllDescriptorTarget = "*";
|
||||||
|
|
||||||
|
private static readonly TagHelperDescriptorComparer DefaultTagHelperDescriptorComparer =
|
||||||
|
new TagHelperDescriptorComparer();
|
||||||
|
|
||||||
|
private IDictionary<string, HashSet<TagHelperDescriptor>> _registrations;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates a new instance of the <see cref="TagHelperDescriptorProvider"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="descriptors">The descriptors that the <see cref="TagHelperDescriptorProvider"/> will pull from.</param>
|
||||||
|
public TagHelperDescriptorProvider(IEnumerable<TagHelperDescriptor> descriptors)
|
||||||
|
{
|
||||||
|
_registrations = new Dictionary<string, HashSet<TagHelperDescriptor>>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
// Populate our registrations
|
||||||
|
foreach (var descriptor in descriptors)
|
||||||
|
{
|
||||||
|
Register(descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all tag helpers that match the given <paramref name="tagName"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tagName">The name of the HTML tag to match. Providing a '*' tag name
|
||||||
|
/// retrieves catch-all <see cref="TagHelperDescriptor"/>s (descriptors that target every tag).</param>
|
||||||
|
/// <returns><see cref="TagHelperDescriptor"/>s that apply to the given <paramref name="tagName"/>.
|
||||||
|
/// Will return an empty <see cref="Enumerable" /> if no <see cref="TagHelperDescriptor"/>s are
|
||||||
|
/// found.</returns>
|
||||||
|
public IEnumerable<TagHelperDescriptor> GetTagHelpers(string tagName)
|
||||||
|
{
|
||||||
|
HashSet<TagHelperDescriptor> descriptors;
|
||||||
|
|
||||||
|
// Ensure there's an ISet to use.
|
||||||
|
if (!_registrations.TryGetValue(CatchAllDescriptorTarget, out descriptors))
|
||||||
|
{
|
||||||
|
descriptors = new HashSet<TagHelperDescriptor>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the requested tag name is the catch-all target, we should short circuit.
|
||||||
|
if (tagName.Equals(CatchAllDescriptorTarget, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return descriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a tag name associated with the requested name, return the descriptors +
|
||||||
|
// all of the catch-all descriptors.
|
||||||
|
if (_registrations.TryGetValue(tagName, out var matchingDescriptors))
|
||||||
|
{
|
||||||
|
return matchingDescriptors.Concat(descriptors);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We couldn't any descriptors associated with the requested tag name, return all
|
||||||
|
// of the "catch-all" tag descriptors (there may not be any).
|
||||||
|
return descriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Register(TagHelperDescriptor descriptor)
|
||||||
|
{
|
||||||
|
HashSet<TagHelperDescriptor> descriptorSet;
|
||||||
|
|
||||||
|
// Ensure there's a List to add the descriptor to.
|
||||||
|
if (!_registrations.TryGetValue(descriptor.TagName, out descriptorSet))
|
||||||
|
{
|
||||||
|
descriptorSet = new HashSet<TagHelperDescriptor>(DefaultTagHelperDescriptorComparer);
|
||||||
|
_registrations[descriptor.TagName] = descriptorSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptorSet.Add(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TagHelperDescriptorComparer : IEqualityComparer<TagHelperDescriptor>
|
||||||
|
{
|
||||||
|
public bool Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)
|
||||||
|
{
|
||||||
|
return descriptorX.TagHelperName == descriptorY.TagHelperName &&
|
||||||
|
descriptorX.TagName == descriptorY.TagName &&
|
||||||
|
descriptorX.ContentBehavior == descriptorY.ContentBehavior;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode(TagHelperDescriptor descriptor)
|
||||||
|
{
|
||||||
|
return HashCodeCombiner.Start()
|
||||||
|
.Add(descriptor.TagName)
|
||||||
|
.Add(descriptor.TagHelperName)
|
||||||
|
.Add(descriptor.ContentBehavior)
|
||||||
|
.CombinedHash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue