diff --git a/src/Microsoft.AspNet.Razor/NotNullArgument.cs b/src/Microsoft.AspNet.Razor/NotNullArgument.cs new file mode 100644 index 0000000000..43016aeb51 --- /dev/null +++ b/src/Microsoft.AspNet.Razor/NotNullArgument.cs @@ -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 + { + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Razor/TagHelpers/ContentBehavior.cs b/src/Microsoft.AspNet.Razor/TagHelpers/ContentBehavior.cs new file mode 100644 index 0000000000..c513d5a710 --- /dev/null +++ b/src/Microsoft.AspNet.Razor/TagHelpers/ContentBehavior.cs @@ -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 +{ + /// + /// Defines how a tag helper will utilize its inner HTML. + /// + public enum ContentBehavior + { + /// + /// Indicates that the tag helper will not modify its inner HTML in any way. This is the default + /// . + /// + /// Children of the current tag helper will execute after the current tag helper. + None, + + /// + /// Indicates that the tag helper wants anything within its tag builder's inner HTML to be + /// appended to content its children generate. + /// + /// Children of the current tag helper will execute before the current tag helper. + Append, + + /// + /// Indicates that the tag helper will modify its HTML content. Therefore this + /// enables the tag helper to examine the content its children generate. + /// + /// Children of the current tag helper will execute before the current tag helper. + Modify, + + /// + /// Indicates that the tag helper wants anything within its tag builder's inner HTML to be + /// prepended to the content its children generate. + /// + /// Children of the current tag helper will execute after the current tag helper. + Prepend, + + /// + /// Indicates that the tag helper wants anything within its tag builder's inner HTML to + /// replace any HTML inside of it. + /// + /// Children of the current tag helper will not execute. + Replace, + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperAttributeDescriptor.cs b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperAttributeDescriptor.cs new file mode 100644 index 0000000000..17529bc8ae --- /dev/null +++ b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperAttributeDescriptor.cs @@ -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 +{ + /// + /// A metadata class describing a tag helper attribute. + /// + public class TagHelperAttributeDescriptor + { + /// + /// Instantiates a new class. + /// + /// The HTML attribute name. + /// The for the tag + /// helper attribute + public TagHelperAttributeDescriptor(string attributeName, + PropertyInfo propertyInfo) + { + AttributeName = attributeName; + PropertyInfo = propertyInfo; + } + + /// + /// The HTML attribute name. + /// + public string AttributeName { get; private set; } + + /// + /// The name of the CLR property name that corresponds to the HTML attribute name. + /// + public string AttributePropertyName + { + get + { + return PropertyInfo.Name; + } + } + + /// + /// The for the tag helper attribute + /// + public PropertyInfo PropertyInfo { get; private set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDescriptor.cs b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDescriptor.cs new file mode 100644 index 0000000000..01a25ac9b8 --- /dev/null +++ b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDescriptor.cs @@ -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 +{ + /// + /// A metadata class describing a tag helper. + /// + public class TagHelperDescriptor + { + /// + /// Instantiates a new instance of the class. + /// + /// The tag name that the tag helper targets. '*' indicates a catch-all + /// which applies to every HTML tag. + /// The full name of the tag helper class. + /// The + /// of the tag helper. + public TagHelperDescriptor(string tagName, + string tagHelperName, + ContentBehavior contentBehavior) + { + TagName = tagName; + TagHelperName = tagHelperName; + ContentBehavior = contentBehavior; + Attributes = new List(); + } + + /// + /// The tag name that the tag helper should target. + /// + public string TagName { get; private set; } + + /// + /// The full name of the tag helper class. + /// + public string TagHelperName { get; private set; } + + /// + /// The of the tag helper. + /// + public ContentBehavior ContentBehavior { get; private set; } + + /// + /// The list of attributes the tag helper expects. + /// + public virtual List Attributes { get; private set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDescriptorProvider.cs b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDescriptorProvider.cs new file mode 100644 index 0000000000..f7e7bfc690 --- /dev/null +++ b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDescriptorProvider.cs @@ -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 +{ + /// + /// Enables retrieval of 's. + /// + public class TagHelperDescriptorProvider + { + private const string CatchAllDescriptorTarget = "*"; + + private static readonly TagHelperDescriptorComparer DefaultTagHelperDescriptorComparer = + new TagHelperDescriptorComparer(); + + private IDictionary> _registrations; + + /// + /// Instantiates a new instance of the . + /// + /// The descriptors that the will pull from. + public TagHelperDescriptorProvider(IEnumerable descriptors) + { + _registrations = new Dictionary>(StringComparer.OrdinalIgnoreCase); + + // Populate our registrations + foreach (var descriptor in descriptors) + { + Register(descriptor); + } + } + + /// + /// Gets all tag helpers that match the given . + /// + /// The name of the HTML tag to match. Providing a '*' tag name + /// retrieves catch-all s (descriptors that target every tag). + /// s that apply to the given . + /// Will return an empty if no s are + /// found. + public IEnumerable GetTagHelpers(string tagName) + { + HashSet descriptors; + + // Ensure there's an ISet to use. + if (!_registrations.TryGetValue(CatchAllDescriptorTarget, out descriptors)) + { + descriptors = new HashSet(); + } + + // 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 descriptorSet; + + // Ensure there's a List to add the descriptor to. + if (!_registrations.TryGetValue(descriptor.TagName, out descriptorSet)) + { + descriptorSet = new HashSet(DefaultTagHelperDescriptorComparer); + _registrations[descriptor.TagName] = descriptorSet; + } + + descriptorSet.Add(descriptor); + } + + private class TagHelperDescriptorComparer : IEqualityComparer + { + 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; + } + } + } +} \ No newline at end of file