Remove Razor Runtime projects

\n\nCommit migrated from 39472ca0d6
This commit is contained in:
Ryan Nowak 2018-12-02 12:36:44 -08:00
parent c8bb6c34bb
commit 616ec14459
99 changed files with 5087 additions and 90 deletions

View File

@ -13,9 +13,10 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.Common\Microsoft.AspNetCore.Razor.Test.Common.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj" />
<ProjectReference Include="..\..\src\Microsoft.CodeAnalysis.Razor\Microsoft.CodeAnalysis.Razor.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.Common\Microsoft.AspNetCore.Razor.Test.Common.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X.csproj" />
</ItemGroup>
<ItemGroup>
@ -25,19 +26,6 @@
<PackageReference Include="Moq" Version="$(MoqPackageVersion)" />
</ItemGroup>
<ItemGroup>
<!-- We need this to compile but don't want it referenced by the project. It is included dynamically in CodeGeneration tests. -->
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<OutputItemType>Content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Targets>Build</Targets>
</ProjectReference>
<!-- Due to how DependencyContext.Load handles our special MvcShim reference above we need to also reference the MvcShim's DiagnosticSource dependency -->
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(SystemDiagnosticsDiagnosticSourcePackageVersion)" />
</ItemGroup>
<ItemGroup>
<MvcShim Condition="$(TargetFramework) != ''" Include="$(ArtifactsBinDir)\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X\$(Configuration)\$(TargetFramework)\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X.deps.json" />
</ItemGroup>

View File

@ -13,9 +13,10 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.Common\Microsoft.AspNetCore.Razor.Test.Common.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj" />
<ProjectReference Include="..\..\src\Microsoft.CodeAnalysis.Razor\Microsoft.CodeAnalysis.Razor.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.Common\Microsoft.AspNetCore.Razor.Test.Common.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X.csproj" />
</ItemGroup>
<ItemGroup>
@ -25,20 +26,6 @@
<PackageReference Include="Moq" Version="$(MoqPackageVersion)" />
</ItemGroup>
<ItemGroup>
<!-- We need this to compile but don't want it referenced by the project. It is included dynamically in CodeGeneration tests. -->
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<OutputItemType>Content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Targets>Build</Targets>
</ProjectReference>
<!-- Due to how DependencyContext.Load handles our special MvcShim reference above we need to also reference the MvcShim's DiagnosticSource dependency -->
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(SystemDiagnosticsDiagnosticSourcePackageVersion)" />
</ItemGroup>
<Target Name="CopyDepsFromShims" AfterTargets="Build">
<ItemGroup>
<MvcShim Condition="$(TargetFramework) != ''" Include="$(ArtifactsBinDir)\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X\$(Configuration)\$(TargetFramework)\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X.deps.json" />

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X
@ -13,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X
{
private static readonly Assembly _assembly = typeof(ViewComponentTypeVisitorTest).GetTypeInfo().Assembly;
private static Compilation Compilation { get; } = TestCompilation.Create(_assembly);
private static CSharpCompilation Compilation { get; } = TestCompilation.Create(_assembly);
// In practice MVC will provide a marker attribute for ViewComponents. To prevent a circular reference between MVC and Razor
// we can use a test class as a marker.

View File

@ -13,9 +13,9 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc.Razor.Extensions\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.Common\Microsoft.AspNetCore.Razor.Test.Common.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj" />
<ProjectReference Include="..\..\src\Microsoft.CodeAnalysis.Razor\Microsoft.CodeAnalysis.Razor.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.Common\Microsoft.AspNetCore.Razor.Test.Common.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.MvcShim\Microsoft.AspNetCore.Razor.Test.MvcShim.csproj" />
</ItemGroup>
<ItemGroup>
@ -25,19 +25,6 @@
<PackageReference Include="Moq" Version="$(MoqPackageVersion)" />
</ItemGroup>
<ItemGroup>
<!-- We need this to compile but don't want it referenced by the project. It is included dynamically in CodeGeneration tests. -->
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.MvcShim\Microsoft.AspNetCore.Razor.Test.MvcShim.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<OutputItemType>Content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Targets>Build</Targets>
</ProjectReference>
<!-- Due to how DependencyContext.Load handles our special MvcShim reference above we need to also reference the MvcShim's DiagnosticSource dependency -->
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(SystemDiagnosticsDiagnosticSourcePackageVersion)" />
</ItemGroup>
<Target Name="CopyDepsFromShims" AfterTargets="Build">
<ItemGroup>
<MvcShim Condition="$(TargetFramework) != ''" Include="$(ArtifactsBinDir)\Microsoft.AspNetCore.Razor.Test.MvcShim\$(Configuration)\$(TargetFramework)\Microsoft.AspNetCore.Razor.Test.MvcShim.deps.json" />

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
@ -13,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{
private static readonly Assembly _assembly = typeof(ViewComponentTypeVisitorTest).GetTypeInfo().Assembly;
private static Compilation Compilation { get; } = TestCompilation.Create(_assembly);
private static CSharpCompilation Compilation { get; } = TestCompilation.Create(_assembly);
// In practice MVC will provide a marker attribute for ViewComponents. To prevent a circular reference between MVC and Razor
// we can use a test class as a marker.

View File

@ -14,9 +14,10 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.CodeAnalysis.Razor\Microsoft.CodeAnalysis.Razor.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Language\Microsoft.AspNetCore.Razor.Language.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor\Microsoft.AspNetCore.Razor.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.Common\Microsoft.AspNetCore.Razor.Test.Common.csproj" />
<!-- Included for definitions of Tag Helper types -->
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Test.MvcShim\Microsoft.AspNetCore.Razor.Test.MvcShim.csproj" />
</ItemGroup>
<ItemGroup>

View File

@ -5,10 +5,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="$(MicrosoftAspNetCoreHtmlAbstractionsPackageVersion)" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(SystemDiagnosticsDiagnosticSourcePackageVersion)" />
</ItemGroup>

View File

@ -0,0 +1,70 @@
// 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 System.Diagnostics;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
{
public class TagHelperExecutionContext
{
public TagHelperExecutionContext(
string tagName,
TagMode tagMode,
IDictionary<object, object> items,
string uniqueId,
Func<Task> executeChildContentAsync,
Action<HtmlEncoder> startTagHelperWritingScope,
Func<TagHelperContent> endTagHelperWritingScope)
{
}
public bool ChildContentRetrieved => false;
public IDictionary<object, object> Items { get; private set; }
public IList<ITagHelper> TagHelpers => null;
public TagHelperOutput Output { get; internal set; }
public TagHelperContext Context { get; }
public void Add(ITagHelper tagHelper)
{
}
public void AddHtmlAttribute(string name, object value, HtmlAttributeValueStyle valueStyle)
{
}
public void AddHtmlAttribute(TagHelperAttribute attribute)
{
}
public void AddTagHelperAttribute(string name, object value, HtmlAttributeValueStyle valueStyle)
{
}
public void AddTagHelperAttribute(TagHelperAttribute attribute)
{
}
public void Reinitialize(
string tagName,
TagMode tagMode,
IDictionary<object, object> items,
string uniqueId,
Func<Task> executeChildContentAsync)
{
}
public Task SetOutputContentAsync()
{
throw null;
}
}
}

View File

@ -0,0 +1,18 @@
// 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 System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
{
public class TagHelperRunner
{
public Task RunAsync(TagHelperExecutionContext executionContext)
{
throw null;
}
}
}

View File

@ -0,0 +1,34 @@
// 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 System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
{
public class TagHelperScopeManager
{
public TagHelperScopeManager(
Action<HtmlEncoder> startTagHelperWritingScope,
Func<TagHelperContent> endTagHelperWritingScope)
{
}
public TagHelperExecutionContext Begin(
string tagName,
TagMode tagMode,
string uniqueId,
Func<Task> executeChildContentAsync)
{
throw null;
}
public TagHelperExecutionContext End()
{
throw null;
}
}
}

View File

@ -0,0 +1,92 @@
// 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.TagHelpers
{
/// <summary>
/// Used to override an <see cref="ITagHelper"/> property's HTML attribute name.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class HtmlAttributeNameAttribute : Attribute
{
private string _dictionaryAttributePrefix;
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlAttributeNameAttribute"/> class with <see cref="Name"/>
/// equal to <c>null</c>.
/// </summary>
/// <remarks>
/// Associated property must not have a public setter and must be compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>.
/// </remarks>
public HtmlAttributeNameAttribute()
{
}
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlAttributeNameAttribute"/> class.
/// </summary>
/// <param name="name">
/// HTML attribute name for the associated property. Must be <c>null</c> or empty if associated property does
/// not have a public setter and is compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>. Otherwise must not be <c>null</c> or empty.
/// </param>
public HtmlAttributeNameAttribute(string name)
{
Name = name;
}
/// <summary>
/// HTML attribute name of the associated property.
/// </summary>
/// <value>
/// <c>null</c> or empty if and only if associated property does not have a public setter and is compatible
/// with <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>.
/// </value>
public string Name { get; }
/// <summary>
/// Gets or sets the prefix used to match HTML attribute names. Matching attributes are added to the
/// associated property (an <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>).
/// </summary>
/// <remarks>
/// If non-<c>null</c> associated property must be compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>.
/// </remarks>
/// <value>
/// <para>
/// If associated property is compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>, default value is <c>Name + "-"</c>.
/// <see cref="Name"/> must not be <c>null</c> or empty in this case.
/// </para>
/// <para>
/// Otherwise default value is <c>null</c>.
/// </para>
/// </value>
public string DictionaryAttributePrefix
{
get
{
return _dictionaryAttributePrefix;
}
set
{
_dictionaryAttributePrefix = value;
DictionaryAttributePrefixSet = true;
}
}
/// <summary>
/// Gets an indication whether <see cref="DictionaryAttributePrefix"/> has been set. Used to distinguish an
/// uninitialized <see cref="DictionaryAttributePrefix"/> value from an explicit <c>null</c> setting.
/// </summary>
/// <value><c>true</c> if <see cref="DictionaryAttributePrefix"/> was set. <c>false</c> otherwise.</value>
public bool DictionaryAttributePrefixSet { get; private set; }
}
}

View File

@ -0,0 +1,21 @@
// 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.TagHelpers
{
/// <summary>
/// Indicates the associated <see cref="ITagHelper"/> property should not be bound to HTML attributes.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class HtmlAttributeNotBoundAttribute : Attribute
{
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlAttributeNotBoundAttribute"/> class.
/// </summary>
public HtmlAttributeNotBoundAttribute()
{
}
}
}

View File

@ -0,0 +1,13 @@
// 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.
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public enum HtmlAttributeValueStyle
{
DoubleQuotes,
SingleQuotes,
NoQuotes,
Minimized,
}
}

View File

@ -0,0 +1,86 @@
// 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.TagHelpers
{
/// <summary>
/// Provides an <see cref="ITagHelper"/>'s target.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public sealed class HtmlTargetElementAttribute : Attribute
{
public const string ElementCatchAllTarget = "*";
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlTargetElementAttribute"/> class that targets all HTML
/// elements with the required <see cref="Attributes"/>.
/// </summary>
/// <remarks><see cref="Tag"/> is set to <c>*</c>.</remarks>
public HtmlTargetElementAttribute()
: this(ElementCatchAllTarget)
{
}
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlTargetElementAttribute"/> class with the given
/// <paramref name="tag"/> as its <see cref="Tag"/> value.
/// </summary>
/// <param name="tag">
/// The HTML tag the <see cref="ITagHelper"/> targets.
/// </param>
/// <remarks>A <c>*</c> <paramref name="tag"/> value indicates this <see cref="ITagHelper"/>
/// targets all HTML elements with the required <see cref="Attributes"/>.</remarks>
public HtmlTargetElementAttribute(string tag)
{
Tag = tag;
}
/// <summary>
/// The HTML tag the <see cref="ITagHelper"/> targets. A <c>*</c> value indicates this <see cref="ITagHelper"/>
/// targets all HTML elements with the required <see cref="Attributes"/>.
/// </summary>
public string Tag { get; }
/// <summary>
/// A comma-separated <see cref="string"/> of attribute selectors the HTML element must match for the
/// <see cref="ITagHelper"/> to run. <c>*</c> at the end of an attribute name acts as a prefix match. A value
/// surrounded by square brackets is handled as a CSS attribute value selector. Operators <c>^=</c>, <c>$=</c> and
/// <c>=</c> are supported e.g. <c>"name"</c>, <c>"[name]"</c>, <c>"[name=value]"</c>, <c>"[ name ^= 'value' ]"</c>.
/// </summary>
public string Attributes { get; set; }
/// <summary>
/// The expected tag structure. Defaults to <see cref="TagStructure.Unspecified"/>.
/// </summary>
/// <remarks>
/// If <see cref="TagStructure.Unspecified"/> and no other tag helpers applying to the same element specify
/// their <see cref="TagStructure"/> the <see cref="TagStructure.NormalOrSelfClosing"/> behavior is used:
/// <para>
/// <code>
/// &lt;my-tag-helper&gt;&lt;/my-tag-helper&gt;
/// &lt;!-- OR --&gt;
/// &lt;my-tag-helper /&gt;
/// </code>
/// Otherwise, if another tag helper applying to the same element does specify their behavior, that behavior
/// is used.
/// </para>
/// <para>
/// If <see cref="TagStructure.WithoutEndTag"/> HTML elements can be written in the following formats:
/// <code>
/// &lt;my-tag-helper&gt;
/// &lt;!-- OR --&gt;
/// &lt;my-tag-helper /&gt;
/// </code>
/// </para>
/// </remarks>
public TagStructure TagStructure { get; set; }
/// <summary>
/// The required HTML element name of the direct parent. A <c>null</c> value indicates any HTML element name is
/// allowed.
/// </summary>
public string ParentTag { get; set; }
}
}

View File

@ -0,0 +1,16 @@
// 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.Threading.Tasks;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public interface ITagHelper
{
int Order { get; }
void Init(TagHelperContext context);
Task ProcessAsync(TagHelperContext context, TagHelperOutput output);
}
}

View File

@ -0,0 +1,35 @@
// 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.TagHelpers
{
/// <summary>
/// Provides a hint of the <see cref="ITagHelper"/>'s output element.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class OutputElementHintAttribute : Attribute
{
/// <summary>
/// Instantiates a new instance of the <see cref="OutputElementHintAttribute"/> class.
/// </summary>
/// <param name="outputElement">
/// The HTML element the <see cref="ITagHelper"/> may output.
/// </param>
public OutputElementHintAttribute(string outputElement)
{
if (outputElement == null)
{
throw new ArgumentNullException(nameof(outputElement));
}
OutputElement = outputElement;
}
/// <summary>
/// The HTML element the <see cref="ITagHelper"/> may output.
/// </summary>
public string OutputElement { get; }
}
}

View File

@ -0,0 +1,190 @@
// 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 System.Collections.ObjectModel;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// A read-only collection of <see cref="TagHelperAttribute"/>s.
/// </summary>
public abstract class ReadOnlyTagHelperAttributeList : ReadOnlyCollection<TagHelperAttribute>
{
private static readonly IReadOnlyList<TagHelperAttribute> EmptyList = new TagHelperAttribute[0];
/// <summary>
/// Instantiates a new instance of <see cref="ReadOnlyTagHelperAttributeList"/> with an empty
/// collection.
/// </summary>
protected ReadOnlyTagHelperAttributeList()
: base(new List<TagHelperAttribute>())
{
}
/// <summary>
/// Instantiates a new instance of <see cref="ReadOnlyTagHelperAttributeList"/> with the specified
/// <paramref name="attributes"/>.
/// </summary>
/// <param name="attributes">The collection to wrap.</param>
public ReadOnlyTagHelperAttributeList(IList<TagHelperAttribute> attributes)
: base(attributes)
{
}
/// <summary>
/// Gets the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/>.
/// </summary>
/// <param name="name">
/// The <see cref="TagHelperAttribute.Name"/> of the <see cref="TagHelperAttribute"/> to get.
/// </param>
/// <returns>The first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/>.
/// </returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public TagHelperAttribute this[string name]
{
get
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
// Perf: Avoid allocating enumerator
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(name, Items[i]))
{
return Items[i];
}
}
return null;
}
}
/// <summary>
/// Determines whether a <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/> exists in the collection.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the
/// <see cref="TagHelperAttribute"/> to get.</param>
/// <returns>
/// <c>true</c> if a <see cref="TagHelperAttribute"/> with the same
/// <see cref="TagHelperAttribute.Name"/> exists in the collection; otherwise, <c>false</c>.
/// </returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool ContainsName(string name)
{
return this[name] != null;
}
/// <summary>
/// Retrieves the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/>.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the
/// <see cref="TagHelperAttribute"/> to get.</param>
/// <param name="attribute">When this method returns, the first <see cref="TagHelperAttribute"/> with
/// <see cref="TagHelperAttribute.Name"/> matching <paramref name="name"/>, if found; otherwise,
/// <c>null</c>.</param>
/// <returns><c>true</c> if a <see cref="TagHelperAttribute"/> with the same
/// <see cref="TagHelperAttribute.Name"/> exists in the collection; otherwise, <c>false</c>.</returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool TryGetAttribute(string name, out TagHelperAttribute attribute)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
attribute = this[name];
return attribute != null;
}
/// <summary>
/// Retrieves <see cref="TagHelperAttribute"/>s in the collection with
/// <see cref="TagHelperAttribute.Name"/> matching <paramref name="name"/>.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the
/// <see cref="TagHelperAttribute"/>s to get.</param>
/// <param name="attributes">When this method returns, the <see cref="TagHelperAttribute"/>s with
/// <see cref="TagHelperAttribute.Name"/> matching <paramref name="name"/>.</param>
/// <returns><c>true</c> if at least one <see cref="TagHelperAttribute"/> with the same
/// <see cref="TagHelperAttribute.Name"/> exists in the collection; otherwise, <c>false</c>.</returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool TryGetAttributes(string name, out IReadOnlyList<TagHelperAttribute> attributes)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
// Perf: Avoid allocating enumerator
List<TagHelperAttribute> matchedAttributes = null;
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(name, Items[i]))
{
if (matchedAttributes == null)
{
matchedAttributes = new List<TagHelperAttribute>();
}
matchedAttributes.Add(Items[i]);
}
}
attributes = matchedAttributes ?? EmptyList;
return matchedAttributes != null;
}
/// <summary>
/// Searches for a <see cref="TagHelperAttribute"/> who's <see cref="TagHelperAttribute.Name"/>
/// case-insensitively matches <paramref name="name"/> and returns the zero-based index of the first
/// occurrence.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> to locate in the collection.</param>
/// <returns>The zero-based index of the first matching <see cref="TagHelperAttribute"/> within the collection,
/// if found; otherwise, -1.</returns>
public int IndexOfName(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(name, Items[i]))
{
return i;
}
}
return -1;
}
/// <summary>
/// Determines if the specified <paramref name="attribute"/> has the same name as <paramref name="name"/>.
/// </summary>
/// <param name="name">The value to compare against <paramref name="attribute"/>s
/// <see cref="TagHelperAttribute.Name"/>.</param>
/// <param name="attribute">The attribute to compare against.</param>
/// <returns><c>true</c> if <paramref name="name"/> case-insensitively matches <paramref name="attribute"/>s
/// <see cref="TagHelperAttribute.Name"/>.</returns>
protected static bool NameEquals(string name, TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
return string.Equals(name, attribute.Name, StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@ -0,0 +1,42 @@
// 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;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Restricts children of the <see cref="ITagHelper"/>'s element.
/// </summary>
/// <remarks>Combining this attribute with a <see cref="HtmlTargetElementAttribute"/> that specifies its
/// <see cref="HtmlTargetElementAttribute.TagStructure"/> as <see cref="TagStructure.WithoutEndTag"/> will result
/// in this attribute being ignored.</remarks>
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class RestrictChildrenAttribute : Attribute
{
/// <summary>
/// Instantiates a new instance of the <see cref="RestrictChildrenAttribute"/> class.
/// </summary>
/// <param name="childTag">
/// The tag name of an element allowed as a child.
/// </param>
/// <param name="childTags">
/// Additional names of elements allowed as children.
/// </param>
public RestrictChildrenAttribute(string childTag, params string[] childTags)
{
var concatenatedNames = new string[1 + childTags.Length];
concatenatedNames[0] = childTag;
childTags.CopyTo(concatenatedNames, 1);
ChildTags = concatenatedNames;
}
/// <summary>
/// Get the names of elements allowed as children.
/// </summary>
public IEnumerable<string> ChildTags { get; }
}
}

View File

@ -0,0 +1,26 @@
// 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.Threading.Tasks;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public abstract class TagHelper : ITagHelper
{
public virtual int Order { get; } = 0;
public virtual void Init(TagHelperContext context)
{
}
public virtual void Process(TagHelperContext context, TagHelperOutput output)
{
}
public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
Process(context, output);
return Task.CompletedTask;
}
}
}

View File

@ -0,0 +1,43 @@
// 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.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Html;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public class TagHelperAttribute : IHtmlContentContainer
{
public TagHelperAttribute(string name)
{
}
public TagHelperAttribute(string name, object value)
{
}
public TagHelperAttribute(string name, object value, HtmlAttributeValueStyle valueStyle)
{
}
public string Name { get; }
public object Value { get; }
public HtmlAttributeValueStyle ValueStyle { get; }
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
}
public void CopyTo(IHtmlContentBuilder destination)
{
}
public void MoveTo(IHtmlContentBuilder destination)
{
}
}
}

View File

@ -0,0 +1,230 @@
// 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;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// A collection of <see cref="TagHelperAttribute"/>s.
/// </summary>
public class TagHelperAttributeList : ReadOnlyTagHelperAttributeList, IList<TagHelperAttribute>
{
/// <summary>
/// Instantiates a new instance of <see cref="TagHelperAttributeList"/> with an empty collection.
/// </summary>
public TagHelperAttributeList()
: base()
{
}
/// <summary>
/// Instantiates a new instance of <see cref="TagHelperAttributeList"/> with the specified
/// <paramref name="attributes"/>.
/// </summary>
/// <param name="attributes">The collection to wrap.</param>
public TagHelperAttributeList(IEnumerable<TagHelperAttribute> attributes)
: base (new List<TagHelperAttribute>(attributes))
{
if (attributes == null)
{
throw new ArgumentNullException(nameof(attributes));
}
}
/// <summary>
/// Instantiates a new instance of <see cref="TagHelperAttributeList"/> with the specified
/// <paramref name="attributes"/>.
/// </summary>
/// <param name="attributes">The collection to wrap.</param>
public TagHelperAttributeList(List<TagHelperAttribute> attributes)
: base(attributes)
{
if (attributes == null)
{
throw new ArgumentNullException(nameof(attributes));
}
}
/// <inheritdoc />
/// <remarks>
/// <paramref name="value"/>'s <see cref="TagHelperAttribute.Name"/> must not be <c>null</c>.
/// </remarks>
public new TagHelperAttribute this[int index]
{
get
{
return base[index];
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
Items[index] = value;
}
}
/// <summary>
/// Replaces the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/> matching
/// <paramref name="name"/> and removes any additional matching <see cref="TagHelperAttribute"/>s. If a
/// matching <see cref="TagHelperAttribute"/> is not found, adds a <see cref="TagHelperAttribute"/> with
/// <paramref name="name"/> and <paramref name="value"/> to the end of the collection.</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>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public void SetAttribute(string name, object value)
{
var attribute = new TagHelperAttribute(name, value);
SetAttribute(attribute);
}
/// <summary>
/// Replaces the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/> matching
/// <paramref name="attribute"/>'s <see cref="TagHelperAttribute.Name"/> and removes any additional matching
/// <see cref="TagHelperAttribute"/>s. If a matching <see cref="TagHelperAttribute"/> is not found, adds the
/// specified <paramref name="attribute"/> to the end of the collection.
/// </summary>
/// <param name="attribute">
/// The <see cref="TagHelperAttribute"/> to set.
/// </param>
/// <remarks><paramref name="attribute"/>'s <see cref="TagHelperAttribute.Name"/> is compared
/// case-insensitively.</remarks>
public void SetAttribute(TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
var attributeReplaced = false;
// Perf: Avoid allocating enumerator
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(attribute.Name, Items[i]))
{
// We replace the first attribute with the provided attribute, remove all the rest.
if (!attributeReplaced)
{
// We replace the first attribute we find with the same name.
Items[i] = attribute;
attributeReplaced = true;
}
else
{
Items.RemoveAt(i--);
}
}
}
// If we didn't replace an attribute value we should add value to the end of the collection.
if (!attributeReplaced)
{
Add(attribute);
}
}
/// <inheritdoc />
bool ICollection<TagHelperAttribute>.IsReadOnly => false;
/// <summary>
/// Adds a <see cref="TagHelperAttribute"/> to the end of the collection with the specified
/// <paramref name="name"/> and <paramref name="value"/>.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the attribute to add.</param>
/// <param name="value">The <see cref="TagHelperAttribute.Value"/> of the attribute to add.</param>
public void Add(string name, object value)
{
var attribute = new TagHelperAttribute(name, value);
Items.Add(attribute);
}
/// <inheritdoc />
public void Add(TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
Items.Add(attribute);
}
/// <inheritdoc />
public void Insert(int index, TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
Items.Insert(index, attribute);
}
/// <inheritdoc />
/// <remarks>
/// <paramref name="attribute"/>s <see cref="TagHelperAttribute.Name"/> is compared case-insensitively.
/// </remarks>
public bool Remove(TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
return Items.Remove(attribute);
}
/// <inheritdoc />
public void RemoveAt(int index)
{
Items.RemoveAt(index);
}
/// <summary>
/// Removes all <see cref="TagHelperAttribute"/>s with <see cref="TagHelperAttribute.Name"/> matching
/// <paramref name="name"/>.
/// </summary>
/// <param name="name">
/// The <see cref="TagHelperAttribute.Name"/> of <see cref="TagHelperAttribute"/>s to remove.
/// </param>
/// <returns>
/// <c>true</c> if at least 1 <see cref="TagHelperAttribute"/> was removed; otherwise, <c>false</c>.
/// </returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool RemoveAll(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
// Perf: Avoid allocating enumerator
var removedAtLeastOne = false;
for (var i = Items.Count - 1; i >= 0; i--)
{
if (NameEquals(name, Items[i]))
{
Items.RemoveAt(i);
removedAtLeastOne = true;
}
}
return removedAtLeastOne;
}
/// <inheritdoc />
public void Clear()
{
Items.Clear();
}
}
}

View File

@ -0,0 +1,179 @@
// 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.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Html;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Abstract class used to buffer content returned by <see cref="ITagHelper"/>s.
/// </summary>
public abstract class TagHelperContent : IHtmlContentBuilder
{
/// <summary>
/// Gets a value indicating whether the content was modified.
/// </summary>
public abstract bool IsModified { get; }
/// <summary>
/// Gets a value indicating whether the content is empty or whitespace.
/// </summary>
public abstract bool IsEmptyOrWhiteSpace { get; }
/// <summary>
/// Sets the content.
/// </summary>
/// <param name="htmlContent">The <see cref="IHtmlContent"/> that replaces the content.</param>
/// <returns>A reference to this instance after the set operation has completed.</returns>
public TagHelperContent SetHtmlContent(IHtmlContent htmlContent)
{
HtmlContentBuilderExtensions.SetHtmlContent(this, htmlContent);
return this;
}
/// <summary>
/// Sets the content.
/// </summary>
/// <param name="unencoded">
/// The <see cref="string"/> that replaces the content. The value is assume to be unencoded
/// as-provided and will be HTML encoded before being written.
/// </param>
/// <returns>A reference to this instance after the set operation has completed.</returns>
public TagHelperContent SetContent(string unencoded)
{
HtmlContentBuilderExtensions.SetContent(this, unencoded);
return this;
}
/// <summary>
/// Sets the content.
/// </summary>
/// <param name="encoded">
/// The <see cref="string"/> that replaces the content. The value is assume to be HTML encoded
/// as-provided and no further encoding will be performed.
/// </param>
/// <returns>A reference to this instance after the set operation has completed.</returns>
public TagHelperContent SetHtmlContent(string encoded)
{
HtmlContentBuilderExtensions.SetHtmlContent(this, encoded);
return this;
}
/// <summary>
/// Appends <paramref name="unencoded"/> to the existing content.
/// </summary>
/// <param name="unencoded">The <see cref="string"/> to be appended.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public abstract TagHelperContent Append(string unencoded);
/// <summary>
/// Appends <paramref name="htmlContent"/> to the existing content.
/// </summary>
/// <param name="htmlContent">The <see cref="IHtmlContent"/> to be appended.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public abstract TagHelperContent AppendHtml(IHtmlContent htmlContent);
/// <summary>
/// Appends <paramref name="encoded"/> to the existing content. <paramref name="encoded"/> is assumed
/// to be an HTML encoded <see cref="string"/> and no further encoding will be performed.
/// </summary>
/// <param name="encoded">The <see cref="string"/> to be appended.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public abstract TagHelperContent AppendHtml(string encoded);
/// <summary>
/// Appends the specified <paramref name="format"/> to the existing content after
/// replacing each format item with the HTML encoded <see cref="string"/> representation of the
/// corresponding item in the <paramref name="args"/> array.
/// </summary>
/// <param name="format">
/// The composite format <see cref="string"/> (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx).
/// </param>
/// <param name="args">The object array to format.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public TagHelperContent AppendFormat(string format, params object[] args)
{
HtmlContentBuilderExtensions.AppendFormat(this, null, format, args);
return this;
}
/// <summary>
/// Appends the specified <paramref name="format"/> to the existing content with information from the
/// <paramref name="provider"/> after replacing each format item with the HTML encoded <see cref="string"/>
/// representation of the corresponding item in the <paramref name="args"/> array.
/// </summary>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="format">
/// The composite format <see cref="string"/> (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx).
/// </param>
/// <param name="args">The object array to format.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public TagHelperContent AppendFormat(IFormatProvider provider, string format, params object[] args)
{
HtmlContentBuilderExtensions.AppendFormat(this, provider, format, args);
return this;
}
/// <summary>
/// Clears the content.
/// </summary>
/// <returns>A reference to this instance after the clear operation has completed.</returns>
public abstract TagHelperContent Clear();
/// <summary>
/// Clears the <see cref="TagHelperContent"/>, so it can be reused.
/// </summary>
/// <remarks>This method does more than what <see cref="Clear"/> does. It also resets the
/// <see cref="IsModified"/> flag.</remarks>
public abstract void Reinitialize();
/// <inheritdoc />
public abstract void CopyTo(IHtmlContentBuilder destination);
/// <inheritdoc />
public abstract void MoveTo(IHtmlContentBuilder destination);
/// <summary>
/// Gets the content.
/// </summary>
/// <returns>A <see cref="string"/> containing the content.</returns>
public abstract string GetContent();
/// <summary>
/// Gets the content.
/// </summary>
/// <param name="encoder">The <see cref="HtmlEncoder"/>.</param>
/// <returns>A <see cref="string"/> containing the content.</returns>
public abstract string GetContent(HtmlEncoder encoder);
/// <inheritdoc />
public abstract void WriteTo(TextWriter writer, HtmlEncoder encoder);
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.AppendHtml(IHtmlContent content)
{
return AppendHtml(content);
}
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.Append(string unencoded)
{
return Append(unencoded);
}
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.AppendHtml(string encoded)
{
return AppendHtml(encoded);
}
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.Clear()
{
return Clear();
}
}
}

View File

@ -0,0 +1,118 @@
// 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;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Contains information related to the execution of <see cref="ITagHelper"/>s.
/// </summary>
public class TagHelperContext
{
private readonly TagHelperAttributeList _allAttributes;
/// <summary>
/// Instantiates a new <see cref="TagHelperContext"/>.
/// </summary>
/// <param name="tagName">The parsed HTML tag name of the element.</param>
/// <param name="allAttributes">Every attribute associated with the current HTML element.</param>
/// <param name="items">Collection of items used to communicate with other <see cref="ITagHelper"/>s.</param>
/// <param name="uniqueId">The unique identifier for the source element this <see cref="TagHelperContext" />
/// applies to.</param>
public TagHelperContext(
string tagName,
TagHelperAttributeList allAttributes,
IDictionary<object, object> items,
string uniqueId) : this(allAttributes, items, uniqueId)
{
if (tagName == null)
{
throw new ArgumentNullException(nameof(tagName));
}
TagName = tagName;
}
/// <summary>
/// Instantiates a new <see cref="TagHelperContext"/>.
/// </summary>
/// <param name="allAttributes">Every attribute associated with the current HTML element.</param>
/// <param name="items">Collection of items used to communicate with other <see cref="ITagHelper"/>s.</param>
/// <param name="uniqueId">The unique identifier for the source element this <see cref="TagHelperContext" />
/// applies to.</param>
public TagHelperContext(
TagHelperAttributeList allAttributes,
IDictionary<object, object> items,
string uniqueId)
{
if (items == null)
{
throw new ArgumentNullException(nameof(items));
}
if (uniqueId == null)
{
throw new ArgumentNullException(nameof(uniqueId));
}
if (allAttributes == null)
{
throw new ArgumentNullException(nameof(allAttributes));
}
_allAttributes = allAttributes;
Items = items;
UniqueId = uniqueId;
}
/// <summary>
/// The parsed HTML tag name of the element.
/// </summary>
public string TagName { get; private set; }
/// <summary>
/// Every attribute associated with the current HTML element.
/// </summary>
public ReadOnlyTagHelperAttributeList AllAttributes => _allAttributes;
/// <summary>
/// Gets the collection of items used to communicate with other <see cref="ITagHelper"/>s.
/// </summary>
/// <remarks>
/// This <see cref="IDictionary{Object, Object}" /> is copy-on-write in order to ensure items added to this
/// collection are visible only to other <see cref="ITagHelper"/>s targeting child elements.
/// </remarks>
public IDictionary<object, object> Items { get; private set; }
/// <summary>
/// An identifier unique to the HTML element this context is for.
/// </summary>
public string UniqueId { get; private set; }
/// <summary>
/// Clears the <see cref="TagHelperContext"/> and updates its state with the provided values.
/// </summary>
/// <param name="tagName">The HTML tag name to use.</param>
/// <param name="items">The <see cref="IDictionary{Object, Object}"/> to use.</param>
/// <param name="uniqueId">The unique id to use.</param>
public void Reinitialize(string tagName, IDictionary<object, object> items, string uniqueId)
{
TagName = tagName;
Reinitialize(items, uniqueId);
}
/// <summary>
/// Clears the <see cref="TagHelperContext"/> and updates its state with the provided values.
/// </summary>
/// <param name="items">The <see cref="IDictionary{Object, Object}"/> to use.</param>
/// <param name="uniqueId">The unique id to use.</param>
public void Reinitialize(IDictionary<object, object> items, string uniqueId)
{
_allAttributes.Clear();
Items = items;
UniqueId = uniqueId;
}
}
}

View File

@ -0,0 +1,79 @@
// 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.IO;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public class TagHelperOutput : IHtmlContentContainer
{
public TagHelperOutput(
string tagName,
TagHelperAttributeList attributes,
Func<bool, HtmlEncoder, Task<TagHelperContent>> getChildContentAsync)
{
}
public string TagName { get; set; }
public TagHelperContent PreElement => null;
public TagHelperContent PreContent => null;
public TagHelperContent Content => null;
public TagHelperContent PostContent => null;
public TagHelperContent PostElement => null;
public bool IsContentModified => true;
public TagMode TagMode { get; set; }
public TagHelperAttributeList Attributes { get; }
public void Reinitialize(string tagName, TagMode tagMode)
{
}
public void SuppressOutput()
{
}
public Task<TagHelperContent> GetChildContentAsync()
{
throw null;
}
public Task<TagHelperContent> GetChildContentAsync(bool useCachedResult)
{
throw null;
}
public Task<TagHelperContent> GetChildContentAsync(HtmlEncoder encoder)
{
throw null;
}
public Task<TagHelperContent> GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder)
{
throw null;
}
void IHtmlContentContainer.CopyTo(IHtmlContentBuilder destination)
{
}
void IHtmlContentContainer.MoveTo(IHtmlContentBuilder destination)
{
}
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
}
}
}

View File

@ -0,0 +1,26 @@
// 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.
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// The mode in which an element should render.
/// </summary>
public enum TagMode
{
/// <summary>
/// Include both start and end tags.
/// </summary>
StartTagAndEndTag,
/// <summary>
/// A self-closed tag.
/// </summary>
SelfClosing,
/// <summary>
/// Only a start tag.
/// </summary>
StartTagOnly
}
}

View File

@ -0,0 +1,28 @@
// 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.
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// The structure the element should be written in.
/// </summary>
public enum TagStructure
{
/// <summary>
/// If no other tag helper applies to the same element and specifies a <see cref="TagStructure"/>,
/// <see cref="NormalOrSelfClosing"/> will be used.
/// </summary>
Unspecified,
/// <summary>
/// Element can be written as &lt;my-tag-helper&gt;&lt;/my-tag-helper&gt; or &lt;my-tag-helper /&gt;.
/// </summary>
NormalOrSelfClosing,
/// <summary>
/// Element can be written as &lt;my-tag-helper&gt; or &lt;my-tag-helper /&gt;.
/// </summary>
/// <remarks>Elements with a <see cref="WithoutEndTag"/> structure will never have any content.</remarks>
WithoutEndTag
}
}

View File

@ -6,10 +6,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="$(MicrosoftAspNetCoreHtmlAbstractionsPackageVersion)" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(SystemDiagnosticsDiagnosticSourcePackageVersion)" />
</ItemGroup>

View File

@ -0,0 +1,54 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Hosting
{
internal class DefaultRazorCompiledItem : RazorCompiledItem
{
private object[] _metadata;
public DefaultRazorCompiledItem(Type type, string kind, string identifier)
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
if (kind == null)
{
throw new ArgumentNullException(nameof(kind));
}
if (identifier == null)
{
throw new ArgumentNullException(nameof(identifier));
}
Type = type;
Kind = kind;
Identifier = identifier;
}
public override string Identifier { get; }
public override string Kind { get; }
public override IReadOnlyList<object> Metadata
{
get
{
if (_metadata == null)
{
_metadata = Type.GetCustomAttributes(inherit: true);
}
return _metadata;
}
}
public override Type Type { get; }
}
}

View File

@ -0,0 +1,26 @@
// 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.
namespace Microsoft.AspNetCore.Razor.Hosting
{
/// <summary>
/// A metadata object containing the checksum of a source file that contributed to a compiled item.
/// </summary>
public interface IRazorSourceChecksumMetadata
{
/// <summary>
/// Gets the checksum as string of hex-encoded bytes.
/// </summary>
string Checksum { get; }
/// <summary>
/// Gets the name of the algorithm used to create this checksum.
/// </summary>
string ChecksumAlgorithm { get; }
/// <summary>
/// Gets the identifier of the source file associated with this checksum.
/// </summary>
string Identifier { get; }
}
}

View File

@ -0,0 +1,40 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Hosting
{
/// <summary>
/// Identifies a compiled item that can be identified and loaded.
/// </summary>
public abstract class RazorCompiledItem
{
/// <summary>
/// Gets the identifier associated with the compiled item. The identifier is used programmatically to locate
/// a specific item of a specific kind and should be uniqure within the assembly.
/// </summary>
public abstract string Identifier { get; }
/// <summary>
/// Gets the kind of compiled item. The kind is used programmatically to associate behaviors and semantics
/// with the item.
/// </summary>
public abstract string Kind { get; }
/// <summary>
/// Gets a collection of arbitrary metadata associated with the item.
/// </summary>
/// <remarks>
/// For items loaded with the default implementation of <see cref="RazorCompiledItemLoader"/>, the
/// metadata collection will return all attributes defined on the <see cref="Type"/>.
/// </remarks>
public abstract IReadOnlyList<object> Metadata { get; }
/// <summary>
/// Gets the <see cref="Type"/> of the compiled item.
/// </summary>
public abstract Type Type { get; }
}
}

View File

@ -0,0 +1,60 @@
// 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.Hosting
{
/// <summary>
/// Specifies that an assembly contains a compiled Razor asset.
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
public sealed class RazorCompiledItemAttribute : Attribute
{
/// <summary>
/// Creates a new <see cref="RazorCompiledItemAttribute"/>.
/// </summary>
/// <param name="type">The <see cref="Type"/> of the compiled item.</param>
/// <param name="kind">
/// The kind of the compiled item. The kind is used programmatically to associate behaviors with the item.
/// </param>
/// <param name="identifier">
/// The identifier associated with the item. The identifier is used programmatically to locate
/// a specific item of a specific kind, and should be unique within the assembly.
/// </param>
public RazorCompiledItemAttribute(Type type, string kind, string identifier)
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
if (kind == null)
{
throw new ArgumentNullException(nameof(kind));
}
Type = type;
Kind = kind;
Identifier = identifier;
}
/// <summary>
/// Gets the kind of compiled item. The kind is used programmatically to associate behaviors and semantics
/// with the item.
/// </summary>
public string Kind { get; }
/// <summary>
/// Gets the identifier associated with the compiled item. The identifier is used programmatically to locate
/// a specific item of a specific kind and should be uniqure within the assembly.
/// </summary>
public string Identifier { get; }
/// <summary>
/// Gets the <see cref="Type"/> of the compiled item. The type should be contained in the assembly associated
/// with this instance of <see cref="RazorCompiledItemAttribute"/>.
/// </summary>
public Type Type { get; }
}
}

View File

@ -0,0 +1,30 @@
// 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 System.Linq;
namespace Microsoft.AspNetCore.Razor.Hosting
{
/// <summary>
/// Extension methods for <see cref="RazorCompiledItem"/>.
/// </summary>
public static class RazorCompiledItemExtensions
{
/// <summary>
/// Gets the list of <see cref="IRazorSourceChecksumMetadata"/> associated with <paramref name="item"/>.
/// </summary>
/// <param name="item">The <see cref="RazorCompiledItem"/>.</param>
/// <returns>A list of <see cref="IRazorSourceChecksumMetadata"/>.</returns>
public static IReadOnlyList<IRazorSourceChecksumMetadata> GetChecksumMetadata(this RazorCompiledItem item)
{
if (item == null)
{
throw new ArgumentNullException(nameof(item));
}
return item.Metadata.OfType<IRazorSourceChecksumMetadata>().ToArray();
}
}
}

View File

@ -0,0 +1,35 @@
// 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.Hosting
{
/// <summary>
/// Defines a key/value metadata pair for the decorated Razor type.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class RazorCompiledItemMetadataAttribute : Attribute
{
/// <summary>
/// Creates a new <see cref="RazorCompiledItemMetadataAttribute"/>.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
public RazorCompiledItemMetadataAttribute(string key, string value)
{
Key = key;
Value = value;
}
/// <summary>
/// Gets the key.
/// </summary>
public string Key { get; }
/// <summary>
/// Gets the value.
/// </summary>
public string Value { get; }
}
}

View File

@ -0,0 +1,38 @@
// 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.Hosting
{
/// <summary>
/// Specifies the name of a Razor configuration as defined by the Razor SDK.
/// </summary>
/// <remarks>
/// This attribute is applied to an application's entry point assembly by the Razor SDK during the build,
/// so that the Razor configuration can be loaded at runtime based on the settings provided by the project
/// file.
/// </remarks>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
public sealed class RazorConfigurationNameAttribute : Attribute
{
/// <summary>
/// Creates a new instance of <see cref="RazorConfigurationNameAttribute"/>.
/// </summary>
/// <param name="configurationName">The name of the Razor configuration.</param>
public RazorConfigurationNameAttribute(string configurationName)
{
if (configurationName == null)
{
throw new ArgumentNullException(nameof(configurationName));
}
ConfigurationName = configurationName;
}
/// <summary>
/// Gets the name of the Razor configuration.
/// </summary>
public string ConfigurationName { get; }
}
}

View File

@ -0,0 +1,50 @@
// 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.Hosting
{
/// <summary>
/// Specifies the name of a Razor extension as defined by the Razor SDK.
/// </summary>
/// <remarks>
/// This attribute is applied to an application's entry point assembly by the Razor SDK during the build,
/// so that the Razor configuration can be loaded at runtime based on the settings provided by the project
/// file.
/// </remarks>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
public sealed class RazorExtensionAssemblyNameAttribute : Attribute
{
/// <summary>
/// Creates a new instance of <see cref="RazorExtensionAssemblyNameAttribute"/>.
/// </summary>
/// <param name="extensionName">The name of the extension.</param>
/// <param name="assemblyName">The assembly name of the extension.</param>
public RazorExtensionAssemblyNameAttribute(string extensionName, string assemblyName)
{
if (extensionName == null)
{
throw new ArgumentNullException(nameof(extensionName));
}
if (assemblyName == null)
{
throw new ArgumentNullException(nameof(assemblyName));
}
ExtensionName = extensionName;
AssemblyName = assemblyName;
}
/// <summary>
/// Gets the assembly name of the extension.
/// </summary>
public string AssemblyName { get; }
/// <summary>
/// Gets the name of the extension.
/// </summary>
public string ExtensionName { get; }
}
}

View File

@ -0,0 +1,38 @@
// 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.Hosting
{
/// <summary>
/// Specifies the name of a Razor configuration as defined by the Razor SDK.
/// </summary>
/// <remarks>
/// This attribute is part of a set of metadata attributes that can be applied to an assembly at build
/// time by the Razor SDK. These attributes allow the Razor configuration to be loaded at runtime based
/// on the settings originally provided by the project file.
/// </remarks>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
public sealed class RazorLanguageVersionAttribute : Attribute
{
/// <summary>
/// Creates a new instance of <see cref="RazorLanguageVersionAttribute"/>.
/// </summary>
/// <param name="languageVersion">The language version of Razor</param>
public RazorLanguageVersionAttribute(string languageVersion)
{
if (languageVersion == null)
{
throw new ArgumentNullException(nameof(languageVersion));
}
LanguageVersion = languageVersion;
}
/// <summary>
/// Gets the Razor language version.
/// </summary>
public string LanguageVersion { get; }
}
}

View File

@ -0,0 +1,67 @@
// 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.Hosting
{
/// <summary>
/// Specifies the checksum of a source file that contributed to a compiled item.
/// </summary>
/// <remarks>
/// <para>
/// These attributes are added by the Razor infrastructure when generating code to assist runtime
/// implementations to determine the integrity of compiled items.
/// </para>
/// <para>
/// Runtime implementations should access the checksum metadata for an item using
/// <see cref="RazorCompiledItemExtensions.GetChecksumMetadata(RazorCompiledItem)"/>.
/// </para>
/// </remarks>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class RazorSourceChecksumAttribute : Attribute, IRazorSourceChecksumMetadata
{
/// <summary>
/// Creates a new <see cref="RazorSourceChecksumAttribute"/>.
/// </summary>
/// <param name="checksumAlgorithm">The algorithm used to create this checksum.</param>
/// <param name="checksum">The checksum as a string of hex-encoded bytes.</param>
/// <param name="identifier">The identifier associated with this thumbprint.</param>
public RazorSourceChecksumAttribute(string checksumAlgorithm, string checksum, string identifier)
{
if (checksumAlgorithm == null)
{
throw new ArgumentNullException(nameof(checksumAlgorithm));
}
if (checksum == null)
{
throw new ArgumentNullException(nameof(checksum));
}
if (identifier == null)
{
throw new ArgumentNullException(nameof(identifier));
}
ChecksumAlgorithm = checksumAlgorithm;
Checksum = checksum;
Identifier = identifier;
}
/// <summary>
/// Gets the checksum as string of hex-encoded bytes.
/// </summary>
public string Checksum { get; }
/// <summary>
/// Gets the name of the algorithm used to create this checksum.
/// </summary>
public string ChecksumAlgorithm { get; }
/// <summary>
/// Gets the identifier of the source file associated with this checksum.
/// </summary>
public string Identifier { get; }
}
}

View File

@ -0,0 +1,70 @@
// 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 System.Diagnostics;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
{
public class TagHelperExecutionContext
{
public TagHelperExecutionContext(
string tagName,
TagMode tagMode,
IDictionary<object, object> items,
string uniqueId,
Func<Task> executeChildContentAsync,
Action<HtmlEncoder> startTagHelperWritingScope,
Func<TagHelperContent> endTagHelperWritingScope)
{
}
public bool ChildContentRetrieved => false;
public IDictionary<object, object> Items { get; private set; }
public IList<ITagHelper> TagHelpers => null;
public TagHelperOutput Output { get; internal set; }
public TagHelperContext Context { get; }
public void Add(ITagHelper tagHelper)
{
}
public void AddHtmlAttribute(string name, object value, HtmlAttributeValueStyle valueStyle)
{
}
public void AddHtmlAttribute(TagHelperAttribute attribute)
{
}
public void AddTagHelperAttribute(string name, object value, HtmlAttributeValueStyle valueStyle)
{
}
public void AddTagHelperAttribute(TagHelperAttribute attribute)
{
}
public void Reinitialize(
string tagName,
TagMode tagMode,
IDictionary<object, object> items,
string uniqueId,
Func<Task> executeChildContentAsync)
{
}
public Task SetOutputContentAsync()
{
throw null;
}
}
}

View File

@ -0,0 +1,18 @@
// 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 System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
{
public class TagHelperRunner
{
public Task RunAsync(TagHelperExecutionContext executionContext)
{
throw null;
}
}
}

View File

@ -0,0 +1,34 @@
// 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 System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
{
public class TagHelperScopeManager
{
public TagHelperScopeManager(
Action<HtmlEncoder> startTagHelperWritingScope,
Func<TagHelperContent> endTagHelperWritingScope)
{
}
public TagHelperExecutionContext Begin(
string tagName,
TagMode tagMode,
string uniqueId,
Func<Task> executeChildContentAsync)
{
throw null;
}
public TagHelperExecutionContext End()
{
throw null;
}
}
}

View File

@ -0,0 +1,92 @@
// 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.TagHelpers
{
/// <summary>
/// Used to override an <see cref="ITagHelper"/> property's HTML attribute name.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class HtmlAttributeNameAttribute : Attribute
{
private string _dictionaryAttributePrefix;
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlAttributeNameAttribute"/> class with <see cref="Name"/>
/// equal to <c>null</c>.
/// </summary>
/// <remarks>
/// Associated property must not have a public setter and must be compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>.
/// </remarks>
public HtmlAttributeNameAttribute()
{
}
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlAttributeNameAttribute"/> class.
/// </summary>
/// <param name="name">
/// HTML attribute name for the associated property. Must be <c>null</c> or empty if associated property does
/// not have a public setter and is compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>. Otherwise must not be <c>null</c> or empty.
/// </param>
public HtmlAttributeNameAttribute(string name)
{
Name = name;
}
/// <summary>
/// HTML attribute name of the associated property.
/// </summary>
/// <value>
/// <c>null</c> or empty if and only if associated property does not have a public setter and is compatible
/// with <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>.
/// </value>
public string Name { get; }
/// <summary>
/// Gets or sets the prefix used to match HTML attribute names. Matching attributes are added to the
/// associated property (an <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>).
/// </summary>
/// <remarks>
/// If non-<c>null</c> associated property must be compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>.
/// </remarks>
/// <value>
/// <para>
/// If associated property is compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>, default value is <c>Name + "-"</c>.
/// <see cref="Name"/> must not be <c>null</c> or empty in this case.
/// </para>
/// <para>
/// Otherwise default value is <c>null</c>.
/// </para>
/// </value>
public string DictionaryAttributePrefix
{
get
{
return _dictionaryAttributePrefix;
}
set
{
_dictionaryAttributePrefix = value;
DictionaryAttributePrefixSet = true;
}
}
/// <summary>
/// Gets an indication whether <see cref="DictionaryAttributePrefix"/> has been set. Used to distinguish an
/// uninitialized <see cref="DictionaryAttributePrefix"/> value from an explicit <c>null</c> setting.
/// </summary>
/// <value><c>true</c> if <see cref="DictionaryAttributePrefix"/> was set. <c>false</c> otherwise.</value>
public bool DictionaryAttributePrefixSet { get; private set; }
}
}

View File

@ -0,0 +1,21 @@
// 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.TagHelpers
{
/// <summary>
/// Indicates the associated <see cref="ITagHelper"/> property should not be bound to HTML attributes.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class HtmlAttributeNotBoundAttribute : Attribute
{
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlAttributeNotBoundAttribute"/> class.
/// </summary>
public HtmlAttributeNotBoundAttribute()
{
}
}
}

View File

@ -0,0 +1,13 @@
// 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.
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public enum HtmlAttributeValueStyle
{
DoubleQuotes,
SingleQuotes,
NoQuotes,
Minimized,
}
}

View File

@ -0,0 +1,86 @@
// 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.TagHelpers
{
/// <summary>
/// Provides an <see cref="ITagHelper"/>'s target.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public sealed class HtmlTargetElementAttribute : Attribute
{
public const string ElementCatchAllTarget = "*";
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlTargetElementAttribute"/> class that targets all HTML
/// elements with the required <see cref="Attributes"/>.
/// </summary>
/// <remarks><see cref="Tag"/> is set to <c>*</c>.</remarks>
public HtmlTargetElementAttribute()
: this(ElementCatchAllTarget)
{
}
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlTargetElementAttribute"/> class with the given
/// <paramref name="tag"/> as its <see cref="Tag"/> value.
/// </summary>
/// <param name="tag">
/// The HTML tag the <see cref="ITagHelper"/> targets.
/// </param>
/// <remarks>A <c>*</c> <paramref name="tag"/> value indicates this <see cref="ITagHelper"/>
/// targets all HTML elements with the required <see cref="Attributes"/>.</remarks>
public HtmlTargetElementAttribute(string tag)
{
Tag = tag;
}
/// <summary>
/// The HTML tag the <see cref="ITagHelper"/> targets. A <c>*</c> value indicates this <see cref="ITagHelper"/>
/// targets all HTML elements with the required <see cref="Attributes"/>.
/// </summary>
public string Tag { get; }
/// <summary>
/// A comma-separated <see cref="string"/> of attribute selectors the HTML element must match for the
/// <see cref="ITagHelper"/> to run. <c>*</c> at the end of an attribute name acts as a prefix match. A value
/// surrounded by square brackets is handled as a CSS attribute value selector. Operators <c>^=</c>, <c>$=</c> and
/// <c>=</c> are supported e.g. <c>"name"</c>, <c>"[name]"</c>, <c>"[name=value]"</c>, <c>"[ name ^= 'value' ]"</c>.
/// </summary>
public string Attributes { get; set; }
/// <summary>
/// The expected tag structure. Defaults to <see cref="TagStructure.Unspecified"/>.
/// </summary>
/// <remarks>
/// If <see cref="TagStructure.Unspecified"/> and no other tag helpers applying to the same element specify
/// their <see cref="TagStructure"/> the <see cref="TagStructure.NormalOrSelfClosing"/> behavior is used:
/// <para>
/// <code>
/// &lt;my-tag-helper&gt;&lt;/my-tag-helper&gt;
/// &lt;!-- OR --&gt;
/// &lt;my-tag-helper /&gt;
/// </code>
/// Otherwise, if another tag helper applying to the same element does specify their behavior, that behavior
/// is used.
/// </para>
/// <para>
/// If <see cref="TagStructure.WithoutEndTag"/> HTML elements can be written in the following formats:
/// <code>
/// &lt;my-tag-helper&gt;
/// &lt;!-- OR --&gt;
/// &lt;my-tag-helper /&gt;
/// </code>
/// </para>
/// </remarks>
public TagStructure TagStructure { get; set; }
/// <summary>
/// The required HTML element name of the direct parent. A <c>null</c> value indicates any HTML element name is
/// allowed.
/// </summary>
public string ParentTag { get; set; }
}
}

View File

@ -0,0 +1,13 @@
// 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.
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Contract used to filter matching HTML elements.
/// Marker interface for <see cref="TagHelper"/>s.
/// </summary>
public interface ITagHelper : ITagHelperComponent
{
}
}

View File

@ -0,0 +1,41 @@
// 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.Threading.Tasks;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Contract used to modify an HTML element.
/// </summary>
public interface ITagHelperComponent
{
/// <summary>
/// When a set of <see cref="ITagHelperComponent"/>s are executed, their <see cref="Init(TagHelperContext)"/>'s
/// are first invoked in the specified <see cref="Order"/>; then their
/// <see cref="ProcessAsync(TagHelperContext, TagHelperOutput)"/>'s are invoked in the specified
/// <see cref="Order"/>. Lower values are executed first.
/// </summary>
int Order { get; }
/// <summary>
/// Initializes the <see cref="ITagHelperComponent"/> with the given <paramref name="context"/>. Additions to
/// <see cref="TagHelperContext.Items"/> should be done within this method to ensure they're added prior to
/// executing the children.
/// </summary>
/// <param name="context">Contains information associated with the current HTML tag.</param>
/// <remarks>When more than one <see cref="ITagHelperComponent"/> runs on the same element,
/// <see cref="M:TagHelperOutput.GetChildContentAsync"/> may be invoked prior to <see cref="ProcessAsync"/>.
/// </remarks>
void Init(TagHelperContext context);
/// <summary>
/// Asynchronously executes the <see cref="ITagHelperComponent"/> with the given <paramref name="context"/> and
/// <paramref name="output"/>.
/// </summary>
/// <param name="context">Contains information associated with the current HTML tag.</param>
/// <param name="output">A stateful HTML element used to generate an HTML tag.</param>
/// <returns>A <see cref="Task"/> that on completion updates the <paramref name="output"/>.</returns>
Task ProcessAsync(TagHelperContext context, TagHelperOutput output);
}
}

View File

@ -0,0 +1,35 @@
// 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.TagHelpers
{
/// <summary>
/// Provides a hint of the <see cref="ITagHelper"/>'s output element.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class OutputElementHintAttribute : Attribute
{
/// <summary>
/// Instantiates a new instance of the <see cref="OutputElementHintAttribute"/> class.
/// </summary>
/// <param name="outputElement">
/// The HTML element the <see cref="ITagHelper"/> may output.
/// </param>
public OutputElementHintAttribute(string outputElement)
{
if (outputElement == null)
{
throw new ArgumentNullException(nameof(outputElement));
}
OutputElement = outputElement;
}
/// <summary>
/// The HTML element the <see cref="ITagHelper"/> may output.
/// </summary>
public string OutputElement { get; }
}
}

View File

@ -0,0 +1,190 @@
// 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 System.Collections.ObjectModel;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// A read-only collection of <see cref="TagHelperAttribute"/>s.
/// </summary>
public abstract class ReadOnlyTagHelperAttributeList : ReadOnlyCollection<TagHelperAttribute>
{
private static readonly IReadOnlyList<TagHelperAttribute> EmptyList = new TagHelperAttribute[0];
/// <summary>
/// Instantiates a new instance of <see cref="ReadOnlyTagHelperAttributeList"/> with an empty
/// collection.
/// </summary>
protected ReadOnlyTagHelperAttributeList()
: base(new List<TagHelperAttribute>())
{
}
/// <summary>
/// Instantiates a new instance of <see cref="ReadOnlyTagHelperAttributeList"/> with the specified
/// <paramref name="attributes"/>.
/// </summary>
/// <param name="attributes">The collection to wrap.</param>
public ReadOnlyTagHelperAttributeList(IList<TagHelperAttribute> attributes)
: base(attributes)
{
}
/// <summary>
/// Gets the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/>.
/// </summary>
/// <param name="name">
/// The <see cref="TagHelperAttribute.Name"/> of the <see cref="TagHelperAttribute"/> to get.
/// </param>
/// <returns>The first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/>.
/// </returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public TagHelperAttribute this[string name]
{
get
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
// Perf: Avoid allocating enumerator
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(name, Items[i]))
{
return Items[i];
}
}
return null;
}
}
/// <summary>
/// Determines whether a <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/> exists in the collection.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the
/// <see cref="TagHelperAttribute"/> to get.</param>
/// <returns>
/// <c>true</c> if a <see cref="TagHelperAttribute"/> with the same
/// <see cref="TagHelperAttribute.Name"/> exists in the collection; otherwise, <c>false</c>.
/// </returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool ContainsName(string name)
{
return this[name] != null;
}
/// <summary>
/// Retrieves the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/>.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the
/// <see cref="TagHelperAttribute"/> to get.</param>
/// <param name="attribute">When this method returns, the first <see cref="TagHelperAttribute"/> with
/// <see cref="TagHelperAttribute.Name"/> matching <paramref name="name"/>, if found; otherwise,
/// <c>null</c>.</param>
/// <returns><c>true</c> if a <see cref="TagHelperAttribute"/> with the same
/// <see cref="TagHelperAttribute.Name"/> exists in the collection; otherwise, <c>false</c>.</returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool TryGetAttribute(string name, out TagHelperAttribute attribute)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
attribute = this[name];
return attribute != null;
}
/// <summary>
/// Retrieves <see cref="TagHelperAttribute"/>s in the collection with
/// <see cref="TagHelperAttribute.Name"/> matching <paramref name="name"/>.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the
/// <see cref="TagHelperAttribute"/>s to get.</param>
/// <param name="attributes">When this method returns, the <see cref="TagHelperAttribute"/>s with
/// <see cref="TagHelperAttribute.Name"/> matching <paramref name="name"/>.</param>
/// <returns><c>true</c> if at least one <see cref="TagHelperAttribute"/> with the same
/// <see cref="TagHelperAttribute.Name"/> exists in the collection; otherwise, <c>false</c>.</returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool TryGetAttributes(string name, out IReadOnlyList<TagHelperAttribute> attributes)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
// Perf: Avoid allocating enumerator
List<TagHelperAttribute> matchedAttributes = null;
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(name, Items[i]))
{
if (matchedAttributes == null)
{
matchedAttributes = new List<TagHelperAttribute>();
}
matchedAttributes.Add(Items[i]);
}
}
attributes = matchedAttributes ?? EmptyList;
return matchedAttributes != null;
}
/// <summary>
/// Searches for a <see cref="TagHelperAttribute"/> who's <see cref="TagHelperAttribute.Name"/>
/// case-insensitively matches <paramref name="name"/> and returns the zero-based index of the first
/// occurrence.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> to locate in the collection.</param>
/// <returns>The zero-based index of the first matching <see cref="TagHelperAttribute"/> within the collection,
/// if found; otherwise, -1.</returns>
public int IndexOfName(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(name, Items[i]))
{
return i;
}
}
return -1;
}
/// <summary>
/// Determines if the specified <paramref name="attribute"/> has the same name as <paramref name="name"/>.
/// </summary>
/// <param name="name">The value to compare against <paramref name="attribute"/>s
/// <see cref="TagHelperAttribute.Name"/>.</param>
/// <param name="attribute">The attribute to compare against.</param>
/// <returns><c>true</c> if <paramref name="name"/> case-insensitively matches <paramref name="attribute"/>s
/// <see cref="TagHelperAttribute.Name"/>.</returns>
protected static bool NameEquals(string name, TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
return string.Equals(name, attribute.Name, StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@ -0,0 +1,42 @@
// 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;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Restricts children of the <see cref="ITagHelper"/>'s element.
/// </summary>
/// <remarks>Combining this attribute with a <see cref="HtmlTargetElementAttribute"/> that specifies its
/// <see cref="HtmlTargetElementAttribute.TagStructure"/> as <see cref="TagStructure.WithoutEndTag"/> will result
/// in this attribute being ignored.</remarks>
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class RestrictChildrenAttribute : Attribute
{
/// <summary>
/// Instantiates a new instance of the <see cref="RestrictChildrenAttribute"/> class.
/// </summary>
/// <param name="childTag">
/// The tag name of an element allowed as a child.
/// </param>
/// <param name="childTags">
/// Additional names of elements allowed as children.
/// </param>
public RestrictChildrenAttribute(string childTag, params string[] childTags)
{
var concatenatedNames = new string[1 + childTags.Length];
concatenatedNames[0] = childTag;
childTags.CopyTo(concatenatedNames, 1);
ChildTags = concatenatedNames;
}
/// <summary>
/// Get the names of elements allowed as children.
/// </summary>
public IEnumerable<string> ChildTags { get; }
}
}

View File

@ -0,0 +1,26 @@
// 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.Threading.Tasks;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public abstract class TagHelper : ITagHelper
{
public virtual int Order { get; } = 0;
public virtual void Init(TagHelperContext context)
{
}
public virtual void Process(TagHelperContext context, TagHelperOutput output)
{
}
public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
Process(context, output);
return Task.CompletedTask;
}
}
}

View File

@ -0,0 +1,43 @@
// 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.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Html;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public class TagHelperAttribute : IHtmlContentContainer
{
public TagHelperAttribute(string name)
{
}
public TagHelperAttribute(string name, object value)
{
}
public TagHelperAttribute(string name, object value, HtmlAttributeValueStyle valueStyle)
{
}
public string Name { get; }
public object Value { get; }
public HtmlAttributeValueStyle ValueStyle { get; }
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
}
public void CopyTo(IHtmlContentBuilder destination)
{
}
public void MoveTo(IHtmlContentBuilder destination)
{
}
}
}

View File

@ -0,0 +1,230 @@
// 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;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// A collection of <see cref="TagHelperAttribute"/>s.
/// </summary>
public class TagHelperAttributeList : ReadOnlyTagHelperAttributeList, IList<TagHelperAttribute>
{
/// <summary>
/// Instantiates a new instance of <see cref="TagHelperAttributeList"/> with an empty collection.
/// </summary>
public TagHelperAttributeList()
: base()
{
}
/// <summary>
/// Instantiates a new instance of <see cref="TagHelperAttributeList"/> with the specified
/// <paramref name="attributes"/>.
/// </summary>
/// <param name="attributes">The collection to wrap.</param>
public TagHelperAttributeList(IEnumerable<TagHelperAttribute> attributes)
: base (new List<TagHelperAttribute>(attributes))
{
if (attributes == null)
{
throw new ArgumentNullException(nameof(attributes));
}
}
/// <summary>
/// Instantiates a new instance of <see cref="TagHelperAttributeList"/> with the specified
/// <paramref name="attributes"/>.
/// </summary>
/// <param name="attributes">The collection to wrap.</param>
public TagHelperAttributeList(List<TagHelperAttribute> attributes)
: base(attributes)
{
if (attributes == null)
{
throw new ArgumentNullException(nameof(attributes));
}
}
/// <inheritdoc />
/// <remarks>
/// <paramref name="value"/>'s <see cref="TagHelperAttribute.Name"/> must not be <c>null</c>.
/// </remarks>
public new TagHelperAttribute this[int index]
{
get
{
return base[index];
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
Items[index] = value;
}
}
/// <summary>
/// Replaces the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/> matching
/// <paramref name="name"/> and removes any additional matching <see cref="TagHelperAttribute"/>s. If a
/// matching <see cref="TagHelperAttribute"/> is not found, adds a <see cref="TagHelperAttribute"/> with
/// <paramref name="name"/> and <paramref name="value"/> to the end of the collection.</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>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public void SetAttribute(string name, object value)
{
var attribute = new TagHelperAttribute(name, value);
SetAttribute(attribute);
}
/// <summary>
/// Replaces the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/> matching
/// <paramref name="attribute"/>'s <see cref="TagHelperAttribute.Name"/> and removes any additional matching
/// <see cref="TagHelperAttribute"/>s. If a matching <see cref="TagHelperAttribute"/> is not found, adds the
/// specified <paramref name="attribute"/> to the end of the collection.
/// </summary>
/// <param name="attribute">
/// The <see cref="TagHelperAttribute"/> to set.
/// </param>
/// <remarks><paramref name="attribute"/>'s <see cref="TagHelperAttribute.Name"/> is compared
/// case-insensitively.</remarks>
public void SetAttribute(TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
var attributeReplaced = false;
// Perf: Avoid allocating enumerator
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(attribute.Name, Items[i]))
{
// We replace the first attribute with the provided attribute, remove all the rest.
if (!attributeReplaced)
{
// We replace the first attribute we find with the same name.
Items[i] = attribute;
attributeReplaced = true;
}
else
{
Items.RemoveAt(i--);
}
}
}
// If we didn't replace an attribute value we should add value to the end of the collection.
if (!attributeReplaced)
{
Add(attribute);
}
}
/// <inheritdoc />
bool ICollection<TagHelperAttribute>.IsReadOnly => false;
/// <summary>
/// Adds a <see cref="TagHelperAttribute"/> to the end of the collection with the specified
/// <paramref name="name"/> and <paramref name="value"/>.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the attribute to add.</param>
/// <param name="value">The <see cref="TagHelperAttribute.Value"/> of the attribute to add.</param>
public void Add(string name, object value)
{
var attribute = new TagHelperAttribute(name, value);
Items.Add(attribute);
}
/// <inheritdoc />
public void Add(TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
Items.Add(attribute);
}
/// <inheritdoc />
public void Insert(int index, TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
Items.Insert(index, attribute);
}
/// <inheritdoc />
/// <remarks>
/// <paramref name="attribute"/>s <see cref="TagHelperAttribute.Name"/> is compared case-insensitively.
/// </remarks>
public bool Remove(TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
return Items.Remove(attribute);
}
/// <inheritdoc />
public void RemoveAt(int index)
{
Items.RemoveAt(index);
}
/// <summary>
/// Removes all <see cref="TagHelperAttribute"/>s with <see cref="TagHelperAttribute.Name"/> matching
/// <paramref name="name"/>.
/// </summary>
/// <param name="name">
/// The <see cref="TagHelperAttribute.Name"/> of <see cref="TagHelperAttribute"/>s to remove.
/// </param>
/// <returns>
/// <c>true</c> if at least 1 <see cref="TagHelperAttribute"/> was removed; otherwise, <c>false</c>.
/// </returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool RemoveAll(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
// Perf: Avoid allocating enumerator
var removedAtLeastOne = false;
for (var i = Items.Count - 1; i >= 0; i--)
{
if (NameEquals(name, Items[i]))
{
Items.RemoveAt(i);
removedAtLeastOne = true;
}
}
return removedAtLeastOne;
}
/// <inheritdoc />
public void Clear()
{
Items.Clear();
}
}
}

View File

@ -0,0 +1,39 @@
// 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.Threading.Tasks;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// An abstract base class for <see cref="ITagHelperComponent"/>.
/// </summary>
public abstract class TagHelperComponent : ITagHelperComponent
{
/// <inheritdoc />
/// <remarks>Default order is <c>0</c>.</remarks>
public virtual int Order => 0;
/// <inheritdoc />
public virtual void Init(TagHelperContext context)
{
}
/// <summary>
/// Synchronously executes the <see cref="ITagHelperComponent"/> with the given <paramref name="context"/> and
/// <paramref name="output"/>.
/// </summary>
/// <param name="context">Contains information associated with the current HTML tag.</param>
/// <param name="output">A stateful HTML element used to generate an HTML tag.</param>
public virtual void Process(TagHelperContext context, TagHelperOutput output)
{
}
/// <inheritdoc />
public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
Process(context, output);
return Task.CompletedTask;
}
}
}

View File

@ -0,0 +1,179 @@
// 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.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Html;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Abstract class used to buffer content returned by <see cref="ITagHelper"/>s.
/// </summary>
public abstract class TagHelperContent : IHtmlContentBuilder
{
/// <summary>
/// Gets a value indicating whether the content was modified.
/// </summary>
public abstract bool IsModified { get; }
/// <summary>
/// Gets a value indicating whether the content is empty or whitespace.
/// </summary>
public abstract bool IsEmptyOrWhiteSpace { get; }
/// <summary>
/// Sets the content.
/// </summary>
/// <param name="htmlContent">The <see cref="IHtmlContent"/> that replaces the content.</param>
/// <returns>A reference to this instance after the set operation has completed.</returns>
public TagHelperContent SetHtmlContent(IHtmlContent htmlContent)
{
HtmlContentBuilderExtensions.SetHtmlContent(this, htmlContent);
return this;
}
/// <summary>
/// Sets the content.
/// </summary>
/// <param name="unencoded">
/// The <see cref="string"/> that replaces the content. The value is assume to be unencoded
/// as-provided and will be HTML encoded before being written.
/// </param>
/// <returns>A reference to this instance after the set operation has completed.</returns>
public TagHelperContent SetContent(string unencoded)
{
HtmlContentBuilderExtensions.SetContent(this, unencoded);
return this;
}
/// <summary>
/// Sets the content.
/// </summary>
/// <param name="encoded">
/// The <see cref="string"/> that replaces the content. The value is assume to be HTML encoded
/// as-provided and no further encoding will be performed.
/// </param>
/// <returns>A reference to this instance after the set operation has completed.</returns>
public TagHelperContent SetHtmlContent(string encoded)
{
HtmlContentBuilderExtensions.SetHtmlContent(this, encoded);
return this;
}
/// <summary>
/// Appends <paramref name="unencoded"/> to the existing content.
/// </summary>
/// <param name="unencoded">The <see cref="string"/> to be appended.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public abstract TagHelperContent Append(string unencoded);
/// <summary>
/// Appends <paramref name="htmlContent"/> to the existing content.
/// </summary>
/// <param name="htmlContent">The <see cref="IHtmlContent"/> to be appended.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public abstract TagHelperContent AppendHtml(IHtmlContent htmlContent);
/// <summary>
/// Appends <paramref name="encoded"/> to the existing content. <paramref name="encoded"/> is assumed
/// to be an HTML encoded <see cref="string"/> and no further encoding will be performed.
/// </summary>
/// <param name="encoded">The <see cref="string"/> to be appended.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public abstract TagHelperContent AppendHtml(string encoded);
/// <summary>
/// Appends the specified <paramref name="format"/> to the existing content after
/// replacing each format item with the HTML encoded <see cref="string"/> representation of the
/// corresponding item in the <paramref name="args"/> array.
/// </summary>
/// <param name="format">
/// The composite format <see cref="string"/> (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx).
/// </param>
/// <param name="args">The object array to format.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public TagHelperContent AppendFormat(string format, params object[] args)
{
HtmlContentBuilderExtensions.AppendFormat(this, null, format, args);
return this;
}
/// <summary>
/// Appends the specified <paramref name="format"/> to the existing content with information from the
/// <paramref name="provider"/> after replacing each format item with the HTML encoded <see cref="string"/>
/// representation of the corresponding item in the <paramref name="args"/> array.
/// </summary>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="format">
/// The composite format <see cref="string"/> (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx).
/// </param>
/// <param name="args">The object array to format.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public TagHelperContent AppendFormat(IFormatProvider provider, string format, params object[] args)
{
HtmlContentBuilderExtensions.AppendFormat(this, provider, format, args);
return this;
}
/// <summary>
/// Clears the content.
/// </summary>
/// <returns>A reference to this instance after the clear operation has completed.</returns>
public abstract TagHelperContent Clear();
/// <summary>
/// Clears the <see cref="TagHelperContent"/>, so it can be reused.
/// </summary>
/// <remarks>This method does more than what <see cref="Clear"/> does. It also resets the
/// <see cref="IsModified"/> flag.</remarks>
public abstract void Reinitialize();
/// <inheritdoc />
public abstract void CopyTo(IHtmlContentBuilder destination);
/// <inheritdoc />
public abstract void MoveTo(IHtmlContentBuilder destination);
/// <summary>
/// Gets the content.
/// </summary>
/// <returns>A <see cref="string"/> containing the content.</returns>
public abstract string GetContent();
/// <summary>
/// Gets the content.
/// </summary>
/// <param name="encoder">The <see cref="HtmlEncoder"/>.</param>
/// <returns>A <see cref="string"/> containing the content.</returns>
public abstract string GetContent(HtmlEncoder encoder);
/// <inheritdoc />
public abstract void WriteTo(TextWriter writer, HtmlEncoder encoder);
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.AppendHtml(IHtmlContent content)
{
return AppendHtml(content);
}
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.Append(string unencoded)
{
return Append(unencoded);
}
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.AppendHtml(string encoded)
{
return AppendHtml(encoded);
}
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.Clear()
{
return Clear();
}
}
}

View File

@ -0,0 +1,118 @@
// 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;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Contains information related to the execution of <see cref="ITagHelper"/>s.
/// </summary>
public class TagHelperContext
{
private readonly TagHelperAttributeList _allAttributes;
/// <summary>
/// Instantiates a new <see cref="TagHelperContext"/>.
/// </summary>
/// <param name="tagName">The parsed HTML tag name of the element.</param>
/// <param name="allAttributes">Every attribute associated with the current HTML element.</param>
/// <param name="items">Collection of items used to communicate with other <see cref="ITagHelper"/>s.</param>
/// <param name="uniqueId">The unique identifier for the source element this <see cref="TagHelperContext" />
/// applies to.</param>
public TagHelperContext(
string tagName,
TagHelperAttributeList allAttributes,
IDictionary<object, object> items,
string uniqueId) : this(allAttributes, items, uniqueId)
{
if (tagName == null)
{
throw new ArgumentNullException(nameof(tagName));
}
TagName = tagName;
}
/// <summary>
/// Instantiates a new <see cref="TagHelperContext"/>.
/// </summary>
/// <param name="allAttributes">Every attribute associated with the current HTML element.</param>
/// <param name="items">Collection of items used to communicate with other <see cref="ITagHelper"/>s.</param>
/// <param name="uniqueId">The unique identifier for the source element this <see cref="TagHelperContext" />
/// applies to.</param>
public TagHelperContext(
TagHelperAttributeList allAttributes,
IDictionary<object, object> items,
string uniqueId)
{
if (items == null)
{
throw new ArgumentNullException(nameof(items));
}
if (uniqueId == null)
{
throw new ArgumentNullException(nameof(uniqueId));
}
if (allAttributes == null)
{
throw new ArgumentNullException(nameof(allAttributes));
}
_allAttributes = allAttributes;
Items = items;
UniqueId = uniqueId;
}
/// <summary>
/// The parsed HTML tag name of the element.
/// </summary>
public string TagName { get; private set; }
/// <summary>
/// Every attribute associated with the current HTML element.
/// </summary>
public ReadOnlyTagHelperAttributeList AllAttributes => _allAttributes;
/// <summary>
/// Gets the collection of items used to communicate with other <see cref="ITagHelper"/>s.
/// </summary>
/// <remarks>
/// This <see cref="IDictionary{Object, Object}" /> is copy-on-write in order to ensure items added to this
/// collection are visible only to other <see cref="ITagHelper"/>s targeting child elements.
/// </remarks>
public IDictionary<object, object> Items { get; private set; }
/// <summary>
/// An identifier unique to the HTML element this context is for.
/// </summary>
public string UniqueId { get; private set; }
/// <summary>
/// Clears the <see cref="TagHelperContext"/> and updates its state with the provided values.
/// </summary>
/// <param name="tagName">The HTML tag name to use.</param>
/// <param name="items">The <see cref="IDictionary{Object, Object}"/> to use.</param>
/// <param name="uniqueId">The unique id to use.</param>
public void Reinitialize(string tagName, IDictionary<object, object> items, string uniqueId)
{
TagName = tagName;
Reinitialize(items, uniqueId);
}
/// <summary>
/// Clears the <see cref="TagHelperContext"/> and updates its state with the provided values.
/// </summary>
/// <param name="items">The <see cref="IDictionary{Object, Object}"/> to use.</param>
/// <param name="uniqueId">The unique id to use.</param>
public void Reinitialize(IDictionary<object, object> items, string uniqueId)
{
_allAttributes.Clear();
Items = items;
UniqueId = uniqueId;
}
}
}

View File

@ -0,0 +1,79 @@
// 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.IO;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public class TagHelperOutput : IHtmlContentContainer
{
public TagHelperOutput(
string tagName,
TagHelperAttributeList attributes,
Func<bool, HtmlEncoder, Task<TagHelperContent>> getChildContentAsync)
{
}
public string TagName { get; set; }
public TagHelperContent PreElement => null;
public TagHelperContent PreContent => null;
public TagHelperContent Content => null;
public TagHelperContent PostContent => null;
public TagHelperContent PostElement => null;
public bool IsContentModified => true;
public TagMode TagMode { get; set; }
public TagHelperAttributeList Attributes { get; }
public void Reinitialize(string tagName, TagMode tagMode)
{
}
public void SuppressOutput()
{
}
public Task<TagHelperContent> GetChildContentAsync()
{
throw null;
}
public Task<TagHelperContent> GetChildContentAsync(bool useCachedResult)
{
throw null;
}
public Task<TagHelperContent> GetChildContentAsync(HtmlEncoder encoder)
{
throw null;
}
public Task<TagHelperContent> GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder)
{
throw null;
}
void IHtmlContentContainer.CopyTo(IHtmlContentBuilder destination)
{
}
void IHtmlContentContainer.MoveTo(IHtmlContentBuilder destination)
{
}
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
}
}
}

View File

@ -0,0 +1,26 @@
// 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.
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// The mode in which an element should render.
/// </summary>
public enum TagMode
{
/// <summary>
/// Include both start and end tags.
/// </summary>
StartTagAndEndTag,
/// <summary>
/// A self-closed tag.
/// </summary>
SelfClosing,
/// <summary>
/// Only a start tag.
/// </summary>
StartTagOnly
}
}

View File

@ -0,0 +1,28 @@
// 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.
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// The structure the element should be written in.
/// </summary>
public enum TagStructure
{
/// <summary>
/// If no other tag helper applies to the same element and specifies a <see cref="TagStructure"/>,
/// <see cref="NormalOrSelfClosing"/> will be used.
/// </summary>
Unspecified,
/// <summary>
/// Element can be written as &lt;my-tag-helper&gt;&lt;/my-tag-helper&gt; or &lt;my-tag-helper /&gt;.
/// </summary>
NormalOrSelfClosing,
/// <summary>
/// Element can be written as &lt;my-tag-helper&gt; or &lt;my-tag-helper /&gt;.
/// </summary>
/// <remarks>Elements with a <see cref="WithoutEndTag"/> structure will never have any content.</remarks>
WithoutEndTag
}
}

View File

@ -6,10 +6,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="$(MicrosoftAspNetCoreHtmlAbstractionsPackageVersion)" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(SystemDiagnosticsDiagnosticSourcePackageVersion)" />
</ItemGroup>

View File

@ -0,0 +1,54 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Hosting
{
internal class DefaultRazorCompiledItem : RazorCompiledItem
{
private object[] _metadata;
public DefaultRazorCompiledItem(Type type, string kind, string identifier)
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
if (kind == null)
{
throw new ArgumentNullException(nameof(kind));
}
if (identifier == null)
{
throw new ArgumentNullException(nameof(identifier));
}
Type = type;
Kind = kind;
Identifier = identifier;
}
public override string Identifier { get; }
public override string Kind { get; }
public override IReadOnlyList<object> Metadata
{
get
{
if (_metadata == null)
{
_metadata = Type.GetCustomAttributes(inherit: true);
}
return _metadata;
}
}
public override Type Type { get; }
}
}

View File

@ -0,0 +1,26 @@
// 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.
namespace Microsoft.AspNetCore.Razor.Hosting
{
/// <summary>
/// A metadata object containing the checksum of a source file that contributed to a compiled item.
/// </summary>
public interface IRazorSourceChecksumMetadata
{
/// <summary>
/// Gets the checksum as string of hex-encoded bytes.
/// </summary>
string Checksum { get; }
/// <summary>
/// Gets the name of the algorithm used to create this checksum.
/// </summary>
string ChecksumAlgorithm { get; }
/// <summary>
/// Gets the identifier of the source file associated with this checksum.
/// </summary>
string Identifier { get; }
}
}

View File

@ -0,0 +1,40 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Hosting
{
/// <summary>
/// Identifies a compiled item that can be identified and loaded.
/// </summary>
public abstract class RazorCompiledItem
{
/// <summary>
/// Gets the identifier associated with the compiled item. The identifier is used programmatically to locate
/// a specific item of a specific kind and should be uniqure within the assembly.
/// </summary>
public abstract string Identifier { get; }
/// <summary>
/// Gets the kind of compiled item. The kind is used programmatically to associate behaviors and semantics
/// with the item.
/// </summary>
public abstract string Kind { get; }
/// <summary>
/// Gets a collection of arbitrary metadata associated with the item.
/// </summary>
/// <remarks>
/// For items loaded with the default implementation of <see cref="RazorCompiledItemLoader"/>, the
/// metadata collection will return all attributes defined on the <see cref="Type"/>.
/// </remarks>
public abstract IReadOnlyList<object> Metadata { get; }
/// <summary>
/// Gets the <see cref="Type"/> of the compiled item.
/// </summary>
public abstract Type Type { get; }
}
}

View File

@ -0,0 +1,60 @@
// 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.Hosting
{
/// <summary>
/// Specifies that an assembly contains a compiled Razor asset.
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
public sealed class RazorCompiledItemAttribute : Attribute
{
/// <summary>
/// Creates a new <see cref="RazorCompiledItemAttribute"/>.
/// </summary>
/// <param name="type">The <see cref="Type"/> of the compiled item.</param>
/// <param name="kind">
/// The kind of the compiled item. The kind is used programmatically to associate behaviors with the item.
/// </param>
/// <param name="identifier">
/// The identifier associated with the item. The identifier is used programmatically to locate
/// a specific item of a specific kind, and should be unique within the assembly.
/// </param>
public RazorCompiledItemAttribute(Type type, string kind, string identifier)
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
if (kind == null)
{
throw new ArgumentNullException(nameof(kind));
}
Type = type;
Kind = kind;
Identifier = identifier;
}
/// <summary>
/// Gets the kind of compiled item. The kind is used programmatically to associate behaviors and semantics
/// with the item.
/// </summary>
public string Kind { get; }
/// <summary>
/// Gets the identifier associated with the compiled item. The identifier is used programmatically to locate
/// a specific item of a specific kind and should be uniqure within the assembly.
/// </summary>
public string Identifier { get; }
/// <summary>
/// Gets the <see cref="Type"/> of the compiled item. The type should be contained in the assembly associated
/// with this instance of <see cref="RazorCompiledItemAttribute"/>.
/// </summary>
public Type Type { get; }
}
}

View File

@ -0,0 +1,30 @@
// 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 System.Linq;
namespace Microsoft.AspNetCore.Razor.Hosting
{
/// <summary>
/// Extension methods for <see cref="RazorCompiledItem"/>.
/// </summary>
public static class RazorCompiledItemExtensions
{
/// <summary>
/// Gets the list of <see cref="IRazorSourceChecksumMetadata"/> associated with <paramref name="item"/>.
/// </summary>
/// <param name="item">The <see cref="RazorCompiledItem"/>.</param>
/// <returns>A list of <see cref="IRazorSourceChecksumMetadata"/>.</returns>
public static IReadOnlyList<IRazorSourceChecksumMetadata> GetChecksumMetadata(this RazorCompiledItem item)
{
if (item == null)
{
throw new ArgumentNullException(nameof(item));
}
return item.Metadata.OfType<IRazorSourceChecksumMetadata>().ToArray();
}
}
}

View File

@ -0,0 +1,35 @@
// 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.Hosting
{
/// <summary>
/// Defines a key/value metadata pair for the decorated Razor type.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class RazorCompiledItemMetadataAttribute : Attribute
{
/// <summary>
/// Creates a new <see cref="RazorCompiledItemMetadataAttribute"/>.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
public RazorCompiledItemMetadataAttribute(string key, string value)
{
Key = key;
Value = value;
}
/// <summary>
/// Gets the key.
/// </summary>
public string Key { get; }
/// <summary>
/// Gets the value.
/// </summary>
public string Value { get; }
}
}

View File

@ -0,0 +1,38 @@
// 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.Hosting
{
/// <summary>
/// Specifies the name of a Razor configuration as defined by the Razor SDK.
/// </summary>
/// <remarks>
/// This attribute is applied to an application's entry point assembly by the Razor SDK during the build,
/// so that the Razor configuration can be loaded at runtime based on the settings provided by the project
/// file.
/// </remarks>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
public sealed class RazorConfigurationNameAttribute : Attribute
{
/// <summary>
/// Creates a new instance of <see cref="RazorConfigurationNameAttribute"/>.
/// </summary>
/// <param name="configurationName">The name of the Razor configuration.</param>
public RazorConfigurationNameAttribute(string configurationName)
{
if (configurationName == null)
{
throw new ArgumentNullException(nameof(configurationName));
}
ConfigurationName = configurationName;
}
/// <summary>
/// Gets the name of the Razor configuration.
/// </summary>
public string ConfigurationName { get; }
}
}

View File

@ -0,0 +1,50 @@
// 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.Hosting
{
/// <summary>
/// Specifies the name of a Razor extension as defined by the Razor SDK.
/// </summary>
/// <remarks>
/// This attribute is applied to an application's entry point assembly by the Razor SDK during the build,
/// so that the Razor configuration can be loaded at runtime based on the settings provided by the project
/// file.
/// </remarks>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
public sealed class RazorExtensionAssemblyNameAttribute : Attribute
{
/// <summary>
/// Creates a new instance of <see cref="RazorExtensionAssemblyNameAttribute"/>.
/// </summary>
/// <param name="extensionName">The name of the extension.</param>
/// <param name="assemblyName">The assembly name of the extension.</param>
public RazorExtensionAssemblyNameAttribute(string extensionName, string assemblyName)
{
if (extensionName == null)
{
throw new ArgumentNullException(nameof(extensionName));
}
if (assemblyName == null)
{
throw new ArgumentNullException(nameof(assemblyName));
}
ExtensionName = extensionName;
AssemblyName = assemblyName;
}
/// <summary>
/// Gets the assembly name of the extension.
/// </summary>
public string AssemblyName { get; }
/// <summary>
/// Gets the name of the extension.
/// </summary>
public string ExtensionName { get; }
}
}

View File

@ -0,0 +1,38 @@
// 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.Hosting
{
/// <summary>
/// Specifies the name of a Razor configuration as defined by the Razor SDK.
/// </summary>
/// <remarks>
/// This attribute is part of a set of metadata attributes that can be applied to an assembly at build
/// time by the Razor SDK. These attributes allow the Razor configuration to be loaded at runtime based
/// on the settings originally provided by the project file.
/// </remarks>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
public sealed class RazorLanguageVersionAttribute : Attribute
{
/// <summary>
/// Creates a new instance of <see cref="RazorLanguageVersionAttribute"/>.
/// </summary>
/// <param name="languageVersion">The language version of Razor</param>
public RazorLanguageVersionAttribute(string languageVersion)
{
if (languageVersion == null)
{
throw new ArgumentNullException(nameof(languageVersion));
}
LanguageVersion = languageVersion;
}
/// <summary>
/// Gets the Razor language version.
/// </summary>
public string LanguageVersion { get; }
}
}

View File

@ -0,0 +1,67 @@
// 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.Hosting
{
/// <summary>
/// Specifies the checksum of a source file that contributed to a compiled item.
/// </summary>
/// <remarks>
/// <para>
/// These attributes are added by the Razor infrastructure when generating code to assist runtime
/// implementations to determine the integrity of compiled items.
/// </para>
/// <para>
/// Runtime implementations should access the checksum metadata for an item using
/// <see cref="RazorCompiledItemExtensions.GetChecksumMetadata(RazorCompiledItem)"/>.
/// </para>
/// </remarks>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class RazorSourceChecksumAttribute : Attribute, IRazorSourceChecksumMetadata
{
/// <summary>
/// Creates a new <see cref="RazorSourceChecksumAttribute"/>.
/// </summary>
/// <param name="checksumAlgorithm">The algorithm used to create this checksum.</param>
/// <param name="checksum">The checksum as a string of hex-encoded bytes.</param>
/// <param name="identifier">The identifier associated with this thumbprint.</param>
public RazorSourceChecksumAttribute(string checksumAlgorithm, string checksum, string identifier)
{
if (checksumAlgorithm == null)
{
throw new ArgumentNullException(nameof(checksumAlgorithm));
}
if (checksum == null)
{
throw new ArgumentNullException(nameof(checksum));
}
if (identifier == null)
{
throw new ArgumentNullException(nameof(identifier));
}
ChecksumAlgorithm = checksumAlgorithm;
Checksum = checksum;
Identifier = identifier;
}
/// <summary>
/// Gets the checksum as string of hex-encoded bytes.
/// </summary>
public string Checksum { get; }
/// <summary>
/// Gets the name of the algorithm used to create this checksum.
/// </summary>
public string ChecksumAlgorithm { get; }
/// <summary>
/// Gets the identifier of the source file associated with this checksum.
/// </summary>
public string Identifier { get; }
}
}

View File

@ -0,0 +1,70 @@
// 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 System.Diagnostics;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
{
public class TagHelperExecutionContext
{
public TagHelperExecutionContext(
string tagName,
TagMode tagMode,
IDictionary<object, object> items,
string uniqueId,
Func<Task> executeChildContentAsync,
Action<HtmlEncoder> startTagHelperWritingScope,
Func<TagHelperContent> endTagHelperWritingScope)
{
}
public bool ChildContentRetrieved => false;
public IDictionary<object, object> Items { get; private set; }
public IList<ITagHelper> TagHelpers => null;
public TagHelperOutput Output { get; internal set; }
public TagHelperContext Context { get; }
public void Add(ITagHelper tagHelper)
{
}
public void AddHtmlAttribute(string name, object value, HtmlAttributeValueStyle valueStyle)
{
}
public void AddHtmlAttribute(TagHelperAttribute attribute)
{
}
public void AddTagHelperAttribute(string name, object value, HtmlAttributeValueStyle valueStyle)
{
}
public void AddTagHelperAttribute(TagHelperAttribute attribute)
{
}
public void Reinitialize(
string tagName,
TagMode tagMode,
IDictionary<object, object> items,
string uniqueId,
Func<Task> executeChildContentAsync)
{
}
public Task SetOutputContentAsync()
{
throw null;
}
}
}

View File

@ -0,0 +1,18 @@
// 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 System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
{
public class TagHelperRunner
{
public Task RunAsync(TagHelperExecutionContext executionContext)
{
throw null;
}
}
}

View File

@ -0,0 +1,34 @@
// 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 System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
{
public class TagHelperScopeManager
{
public TagHelperScopeManager(
Action<HtmlEncoder> startTagHelperWritingScope,
Func<TagHelperContent> endTagHelperWritingScope)
{
}
public TagHelperExecutionContext Begin(
string tagName,
TagMode tagMode,
string uniqueId,
Func<Task> executeChildContentAsync)
{
throw null;
}
public TagHelperExecutionContext End()
{
throw null;
}
}
}

View File

@ -0,0 +1,92 @@
// 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.TagHelpers
{
/// <summary>
/// Used to override an <see cref="ITagHelper"/> property's HTML attribute name.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class HtmlAttributeNameAttribute : Attribute
{
private string _dictionaryAttributePrefix;
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlAttributeNameAttribute"/> class with <see cref="Name"/>
/// equal to <c>null</c>.
/// </summary>
/// <remarks>
/// Associated property must not have a public setter and must be compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>.
/// </remarks>
public HtmlAttributeNameAttribute()
{
}
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlAttributeNameAttribute"/> class.
/// </summary>
/// <param name="name">
/// HTML attribute name for the associated property. Must be <c>null</c> or empty if associated property does
/// not have a public setter and is compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>. Otherwise must not be <c>null</c> or empty.
/// </param>
public HtmlAttributeNameAttribute(string name)
{
Name = name;
}
/// <summary>
/// HTML attribute name of the associated property.
/// </summary>
/// <value>
/// <c>null</c> or empty if and only if associated property does not have a public setter and is compatible
/// with <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>.
/// </value>
public string Name { get; }
/// <summary>
/// Gets or sets the prefix used to match HTML attribute names. Matching attributes are added to the
/// associated property (an <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>).
/// </summary>
/// <remarks>
/// If non-<c>null</c> associated property must be compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> where <c>TKey</c> is
/// <see cref="string"/>.
/// </remarks>
/// <value>
/// <para>
/// If associated property is compatible with
/// <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>, default value is <c>Name + "-"</c>.
/// <see cref="Name"/> must not be <c>null</c> or empty in this case.
/// </para>
/// <para>
/// Otherwise default value is <c>null</c>.
/// </para>
/// </value>
public string DictionaryAttributePrefix
{
get
{
return _dictionaryAttributePrefix;
}
set
{
_dictionaryAttributePrefix = value;
DictionaryAttributePrefixSet = true;
}
}
/// <summary>
/// Gets an indication whether <see cref="DictionaryAttributePrefix"/> has been set. Used to distinguish an
/// uninitialized <see cref="DictionaryAttributePrefix"/> value from an explicit <c>null</c> setting.
/// </summary>
/// <value><c>true</c> if <see cref="DictionaryAttributePrefix"/> was set. <c>false</c> otherwise.</value>
public bool DictionaryAttributePrefixSet { get; private set; }
}
}

View File

@ -0,0 +1,21 @@
// 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.TagHelpers
{
/// <summary>
/// Indicates the associated <see cref="ITagHelper"/> property should not be bound to HTML attributes.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class HtmlAttributeNotBoundAttribute : Attribute
{
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlAttributeNotBoundAttribute"/> class.
/// </summary>
public HtmlAttributeNotBoundAttribute()
{
}
}
}

View File

@ -0,0 +1,13 @@
// 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.
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public enum HtmlAttributeValueStyle
{
DoubleQuotes,
SingleQuotes,
NoQuotes,
Minimized,
}
}

View File

@ -0,0 +1,86 @@
// 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.TagHelpers
{
/// <summary>
/// Provides an <see cref="ITagHelper"/>'s target.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public sealed class HtmlTargetElementAttribute : Attribute
{
public const string ElementCatchAllTarget = "*";
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlTargetElementAttribute"/> class that targets all HTML
/// elements with the required <see cref="Attributes"/>.
/// </summary>
/// <remarks><see cref="Tag"/> is set to <c>*</c>.</remarks>
public HtmlTargetElementAttribute()
: this(ElementCatchAllTarget)
{
}
/// <summary>
/// Instantiates a new instance of the <see cref="HtmlTargetElementAttribute"/> class with the given
/// <paramref name="tag"/> as its <see cref="Tag"/> value.
/// </summary>
/// <param name="tag">
/// The HTML tag the <see cref="ITagHelper"/> targets.
/// </param>
/// <remarks>A <c>*</c> <paramref name="tag"/> value indicates this <see cref="ITagHelper"/>
/// targets all HTML elements with the required <see cref="Attributes"/>.</remarks>
public HtmlTargetElementAttribute(string tag)
{
Tag = tag;
}
/// <summary>
/// The HTML tag the <see cref="ITagHelper"/> targets. A <c>*</c> value indicates this <see cref="ITagHelper"/>
/// targets all HTML elements with the required <see cref="Attributes"/>.
/// </summary>
public string Tag { get; }
/// <summary>
/// A comma-separated <see cref="string"/> of attribute selectors the HTML element must match for the
/// <see cref="ITagHelper"/> to run. <c>*</c> at the end of an attribute name acts as a prefix match. A value
/// surrounded by square brackets is handled as a CSS attribute value selector. Operators <c>^=</c>, <c>$=</c> and
/// <c>=</c> are supported e.g. <c>"name"</c>, <c>"[name]"</c>, <c>"[name=value]"</c>, <c>"[ name ^= 'value' ]"</c>.
/// </summary>
public string Attributes { get; set; }
/// <summary>
/// The expected tag structure. Defaults to <see cref="TagStructure.Unspecified"/>.
/// </summary>
/// <remarks>
/// If <see cref="TagStructure.Unspecified"/> and no other tag helpers applying to the same element specify
/// their <see cref="TagStructure"/> the <see cref="TagStructure.NormalOrSelfClosing"/> behavior is used:
/// <para>
/// <code>
/// &lt;my-tag-helper&gt;&lt;/my-tag-helper&gt;
/// &lt;!-- OR --&gt;
/// &lt;my-tag-helper /&gt;
/// </code>
/// Otherwise, if another tag helper applying to the same element does specify their behavior, that behavior
/// is used.
/// </para>
/// <para>
/// If <see cref="TagStructure.WithoutEndTag"/> HTML elements can be written in the following formats:
/// <code>
/// &lt;my-tag-helper&gt;
/// &lt;!-- OR --&gt;
/// &lt;my-tag-helper /&gt;
/// </code>
/// </para>
/// </remarks>
public TagStructure TagStructure { get; set; }
/// <summary>
/// The required HTML element name of the direct parent. A <c>null</c> value indicates any HTML element name is
/// allowed.
/// </summary>
public string ParentTag { get; set; }
}
}

View File

@ -0,0 +1,13 @@
// 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.
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Contract used to filter matching HTML elements.
/// Marker interface for <see cref="TagHelper"/>s.
/// </summary>
public interface ITagHelper : ITagHelperComponent
{
}
}

View File

@ -0,0 +1,41 @@
// 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.Threading.Tasks;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Contract used to modify an HTML element.
/// </summary>
public interface ITagHelperComponent
{
/// <summary>
/// When a set of <see cref="ITagHelperComponent"/>s are executed, their <see cref="Init(TagHelperContext)"/>'s
/// are first invoked in the specified <see cref="Order"/>; then their
/// <see cref="ProcessAsync(TagHelperContext, TagHelperOutput)"/>'s are invoked in the specified
/// <see cref="Order"/>. Lower values are executed first.
/// </summary>
int Order { get; }
/// <summary>
/// Initializes the <see cref="ITagHelperComponent"/> with the given <paramref name="context"/>. Additions to
/// <see cref="TagHelperContext.Items"/> should be done within this method to ensure they're added prior to
/// executing the children.
/// </summary>
/// <param name="context">Contains information associated with the current HTML tag.</param>
/// <remarks>When more than one <see cref="ITagHelperComponent"/> runs on the same element,
/// <see cref="M:TagHelperOutput.GetChildContentAsync"/> may be invoked prior to <see cref="ProcessAsync"/>.
/// </remarks>
void Init(TagHelperContext context);
/// <summary>
/// Asynchronously executes the <see cref="ITagHelperComponent"/> with the given <paramref name="context"/> and
/// <paramref name="output"/>.
/// </summary>
/// <param name="context">Contains information associated with the current HTML tag.</param>
/// <param name="output">A stateful HTML element used to generate an HTML tag.</param>
/// <returns>A <see cref="Task"/> that on completion updates the <paramref name="output"/>.</returns>
Task ProcessAsync(TagHelperContext context, TagHelperOutput output);
}
}

View File

@ -0,0 +1,35 @@
// 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.TagHelpers
{
/// <summary>
/// Provides a hint of the <see cref="ITagHelper"/>'s output element.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class OutputElementHintAttribute : Attribute
{
/// <summary>
/// Instantiates a new instance of the <see cref="OutputElementHintAttribute"/> class.
/// </summary>
/// <param name="outputElement">
/// The HTML element the <see cref="ITagHelper"/> may output.
/// </param>
public OutputElementHintAttribute(string outputElement)
{
if (outputElement == null)
{
throw new ArgumentNullException(nameof(outputElement));
}
OutputElement = outputElement;
}
/// <summary>
/// The HTML element the <see cref="ITagHelper"/> may output.
/// </summary>
public string OutputElement { get; }
}
}

View File

@ -0,0 +1,190 @@
// 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 System.Collections.ObjectModel;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// A read-only collection of <see cref="TagHelperAttribute"/>s.
/// </summary>
public abstract class ReadOnlyTagHelperAttributeList : ReadOnlyCollection<TagHelperAttribute>
{
private static readonly IReadOnlyList<TagHelperAttribute> EmptyList = new TagHelperAttribute[0];
/// <summary>
/// Instantiates a new instance of <see cref="ReadOnlyTagHelperAttributeList"/> with an empty
/// collection.
/// </summary>
protected ReadOnlyTagHelperAttributeList()
: base(new List<TagHelperAttribute>())
{
}
/// <summary>
/// Instantiates a new instance of <see cref="ReadOnlyTagHelperAttributeList"/> with the specified
/// <paramref name="attributes"/>.
/// </summary>
/// <param name="attributes">The collection to wrap.</param>
public ReadOnlyTagHelperAttributeList(IList<TagHelperAttribute> attributes)
: base(attributes)
{
}
/// <summary>
/// Gets the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/>.
/// </summary>
/// <param name="name">
/// The <see cref="TagHelperAttribute.Name"/> of the <see cref="TagHelperAttribute"/> to get.
/// </param>
/// <returns>The first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/>.
/// </returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public TagHelperAttribute this[string name]
{
get
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
// Perf: Avoid allocating enumerator
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(name, Items[i]))
{
return Items[i];
}
}
return null;
}
}
/// <summary>
/// Determines whether a <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/> exists in the collection.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the
/// <see cref="TagHelperAttribute"/> to get.</param>
/// <returns>
/// <c>true</c> if a <see cref="TagHelperAttribute"/> with the same
/// <see cref="TagHelperAttribute.Name"/> exists in the collection; otherwise, <c>false</c>.
/// </returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool ContainsName(string name)
{
return this[name] != null;
}
/// <summary>
/// Retrieves the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/>
/// matching <paramref name="name"/>.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the
/// <see cref="TagHelperAttribute"/> to get.</param>
/// <param name="attribute">When this method returns, the first <see cref="TagHelperAttribute"/> with
/// <see cref="TagHelperAttribute.Name"/> matching <paramref name="name"/>, if found; otherwise,
/// <c>null</c>.</param>
/// <returns><c>true</c> if a <see cref="TagHelperAttribute"/> with the same
/// <see cref="TagHelperAttribute.Name"/> exists in the collection; otherwise, <c>false</c>.</returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool TryGetAttribute(string name, out TagHelperAttribute attribute)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
attribute = this[name];
return attribute != null;
}
/// <summary>
/// Retrieves <see cref="TagHelperAttribute"/>s in the collection with
/// <see cref="TagHelperAttribute.Name"/> matching <paramref name="name"/>.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the
/// <see cref="TagHelperAttribute"/>s to get.</param>
/// <param name="attributes">When this method returns, the <see cref="TagHelperAttribute"/>s with
/// <see cref="TagHelperAttribute.Name"/> matching <paramref name="name"/>.</param>
/// <returns><c>true</c> if at least one <see cref="TagHelperAttribute"/> with the same
/// <see cref="TagHelperAttribute.Name"/> exists in the collection; otherwise, <c>false</c>.</returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool TryGetAttributes(string name, out IReadOnlyList<TagHelperAttribute> attributes)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
// Perf: Avoid allocating enumerator
List<TagHelperAttribute> matchedAttributes = null;
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(name, Items[i]))
{
if (matchedAttributes == null)
{
matchedAttributes = new List<TagHelperAttribute>();
}
matchedAttributes.Add(Items[i]);
}
}
attributes = matchedAttributes ?? EmptyList;
return matchedAttributes != null;
}
/// <summary>
/// Searches for a <see cref="TagHelperAttribute"/> who's <see cref="TagHelperAttribute.Name"/>
/// case-insensitively matches <paramref name="name"/> and returns the zero-based index of the first
/// occurrence.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> to locate in the collection.</param>
/// <returns>The zero-based index of the first matching <see cref="TagHelperAttribute"/> within the collection,
/// if found; otherwise, -1.</returns>
public int IndexOfName(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(name, Items[i]))
{
return i;
}
}
return -1;
}
/// <summary>
/// Determines if the specified <paramref name="attribute"/> has the same name as <paramref name="name"/>.
/// </summary>
/// <param name="name">The value to compare against <paramref name="attribute"/>s
/// <see cref="TagHelperAttribute.Name"/>.</param>
/// <param name="attribute">The attribute to compare against.</param>
/// <returns><c>true</c> if <paramref name="name"/> case-insensitively matches <paramref name="attribute"/>s
/// <see cref="TagHelperAttribute.Name"/>.</returns>
protected static bool NameEquals(string name, TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
return string.Equals(name, attribute.Name, StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@ -0,0 +1,42 @@
// 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;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Restricts children of the <see cref="ITagHelper"/>'s element.
/// </summary>
/// <remarks>Combining this attribute with a <see cref="HtmlTargetElementAttribute"/> that specifies its
/// <see cref="HtmlTargetElementAttribute.TagStructure"/> as <see cref="TagStructure.WithoutEndTag"/> will result
/// in this attribute being ignored.</remarks>
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class RestrictChildrenAttribute : Attribute
{
/// <summary>
/// Instantiates a new instance of the <see cref="RestrictChildrenAttribute"/> class.
/// </summary>
/// <param name="childTag">
/// The tag name of an element allowed as a child.
/// </param>
/// <param name="childTags">
/// Additional names of elements allowed as children.
/// </param>
public RestrictChildrenAttribute(string childTag, params string[] childTags)
{
var concatenatedNames = new string[1 + childTags.Length];
concatenatedNames[0] = childTag;
childTags.CopyTo(concatenatedNames, 1);
ChildTags = concatenatedNames;
}
/// <summary>
/// Get the names of elements allowed as children.
/// </summary>
public IEnumerable<string> ChildTags { get; }
}
}

View File

@ -0,0 +1,26 @@
// 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.Threading.Tasks;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public abstract class TagHelper : ITagHelper
{
public virtual int Order { get; } = 0;
public virtual void Init(TagHelperContext context)
{
}
public virtual void Process(TagHelperContext context, TagHelperOutput output)
{
}
public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
Process(context, output);
return Task.CompletedTask;
}
}
}

View File

@ -0,0 +1,43 @@
// 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.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Html;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public class TagHelperAttribute : IHtmlContentContainer
{
public TagHelperAttribute(string name)
{
}
public TagHelperAttribute(string name, object value)
{
}
public TagHelperAttribute(string name, object value, HtmlAttributeValueStyle valueStyle)
{
}
public string Name { get; }
public object Value { get; }
public HtmlAttributeValueStyle ValueStyle { get; }
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
}
public void CopyTo(IHtmlContentBuilder destination)
{
}
public void MoveTo(IHtmlContentBuilder destination)
{
}
}
}

View File

@ -0,0 +1,230 @@
// 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;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// A collection of <see cref="TagHelperAttribute"/>s.
/// </summary>
public class TagHelperAttributeList : ReadOnlyTagHelperAttributeList, IList<TagHelperAttribute>
{
/// <summary>
/// Instantiates a new instance of <see cref="TagHelperAttributeList"/> with an empty collection.
/// </summary>
public TagHelperAttributeList()
: base()
{
}
/// <summary>
/// Instantiates a new instance of <see cref="TagHelperAttributeList"/> with the specified
/// <paramref name="attributes"/>.
/// </summary>
/// <param name="attributes">The collection to wrap.</param>
public TagHelperAttributeList(IEnumerable<TagHelperAttribute> attributes)
: base (new List<TagHelperAttribute>(attributes))
{
if (attributes == null)
{
throw new ArgumentNullException(nameof(attributes));
}
}
/// <summary>
/// Instantiates a new instance of <see cref="TagHelperAttributeList"/> with the specified
/// <paramref name="attributes"/>.
/// </summary>
/// <param name="attributes">The collection to wrap.</param>
public TagHelperAttributeList(List<TagHelperAttribute> attributes)
: base(attributes)
{
if (attributes == null)
{
throw new ArgumentNullException(nameof(attributes));
}
}
/// <inheritdoc />
/// <remarks>
/// <paramref name="value"/>'s <see cref="TagHelperAttribute.Name"/> must not be <c>null</c>.
/// </remarks>
public new TagHelperAttribute this[int index]
{
get
{
return base[index];
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
Items[index] = value;
}
}
/// <summary>
/// Replaces the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/> matching
/// <paramref name="name"/> and removes any additional matching <see cref="TagHelperAttribute"/>s. If a
/// matching <see cref="TagHelperAttribute"/> is not found, adds a <see cref="TagHelperAttribute"/> with
/// <paramref name="name"/> and <paramref name="value"/> to the end of the collection.</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>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public void SetAttribute(string name, object value)
{
var attribute = new TagHelperAttribute(name, value);
SetAttribute(attribute);
}
/// <summary>
/// Replaces the first <see cref="TagHelperAttribute"/> with <see cref="TagHelperAttribute.Name"/> matching
/// <paramref name="attribute"/>'s <see cref="TagHelperAttribute.Name"/> and removes any additional matching
/// <see cref="TagHelperAttribute"/>s. If a matching <see cref="TagHelperAttribute"/> is not found, adds the
/// specified <paramref name="attribute"/> to the end of the collection.
/// </summary>
/// <param name="attribute">
/// The <see cref="TagHelperAttribute"/> to set.
/// </param>
/// <remarks><paramref name="attribute"/>'s <see cref="TagHelperAttribute.Name"/> is compared
/// case-insensitively.</remarks>
public void SetAttribute(TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
var attributeReplaced = false;
// Perf: Avoid allocating enumerator
for (var i = 0; i < Items.Count; i++)
{
if (NameEquals(attribute.Name, Items[i]))
{
// We replace the first attribute with the provided attribute, remove all the rest.
if (!attributeReplaced)
{
// We replace the first attribute we find with the same name.
Items[i] = attribute;
attributeReplaced = true;
}
else
{
Items.RemoveAt(i--);
}
}
}
// If we didn't replace an attribute value we should add value to the end of the collection.
if (!attributeReplaced)
{
Add(attribute);
}
}
/// <inheritdoc />
bool ICollection<TagHelperAttribute>.IsReadOnly => false;
/// <summary>
/// Adds a <see cref="TagHelperAttribute"/> to the end of the collection with the specified
/// <paramref name="name"/> and <paramref name="value"/>.
/// </summary>
/// <param name="name">The <see cref="TagHelperAttribute.Name"/> of the attribute to add.</param>
/// <param name="value">The <see cref="TagHelperAttribute.Value"/> of the attribute to add.</param>
public void Add(string name, object value)
{
var attribute = new TagHelperAttribute(name, value);
Items.Add(attribute);
}
/// <inheritdoc />
public void Add(TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
Items.Add(attribute);
}
/// <inheritdoc />
public void Insert(int index, TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
Items.Insert(index, attribute);
}
/// <inheritdoc />
/// <remarks>
/// <paramref name="attribute"/>s <see cref="TagHelperAttribute.Name"/> is compared case-insensitively.
/// </remarks>
public bool Remove(TagHelperAttribute attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
return Items.Remove(attribute);
}
/// <inheritdoc />
public void RemoveAt(int index)
{
Items.RemoveAt(index);
}
/// <summary>
/// Removes all <see cref="TagHelperAttribute"/>s with <see cref="TagHelperAttribute.Name"/> matching
/// <paramref name="name"/>.
/// </summary>
/// <param name="name">
/// The <see cref="TagHelperAttribute.Name"/> of <see cref="TagHelperAttribute"/>s to remove.
/// </param>
/// <returns>
/// <c>true</c> if at least 1 <see cref="TagHelperAttribute"/> was removed; otherwise, <c>false</c>.
/// </returns>
/// <remarks><paramref name="name"/> is compared case-insensitively.</remarks>
public bool RemoveAll(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
// Perf: Avoid allocating enumerator
var removedAtLeastOne = false;
for (var i = Items.Count - 1; i >= 0; i--)
{
if (NameEquals(name, Items[i]))
{
Items.RemoveAt(i);
removedAtLeastOne = true;
}
}
return removedAtLeastOne;
}
/// <inheritdoc />
public void Clear()
{
Items.Clear();
}
}
}

View File

@ -0,0 +1,39 @@
// 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.Threading.Tasks;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// An abstract base class for <see cref="ITagHelperComponent"/>.
/// </summary>
public abstract class TagHelperComponent : ITagHelperComponent
{
/// <inheritdoc />
/// <remarks>Default order is <c>0</c>.</remarks>
public virtual int Order => 0;
/// <inheritdoc />
public virtual void Init(TagHelperContext context)
{
}
/// <summary>
/// Synchronously executes the <see cref="ITagHelperComponent"/> with the given <paramref name="context"/> and
/// <paramref name="output"/>.
/// </summary>
/// <param name="context">Contains information associated with the current HTML tag.</param>
/// <param name="output">A stateful HTML element used to generate an HTML tag.</param>
public virtual void Process(TagHelperContext context, TagHelperOutput output)
{
}
/// <inheritdoc />
public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
Process(context, output);
return Task.CompletedTask;
}
}
}

View File

@ -0,0 +1,179 @@
// 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.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Html;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Abstract class used to buffer content returned by <see cref="ITagHelper"/>s.
/// </summary>
public abstract class TagHelperContent : IHtmlContentBuilder
{
/// <summary>
/// Gets a value indicating whether the content was modified.
/// </summary>
public abstract bool IsModified { get; }
/// <summary>
/// Gets a value indicating whether the content is empty or whitespace.
/// </summary>
public abstract bool IsEmptyOrWhiteSpace { get; }
/// <summary>
/// Sets the content.
/// </summary>
/// <param name="htmlContent">The <see cref="IHtmlContent"/> that replaces the content.</param>
/// <returns>A reference to this instance after the set operation has completed.</returns>
public TagHelperContent SetHtmlContent(IHtmlContent htmlContent)
{
HtmlContentBuilderExtensions.SetHtmlContent(this, htmlContent);
return this;
}
/// <summary>
/// Sets the content.
/// </summary>
/// <param name="unencoded">
/// The <see cref="string"/> that replaces the content. The value is assume to be unencoded
/// as-provided and will be HTML encoded before being written.
/// </param>
/// <returns>A reference to this instance after the set operation has completed.</returns>
public TagHelperContent SetContent(string unencoded)
{
HtmlContentBuilderExtensions.SetContent(this, unencoded);
return this;
}
/// <summary>
/// Sets the content.
/// </summary>
/// <param name="encoded">
/// The <see cref="string"/> that replaces the content. The value is assume to be HTML encoded
/// as-provided and no further encoding will be performed.
/// </param>
/// <returns>A reference to this instance after the set operation has completed.</returns>
public TagHelperContent SetHtmlContent(string encoded)
{
HtmlContentBuilderExtensions.SetHtmlContent(this, encoded);
return this;
}
/// <summary>
/// Appends <paramref name="unencoded"/> to the existing content.
/// </summary>
/// <param name="unencoded">The <see cref="string"/> to be appended.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public abstract TagHelperContent Append(string unencoded);
/// <summary>
/// Appends <paramref name="htmlContent"/> to the existing content.
/// </summary>
/// <param name="htmlContent">The <see cref="IHtmlContent"/> to be appended.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public abstract TagHelperContent AppendHtml(IHtmlContent htmlContent);
/// <summary>
/// Appends <paramref name="encoded"/> to the existing content. <paramref name="encoded"/> is assumed
/// to be an HTML encoded <see cref="string"/> and no further encoding will be performed.
/// </summary>
/// <param name="encoded">The <see cref="string"/> to be appended.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public abstract TagHelperContent AppendHtml(string encoded);
/// <summary>
/// Appends the specified <paramref name="format"/> to the existing content after
/// replacing each format item with the HTML encoded <see cref="string"/> representation of the
/// corresponding item in the <paramref name="args"/> array.
/// </summary>
/// <param name="format">
/// The composite format <see cref="string"/> (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx).
/// </param>
/// <param name="args">The object array to format.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public TagHelperContent AppendFormat(string format, params object[] args)
{
HtmlContentBuilderExtensions.AppendFormat(this, null, format, args);
return this;
}
/// <summary>
/// Appends the specified <paramref name="format"/> to the existing content with information from the
/// <paramref name="provider"/> after replacing each format item with the HTML encoded <see cref="string"/>
/// representation of the corresponding item in the <paramref name="args"/> array.
/// </summary>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="format">
/// The composite format <see cref="string"/> (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx).
/// </param>
/// <param name="args">The object array to format.</param>
/// <returns>A reference to this instance after the append operation has completed.</returns>
public TagHelperContent AppendFormat(IFormatProvider provider, string format, params object[] args)
{
HtmlContentBuilderExtensions.AppendFormat(this, provider, format, args);
return this;
}
/// <summary>
/// Clears the content.
/// </summary>
/// <returns>A reference to this instance after the clear operation has completed.</returns>
public abstract TagHelperContent Clear();
/// <summary>
/// Clears the <see cref="TagHelperContent"/>, so it can be reused.
/// </summary>
/// <remarks>This method does more than what <see cref="Clear"/> does. It also resets the
/// <see cref="IsModified"/> flag.</remarks>
public abstract void Reinitialize();
/// <inheritdoc />
public abstract void CopyTo(IHtmlContentBuilder destination);
/// <inheritdoc />
public abstract void MoveTo(IHtmlContentBuilder destination);
/// <summary>
/// Gets the content.
/// </summary>
/// <returns>A <see cref="string"/> containing the content.</returns>
public abstract string GetContent();
/// <summary>
/// Gets the content.
/// </summary>
/// <param name="encoder">The <see cref="HtmlEncoder"/>.</param>
/// <returns>A <see cref="string"/> containing the content.</returns>
public abstract string GetContent(HtmlEncoder encoder);
/// <inheritdoc />
public abstract void WriteTo(TextWriter writer, HtmlEncoder encoder);
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.AppendHtml(IHtmlContent content)
{
return AppendHtml(content);
}
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.Append(string unencoded)
{
return Append(unencoded);
}
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.AppendHtml(string encoded)
{
return AppendHtml(encoded);
}
/// <inheritdoc />
IHtmlContentBuilder IHtmlContentBuilder.Clear()
{
return Clear();
}
}
}

View File

@ -0,0 +1,118 @@
// 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;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// Contains information related to the execution of <see cref="ITagHelper"/>s.
/// </summary>
public class TagHelperContext
{
private readonly TagHelperAttributeList _allAttributes;
/// <summary>
/// Instantiates a new <see cref="TagHelperContext"/>.
/// </summary>
/// <param name="tagName">The parsed HTML tag name of the element.</param>
/// <param name="allAttributes">Every attribute associated with the current HTML element.</param>
/// <param name="items">Collection of items used to communicate with other <see cref="ITagHelper"/>s.</param>
/// <param name="uniqueId">The unique identifier for the source element this <see cref="TagHelperContext" />
/// applies to.</param>
public TagHelperContext(
string tagName,
TagHelperAttributeList allAttributes,
IDictionary<object, object> items,
string uniqueId) : this(allAttributes, items, uniqueId)
{
if (tagName == null)
{
throw new ArgumentNullException(nameof(tagName));
}
TagName = tagName;
}
/// <summary>
/// Instantiates a new <see cref="TagHelperContext"/>.
/// </summary>
/// <param name="allAttributes">Every attribute associated with the current HTML element.</param>
/// <param name="items">Collection of items used to communicate with other <see cref="ITagHelper"/>s.</param>
/// <param name="uniqueId">The unique identifier for the source element this <see cref="TagHelperContext" />
/// applies to.</param>
public TagHelperContext(
TagHelperAttributeList allAttributes,
IDictionary<object, object> items,
string uniqueId)
{
if (items == null)
{
throw new ArgumentNullException(nameof(items));
}
if (uniqueId == null)
{
throw new ArgumentNullException(nameof(uniqueId));
}
if (allAttributes == null)
{
throw new ArgumentNullException(nameof(allAttributes));
}
_allAttributes = allAttributes;
Items = items;
UniqueId = uniqueId;
}
/// <summary>
/// The parsed HTML tag name of the element.
/// </summary>
public string TagName { get; private set; }
/// <summary>
/// Every attribute associated with the current HTML element.
/// </summary>
public ReadOnlyTagHelperAttributeList AllAttributes => _allAttributes;
/// <summary>
/// Gets the collection of items used to communicate with other <see cref="ITagHelper"/>s.
/// </summary>
/// <remarks>
/// This <see cref="IDictionary{Object, Object}" /> is copy-on-write in order to ensure items added to this
/// collection are visible only to other <see cref="ITagHelper"/>s targeting child elements.
/// </remarks>
public IDictionary<object, object> Items { get; private set; }
/// <summary>
/// An identifier unique to the HTML element this context is for.
/// </summary>
public string UniqueId { get; private set; }
/// <summary>
/// Clears the <see cref="TagHelperContext"/> and updates its state with the provided values.
/// </summary>
/// <param name="tagName">The HTML tag name to use.</param>
/// <param name="items">The <see cref="IDictionary{Object, Object}"/> to use.</param>
/// <param name="uniqueId">The unique id to use.</param>
public void Reinitialize(string tagName, IDictionary<object, object> items, string uniqueId)
{
TagName = tagName;
Reinitialize(items, uniqueId);
}
/// <summary>
/// Clears the <see cref="TagHelperContext"/> and updates its state with the provided values.
/// </summary>
/// <param name="items">The <see cref="IDictionary{Object, Object}"/> to use.</param>
/// <param name="uniqueId">The unique id to use.</param>
public void Reinitialize(IDictionary<object, object> items, string uniqueId)
{
_allAttributes.Clear();
Items = items;
UniqueId = uniqueId;
}
}
}

View File

@ -0,0 +1,79 @@
// 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.IO;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
public class TagHelperOutput : IHtmlContentContainer
{
public TagHelperOutput(
string tagName,
TagHelperAttributeList attributes,
Func<bool, HtmlEncoder, Task<TagHelperContent>> getChildContentAsync)
{
}
public string TagName { get; set; }
public TagHelperContent PreElement => null;
public TagHelperContent PreContent => null;
public TagHelperContent Content => null;
public TagHelperContent PostContent => null;
public TagHelperContent PostElement => null;
public bool IsContentModified => true;
public TagMode TagMode { get; set; }
public TagHelperAttributeList Attributes { get; }
public void Reinitialize(string tagName, TagMode tagMode)
{
}
public void SuppressOutput()
{
}
public Task<TagHelperContent> GetChildContentAsync()
{
throw null;
}
public Task<TagHelperContent> GetChildContentAsync(bool useCachedResult)
{
throw null;
}
public Task<TagHelperContent> GetChildContentAsync(HtmlEncoder encoder)
{
throw null;
}
public Task<TagHelperContent> GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder)
{
throw null;
}
void IHtmlContentContainer.CopyTo(IHtmlContentBuilder destination)
{
}
void IHtmlContentContainer.MoveTo(IHtmlContentBuilder destination)
{
}
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{
}
}
}

View File

@ -0,0 +1,26 @@
// 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.
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// The mode in which an element should render.
/// </summary>
public enum TagMode
{
/// <summary>
/// Include both start and end tags.
/// </summary>
StartTagAndEndTag,
/// <summary>
/// A self-closed tag.
/// </summary>
SelfClosing,
/// <summary>
/// Only a start tag.
/// </summary>
StartTagOnly
}
}

View File

@ -0,0 +1,28 @@
// 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.
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
/// <summary>
/// The structure the element should be written in.
/// </summary>
public enum TagStructure
{
/// <summary>
/// If no other tag helper applies to the same element and specifies a <see cref="TagStructure"/>,
/// <see cref="NormalOrSelfClosing"/> will be used.
/// </summary>
Unspecified,
/// <summary>
/// Element can be written as &lt;my-tag-helper&gt;&lt;/my-tag-helper&gt; or &lt;my-tag-helper /&gt;.
/// </summary>
NormalOrSelfClosing,
/// <summary>
/// Element can be written as &lt;my-tag-helper&gt; or &lt;my-tag-helper /&gt;.
/// </summary>
/// <remarks>Elements with a <see cref="WithoutEndTag"/> structure will never have any content.</remarks>
WithoutEndTag
}
}

View File

@ -6,10 +6,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="$(MicrosoftAspNetCoreHtmlAbstractionsPackageVersion)" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(SystemDiagnosticsDiagnosticSourcePackageVersion)" />
</ItemGroup>

View File

@ -22,13 +22,10 @@
<ItemGroup Condition="'$(BinariesRoot)'==''">
<!-- In test scenarios $(BinariesRoot) is defined in a generated Directory.Build.props file -->
<ProjectReference Include="..\..\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj"/>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj"/>
</ItemGroup>
<ItemGroup Condition="'$(BinariesRoot)'!=''">
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Html.Abstractions.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Runtime.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.dll"/>
</ItemGroup>
</Project>

View File

@ -25,13 +25,10 @@
<ItemGroup Condition="'$(BinariesRoot)'==''">
<!-- In test scenarios $(BinariesRoot) is defined in a generated Directory.Build.props file -->
<ProjectReference Include="..\..\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj"/>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj"/>
</ItemGroup>
<ItemGroup Condition="'$(BinariesRoot)'!=''">
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Html.Abstractions.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Runtime.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.dll"/>
</ItemGroup>

View File

@ -24,13 +24,10 @@
<ItemGroup Condition="'$(BinariesRoot)'==''">
<!-- In test scenarios $(BinariesRoot) is defined in a generated Directory.Build.props file -->
<ProjectReference Include="..\..\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj"/>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj"/>
</ItemGroup>
<ItemGroup Condition="'$(BinariesRoot)'!=''">
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Html.Abstractions.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Runtime.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.dll"/>
</ItemGroup>

View File

@ -16,13 +16,10 @@
<ItemGroup Condition="'$(BinariesRoot)'==''">
<!-- In test scenarios $(BinariesRoot) is defined in a generated Directory.Build.props file -->
<ProjectReference Include="..\..\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj"/>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj"/>
</ItemGroup>
<ItemGroup Condition="'$(BinariesRoot)'!=''">
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Html.Abstractions.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Runtime.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.dll"/>
</ItemGroup>

View File

@ -16,13 +16,10 @@
<ItemGroup Condition="'$(BinariesRoot)'==''">
<!-- In test scenarios $(BinariesRoot) is defined in a generated Directory.Build.props file -->
<ProjectReference Include="..\..\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj"/>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj"/>
</ItemGroup>
<ItemGroup Condition="'$(BinariesRoot)'!=''">
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Html.Abstractions.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Runtime.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.dll"/>
</ItemGroup>

View File

@ -16,13 +16,10 @@
<ItemGroup Condition="'$(BinariesRoot)'==''">
<!-- In test scenarios $(BinariesRoot) is defined in a generated Directory.Build.props file -->
<ProjectReference Include="..\..\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj"/>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj"/>
</ItemGroup>
<ItemGroup Condition="'$(BinariesRoot)'!=''">
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Html.Abstractions.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Runtime.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.dll"/>
</ItemGroup>

View File

@ -21,13 +21,10 @@
<ItemGroup Condition="'$(BinariesRoot)'==''">
<!-- In test scenarios $(BinariesRoot) is defined in a generated Directory.Build.props file -->
<ProjectReference Include="..\..\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj"/>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj"/>
</ItemGroup>
<ItemGroup Condition="'$(BinariesRoot)'!=''">
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Html.Abstractions.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Runtime.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.dll"/>
</ItemGroup>

View File

@ -16,13 +16,10 @@
<ItemGroup Condition="'$(BinariesRoot)'==''">
<!-- In test scenarios $(BinariesRoot) is defined in a generated Directory.Build.props file -->
<ProjectReference Include="..\..\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj"/>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj"/>
</ItemGroup>
<ItemGroup Condition="'$(BinariesRoot)'!=''">
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Html.Abstractions.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Runtime.dll"/>
<Reference Include="$(BinariesRoot)\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.dll"/>
</ItemGroup>