Merge branch 'release' of github.com:aspnet/Razor into release
This commit is contained in:
commit
ba387a3a22
|
|
@ -19,10 +19,10 @@ IF EXIST packages\KoreBuild goto run
|
||||||
.nuget\NuGet.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
|
.nuget\NuGet.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
|
||||||
.nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion
|
.nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion
|
||||||
|
|
||||||
IF "%SKIP_KRE_INSTALL%"=="1" goto run
|
IF "%SKIP_DOTNET_INSTALL%"=="1" goto run
|
||||||
CALL packages\KoreBuild\build\kvm upgrade -runtime CLR -x86
|
CALL packages\KoreBuild\build\dotnetsdk upgrade -runtime CLR -x86
|
||||||
CALL packages\KoreBuild\build\kvm install default -runtime CoreCLR -x86
|
CALL packages\KoreBuild\build\dotnetsdk install default -runtime CoreCLR -x86
|
||||||
|
|
||||||
:run
|
:run
|
||||||
CALL packages\KoreBuild\build\kvm use default -runtime CLR -x86
|
CALL packages\KoreBuild\build\dotnetsdk use default -runtime CLR -x86
|
||||||
packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %*
|
packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %*
|
||||||
|
|
|
||||||
4
build.sh
4
build.sh
|
|
@ -28,11 +28,11 @@ if test ! -d packages/KoreBuild; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! type k > /dev/null 2>&1; then
|
if ! type k > /dev/null 2>&1; then
|
||||||
source packages/KoreBuild/build/kvm.sh
|
source packages/KoreBuild/build/dotnetsdk.sh
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! type k > /dev/null 2>&1; then
|
if ! type k > /dev/null 2>&1; then
|
||||||
kvm upgrade
|
dotnetsdk upgrade
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@"
|
mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@"
|
||||||
|
|
|
||||||
|
|
@ -81,17 +81,17 @@ namespace Microsoft.AspNet.Razor.Runtime
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parameter {0} must not contain null tag names.
|
/// Parameter {0} must not contain null tag names.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string TagNameAttribute_AdditionalTagsCannotContainNull
|
internal static string HtmlElementNameAttribute_AdditionalTagsCannotContainNull
|
||||||
{
|
{
|
||||||
get { return GetString("TagNameAttribute_AdditionalTagsCannotContainNull"); }
|
get { return GetString("HtmlElementNameAttribute_AdditionalTagsCannotContainNull"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parameter {0} must not contain null tag names.
|
/// Parameter {0} must not contain null tag names.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string FormatTagNameAttribute_AdditionalTagsCannotContainNull(object p0)
|
internal static string FormatHtmlElementNameAttribute_AdditionalTagsCannotContainNull(object p0)
|
||||||
{
|
{
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("TagNameAttribute_AdditionalTagsCannotContainNull"), p0);
|
return string.Format(CultureInfo.CurrentCulture, GetString("HtmlElementNameAttribute_AdditionalTagsCannotContainNull"), p0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@
|
||||||
<data name="ScopeManager_EndCannotBeCalledWithoutACallToBegin" xml:space="preserve">
|
<data name="ScopeManager_EndCannotBeCalledWithoutACallToBegin" xml:space="preserve">
|
||||||
<value>Must call '{2}.{1}' before calling '{2}.{0}'.</value>
|
<value>Must call '{2}.{1}' before calling '{2}.{0}'.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TagNameAttribute_AdditionalTagsCannotContainNull" xml:space="preserve">
|
<data name="HtmlElementNameAttribute_AdditionalTagsCannotContainNull" xml:space="preserve">
|
||||||
<value>Parameter {0} must not contain null tag names.</value>
|
<value>Parameter {0} must not contain null tag names.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ArgumentCannotBeNullOrEmpty" xml:space="preserve">
|
<data name="ArgumentCannotBeNullOrEmpty" xml:space="preserve">
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Used to override <see cref="ITagHelper"/>'s behavior when its
|
|
||||||
/// <see cref="ITagHelper.ProcessAsync"/> is invoked.
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
|
||||||
public sealed class ContentBehaviorAttribute : Attribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Instantiates a new instance of the <see cref="ContentBehaviorAttribute"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="contentBehavior">The <see cref="Razor.TagHelpers.ContentBehavior"/> for the
|
|
||||||
/// <see cref="ITagHelper"/>.</param>
|
|
||||||
public ContentBehaviorAttribute(ContentBehavior contentBehavior)
|
|
||||||
{
|
|
||||||
ContentBehavior = contentBehavior;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Razor.TagHelpers.ContentBehavior"/> for the <see cref="ITagHelper"/>.
|
|
||||||
/// </summary>
|
|
||||||
public ContentBehavior ContentBehavior { get; private set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -11,29 +11,29 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
/// Used to override a <see cref="ITagHelper"/>'s default tag name target.
|
/// Used to override a <see cref="ITagHelper"/>'s default tag name target.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
|
||||||
public sealed class TagNameAttribute : Attribute
|
public sealed class HtmlElementNameAttribute : Attribute
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instantiates a new instance of the <see cref="TagNameAttribute"/> class.
|
/// Instantiates a new instance of the <see cref="HtmlElementNameAttribute"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tag">The HTML tag name for the <see cref="TagHelper"/> to target.</param>
|
/// <param name="tag">The HTML tag name for the <see cref="TagHelper"/> to target.</param>
|
||||||
public TagNameAttribute([NotNull] string tag)
|
public HtmlElementNameAttribute([NotNull] string tag)
|
||||||
{
|
{
|
||||||
Tags = new[] { tag };
|
Tags = new[] { tag };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instantiates a new instance of the <see cref="TagNameAttribute"/> class.
|
/// Instantiates a new instance of the <see cref="HtmlElementNameAttribute"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tag">The HTML tag name for the <see cref="TagHelper"/> to target.</param>
|
/// <param name="tag">The HTML tag name for the <see cref="TagHelper"/> to target.</param>
|
||||||
/// <param name="additionalTags">Additional HTML tag names for the <see cref="TagHelper"/> to target.</param>
|
/// <param name="additionalTags">Additional HTML tag names for the <see cref="TagHelper"/> to target.</param>
|
||||||
public TagNameAttribute([NotNull] string tag, [NotNull] params string[] additionalTags)
|
public HtmlElementNameAttribute([NotNull] string tag, [NotNull] params string[] additionalTags)
|
||||||
{
|
{
|
||||||
if (additionalTags.Contains(null))
|
if (additionalTags.Contains(null))
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(
|
throw new ArgumentNullException(
|
||||||
nameof(additionalTags),
|
nameof(additionalTags),
|
||||||
Resources.FormatTagNameAttribute_AdditionalTagsCannotContainNull(nameof(additionalTags)));
|
Resources.FormatHtmlElementNameAttribute_AdditionalTagsCannotContainNull(nameof(additionalTags)));
|
||||||
};
|
};
|
||||||
|
|
||||||
var allTags = new List<string>(additionalTags);
|
var allTags = new List<string>(additionalTags);
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// 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.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
{
|
{
|
||||||
|
|
@ -10,18 +12,42 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TagHelperContext
|
public class TagHelperContext
|
||||||
{
|
{
|
||||||
|
private readonly Func<Task<string>> _getChildContentAsync;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instantiates a new <see cref="TagHelperContext"/>.
|
/// Instantiates a new <see cref="TagHelperContext"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="allAttributes">Every attribute associated with the current HTML element.</param>
|
/// <param name="allAttributes">Every attribute associated with the current HTML element.</param>
|
||||||
public TagHelperContext([NotNull] IDictionary<string, object> allAttributes)
|
/// <param name="uniqueId">The unique identifier for the source element this <see cref="TagHelperContext" />
|
||||||
|
/// applies to.</param>
|
||||||
|
/// <param name="getChildContentAsync">A delegate used to execute and retrieve the rendered child content
|
||||||
|
/// asynchronously.</param>
|
||||||
|
public TagHelperContext([NotNull] IDictionary<string, object> allAttributes,
|
||||||
|
[NotNull] string uniqueId,
|
||||||
|
[NotNull] Func<Task<string>> getChildContentAsync)
|
||||||
{
|
{
|
||||||
AllAttributes = allAttributes;
|
AllAttributes = allAttributes;
|
||||||
|
UniqueId = uniqueId;
|
||||||
|
_getChildContentAsync = getChildContentAsync;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Every attribute associated with the current HTML element.
|
/// Every attribute associated with the current HTML element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDictionary<string, object> AllAttributes { get; private set; }
|
public IDictionary<string, object> AllAttributes { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An identifier unique to the HTML element this context is for.
|
||||||
|
/// </summary>
|
||||||
|
public string UniqueId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate used to execute and retrieve the rendered child content asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="Task"/> that when executed returns content rendered by children.</returns>
|
||||||
|
public Task<string> GetChildContentAsync()
|
||||||
|
{
|
||||||
|
return _getChildContentAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
|
|
@ -15,6 +16,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
public static class TagHelperDescriptorFactory
|
public static class TagHelperDescriptorFactory
|
||||||
{
|
{
|
||||||
private const string TagHelperNameEnding = "TagHelper";
|
private const string TagHelperNameEnding = "TagHelper";
|
||||||
|
private const string HtmlCaseRegexReplacement = "-$1$2";
|
||||||
|
|
||||||
|
// This matches the following AFTER the start of the input string (MATCH).
|
||||||
|
// Any letter/number followed by an uppercase letter then lowercase letter: 1(Aa), a(Aa), A(Aa)
|
||||||
|
// Any lowercase letter followed by an uppercase letter: a(A)
|
||||||
|
// Each match is then prefixed by a "-" via the ToHtmlCase method.
|
||||||
|
private static readonly Regex HtmlCaseRegex =
|
||||||
|
new Regex("(?<!^)((?<=[a-zA-Z0-9])[A-Z][a-z])|((?<=[a-z])[A-Z])", RegexOptions.None);
|
||||||
|
|
||||||
// TODO: Investigate if we should cache TagHelperDescriptors for types:
|
// TODO: Investigate if we should cache TagHelperDescriptors for types:
|
||||||
// https://github.com/aspnet/Razor/issues/165
|
// https://github.com/aspnet/Razor/issues/165
|
||||||
|
|
@ -29,21 +38,19 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
var tagNames = GetTagNames(type);
|
var tagNames = GetTagNames(type);
|
||||||
var typeName = type.FullName;
|
var typeName = type.FullName;
|
||||||
var attributeDescriptors = GetAttributeDescriptors(type);
|
var attributeDescriptors = GetAttributeDescriptors(type);
|
||||||
var contentBehavior = GetContentBehavior(type);
|
|
||||||
var assemblyName = type.GetTypeInfo().Assembly.GetName().Name;
|
var assemblyName = type.GetTypeInfo().Assembly.GetName().Name;
|
||||||
|
|
||||||
return tagNames.Select(tagName =>
|
return tagNames.Select(tagName =>
|
||||||
new TagHelperDescriptor(tagName,
|
new TagHelperDescriptor(tagName,
|
||||||
typeName,
|
typeName,
|
||||||
assemblyName,
|
assemblyName,
|
||||||
contentBehavior,
|
|
||||||
attributeDescriptors));
|
attributeDescriptors));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<string> GetTagNames(Type tagHelperType)
|
private static IEnumerable<string> GetTagNames(Type tagHelperType)
|
||||||
{
|
{
|
||||||
var typeInfo = tagHelperType.GetTypeInfo();
|
var typeInfo = tagHelperType.GetTypeInfo();
|
||||||
var attributes = typeInfo.GetCustomAttributes<TagNameAttribute>(inherit: false);
|
var attributes = typeInfo.GetCustomAttributes<HtmlElementNameAttribute>(inherit: false);
|
||||||
|
|
||||||
// If there isn't an attribute specifying the tag name derive it from the name
|
// If there isn't an attribute specifying the tag name derive it from the name
|
||||||
if (!attributes.Any())
|
if (!attributes.Any())
|
||||||
|
|
@ -55,7 +62,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
name = name.Substring(0, name.Length - TagHelperNameEnding.Length);
|
name = name.Substring(0, name.Length - TagHelperNameEnding.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new[] { name };
|
return new[] { ToHtmlCase(name) };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove duplicate tag names.
|
// Remove duplicate tag names.
|
||||||
|
|
@ -75,21 +82,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
var attributeNameAttribute = property.GetCustomAttribute<HtmlAttributeNameAttribute>(inherit: false);
|
var attributeNameAttribute = property.GetCustomAttribute<HtmlAttributeNameAttribute>(inherit: false);
|
||||||
var attributeName = attributeNameAttribute != null ?
|
var attributeName = attributeNameAttribute != null ?
|
||||||
attributeNameAttribute.Name :
|
attributeNameAttribute.Name :
|
||||||
property.Name;
|
ToHtmlCase(property.Name);
|
||||||
|
|
||||||
return new TagHelperAttributeDescriptor(attributeName, property.Name, property.PropertyType.FullName);
|
return new TagHelperAttributeDescriptor(attributeName, property.Name, property.PropertyType.FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ContentBehavior GetContentBehavior(Type type)
|
|
||||||
{
|
|
||||||
var typeInfo = type.GetTypeInfo();
|
|
||||||
var contentBehaviorAttribute = typeInfo.GetCustomAttribute<ContentBehaviorAttribute>(inherit: false);
|
|
||||||
|
|
||||||
return contentBehaviorAttribute != null ?
|
|
||||||
contentBehaviorAttribute.ContentBehavior :
|
|
||||||
ContentBehavior.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsValidProperty(PropertyInfo property)
|
private static bool IsValidProperty(PropertyInfo property)
|
||||||
{
|
{
|
||||||
return property.GetMethod != null &&
|
return property.GetMethod != null &&
|
||||||
|
|
@ -97,5 +94,22 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
property.SetMethod != null &&
|
property.SetMethod != null &&
|
||||||
property.SetMethod.IsPublic;
|
property.SetMethod.IsPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts from pascal/camel case to lower kebab-case.
|
||||||
|
/// </summary>
|
||||||
|
/// <example>
|
||||||
|
/// SomeThing => some-thing
|
||||||
|
/// capsONInside => caps-on-inside
|
||||||
|
/// CAPSOnOUTSIDE => caps-on-outside
|
||||||
|
/// ALLCAPS => allcaps
|
||||||
|
/// One1Two2Three3 => one1-two2-three3
|
||||||
|
/// ONE1TWO2THREE3 => one1two2three3
|
||||||
|
/// First_Second_ThirdHi => first_second_third-hi
|
||||||
|
/// </example>
|
||||||
|
private static string ToHtmlCase(string name)
|
||||||
|
{
|
||||||
|
return HtmlCaseRegex.Replace(name, HtmlCaseRegexReplacement).ToLowerInvariant();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
{
|
{
|
||||||
|
|
@ -12,28 +14,73 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
public class TagHelperExecutionContext
|
public class TagHelperExecutionContext
|
||||||
{
|
{
|
||||||
private readonly List<ITagHelper> _tagHelpers;
|
private readonly List<ITagHelper> _tagHelpers;
|
||||||
|
private readonly Func<Task> _executeChildContentAsync;
|
||||||
|
private readonly Action _startWritingScope;
|
||||||
|
private readonly Func<TextWriter> _endWritingScope;
|
||||||
|
private string _childContent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Internal for testing purposes only.
|
||||||
|
/// </summary>
|
||||||
|
internal TagHelperExecutionContext(string tagName)
|
||||||
|
: this(tagName,
|
||||||
|
uniqueId: string.Empty,
|
||||||
|
executeChildContentAsync: async () => await Task.FromResult(result: true),
|
||||||
|
startWritingScope: () => { },
|
||||||
|
endWritingScope: () => new StringWriter())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instantiates a new <see cref="TagHelperExecutionContext"/>.
|
/// Instantiates a new <see cref="TagHelperExecutionContext"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tagName">The HTML tag name in the Razor source.</param>
|
/// <param name="tagName">The HTML tag name in the Razor source.</param>
|
||||||
public TagHelperExecutionContext([NotNull] string tagName)
|
/// <param name="uniqueId">An identifier unique to the HTML element this context is for.</param>
|
||||||
|
/// <param name="executeChildContentAsync">A delegate used to execute the child content asynchronously.</param>
|
||||||
|
/// <param name="startWritingScope">A delegate used to start a writing scope in a Razor page.</param>
|
||||||
|
/// <param name="endWritingScope">A delegate used to end a writing scope in a Razor page.</param>
|
||||||
|
public TagHelperExecutionContext([NotNull] string tagName,
|
||||||
|
[NotNull] string uniqueId,
|
||||||
|
[NotNull] Func<Task> executeChildContentAsync,
|
||||||
|
[NotNull] Action startWritingScope,
|
||||||
|
[NotNull] Func<TextWriter> endWritingScope)
|
||||||
{
|
{
|
||||||
|
_tagHelpers = new List<ITagHelper>();
|
||||||
|
_executeChildContentAsync = executeChildContentAsync;
|
||||||
|
_startWritingScope = startWritingScope;
|
||||||
|
_endWritingScope = endWritingScope;
|
||||||
|
|
||||||
AllAttributes = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
AllAttributes = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||||
HTMLAttributes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
HTMLAttributes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
_tagHelpers = new List<ITagHelper>();
|
|
||||||
TagName = tagName;
|
TagName = tagName;
|
||||||
|
UniqueId = uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if <see cref="GetChildContentAsync"/> has been called.
|
||||||
|
/// </summary>
|
||||||
|
public bool ChildContentRetrieved
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _childContent != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// HTML attributes.
|
/// HTML attributes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDictionary<string, string> HTMLAttributes { get; private set; }
|
public IDictionary<string, string> HTMLAttributes { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="ITagHelper"/> bound attributes and HTML attributes.
|
/// <see cref="ITagHelper"/> bound attributes and HTML attributes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDictionary<string, object> AllAttributes { get; private set; }
|
public IDictionary<string, object> AllAttributes { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An identifier unique to the HTML element this context is for.
|
||||||
|
/// </summary>
|
||||||
|
public string UniqueId { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="ITagHelper"/>s that should be run.
|
/// <see cref="ITagHelper"/>s that should be run.
|
||||||
|
|
@ -49,7 +96,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The HTML tag name in the Razor source.
|
/// The HTML tag name in the Razor source.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TagName { get; private set; }
|
public string TagName { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="ITagHelper"/>s' output.
|
/// The <see cref="ITagHelper"/>s' output.
|
||||||
|
|
@ -85,5 +132,34 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
{
|
{
|
||||||
AllAttributes.Add(name, value);
|
AllAttributes.Add(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes the child content asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="Task"/> which on completion executes all child content.</returns>
|
||||||
|
public Task ExecuteChildContentAsync()
|
||||||
|
{
|
||||||
|
return _executeChildContentAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute and retrieve the rendered child content asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="Task"/> that on completion returns the rendered child content.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// Child content is only executed once. Successive calls to this method or successive executions of the
|
||||||
|
/// returned <see cref="Task{string}"/> return a cached result.
|
||||||
|
/// </remarks>
|
||||||
|
public async Task<string> GetChildContentAsync()
|
||||||
|
{
|
||||||
|
if (_childContent == null)
|
||||||
|
{
|
||||||
|
_startWritingScope();
|
||||||
|
await _executeChildContentAsync();
|
||||||
|
_childContent = _endWritingScope().ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _childContent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
public class TagHelperOutput
|
public class TagHelperOutput
|
||||||
{
|
{
|
||||||
private string _content;
|
private string _content;
|
||||||
private string _tagName;
|
private bool _contentSet;
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
internal TagHelperOutput(string tagName)
|
internal TagHelperOutput(string tagName)
|
||||||
|
|
@ -24,48 +24,39 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
Attributes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
Attributes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
|
||||||
internal TagHelperOutput(string tagName, [NotNull] IDictionary<string, string> attributes)
|
|
||||||
: this(tagName, attributes, string.Empty)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instantiates a new instance of <see cref="TagHelperOutput"/>.
|
/// Instantiates a new instance of <see cref="TagHelperOutput"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tagName">The HTML element's tag name.</param>
|
/// <param name="tagName">The HTML element's tag name.</param>
|
||||||
/// <param name="attributes">The HTML attributes.</param>
|
/// <param name="attributes">The HTML attributes.</param>
|
||||||
/// <param name="content">The HTML element's content.</param>
|
public TagHelperOutput(string tagName, [NotNull] IDictionary<string, string> attributes)
|
||||||
public TagHelperOutput(string tagName,
|
|
||||||
[NotNull] IDictionary<string, string> attributes,
|
|
||||||
string content)
|
|
||||||
{
|
{
|
||||||
TagName = tagName;
|
TagName = tagName;
|
||||||
Content = content;
|
|
||||||
Attributes = new Dictionary<string, string>(attributes, StringComparer.OrdinalIgnoreCase);
|
Attributes = new Dictionary<string, string>(attributes, StringComparer.OrdinalIgnoreCase);
|
||||||
|
PreContent = string.Empty;
|
||||||
|
_content = string.Empty;
|
||||||
|
PostContent = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The HTML element's tag name.
|
/// The HTML element's tag name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// A whitespace value results in no start or end tag being rendered.
|
/// A whitespace or <c>null</c> value results in no start or end tag being rendered.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public string TagName
|
public string TagName { get; set; }
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _tagName;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_tagName = value ?? string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The HTML element's content.
|
/// The HTML element's pre content.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>Value is prepended to the <see cref="ITagHelper"/>'s final output.</remarks>
|
||||||
|
public string PreContent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The HTML element's main content.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Value occurs in the <see cref="ITagHelper"/>'s final output after <see cref="PreContent"/> and
|
||||||
|
/// before <see cref="PostContent"/></remarks>
|
||||||
public string Content
|
public string Content
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -74,7 +65,25 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_content = value ?? string.Empty;
|
_contentSet = true;
|
||||||
|
_content = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The HTML element's post content.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Value is appended to the <see cref="ITagHelper"/>'s final output.</remarks>
|
||||||
|
public string PostContent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <c>true</c> if <see cref="Content"/> has been set, <c>false</c> otherwise.
|
||||||
|
/// </summary>
|
||||||
|
public bool ContentSet
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _contentSet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,7 +95,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The HTML element's attributes.
|
/// The HTML element's attributes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDictionary<string, string> Attributes { get; private set; }
|
public IDictionary<string, string> Attributes { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates the <see cref="TagHelperOutput"/>'s start tag.
|
/// Generates the <see cref="TagHelperOutput"/>'s start tag.
|
||||||
|
|
@ -126,6 +135,22 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates the <see cref="TagHelperOutput"/>'s <see cref="PreContent"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns><c>string.Empty</c> if <see cref="SelfClosing"/> is <c>true</c>. <see cref="PreContent"/>
|
||||||
|
/// otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public string GeneratePreContent()
|
||||||
|
{
|
||||||
|
if (SelfClosing)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PreContent;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates the <see cref="TagHelperOutput"/>'s body.
|
/// Generates the <see cref="TagHelperOutput"/>'s body.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -141,6 +166,22 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
return Content;
|
return Content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates the <see cref="TagHelperOutput"/>'s <see cref="PostContent"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns><c>string.Empty</c> if <see cref="SelfClosing"/> is <c>true</c>. <see cref="PostContent"/>
|
||||||
|
/// otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public string GeneratePostContent()
|
||||||
|
{
|
||||||
|
if (SelfClosing)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PostContent;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates the <see cref="TagHelperOutput"/>'s end tag.
|
/// Generates the <see cref="TagHelperOutput"/>'s end tag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -155,5 +196,20 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
|
|
||||||
return string.Format(CultureInfo.InvariantCulture, "</{0}>", TagName);
|
return string.Format(CultureInfo.InvariantCulture, "</{0}>", TagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes <see cref="TagHelperOutput"/> to generate nothing.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sets <see cref="TagName"/>, <see cref="PreContent"/>, <see cref="Content"/>, and <see cref="PostContent"/>
|
||||||
|
/// to <c>null</c> to suppress output.
|
||||||
|
/// </remarks>
|
||||||
|
public void SuppressOutput()
|
||||||
|
{
|
||||||
|
TagName = null;
|
||||||
|
PreContent = null;
|
||||||
|
Content = null;
|
||||||
|
PostContent = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
|
|
@ -14,33 +13,17 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calls the <see cref="ITagHelper.ProcessAsync"/> method on <see cref="ITagHelper"/>s.
|
/// Calls the <see cref="ITagHelper.ProcessAsync"/> method on <see cref="ITagHelper"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">Contains information associated with running <see cref="ITagHelper"/>s.</param>
|
/// <param name="executionContext">Contains information associated with running <see cref="ITagHelper"/>s.
|
||||||
|
/// </param>
|
||||||
/// <returns>Resulting <see cref="TagHelperOutput"/> from processing all of the
|
/// <returns>Resulting <see cref="TagHelperOutput"/> from processing all of the
|
||||||
/// <paramref name="context"/>'s <see cref="ITagHelper"/>s.</returns>
|
/// <paramref name="executionContext"/>'s <see cref="ITagHelper"/>s.</returns>
|
||||||
public async Task<TagHelperOutput> RunAsync([NotNull] TagHelperExecutionContext context)
|
public async Task<TagHelperOutput> RunAsync([NotNull] TagHelperExecutionContext executionContext)
|
||||||
{
|
{
|
||||||
return await RunAsyncCore(context, string.Empty);
|
var tagHelperContext = new TagHelperContext(
|
||||||
}
|
executionContext.AllAttributes,
|
||||||
|
executionContext.UniqueId,
|
||||||
/// <summary>
|
executionContext.GetChildContentAsync);
|
||||||
/// Calls the <see cref="ITagHelper.ProcessAsync"/> method on <see cref="ITagHelper"/>s.
|
var tagHelperOutput = new TagHelperOutput(executionContext.TagName, executionContext.HTMLAttributes);
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">Contains information associated with running <see cref="ITagHelper"/>s.</param>
|
|
||||||
/// <param name="bufferedBody">Contains the buffered content of the current HTML tag.</param>
|
|
||||||
/// <returns>Resulting <see cref="TagHelperOutput"/> from processing all of the
|
|
||||||
/// <paramref name="context"/>'s <see cref="ITagHelper"/>s.</returns>
|
|
||||||
public async Task<TagHelperOutput> RunAsync([NotNull] TagHelperExecutionContext context,
|
|
||||||
[NotNull] TextWriter bufferedBody)
|
|
||||||
{
|
|
||||||
return await RunAsyncCore(context, bufferedBody.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<TagHelperOutput> RunAsyncCore(TagHelperExecutionContext executionContext, string outputContent)
|
|
||||||
{
|
|
||||||
var tagHelperContext = new TagHelperContext(executionContext.AllAttributes);
|
|
||||||
var tagHelperOutput = new TagHelperOutput(executionContext.TagName,
|
|
||||||
executionContext.HTMLAttributes,
|
|
||||||
outputContent);
|
|
||||||
|
|
||||||
foreach (var tagHelper in executionContext.TagHelpers)
|
foreach (var tagHelper in executionContext.TagHelpers)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
{
|
{
|
||||||
|
|
@ -25,10 +27,22 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
/// Starts a <see cref="TagHelperExecutionContext"/> scope.
|
/// Starts a <see cref="TagHelperExecutionContext"/> scope.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tagName">The HTML tag name that the scope is associated with.</param>
|
/// <param name="tagName">The HTML tag name that the scope is associated with.</param>
|
||||||
|
/// <param name="uniqueId">An identifier unique to the HTML element this scope is for.</param>
|
||||||
|
/// <param name="executeChildContentAsync">A delegate used to execute the child content asynchronously.</param>
|
||||||
|
/// <param name="startWritingScope">A delegate used to start a writing scope in a Razor page.</param>
|
||||||
|
/// <param name="endWritingScope">A delegate used to end a writing scope in a Razor page.</param>
|
||||||
/// <returns>A <see cref="TagHelperExecutionContext"/> to use.</returns>
|
/// <returns>A <see cref="TagHelperExecutionContext"/> to use.</returns>
|
||||||
public TagHelperExecutionContext Begin(string tagName)
|
public TagHelperExecutionContext Begin([NotNull] string tagName,
|
||||||
|
[NotNull] string uniqueId,
|
||||||
|
[NotNull] Func<Task> executeChildContentAsync,
|
||||||
|
[NotNull] Action startWritingScope,
|
||||||
|
[NotNull] Func<TextWriter> endWritingScope)
|
||||||
{
|
{
|
||||||
var executionContext = new TagHelperExecutionContext(tagName);
|
var executionContext = new TagHelperExecutionContext(tagName,
|
||||||
|
uniqueId,
|
||||||
|
executeChildContentAsync,
|
||||||
|
startWritingScope,
|
||||||
|
endWritingScope);
|
||||||
|
|
||||||
_executionScopes.Push(executionContext);
|
_executionScopes.Push(executionContext);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
IEnumerable<TypeInfo> libraryTypes;
|
IEnumerable<TypeInfo> libraryTypes;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
libraryTypes = GetLibraryDefinedTypes(assemblyName);
|
libraryTypes = GetExportedTypes(assemblyName);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -72,8 +72,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
return validTagHelpers.Select(type => type.AsType());
|
return validTagHelpers.Select(type => type.AsType());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing, don't want to be loading assemblies during a test.
|
/// <summary>
|
||||||
internal virtual IEnumerable<TypeInfo> GetLibraryDefinedTypes(AssemblyName assemblyName)
|
/// Returns all exported types from the given <paramref name="assemblyName"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assemblyName">The <see cref="AssemblyName"/> to get <see cref="TypeInfo"/>s from.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// An <see cref="IEnumerable{TypeInfo}"/> of types exported from the given <paramref name="assemblyName"/>.
|
||||||
|
/// </returns>
|
||||||
|
protected virtual IEnumerable<TypeInfo> GetExportedTypes(AssemblyName assemblyName)
|
||||||
{
|
{
|
||||||
var assembly = Assembly.Load(assemblyName);
|
var assembly = Assembly.Load(assemblyName);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@
|
||||||
"aspnet50": { },
|
"aspnet50": { },
|
||||||
"aspnetcore50": {
|
"aspnetcore50": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"System.Reflection.Extensions": "4.0.0-beta-*"
|
"System.Reflection.Extensions": "4.0.0-beta-*",
|
||||||
|
"System.Text.RegularExpressions": "4.0.10-beta-*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Generator
|
namespace Microsoft.AspNet.Razor.Generator
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -12,9 +14,14 @@ namespace Microsoft.AspNet.Razor.Generator
|
||||||
/// Instantiates a new instance of the <see cref="CodeBuilderContext"/> object.
|
/// Instantiates a new instance of the <see cref="CodeBuilderContext"/> object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="generatorContext">A <see cref="CodeGeneratorContext"/> to copy information from.</param>
|
/// <param name="generatorContext">A <see cref="CodeGeneratorContext"/> to copy information from.</param>
|
||||||
public CodeBuilderContext(CodeGeneratorContext generatorContext)
|
/// <param name="errorSink">
|
||||||
|
/// The <see cref="ParserErrorSink"/> used to collect <see cref="Parser.SyntaxTree.RazorError"/>s encountered
|
||||||
|
/// when parsing the current Razor document.
|
||||||
|
/// </param>
|
||||||
|
public CodeBuilderContext(CodeGeneratorContext generatorContext, ParserErrorSink errorSink)
|
||||||
: base(generatorContext)
|
: base(generatorContext)
|
||||||
{
|
{
|
||||||
|
ErrorSink = errorSink;
|
||||||
ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput;
|
ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -23,9 +30,11 @@ namespace Microsoft.AspNet.Razor.Generator
|
||||||
string className,
|
string className,
|
||||||
string rootNamespace,
|
string rootNamespace,
|
||||||
string sourceFile,
|
string sourceFile,
|
||||||
bool shouldGenerateLinePragmas)
|
bool shouldGenerateLinePragmas,
|
||||||
|
ParserErrorSink errorSink)
|
||||||
: base(host, className, rootNamespace, sourceFile, shouldGenerateLinePragmas)
|
: base(host, className, rootNamespace, sourceFile, shouldGenerateLinePragmas)
|
||||||
{
|
{
|
||||||
|
ErrorSink = errorSink;
|
||||||
ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput;
|
ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,5 +65,10 @@ namespace Microsoft.AspNet.Razor.Generator
|
||||||
/// <see cref="CodeGeneratorContext.SourceFile"/>.
|
/// <see cref="CodeGeneratorContext.SourceFile"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Checksum { get; set; }
|
public string Checksum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to aggregate <see cref="Parser.SyntaxTree.RazorError"/>s.
|
||||||
|
/// </summary>
|
||||||
|
public ParserErrorSink ErrorSink { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,6 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
// Separate the usings and the class
|
// Separate the usings and the class
|
||||||
writer.WriteLine();
|
writer.WriteLine();
|
||||||
|
|
||||||
new CSharpClassAttributeVisitor(writer, Context).Accept(Tree.Chunks);
|
|
||||||
|
|
||||||
using (BuildClassDeclaration(writer))
|
using (BuildClassDeclaration(writer))
|
||||||
{
|
{
|
||||||
if (Host.DesignTimeMode)
|
if (Host.DesignTimeMode)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
@ -57,14 +58,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
{
|
{
|
||||||
var tagHelperDescriptors = chunk.Descriptors;
|
var tagHelperDescriptors = chunk.Descriptors;
|
||||||
|
|
||||||
// Find the first content behavior that doesn't have a content behavior of None.
|
RenderBeginTagHelperScope(chunk.TagName, chunk.Children);
|
||||||
// The resolver restricts content behavior collisions so the first one that's not None will be
|
|
||||||
// the content behavior we need to abide by. None can work in unison with other ContentBehaviors.
|
|
||||||
var contentBehavior = tagHelperDescriptors.Select(descriptor => descriptor.ContentBehavior)
|
|
||||||
.FirstOrDefault(
|
|
||||||
behavior => behavior != ContentBehavior.None);
|
|
||||||
|
|
||||||
RenderBeginTagHelperScope(chunk.TagName);
|
|
||||||
|
|
||||||
RenderTagHelpersCreation(chunk);
|
RenderTagHelpersCreation(chunk);
|
||||||
|
|
||||||
|
|
@ -77,42 +71,15 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
RenderUnboundHTMLAttributes(unboundHTMLAttributes);
|
RenderUnboundHTMLAttributes(unboundHTMLAttributes);
|
||||||
|
|
||||||
switch (contentBehavior)
|
RenderRunTagHelpers();
|
||||||
{
|
|
||||||
case ContentBehavior.None:
|
RenderTagOutput(_tagHelperContext.OutputGenerateStartTagMethodName);
|
||||||
RenderRunTagHelpers(bufferedBody: false);
|
RenderTagOutput(_tagHelperContext.OutputGeneratePreContentMethodName);
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateStartTagMethodName);
|
|
||||||
RenderTagHelperBody(chunk.Children, bufferBody: false);
|
RenderTagHelperContent();
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateEndTagMethodName);
|
|
||||||
break;
|
RenderTagOutput(_tagHelperContext.OutputGeneratePostContentMethodName);
|
||||||
case ContentBehavior.Append:
|
RenderTagOutput(_tagHelperContext.OutputGenerateEndTagMethodName);
|
||||||
RenderRunTagHelpers(bufferedBody: false);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateStartTagMethodName);
|
|
||||||
RenderTagHelperBody(chunk.Children, bufferBody: false);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateContentMethodName);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateEndTagMethodName);
|
|
||||||
break;
|
|
||||||
case ContentBehavior.Prepend:
|
|
||||||
RenderRunTagHelpers(bufferedBody: false);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateStartTagMethodName);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateContentMethodName);
|
|
||||||
RenderTagHelperBody(chunk.Children, bufferBody: false);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateEndTagMethodName);
|
|
||||||
break;
|
|
||||||
case ContentBehavior.Replace:
|
|
||||||
RenderRunTagHelpers(bufferedBody: false);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateStartTagMethodName);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateContentMethodName);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateEndTagMethodName);
|
|
||||||
break;
|
|
||||||
case ContentBehavior.Modify:
|
|
||||||
RenderTagHelperBody(chunk.Children, bufferBody: true);
|
|
||||||
RenderRunTagHelpers(bufferedBody: true);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateStartTagMethodName);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateContentMethodName);
|
|
||||||
RenderTagOutput(_tagHelperContext.OutputGenerateEndTagMethodName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderEndTagHelpersScope();
|
RenderEndTagHelpersScope();
|
||||||
}
|
}
|
||||||
|
|
@ -122,11 +89,13 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
return "__" + descriptor.TypeName.Replace('.', '_');
|
return "__" + descriptor.TypeName.Replace('.', '_');
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderBeginTagHelperScope(string tagName)
|
private void RenderBeginTagHelperScope(string tagName, IList<Chunk> children)
|
||||||
{
|
{
|
||||||
// Scopes/execution contexts are a runtime feature.
|
// Scopes/execution contexts are a runtime feature.
|
||||||
if (_designTimeMode)
|
if (_designTimeMode)
|
||||||
{
|
{
|
||||||
|
// Render all of the tag helper children inline for IntelliSense.
|
||||||
|
_bodyVisitor.Accept(children);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,10 +104,50 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
_writer.WriteStartAssignment(ExecutionContextVariableName)
|
_writer.WriteStartAssignment(ExecutionContextVariableName)
|
||||||
.WriteStartInstanceMethodInvocation(ScopeManagerVariableName,
|
.WriteStartInstanceMethodInvocation(ScopeManagerVariableName,
|
||||||
_tagHelperContext.ScopeManagerBeginMethodName);
|
_tagHelperContext.ScopeManagerBeginMethodName);
|
||||||
|
|
||||||
|
// Assign a unique ID for this instance of the source HTML tag. This must be unique
|
||||||
|
// per call site, e.g. if the tag is on the view twice, there should be two IDs.
|
||||||
_writer.WriteStringLiteral(tagName)
|
_writer.WriteStringLiteral(tagName)
|
||||||
|
.WriteParameterSeparator()
|
||||||
|
.WriteStringLiteral(GenerateUniqueId())
|
||||||
|
.WriteParameterSeparator();
|
||||||
|
|
||||||
|
// We remove the target writer so TagHelper authors can retrieve content.
|
||||||
|
var oldWriter = _context.TargetWriterName;
|
||||||
|
_context.TargetWriterName = null;
|
||||||
|
|
||||||
|
// Disabling instrumentation inside TagHelper bodies since we never know if it's accurate
|
||||||
|
var oldInstrumentation = _context.Host.EnableInstrumentation;
|
||||||
|
_context.Host.EnableInstrumentation = false;
|
||||||
|
|
||||||
|
using (_writer.BuildAsyncLambda(endLine: false))
|
||||||
|
{
|
||||||
|
// Render all of the tag helper children.
|
||||||
|
_bodyVisitor.Accept(children);
|
||||||
|
}
|
||||||
|
|
||||||
|
_context.Host.EnableInstrumentation = oldInstrumentation;
|
||||||
|
|
||||||
|
_context.TargetWriterName = oldWriter;
|
||||||
|
|
||||||
|
_writer.WriteParameterSeparator()
|
||||||
|
.Write(_tagHelperContext.StartWritingScopeMethodName)
|
||||||
|
.WriteParameterSeparator()
|
||||||
|
.Write(_tagHelperContext.EndWritingScopeMethodName)
|
||||||
.WriteEndMethodInvocation();
|
.WriteEndMethodInvocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a unique ID for an HTML element.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// A globally unique ID.
|
||||||
|
/// </returns>
|
||||||
|
protected virtual string GenerateUniqueId()
|
||||||
|
{
|
||||||
|
return Guid.NewGuid().ToString("N");
|
||||||
|
}
|
||||||
|
|
||||||
private void RenderTagHelpersCreation(TagHelperChunk chunk)
|
private void RenderTagHelpersCreation(TagHelperChunk chunk)
|
||||||
{
|
{
|
||||||
var tagHelperDescriptors = chunk.Descriptors;
|
var tagHelperDescriptors = chunk.Descriptors;
|
||||||
|
|
@ -213,48 +222,67 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
tagHelperVariableName,
|
tagHelperVariableName,
|
||||||
attributeDescriptor.PropertyName);
|
attributeDescriptor.PropertyName);
|
||||||
|
|
||||||
_writer.WriteStartAssignment(valueAccessor);
|
|
||||||
|
|
||||||
// If we haven't recorded this attribute value before then we need to record its value.
|
// If we haven't recorded this attribute value before then we need to record its value.
|
||||||
if (!attributeValueRecorded)
|
if (!attributeValueRecorded)
|
||||||
{
|
{
|
||||||
// We only need to create attribute values once per HTML element (not once per tag helper).
|
// We only need to create attribute values once per HTML element (not once per tag helper).
|
||||||
// We're saving the value accessor so we can retrieve it later if there are more tag helpers that
|
// We're saving the value accessor so we can retrieve it later if there are more tag
|
||||||
// need the value.
|
// helpers that need the value.
|
||||||
htmlAttributeValues.Add(attributeDescriptor.Name, valueAccessor);
|
htmlAttributeValues.Add(attributeDescriptor.Name, valueAccessor);
|
||||||
|
|
||||||
if (bufferableAttribute)
|
if (bufferableAttribute)
|
||||||
{
|
{
|
||||||
// If the attribute is bufferable but has a plain text value that means the value
|
_writer.WriteStartAssignment(valueAccessor);
|
||||||
// is a string which needs to be surrounded in quotes.
|
|
||||||
if (isPlainTextValue)
|
if (isPlainTextValue)
|
||||||
{
|
{
|
||||||
|
// If the attribute is bufferable but has a plain text value that means the value
|
||||||
|
// is a string which needs to be surrounded in quotes.
|
||||||
RenderQuotedAttributeValue(textValue, attributeDescriptor);
|
RenderQuotedAttributeValue(textValue, attributeDescriptor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The value contains more than plain text. e.g. someAttribute="Time: @DateTime.Now"
|
// The value contains more than plain text e.g.
|
||||||
|
// stringAttribute ="Time: @DateTime.Now"
|
||||||
RenderBufferedAttributeValue(attributeDescriptor);
|
RenderBufferedAttributeValue(attributeDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_writer.WriteLine(";");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: Make complex types in non-bufferable attributes work in
|
// Write out simple assignment for non-string property value. Try to keep the whole
|
||||||
// https://github.com/aspnet/Razor/issues/129
|
// statement together and the #line pragma correct to make debugging possible.
|
||||||
if (!isPlainTextValue)
|
using (var lineMapper = new CSharpLineMappingWriter(
|
||||||
|
_writer,
|
||||||
|
attributeValueChunk.Association.Start,
|
||||||
|
_context.SourceFile))
|
||||||
{
|
{
|
||||||
|
// Place the assignment LHS to align RHS with original attribute value's indentation.
|
||||||
|
// Unfortunately originalIndent is incorrect if original line contains tabs. Unable to
|
||||||
|
// use a CSharpPaddingBuilder because the Association has no Previous node; lost the
|
||||||
|
// original Span sequence when the parse tree was rewritten.
|
||||||
|
var originalIndent = attributeValueChunk.Start.CharacterIndex;
|
||||||
|
var generatedLength = valueAccessor.Length + " = ".Length;
|
||||||
|
var newIndent = originalIndent - generatedLength;
|
||||||
|
if (newIndent > 0)
|
||||||
|
{
|
||||||
|
_writer.Indent(newIndent);
|
||||||
|
}
|
||||||
|
|
||||||
|
_writer.WriteStartAssignment(valueAccessor);
|
||||||
|
lineMapper.MarkLineMappingStart();
|
||||||
|
|
||||||
|
// Write out bare expression for this attribute value. Property is not a string.
|
||||||
|
// So quoting or buffering are not helpful.
|
||||||
|
RenderRawAttributeValue(attributeValueChunk, attributeDescriptor, isPlainTextValue);
|
||||||
|
|
||||||
|
// End the assignment to the attribute.
|
||||||
|
lineMapper.MarkLineMappingEnd();
|
||||||
_writer.WriteLine(";");
|
_writer.WriteLine(";");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We aren't a bufferable attribute which means we have no Razor code in our value.
|
|
||||||
// Therefore we can just use the "textValue" as the attribute value.
|
|
||||||
RenderRawAttributeValue(textValue, attributeDescriptor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// End the assignment to the attribute.
|
|
||||||
_writer.WriteLine(";");
|
|
||||||
|
|
||||||
// Execution contexts are a runtime feature.
|
// Execution contexts are a runtime feature.
|
||||||
if (_designTimeMode)
|
if (_designTimeMode)
|
||||||
{
|
{
|
||||||
|
|
@ -262,20 +290,23 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to inform the context of the attribute value.
|
// We need to inform the context of the attribute value.
|
||||||
_writer.WriteStartInstanceMethodInvocation(
|
_writer
|
||||||
ExecutionContextVariableName,
|
.WriteStartInstanceMethodInvocation(
|
||||||
_tagHelperContext.ExecutionContextAddTagHelperAttributeMethodName);
|
ExecutionContextVariableName,
|
||||||
|
_tagHelperContext.ExecutionContextAddTagHelperAttributeMethodName)
|
||||||
_writer.WriteStringLiteral(attributeDescriptor.Name)
|
.WriteStringLiteral(attributeDescriptor.Name)
|
||||||
.WriteParameterSeparator()
|
.WriteParameterSeparator()
|
||||||
.Write(valueAccessor)
|
.Write(valueAccessor)
|
||||||
.WriteEndMethodInvocation();
|
.WriteEndMethodInvocation();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The attribute value has already been recorded, lets retrieve it from the stored value accessors.
|
// The attribute value has already been recorded, lets retrieve it from the stored value
|
||||||
_writer.Write(htmlAttributeValues[attributeDescriptor.Name])
|
// accessors.
|
||||||
.WriteLine(";");
|
_writer
|
||||||
|
.WriteStartAssignment(valueAccessor)
|
||||||
|
.Write(htmlAttributeValues[attributeDescriptor.Name])
|
||||||
|
.WriteLine(";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -323,18 +354,74 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderTagHelperBody(IList<Chunk> children, bool bufferBody)
|
private void RenderTagHelperContent()
|
||||||
{
|
{
|
||||||
// If we want to buffer the body we need to create a writing scope to capture the body content.
|
// Rendering output is a runtime feature.
|
||||||
if (bufferBody)
|
if (_designTimeMode)
|
||||||
{
|
{
|
||||||
// Render all of the tag helper children in a buffered writing scope.
|
return;
|
||||||
BuildBufferedWritingScope(children);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
_writer.Write("if (")
|
||||||
|
.Write(ExecutionContextVariableName)
|
||||||
|
.Write(".")
|
||||||
|
.Write(_tagHelperContext.ExecutionContextOutputPropertyName)
|
||||||
|
.Write(".")
|
||||||
|
.Write(_tagHelperContext.OutputContentSetPropertyName)
|
||||||
|
.WriteLine(")");
|
||||||
|
|
||||||
|
// At this point in the codegen, TagHelperOutput.Content is set. We need to use this to render the Content
|
||||||
|
// instead of executing the child content
|
||||||
|
using (_writer.BuildScope())
|
||||||
{
|
{
|
||||||
// Render all of the tag helper children.
|
RenderTagOutput(_tagHelperContext.OutputGenerateContentMethodName);
|
||||||
_bodyVisitor.Accept(children);
|
}
|
||||||
|
|
||||||
|
_writer.Write("else if (")
|
||||||
|
.Write(ExecutionContextVariableName)
|
||||||
|
.Write(".")
|
||||||
|
.Write(_tagHelperContext.ExecutionContextChildContentRetrievedPropertyName)
|
||||||
|
.WriteLine(")");
|
||||||
|
|
||||||
|
// Render the body of the else if statement, at this point in the codegen the GetChildContentAsync method
|
||||||
|
// was invoked but the TagHelperOutput's Content was not set. Call into GetChildContentAsync to retrieve
|
||||||
|
// the cached value of the content so we don't execute the child content twice.
|
||||||
|
using (_writer.BuildScope())
|
||||||
|
{
|
||||||
|
CSharpCodeVisitor.RenderPreWriteStart(_writer, _context);
|
||||||
|
|
||||||
|
_writer.WriteInstanceMethodInvocation(ExecutionContextVariableName,
|
||||||
|
_tagHelperContext.ExecutionContextGetChildContentAsyncMethodName,
|
||||||
|
endLine: false);
|
||||||
|
|
||||||
|
_writer.Write(".Result")
|
||||||
|
.WriteEndMethodInvocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
_writer.WriteLine("else");
|
||||||
|
|
||||||
|
// Render the body of the else statement, at this point in the codegen the GetChildContentAsync method
|
||||||
|
// was not invoked and the TagHelperOutput's Content was not set. Call into ExecuteChildContentAsync to
|
||||||
|
// to execute and render child content.
|
||||||
|
using (_writer.BuildScope())
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(_context.TargetWriterName))
|
||||||
|
{
|
||||||
|
_writer.WriteMethodInvocation(
|
||||||
|
_tagHelperContext.StartWritingScopeMethodName,
|
||||||
|
_context.TargetWriterName);
|
||||||
|
}
|
||||||
|
|
||||||
|
_writer.WriteInstanceMethodInvocation(
|
||||||
|
ExecutionContextVariableName,
|
||||||
|
_tagHelperContext.ExecutionContextExecuteChildContentAsyncMethodName,
|
||||||
|
endLine: false);
|
||||||
|
_writer.WriteLine(".Wait();");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_context.TargetWriterName))
|
||||||
|
{
|
||||||
|
_writer.WriteMethodInvocation(_tagHelperContext.EndWritingScopeMethodName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -369,7 +456,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
.WriteEndMethodInvocation();
|
.WriteEndMethodInvocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderRunTagHelpers(bool bufferedBody)
|
private void RenderRunTagHelpers()
|
||||||
{
|
{
|
||||||
// No need to run anything in design time mode.
|
// No need to run anything in design time mode.
|
||||||
if (_designTimeMode)
|
if (_designTimeMode)
|
||||||
|
|
@ -383,36 +470,38 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
.Write(" = ")
|
.Write(" = ")
|
||||||
.WriteStartInstanceMethodInvocation(RunnerVariableName,
|
.WriteStartInstanceMethodInvocation(RunnerVariableName,
|
||||||
_tagHelperContext.RunnerRunAsyncMethodName);
|
_tagHelperContext.RunnerRunAsyncMethodName);
|
||||||
_writer.Write(ExecutionContextVariableName);
|
|
||||||
|
|
||||||
if (bufferedBody)
|
_writer.Write(ExecutionContextVariableName)
|
||||||
{
|
.WriteEndMethodInvocation(endLine: false)
|
||||||
_writer.WriteParameterSeparator()
|
|
||||||
.Write(StringValueBufferVariableName);
|
|
||||||
}
|
|
||||||
|
|
||||||
_writer.WriteEndMethodInvocation(endLine: false)
|
|
||||||
.WriteLine(".Result;");
|
.WriteLine(".Result;");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderBufferedAttributeValue(TagHelperAttributeDescriptor attributeDescriptor)
|
private void RenderBufferedAttributeValue(TagHelperAttributeDescriptor attributeDescriptor)
|
||||||
{
|
{
|
||||||
|
// Pass complexValue: false because variable.ToString() replaces any original complexity in the expression.
|
||||||
RenderAttributeValue(
|
RenderAttributeValue(
|
||||||
attributeDescriptor,
|
attributeDescriptor,
|
||||||
valueRenderer: (writer) =>
|
valueRenderer: (writer) =>
|
||||||
{
|
{
|
||||||
RenderBufferedAttributeValueAccessor(writer);
|
RenderBufferedAttributeValueAccessor(writer);
|
||||||
});
|
},
|
||||||
|
complexValue: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderRawAttributeValue(string value, TagHelperAttributeDescriptor attributeDescriptor)
|
private void RenderRawAttributeValue(
|
||||||
|
Chunk attributeValueChunk,
|
||||||
|
TagHelperAttributeDescriptor attributeDescriptor,
|
||||||
|
bool isPlainTextValue)
|
||||||
{
|
{
|
||||||
RenderAttributeValue(
|
RenderAttributeValue(
|
||||||
attributeDescriptor,
|
attributeDescriptor,
|
||||||
valueRenderer: (writer) =>
|
valueRenderer: (writer) =>
|
||||||
{
|
{
|
||||||
writer.Write(value);
|
var visitor =
|
||||||
});
|
new CSharpTagHelperAttributeValueVisitor(writer, _context, attributeDescriptor.TypeName);
|
||||||
|
visitor.Accept(attributeValueChunk);
|
||||||
|
},
|
||||||
|
complexValue: !isPlainTextValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderQuotedAttributeValue(string value, TagHelperAttributeDescriptor attributeDescriptor)
|
private void RenderQuotedAttributeValue(string value, TagHelperAttributeDescriptor attributeDescriptor)
|
||||||
|
|
@ -422,7 +511,8 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
valueRenderer: (writer) =>
|
valueRenderer: (writer) =>
|
||||||
{
|
{
|
||||||
writer.WriteStringLiteral(value);
|
writer.WriteStringLiteral(value);
|
||||||
});
|
},
|
||||||
|
complexValue: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildBufferedWritingScope(Chunk htmlAttributeChunk)
|
private void BuildBufferedWritingScope(Chunk htmlAttributeChunk)
|
||||||
|
|
@ -473,9 +563,15 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderAttributeValue(TagHelperAttributeDescriptor attributeDescriptor,
|
private void RenderAttributeValue(TagHelperAttributeDescriptor attributeDescriptor,
|
||||||
Action<CSharpCodeWriter> valueRenderer)
|
Action<CSharpCodeWriter> valueRenderer,
|
||||||
|
bool complexValue)
|
||||||
{
|
{
|
||||||
AttributeValueCodeRenderer.RenderAttributeValue(attributeDescriptor, _writer, _context, valueRenderer);
|
AttributeValueCodeRenderer.RenderAttributeValue(
|
||||||
|
attributeDescriptor,
|
||||||
|
_writer,
|
||||||
|
_context,
|
||||||
|
valueRenderer,
|
||||||
|
complexValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderBufferedAttributeValueAccessor(CSharpCodeWriter writer)
|
private void RenderBufferedAttributeValueAccessor(CSharpCodeWriter writer)
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using Microsoft.AspNet.Razor.Parser;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|
||||||
{
|
|
||||||
public class CSharpClassAttributeVisitor : CodeVisitor<CSharpCodeWriter>
|
|
||||||
{
|
|
||||||
public CSharpClassAttributeVisitor(CSharpCodeWriter writer, CodeBuilderContext context)
|
|
||||||
: base(writer, context)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
protected override void Visit(SessionStateChunk chunk)
|
|
||||||
{
|
|
||||||
Writer.Write("[")
|
|
||||||
.Write(typeof(RazorDirectiveAttribute).FullName)
|
|
||||||
.Write("(")
|
|
||||||
.WriteStringLiteral(SyntaxConstants.CSharp.SessionStateKeyword)
|
|
||||||
.WriteParameterSeparator()
|
|
||||||
.WriteStringLiteral(chunk.Value)
|
|
||||||
.WriteLine(")]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="CodeVisitor{CSharpCodeWriter}"/> that writes code for a non-<see langword="string"/> tag helper
|
||||||
|
/// bound attribute value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Since attribute value is not written out as HTML, does not emit instrumentation. Further this
|
||||||
|
/// <see cref="CodeVisitor{CSharpCodeWriter}"/> writes identical code at design- and runtime.
|
||||||
|
/// </remarks>
|
||||||
|
public class CSharpTagHelperAttributeValueVisitor : CodeVisitor<CSharpCodeWriter>
|
||||||
|
{
|
||||||
|
private string _attributeTypeName;
|
||||||
|
private bool _firstChild;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CSharpTagHelperAttributeValueVisitor"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="CSharpCodeWriter"/> used to write code.</param>
|
||||||
|
/// <param name="context">
|
||||||
|
/// A <see cref="CodeBuilderContext"/> instance that contains information about the current code generation
|
||||||
|
/// process.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="attributeTypeName">
|
||||||
|
/// Full name of the property <see cref="System.Type"/> for which this
|
||||||
|
/// <see cref="CSharpTagHelperAttributeValueVisitor"/> is writing the value.
|
||||||
|
/// </param>
|
||||||
|
public CSharpTagHelperAttributeValueVisitor(
|
||||||
|
CSharpCodeWriter writer,
|
||||||
|
CodeBuilderContext context,
|
||||||
|
string attributeTypeName)
|
||||||
|
: base(writer, context)
|
||||||
|
{
|
||||||
|
_attributeTypeName = attributeTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes code for the given <paramref name="chunk"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chunk">The <see cref="ChunkBlock"/> to render.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// Tracks code mappings for all children while writing.
|
||||||
|
/// </remarks>
|
||||||
|
protected override void Visit(ChunkBlock chunk)
|
||||||
|
{
|
||||||
|
// Line mappings are captured in RenderCode(), not this method.
|
||||||
|
_firstChild = true;
|
||||||
|
Accept(chunk.Children);
|
||||||
|
|
||||||
|
if (_firstChild)
|
||||||
|
{
|
||||||
|
// Attribute value was empty.
|
||||||
|
Context.ErrorSink.OnError(
|
||||||
|
chunk.Association.Start,
|
||||||
|
RazorResources.TagHelpers_AttributeExpressionRequired,
|
||||||
|
chunk.Association.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes code for the given <paramref name="chunk"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chunk">The <see cref="ExpressionBlockChunk"/> to render.</param>
|
||||||
|
protected override void Visit(ExpressionBlockChunk chunk)
|
||||||
|
{
|
||||||
|
Accept(chunk.Children);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes code for the given <paramref name="chunk"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chunk">The <see cref="ExpressionChunk"/> to render.</param>
|
||||||
|
protected override void Visit(ExpressionChunk chunk)
|
||||||
|
{
|
||||||
|
RenderCode(chunk.Code, (Span)chunk.Association);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes code for the given <paramref name="chunk"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chunk">The <see cref="LiteralChunk"/> to render.</param>
|
||||||
|
protected override void Visit(LiteralChunk chunk)
|
||||||
|
{
|
||||||
|
RenderCode(chunk.Text, (Span)chunk.Association);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes code for the given <paramref name="chunk"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chunk">The <see cref="ResolveUrlChunk"/> to render.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// Allowed to support future C# extensions. Likely "~/..." will lead to a C# compilation error but that is up
|
||||||
|
/// to the compiler.
|
||||||
|
/// </remarks>
|
||||||
|
protected override void Visit(ResolveUrlChunk chunk)
|
||||||
|
{
|
||||||
|
RenderCode(chunk.Url, (Span)chunk.Association);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes code for the given <paramref name="chunk"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chunk">The <see cref="SectionChunk"/> to render.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// Unconditionally adds a <see cref="RazorError"/> to inform user of unexpected <c>@section</c> directive.
|
||||||
|
/// </remarks>
|
||||||
|
protected override void Visit(SectionChunk chunk)
|
||||||
|
{
|
||||||
|
Context.ErrorSink.OnError(
|
||||||
|
chunk.Association.Start,
|
||||||
|
RazorResources.FormatTagHelpers_Directives_NotSupported_InAttributes(
|
||||||
|
SyntaxConstants.CSharp.SectionKeyword),
|
||||||
|
chunk.Association.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes code for the given <paramref name="chunk"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chunk">The <see cref="SetLayoutChunk"/> to render.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// Unconditionally adds a <see cref="RazorError"/> to inform user of unexpected <c>@layout</c> directive.
|
||||||
|
/// </remarks>
|
||||||
|
protected override void Visit(SetLayoutChunk chunk)
|
||||||
|
{
|
||||||
|
Context.ErrorSink.OnError(
|
||||||
|
chunk.Association.Start,
|
||||||
|
RazorResources.FormatTagHelpers_Directives_NotSupported_InAttributes(
|
||||||
|
SyntaxConstants.CSharp.LayoutKeyword),
|
||||||
|
chunk.Association.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes code for the given <paramref name="chunk"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chunk">The <see cref="StatementChunk"/> to render.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// Unconditionally adds a <see cref="RazorError"/> to inform user of unexpected code block.
|
||||||
|
/// </remarks>
|
||||||
|
protected override void Visit(StatementChunk chunk)
|
||||||
|
{
|
||||||
|
Context.ErrorSink.OnError(
|
||||||
|
chunk.Association.Start,
|
||||||
|
RazorResources.TagHelpers_CodeBlocks_NotSupported_InAttributes,
|
||||||
|
chunk.Association.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes code for the given <paramref name="chunk"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chunk">The <see cref="TemplateChunk"/> to render.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// Unconditionally adds a <see cref="RazorError"/> to inform user of unexpected template e.g.
|
||||||
|
/// <c>@<p>paragraph@</p></c>.
|
||||||
|
/// </remarks>
|
||||||
|
protected override void Visit(TemplateChunk chunk)
|
||||||
|
{
|
||||||
|
Context.ErrorSink.OnError(
|
||||||
|
chunk.Association.Start,
|
||||||
|
RazorResources.FormatTagHelpers_InlineMarkupBlocks_NotSupported_InAttributes(_attributeTypeName),
|
||||||
|
chunk.Association.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tracks the code mapping and writes code for a leaf node in the attribute value Chunk tree.
|
||||||
|
private void RenderCode(string code, Span association)
|
||||||
|
{
|
||||||
|
_firstChild = false;
|
||||||
|
using (new CSharpLineMappingWriter(Writer, association.Start, code.Length))
|
||||||
|
{
|
||||||
|
Writer.Write(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -34,9 +34,13 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
// Runtime fields aren't useful during design time.
|
// Runtime fields aren't useful during design time.
|
||||||
if (!Context.Host.DesignTimeMode)
|
if (!Context.Host.DesignTimeMode)
|
||||||
{
|
{
|
||||||
|
// Need to disable the warning "X is assigned to but never used." for the value buffer since
|
||||||
|
// whether it's used depends on how a TagHelper is used.
|
||||||
|
Writer.WritePragma("warning disable 0414");
|
||||||
WritePrivateField(typeof(TextWriter).FullName,
|
WritePrivateField(typeof(TextWriter).FullName,
|
||||||
CSharpTagHelperCodeRenderer.StringValueBufferVariableName,
|
CSharpTagHelperCodeRenderer.StringValueBufferVariableName,
|
||||||
value: null);
|
value: null);
|
||||||
|
Writer.WritePragma("warning restore 0414");
|
||||||
|
|
||||||
WritePrivateField(_tagHelperContext.ExecutionContextTypeName,
|
WritePrivateField(_tagHelperContext.ExecutionContextTypeName,
|
||||||
CSharpTagHelperCodeRenderer.ExecutionContextVariableName,
|
CSharpTagHelperCodeRenderer.ExecutionContextVariableName,
|
||||||
|
|
|
||||||
|
|
@ -113,10 +113,6 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||||
{
|
{
|
||||||
Visit((ChunkBlock)chunk);
|
Visit((ChunkBlock)chunk);
|
||||||
}
|
}
|
||||||
else if (chunk is SessionStateChunk)
|
|
||||||
{
|
|
||||||
Visit((SessionStateChunk)chunk);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void Visit(LiteralChunk chunk);
|
protected abstract void Visit(LiteralChunk chunk);
|
||||||
|
|
@ -138,6 +134,5 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||||
protected abstract void Visit(TemplateChunk chunk);
|
protected abstract void Visit(TemplateChunk chunk);
|
||||||
protected abstract void Visit(SetLayoutChunk chunk);
|
protected abstract void Visit(SetLayoutChunk chunk);
|
||||||
protected abstract void Visit(ExpressionBlockChunk chunk);
|
protected abstract void Visit(ExpressionBlockChunk chunk);
|
||||||
protected abstract void Visit(SessionStateChunk chunk);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,5 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||||
protected override void Visit(SetLayoutChunk chunk)
|
protected override void Visit(SetLayoutChunk chunk)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
protected override void Visit(SessionStateChunk chunk)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Generator.Compiler
|
|
||||||
{
|
|
||||||
public class SessionStateChunk : Chunk
|
|
||||||
{
|
|
||||||
public string Value { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -145,14 +145,6 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||||
}, association, topLevel: true);
|
}, association, topLevel: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSessionStateChunk(string value, SyntaxTreeNode association)
|
|
||||||
{
|
|
||||||
AddChunk(new SessionStateChunk
|
|
||||||
{
|
|
||||||
Value = value
|
|
||||||
}, association, topLevel: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T StartChunkBlock<T>(SyntaxTreeNode association) where T : ChunkBlock, new()
|
public T StartChunkBlock<T>(SyntaxTreeNode association) where T : ChunkBlock, new()
|
||||||
{
|
{
|
||||||
return StartChunkBlock<T>(association, topLevel: false);
|
return StartChunkBlock<T>(association, topLevel: false);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Generator.Compiler
|
namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||||
{
|
{
|
||||||
public class LineMapping
|
public class LineMapping
|
||||||
|
|
@ -40,5 +42,10 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||||
{
|
{
|
||||||
return !left.Equals(right);
|
return !left.Equals(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentUICulture, "{0} -> {1}", DocumentLocation, GeneratedLocation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
using Microsoft.AspNet.Razor.Text;
|
using Microsoft.AspNet.Razor.Text;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Generator.Compiler
|
namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||||
|
|
@ -37,6 +38,16 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||||
return base.GetHashCode();
|
return base.GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Format(
|
||||||
|
CultureInfo.CurrentCulture, "({0}:{1},{2} [{3}])",
|
||||||
|
AbsoluteIndex,
|
||||||
|
LineIndex,
|
||||||
|
CharacterIndex,
|
||||||
|
ContentLength);
|
||||||
|
}
|
||||||
|
|
||||||
public static bool operator ==(MappingLocation left, MappingLocation right)
|
public static bool operator ==(MappingLocation left, MappingLocation right)
|
||||||
{
|
{
|
||||||
return left.Equals(right);
|
return left.Equals(right);
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,15 @@ namespace Microsoft.AspNet.Razor.Generator
|
||||||
RunnerRunAsyncMethodName = "RunAsync";
|
RunnerRunAsyncMethodName = "RunAsync";
|
||||||
ScopeManagerBeginMethodName = "Begin";
|
ScopeManagerBeginMethodName = "Begin";
|
||||||
ScopeManagerEndMethodName = "End";
|
ScopeManagerEndMethodName = "End";
|
||||||
|
OutputContentSetPropertyName = "ContentSet";
|
||||||
OutputGenerateStartTagMethodName = "GenerateStartTag";
|
OutputGenerateStartTagMethodName = "GenerateStartTag";
|
||||||
|
OutputGeneratePreContentMethodName = "GeneratePreContent";
|
||||||
OutputGenerateContentMethodName = "GenerateContent";
|
OutputGenerateContentMethodName = "GenerateContent";
|
||||||
|
OutputGeneratePostContentMethodName = "GeneratePostContent";
|
||||||
OutputGenerateEndTagMethodName = "GenerateEndTag";
|
OutputGenerateEndTagMethodName = "GenerateEndTag";
|
||||||
|
ExecutionContextChildContentRetrievedPropertyName = "ChildContentRetrieved";
|
||||||
|
ExecutionContextExecuteChildContentAsyncMethodName = "ExecuteChildContentAsync";
|
||||||
|
ExecutionContextGetChildContentAsyncMethodName = "GetChildContentAsync";
|
||||||
ExecutionContextAddMethodName = "Add";
|
ExecutionContextAddMethodName = "Add";
|
||||||
ExecutionContextAddTagHelperAttributeMethodName = "AddTagHelperAttribute";
|
ExecutionContextAddTagHelperAttributeMethodName = "AddTagHelperAttribute";
|
||||||
ExecutionContextAddHtmlAttributeMethodName = "AddHtmlAttribute";
|
ExecutionContextAddHtmlAttributeMethodName = "AddHtmlAttribute";
|
||||||
|
|
@ -51,21 +57,52 @@ namespace Microsoft.AspNet.Razor.Generator
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ScopeManagerEndMethodName { get; set; }
|
public string ScopeManagerEndMethodName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the property used to determine if a tag helper output's content was set.
|
||||||
|
/// </summary>
|
||||||
|
public string OutputContentSetPropertyName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the method used to generate a tag helper output's start tag.
|
/// The name of the method used to generate a tag helper output's start tag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OutputGenerateStartTagMethodName { get; set; }
|
public string OutputGenerateStartTagMethodName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the method used to generate a tag helper output's pre content.
|
||||||
|
/// </summary>
|
||||||
|
public string OutputGeneratePreContentMethodName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the method used to generate a tag helper output's content.
|
/// The name of the method used to generate a tag helper output's content.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OutputGenerateContentMethodName { get; set; }
|
public string OutputGenerateContentMethodName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the method used to generate a tag helper output's post-content.
|
||||||
|
/// </summary>
|
||||||
|
public string OutputGeneratePostContentMethodName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the method used to generate a tag helper output's end tag.
|
/// The name of the method used to generate a tag helper output's end tag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OutputGenerateEndTagMethodName { get; set; }
|
public string OutputGenerateEndTagMethodName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the <see cref="ExecutionContextTypeName"/> method used to get a
|
||||||
|
/// <see cref="System.Threading.Tasks.Task"/> that executes tag helper child content.
|
||||||
|
/// </summary>
|
||||||
|
public string ExecutionContextChildContentRetrievedPropertyName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public string ExecutionContextExecuteChildContentAsyncMethodName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the <see cref="ExecutionContextTypeName"/> method used to execute and retrieve tag helper
|
||||||
|
/// child content.
|
||||||
|
/// </summary>
|
||||||
|
public string ExecutionContextGetChildContentAsyncMethodName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the <see cref="ExecutionContextTypeName"/> method used to add tag helper attributes.
|
/// The name of the <see cref="ExecutionContextTypeName"/> method used to add tag helper attributes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.AspNet.Razor.Parser;
|
|
||||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Generator
|
|
||||||
{
|
|
||||||
public class RazorDirectiveAttributeCodeGenerator : SpanCodeGenerator
|
|
||||||
{
|
|
||||||
public RazorDirectiveAttributeCodeGenerator(string name, string value)
|
|
||||||
{
|
|
||||||
if (String.IsNullOrEmpty(name))
|
|
||||||
{
|
|
||||||
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "name");
|
|
||||||
}
|
|
||||||
Name = name;
|
|
||||||
Value = value ?? String.Empty; // Coerce to empty string if it was null.
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name { get; private set; }
|
|
||||||
|
|
||||||
public string Value { get; private set; }
|
|
||||||
|
|
||||||
public override void GenerateCode(Span target, CodeGeneratorContext context)
|
|
||||||
{
|
|
||||||
if (Name == SyntaxConstants.CSharp.SessionStateKeyword)
|
|
||||||
{
|
|
||||||
context.CodeTreeBuilder.AddSessionStateChunk(Value, target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return "Directive: " + Name + ", Value: " + Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
var other = obj as RazorDirectiveAttributeCodeGenerator;
|
|
||||||
return other != null &&
|
|
||||||
Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
Value.Equals(other.Value, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return Tuple.Create(Name.ToUpperInvariant(), Value.ToUpperInvariant())
|
|
||||||
.GetHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,10 +3,12 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
using Microsoft.AspNet.Razor.Parser.TagHelpers;
|
using Microsoft.AspNet.Razor.Parser.TagHelpers;
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
|
using Microsoft.AspNet.Razor.Text;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Generator
|
namespace Microsoft.AspNet.Razor.Generator
|
||||||
{
|
{
|
||||||
|
|
@ -60,10 +62,13 @@ namespace Microsoft.AspNet.Razor.Generator
|
||||||
attribute.Value.Accept(codeGenerator);
|
attribute.Value.Accept(codeGenerator);
|
||||||
|
|
||||||
var chunks = codeGenerator.Context.CodeTreeBuilder.CodeTree.Chunks;
|
var chunks = codeGenerator.Context.CodeTreeBuilder.CodeTree.Chunks;
|
||||||
|
var first = chunks.FirstOrDefault();
|
||||||
|
|
||||||
attributes[attribute.Key] = new ChunkBlock
|
attributes[attribute.Key] = new ChunkBlock
|
||||||
{
|
{
|
||||||
Children = chunks
|
Association = first?.Association,
|
||||||
|
Children = chunks,
|
||||||
|
Start = first == null ? SourceLocation.Zero : first.Start
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reset the code tree builder so we can build a new one for the next attribute
|
// Reset the code tree builder so we can build a new one for the next attribute
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||||
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
|
|
||||||
|
|
@ -24,7 +25,7 @@ namespace Microsoft.AspNet.Razor
|
||||||
[NotNull] CodeTree codeTree)
|
[NotNull] CodeTree codeTree)
|
||||||
: this(parserResults.Document,
|
: this(parserResults.Document,
|
||||||
parserResults.TagHelperDescriptors,
|
parserResults.TagHelperDescriptors,
|
||||||
parserResults.ParserErrors,
|
parserResults.ErrorSink,
|
||||||
codeBuilderResult,
|
codeBuilderResult,
|
||||||
codeTree)
|
codeTree)
|
||||||
{
|
{
|
||||||
|
|
@ -34,35 +35,21 @@ namespace Microsoft.AspNet.Razor
|
||||||
/// Instantiates a new <see cref="GeneratorResults"/> instance.
|
/// Instantiates a new <see cref="GeneratorResults"/> instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="document">The <see cref="Block"/> for the syntax tree.</param>
|
/// <param name="document">The <see cref="Block"/> for the syntax tree.</param>
|
||||||
/// <param name="tagHelperDescriptors"><see cref="TagHelperDescriptor"/>s for the document.</param>
|
/// <param name="tagHelperDescriptors">
|
||||||
/// <param name="parserErrors"><see cref="RazorError"/>s encountered when parsing the document.</param>
|
/// The <see cref="TagHelperDescriptor"/>s that apply to the current Razor document.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="errorSink">
|
||||||
|
/// The <see cref="ParserErrorSink"/> used to collect <see cref="RazorError"/>s encountered when parsing the
|
||||||
|
/// current Razor document.
|
||||||
|
/// </param>
|
||||||
/// <param name="codeBuilderResult">The results of generating code for the document.</param>
|
/// <param name="codeBuilderResult">The results of generating code for the document.</param>
|
||||||
/// <param name="codeTree">A <see cref="CodeTree"/> for the document.</param>
|
/// <param name="codeTree">A <see cref="CodeTree"/> for the document.</param>
|
||||||
public GeneratorResults([NotNull] Block document,
|
public GeneratorResults([NotNull] Block document,
|
||||||
[NotNull] IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
|
[NotNull] IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
|
||||||
[NotNull] IList<RazorError> parserErrors,
|
[NotNull] ParserErrorSink errorSink,
|
||||||
[NotNull] CodeBuilderResult codeBuilderResult,
|
[NotNull] CodeBuilderResult codeBuilderResult,
|
||||||
[NotNull] CodeTree codeTree)
|
[NotNull] CodeTree codeTree)
|
||||||
: this(parserErrors.Count == 0, document, tagHelperDescriptors, parserErrors, codeBuilderResult, codeTree)
|
: base(document, tagHelperDescriptors, errorSink)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Instantiates a new <see cref="GeneratorResults"/> instance.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="success"><c>true</c> if parsing was successful, <c>false</c> otherwise.</param>
|
|
||||||
/// <param name="document">The <see cref="Block"/> for the syntax tree.</param>
|
|
||||||
/// <param name="tagHelperDescriptors"><see cref="TagHelperDescriptor"/>s for the document.</param>
|
|
||||||
/// <param name="parserErrors"><see cref="RazorError"/>s encountered when parsing the document.</param>
|
|
||||||
/// <param name="codeBuilderResult">The results of generating code for the document.</param>
|
|
||||||
/// <param name="codeTree">A <see cref="CodeTree"/> for the document.</param>
|
|
||||||
protected GeneratorResults(bool success,
|
|
||||||
[NotNull] Block document,
|
|
||||||
[NotNull] IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
|
|
||||||
[NotNull] IList<RazorError> parserErrors,
|
|
||||||
[NotNull] CodeBuilderResult codeBuilderResult,
|
|
||||||
[NotNull] CodeTree codeTree)
|
|
||||||
: base(success, document, tagHelperDescriptors, parserErrors)
|
|
||||||
{
|
{
|
||||||
GeneratedCode = codeBuilderResult.Code;
|
GeneratedCode = codeBuilderResult.Code;
|
||||||
DesignTimeLineMappings = codeBuilderResult.DesignTimeLineMappings;
|
DesignTimeLineMappings = codeBuilderResult.DesignTimeLineMappings;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
MapDirectives(SectionDirective, SyntaxConstants.CSharp.SectionKeyword);
|
MapDirectives(SectionDirective, SyntaxConstants.CSharp.SectionKeyword);
|
||||||
MapDirectives(HelperDirective, SyntaxConstants.CSharp.HelperKeyword);
|
MapDirectives(HelperDirective, SyntaxConstants.CSharp.HelperKeyword);
|
||||||
MapDirectives(LayoutDirective, SyntaxConstants.CSharp.LayoutKeyword);
|
MapDirectives(LayoutDirective, SyntaxConstants.CSharp.LayoutKeyword);
|
||||||
MapDirectives(SessionStateDirective, SyntaxConstants.CSharp.SessionStateKeyword);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddTagHelperDirective()
|
protected virtual void AddTagHelperDirective()
|
||||||
|
|
@ -58,65 +57,6 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
Output(SpanKind.MetaCode, foundNewline ? AcceptedCharacters.None : AcceptedCharacters.Any);
|
Output(SpanKind.MetaCode, foundNewline ? AcceptedCharacters.None : AcceptedCharacters.Any);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void SessionStateDirective()
|
|
||||||
{
|
|
||||||
AssertDirective(SyntaxConstants.CSharp.SessionStateKeyword);
|
|
||||||
AcceptAndMoveNext();
|
|
||||||
|
|
||||||
SessionStateDirectiveCore();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void SessionStateDirectiveCore()
|
|
||||||
{
|
|
||||||
SessionStateTypeDirective(RazorResources.ParserEror_SessionDirectiveMissingValue, (key, value) => new RazorDirectiveAttributeCodeGenerator(key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void SessionStateTypeDirective(string noValueError, Func<string, string, SpanCodeGenerator> createCodeGenerator)
|
|
||||||
{
|
|
||||||
// Set the block type
|
|
||||||
Context.CurrentBlock.Type = BlockType.Directive;
|
|
||||||
|
|
||||||
// Accept whitespace
|
|
||||||
var remainingWs = AcceptSingleWhiteSpaceCharacter();
|
|
||||||
|
|
||||||
if (Span.Symbols.Count > 1)
|
|
||||||
{
|
|
||||||
Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Output(SpanKind.MetaCode);
|
|
||||||
|
|
||||||
if (remainingWs != null)
|
|
||||||
{
|
|
||||||
Accept(remainingWs);
|
|
||||||
}
|
|
||||||
AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true));
|
|
||||||
|
|
||||||
// Parse a Type Name
|
|
||||||
if (!ValidSessionStateValue())
|
|
||||||
{
|
|
||||||
Context.OnError(CurrentLocation, noValueError);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pull out the type name
|
|
||||||
var sessionStateValue = String.Concat(
|
|
||||||
Span.Symbols
|
|
||||||
.Cast<CSharpSymbol>()
|
|
||||||
.Select(sym => sym.Content)).Trim();
|
|
||||||
|
|
||||||
// Set up code generation
|
|
||||||
Span.CodeGenerator = createCodeGenerator(SyntaxConstants.CSharp.SessionStateKeyword, sessionStateValue);
|
|
||||||
|
|
||||||
// Output the span and finish the block
|
|
||||||
CompleteBlock();
|
|
||||||
Output(SpanKind.Code);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual bool ValidSessionStateValue()
|
|
||||||
{
|
|
||||||
return Optional(CSharpSymbolType.Identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
[SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Coupling will be reviewed at a later date")]
|
[SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Coupling will be reviewed at a later date")]
|
||||||
[SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "C# Keywords are always lower-case")]
|
[SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "C# Keywords are always lower-case")]
|
||||||
protected virtual void HelperDirective()
|
protected virtual void HelperDirective()
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
"namespace",
|
"namespace",
|
||||||
"class",
|
"class",
|
||||||
"layout",
|
"layout",
|
||||||
"sessionstate"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private Dictionary<string, Action> _directiveParsers = new Dictionary<string, Action>();
|
private Dictionary<string, Action> _directiveParsers = new Dictionary<string, Action>();
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
// TagHelperDescriptors are not found by default. The RazorParser is responsible
|
// TagHelperDescriptors are not found by default. The RazorParser is responsible
|
||||||
// for identifying TagHelperDescriptors and rebuilding ParserResults.
|
// for identifying TagHelperDescriptors and rebuilding ParserResults.
|
||||||
tagHelperDescriptors: Enumerable.Empty<TagHelperDescriptor>(),
|
tagHelperDescriptors: Enumerable.Empty<TagHelperDescriptor>(),
|
||||||
parserErrors: _errorSink.Errors.ToList());
|
errorSink: _errorSink);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Conditional("DEBUG")]
|
[Conditional("DEBUG")]
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the new result
|
// Return the new result
|
||||||
return new ParserResults(syntaxTree, descriptors, errorSink.Errors.ToList());
|
return new ParserResults(syntaxTree, descriptors, errorSink);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
public static readonly string NamespaceKeyword = "namespace";
|
public static readonly string NamespaceKeyword = "namespace";
|
||||||
public static readonly string ClassKeyword = "class";
|
public static readonly string ClassKeyword = "class";
|
||||||
public static readonly string LayoutKeyword = "layout";
|
public static readonly string LayoutKeyword = "layout";
|
||||||
public static readonly string SessionStateKeyword = "sessionstate";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
using Microsoft.AspNet.Razor.Text;
|
using Microsoft.AspNet.Razor.Text;
|
||||||
using Microsoft.Internal.Web.Utils;
|
using Microsoft.Internal.Web.Utils;
|
||||||
|
|
||||||
|
|
@ -27,6 +28,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
: base(source.Type, source.Children, source.CodeGenerator)
|
: base(source.Type, source.Children, source.CodeGenerator)
|
||||||
{
|
{
|
||||||
TagName = source.TagName;
|
TagName = source.TagName;
|
||||||
|
Descriptors = source.Descriptors;
|
||||||
Attributes = new Dictionary<string, SyntaxTreeNode>(source.Attributes);
|
Attributes = new Dictionary<string, SyntaxTreeNode>(source.Attributes);
|
||||||
_start = source.Start;
|
_start = source.Start;
|
||||||
|
|
||||||
|
|
@ -38,6 +40,11 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="TagHelperDescriptor"/>s for the HTML element.
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<TagHelperDescriptor> Descriptors { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The HTML attributes.
|
/// The HTML attributes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// 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.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.AspNet.Razor.Generator;
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
using Microsoft.AspNet.Razor.Text;
|
using Microsoft.AspNet.Razor.Text;
|
||||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
{
|
{
|
||||||
|
|
@ -18,7 +15,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
public class TagHelperBlockBuilder : BlockBuilder
|
public class TagHelperBlockBuilder : BlockBuilder
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instantiates a new <see cref="TagHelperBlockBuilder"/> instance based on given the
|
/// Instantiates a new <see cref="TagHelperBlockBuilder"/> instance based on the given
|
||||||
/// <paramref name="original"/>.
|
/// <paramref name="original"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="original">The original <see cref="TagHelperBlock"/> to copy data from.</param>
|
/// <param name="original">The original <see cref="TagHelperBlock"/> to copy data from.</param>
|
||||||
|
|
@ -26,6 +23,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
: base(original)
|
: base(original)
|
||||||
{
|
{
|
||||||
TagName = original.TagName;
|
TagName = original.TagName;
|
||||||
|
Descriptors = original.Descriptors;
|
||||||
Attributes = new Dictionary<string, SyntaxTreeNode>(original.Attributes);
|
Attributes = new Dictionary<string, SyntaxTreeNode>(original.Attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,19 +33,21 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
/// and <see cref="BlockBuilder.Type"/> from the <paramref name="startTag"/>.
|
/// and <see cref="BlockBuilder.Type"/> from the <paramref name="startTag"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tagName">An HTML tag name.</param>
|
/// <param name="tagName">An HTML tag name.</param>
|
||||||
|
/// <param name="start">Starting location of the <see cref="TagHelperBlock"/>.</param>
|
||||||
|
/// <param name="attributes">Attributes of the <see cref="TagHelperBlock"/>.</param>
|
||||||
/// <param name="descriptors">The <see cref="TagHelperDescriptor"/>s associated with the current HTML
|
/// <param name="descriptors">The <see cref="TagHelperDescriptor"/>s associated with the current HTML
|
||||||
/// tag.</param>
|
/// tag.</param>
|
||||||
/// <param name="startTag">The <see cref="Block"/> that contains all information about the start
|
public TagHelperBlockBuilder(string tagName,
|
||||||
/// of the HTML element.</param>
|
SourceLocation start,
|
||||||
public TagHelperBlockBuilder(string tagName, IEnumerable<TagHelperDescriptor> descriptors, Block startTag)
|
IDictionary<string, SyntaxTreeNode> attributes,
|
||||||
|
IEnumerable<TagHelperDescriptor> descriptors)
|
||||||
{
|
{
|
||||||
TagName = tagName;
|
TagName = tagName;
|
||||||
|
Start = start;
|
||||||
|
Descriptors = descriptors;
|
||||||
|
Type = BlockType.Tag;
|
||||||
CodeGenerator = new TagHelperCodeGenerator(descriptors);
|
CodeGenerator = new TagHelperCodeGenerator(descriptors);
|
||||||
Type = startTag.Type;
|
Attributes = new Dictionary<string, SyntaxTreeNode>(attributes);
|
||||||
Attributes = GetTagAttributes(startTag, descriptors);
|
|
||||||
|
|
||||||
// There will always be at least one child for the '<'.
|
|
||||||
Start = startTag.Children.First().Start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
// Internal for testing
|
||||||
|
|
@ -67,6 +67,11 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="TagHelperDescriptor"/>s for the HTML element.
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<TagHelperDescriptor> Descriptors { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The HTML attributes.
|
/// The HTML attributes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -106,280 +111,5 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
||||||
/// The starting <see cref="SourceLocation"/> of the tag helper.
|
/// The starting <see cref="SourceLocation"/> of the tag helper.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SourceLocation Start { get; private set; }
|
public SourceLocation Start { get; private set; }
|
||||||
|
|
||||||
private static IDictionary<string, SyntaxTreeNode> GetTagAttributes(
|
|
||||||
Block tagBlock,
|
|
||||||
IEnumerable<TagHelperDescriptor> descriptors)
|
|
||||||
{
|
|
||||||
var attributes = new Dictionary<string, SyntaxTreeNode>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
// Build a dictionary so we can easily lookup expected attribute value lookups
|
|
||||||
IReadOnlyDictionary<string, string> attributeValueTypes =
|
|
||||||
descriptors.SelectMany(descriptor => descriptor.Attributes)
|
|
||||||
.Distinct(TagHelperAttributeDescriptorComparer.Default)
|
|
||||||
.ToDictionary(descriptor => descriptor.Name,
|
|
||||||
descriptor => descriptor.TypeName,
|
|
||||||
StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
// We skip the first child "<tagname" and take everything up to the "ending" portion of the tag ">" or "/>".
|
|
||||||
// The -2 accounts for both the start and end tags.
|
|
||||||
var attributeChildren = tagBlock.Children.Skip(1).Take(tagBlock.Children.Count() - 2);
|
|
||||||
|
|
||||||
foreach (var child in attributeChildren)
|
|
||||||
{
|
|
||||||
KeyValuePair<string, SyntaxTreeNode> attribute;
|
|
||||||
|
|
||||||
if (child.IsBlock)
|
|
||||||
{
|
|
||||||
attribute = ParseBlock((Block)child, attributeValueTypes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
attribute = ParseSpan((Span)child, attributeValueTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
attributes.Add(attribute.Key, attribute.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method handles cases when the attribute is a simple span attribute such as
|
|
||||||
// class="something moresomething". This does not handle complex attributes such as
|
|
||||||
// class="@myclass". Therefore the span.Content is equivalent to the entire attribute.
|
|
||||||
private static KeyValuePair<string, SyntaxTreeNode> ParseSpan(
|
|
||||||
Span span,
|
|
||||||
IReadOnlyDictionary<string, string> attributeValueTypes)
|
|
||||||
{
|
|
||||||
var afterEquals = false;
|
|
||||||
var builder = new SpanBuilder
|
|
||||||
{
|
|
||||||
CodeGenerator = span.CodeGenerator,
|
|
||||||
EditHandler = span.EditHandler,
|
|
||||||
Kind = span.Kind
|
|
||||||
};
|
|
||||||
var htmlSymbols = span.Symbols.OfType<HtmlSymbol>().ToArray();
|
|
||||||
var symbolOffset = 1;
|
|
||||||
string name = null;
|
|
||||||
|
|
||||||
// Iterate down through the symbols to find the name and the start of the value.
|
|
||||||
// We subtract the symbolOffset so we don't accept an ending quote of a span.
|
|
||||||
for (var i = 0; i < htmlSymbols.Length - symbolOffset; i++)
|
|
||||||
{
|
|
||||||
var symbol = htmlSymbols[i];
|
|
||||||
|
|
||||||
if (name == null && symbol.Type == HtmlSymbolType.Text)
|
|
||||||
{
|
|
||||||
name = symbol.Content;
|
|
||||||
}
|
|
||||||
else if (afterEquals)
|
|
||||||
{
|
|
||||||
builder.Accept(symbol);
|
|
||||||
}
|
|
||||||
else if (symbol.Type == HtmlSymbolType.Equals)
|
|
||||||
{
|
|
||||||
// We've found an '=' symbol, this means that the coming symbols will either be a quote
|
|
||||||
// or value (in the case that the value is unquoted).
|
|
||||||
// Spaces after/before the equal symbol are not yet supported:
|
|
||||||
// https://github.com/aspnet/Razor/issues/123
|
|
||||||
|
|
||||||
// TODO: Handle malformed tags, if there's an '=' then there MUST be a value.
|
|
||||||
// https://github.com/aspnet/Razor/issues/104
|
|
||||||
|
|
||||||
// Check for attribute start values, aka single or double quote
|
|
||||||
if (IsQuote(htmlSymbols[i + 1]))
|
|
||||||
{
|
|
||||||
// Move past the attribute start so we can accept the true value.
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set the symbol offset to 0 so we don't attempt to skip an end quote that doesn't exist.
|
|
||||||
symbolOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEquals = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return CreateMarkupAttribute(name, builder, attributeValueTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static KeyValuePair<string, SyntaxTreeNode> ParseBlock(
|
|
||||||
Block block,
|
|
||||||
IReadOnlyDictionary<string, string> attributeValueTypes)
|
|
||||||
{
|
|
||||||
// TODO: Accept more than just spans: https://github.com/aspnet/Razor/issues/96.
|
|
||||||
// The first child will only ever NOT be a Span if a user is doing something like:
|
|
||||||
// <input @checked />
|
|
||||||
|
|
||||||
var childSpan = block.Children.First() as Span;
|
|
||||||
|
|
||||||
if (childSpan == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(RazorResources.TagHelpers_CannotHaveCSharpInTagDeclaration);
|
|
||||||
}
|
|
||||||
|
|
||||||
var builder = new BlockBuilder(block);
|
|
||||||
|
|
||||||
// If there's only 1 child it means that it's plain text inside of the attribute.
|
|
||||||
// i.e. <div class="plain text in attribute">
|
|
||||||
if (builder.Children.Count == 1)
|
|
||||||
{
|
|
||||||
return ParseSpan(childSpan, attributeValueTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
var textSymbol = childSpan.Symbols.FirstHtmlSymbolAs(HtmlSymbolType.Text);
|
|
||||||
var name = textSymbol != null ? textSymbol.Content : null;
|
|
||||||
|
|
||||||
if (name == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(RazorResources.TagHelpers_AttributesMustHaveAName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove first child i.e. foo="
|
|
||||||
builder.Children.RemoveAt(0);
|
|
||||||
|
|
||||||
// Grabbing last child to check if the attribute value is quoted.
|
|
||||||
var endNode = block.Children.Last();
|
|
||||||
if (!endNode.IsBlock)
|
|
||||||
{
|
|
||||||
var endSpan = (Span)endNode;
|
|
||||||
var endSymbol = (HtmlSymbol)endSpan.Symbols.Last();
|
|
||||||
|
|
||||||
// Checking to see if it's a quoted attribute, if so we should remove end quote
|
|
||||||
if (IsQuote(endSymbol))
|
|
||||||
{
|
|
||||||
builder.Children.RemoveAt(builder.Children.Count - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to rebuild the code generators of the builder and its children (this is needed to
|
|
||||||
// ensure we don't do special attribute code generation since this is a tag helper).
|
|
||||||
block = RebuildCodeGenerators(builder.Build());
|
|
||||||
|
|
||||||
// If there's only 1 child at this point its value could be a simple markup span (treated differently than
|
|
||||||
// block level elements for attributes).
|
|
||||||
if (block.Children.Count() == 1)
|
|
||||||
{
|
|
||||||
var child = block.Children.First() as Span;
|
|
||||||
|
|
||||||
if (child != null)
|
|
||||||
{
|
|
||||||
// After pulling apart the block we just have a value span.
|
|
||||||
|
|
||||||
var spanBuilder = new SpanBuilder(child);
|
|
||||||
|
|
||||||
return CreateMarkupAttribute(name, spanBuilder, attributeValueTypes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new KeyValuePair<string, SyntaxTreeNode>(name, block);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Block RebuildCodeGenerators(Block block)
|
|
||||||
{
|
|
||||||
var builder = new BlockBuilder(block);
|
|
||||||
|
|
||||||
var isDynamic = builder.CodeGenerator is DynamicAttributeBlockCodeGenerator;
|
|
||||||
|
|
||||||
// We don't want any attribute specific logic here, null out the block code generator.
|
|
||||||
if (isDynamic || builder.CodeGenerator is AttributeBlockCodeGenerator)
|
|
||||||
{
|
|
||||||
builder.CodeGenerator = BlockCodeGenerator.Null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < builder.Children.Count; i++)
|
|
||||||
{
|
|
||||||
var child = builder.Children[i];
|
|
||||||
|
|
||||||
if (child.IsBlock)
|
|
||||||
{
|
|
||||||
// The child is a block, recurse down into the block to rebuild its children
|
|
||||||
builder.Children[i] = RebuildCodeGenerators((Block)child);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var childSpan = (Span)child;
|
|
||||||
ISpanCodeGenerator newCodeGenerator = null;
|
|
||||||
var literalGenerator = childSpan.CodeGenerator as LiteralAttributeCodeGenerator;
|
|
||||||
|
|
||||||
if (literalGenerator != null)
|
|
||||||
{
|
|
||||||
if (literalGenerator.ValueGenerator == null || literalGenerator.ValueGenerator.Value == null)
|
|
||||||
{
|
|
||||||
newCodeGenerator = new MarkupCodeGenerator();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newCodeGenerator = literalGenerator.ValueGenerator.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (isDynamic && childSpan.CodeGenerator == SpanCodeGenerator.Null)
|
|
||||||
{
|
|
||||||
// Usually the dynamic code generator handles rendering the null code generators underneath
|
|
||||||
// it. This doesn't make sense in terms of tag helpers though, we need to change null code
|
|
||||||
// generators to markup code generators.
|
|
||||||
|
|
||||||
newCodeGenerator = new MarkupCodeGenerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have a new code generator we'll need to re-build the child
|
|
||||||
if (newCodeGenerator != null)
|
|
||||||
{
|
|
||||||
var childSpanBuilder = new SpanBuilder(childSpan)
|
|
||||||
{
|
|
||||||
CodeGenerator = newCodeGenerator
|
|
||||||
};
|
|
||||||
|
|
||||||
builder.Children[i] = childSpanBuilder.Build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static KeyValuePair<string, SyntaxTreeNode> CreateMarkupAttribute(
|
|
||||||
string name,
|
|
||||||
SpanBuilder builder,
|
|
||||||
IReadOnlyDictionary<string, string> attributeValueTypes)
|
|
||||||
{
|
|
||||||
string attributeTypeName;
|
|
||||||
|
|
||||||
// If the attribute was requested by the tag helper and doesn't happen to be a string then we need to treat
|
|
||||||
// its value as code. Any non-string value can be any C# value so we need to ensure the SyntaxTreeNode
|
|
||||||
// reflects that.
|
|
||||||
if (attributeValueTypes.TryGetValue(name, out attributeTypeName) &&
|
|
||||||
!string.Equals(attributeTypeName, typeof(string).FullName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
builder.Kind = SpanKind.Code;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new KeyValuePair<string, SyntaxTreeNode>(name, builder.Build());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsQuote(HtmlSymbol htmlSymbol)
|
|
||||||
{
|
|
||||||
return htmlSymbol.Type == HtmlSymbolType.DoubleQuote ||
|
|
||||||
htmlSymbol.Type == HtmlSymbolType.SingleQuote;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This class is used to compare tag helper attributes by comparing only the HTML attribute name.
|
|
||||||
private class TagHelperAttributeDescriptorComparer : IEqualityComparer<TagHelperAttributeDescriptor>
|
|
||||||
{
|
|
||||||
public static readonly TagHelperAttributeDescriptorComparer Default =
|
|
||||||
new TagHelperAttributeDescriptorComparer();
|
|
||||||
|
|
||||||
public bool Equals(TagHelperAttributeDescriptor descriptorX, TagHelperAttributeDescriptor descriptorY)
|
|
||||||
{
|
|
||||||
return string.Equals(descriptorX.Name, descriptorY.Name, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetHashCode(TagHelperAttributeDescriptor descriptor)
|
|
||||||
{
|
|
||||||
return StringComparer.OrdinalIgnoreCase.GetHashCode(descriptor.Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,375 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
|
using Microsoft.AspNet.Razor.Text;
|
||||||
|
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
|
{
|
||||||
|
public static class TagHelperBlockRewriter
|
||||||
|
{
|
||||||
|
public static TagHelperBlockBuilder Rewrite(string tagName,
|
||||||
|
bool validStructure,
|
||||||
|
Block tag,
|
||||||
|
IEnumerable<TagHelperDescriptor> descriptors,
|
||||||
|
ParserErrorSink errorSink)
|
||||||
|
{
|
||||||
|
// There will always be at least one child for the '<'.
|
||||||
|
var start = tag.Children.First().Start;
|
||||||
|
var attributes = GetTagAttributes(tagName, validStructure, tag, descriptors, errorSink);
|
||||||
|
|
||||||
|
return new TagHelperBlockBuilder(tagName, start, attributes, descriptors);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IDictionary<string, SyntaxTreeNode> GetTagAttributes(
|
||||||
|
string tagName,
|
||||||
|
bool validStructure,
|
||||||
|
Block tagBlock,
|
||||||
|
IEnumerable<TagHelperDescriptor> descriptors,
|
||||||
|
ParserErrorSink errorSink)
|
||||||
|
{
|
||||||
|
var attributes = new Dictionary<string, SyntaxTreeNode>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
// Build a dictionary so we can easily lookup expected attribute value lookups
|
||||||
|
IReadOnlyDictionary<string, string> attributeValueTypes =
|
||||||
|
descriptors.SelectMany(descriptor => descriptor.Attributes)
|
||||||
|
.Distinct(TagHelperAttributeDescriptorComparer.Default)
|
||||||
|
.ToDictionary(descriptor => descriptor.Name,
|
||||||
|
descriptor => descriptor.TypeName,
|
||||||
|
StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
// We skip the first child "<tagname" and take everything up to the ending portion of the tag ">" or "/>".
|
||||||
|
// The -2 accounts for both the start and end tags. If the tag does not have a valid structure then there's
|
||||||
|
// no end tag to ignore.
|
||||||
|
var symbolOffset = validStructure ? 2 : 1;
|
||||||
|
var attributeChildren = tagBlock.Children.Skip(1).Take(tagBlock.Children.Count() - symbolOffset);
|
||||||
|
|
||||||
|
foreach (var child in attributeChildren)
|
||||||
|
{
|
||||||
|
KeyValuePair<string, SyntaxTreeNode> attribute;
|
||||||
|
bool succeeded = true;
|
||||||
|
|
||||||
|
if (child.IsBlock)
|
||||||
|
{
|
||||||
|
succeeded = TryParseBlock(tagName, (Block)child, attributeValueTypes, errorSink, out attribute);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
succeeded = TryParseSpan((Span)child, attributeValueTypes, errorSink, out attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only want to track the attribute if we succeeded in parsing its corresponding Block/Span.
|
||||||
|
if (succeeded)
|
||||||
|
{
|
||||||
|
attributes[attribute.Key] = attribute.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method handles cases when the attribute is a simple span attribute such as
|
||||||
|
// class="something moresomething". This does not handle complex attributes such as
|
||||||
|
// class="@myclass". Therefore the span.Content is equivalent to the entire attribute.
|
||||||
|
private static bool TryParseSpan(
|
||||||
|
Span span,
|
||||||
|
IReadOnlyDictionary<string, string> attributeValueTypes,
|
||||||
|
ParserErrorSink errorSink,
|
||||||
|
out KeyValuePair<string, SyntaxTreeNode> attribute)
|
||||||
|
{
|
||||||
|
var afterEquals = false;
|
||||||
|
var builder = new SpanBuilder
|
||||||
|
{
|
||||||
|
CodeGenerator = span.CodeGenerator,
|
||||||
|
EditHandler = span.EditHandler,
|
||||||
|
Kind = span.Kind
|
||||||
|
};
|
||||||
|
var htmlSymbols = span.Symbols.OfType<HtmlSymbol>().ToArray();
|
||||||
|
var capturedAttributeValueStart = false;
|
||||||
|
var attributeValueStartLocation = span.Start;
|
||||||
|
var symbolOffset = 1;
|
||||||
|
string name = null;
|
||||||
|
|
||||||
|
// Iterate down through the symbols to find the name and the start of the value.
|
||||||
|
// We subtract the symbolOffset so we don't accept an ending quote of a span.
|
||||||
|
for (var i = 0; i < htmlSymbols.Length - symbolOffset; i++)
|
||||||
|
{
|
||||||
|
var symbol = htmlSymbols[i];
|
||||||
|
|
||||||
|
if (afterEquals)
|
||||||
|
{
|
||||||
|
// When symbols are accepted into SpanBuilders, their locations get altered to be offset by the
|
||||||
|
// parent which is why we need to mark our start location prior to adding the symbol.
|
||||||
|
// This is needed to know the location of the attribute value start within the document.
|
||||||
|
if (!capturedAttributeValueStart)
|
||||||
|
{
|
||||||
|
capturedAttributeValueStart = true;
|
||||||
|
|
||||||
|
attributeValueStartLocation = span.Start + symbol.Start;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Accept(symbol);
|
||||||
|
}
|
||||||
|
else if (name == null && symbol.Type == HtmlSymbolType.Text)
|
||||||
|
{
|
||||||
|
name = symbol.Content;
|
||||||
|
attributeValueStartLocation = SourceLocation.Advance(span.Start, name);
|
||||||
|
}
|
||||||
|
else if (symbol.Type == HtmlSymbolType.Equals)
|
||||||
|
{
|
||||||
|
// We've found an '=' symbol, this means that the coming symbols will either be a quote
|
||||||
|
// or value (in the case that the value is unquoted).
|
||||||
|
// Spaces after/before the equal symbol are not yet supported:
|
||||||
|
// https://github.com/aspnet/Razor/issues/123
|
||||||
|
|
||||||
|
// TODO: Handle malformed tags, if there's an '=' then there MUST be a value.
|
||||||
|
// https://github.com/aspnet/Razor/issues/104
|
||||||
|
|
||||||
|
SourceLocation symbolStartLocation;
|
||||||
|
|
||||||
|
// Check for attribute start values, aka single or double quote
|
||||||
|
if (IsQuote(htmlSymbols[i + 1]))
|
||||||
|
{
|
||||||
|
// Move past the attribute start so we can accept the true value.
|
||||||
|
i++;
|
||||||
|
symbolStartLocation = htmlSymbols[i + 1].Start;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
symbolStartLocation = symbol.Start;
|
||||||
|
|
||||||
|
// Set the symbol offset to 0 so we don't attempt to skip an end quote that doesn't exist.
|
||||||
|
symbolOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
attributeValueStartLocation = symbolStartLocation +
|
||||||
|
span.Start +
|
||||||
|
new SourceLocation(absoluteIndex: 1,
|
||||||
|
lineIndex: 0,
|
||||||
|
characterIndex: 1);
|
||||||
|
afterEquals = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// After all symbols have been added we need to set the builders start position so we do not indirectly
|
||||||
|
// modify each symbol's Start location.
|
||||||
|
builder.Start = attributeValueStartLocation;
|
||||||
|
|
||||||
|
if (name == null)
|
||||||
|
{
|
||||||
|
errorSink.OnError(span.Start,
|
||||||
|
RazorResources.TagHelperBlockRewriter_TagHelperAttributesMustBeWelformed,
|
||||||
|
span.Content.Length);
|
||||||
|
|
||||||
|
attribute = default(KeyValuePair<string, SyntaxTreeNode>);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute = CreateMarkupAttribute(name, builder, attributeValueTypes);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryParseBlock(
|
||||||
|
string tagName,
|
||||||
|
Block block,
|
||||||
|
IReadOnlyDictionary<string, string> attributeValueTypes,
|
||||||
|
ParserErrorSink errorSink,
|
||||||
|
out KeyValuePair<string, SyntaxTreeNode> attribute)
|
||||||
|
{
|
||||||
|
// TODO: Accept more than just spans: https://github.com/aspnet/Razor/issues/96.
|
||||||
|
// The first child will only ever NOT be a Span if a user is doing something like:
|
||||||
|
// <input @checked />
|
||||||
|
|
||||||
|
var childSpan = block.Children.First() as Span;
|
||||||
|
|
||||||
|
if (childSpan == null || childSpan.Kind != SpanKind.Markup)
|
||||||
|
{
|
||||||
|
errorSink.OnError(block.Children.First().Start,
|
||||||
|
RazorResources.FormatTagHelpers_CannotHaveCSharpInTagDeclaration(tagName));
|
||||||
|
|
||||||
|
attribute = default(KeyValuePair<string, SyntaxTreeNode>);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = new BlockBuilder(block);
|
||||||
|
|
||||||
|
// If there's only 1 child it means that it's plain text inside of the attribute.
|
||||||
|
// i.e. <div class="plain text in attribute">
|
||||||
|
if (builder.Children.Count == 1)
|
||||||
|
{
|
||||||
|
return TryParseSpan(childSpan, attributeValueTypes, errorSink, out attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
var textSymbol = childSpan.Symbols.FirstHtmlSymbolAs(HtmlSymbolType.Text);
|
||||||
|
var name = textSymbol != null ? textSymbol.Content : null;
|
||||||
|
|
||||||
|
if (name == null)
|
||||||
|
{
|
||||||
|
errorSink.OnError(childSpan.Start, RazorResources.FormatTagHelpers_AttributesMustHaveAName(tagName));
|
||||||
|
|
||||||
|
attribute = default(KeyValuePair<string, SyntaxTreeNode>);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Support no attribute values: https://github.com/aspnet/Razor/issues/220
|
||||||
|
|
||||||
|
// Remove first child i.e. foo="
|
||||||
|
builder.Children.RemoveAt(0);
|
||||||
|
|
||||||
|
// Grabbing last child to check if the attribute value is quoted.
|
||||||
|
var endNode = block.Children.Last();
|
||||||
|
if (!endNode.IsBlock)
|
||||||
|
{
|
||||||
|
var endSpan = (Span)endNode;
|
||||||
|
var endSymbol = (HtmlSymbol)endSpan.Symbols.Last();
|
||||||
|
|
||||||
|
// Checking to see if it's a quoted attribute, if so we should remove end quote
|
||||||
|
if (IsQuote(endSymbol))
|
||||||
|
{
|
||||||
|
builder.Children.RemoveAt(builder.Children.Count - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to rebuild the code generators of the builder and its children (this is needed to
|
||||||
|
// ensure we don't do special attribute code generation since this is a tag helper).
|
||||||
|
block = RebuildCodeGenerators(builder.Build());
|
||||||
|
|
||||||
|
// If there's only 1 child at this point its value could be a simple markup span (treated differently than
|
||||||
|
// block level elements for attributes).
|
||||||
|
if (block.Children.Count() == 1)
|
||||||
|
{
|
||||||
|
var child = block.Children.First() as Span;
|
||||||
|
|
||||||
|
if (child != null)
|
||||||
|
{
|
||||||
|
// After pulling apart the block we just have a value span.
|
||||||
|
|
||||||
|
var spanBuilder = new SpanBuilder(child);
|
||||||
|
|
||||||
|
attribute = CreateMarkupAttribute(name, spanBuilder, attributeValueTypes);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute = new KeyValuePair<string, SyntaxTreeNode>(name, block);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Block RebuildCodeGenerators(Block block)
|
||||||
|
{
|
||||||
|
var builder = new BlockBuilder(block);
|
||||||
|
|
||||||
|
var isDynamic = builder.CodeGenerator is DynamicAttributeBlockCodeGenerator;
|
||||||
|
|
||||||
|
// We don't want any attribute specific logic here, null out the block code generator.
|
||||||
|
if (isDynamic || builder.CodeGenerator is AttributeBlockCodeGenerator)
|
||||||
|
{
|
||||||
|
builder.CodeGenerator = BlockCodeGenerator.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < builder.Children.Count; i++)
|
||||||
|
{
|
||||||
|
var child = builder.Children[i];
|
||||||
|
|
||||||
|
if (child.IsBlock)
|
||||||
|
{
|
||||||
|
// The child is a block, recurse down into the block to rebuild its children
|
||||||
|
builder.Children[i] = RebuildCodeGenerators((Block)child);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var childSpan = (Span)child;
|
||||||
|
ISpanCodeGenerator newCodeGenerator = null;
|
||||||
|
var literalGenerator = childSpan.CodeGenerator as LiteralAttributeCodeGenerator;
|
||||||
|
|
||||||
|
if (literalGenerator != null)
|
||||||
|
{
|
||||||
|
if (literalGenerator.ValueGenerator == null || literalGenerator.ValueGenerator.Value == null)
|
||||||
|
{
|
||||||
|
newCodeGenerator = new MarkupCodeGenerator();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newCodeGenerator = literalGenerator.ValueGenerator.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isDynamic && childSpan.CodeGenerator == SpanCodeGenerator.Null)
|
||||||
|
{
|
||||||
|
// Usually the dynamic code generator handles rendering the null code generators underneath
|
||||||
|
// it. This doesn't make sense in terms of tag helpers though, we need to change null code
|
||||||
|
// generators to markup code generators.
|
||||||
|
|
||||||
|
newCodeGenerator = new MarkupCodeGenerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a new code generator we'll need to re-build the child
|
||||||
|
if (newCodeGenerator != null)
|
||||||
|
{
|
||||||
|
var childSpanBuilder = new SpanBuilder(childSpan)
|
||||||
|
{
|
||||||
|
CodeGenerator = newCodeGenerator
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.Children[i] = childSpanBuilder.Build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static KeyValuePair<string, SyntaxTreeNode> CreateMarkupAttribute(
|
||||||
|
string name,
|
||||||
|
SpanBuilder builder,
|
||||||
|
IReadOnlyDictionary<string, string> attributeValueTypes)
|
||||||
|
{
|
||||||
|
string attributeTypeName;
|
||||||
|
|
||||||
|
// If the attribute was requested by the tag helper and doesn't happen to be a string then we need to treat
|
||||||
|
// its value as code. Any non-string value can be any C# value so we need to ensure the SyntaxTreeNode
|
||||||
|
// reflects that.
|
||||||
|
if (attributeValueTypes.TryGetValue(name, out attributeTypeName) &&
|
||||||
|
!string.Equals(attributeTypeName, typeof(string).FullName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
builder.Kind = SpanKind.Code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new KeyValuePair<string, SyntaxTreeNode>(name, builder.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsQuote(HtmlSymbol htmlSymbol)
|
||||||
|
{
|
||||||
|
return htmlSymbol.Type == HtmlSymbolType.DoubleQuote ||
|
||||||
|
htmlSymbol.Type == HtmlSymbolType.SingleQuote;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This class is used to compare tag helper attributes by comparing only the HTML attribute name.
|
||||||
|
private class TagHelperAttributeDescriptorComparer : IEqualityComparer<TagHelperAttributeDescriptor>
|
||||||
|
{
|
||||||
|
public static readonly TagHelperAttributeDescriptorComparer Default =
|
||||||
|
new TagHelperAttributeDescriptorComparer();
|
||||||
|
|
||||||
|
public bool Equals(TagHelperAttributeDescriptor descriptorX, TagHelperAttributeDescriptor descriptorY)
|
||||||
|
{
|
||||||
|
return string.Equals(descriptorX.Name, descriptorY.Name, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode(TagHelperAttributeDescriptor descriptor)
|
||||||
|
{
|
||||||
|
return StringComparer.OrdinalIgnoreCase.GetHashCode(descriptor.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,14 +27,12 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
|
|
||||||
public void Rewrite(RewritingContext context)
|
public void Rewrite(RewritingContext context)
|
||||||
{
|
{
|
||||||
RewriteTags(context.SyntaxTree);
|
RewriteTags(context.SyntaxTree, context);
|
||||||
|
|
||||||
ValidateRewrittenSyntaxTree(context);
|
|
||||||
|
|
||||||
context.SyntaxTree = _currentBlock.Build();
|
context.SyntaxTree = _currentBlock.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RewriteTags(Block input)
|
private void RewriteTags(Block input, RewritingContext context)
|
||||||
{
|
{
|
||||||
// We want to start a new block without the children from existing (we rebuild them).
|
// We want to start a new block without the children from existing (we rebuild them).
|
||||||
TrackBlock(new BlockBuilder
|
TrackBlock(new BlockBuilder
|
||||||
|
|
@ -43,6 +41,8 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
CodeGenerator = input.CodeGenerator
|
CodeGenerator = input.CodeGenerator
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var activeTagHelpers = _tagStack.Count;
|
||||||
|
|
||||||
foreach (var child in input.Children)
|
foreach (var child in input.Children)
|
||||||
{
|
{
|
||||||
if (child.IsBlock)
|
if (child.IsBlock)
|
||||||
|
|
@ -51,65 +51,18 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
|
|
||||||
if (childBlock.Type == BlockType.Tag)
|
if (childBlock.Type == BlockType.Tag)
|
||||||
{
|
{
|
||||||
// TODO: Fully handle malformed tags: https://github.com/aspnet/Razor/issues/104
|
if (TryRewriteTagHelper(childBlock, context))
|
||||||
|
|
||||||
// Get tag name of the current block (doesn't matter if it's an end or start tag)
|
|
||||||
var tagName = GetTagName(childBlock);
|
|
||||||
|
|
||||||
// Could not determine tag name, it can't be a TagHelper, continue on and track the element.
|
|
||||||
if (tagName == null)
|
|
||||||
{
|
{
|
||||||
_currentBlock.Children.Add(child);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsEndTag(childBlock))
|
// If we get to here it means that we're a normal html tag. No need to iterate any deeper into
|
||||||
{
|
// the children of it because they wont be tag helpers.
|
||||||
// We're in a begin tag block
|
|
||||||
|
|
||||||
if (IsPotentialTagHelper(tagName, childBlock))
|
|
||||||
{
|
|
||||||
var descriptors = _provider.GetTagHelpers(tagName);
|
|
||||||
|
|
||||||
// We could be a tag helper, but only if we have descriptors registered
|
|
||||||
if (descriptors.Any())
|
|
||||||
{
|
|
||||||
// Found a new tag helper block
|
|
||||||
TrackTagHelperBlock(new TagHelperBlockBuilder(tagName, descriptors, childBlock));
|
|
||||||
|
|
||||||
// If it's a self closing block then we don't have to worry about nested children
|
|
||||||
// within the tag... complete it.
|
|
||||||
if (IsSelfClosing(childBlock))
|
|
||||||
{
|
|
||||||
BuildCurrentlyTrackedTagHelperBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var currentTagHelper = _tagStack.Count > 0 ? _tagStack.Peek() : null;
|
|
||||||
|
|
||||||
// Check if it's an "end" tag helper that matches our current tag helper
|
|
||||||
if (currentTagHelper != null &&
|
|
||||||
string.Equals(currentTagHelper.TagName, tagName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
BuildCurrentlyTrackedTagHelperBlock();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're in an end tag, there won't be anymore tag helpers nested.
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we get to here it means that we're a normal html tag. No need to iterate
|
|
||||||
// any deeper into the children of it because they wont be tag helpers.
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We're not an Html tag so iterate through children recursively.
|
// We're not an Html tag so iterate through children recursively.
|
||||||
RewriteTags(childBlock);
|
RewriteTags(childBlock, context);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -117,42 +70,141 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
// At this point the child is a Span or Block with Type BlockType.Tag that doesn't happen to be a
|
// At this point the child is a Span or Block with Type BlockType.Tag that doesn't happen to be a
|
||||||
// tag helper.
|
// tag helper.
|
||||||
|
|
||||||
// Add the child to current block.
|
// Add the child to current block.
|
||||||
_currentBlock.Children.Add(child);
|
_currentBlock.Children.Add(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We captured the number of active tag helpers at the start of our logic, it should be the same. If not
|
||||||
|
// it means that there are malformed tag helpers at the top of our stack.
|
||||||
|
if (activeTagHelpers != _tagStack.Count)
|
||||||
|
{
|
||||||
|
// Malformed tag helpers built here will be tag helpers that do not have end tags in the current block
|
||||||
|
// scope. Block scopes are special cases in Razor such as @<p> would cause an error because there's no
|
||||||
|
// matching end </p> tag in the template block scope and therefore doesn't make sense as a tag helper.
|
||||||
|
BuildMalformedTagHelpers(_tagStack.Count - activeTagHelpers, context);
|
||||||
|
|
||||||
|
Debug.Assert(activeTagHelpers == _tagStack.Count);
|
||||||
|
}
|
||||||
|
|
||||||
BuildCurrentlyTrackedBlock();
|
BuildCurrentlyTrackedBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateRewrittenSyntaxTree(RewritingContext context)
|
private bool TryRewriteTagHelper(Block tagBlock, RewritingContext context)
|
||||||
{
|
{
|
||||||
// If the blockStack still has elements in it that means there's at least one malformed TagHelper block in
|
// TODO: Fully handle malformed tags: https://github.com/aspnet/Razor/issues/104
|
||||||
// the document, that's the only way we can have a non-zero _blockStack.Count.
|
|
||||||
if (_blockStack.Count != 0)
|
// Get tag name of the current block (doesn't matter if it's an end or start tag)
|
||||||
|
var tagName = GetTagName(tagBlock);
|
||||||
|
|
||||||
|
// Could not determine tag name, it can't be a TagHelper, continue on and track the element.
|
||||||
|
if (tagName == null)
|
||||||
{
|
{
|
||||||
// We reverse the children so we can search from the back to the front for the TagHelper that is
|
return false;
|
||||||
// malformed.
|
}
|
||||||
var candidateChildren = _currentBlock.Children.Reverse();
|
|
||||||
var malformedTagHelper = candidateChildren.OfType<TagHelperBlock>().FirstOrDefault();
|
|
||||||
|
|
||||||
// If the malformed tag helper is null that means something other than a TagHelper caused the
|
var descriptors = Enumerable.Empty<TagHelperDescriptor>();
|
||||||
// unbalancing of the syntax tree (should never happen).
|
|
||||||
Debug.Assert(malformedTagHelper != null);
|
|
||||||
|
|
||||||
// We only create a single error because we can't reasonably determine other invalid tag helpers in the
|
if (IsPotentialTagHelper(tagName, tagBlock))
|
||||||
// document; having one malformed tag helper puts the document into an invalid state.
|
{
|
||||||
context.ErrorSink.OnError(
|
descriptors = _provider.GetTagHelpers(tagName);
|
||||||
malformedTagHelper.Start,
|
}
|
||||||
RazorResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper(
|
|
||||||
malformedTagHelper.TagName));
|
|
||||||
|
|
||||||
// We need to build the remaining blocks in the stack to ensure we don't return an invalid syntax tree.
|
// If there aren't any TagHelperDescriptors registered then we aren't a TagHelper
|
||||||
do
|
if (!descriptors.Any())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsEndTag(tagBlock))
|
||||||
|
{
|
||||||
|
// We're in a begin tag helper block
|
||||||
|
|
||||||
|
var validTagStructure = ValidTagStructure(tagName, tagBlock, context);
|
||||||
|
|
||||||
|
var builder = TagHelperBlockRewriter.Rewrite(tagName,
|
||||||
|
validTagStructure,
|
||||||
|
tagBlock,
|
||||||
|
descriptors,
|
||||||
|
context.ErrorSink);
|
||||||
|
|
||||||
|
// Found a new tag helper block
|
||||||
|
TrackTagHelperBlock(builder);
|
||||||
|
|
||||||
|
// If it's a self closing block then we don't have to worry about nested children
|
||||||
|
// within the tag... complete it.
|
||||||
|
if (IsSelfClosing(tagBlock))
|
||||||
{
|
{
|
||||||
BuildCurrentlyTrackedTagHelperBlock();
|
BuildCurrentlyTrackedTagHelperBlock();
|
||||||
}
|
}
|
||||||
while (_blockStack.Count != 0);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We're in an end tag helper block.
|
||||||
|
|
||||||
|
var tagNameScope = _tagStack.Count > 0 ? _tagStack.Peek().TagName : string.Empty;
|
||||||
|
|
||||||
|
// Validate that our end tag helper matches the currently scoped tag helper, if not we
|
||||||
|
// need to error.
|
||||||
|
if (tagNameScope.Equals(tagName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
ValidTagStructure(tagName, tagBlock, context);
|
||||||
|
|
||||||
|
BuildCurrentlyTrackedTagHelperBlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Current tag helper scope does not match the end tag. Attempt to recover the tag
|
||||||
|
// helper by looking up the previous tag helper scopes for a matching tag. If we
|
||||||
|
// can't recover it means there was no corresponding tag helper begin tag.
|
||||||
|
if (TryRecoverTagHelper(tagName, context))
|
||||||
|
{
|
||||||
|
ValidTagStructure(tagName, tagBlock, context);
|
||||||
|
|
||||||
|
// Successfully recovered, move onto the next element.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Could not recover, the end tag helper has no corresponding begin tag, create
|
||||||
|
// an error based on the current childBlock.
|
||||||
|
context.ErrorSink.OnError(
|
||||||
|
tagBlock.Start,
|
||||||
|
RazorResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper(tagName));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool ValidTagStructure(string tagName, Block tag, RewritingContext context)
|
||||||
|
{
|
||||||
|
// We assume an invalid structure until we verify that the tag meets all of our "valid structure" criteria.
|
||||||
|
var invalidStructure = true;
|
||||||
|
|
||||||
|
// No need to validate the tag end because in order to be a tag block it must start with '<'.
|
||||||
|
var tagEnd = tag.Children.Last() as Span;
|
||||||
|
|
||||||
|
// If our tag end is not a markup span it means it's some sort of code SyntaxTreeNode (not a valid format)
|
||||||
|
if (tagEnd != null && tagEnd.Kind == SpanKind.Markup)
|
||||||
|
{
|
||||||
|
var endSymbol = tagEnd.Symbols.LastOrDefault() as HtmlSymbol;
|
||||||
|
|
||||||
|
if (endSymbol != null && endSymbol.Type == HtmlSymbolType.CloseAngle)
|
||||||
|
{
|
||||||
|
invalidStructure = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invalidStructure)
|
||||||
|
{
|
||||||
|
context.ErrorSink.OnError(
|
||||||
|
tag.Start,
|
||||||
|
RazorResources.FormatTagHelpersParseTreeRewriter_MissingCloseAngle(tagName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return !invalidStructure;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildCurrentlyTrackedBlock()
|
private void BuildCurrentlyTrackedBlock()
|
||||||
|
|
@ -216,6 +268,52 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
TrackBlock(builder);
|
TrackBlock(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryRecoverTagHelper(string tagName, RewritingContext context)
|
||||||
|
{
|
||||||
|
var malformedTagHelperCount = 0;
|
||||||
|
|
||||||
|
foreach (var tag in _tagStack)
|
||||||
|
{
|
||||||
|
if (tag.TagName.Equals(tagName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
malformedTagHelperCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the malformedTagHelperCount == _tagStack.Count it means we couldn't find a begin tag for the tag
|
||||||
|
// helper, can't recover.
|
||||||
|
if (malformedTagHelperCount != _tagStack.Count)
|
||||||
|
{
|
||||||
|
BuildMalformedTagHelpers(malformedTagHelperCount, context);
|
||||||
|
|
||||||
|
// One final build, this is the build that completes our target tag helper block which is not malformed.
|
||||||
|
BuildCurrentlyTrackedTagHelperBlock();
|
||||||
|
|
||||||
|
// We were able to recover
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Could not recover tag helper. Aka we found a tag helper end tag without a corresponding begin tag.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildMalformedTagHelpers(int count, RewritingContext context)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var malformedTagHelper = _tagStack.Peek();
|
||||||
|
|
||||||
|
context.ErrorSink.OnError(
|
||||||
|
malformedTagHelper.Start,
|
||||||
|
RazorResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper(
|
||||||
|
malformedTagHelper.TagName));
|
||||||
|
|
||||||
|
BuildCurrentlyTrackedTagHelperBlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static string GetTagName(Block tagBlock)
|
private static string GetTagName(Block tagBlock)
|
||||||
{
|
{
|
||||||
var child = tagBlock.Children.First();
|
var child = tagBlock.Children.First();
|
||||||
|
|
@ -240,9 +338,9 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
||||||
{
|
{
|
||||||
EnsureTagBlock(beginTagBlock);
|
EnsureTagBlock(beginTagBlock);
|
||||||
|
|
||||||
var childSpan = (Span)beginTagBlock.Children.Last();
|
var childSpan = beginTagBlock.Children.Last() as Span;
|
||||||
|
|
||||||
return childSpan.Content.EndsWith("/>");
|
return childSpan?.Content.EndsWith("/>") ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsEndTag(Block tagBlock)
|
private static bool IsEndTag(Block tagBlock)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
|
|
||||||
|
|
@ -15,15 +17,18 @@ namespace Microsoft.AspNet.Razor
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instantiates a new <see cref="ParserResults"/> instance.
|
/// Instantiates a new <see cref="ParserResults"/> instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="document">The Razor syntax tree.</param>
|
/// <param name="document">The <see cref="Block"/> for the syntax tree.</param>
|
||||||
/// <param name="tagHelperDescriptors"><see cref="TagHelperDescriptor"/>s that apply to the current Razor
|
/// <param name="tagHelperDescriptors">
|
||||||
/// document.</param>
|
/// The <see cref="TagHelperDescriptor"/>s that apply to the current Razor document.
|
||||||
/// <param name="parserErrors"><see cref="RazorError"/>s encountered when parsing the current Razor
|
/// </param>
|
||||||
/// document.</param>
|
/// <param name="errorSink">
|
||||||
|
/// The <see cref="ParserErrorSink"/> used to collect <see cref="RazorError"/>s encountered when parsing the
|
||||||
|
/// current Razor document.
|
||||||
|
/// </param>
|
||||||
public ParserResults([NotNull] Block document,
|
public ParserResults([NotNull] Block document,
|
||||||
[NotNull] IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
|
[NotNull] IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
|
||||||
[NotNull] IList<RazorError> parserErrors)
|
[NotNull] ParserErrorSink errorSink)
|
||||||
: this(parserErrors == null || parserErrors.Count == 0, document, tagHelperDescriptors, parserErrors)
|
: this(!errorSink.Errors.Any(), document, tagHelperDescriptors, errorSink)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,40 +36,50 @@ namespace Microsoft.AspNet.Razor
|
||||||
/// Instantiates a new <see cref="ParserResults"/> instance.
|
/// Instantiates a new <see cref="ParserResults"/> instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="success"><c>true</c> if parsing was successful, <c>false</c> otherwise.</param>
|
/// <param name="success"><c>true</c> if parsing was successful, <c>false</c> otherwise.</param>
|
||||||
/// <param name="document">The Razor syntax tree.</param>
|
/// <param name="document">The <see cref="Block"/> for the syntax tree.</param>
|
||||||
/// <param name="tagHelperDescriptors"><see cref="TagHelperDescriptor"/>s that apply to the current Razor
|
/// <param name="tagHelperDescriptors">
|
||||||
/// document.</param>
|
/// The <see cref="TagHelperDescriptor"/>s that apply to the current Razor document.
|
||||||
/// <param name="errors"><see cref="RazorError"/>s encountered when parsing the current Razor
|
/// </param>
|
||||||
/// document.</param>
|
/// <param name="errorSink">
|
||||||
|
/// The <see cref="ParserErrorSink"/> used to collect <see cref="RazorError"/>s encountered when parsing the
|
||||||
|
/// current Razor document.
|
||||||
|
/// </param>
|
||||||
protected ParserResults(bool success,
|
protected ParserResults(bool success,
|
||||||
[NotNull] Block document,
|
[NotNull] Block document,
|
||||||
[NotNull] IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
|
[NotNull] IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
|
||||||
[NotNull] IList<RazorError> errors)
|
[NotNull] ParserErrorSink errorSink)
|
||||||
{
|
{
|
||||||
Success = success;
|
Success = success;
|
||||||
Document = document;
|
Document = document;
|
||||||
TagHelperDescriptors = tagHelperDescriptors;
|
TagHelperDescriptors = tagHelperDescriptors;
|
||||||
ParserErrors = errors ?? new List<RazorError>();
|
ErrorSink = errorSink;
|
||||||
|
ParserErrors = errorSink.Errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if parsing was successful (no errors)
|
/// Indicates if parsing was successful (no errors).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Success { get; private set; }
|
/// <value><c>true</c> if parsing was successful, <c>false</c> otherwise.</value>
|
||||||
|
public bool Success { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The root node in the document's syntax tree
|
/// The root node in the document's syntax tree.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Block Document { get; private set; }
|
public Block Document { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to aggregate <see cref="RazorError"/>s.
|
||||||
|
/// </summary>
|
||||||
|
public ParserErrorSink ErrorSink { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of errors which occurred during parsing.
|
/// The list of errors which occurred during parsing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IList<RazorError> ParserErrors { get; private set; }
|
public IEnumerable<RazorError> ParserErrors { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="TagHelperDescriptor"/>s found for the current Razor document.
|
/// The <see cref="TagHelperDescriptor"/>s found for the current Razor document.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<TagHelperDescriptor> TagHelperDescriptors { get; private set; }
|
public IEnumerable<TagHelperDescriptor> TagHelperDescriptors { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ namespace Microsoft.AspNet.Razor
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The "@" character must be followed by a ":", "(", or a C# identifier. If you intended to switch to markup, use an HTML start tag, for example:
|
/// The "@" character must be followed by a ":", "(", or a C# identifier. If you intended to switch to markup, use an HTML start tag, for example:
|
||||||
///
|
///
|
||||||
/// @if(isLoggedIn) {
|
/// @if(isLoggedIn) {
|
||||||
/// <p>Hello, @user!</p>
|
/// <p>Hello, @user!</p>
|
||||||
/// }
|
/// }
|
||||||
|
|
@ -104,7 +104,7 @@ namespace Microsoft.AspNet.Razor
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The "@" character must be followed by a ":", "(", or a C# identifier. If you intended to switch to markup, use an HTML start tag, for example:
|
/// The "@" character must be followed by a ":", "(", or a C# identifier. If you intended to switch to markup, use an HTML start tag, for example:
|
||||||
///
|
///
|
||||||
/// @if(isLoggedIn) {
|
/// @if(isLoggedIn) {
|
||||||
/// <p>Hello, @user!</p>
|
/// <p>Hello, @user!</p>
|
||||||
/// }
|
/// }
|
||||||
|
|
@ -228,7 +228,7 @@ namespace Microsoft.AspNet.Razor
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sections cannot be empty. The "@section" keyword must be followed by a block of markup surrounded by "{}". For example:
|
/// Sections cannot be empty. The "@section" keyword must be followed by a block of markup surrounded by "{}". For example:
|
||||||
///
|
///
|
||||||
/// @section Sidebar {
|
/// @section Sidebar {
|
||||||
/// <!-- Markup and text goes here -->
|
/// <!-- Markup and text goes here -->
|
||||||
/// }
|
/// }
|
||||||
|
|
@ -240,7 +240,7 @@ namespace Microsoft.AspNet.Razor
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sections cannot be empty. The "@section" keyword must be followed by a block of markup surrounded by "{}". For example:
|
/// Sections cannot be empty. The "@section" keyword must be followed by a block of markup surrounded by "{}". For example:
|
||||||
///
|
///
|
||||||
/// @section Sidebar {
|
/// @section Sidebar {
|
||||||
/// <!-- Markup and text goes here -->
|
/// <!-- Markup and text goes here -->
|
||||||
/// }
|
/// }
|
||||||
|
|
@ -252,7 +252,7 @@ namespace Microsoft.AspNet.Razor
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Namespace imports and type aliases cannot be placed within code blocks. They must immediately follow an "@" character in markup. It is recommended that you put them at the top of the page, as in the following example:
|
/// Namespace imports and type aliases cannot be placed within code blocks. They must immediately follow an "@" character in markup. It is recommended that you put them at the top of the page, as in the following example:
|
||||||
///
|
///
|
||||||
/// @using System.Drawing;
|
/// @using System.Drawing;
|
||||||
/// @{
|
/// @{
|
||||||
/// // OK here to use types from System.Drawing in the page.
|
/// // OK here to use types from System.Drawing in the page.
|
||||||
|
|
@ -265,7 +265,7 @@ namespace Microsoft.AspNet.Razor
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Namespace imports and type aliases cannot be placed within code blocks. They must immediately follow an "@" character in markup. It is recommended that you put them at the top of the page, as in the following example:
|
/// Namespace imports and type aliases cannot be placed within code blocks. They must immediately follow an "@" character in markup. It is recommended that you put them at the top of the page, as in the following example:
|
||||||
///
|
///
|
||||||
/// @using System.Drawing;
|
/// @using System.Drawing;
|
||||||
/// @{
|
/// @{
|
||||||
/// // OK here to use types from System.Drawing in the page.
|
/// // OK here to use types from System.Drawing in the page.
|
||||||
|
|
@ -278,12 +278,12 @@ namespace Microsoft.AspNet.Razor
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Expected a "{0}" but found a "{1}". Block statements must be enclosed in "{{" and "}}". You cannot use single-statement control-flow statements in CSHTML pages. For example, the following is not allowed:
|
/// Expected a "{0}" but found a "{1}". Block statements must be enclosed in "{{" and "}}". You cannot use single-statement control-flow statements in CSHTML pages. For example, the following is not allowed:
|
||||||
///
|
///
|
||||||
/// @if(isLoggedIn)
|
/// @if(isLoggedIn)
|
||||||
/// <p>Hello, @user</p>
|
/// <p>Hello, @user</p>
|
||||||
///
|
///
|
||||||
/// Instead, wrap the contents of the block in "{{}}":
|
/// Instead, wrap the contents of the block in "{{}}":
|
||||||
///
|
///
|
||||||
/// @if(isLoggedIn) {{
|
/// @if(isLoggedIn) {{
|
||||||
/// <p>Hello, @user</p>
|
/// <p>Hello, @user</p>
|
||||||
/// }}
|
/// }}
|
||||||
|
|
@ -295,12 +295,12 @@ namespace Microsoft.AspNet.Razor
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Expected a "{0}" but found a "{1}". Block statements must be enclosed in "{{" and "}}". You cannot use single-statement control-flow statements in CSHTML pages. For example, the following is not allowed:
|
/// Expected a "{0}" but found a "{1}". Block statements must be enclosed in "{{" and "}}". You cannot use single-statement control-flow statements in CSHTML pages. For example, the following is not allowed:
|
||||||
///
|
///
|
||||||
/// @if(isLoggedIn)
|
/// @if(isLoggedIn)
|
||||||
/// <p>Hello, @user</p>
|
/// <p>Hello, @user</p>
|
||||||
///
|
///
|
||||||
/// Instead, wrap the contents of the block in "{{}}":
|
/// Instead, wrap the contents of the block in "{{}}":
|
||||||
///
|
///
|
||||||
/// @if(isLoggedIn) {{
|
/// @if(isLoggedIn) {{
|
||||||
/// <p>Hello, @user</p>
|
/// <p>Hello, @user</p>
|
||||||
/// }}
|
/// }}
|
||||||
|
|
@ -390,38 +390,6 @@ namespace Microsoft.AspNet.Razor
|
||||||
return GetString("ParseError_Unterminated_String_Literal");
|
return GetString("ParseError_Unterminated_String_Literal");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unknown option: "{0}".
|
|
||||||
/// </summary>
|
|
||||||
internal static string ParseError_UnknownOption
|
|
||||||
{
|
|
||||||
get { return GetString("ParseError_UnknownOption"); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unknown option: "{0}".
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatParseError_UnknownOption(object p0)
|
|
||||||
{
|
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("ParseError_UnknownOption"), p0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The "{0}" block was not terminated. All "{0}" statements must be terminated with a matching "{1}".
|
|
||||||
/// </summary>
|
|
||||||
internal static string ParseError_BlockNotTerminated
|
|
||||||
{
|
|
||||||
get { return GetString("ParseError_BlockNotTerminated"); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The "{0}" block was not terminated. All "{0}" statements must be terminated with a matching "{1}".
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatParseError_BlockNotTerminated(object p0, object p1)
|
|
||||||
{
|
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("ParseError_BlockNotTerminated"), p0, p1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// @section Header { ... }
|
/// @section Header { ... }
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -454,22 +422,6 @@ namespace Microsoft.AspNet.Razor
|
||||||
return GetString("ParseError_TextTagCannotContainAttributes");
|
return GetString("ParseError_TextTagCannotContainAttributes");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The "Imports" keyword must be followed by a namespace or a type alias on the same line.
|
|
||||||
/// </summary>
|
|
||||||
internal static string ParseError_NamespaceOrTypeAliasExpected
|
|
||||||
{
|
|
||||||
get { return GetString("ParseError_NamespaceOrTypeAliasExpected"); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The "Imports" keyword must be followed by a namespace or a type alias on the same line.
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatParseError_NamespaceOrTypeAliasExpected()
|
|
||||||
{
|
|
||||||
return GetString("ParseError_NamespaceOrTypeAliasExpected");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A space or line break was encountered after the "@" character. Only valid identifiers, keywords, comments, "(" and "{" are valid at the start of a code block and they must occur immediately following "@" with no space in between.
|
/// A space or line break was encountered after the "@" character. Only valid identifiers, keywords, comments, "(" and "{" are valid at the start of a code block and they must occur immediately following "@" with no space in between.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -998,22 +950,6 @@ namespace Microsoft.AspNet.Razor
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("TokenizerView_CannotPutBack"), p0, p1);
|
return string.Format(CultureInfo.CurrentCulture, GetString("TokenizerView_CannotPutBack"), p0, p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unexpected "{0}"
|
|
||||||
/// </summary>
|
|
||||||
internal static string ParseError_Unexpected
|
|
||||||
{
|
|
||||||
get { return GetString("ParseError_Unexpected"); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unexpected "{0}"
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatParseError_Unexpected(object p0)
|
|
||||||
{
|
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("ParseError_Unexpected"), p0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unexpected "{" after "@" character. Once inside the body of a code block (@if {}, @{}, etc.) you do not need to use "@{" to switch to code.
|
/// Unexpected "{" after "@" character. Once inside the body of a code block (@if {}, @{}, etc.) you do not need to use "@{" to switch to code.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1142,38 +1078,6 @@ namespace Microsoft.AspNet.Razor
|
||||||
return GetString("Language_Does_Not_Support_RazorComment");
|
return GetString("Language_Does_Not_Support_RazorComment");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Missing value for session state directive.
|
|
||||||
/// </summary>
|
|
||||||
internal static string ParserEror_SessionDirectiveMissingValue
|
|
||||||
{
|
|
||||||
get { return GetString("ParserEror_SessionDirectiveMissingValue"); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Missing value for session state directive.
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatParserEror_SessionDirectiveMissingValue()
|
|
||||||
{
|
|
||||||
return GetString("ParserEror_SessionDirectiveMissingValue");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cannot call CreateCodeWriter, a CodeWriter was not provided to the Create method
|
|
||||||
/// </summary>
|
|
||||||
internal static string CreateCodeWriter_NoCodeWriter
|
|
||||||
{
|
|
||||||
get { return GetString("CreateCodeWriter_NoCodeWriter"); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cannot call CreateCodeWriter, a CodeWriter was not provided to the Create method
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatCreateCodeWriter_NoCodeWriter()
|
|
||||||
{
|
|
||||||
return GetString("CreateCodeWriter_NoCodeWriter");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// [BG][{0}] Shutdown
|
/// [BG][{0}] Shutdown
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1431,7 +1335,7 @@ namespace Microsoft.AspNet.Razor
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tag Helper attributes must have a name.
|
/// Tag Helper '{0}'s attributes must have names.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string TagHelpers_AttributesMustHaveAName
|
internal static string TagHelpers_AttributesMustHaveAName
|
||||||
{
|
{
|
||||||
|
|
@ -1439,15 +1343,15 @@ namespace Microsoft.AspNet.Razor
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tag Helper attributes must have a name.
|
/// Tag Helper '{0}'s attributes must have names.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string FormatTagHelpers_AttributesMustHaveAName()
|
internal static string FormatTagHelpers_AttributesMustHaveAName(object p0)
|
||||||
{
|
{
|
||||||
return GetString("TagHelpers_AttributesMustHaveAName");
|
return string.Format(CultureInfo.CurrentCulture, GetString("TagHelpers_AttributesMustHaveAName"), p0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tag Helpers cannot have C# in an HTML tag element's attribute declaration area.
|
/// The tag helper '{0}' must not have C# in the element's attribute declaration area.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string TagHelpers_CannotHaveCSharpInTagDeclaration
|
internal static string TagHelpers_CannotHaveCSharpInTagDeclaration
|
||||||
{
|
{
|
||||||
|
|
@ -1455,11 +1359,11 @@ namespace Microsoft.AspNet.Razor
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tag Helpers cannot have C# in an HTML tag element's attribute declaration area.
|
/// The tag helper '{0}' must not have C# in the element's attribute declaration area.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string FormatTagHelpers_CannotHaveCSharpInTagDeclaration()
|
internal static string FormatTagHelpers_CannotHaveCSharpInTagDeclaration(object p0)
|
||||||
{
|
{
|
||||||
return GetString("TagHelpers_CannotHaveCSharpInTagDeclaration");
|
return string.Format(CultureInfo.CurrentCulture, GetString("TagHelpers_CannotHaveCSharpInTagDeclaration"), p0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -1478,22 +1382,6 @@ namespace Microsoft.AspNet.Razor
|
||||||
return GetString("TagHelpers_TagHelperCodeGeneartorMustBeAssociatedWithATagHelperBlock");
|
return GetString("TagHelpers_TagHelperCodeGeneartorMustBeAssociatedWithATagHelperBlock");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// TagHelper attributes that do not expect strings must not have @ symbols within them. Found attribute '{0}' with an invalid value.
|
|
||||||
/// </summary>
|
|
||||||
internal static string TagHelpers_AttributesThatAreNotStringsMustNotContainAtSymbols
|
|
||||||
{
|
|
||||||
get { return GetString("TagHelpers_AttributesThatAreNotStringsMustNotContainAtSymbols"); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// TagHelper attributes that do not expect strings must not have @ symbols within them. Found attribute '{0}' with an invalid value.
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatTagHelpers_AttributesThatAreNotStringsMustNotContainAtSymbols(object p0)
|
|
||||||
{
|
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("TagHelpers_AttributesThatAreNotStringsMustNotContainAtSymbols"), p0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Directive '{0}' must have a value.
|
/// Directive '{0}' must have a value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1542,6 +1430,106 @@ namespace Microsoft.AspNet.Razor
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("TagHelpersParseTreeRewriter_FoundMalformedTagHelper"), p0);
|
return string.Format(CultureInfo.CurrentCulture, GetString("TagHelpersParseTreeRewriter_FoundMalformedTagHelper"), p0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Missing close angle for tag helper '{0}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string TagHelpersParseTreeRewriter_MissingCloseAngle
|
||||||
|
{
|
||||||
|
get { return GetString("TagHelpersParseTreeRewriter_MissingCloseAngle"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Missing close angle for tag helper '{0}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatTagHelpersParseTreeRewriter_MissingCloseAngle(object p0)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("TagHelpersParseTreeRewriter_MissingCloseAngle"), p0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TagHelper attributes must be welformed.
|
||||||
|
/// </summary>
|
||||||
|
internal static string TagHelperBlockRewriter_TagHelperAttributesMustBeWelformed
|
||||||
|
{
|
||||||
|
get { return GetString("TagHelperBlockRewriter_TagHelperAttributesMustBeWelformed"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TagHelper attributes must be welformed.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatTagHelperBlockRewriter_TagHelperAttributesMustBeWelformed()
|
||||||
|
{
|
||||||
|
return GetString("TagHelperBlockRewriter_TagHelperAttributesMustBeWelformed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Non-string tag helper attribute values must not be empty. Add an expression to this attribute value.
|
||||||
|
/// </summary>
|
||||||
|
internal static string TagHelpers_AttributeExpressionRequired
|
||||||
|
{
|
||||||
|
get { return GetString("TagHelpers_AttributeExpressionRequired"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Non-string tag helper attribute values must not be empty. Add an expression to this attribute value.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatTagHelpers_AttributeExpressionRequired()
|
||||||
|
{
|
||||||
|
return GetString("TagHelpers_AttributeExpressionRequired");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Code blocks (e.g. @{{var variable = 23;}}) must not appear in non-string tag helper attribute values.
|
||||||
|
/// Already in an expression (code) context. If necessary an explicit expression (e.g. @(@readonly)) may be used.
|
||||||
|
/// </summary>
|
||||||
|
internal static string TagHelpers_CodeBlocks_NotSupported_InAttributes
|
||||||
|
{
|
||||||
|
get { return GetString("TagHelpers_CodeBlocks_NotSupported_InAttributes"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Code blocks (e.g. @{{var variable = 23;}}) must not appear in non-string tag helper attribute values.
|
||||||
|
/// Already in an expression (code) context. If necessary an explicit expression (e.g. @(@readonly)) may be used.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatTagHelpers_CodeBlocks_NotSupported_InAttributes()
|
||||||
|
{
|
||||||
|
return GetString("TagHelpers_CodeBlocks_NotSupported_InAttributes");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// @'{0}' directives must not appear in non-string tag helper attribute values.
|
||||||
|
/// </summary>
|
||||||
|
internal static string TagHelpers_Directives_NotSupported_InAttributes
|
||||||
|
{
|
||||||
|
get { return GetString("TagHelpers_Directives_NotSupported_InAttributes"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// @'{0}' directives must not appear in non-string tag helper attribute values.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatTagHelpers_Directives_NotSupported_InAttributes(object p0)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("TagHelpers_Directives_NotSupported_InAttributes"), p0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inline markup blocks (e.g. @<p>content</p>) must not appear in non-string tag helper attribute values.
|
||||||
|
/// Expected a '{0}' attribute value, not a string.
|
||||||
|
/// </summary>
|
||||||
|
internal static string TagHelpers_InlineMarkupBlocks_NotSupported_InAttributes
|
||||||
|
{
|
||||||
|
get { return GetString("TagHelpers_InlineMarkupBlocks_NotSupported_InAttributes"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inline markup blocks (e.g. @<p>content</p>) must not appear in non-string tag helper attribute values.
|
||||||
|
/// Expected a '{0}' attribute value, not a string.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatTagHelpers_InlineMarkupBlocks_NotSupported_InAttributes(object p0)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("TagHelpers_InlineMarkupBlocks_NotSupported_InAttributes"), p0);
|
||||||
|
}
|
||||||
|
|
||||||
private static string GetString(string name, params string[] formatterNames)
|
private static string GetString(string name, params string[] formatterNames)
|
||||||
{
|
{
|
||||||
var value = _resourceManager.GetString(name);
|
var value = _resourceManager.GetString(name);
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
|
|
||||||
Version 2.0
|
Version 2.0
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
The primary goals of this format is to allow a simple XML format
|
||||||
that is mostly human readable. The generation and parsing of the
|
that is mostly human readable. The generation and parsing of the
|
||||||
various data types are done through the TypeConverter classes
|
various data types are done through the TypeConverter classes
|
||||||
associated with the data types.
|
associated with the data types.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
... ado.net/XML headers & schema ...
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
<resheader name="version">2.0</resheader>
|
<resheader name="version">2.0</resheader>
|
||||||
|
|
@ -26,36 +26,36 @@
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
<comment>This is a comment</comment>
|
<comment>This is a comment</comment>
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
There are any number of "resheader" rows that contain simple
|
||||||
name/value pairs.
|
name/value pairs.
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
Each data row contains a name, and value. The row also contains a
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
text/value conversion through the TypeConverter architecture.
|
text/value conversion through the TypeConverter architecture.
|
||||||
Classes that don't support this are serialized and stored with the
|
Classes that don't support this are serialized and stored with the
|
||||||
mimetype set.
|
mimetype set.
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
The mimetype is used for serialized objects, and tells the
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
read any of the formats listed below.
|
read any of the formats listed below.
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
value : The object must be serialized with
|
value : The object must be serialized with
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
: and then encoded with base64 encoding.
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
value : The object must be serialized with
|
value : The object must be serialized with
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
: and then encoded with base64 encoding.
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
value : The object must be serialized into a byte array
|
value : The object must be serialized into a byte array
|
||||||
: using a System.ComponentModel.TypeConverter
|
: using a System.ComponentModel.TypeConverter
|
||||||
: and then encoded with base64 encoding.
|
: and then encoded with base64 encoding.
|
||||||
-->
|
-->
|
||||||
|
|
@ -206,12 +206,6 @@ Instead, wrap the contents of the block in "{{}}":
|
||||||
<data name="ParseError_Unterminated_String_Literal" xml:space="preserve">
|
<data name="ParseError_Unterminated_String_Literal" xml:space="preserve">
|
||||||
<value>Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.</value>
|
<value>Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ParseError_UnknownOption" xml:space="preserve">
|
|
||||||
<value>Unknown option: "{0}".</value>
|
|
||||||
</data>
|
|
||||||
<data name="ParseError_BlockNotTerminated" xml:space="preserve">
|
|
||||||
<value>The "{0}" block was not terminated. All "{0}" statements must be terminated with a matching "{1}".</value>
|
|
||||||
</data>
|
|
||||||
<data name="SectionExample_CS" xml:space="preserve">
|
<data name="SectionExample_CS" xml:space="preserve">
|
||||||
<value>@section Header { ... }</value>
|
<value>@section Header { ... }</value>
|
||||||
<comment>In CSHTML, the @section keyword is case-sensitive and lowercase (as with all C# keywords)</comment>
|
<comment>In CSHTML, the @section keyword is case-sensitive and lowercase (as with all C# keywords)</comment>
|
||||||
|
|
@ -219,9 +213,6 @@ Instead, wrap the contents of the block in "{{}}":
|
||||||
<data name="ParseError_TextTagCannotContainAttributes" xml:space="preserve">
|
<data name="ParseError_TextTagCannotContainAttributes" xml:space="preserve">
|
||||||
<value>"<text>" and "</text>" tags cannot contain attributes.</value>
|
<value>"<text>" and "</text>" tags cannot contain attributes.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ParseError_NamespaceOrTypeAliasExpected" xml:space="preserve">
|
|
||||||
<value>The "Imports" keyword must be followed by a namespace or a type alias on the same line.</value>
|
|
||||||
</data>
|
|
||||||
<data name="ParseError_Unexpected_WhiteSpace_At_Start_Of_CodeBlock_CS" xml:space="preserve">
|
<data name="ParseError_Unexpected_WhiteSpace_At_Start_Of_CodeBlock_CS" xml:space="preserve">
|
||||||
<value>A space or line break was encountered after the "@" character. Only valid identifiers, keywords, comments, "(" and "{" are valid at the start of a code block and they must occur immediately following "@" with no space in between.</value>
|
<value>A space or line break was encountered after the "@" character. Only valid identifiers, keywords, comments, "(" and "{" are valid at the start of a code block and they must occur immediately following "@" with no space in between.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -321,9 +312,6 @@ Instead, wrap the contents of the block in "{{}}":
|
||||||
<data name="TokenizerView_CannotPutBack" xml:space="preserve">
|
<data name="TokenizerView_CannotPutBack" xml:space="preserve">
|
||||||
<value>In order to put a symbol back, it must have been the symbol which ended at the current position. The specified symbol ends at {0}, but the current position is {1}</value>
|
<value>In order to put a symbol back, it must have been the symbol which ended at the current position. The specified symbol ends at {0}, but the current position is {1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ParseError_Unexpected" xml:space="preserve">
|
|
||||||
<value>Unexpected "{0}"</value>
|
|
||||||
</data>
|
|
||||||
<data name="ParseError_Unexpected_Nested_CodeBlock" xml:space="preserve">
|
<data name="ParseError_Unexpected_Nested_CodeBlock" xml:space="preserve">
|
||||||
<value>Unexpected "{" after "@" character. Once inside the body of a code block (@if {}, @{}, etc.) you do not need to use "@{" to switch to code.</value>
|
<value>Unexpected "{" after "@" character. Once inside the body of a code block (@if {}, @{}, etc.) you do not need to use "@{" to switch to code.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -348,13 +336,6 @@ Instead, wrap the contents of the block in "{{}}":
|
||||||
<data name="Language_Does_Not_Support_RazorComment" xml:space="preserve">
|
<data name="Language_Does_Not_Support_RazorComment" xml:space="preserve">
|
||||||
<value>Cannot use built-in RazorComment handler, language characteristics does not define the CommentStart, CommentStar and CommentBody known symbol types or parser does not override TokenizerBackedParser.OutputSpanBeforeRazorComment</value>
|
<value>Cannot use built-in RazorComment handler, language characteristics does not define the CommentStart, CommentStar and CommentBody known symbol types or parser does not override TokenizerBackedParser.OutputSpanBeforeRazorComment</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ParserEror_SessionDirectiveMissingValue" xml:space="preserve">
|
|
||||||
<value>Missing value for session state directive.</value>
|
|
||||||
</data>
|
|
||||||
<data name="CreateCodeWriter_NoCodeWriter" xml:space="preserve">
|
|
||||||
<value>Cannot call CreateCodeWriter, a CodeWriter was not provided to the Create method</value>
|
|
||||||
<comment>This error should not be seen by users, it should only appear to internal developers, but I'm putting it in resources just in case</comment>
|
|
||||||
</data>
|
|
||||||
<data name="Trace_BackgroundThreadShutdown" xml:space="preserve">
|
<data name="Trace_BackgroundThreadShutdown" xml:space="preserve">
|
||||||
<value>[BG][{0}] Shutdown</value>
|
<value>[BG][{0}] Shutdown</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -404,17 +385,14 @@ Instead, wrap the contents of the block in "{{}}":
|
||||||
<value>Section blocks ("{0}") cannot be nested. Only one level of section blocks are allowed.</value>
|
<value>Section blocks ("{0}") cannot be nested. Only one level of section blocks are allowed.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TagHelpers_AttributesMustHaveAName" xml:space="preserve">
|
<data name="TagHelpers_AttributesMustHaveAName" xml:space="preserve">
|
||||||
<value>Tag Helper attributes must have a name.</value>
|
<value>Tag Helper '{0}'s attributes must have names.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TagHelpers_CannotHaveCSharpInTagDeclaration" xml:space="preserve">
|
<data name="TagHelpers_CannotHaveCSharpInTagDeclaration" xml:space="preserve">
|
||||||
<value>Tag Helpers cannot have C# in an HTML tag element's attribute declaration area.</value>
|
<value>The tag helper '{0}' must not have C# in the element's attribute declaration area.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TagHelpers_TagHelperCodeGeneartorMustBeAssociatedWithATagHelperBlock" xml:space="preserve">
|
<data name="TagHelpers_TagHelperCodeGeneartorMustBeAssociatedWithATagHelperBlock" xml:space="preserve">
|
||||||
<value>A TagHelperCodeGenerator must only be used with TagHelperBlocks.</value>
|
<value>A TagHelperCodeGenerator must only be used with TagHelperBlocks.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TagHelpers_AttributesThatAreNotStringsMustNotContainAtSymbols" xml:space="preserve">
|
|
||||||
<value>TagHelper attributes that do not expect strings must not have @ symbols within them. Found attribute '{0}' with an invalid value.</value>
|
|
||||||
</data>
|
|
||||||
<data name="ParseError_DirectiveMustHaveValue" xml:space="preserve">
|
<data name="ParseError_DirectiveMustHaveValue" xml:space="preserve">
|
||||||
<value>Directive '{0}' must have a value.</value>
|
<value>Directive '{0}' must have a value.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -424,4 +402,24 @@ Instead, wrap the contents of the block in "{{}}":
|
||||||
<data name="TagHelpersParseTreeRewriter_FoundMalformedTagHelper" xml:space="preserve">
|
<data name="TagHelpersParseTreeRewriter_FoundMalformedTagHelper" xml:space="preserve">
|
||||||
<value>Found a malformed '{0}' tag helper. Tag helpers must have a start and end tag or be self closing.</value>
|
<value>Found a malformed '{0}' tag helper. Tag helpers must have a start and end tag or be self closing.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TagHelpersParseTreeRewriter_MissingCloseAngle" xml:space="preserve">
|
||||||
|
<value>Missing close angle for tag helper '{0}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TagHelperBlockRewriter_TagHelperAttributesMustBeWelformed" xml:space="preserve">
|
||||||
|
<value>TagHelper attributes must be welformed.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TagHelpers_AttributeExpressionRequired" xml:space="preserve">
|
||||||
|
<value>Non-string tag helper attribute values must not be empty. Add an expression to this attribute value.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TagHelpers_CodeBlocks_NotSupported_InAttributes" xml:space="preserve">
|
||||||
|
<value>Code blocks (e.g. @{{var variable = 23;}}) must not appear in non-string tag helper attribute values.
|
||||||
|
Already in an expression (code) context. If necessary an explicit expression (e.g. @(@readonly)) may be used.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TagHelpers_Directives_NotSupported_InAttributes" xml:space="preserve">
|
||||||
|
<value>@'{0}' directives must not appear in non-string tag helper attribute values.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TagHelpers_InlineMarkupBlocks_NotSupported_InAttributes" xml:space="preserve">
|
||||||
|
<value>Inline markup blocks (e.g. @<p>content</p>) must not appear in non-string tag helper attribute values.
|
||||||
|
Expected a '{0}' attribute value, not a string.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -252,7 +252,7 @@ namespace Microsoft.AspNet.Razor
|
||||||
generator.DesignTimeMode = Host.DesignTimeMode;
|
generator.DesignTimeMode = Host.DesignTimeMode;
|
||||||
generator.Visit(results);
|
generator.Visit(results);
|
||||||
|
|
||||||
var codeBuilderContext = new CodeBuilderContext(generator.Context);
|
var codeBuilderContext = new CodeBuilderContext(generator.Context, results.ErrorSink);
|
||||||
codeBuilderContext.Checksum = checksum;
|
codeBuilderContext.Checksum = checksum;
|
||||||
var builder = CreateCodeBuilder(codeBuilderContext);
|
var builder = CreateCodeBuilder(codeBuilderContext);
|
||||||
var builderResult = builder.Build();
|
var builderResult = builder.Build();
|
||||||
|
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.TagHelpers
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Defines how a tag helper will utilize its inner HTML.
|
|
||||||
/// </summary>
|
|
||||||
public enum ContentBehavior
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates that a tag helper will not modify its content in any way. This is the default
|
|
||||||
/// <see cref="ContentBehavior"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Children of the current tag helper will execute after the current tag helper.</remarks>
|
|
||||||
None,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates the tag helper's content should be appended to what its children generate.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Children of the current tag helper will execute before the current tag helper.</remarks>
|
|
||||||
Append,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates that the tag helper will modify its HTML content. Therefore this <see cref="ContentBehavior"/>
|
|
||||||
/// enables the tag helper to examine the content its children generate.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Children of the current tag helper will execute before the current tag helper.</remarks>
|
|
||||||
Modify,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates the tag helper's content should be prepended to what its children generate.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Children of the current tag helper will execute after the current tag helper.</remarks>
|
|
||||||
Prepend,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates the tag helper's content should replace the HTML its children generate.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Children of the current tag helper will not execute.</remarks>
|
|
||||||
Replace,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -16,15 +16,25 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
/// Called during Razor's code generation process to generate code that instantiates the value of the tag
|
/// Called during Razor's code generation process to generate code that instantiates the value of the tag
|
||||||
/// helper's property. Last value written should not be or end with a semicolon.
|
/// helper's property. Last value written should not be or end with a semicolon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="attributeDescriptor">The <see cref="TagHelperAttributeDescriptor"/> to generate code for.</param>
|
/// <param name="attributeDescriptor">
|
||||||
|
/// The <see cref="TagHelperAttributeDescriptor"/> to generate code for.
|
||||||
|
/// </param>
|
||||||
/// <param name="writer">The <see cref="CSharpCodeWriter"/> that's used to write code.</param>
|
/// <param name="writer">The <see cref="CSharpCodeWriter"/> that's used to write code.</param>
|
||||||
/// <param name="context">A <see cref="CodeGeneratorContext"/> instance that contains information about
|
/// <param name="context">A <see cref="CodeGeneratorContext"/> instance that contains information about
|
||||||
/// the current code generation process.</param>
|
/// the current code generation process.</param>
|
||||||
/// <param name="renderAttributeValue"><see cref="Action"/> that renders the raw value of the HTML attribute.</param>
|
/// <param name="renderAttributeValue">
|
||||||
|
/// <see cref="Action"/> that renders the raw value of the HTML attribute.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="complexValue">
|
||||||
|
/// Indicates whether or not the source attribute value contains more than simple text. <c>false</c> for plain
|
||||||
|
/// C# expressions e.g. <c>"PropertyName"</c>. <c>true</c> if the attribute value contain at least one in-line
|
||||||
|
/// Razor construct e.g. <c>"@(@readonly)"</c>.
|
||||||
|
/// </param>
|
||||||
public virtual void RenderAttributeValue([NotNull] TagHelperAttributeDescriptor attributeDescriptor,
|
public virtual void RenderAttributeValue([NotNull] TagHelperAttributeDescriptor attributeDescriptor,
|
||||||
[NotNull] CSharpCodeWriter writer,
|
[NotNull] CSharpCodeWriter writer,
|
||||||
[NotNull] CodeBuilderContext context,
|
[NotNull] CodeBuilderContext context,
|
||||||
[NotNull] Action<CSharpCodeWriter> renderAttributeValue)
|
[NotNull] Action<CSharpCodeWriter> renderAttributeValue,
|
||||||
|
bool complexValue)
|
||||||
{
|
{
|
||||||
renderAttributeValue(writer);
|
renderAttributeValue(writer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal TagHelperDescriptor([NotNull] string tagName,
|
internal TagHelperDescriptor([NotNull] string tagName,
|
||||||
[NotNull] string typeName,
|
[NotNull] string typeName,
|
||||||
[NotNull] string assemblyName,
|
[NotNull] string assemblyName)
|
||||||
ContentBehavior contentBehavior)
|
|
||||||
: this(tagName,
|
: this(tagName,
|
||||||
typeName,
|
typeName,
|
||||||
assemblyName,
|
assemblyName,
|
||||||
contentBehavior,
|
|
||||||
Enumerable.Empty<TagHelperAttributeDescriptor>())
|
Enumerable.Empty<TagHelperAttributeDescriptor>())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -34,21 +32,17 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
/// <see cref="TagHelperDescriptor"/> which applies to every HTML tag.</param>
|
/// <see cref="TagHelperDescriptor"/> which applies to every HTML tag.</param>
|
||||||
/// <param name="typeName">The full name of the tag helper class.</param>
|
/// <param name="typeName">The full name of the tag helper class.</param>
|
||||||
/// <param name="assemblyName">The name of the assembly containing the tag helper class.</param>
|
/// <param name="assemblyName">The name of the assembly containing the tag helper class.</param>
|
||||||
/// <param name="contentBehavior">The <see cref="TagHelpers.ContentBehavior"/>
|
|
||||||
/// of the tag helper.</param>
|
|
||||||
/// <param name="attributes">
|
/// <param name="attributes">
|
||||||
/// The <see cref="TagHelperAttributeDescriptor"/>s to request from the HTML tag.
|
/// The <see cref="TagHelperAttributeDescriptor"/>s to request from the HTML tag.
|
||||||
/// </param>
|
/// </param>
|
||||||
public TagHelperDescriptor([NotNull] string tagName,
|
public TagHelperDescriptor([NotNull] string tagName,
|
||||||
[NotNull] string typeName,
|
[NotNull] string typeName,
|
||||||
[NotNull] string assemblyName,
|
[NotNull] string assemblyName,
|
||||||
ContentBehavior contentBehavior,
|
|
||||||
[NotNull] IEnumerable<TagHelperAttributeDescriptor> attributes)
|
[NotNull] IEnumerable<TagHelperAttributeDescriptor> attributes)
|
||||||
{
|
{
|
||||||
TagName = tagName;
|
TagName = tagName;
|
||||||
TypeName = typeName;
|
TypeName = typeName;
|
||||||
AssemblyName = assemblyName;
|
AssemblyName = assemblyName;
|
||||||
ContentBehavior = contentBehavior;
|
|
||||||
Attributes = new List<TagHelperAttributeDescriptor>(attributes);
|
Attributes = new List<TagHelperAttributeDescriptor>(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,11 +61,6 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string AssemblyName { get; private set; }
|
public string AssemblyName { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="TagHelpers.ContentBehavior"/> of the tag helper.
|
|
||||||
/// </summary>
|
|
||||||
public ContentBehavior ContentBehavior { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of attributes the tag helper expects.
|
/// The list of attributes the tag helper expects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,13 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
/// <c>false</c> otherwise.</returns>
|
/// <c>false</c> otherwise.</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Determines equality based on <see cref="TagHelperDescriptor.TypeName"/>,
|
/// Determines equality based on <see cref="TagHelperDescriptor.TypeName"/>,
|
||||||
/// <see cref="TagHelperDescriptor.AssemblyName"/>, <see cref="TagHelperDescriptor.TagName"/> and
|
/// <see cref="TagHelperDescriptor.AssemblyName"/> and <see cref="TagHelperDescriptor.TagName"/>.
|
||||||
/// <see cref="TagHelperDescriptor.ContentBehavior"/>.
|
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public bool Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)
|
public bool Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)
|
||||||
{
|
{
|
||||||
return string.Equals(descriptorX.TypeName, descriptorY.TypeName, StringComparison.Ordinal) &&
|
return string.Equals(descriptorX.TypeName, descriptorY.TypeName, StringComparison.Ordinal) &&
|
||||||
string.Equals(descriptorX.TagName, descriptorY.TagName, StringComparison.OrdinalIgnoreCase) &&
|
string.Equals(descriptorX.TagName, descriptorY.TagName, StringComparison.OrdinalIgnoreCase) &&
|
||||||
string.Equals(descriptorX.AssemblyName, descriptorY.AssemblyName, StringComparison.Ordinal) &&
|
string.Equals(descriptorX.AssemblyName, descriptorY.AssemblyName, StringComparison.Ordinal);
|
||||||
descriptorX.ContentBehavior == descriptorY.ContentBehavior;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -51,7 +49,6 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
.Add(descriptor.TagName, StringComparer.OrdinalIgnoreCase)
|
.Add(descriptor.TagName, StringComparer.OrdinalIgnoreCase)
|
||||||
.Add(descriptor.TypeName, StringComparer.Ordinal)
|
.Add(descriptor.TypeName, StringComparer.Ordinal)
|
||||||
.Add(descriptor.AssemblyName, StringComparer.Ordinal)
|
.Add(descriptor.AssemblyName, StringComparer.Ordinal)
|
||||||
.Add(descriptor.ContentBehavior)
|
|
||||||
.CombinedHash;
|
.CombinedHash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,13 @@
|
||||||
"System.Collections": "4.0.10-beta-*",
|
"System.Collections": "4.0.10-beta-*",
|
||||||
"System.Diagnostics.Debug": "4.0.10-beta-*",
|
"System.Diagnostics.Debug": "4.0.10-beta-*",
|
||||||
"System.Diagnostics.Tools": "4.0.0-beta-*",
|
"System.Diagnostics.Tools": "4.0.0-beta-*",
|
||||||
|
"System.IO": "4.0.10-beta-*",
|
||||||
"System.IO.FileSystem": "4.0.0-beta-*",
|
"System.IO.FileSystem": "4.0.0-beta-*",
|
||||||
"System.Linq": "4.0.0-beta-*",
|
"System.Linq": "4.0.0-beta-*",
|
||||||
"System.Reflection": "4.0.10-beta-*",
|
"System.Reflection": "4.0.10-beta-*",
|
||||||
"System.Resources.ResourceManager": "4.0.0-beta-*",
|
"System.Resources.ResourceManager": "4.0.0-beta-*",
|
||||||
"System.Runtime.Extensions": "4.0.10-beta-*",
|
"System.Runtime.Extensions": "4.0.10-beta-*",
|
||||||
"System.Threading": "4.0.0-beta-*",
|
"System.Threading": "4.0.10-beta-*",
|
||||||
"System.Threading.Tasks": "4.0.10-beta-*",
|
"System.Threading.Tasks": "4.0.10-beta-*",
|
||||||
"System.Threading.Thread": "4.0.0-beta-*",
|
"System.Threading.Thread": "4.0.0-beta-*",
|
||||||
"System.Security.Cryptography.Hashing.Algorithms": "4.0.0-beta-*"
|
"System.Security.Cryptography.Hashing.Algorithms": "4.0.0-beta-*"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// 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.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
|
|
@ -20,6 +21,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
bool IEqualityComparer<TagHelperDescriptor>.Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)
|
bool IEqualityComparer<TagHelperDescriptor>.Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)
|
||||||
{
|
{
|
||||||
return base.Equals(descriptorX, descriptorY) &&
|
return base.Equals(descriptorX, descriptorY) &&
|
||||||
|
// Tests should be exact casing
|
||||||
|
string.Equals(descriptorX.TagName, descriptorY.TagName, StringComparison.Ordinal) &&
|
||||||
descriptorX.Attributes.SequenceEqual(descriptorY.Attributes,
|
descriptorX.Attributes.SequenceEqual(descriptorY.Attributes,
|
||||||
CompleteTagHelperAttributeDescriptorComparer.Default);
|
CompleteTagHelperAttributeDescriptorComparer.Default);
|
||||||
}
|
}
|
||||||
|
|
@ -43,17 +46,17 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
|
|
||||||
public bool Equals(TagHelperAttributeDescriptor descriptorX, TagHelperAttributeDescriptor descriptorY)
|
public bool Equals(TagHelperAttributeDescriptor descriptorX, TagHelperAttributeDescriptor descriptorY)
|
||||||
{
|
{
|
||||||
return descriptorX.Name == descriptorY.Name &&
|
return string.Equals(descriptorX.Name, descriptorY.Name, StringComparison.Ordinal) &&
|
||||||
descriptorX.PropertyName == descriptorY.PropertyName &&
|
string.Equals(descriptorX.PropertyName, descriptorY.PropertyName, StringComparison.Ordinal) &&
|
||||||
descriptorX.TypeName == descriptorY.TypeName;
|
string.Equals(descriptorX.TypeName, descriptorY.TypeName, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetHashCode(TagHelperAttributeDescriptor descriptor)
|
public int GetHashCode(TagHelperAttributeDescriptor descriptor)
|
||||||
{
|
{
|
||||||
return HashCodeCombiner.Start()
|
return HashCodeCombiner.Start()
|
||||||
.Add(descriptor.Name)
|
.Add(descriptor.Name, StringComparer.Ordinal)
|
||||||
.Add(descriptor.PropertyName)
|
.Add(descriptor.PropertyName, StringComparer.Ordinal)
|
||||||
.Add(descriptor.TypeName)
|
.Add(descriptor.TypeName, StringComparer.Ordinal)
|
||||||
.CombinedHash;
|
.CombinedHash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -12,6 +13,42 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
private static readonly string AssemblyName =
|
private static readonly string AssemblyName =
|
||||||
typeof(TagHelperDescriptorFactoryTest).GetTypeInfo().Assembly.GetName().Name;
|
typeof(TagHelperDescriptorFactoryTest).GetTypeInfo().Assembly.GetName().Name;
|
||||||
|
|
||||||
|
public static TheoryData HtmlCaseData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// tagHelperType, expectedTagName, expectedAttributeName
|
||||||
|
return new TheoryData<Type, string, string>
|
||||||
|
{
|
||||||
|
{ typeof(SingleAttributeTagHelper), "single-attribute", "int-attribute" },
|
||||||
|
{ typeof(ALLCAPSTAGHELPER), "allcaps", "allcapsattribute" },
|
||||||
|
{ typeof(CAPSOnOUTSIDETagHelper), "caps-on-outside", "caps-on-outsideattribute" },
|
||||||
|
{ typeof(capsONInsideTagHelper), "caps-on-inside", "caps-on-insideattribute" },
|
||||||
|
{ typeof(One1Two2Three3TagHelper), "one1-two2-three3", "one1-two2-three3-attribute" },
|
||||||
|
{ typeof(ONE1TWO2THREE3TagHelper), "one1two2three3", "one1two2three3-attribute" },
|
||||||
|
{ typeof(First_Second_ThirdHiTagHelper), "first_second_third-hi", "first_second_third-attribute" },
|
||||||
|
{ typeof(UNSuffixedCLASS), "un-suffixed-class", "un-suffixed-attribute" },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(HtmlCaseData))]
|
||||||
|
public void CreateDescriptor_HtmlCasesTagNameAndAttributeName(
|
||||||
|
Type tagHelperType,
|
||||||
|
string expectedTagName,
|
||||||
|
string expectedAttributeName)
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(tagHelperType);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var descriptor = Assert.Single(descriptors);
|
||||||
|
Assert.Equal(expectedTagName, descriptor.TagName, StringComparer.Ordinal);
|
||||||
|
var attributeDescriptor = Assert.Single(descriptor.Attributes);
|
||||||
|
Assert.Equal(expectedAttributeName, attributeDescriptor.Name);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateDescriptor_OverridesAttributeNameFromAttribute()
|
public void CreateDescriptor_OverridesAttributeNameFromAttribute()
|
||||||
{
|
{
|
||||||
|
|
@ -22,10 +59,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
nameof(OverriddenAttributeTagHelper.ValidAttribute2));
|
nameof(OverriddenAttributeTagHelper.ValidAttribute2));
|
||||||
var expectedDescriptors = new[] {
|
var expectedDescriptors = new[] {
|
||||||
new TagHelperDescriptor(
|
new TagHelperDescriptor(
|
||||||
"OverriddenAttribute",
|
"overridden-attribute",
|
||||||
typeof(OverriddenAttributeTagHelper).FullName,
|
typeof(OverriddenAttributeTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName,
|
||||||
ContentBehavior.None,
|
|
||||||
new[] {
|
new[] {
|
||||||
new TagHelperAttributeDescriptor("SomethingElse", validProperty1),
|
new TagHelperAttributeDescriptor("SomethingElse", validProperty1),
|
||||||
new TagHelperAttributeDescriptor("Something-Else", validProperty2)
|
new TagHelperAttributeDescriptor("Something-Else", validProperty2)
|
||||||
|
|
@ -49,12 +85,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
nameof(InheritedOverriddenAttributeTagHelper.ValidAttribute2));
|
nameof(InheritedOverriddenAttributeTagHelper.ValidAttribute2));
|
||||||
var expectedDescriptors = new[] {
|
var expectedDescriptors = new[] {
|
||||||
new TagHelperDescriptor(
|
new TagHelperDescriptor(
|
||||||
"InheritedOverriddenAttribute",
|
"inherited-overridden-attribute",
|
||||||
typeof(InheritedOverriddenAttributeTagHelper).FullName,
|
typeof(InheritedOverriddenAttributeTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName,
|
||||||
ContentBehavior.None,
|
|
||||||
new[] {
|
new[] {
|
||||||
new TagHelperAttributeDescriptor(nameof(InheritedOverriddenAttributeTagHelper.ValidAttribute1),
|
new TagHelperAttributeDescriptor("valid-attribute1",
|
||||||
validProperty1),
|
validProperty1),
|
||||||
new TagHelperAttributeDescriptor("Something-Else", validProperty2)
|
new TagHelperAttributeDescriptor("Something-Else", validProperty2)
|
||||||
})
|
})
|
||||||
|
|
@ -77,10 +112,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
nameof(InheritedNotOverriddenAttributeTagHelper.ValidAttribute2));
|
nameof(InheritedNotOverriddenAttributeTagHelper.ValidAttribute2));
|
||||||
var expectedDescriptors = new[] {
|
var expectedDescriptors = new[] {
|
||||||
new TagHelperDescriptor(
|
new TagHelperDescriptor(
|
||||||
"InheritedNotOverriddenAttribute",
|
"inherited-not-overridden-attribute",
|
||||||
typeof(InheritedNotOverriddenAttributeTagHelper).FullName,
|
typeof(InheritedNotOverriddenAttributeTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName,
|
||||||
ContentBehavior.None,
|
|
||||||
new[] {
|
new[] {
|
||||||
new TagHelperAttributeDescriptor("SomethingElse", validProperty1),
|
new TagHelperAttributeDescriptor("SomethingElse", validProperty1),
|
||||||
new TagHelperAttributeDescriptor("Something-Else", validProperty2)
|
new TagHelperAttributeDescriptor("Something-Else", validProperty2)
|
||||||
|
|
@ -100,7 +134,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var objectAssemblyName = typeof(object).GetTypeInfo().Assembly.GetName().Name;
|
var objectAssemblyName = typeof(object).GetTypeInfo().Assembly.GetName().Name;
|
||||||
var expectedDescriptor =
|
var expectedDescriptor =
|
||||||
new TagHelperDescriptor("Object", "System.Object", objectAssemblyName, ContentBehavior.None);
|
new TagHelperDescriptor("object", "System.Object", objectAssemblyName);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(typeof(object));
|
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(typeof(object));
|
||||||
|
|
@ -117,12 +151,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
var intProperty = typeof(InheritedSingleAttributeTagHelper).GetProperty(
|
var intProperty = typeof(InheritedSingleAttributeTagHelper).GetProperty(
|
||||||
nameof(InheritedSingleAttributeTagHelper.IntAttribute));
|
nameof(InheritedSingleAttributeTagHelper.IntAttribute));
|
||||||
var expectedDescriptor = new TagHelperDescriptor(
|
var expectedDescriptor = new TagHelperDescriptor(
|
||||||
"InheritedSingleAttribute",
|
"inherited-single-attribute",
|
||||||
typeof(InheritedSingleAttributeTagHelper).FullName,
|
typeof(InheritedSingleAttributeTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName,
|
||||||
ContentBehavior.None,
|
|
||||||
new[] {
|
new[] {
|
||||||
new TagHelperAttributeDescriptor(nameof(InheritedSingleAttributeTagHelper.IntAttribute), intProperty)
|
new TagHelperAttributeDescriptor("int-attribute", intProperty)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -139,12 +172,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var intProperty = typeof(SingleAttributeTagHelper).GetProperty(nameof(SingleAttributeTagHelper.IntAttribute));
|
var intProperty = typeof(SingleAttributeTagHelper).GetProperty(nameof(SingleAttributeTagHelper.IntAttribute));
|
||||||
var expectedDescriptor = new TagHelperDescriptor(
|
var expectedDescriptor = new TagHelperDescriptor(
|
||||||
"SingleAttribute",
|
"single-attribute",
|
||||||
typeof(SingleAttributeTagHelper).FullName,
|
typeof(SingleAttributeTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName,
|
||||||
ContentBehavior.None,
|
|
||||||
new[] {
|
new[] {
|
||||||
new TagHelperAttributeDescriptor(nameof(SingleAttributeTagHelper.IntAttribute), intProperty)
|
new TagHelperAttributeDescriptor("int-attribute", intProperty)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -162,12 +194,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
var validProperty = typeof(MissingAccessorTagHelper).GetProperty(
|
var validProperty = typeof(MissingAccessorTagHelper).GetProperty(
|
||||||
nameof(MissingAccessorTagHelper.ValidAttribute));
|
nameof(MissingAccessorTagHelper.ValidAttribute));
|
||||||
var expectedDescriptor = new TagHelperDescriptor(
|
var expectedDescriptor = new TagHelperDescriptor(
|
||||||
"MissingAccessor",
|
"missing-accessor",
|
||||||
typeof(MissingAccessorTagHelper).FullName,
|
typeof(MissingAccessorTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName,
|
||||||
ContentBehavior.None,
|
|
||||||
new[] {
|
new[] {
|
||||||
new TagHelperAttributeDescriptor(nameof(MissingAccessorTagHelper.ValidAttribute), validProperty)
|
new TagHelperAttributeDescriptor("valid-attribute", validProperty)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -185,13 +216,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
var validProperty = typeof(PrivateAccessorTagHelper).GetProperty(
|
var validProperty = typeof(PrivateAccessorTagHelper).GetProperty(
|
||||||
nameof(PrivateAccessorTagHelper.ValidAttribute));
|
nameof(PrivateAccessorTagHelper.ValidAttribute));
|
||||||
var expectedDescriptor = new TagHelperDescriptor(
|
var expectedDescriptor = new TagHelperDescriptor(
|
||||||
"PrivateAccessor",
|
"private-accessor",
|
||||||
typeof(PrivateAccessorTagHelper).FullName,
|
typeof(PrivateAccessorTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName,
|
||||||
ContentBehavior.None,
|
|
||||||
new[] {
|
new[] {
|
||||||
new TagHelperAttributeDescriptor(
|
new TagHelperAttributeDescriptor(
|
||||||
nameof(PrivateAccessorTagHelper.ValidAttribute), validProperty)
|
"valid-attribute", validProperty)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -202,43 +232,6 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
Assert.Equal(expectedDescriptor, descriptor, CompleteTagHelperDescriptorComparer.Default);
|
Assert.Equal(expectedDescriptor, descriptor, CompleteTagHelperDescriptorComparer.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void CreateDescriptor_ResolvesCustomContentBehavior()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var expectedDescriptor = new TagHelperDescriptor(
|
|
||||||
"CustomContentBehavior",
|
|
||||||
typeof(CustomContentBehaviorTagHelper).FullName,
|
|
||||||
AssemblyName,
|
|
||||||
ContentBehavior.Append);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(typeof(CustomContentBehaviorTagHelper));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var descriptor = Assert.Single(descriptors);
|
|
||||||
Assert.Equal(expectedDescriptor, descriptor, CompleteTagHelperDescriptorComparer.Default);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void CreateDescriptor_DoesNotResolveInheritedCustomContentBehavior()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var expectedDescriptor = new TagHelperDescriptor(
|
|
||||||
"InheritedCustomContentBehavior",
|
|
||||||
typeof(InheritedCustomContentBehaviorTagHelper).FullName,
|
|
||||||
AssemblyName,
|
|
||||||
ContentBehavior.None);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
|
|
||||||
typeof(InheritedCustomContentBehaviorTagHelper));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var descriptor = Assert.Single(descriptors);
|
|
||||||
Assert.Equal(expectedDescriptor, descriptor, CompleteTagHelperDescriptorComparer.Default);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateDescriptor_ResolvesMultipleTagHelperDescriptorsFromSingleType()
|
public void CreateDescriptor_ResolvesMultipleTagHelperDescriptorsFromSingleType()
|
||||||
{
|
{
|
||||||
|
|
@ -249,17 +242,15 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
"div",
|
"div",
|
||||||
typeof(MultiTagTagHelper).FullName,
|
typeof(MultiTagTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName,
|
||||||
ContentBehavior.None,
|
|
||||||
new[] {
|
new[] {
|
||||||
new TagHelperAttributeDescriptor(nameof(MultiTagTagHelper.ValidAttribute), validProp)
|
new TagHelperAttributeDescriptor("valid-attribute", validProp)
|
||||||
}),
|
}),
|
||||||
new TagHelperDescriptor(
|
new TagHelperDescriptor(
|
||||||
"p",
|
"p",
|
||||||
typeof(MultiTagTagHelper).FullName,
|
typeof(MultiTagTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName,
|
||||||
ContentBehavior.None,
|
|
||||||
new[] {
|
new[] {
|
||||||
new TagHelperAttributeDescriptor(nameof(MultiTagTagHelper.ValidAttribute), validProp)
|
new TagHelperAttributeDescriptor("valid-attribute", validProp)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -276,12 +267,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var validProp = typeof(InheritedMultiTagTagHelper).GetProperty(nameof(InheritedMultiTagTagHelper.ValidAttribute));
|
var validProp = typeof(InheritedMultiTagTagHelper).GetProperty(nameof(InheritedMultiTagTagHelper.ValidAttribute));
|
||||||
var expectedDescriptor = new TagHelperDescriptor(
|
var expectedDescriptor = new TagHelperDescriptor(
|
||||||
"InheritedMultiTag",
|
"inherited-multi-tag",
|
||||||
typeof(InheritedMultiTagTagHelper).FullName,
|
typeof(InheritedMultiTagTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName,
|
||||||
ContentBehavior.None,
|
|
||||||
new[] {
|
new[] {
|
||||||
new TagHelperAttributeDescriptor(nameof(InheritedMultiTagTagHelper.ValidAttribute), validProp)
|
new TagHelperAttributeDescriptor("valid-attribute", validProp)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -300,13 +290,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
new TagHelperDescriptor(
|
new TagHelperDescriptor(
|
||||||
"p",
|
"p",
|
||||||
typeof(DuplicateTagNameTagHelper).FullName,
|
typeof(DuplicateTagNameTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName),
|
||||||
ContentBehavior.None),
|
|
||||||
new TagHelperDescriptor(
|
new TagHelperDescriptor(
|
||||||
"div",
|
"div",
|
||||||
typeof(DuplicateTagNameTagHelper).FullName,
|
typeof(DuplicateTagNameTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName)
|
||||||
ContentBehavior.None)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -323,8 +311,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
var expectedDescriptors = new[] {
|
var expectedDescriptors = new[] {
|
||||||
new TagHelperDescriptor("data-condition",
|
new TagHelperDescriptor("data-condition",
|
||||||
typeof(OverrideNameTagHelper).FullName,
|
typeof(OverrideNameTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName),
|
||||||
ContentBehavior.None),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -342,18 +329,15 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
new TagHelperDescriptor(
|
new TagHelperDescriptor(
|
||||||
"span",
|
"span",
|
||||||
typeof(MultipleAttributeTagHelper).FullName,
|
typeof(MultipleAttributeTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName),
|
||||||
ContentBehavior.None),
|
|
||||||
new TagHelperDescriptor(
|
new TagHelperDescriptor(
|
||||||
"p",
|
"p",
|
||||||
typeof(MultipleAttributeTagHelper).FullName,
|
typeof(MultipleAttributeTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName),
|
||||||
ContentBehavior.None),
|
|
||||||
new TagHelperDescriptor(
|
new TagHelperDescriptor(
|
||||||
"div",
|
"div",
|
||||||
typeof(MultipleAttributeTagHelper).FullName,
|
typeof(MultipleAttributeTagHelper).FullName,
|
||||||
AssemblyName,
|
AssemblyName)
|
||||||
ContentBehavior.None)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -363,16 +347,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
Assert.Equal(expectedDescriptors, descriptors, CompleteTagHelperDescriptorComparer.Default);
|
Assert.Equal(expectedDescriptors, descriptors, CompleteTagHelperDescriptorComparer.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ContentBehavior(ContentBehavior.Append)]
|
[HtmlElementName("p", "div")]
|
||||||
private class CustomContentBehaviorTagHelper
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private class InheritedCustomContentBehaviorTagHelper : CustomContentBehaviorTagHelper
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[TagName("p", "div")]
|
|
||||||
private class MultiTagTagHelper
|
private class MultiTagTagHelper
|
||||||
{
|
{
|
||||||
public string ValidAttribute { get; set; }
|
public string ValidAttribute { get; set; }
|
||||||
|
|
@ -382,18 +357,18 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[TagName("p", "p", "div", "div")]
|
[HtmlElementName("p", "p", "div", "div")]
|
||||||
private class DuplicateTagNameTagHelper
|
private class DuplicateTagNameTagHelper
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[TagName("data-condition")]
|
[HtmlElementName("data-condition")]
|
||||||
private class OverrideNameTagHelper
|
private class OverrideNameTagHelper
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[TagName("span")]
|
[HtmlElementName("span")]
|
||||||
[TagName("div", "p")]
|
[HtmlElementName("div", "p")]
|
||||||
private class MultipleAttributeTagHelper
|
private class MultipleAttributeTagHelper
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -419,5 +394,41 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
private class InheritedNotOverriddenAttributeTagHelper : OverriddenAttributeTagHelper
|
private class InheritedNotOverriddenAttributeTagHelper : OverriddenAttributeTagHelper
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ALLCAPSTAGHELPER : TagHelper
|
||||||
|
{
|
||||||
|
public int ALLCAPSATTRIBUTE { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CAPSOnOUTSIDETagHelper : TagHelper
|
||||||
|
{
|
||||||
|
public int CAPSOnOUTSIDEATTRIBUTE { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class capsONInsideTagHelper : TagHelper
|
||||||
|
{
|
||||||
|
public int capsONInsideattribute { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class One1Two2Three3TagHelper : TagHelper
|
||||||
|
{
|
||||||
|
public int One1Two2Three3Attribute { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ONE1TWO2THREE3TagHelper : TagHelper
|
||||||
|
{
|
||||||
|
public int ONE1TWO2THREE3Attribute { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class First_Second_ThirdHiTagHelper : TagHelper
|
||||||
|
{
|
||||||
|
public int First_Second_ThirdAttribute { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UNSuffixedCLASS : TagHelper
|
||||||
|
{
|
||||||
|
public int UNSuffixedATTRIBUTE { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -25,10 +25,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return new TagHelperDescriptor("Valid_Plain",
|
return new TagHelperDescriptor("valid_plain",
|
||||||
Valid_PlainTagHelperType.FullName,
|
Valid_PlainTagHelperType.FullName,
|
||||||
AssemblyName,
|
AssemblyName);
|
||||||
ContentBehavior.None);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,10 +35,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return new TagHelperDescriptor("Valid_Inherited",
|
return new TagHelperDescriptor("valid_inherited",
|
||||||
Valid_InheritedTagHelperType.FullName,
|
Valid_InheritedTagHelperType.FullName,
|
||||||
AssemblyName,
|
AssemblyName);
|
||||||
ContentBehavior.None);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,8 +73,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
var stringTagHelperDescriptor =
|
var stringTagHelperDescriptor =
|
||||||
new TagHelperDescriptor("string",
|
new TagHelperDescriptor("string",
|
||||||
"System.String",
|
"System.String",
|
||||||
assemblyB,
|
assemblyB);
|
||||||
ContentBehavior.None);
|
|
||||||
|
|
||||||
return new TheoryData<Dictionary<string, IEnumerable<Type>>, // descriptorAssemblyLookups
|
return new TheoryData<Dictionary<string, IEnumerable<Type>>, // descriptorAssemblyLookups
|
||||||
IEnumerable<TagHelperDirectiveDescriptor>, // directiveDescriptors
|
IEnumerable<TagHelperDirectiveDescriptor>, // directiveDescriptors
|
||||||
|
|
@ -230,8 +227,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
var stringTagHelperDescriptor =
|
var stringTagHelperDescriptor =
|
||||||
new TagHelperDescriptor("string",
|
new TagHelperDescriptor("string",
|
||||||
"System.String",
|
"System.String",
|
||||||
assemblyB,
|
assemblyB);
|
||||||
ContentBehavior.None);
|
|
||||||
|
|
||||||
return new TheoryData<Dictionary<string, IEnumerable<Type>>, // descriptorAssemblyLookups
|
return new TheoryData<Dictionary<string, IEnumerable<Type>>, // descriptorAssemblyLookups
|
||||||
IEnumerable<TagHelperDirectiveDescriptor>> // directiveDescriptors
|
IEnumerable<TagHelperDirectiveDescriptor>> // directiveDescriptors
|
||||||
|
|
@ -358,7 +354,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperTypeResolver = new TestTagHelperTypeResolver(TestableTagHelpers)
|
var tagHelperTypeResolver = new TestTagHelperTypeResolver(TestableTagHelpers)
|
||||||
{
|
{
|
||||||
OnGetLibraryDefinedTypes = (assemblyName) =>
|
OnGetExportedTypes = (assemblyName) =>
|
||||||
{
|
{
|
||||||
Assert.Equal("MyAssembly", assemblyName.Name);
|
Assert.Equal("MyAssembly", assemblyName.Name);
|
||||||
}
|
}
|
||||||
|
|
@ -523,7 +519,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
_lookupValues = lookupValues;
|
_lookupValues = lookupValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override IEnumerable<TypeInfo> GetLibraryDefinedTypes(AssemblyName assemblyName)
|
protected override IEnumerable<TypeInfo> GetExportedTypes(AssemblyName assemblyName)
|
||||||
{
|
{
|
||||||
IEnumerable<Type> types;
|
IEnumerable<Type> types;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,76 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// 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.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
{
|
{
|
||||||
public class TagHelperExecutionContextTest
|
public class TagHelperExecutionContextTest
|
||||||
{
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task GetChildContentAsync_CachesValue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var writer = new StringWriter();
|
||||||
|
var expectedContent = string.Empty;
|
||||||
|
var executionContext = new TagHelperExecutionContext(
|
||||||
|
"p",
|
||||||
|
uniqueId: string.Empty,
|
||||||
|
executeChildContentAsync: () =>
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(expectedContent))
|
||||||
|
{
|
||||||
|
expectedContent = "Hello from child content: " + Guid.NewGuid().ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.Write(expectedContent);
|
||||||
|
|
||||||
|
return Task.FromResult(result: true);
|
||||||
|
},
|
||||||
|
startWritingScope: () => { },
|
||||||
|
endWritingScope: () => writer);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var content1 = await executionContext.GetChildContentAsync();
|
||||||
|
var content2 = await executionContext.GetChildContentAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Same(content1, content2);
|
||||||
|
Assert.Equal(expectedContent, content1);
|
||||||
|
Assert.Equal(expectedContent, content2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ExecuteChildContentAsync_IsNotMemoized()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var childContentExecutionCount = 0;
|
||||||
|
var executionContext = new TagHelperExecutionContext(
|
||||||
|
"p",
|
||||||
|
uniqueId: string.Empty,
|
||||||
|
executeChildContentAsync: () =>
|
||||||
|
{
|
||||||
|
childContentExecutionCount++;
|
||||||
|
|
||||||
|
return Task.FromResult(result: true);
|
||||||
|
},
|
||||||
|
startWritingScope: () => { },
|
||||||
|
endWritingScope: () => new StringWriter());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await executionContext.ExecuteChildContentAsync();
|
||||||
|
await executionContext.ExecuteChildContentAsync();
|
||||||
|
await executionContext.ExecuteChildContentAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(3, childContentExecutionCount);
|
||||||
|
}
|
||||||
|
|
||||||
public static TheoryData<string, string> DictionaryCaseTestingData
|
public static TheoryData<string, string> DictionaryCaseTestingData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
||||||
|
|
@ -9,39 +9,65 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
public class TagHelperOutputTest
|
public class TagHelperOutputTest
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TagName_CannotSetToNullInCtor()
|
public void TagName_CanSetToNullInCtor()
|
||||||
{
|
{
|
||||||
// Arrange & Act
|
// Arrange & Act
|
||||||
var tagHelperOutput = new TagHelperOutput(null);
|
var tagHelperOutput = new TagHelperOutput(null);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(tagHelperOutput.TagName);
|
Assert.Null(tagHelperOutput.TagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TagName_CannotSetToNull()
|
public void TagName_CanSetToNull()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange & Act
|
||||||
var tagHelperOutput = new TagHelperOutput("p");
|
var tagHelperOutput = new TagHelperOutput("p")
|
||||||
|
{
|
||||||
// Act
|
TagName = null
|
||||||
tagHelperOutput.TagName = null;
|
};
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(tagHelperOutput.TagName);
|
Assert.Null(tagHelperOutput.TagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Content_CannotSetToNull()
|
public void Content_CanSetToNull()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange & Act
|
||||||
var tagHelperOutput = new TagHelperOutput("p");
|
var tagHelperOutput = new TagHelperOutput("p")
|
||||||
|
{
|
||||||
// Act
|
Content = null
|
||||||
tagHelperOutput.Content = null;
|
};
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(tagHelperOutput.Content);
|
Assert.Null(tagHelperOutput.Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreContent_CanSetToNull()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var tagHelperOutput = new TagHelperOutput("p")
|
||||||
|
{
|
||||||
|
PreContent = null
|
||||||
|
};
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Null(tagHelperOutput.PreContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PostContent_CanSetToNull()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var tagHelperOutput = new TagHelperOutput("p")
|
||||||
|
{
|
||||||
|
PostContent = null
|
||||||
|
};
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Null(tagHelperOutput.PostContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -119,9 +145,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
{
|
{
|
||||||
{ "class", "btn" },
|
{ "class", "btn" },
|
||||||
{ "something", " spaced " }
|
{ "something", " spaced " }
|
||||||
});
|
})
|
||||||
|
{
|
||||||
tagHelperOutput.SelfClosing = true;
|
SelfClosing = true
|
||||||
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var output = tagHelperOutput.GenerateStartTag();
|
var output = tagHelperOutput.GenerateStartTag();
|
||||||
|
|
@ -135,9 +162,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
public void GenerateEndTag_ReturnsNothingIfWhitespaceTagName()
|
public void GenerateEndTag_ReturnsNothingIfWhitespaceTagName()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput(" "); ;
|
var tagHelperOutput = new TagHelperOutput(" ")
|
||||||
|
{
|
||||||
tagHelperOutput.Content = "Hello World";
|
Content = "Hello World"
|
||||||
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var output = tagHelperOutput.GenerateEndTag();
|
var output = tagHelperOutput.GenerateEndTag();
|
||||||
|
|
@ -146,13 +174,47 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
Assert.Empty(output);
|
Assert.Empty(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GeneratePreContent_ReturnsPreContent()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperOutput = new TagHelperOutput("p")
|
||||||
|
{
|
||||||
|
PreContent = "Hello World"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var output = tagHelperOutput.GeneratePreContent();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("Hello World", output);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GeneratePreContent_ReturnsNothingIfSelfClosing()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperOutput = new TagHelperOutput("p")
|
||||||
|
{
|
||||||
|
SelfClosing = true,
|
||||||
|
PreContent = "Hello World"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var output = tagHelperOutput.GeneratePreContent();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(output);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GenerateContent_ReturnsContent()
|
public void GenerateContent_ReturnsContent()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput("p");
|
var tagHelperOutput = new TagHelperOutput("p")
|
||||||
|
{
|
||||||
tagHelperOutput.Content = "Hello World";
|
Content = "Hello World"
|
||||||
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var output = tagHelperOutput.GenerateContent();
|
var output = tagHelperOutput.GenerateContent();
|
||||||
|
|
@ -168,11 +230,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var tagHelperOutput = new TagHelperOutput("p")
|
var tagHelperOutput = new TagHelperOutput("p")
|
||||||
{
|
{
|
||||||
SelfClosing = true
|
SelfClosing = true,
|
||||||
|
Content = "Hello World"
|
||||||
};
|
};
|
||||||
|
|
||||||
tagHelperOutput.Content = "Hello World";
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var output = tagHelperOutput.GenerateContent();
|
var output = tagHelperOutput.GenerateContent();
|
||||||
|
|
||||||
|
|
@ -180,6 +241,39 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
Assert.Empty(output);
|
Assert.Empty(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GeneratePostContent_ReturnsPostContent()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperOutput = new TagHelperOutput("p")
|
||||||
|
{
|
||||||
|
PostContent = "Hello World"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var output = tagHelperOutput.GeneratePostContent();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("Hello World", output);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GeneratePostContent_ReturnsNothingIfSelfClosing()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperOutput = new TagHelperOutput("p")
|
||||||
|
{
|
||||||
|
SelfClosing = true,
|
||||||
|
PostContent = "Hello World"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var output = tagHelperOutput.GeneratePostContent();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(output);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GenerateEndTag_ReturnsEndTag()
|
public void GenerateEndTag_ReturnsEndTag()
|
||||||
{
|
{
|
||||||
|
|
@ -209,6 +303,54 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
Assert.Empty(output);
|
Assert.Empty(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SuppressOutput_Sets_TagName_Content_PreContent_PostContent_ToNull()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperOutput = new TagHelperOutput("p")
|
||||||
|
{
|
||||||
|
PreContent = "Pre Content",
|
||||||
|
Content = "Content",
|
||||||
|
PostContent = "Post Content"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
tagHelperOutput.SuppressOutput();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Null(tagHelperOutput.TagName);
|
||||||
|
Assert.Null(tagHelperOutput.PreContent);
|
||||||
|
Assert.Null(tagHelperOutput.Content);
|
||||||
|
Assert.Null(tagHelperOutput.PostContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SuppressOutput_PreventsTagOutput()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperOutput = new TagHelperOutput("p",
|
||||||
|
attributes: new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "class", "btn" },
|
||||||
|
{ "something", " spaced " }
|
||||||
|
})
|
||||||
|
{
|
||||||
|
PreContent = "Pre Content",
|
||||||
|
Content = "Content",
|
||||||
|
PostContent = "Post Content"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
tagHelperOutput.SuppressOutput();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(tagHelperOutput.GenerateStartTag());
|
||||||
|
Assert.Null(tagHelperOutput.GeneratePreContent());
|
||||||
|
Assert.Null(tagHelperOutput.GenerateContent());
|
||||||
|
Assert.Null(tagHelperOutput.GeneratePostContent());
|
||||||
|
Assert.Empty(tagHelperOutput.GenerateEndTag());
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("class", "ClASs")]
|
[InlineData("class", "ClASs")]
|
||||||
[InlineData("CLaSs", "class")]
|
[InlineData("CLaSs", "class")]
|
||||||
|
|
|
||||||
|
|
@ -66,23 +66,6 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
Assert.Equal("True", output.Attributes["foo"]);
|
Assert.Equal("True", output.Attributes["foo"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task RunAsync_WithContentSetsOutputsContent()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var runner = new TagHelperRunner();
|
|
||||||
var executionContext = new TagHelperExecutionContext("p");
|
|
||||||
var tagHelper = new ExecutableTagHelper();
|
|
||||||
var contentWriter = new StringWriter(new StringBuilder("Hello World"));
|
|
||||||
|
|
||||||
// Act
|
|
||||||
executionContext.Add(tagHelper);
|
|
||||||
var output = await runner.RunAsync(executionContext, contentWriter);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(output.Content, "Hello World");
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ExecutableTagHelper : TagHelper
|
private class ExecutableTagHelper : TagHelper
|
||||||
{
|
{
|
||||||
public bool Processed { get; set; }
|
public bool Processed { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -9,6 +11,11 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
||||||
{
|
{
|
||||||
public class TagHelperScopeManagerTest
|
public class TagHelperScopeManagerTest
|
||||||
{
|
{
|
||||||
|
private static readonly Action DefaultStartWritingScope = () => { };
|
||||||
|
private static readonly Func<TextWriter> DefaultEndWritingScope = () => new StringWriter();
|
||||||
|
private static readonly Func<Task> DefaultExecuteChildContentAsync =
|
||||||
|
async () => await Task.FromResult(result: true);
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Begin_CreatesContextWithAppropriateTagName()
|
public void Begin_CreatesContextWithAppropriateTagName()
|
||||||
{
|
{
|
||||||
|
|
@ -16,7 +23,11 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
||||||
var scopeManager = new TagHelperScopeManager();
|
var scopeManager = new TagHelperScopeManager();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var executionContext = scopeManager.Begin("p");
|
var executionContext = scopeManager.Begin("p",
|
||||||
|
string.Empty,
|
||||||
|
DefaultExecuteChildContentAsync,
|
||||||
|
DefaultStartWritingScope,
|
||||||
|
DefaultEndWritingScope);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("p", executionContext.TagName);
|
Assert.Equal("p", executionContext.TagName);
|
||||||
|
|
@ -29,8 +40,16 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
||||||
var scopeManager = new TagHelperScopeManager();
|
var scopeManager = new TagHelperScopeManager();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var executionContext = scopeManager.Begin("p");
|
var executionContext = scopeManager.Begin("p",
|
||||||
executionContext = scopeManager.Begin("div");
|
string.Empty,
|
||||||
|
DefaultExecuteChildContentAsync,
|
||||||
|
DefaultStartWritingScope,
|
||||||
|
DefaultEndWritingScope);
|
||||||
|
executionContext = scopeManager.Begin("div",
|
||||||
|
string.Empty,
|
||||||
|
DefaultExecuteChildContentAsync,
|
||||||
|
DefaultStartWritingScope,
|
||||||
|
DefaultEndWritingScope);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("div", executionContext.TagName);
|
Assert.Equal("div", executionContext.TagName);
|
||||||
|
|
@ -43,8 +62,16 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
||||||
var scopeManager = new TagHelperScopeManager();
|
var scopeManager = new TagHelperScopeManager();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var executionContext = scopeManager.Begin("p");
|
var executionContext = scopeManager.Begin("p",
|
||||||
executionContext = scopeManager.Begin("div");
|
string.Empty,
|
||||||
|
DefaultExecuteChildContentAsync,
|
||||||
|
DefaultStartWritingScope,
|
||||||
|
DefaultEndWritingScope);
|
||||||
|
executionContext = scopeManager.Begin("div",
|
||||||
|
string.Empty,
|
||||||
|
DefaultExecuteChildContentAsync,
|
||||||
|
DefaultStartWritingScope,
|
||||||
|
DefaultEndWritingScope);
|
||||||
executionContext = scopeManager.End();
|
executionContext = scopeManager.End();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
@ -58,8 +85,16 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
||||||
var scopeManager = new TagHelperScopeManager();
|
var scopeManager = new TagHelperScopeManager();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var executionContext = scopeManager.Begin("p");
|
var executionContext = scopeManager.Begin("p",
|
||||||
executionContext = scopeManager.Begin("div");
|
string.Empty,
|
||||||
|
DefaultExecuteChildContentAsync,
|
||||||
|
DefaultStartWritingScope,
|
||||||
|
DefaultEndWritingScope);
|
||||||
|
executionContext = scopeManager.Begin("div",
|
||||||
|
string.Empty,
|
||||||
|
DefaultExecuteChildContentAsync,
|
||||||
|
DefaultStartWritingScope,
|
||||||
|
DefaultEndWritingScope);
|
||||||
executionContext = scopeManager.End();
|
executionContext = scopeManager.End();
|
||||||
executionContext = scopeManager.End();
|
executionContext = scopeManager.End();
|
||||||
|
|
||||||
|
|
@ -85,7 +120,6 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
||||||
});
|
});
|
||||||
|
|
||||||
Assert.Equal(expectedError, ex.Message);
|
Assert.Equal(expectedError, ex.Message);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -114,14 +114,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||||
public TestTagHelperTypeResolver(IEnumerable<Type> assemblyTypes)
|
public TestTagHelperTypeResolver(IEnumerable<Type> assemblyTypes)
|
||||||
{
|
{
|
||||||
_assemblyTypeInfos = assemblyTypes.Select(type => type.GetTypeInfo());
|
_assemblyTypeInfos = assemblyTypes.Select(type => type.GetTypeInfo());
|
||||||
OnGetLibraryDefinedTypes = (_) => { };
|
OnGetExportedTypes = (_) => { };
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action<AssemblyName> OnGetLibraryDefinedTypes { get; set; }
|
public Action<AssemblyName> OnGetExportedTypes { get; set; }
|
||||||
|
|
||||||
internal override IEnumerable<TypeInfo> GetLibraryDefinedTypes(AssemblyName assemblyName)
|
protected override IEnumerable<TypeInfo> GetExportedTypes(AssemblyName assemblyName)
|
||||||
{
|
{
|
||||||
OnGetLibraryDefinedTypes(assemblyName);
|
OnGetExportedTypes(assemblyName);
|
||||||
|
|
||||||
return _assemblyTypeInfos;
|
return _assemblyTypeInfos;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,16 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.AspNet.Razor.Runtime": "4.0.0-*",
|
"Microsoft.AspNet.Razor.Runtime": "4.0.0-*",
|
||||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||||
"Xunit.KRunner": "1.0.0-*"
|
"xunit.runner.kre": "1.0.0-*"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
"test": "Xunit.KRunner"
|
"test": "xunit.runner.kre"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"aspnet50": { },
|
"aspnet50": { },
|
||||||
"aspnetcore50": {
|
"aspnetcore50": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"System.Reflection.TypeExtensions": "4.0.0-beta-*",
|
||||||
"System.Runtime.Extensions": "4.0.10-beta-*"
|
"System.Runtime.Extensions": "4.0.10-beta-*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,8 @@ namespace Microsoft.AspNet.Razor.Test
|
||||||
"myclass",
|
"myclass",
|
||||||
"myns",
|
"myns",
|
||||||
string.Empty,
|
string.Empty,
|
||||||
shouldGenerateLinePragmas: false);
|
shouldGenerateLinePragmas: false,
|
||||||
|
errorSink: new ParserErrorSink());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var generator = language.CreateCodeBuilder(codeBuilderContext);
|
var generator = language.CreateCodeBuilder(codeBuilderContext);
|
||||||
|
|
|
||||||
|
|
@ -434,28 +434,30 @@ namespace Microsoft.AspNet.Razor.Test.Framework
|
||||||
collector.AddError("{0} - FAILED :: Actual: << Null >>", expected);
|
collector.AddError("{0} - FAILED :: Actual: << Null >>", expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EvaluateRazorErrors(IList<RazorError> actualErrors, IList<RazorError> expectedErrors)
|
public static void EvaluateRazorErrors(IEnumerable<RazorError> actualErrors, IList<RazorError> expectedErrors)
|
||||||
{
|
{
|
||||||
|
var realCount = actualErrors.Count();
|
||||||
|
|
||||||
// Evaluate the errors
|
// Evaluate the errors
|
||||||
if (expectedErrors == null || expectedErrors.Count == 0)
|
if (expectedErrors == null || expectedErrors.Count == 0)
|
||||||
{
|
{
|
||||||
Assert.True(actualErrors.Count == 0,
|
Assert.True(realCount == 0,
|
||||||
String.Format("Expected that no errors would be raised, but the following errors were:\r\n{0}", FormatErrors(actualErrors)));
|
String.Format("Expected that no errors would be raised, but the following errors were:\r\n{0}", FormatErrors(actualErrors)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Assert.True(expectedErrors.Count == actualErrors.Count,
|
Assert.True(expectedErrors.Count == realCount,
|
||||||
String.Format("Expected that {0} errors would be raised, but {1} errors were.\r\nExpected Errors: \r\n{2}\r\nActual Errors: \r\n{3}",
|
String.Format("Expected that {0} errors would be raised, but {1} errors were.\r\nExpected Errors: \r\n{2}\r\nActual Errors: \r\n{3}",
|
||||||
expectedErrors.Count,
|
expectedErrors.Count,
|
||||||
actualErrors.Count,
|
realCount,
|
||||||
FormatErrors(expectedErrors),
|
FormatErrors(expectedErrors),
|
||||||
FormatErrors(actualErrors)));
|
FormatErrors(actualErrors)));
|
||||||
Assert.Equal(expectedErrors.ToArray(), actualErrors.ToArray());
|
Assert.Equal(expectedErrors, actualErrors);
|
||||||
}
|
}
|
||||||
WriteTraceLine("Expected Errors were raised:\r\n{0}", FormatErrors(expectedErrors));
|
WriteTraceLine("Expected Errors were raised:\r\n{0}", FormatErrors(expectedErrors));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FormatErrors(IList<RazorError> errors)
|
public static string FormatErrors(IEnumerable<RazorError> errors)
|
||||||
{
|
{
|
||||||
if (errors == null)
|
if (errors == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -300,11 +300,6 @@ namespace Microsoft.AspNet.Razor.Test.Framework
|
||||||
return _self.With(new SetBaseTypeCodeGenerator(baseType));
|
return _self.With(new SetBaseTypeCodeGenerator(baseType));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpanConstructor AsRazorDirectiveAttribute(string key, string value)
|
|
||||||
{
|
|
||||||
return _self.With(new RazorDirectiveAttributeCodeGenerator(key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SpanConstructor AsAddTagHelper(string lookupText)
|
public SpanConstructor AsAddTagHelper(string lookupText)
|
||||||
{
|
{
|
||||||
return _self.With(
|
return _self.With(
|
||||||
|
|
|
||||||
|
|
@ -26,21 +26,18 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
new TagHelperDescriptor("p",
|
new TagHelperDescriptor("p",
|
||||||
"PTagHelper",
|
"PTagHelper",
|
||||||
"SomeAssembly",
|
"SomeAssembly",
|
||||||
ContentBehavior.None,
|
|
||||||
new [] {
|
new [] {
|
||||||
new TagHelperAttributeDescriptor("age", pAgePropertyInfo)
|
new TagHelperAttributeDescriptor("age", pAgePropertyInfo)
|
||||||
}),
|
}),
|
||||||
new TagHelperDescriptor("input",
|
new TagHelperDescriptor("input",
|
||||||
"InputTagHelper",
|
"InputTagHelper",
|
||||||
"SomeAssembly",
|
"SomeAssembly",
|
||||||
ContentBehavior.None,
|
|
||||||
new TagHelperAttributeDescriptor[] {
|
new TagHelperAttributeDescriptor[] {
|
||||||
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
|
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
|
||||||
}),
|
}),
|
||||||
new TagHelperDescriptor("input",
|
new TagHelperDescriptor("input",
|
||||||
"InputTagHelper2",
|
"InputTagHelper2",
|
||||||
"SomeAssembly",
|
"SomeAssembly",
|
||||||
ContentBehavior.None,
|
|
||||||
new TagHelperAttributeDescriptor[] {
|
new TagHelperAttributeDescriptor[] {
|
||||||
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo),
|
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo),
|
||||||
new TagHelperAttributeDescriptor("checked", checkedPropertyInfo)
|
new TagHelperAttributeDescriptor("checked", checkedPropertyInfo)
|
||||||
|
|
@ -49,21 +46,6 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<TagHelperDescriptor> ContentBehaviorTagHelperDescriptors
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new[]
|
|
||||||
{
|
|
||||||
new TagHelperDescriptor("modify", "ModifyTagHelper", "SomeAssembly", ContentBehavior.Modify),
|
|
||||||
new TagHelperDescriptor("none", "NoneTagHelper", "SomeAssembly", ContentBehavior.None),
|
|
||||||
new TagHelperDescriptor("append", "AppendTagHelper", "SomeAssembly", ContentBehavior.Append),
|
|
||||||
new TagHelperDescriptor("prepend", "PrependTagHelper", "SomeAssembly", ContentBehavior.Prepend),
|
|
||||||
new TagHelperDescriptor("replace", "ReplaceTagHelper", "SomeAssembly", ContentBehavior.Replace)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TheoryData TagHelperDescriptorFlowTestData
|
public static TheoryData TagHelperDescriptorFlowTestData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -109,13 +91,6 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
Enumerable.Empty<TagHelperDescriptor>(),
|
Enumerable.Empty<TagHelperDescriptor>(),
|
||||||
false
|
false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ContentBehaviorTagHelpers",
|
|
||||||
"ContentBehaviorTagHelpers",
|
|
||||||
ContentBehaviorTagHelperDescriptors,
|
|
||||||
ContentBehaviorTagHelperDescriptors,
|
|
||||||
false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ComplexTagHelpers",
|
"ComplexTagHelpers",
|
||||||
"ComplexTagHelpers",
|
"ComplexTagHelpers",
|
||||||
|
|
@ -144,7 +119,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
bool designTimeMode)
|
bool designTimeMode)
|
||||||
{
|
{
|
||||||
RunTagHelperTest(
|
RunTagHelperTest(
|
||||||
testName,
|
testName,
|
||||||
baseLineName: baselineName,
|
baseLineName: baselineName,
|
||||||
tagHelperDescriptors: tagHelperDescriptors,
|
tagHelperDescriptors: tagHelperDescriptors,
|
||||||
onResults: (results) =>
|
onResults: (results) =>
|
||||||
|
|
@ -174,7 +149,13 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
generatedAbsoluteIndex: 475,
|
generatedAbsoluteIndex: 475,
|
||||||
generatedLineIndex: 15,
|
generatedLineIndex: 15,
|
||||||
characterOffsetIndex: 14,
|
characterOffsetIndex: 14,
|
||||||
contentLength: 11)
|
contentLength: 11),
|
||||||
|
BuildLineMapping(documentAbsoluteIndex: 57,
|
||||||
|
documentLineIndex: 2,
|
||||||
|
generatedAbsoluteIndex: 958,
|
||||||
|
generatedLineIndex: 34,
|
||||||
|
characterOffsetIndex: 28,
|
||||||
|
contentLength: 4)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -188,21 +169,13 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
generatedAbsoluteIndex: 475,
|
generatedAbsoluteIndex: 475,
|
||||||
generatedLineIndex: 15,
|
generatedLineIndex: 15,
|
||||||
characterOffsetIndex: 14,
|
characterOffsetIndex: 14,
|
||||||
contentLength: 11)
|
contentLength: 11),
|
||||||
}
|
BuildLineMapping(documentAbsoluteIndex: 189,
|
||||||
},
|
documentLineIndex: 6,
|
||||||
{
|
generatedAbsoluteIndex: 1574,
|
||||||
"ContentBehaviorTagHelpers",
|
generatedLineIndex: 44,
|
||||||
"ContentBehaviorTagHelpers.DesignTime",
|
characterOffsetIndex: 40,
|
||||||
ContentBehaviorTagHelperDescriptors,
|
contentLength: 4)
|
||||||
new List<LineMapping>
|
|
||||||
{
|
|
||||||
BuildLineMapping(documentAbsoluteIndex: 14,
|
|
||||||
documentLineIndex: 0,
|
|
||||||
generatedAbsoluteIndex: 495,
|
|
||||||
generatedLineIndex: 15,
|
|
||||||
characterOffsetIndex: 14,
|
|
||||||
contentLength: 11)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -213,17 +186,32 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
{
|
{
|
||||||
BuildLineMapping(14, 0, 479, 15, 14, 11),
|
BuildLineMapping(14, 0, 479, 15, 14, 11),
|
||||||
BuildLineMapping(30, 2, 1, 995, 35, 0, 48),
|
BuildLineMapping(30, 2, 1, 995, 35, 0, 48),
|
||||||
BuildLineMapping(157, 7, 32, 1177, 45, 6, 12),
|
BuildLineMapping(205, 9, 1113, 44, 0, 12),
|
||||||
BuildLineMapping(205, 9, 1260, 50, 0, 12),
|
BuildLineMapping(218, 9, 13, 1209, 50, 12, 27),
|
||||||
BuildLineMapping(218, 9, 13, 1356, 56, 12, 27),
|
BuildLineMapping(346, 12, 1607, 62, 0, 48),
|
||||||
BuildLineMapping(346, 12, 1754, 68, 0, 48),
|
BuildLineMapping(440, 15, 46, 1798, 71, 6, 8),
|
||||||
BuildLineMapping(440, 15, 46, 2004, 78, 6, 8),
|
BuildLineMapping(457, 15, 2121, 79, 63, 4),
|
||||||
BuildLineMapping(501, 16, 31, 2384, 88, 6, 30),
|
BuildLineMapping(501, 16, 31, 2328, 86, 6, 30),
|
||||||
BuildLineMapping(568, 17, 30, 2733, 97, 0, 10),
|
BuildLineMapping(568, 17, 30, 2677, 95, 0, 10),
|
||||||
BuildLineMapping(601, 17, 63, 2815, 103, 0, 8),
|
BuildLineMapping(601, 17, 63, 2759, 101, 0, 8),
|
||||||
BuildLineMapping(632, 17, 94, 2895, 109, 0, 1),
|
BuildLineMapping(632, 17, 94, 2839, 107, 0, 1),
|
||||||
BuildLineMapping(639, 18, 3149, 118, 0, 15),
|
BuildLineMapping(639, 18, 3093, 116, 0, 15),
|
||||||
BuildLineMapping(680, 21, 3234, 124, 0, 1)
|
BuildLineMapping(157, 7, 32, 3242, 123, 6, 12),
|
||||||
|
BuildLineMapping(719, 21, 3325, 128, 0, 12),
|
||||||
|
BuildLineMapping(733, 21, 3423, 134, 14, 21),
|
||||||
|
BuildLineMapping(787, 22, 30, 3680, 142, 28, 7),
|
||||||
|
BuildLineMapping(685, 20, 17, 3836, 148, 19, 23),
|
||||||
|
BuildLineMapping(708, 20, 40, 3859, 148, 42, 7),
|
||||||
|
BuildLineMapping(897, 25, 30, 4101, 155, 28, 30),
|
||||||
|
BuildLineMapping(831, 24, 16, 4280, 161, 19, 8),
|
||||||
|
BuildLineMapping(840, 24, 25, 4288, 161, 27, 23),
|
||||||
|
BuildLineMapping(1026, 28, 4546, 168, 28, 30),
|
||||||
|
BuildLineMapping(964, 27, 16, 4725, 174, 19, 30),
|
||||||
|
BuildLineMapping(1156, 31, 4990, 181, 28, 3),
|
||||||
|
BuildLineMapping(1161, 31, 33, 4993, 181, 31, 27),
|
||||||
|
BuildLineMapping(1189, 31, 61, 5020, 181, 58, 10),
|
||||||
|
BuildLineMapping(1094, 30, 18, 5179, 187, 19, 29),
|
||||||
|
BuildLineMapping(1231, 34, 5279, 192, 0, 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -256,7 +244,6 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
{ "SingleTagHelper", PAndInputTagHelperDescriptors },
|
{ "SingleTagHelper", PAndInputTagHelperDescriptors },
|
||||||
{ "BasicTagHelpers", PAndInputTagHelperDescriptors },
|
{ "BasicTagHelpers", PAndInputTagHelperDescriptors },
|
||||||
{ "BasicTagHelpers.RemoveTagHelper", PAndInputTagHelperDescriptors },
|
{ "BasicTagHelpers.RemoveTagHelper", PAndInputTagHelperDescriptors },
|
||||||
{ "ContentBehaviorTagHelpers", ContentBehaviorTagHelperDescriptors },
|
|
||||||
{ "ComplexTagHelpers", PAndInputTagHelperDescriptors },
|
{ "ComplexTagHelpers", PAndInputTagHelperDescriptors },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -312,7 +299,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
RunTagHelperTest("AddTagHelperDirective",
|
RunTagHelperTest("AddTagHelperDirective",
|
||||||
designTimeMode: true,
|
designTimeMode: true,
|
||||||
tagHelperDescriptors: new[] {
|
tagHelperDescriptors: new[] {
|
||||||
new TagHelperDescriptor("p", "pTagHelper", "SomeAssembly", ContentBehavior.None)
|
new TagHelperDescriptor("p", "pTagHelper", "SomeAssembly")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -328,12 +315,11 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
new TagHelperDescriptor("MyTagHelper",
|
new TagHelperDescriptor("MyTagHelper",
|
||||||
"MyTagHelper",
|
"MyTagHelper",
|
||||||
"SomeAssembly",
|
"SomeAssembly",
|
||||||
ContentBehavior.None,
|
|
||||||
new [] {
|
new [] {
|
||||||
new TagHelperAttributeDescriptor("BoundProperty",
|
new TagHelperAttributeDescriptor("BoundProperty",
|
||||||
propertyInfo)
|
propertyInfo)
|
||||||
}),
|
}),
|
||||||
new TagHelperDescriptor("NestedTagHelper", "NestedTagHelper", "SomeAssembly", ContentBehavior.Modify)
|
new TagHelperDescriptor("NestedTagHelper", "NestedTagHelper", "SomeAssembly")
|
||||||
};
|
};
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
|
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||||
|
using Microsoft.AspNet.Razor.Generator.Compiler.CSharp;
|
||||||
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
|
{
|
||||||
|
public class CSharpTagHelperRenderingUnitTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void CreatesAUniqueIdForSingleTagHelperChunk()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var chunk = CreateTagHelperChunk("div", new[] {
|
||||||
|
new TagHelperDescriptor("div", "DivTagHelper", "FakeAssemblyName")
|
||||||
|
});
|
||||||
|
var codeRenderer = CreateCodeRenderer();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
codeRenderer.RenderTagHelper(chunk);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(1, codeRenderer.GenerateUniqueIdCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void UsesTheSameUniqueIdForTagHelperChunkWithMultipleTagHelpers()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var chunk = CreateTagHelperChunk("div", new[] {
|
||||||
|
new TagHelperDescriptor("div", "DivTagHelper", "FakeAssemblyName"),
|
||||||
|
new TagHelperDescriptor("div", "Div2TagHelper", "FakeAssemblyName")
|
||||||
|
});
|
||||||
|
var codeRenderer = CreateCodeRenderer();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
codeRenderer.RenderTagHelper(chunk);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(1, codeRenderer.GenerateUniqueIdCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void UsesDifferentUniqueIdForMultipleTagHelperChunksForSameTagHelper()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var chunk1 = CreateTagHelperChunk("div", new[] {
|
||||||
|
new TagHelperDescriptor("div", "DivTagHelper", "FakeAssemblyName")
|
||||||
|
});
|
||||||
|
var chunk2 = CreateTagHelperChunk("div", new[] {
|
||||||
|
new TagHelperDescriptor("div", "DivTagHelper", "FakeAssemblyName")
|
||||||
|
});
|
||||||
|
var codeRenderer = CreateCodeRenderer();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
codeRenderer.RenderTagHelper(chunk1);
|
||||||
|
codeRenderer.RenderTagHelper(chunk2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(2, codeRenderer.GenerateUniqueIdCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void UsesDifferentUniqueIdForNestedTagHelperChunksForSameTagHelper()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var parentChunk = CreateTagHelperChunk("div", new[] {
|
||||||
|
new TagHelperDescriptor("div", "DivTagHelper", "FakeAssemblyName")
|
||||||
|
});
|
||||||
|
var childChunk = CreateTagHelperChunk("div", new[] {
|
||||||
|
new TagHelperDescriptor("div", "DivTagHelper", "FakeAssemblyName")
|
||||||
|
});
|
||||||
|
parentChunk.Children.Add(childChunk);
|
||||||
|
var codeRenderer = CreateCodeRenderer();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
codeRenderer.RenderTagHelper(parentChunk);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(2, codeRenderer.GenerateUniqueIdCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void UsesDifferentUniqueIdForMultipleTagHelperChunksForDifferentTagHelpers()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var divChunk = CreateTagHelperChunk("div", new[] {
|
||||||
|
new TagHelperDescriptor("div", "DivTagHelper", "FakeAssemblyName")
|
||||||
|
});
|
||||||
|
var spanChunk = CreateTagHelperChunk("span", new[] {
|
||||||
|
new TagHelperDescriptor("span", "SpanTagHelper", "FakeAssemblyName")
|
||||||
|
});
|
||||||
|
var codeRenderer = CreateCodeRenderer();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
codeRenderer.RenderTagHelper(divChunk);
|
||||||
|
codeRenderer.RenderTagHelper(spanChunk);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(2, codeRenderer.GenerateUniqueIdCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void UsesCorrectUniqueIdForMultipleTagHelperChunksSomeWithSameSameTagHelpersSomeWithDifferentTagHelpers()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var chunk1 = CreateTagHelperChunk("div", new[] {
|
||||||
|
new TagHelperDescriptor("div", "DivTagHelper", "FakeAssemblyName"),
|
||||||
|
new TagHelperDescriptor("div", "Div2TagHelper", "FakeAssemblyName")
|
||||||
|
});
|
||||||
|
var chunk2 = CreateTagHelperChunk("span", new[] {
|
||||||
|
new TagHelperDescriptor("span", "SpanTagHelper", "FakeAssemblyName")
|
||||||
|
});
|
||||||
|
var chunk3 = CreateTagHelperChunk("span", new[] {
|
||||||
|
new TagHelperDescriptor("span", "SpanTagHelper", "FakeAssemblyName"),
|
||||||
|
new TagHelperDescriptor("span", "Span2TagHelper", "FakeAssemblyName")
|
||||||
|
});
|
||||||
|
var codeRenderer = CreateCodeRenderer();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
codeRenderer.RenderTagHelper(chunk1);
|
||||||
|
codeRenderer.RenderTagHelper(chunk2);
|
||||||
|
codeRenderer.RenderTagHelper(chunk3);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(3, codeRenderer.GenerateUniqueIdCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TagHelperChunk CreateTagHelperChunk(string tagName, IEnumerable<TagHelperDescriptor> tagHelperDescriptors)
|
||||||
|
{
|
||||||
|
return new TagHelperChunk
|
||||||
|
{
|
||||||
|
TagName = tagName,
|
||||||
|
Descriptors = tagHelperDescriptors,
|
||||||
|
Children = new List<Chunk>(),
|
||||||
|
Attributes = new Dictionary<string, Chunk>()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TrackingUniqueIdsTagHelperCodeRenderer CreateCodeRenderer()
|
||||||
|
{
|
||||||
|
var writer = new CSharpCodeWriter();
|
||||||
|
var codeBuilderContext = CreateContext();
|
||||||
|
var visitor = new CSharpCodeVisitor(writer, codeBuilderContext);
|
||||||
|
var codeRenderer = new TrackingUniqueIdsTagHelperCodeRenderer(
|
||||||
|
visitor,
|
||||||
|
writer,
|
||||||
|
codeBuilderContext);
|
||||||
|
visitor.TagHelperRenderer = codeRenderer;
|
||||||
|
return codeRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CodeBuilderContext CreateContext()
|
||||||
|
{
|
||||||
|
return new CodeBuilderContext(
|
||||||
|
new CodeGeneratorContext(
|
||||||
|
new RazorEngineHost(new CSharpRazorCodeLanguage()),
|
||||||
|
"MyClass",
|
||||||
|
"MyNamespace",
|
||||||
|
string.Empty,
|
||||||
|
shouldGenerateLinePragmas: true),
|
||||||
|
new ParserErrorSink());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TrackingUniqueIdsTagHelperCodeRenderer : CSharpTagHelperCodeRenderer
|
||||||
|
{
|
||||||
|
public TrackingUniqueIdsTagHelperCodeRenderer(
|
||||||
|
IChunkVisitor bodyVisitor,
|
||||||
|
CSharpCodeWriter writer,
|
||||||
|
CodeBuilderContext context)
|
||||||
|
: base(bodyVisitor, writer, context)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GenerateUniqueId()
|
||||||
|
{
|
||||||
|
GenerateUniqueIdCount++;
|
||||||
|
return "test";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GenerateUniqueIdCount { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#if !ASPNETCORE50
|
#if !ASPNETCORE50
|
||||||
using Microsoft.AspNet.Razor.Generator;
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
using Microsoft.AspNet.Razor.Test.Utils;
|
using Microsoft.AspNet.Razor.Test.Utils;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
@ -23,7 +24,8 @@ namespace Microsoft.AspNet.Razor.Test.Generator.CodeTree
|
||||||
"TestClass",
|
"TestClass",
|
||||||
"TestNamespace",
|
"TestNamespace",
|
||||||
"Foo.cs",
|
"Foo.cs",
|
||||||
shouldGenerateLinePragmas: false);
|
shouldGenerateLinePragmas: false,
|
||||||
|
errorSink: new ParserErrorSink());
|
||||||
codeBuilderContext.CodeTreeBuilder.AddUsingChunk("FakeNamespace1", syntaxTreeNode.Object);
|
codeBuilderContext.CodeTreeBuilder.AddUsingChunk("FakeNamespace1", syntaxTreeNode.Object);
|
||||||
codeBuilderContext.CodeTreeBuilder.AddUsingChunk("FakeNamespace2.SubNamespace", syntaxTreeNode.Object);
|
codeBuilderContext.CodeTreeBuilder.AddUsingChunk("FakeNamespace2.SubNamespace", syntaxTreeNode.Object);
|
||||||
var codeBuilder = language.CreateCodeBuilder(codeBuilderContext);
|
var codeBuilder = language.CreateCodeBuilder(codeBuilderContext);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#if !ASPNETCORE50
|
#if !ASPNETCORE50
|
||||||
using Microsoft.AspNet.Razor.Generator;
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||||
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Moq.Protected;
|
using Moq.Protected;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -34,7 +35,8 @@ namespace Microsoft.AspNet.Razor
|
||||||
"myclass",
|
"myclass",
|
||||||
"myns",
|
"myns",
|
||||||
string.Empty,
|
string.Empty,
|
||||||
shouldGenerateLinePragmas: false);
|
shouldGenerateLinePragmas: false,
|
||||||
|
errorSink: new ParserErrorSink());
|
||||||
var writer = Mock.Of<CodeWriter>();
|
var writer = Mock.Of<CodeWriter>();
|
||||||
return new Mock<ChunkVisitor<CodeWriter>>(writer, codeBuilderContext);
|
return new Mock<ChunkVisitor<CodeWriter>>(writer, codeBuilderContext);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -181,17 +181,13 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
|
|
||||||
if (expectedDesignTimePragmas != null)
|
if (expectedDesignTimePragmas != null)
|
||||||
{
|
{
|
||||||
Assert.True(results.DesignTimeLineMappings != null && results.DesignTimeLineMappings.Count > 0);
|
Assert.True(results.DesignTimeLineMappings != null); // Guard
|
||||||
|
for (var i = 0; i < expectedDesignTimePragmas.Count && i < results.DesignTimeLineMappings.Count; i++)
|
||||||
|
{
|
||||||
|
Assert.Equal(expectedDesignTimePragmas[i], results.DesignTimeLineMappings[i]);
|
||||||
|
}
|
||||||
|
|
||||||
Assert.Equal(expectedDesignTimePragmas.Count, results.DesignTimeLineMappings.Count);
|
Assert.Equal(expectedDesignTimePragmas.Count, results.DesignTimeLineMappings.Count);
|
||||||
|
|
||||||
for (var i = 0; i < expectedDesignTimePragmas.Count; i++)
|
|
||||||
{
|
|
||||||
if (!expectedDesignTimePragmas[i].Equals(results.DesignTimeLineMappings[i]))
|
|
||||||
{
|
|
||||||
Assert.True(false, String.Format("Line mapping {0} is not equivalent.", i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,18 +23,16 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
var checkedPropertyInfo = typeof(TestType).GetProperty("Checked");
|
var checkedPropertyInfo = typeof(TestType).GetProperty("Checked");
|
||||||
var tagHelperDescriptors = new TagHelperDescriptor[]
|
var tagHelperDescriptors = new TagHelperDescriptor[]
|
||||||
{
|
{
|
||||||
new TagHelperDescriptor("p", "PTagHelper", "SomeAssembly", ContentBehavior.None),
|
new TagHelperDescriptor("p", "PTagHelper", "SomeAssembly"),
|
||||||
new TagHelperDescriptor("input",
|
new TagHelperDescriptor("input",
|
||||||
"InputTagHelper",
|
"InputTagHelper",
|
||||||
"SomeAssembly",
|
"SomeAssembly",
|
||||||
ContentBehavior.None,
|
|
||||||
new TagHelperAttributeDescriptor[] {
|
new TagHelperAttributeDescriptor[] {
|
||||||
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
|
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
|
||||||
}),
|
}),
|
||||||
new TagHelperDescriptor("input",
|
new TagHelperDescriptor("input",
|
||||||
"InputTagHelper2",
|
"InputTagHelper2",
|
||||||
"SomeAssembly",
|
"SomeAssembly",
|
||||||
ContentBehavior.None,
|
|
||||||
new TagHelperAttributeDescriptor[] {
|
new TagHelperAttributeDescriptor[] {
|
||||||
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo),
|
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo),
|
||||||
new TagHelperAttributeDescriptor("checked", checkedPropertyInfo)
|
new TagHelperAttributeDescriptor("checked", checkedPropertyInfo)
|
||||||
|
|
@ -65,7 +63,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AttributeCodeGeneratorReplacingCodeBuilder : CSharpCodeBuilder
|
private class AttributeCodeGeneratorReplacingCodeBuilder : TestCSharpCodeBuilder
|
||||||
{
|
{
|
||||||
public AttributeCodeGeneratorReplacingCodeBuilder(CodeBuilderContext context)
|
public AttributeCodeGeneratorReplacingCodeBuilder(CodeBuilderContext context)
|
||||||
: base(context)
|
: base(context)
|
||||||
|
|
@ -88,11 +86,12 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
public override void RenderAttributeValue([NotNull] TagHelperAttributeDescriptor attributeInfo,
|
public override void RenderAttributeValue([NotNull] TagHelperAttributeDescriptor attributeInfo,
|
||||||
[NotNull] CSharpCodeWriter writer,
|
[NotNull] CSharpCodeWriter writer,
|
||||||
[NotNull] CodeBuilderContext context,
|
[NotNull] CodeBuilderContext context,
|
||||||
[NotNull] Action<CSharpCodeWriter> renderAttributeValue)
|
[NotNull] Action<CSharpCodeWriter> renderAttributeValue,
|
||||||
|
bool complexValue)
|
||||||
{
|
{
|
||||||
writer.Write("**From custom attribute code renderer**: ");
|
writer.Write("**From custom attribute code renderer**: ");
|
||||||
|
|
||||||
base.RenderAttributeValue(attributeInfo, writer, context, renderAttributeValue);
|
base.RenderAttributeValue(attributeInfo, writer, context, renderAttributeValue, complexValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,9 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||||
|
using Microsoft.AspNet.Razor.Generator.Compiler.CSharp;
|
||||||
using Microsoft.AspNet.Razor.Parser;
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
using Microsoft.AspNet.Razor.TagHelpers;
|
using Microsoft.AspNet.Razor.TagHelpers;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -78,6 +80,11 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
_tagHelperDescriptors = tagHelperDescriptors;
|
_tagHelperDescriptors = tagHelperDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected internal override CodeBuilder CreateCodeBuilder(CodeBuilderContext context)
|
||||||
|
{
|
||||||
|
return Host.DecorateCodeBuilder(new TestCSharpCodeBuilder(context), context);
|
||||||
|
}
|
||||||
|
|
||||||
protected internal override RazorParser CreateParser(string fileName)
|
protected internal override RazorParser CreateParser(string fileName)
|
||||||
{
|
{
|
||||||
var parser = base.CreateParser(fileName);
|
var parser = base.CreateParser(fileName);
|
||||||
|
|
@ -87,5 +94,37 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
new CustomTagHelperDescriptorResolver(_tagHelperDescriptors));
|
new CustomTagHelperDescriptorResolver(_tagHelperDescriptors));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected class TestCSharpCodeBuilder : CSharpCodeBuilder
|
||||||
|
{
|
||||||
|
public TestCSharpCodeBuilder(CodeBuilderContext context)
|
||||||
|
: base(context)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override CSharpCodeVisitor CreateCSharpCodeVisitor(CSharpCodeWriter writer, CodeBuilderContext context)
|
||||||
|
{
|
||||||
|
var visitor = base.CreateCSharpCodeVisitor(writer, context);
|
||||||
|
visitor.TagHelperRenderer = new NoUniqueIdsTagHelperCodeRenderer(visitor, writer, context);
|
||||||
|
return visitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NoUniqueIdsTagHelperCodeRenderer : CSharpTagHelperCodeRenderer
|
||||||
|
{
|
||||||
|
public NoUniqueIdsTagHelperCodeRenderer(IChunkVisitor bodyVisitor,
|
||||||
|
CSharpCodeWriter writer,
|
||||||
|
CodeBuilderContext context)
|
||||||
|
: base(bodyVisitor, writer, context)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GenerateUniqueId()
|
||||||
|
{
|
||||||
|
return "test";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -247,32 +247,6 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||||
.AsBaseType("$rootnamespace$.MyBase")));
|
.AsBaseType("$rootnamespace$.MyBase")));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void SessionStateDirectiveWorks()
|
|
||||||
{
|
|
||||||
ParseBlockTest("@sessionstate InProc",
|
|
||||||
new DirectiveBlock(
|
|
||||||
Factory.CodeTransition(),
|
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.SessionStateKeyword + " ")
|
|
||||||
.Accepts(AcceptedCharacters.None),
|
|
||||||
Factory.Code("InProc")
|
|
||||||
.AsRazorDirectiveAttribute("sessionstate", "InProc")
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void SessionStateDirectiveParsesInvalidSessionValue()
|
|
||||||
{
|
|
||||||
ParseBlockTest("@sessionstate Blah",
|
|
||||||
new DirectiveBlock(
|
|
||||||
Factory.CodeTransition(),
|
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.SessionStateKeyword + " ")
|
|
||||||
.Accepts(AcceptedCharacters.None),
|
|
||||||
Factory.Code("Blah")
|
|
||||||
.AsRazorDirectiveAttribute("sessionstate", "Blah")
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void FunctionsDirective()
|
public void FunctionsDirective()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||||
var rewritten = rewritingContext.SyntaxTree;
|
var rewritten = rewritingContext.SyntaxTree;
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(0, results.ParserErrors.Count);
|
Assert.Equal(0, results.ParserErrors.Count());
|
||||||
EvaluateParseTree(rewritten,
|
EvaluateParseTree(rewritten,
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupTagBlock(
|
new MarkupTagBlock(
|
||||||
|
|
@ -277,7 +277,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||||
var rewritten = rewritingContext.SyntaxTree;
|
var rewritten = rewritingContext.SyntaxTree;
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(0, results.ParserErrors.Count);
|
Assert.Equal(0, results.ParserErrors.Count());
|
||||||
Assert.Equal(rewritten.Children.Count(), results.Document.Children.Count());
|
Assert.Equal(rewritten.Children.Count(), results.Document.Children.Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,10 @@ namespace Microsoft.AspNet.Razor.Test.Parser
|
||||||
public void VisitThrowsOnNullVisitor()
|
public void VisitThrowsOnNullVisitor()
|
||||||
{
|
{
|
||||||
ParserVisitor target = null;
|
ParserVisitor target = null;
|
||||||
|
var errorSink = new ParserErrorSink();
|
||||||
var results = new ParserResults(new BlockBuilder() { Type = BlockType.Comment }.Build(),
|
var results = new ParserResults(new BlockBuilder() { Type = BlockType.Comment }.Build(),
|
||||||
Enumerable.Empty<TagHelperDescriptor>(),
|
Enumerable.Empty<TagHelperDescriptor>(),
|
||||||
parserErrors: new List<RazorError>());
|
errorSink);
|
||||||
|
|
||||||
Assert.Throws<ArgumentNullException>("self", () => target.Visit(results));
|
Assert.Throws<ArgumentNullException>("self", () => target.Visit(results));
|
||||||
}
|
}
|
||||||
|
|
@ -39,9 +40,10 @@ namespace Microsoft.AspNet.Razor.Test.Parser
|
||||||
// Arrange
|
// Arrange
|
||||||
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
||||||
var root = new BlockBuilder() { Type = BlockType.Comment }.Build();
|
var root = new BlockBuilder() { Type = BlockType.Comment }.Build();
|
||||||
|
var errorSink = new ParserErrorSink();
|
||||||
var results = new ParserResults(root,
|
var results = new ParserResults(root,
|
||||||
Enumerable.Empty<TagHelperDescriptor>(),
|
Enumerable.Empty<TagHelperDescriptor>(),
|
||||||
parserErrors: new List<RazorError>());
|
errorSink);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
targetMock.Object.Visit(results);
|
targetMock.Object.Visit(results);
|
||||||
|
|
@ -56,11 +58,17 @@ namespace Microsoft.AspNet.Razor.Test.Parser
|
||||||
// Arrange
|
// Arrange
|
||||||
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
||||||
var root = new BlockBuilder() { Type = BlockType.Comment }.Build();
|
var root = new BlockBuilder() { Type = BlockType.Comment }.Build();
|
||||||
List<RazorError> errors = new List<RazorError>() {
|
var errorSink = new ParserErrorSink();
|
||||||
|
List<RazorError> errors = new List<RazorError>
|
||||||
|
{
|
||||||
new RazorError("Foo", 1, 0, 1),
|
new RazorError("Foo", 1, 0, 1),
|
||||||
new RazorError("Bar", 2, 0, 2)
|
new RazorError("Bar", 2, 0, 2),
|
||||||
};
|
};
|
||||||
var results = new ParserResults(root, Enumerable.Empty<TagHelperDescriptor>(), errors);
|
foreach (var error in errors)
|
||||||
|
{
|
||||||
|
errorSink.OnError(error);
|
||||||
|
}
|
||||||
|
var results = new ParserResults(root, Enumerable.Empty<TagHelperDescriptor>(), errorSink);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
targetMock.Object.Visit(results);
|
targetMock.Object.Visit(results);
|
||||||
|
|
@ -76,11 +84,10 @@ namespace Microsoft.AspNet.Razor.Test.Parser
|
||||||
// Arrange
|
// Arrange
|
||||||
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
||||||
var root = new BlockBuilder() { Type = BlockType.Comment }.Build();
|
var root = new BlockBuilder() { Type = BlockType.Comment }.Build();
|
||||||
List<RazorError> errors = new List<RazorError>() {
|
var errorSink = new ParserErrorSink();
|
||||||
new RazorError("Foo", 1, 0, 1),
|
errorSink.OnError(new RazorError("Foo", 1, 0, 1));
|
||||||
new RazorError("Bar", 2, 0, 2)
|
errorSink.OnError(new RazorError("Bar", 2, 0, 2));
|
||||||
};
|
var results = new ParserResults(root, Enumerable.Empty<TagHelperDescriptor>(), errorSink);
|
||||||
var results = new ParserResults(root, Enumerable.Empty<TagHelperDescriptor>(), errors);
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
targetMock.Object.Visit(results);
|
targetMock.Object.Visit(results);
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,8 @@ namespace Microsoft.AspNet.Razor.Test
|
||||||
"different-class",
|
"different-class",
|
||||||
"different-ns",
|
"different-ns",
|
||||||
string.Empty,
|
string.Empty,
|
||||||
shouldGenerateLinePragmas: true);
|
shouldGenerateLinePragmas: true,
|
||||||
|
errorSink: new ParserErrorSink());
|
||||||
|
|
||||||
var expected = new CSharpCodeBuilder(codeBuilderContext);
|
var expected = new CSharpCodeBuilder(codeBuilderContext);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -168,8 +168,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
||||||
new ParserErrorSink());
|
new ParserErrorSink());
|
||||||
var document = new MarkupBlock(Factory.Markup("Hello World"));
|
var document = new MarkupBlock(Factory.Markup("Hello World"));
|
||||||
|
|
||||||
// Act & Assert
|
// Act
|
||||||
Assert.DoesNotThrow(() => addOrRemoveTagHelperSpanVisitor.GetDescriptors(document));
|
var descriptors = addOrRemoveTagHelperSpanVisitor.GetDescriptors(document);
|
||||||
|
|
||||||
|
Assert.Empty(descriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestTagHelperDescriptorResolver : ITagHelperDescriptorResolver
|
private class TestTagHelperDescriptorResolver : ITagHelperDescriptorResolver
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
public void TagHelperDescriptorProvider_GetTagHelpersReturnsNothingForUnregisteredTags()
|
public void TagHelperDescriptorProvider_GetTagHelpersReturnsNothingForUnregisteredTags()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly", ContentBehavior.None);
|
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
|
||||||
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly", ContentBehavior.None);
|
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly");
|
||||||
var descriptors = new TagHelperDescriptor[] { divDescriptor, spanDescriptor };
|
var descriptors = new TagHelperDescriptor[] { divDescriptor, spanDescriptor };
|
||||||
var provider = new TagHelperDescriptorProvider(descriptors);
|
var provider = new TagHelperDescriptorProvider(descriptors);
|
||||||
|
|
||||||
|
|
@ -29,9 +29,9 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
public void TagHelperDescriptorProvider_GetTagHelpersDoesNotReturnNonCatchAllTagsForCatchAll()
|
public void TagHelperDescriptorProvider_GetTagHelpersDoesNotReturnNonCatchAllTagsForCatchAll()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly", ContentBehavior.None);
|
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
|
||||||
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly", ContentBehavior.None);
|
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly");
|
||||||
var catchAllDescriptor = new TagHelperDescriptor("*", "foo3", "SomeAssembly", ContentBehavior.None);
|
var catchAllDescriptor = new TagHelperDescriptor("*", "foo3", "SomeAssembly");
|
||||||
var descriptors = new TagHelperDescriptor[] { divDescriptor, spanDescriptor, catchAllDescriptor };
|
var descriptors = new TagHelperDescriptor[] { divDescriptor, spanDescriptor, catchAllDescriptor };
|
||||||
var provider = new TagHelperDescriptorProvider(descriptors);
|
var provider = new TagHelperDescriptorProvider(descriptors);
|
||||||
|
|
||||||
|
|
@ -47,9 +47,9 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
public void TagHelperDescriptorProvider_GetTagHelpersReturnsCatchAllsWithEveryTagName()
|
public void TagHelperDescriptorProvider_GetTagHelpersReturnsCatchAllsWithEveryTagName()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly", ContentBehavior.None);
|
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
|
||||||
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly", ContentBehavior.None);
|
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly");
|
||||||
var catchAllDescriptor = new TagHelperDescriptor("*", "foo3", "SomeAssembly", ContentBehavior.None);
|
var catchAllDescriptor = new TagHelperDescriptor("*", "foo3", "SomeAssembly");
|
||||||
var descriptors = new TagHelperDescriptor[] { divDescriptor, spanDescriptor, catchAllDescriptor };
|
var descriptors = new TagHelperDescriptor[] { divDescriptor, spanDescriptor, catchAllDescriptor };
|
||||||
var provider = new TagHelperDescriptorProvider(descriptors);
|
var provider = new TagHelperDescriptorProvider(descriptors);
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
public void TagHelperDescriptorProvider_DuplicateDescriptorsAreNotPartOfTagHelperDescriptorPool()
|
public void TagHelperDescriptorProvider_DuplicateDescriptorsAreNotPartOfTagHelperDescriptorPool()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly", ContentBehavior.None);
|
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
|
||||||
var descriptors = new TagHelperDescriptor[] { divDescriptor, divDescriptor };
|
var descriptors = new TagHelperDescriptor[] { divDescriptor, divDescriptor };
|
||||||
var provider = new TagHelperDescriptorProvider(descriptors);
|
var provider = new TagHelperDescriptorProvider(descriptors);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,430 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
{
|
{
|
||||||
public class TagHelperParseTreeRewriterTest : CsHtmlMarkupParserTestBase
|
public class TagHelperParseTreeRewriterTest : CsHtmlMarkupParserTestBase
|
||||||
{
|
{
|
||||||
|
public static TheoryData<string, MarkupBlock, RazorError[]> MalformedTagHelperAttributeBlockData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var factory = CreateDefaultSpanFactory();
|
||||||
|
var blockFactory = new BlockFactory(factory);
|
||||||
|
var errorFormatUnclosed = "Found a malformed '{0}' tag helper. Tag helpers must have a start and " +
|
||||||
|
"end tag or be self closing.";
|
||||||
|
var errorFormatNoCloseAngle = "Missing close angle for tag helper '{0}'.";
|
||||||
|
var errorFormatNoCSharp = "The tag helper '{0}' must not have C# in the element's attribute " +
|
||||||
|
"declaration area.";
|
||||||
|
Func<string, Block> createInvalidDoBlock = extraCode =>
|
||||||
|
{
|
||||||
|
return new MarkupBlock(
|
||||||
|
new MarkupBlock(
|
||||||
|
new StatementBlock(
|
||||||
|
factory.CodeTransition(),
|
||||||
|
factory.Code("do {" + extraCode).AsStatement())));
|
||||||
|
};
|
||||||
|
var dateTimeNow = new MarkupBlock(
|
||||||
|
new MarkupBlock(
|
||||||
|
new ExpressionBlock(
|
||||||
|
factory.CodeTransition(),
|
||||||
|
factory.Code("DateTime.Now")
|
||||||
|
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||||
|
.Accepts(AcceptedCharacters.NonWhiteSpace))));
|
||||||
|
|
||||||
|
return new TheoryData<string, MarkupBlock, RazorError[]>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"<p =\"false\"\" ></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>())),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p bar=\"false\"\" <strong>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "bar", factory.Markup("false") }
|
||||||
|
})),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p bar='false <strong>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "bar", new MarkupBlock(factory.Markup("false"), factory.Markup(" <strong>")) }
|
||||||
|
})),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p foo bar<strong>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new MarkupTagHelperBlock("strong"))),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "strong"),
|
||||||
|
absoluteIndex: 10, lineIndex: 0, columnIndex: 10)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class=btn\" bar<strong>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "class", factory.Markup("btn") }
|
||||||
|
})),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class=btn\" bar=\"foo\"<strong>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "class", factory.Markup("btn") }
|
||||||
|
})),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class=\"btn bar=\"foo\"<strong>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar=")) },
|
||||||
|
{ "foo", factory.Markup(string.Empty) }
|
||||||
|
},
|
||||||
|
new MarkupTagHelperBlock("strong"))),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "strong"),
|
||||||
|
absoluteIndex: 23, lineIndex: 0, columnIndex: 23)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class=\"btn bar=\"foo\"></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "class", new MarkupBlock(factory.Markup("btn"), factory.Markup(" bar=")) },
|
||||||
|
})),
|
||||||
|
new RazorError[0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p @DateTime.Now class=\"btn\"></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p")),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCSharp, "p"),
|
||||||
|
absoluteIndex: 3, lineIndex: 0 , columnIndex: 3)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p @DateTime.Now=\"btn\"></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p")),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCSharp, "p"),
|
||||||
|
absoluteIndex: 3, lineIndex: 0 , columnIndex: 3)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class=@DateTime.Now\"></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "class", dateTimeNow }
|
||||||
|
})),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class=\"@do {",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "class", createInvalidDoBlock(string.Empty) }
|
||||||
|
})),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF("do", "}", "{"),
|
||||||
|
absoluteIndex: 11, lineIndex: 0, columnIndex: 11)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p class=\"@do {\"></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
|
{
|
||||||
|
{ "class", createInvalidDoBlock("\"></p>") }
|
||||||
|
})),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF("do", "}", "{"),
|
||||||
|
absoluteIndex: 11, lineIndex: 0, columnIndex: 11),
|
||||||
|
new RazorError(
|
||||||
|
RazorResources.ParseError_Unterminated_String_Literal,
|
||||||
|
absoluteIndex: 15, lineIndex: 0, columnIndex: 15)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p @do { someattribute=\"btn\"></p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p")),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCSharp, "p"),
|
||||||
|
absoluteIndex: 3, lineIndex: 0 , columnIndex: 3),
|
||||||
|
new RazorError(
|
||||||
|
RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF("do", "}", "{"),
|
||||||
|
absoluteIndex: 4, lineIndex: 0, columnIndex: 4),
|
||||||
|
new RazorError(
|
||||||
|
RazorResources.FormatParseError_UnexpectedEndTag("p"),
|
||||||
|
absoluteIndex: 29, lineIndex: 0, columnIndex: 29)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(MalformedTagHelperAttributeBlockData))]
|
||||||
|
public void Rewrite_CreatesErrorForMalformedTagHelpersWithAttributes(
|
||||||
|
string documentContent,
|
||||||
|
MarkupBlock expectedOutput,
|
||||||
|
RazorError[] expectedErrors)
|
||||||
|
{
|
||||||
|
RunParseTreeRewriterTest(documentContent, expectedOutput, expectedErrors, "strong", "p");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TheoryData<string, MarkupBlock, RazorError[]> MalformedTagHelperBlockData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var factory = CreateDefaultSpanFactory();
|
||||||
|
var blockFactory = new BlockFactory(factory);
|
||||||
|
var errorFormatUnclosed = "Found a malformed '{0}' tag helper. Tag helpers must have a start and " +
|
||||||
|
"end tag or be self closing.";
|
||||||
|
var errorFormatNoCloseAngle = "Missing close angle for tag helper '{0}'.";
|
||||||
|
|
||||||
|
return new TheoryData<string, MarkupBlock, RazorError[]>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"<p",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p")),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p></p",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p")),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "p"),
|
||||||
|
absoluteIndex: 3, lineIndex: 0, columnIndex: 3)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<p><strong",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("p",
|
||||||
|
new MarkupTagHelperBlock("strong"))),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "strong"),
|
||||||
|
absoluteIndex: 3, lineIndex: 0, columnIndex: 3),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "strong"),
|
||||||
|
absoluteIndex: 3, lineIndex: 0, columnIndex: 3)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<strong <p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("strong",
|
||||||
|
new MarkupTagHelperBlock("p"))),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "strong"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "strong"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
absoluteIndex: 8, lineIndex: 0, columnIndex: 8)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<strong </strong",
|
||||||
|
new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock("strong")),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "strong"),
|
||||||
|
SourceLocation.Zero),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatNoCloseAngle, "strong"),
|
||||||
|
absoluteIndex: 8, lineIndex: 0, columnIndex: 8)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<<</strong> <<p>",
|
||||||
|
new MarkupBlock(
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
blockFactory.MarkupTagBlock("</strong>"),
|
||||||
|
factory.Markup(" "),
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
new MarkupTagHelperBlock("p")),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "strong"),
|
||||||
|
absoluteIndex: 2, lineIndex: 0, columnIndex: 2),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
absoluteIndex: 13, lineIndex: 0, columnIndex: 13)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<<<strong>> <<>>",
|
||||||
|
new MarkupBlock(
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
new MarkupTagHelperBlock("strong",
|
||||||
|
factory.Markup("> "),
|
||||||
|
blockFactory.MarkupTagBlock("<"),
|
||||||
|
blockFactory.MarkupTagBlock("<>"),
|
||||||
|
factory.Markup(">"))),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "strong"),
|
||||||
|
absoluteIndex: 2, lineIndex: 0, columnIndex: 2)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<str<strong></p></strong>",
|
||||||
|
new MarkupBlock(
|
||||||
|
blockFactory.MarkupTagBlock("<str"),
|
||||||
|
new MarkupTagHelperBlock("strong",
|
||||||
|
blockFactory.MarkupTagBlock("</p>"))),
|
||||||
|
new []
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, errorFormatUnclosed, "p"),
|
||||||
|
absoluteIndex: 12, lineIndex: 0, columnIndex: 12)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(MalformedTagHelperBlockData))]
|
||||||
|
public void Rewrite_CreatesErrorForMalformedTagHelper(
|
||||||
|
string documentContent,
|
||||||
|
MarkupBlock expectedOutput,
|
||||||
|
RazorError[] expectedErrors)
|
||||||
|
{
|
||||||
|
RunParseTreeRewriterTest(documentContent, expectedOutput, expectedErrors, "strong", "p");
|
||||||
|
}
|
||||||
|
|
||||||
public static TheoryData CodeTagHelperAttributesData
|
public static TheoryData CodeTagHelperAttributesData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -94,7 +518,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
// Arrange
|
// Arrange
|
||||||
var descriptors = new TagHelperDescriptor[]
|
var descriptors = new TagHelperDescriptor[]
|
||||||
{
|
{
|
||||||
new TagHelperDescriptor("person", "PersonTagHelper", "personAssembly", ContentBehavior.None,
|
new TagHelperDescriptor("person", "PersonTagHelper", "personAssembly",
|
||||||
attributes: new[]
|
attributes: new[]
|
||||||
{
|
{
|
||||||
new TagHelperAttributeDescriptor("age", "Age", typeof(int).FullName),
|
new TagHelperAttributeDescriptor("age", "Age", typeof(int).FullName),
|
||||||
|
|
@ -105,9 +529,9 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
var providerContext = new TagHelperDescriptorProvider(descriptors);
|
var providerContext = new TagHelperDescriptorProvider(descriptors);
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
EvaluateData(providerContext,
|
EvaluateData(providerContext,
|
||||||
documentContent,
|
documentContent,
|
||||||
expectedOutput,
|
expectedOutput,
|
||||||
expectedErrors: Enumerable.Empty<RazorError>());
|
expectedErrors: Enumerable.Empty<RazorError>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,8 +541,8 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
{
|
{
|
||||||
var factory = CreateDefaultSpanFactory();
|
var factory = CreateDefaultSpanFactory();
|
||||||
var blockFactory = new BlockFactory(factory);
|
var blockFactory = new BlockFactory(factory);
|
||||||
var errorFormat = "Found a malformed '{0}' tag helper. Tag helpers must have a start and end tag or " +
|
var malformedErrorFormat = "Found a malformed '{0}' tag helper. Tag helpers must have a start and " +
|
||||||
"be self closing.";
|
"end tag or be self closing.";
|
||||||
var dateTimeNow = new MarkupBlock(
|
var dateTimeNow = new MarkupBlock(
|
||||||
new ExpressionBlock(
|
new ExpressionBlock(
|
||||||
factory.CodeTransition(),
|
factory.CodeTransition(),
|
||||||
|
|
@ -130,16 +554,23 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
"<p class=foo dynamic=@DateTime.Now style=color:red;><strong></p></strong>",
|
"<p class=foo dynamic=@DateTime.Now style=color:red;><strong></p></strong>",
|
||||||
new MarkupBlock(
|
new MarkupBlock(
|
||||||
new MarkupTagHelperBlock("p",
|
new MarkupTagHelperBlock("p",
|
||||||
new Dictionary<string, SyntaxTreeNode>
|
new Dictionary<string, SyntaxTreeNode>
|
||||||
{
|
{
|
||||||
{ "class", factory.Markup("foo") },
|
{ "class", factory.Markup("foo") },
|
||||||
{ "dynamic", new MarkupBlock(dateTimeNow) },
|
{ "dynamic", new MarkupBlock(dateTimeNow) },
|
||||||
{ "style", factory.Markup("color:red;") }
|
{ "style", factory.Markup("color:red;") }
|
||||||
},
|
},
|
||||||
new MarkupTagHelperBlock("strong",
|
new MarkupTagHelperBlock("strong")),
|
||||||
blockFactory.MarkupTagBlock("</p>")))),
|
blockFactory.MarkupTagBlock("</strong>")),
|
||||||
new RazorError(string.Format(CultureInfo.InvariantCulture, errorFormat, "p"),
|
new RazorError[]
|
||||||
SourceLocation.Zero)
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, malformedErrorFormat, "strong"),
|
||||||
|
absoluteIndex: 52, lineIndex: 0, columnIndex: 52),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, malformedErrorFormat, "strong"),
|
||||||
|
absoluteIndex: 64, lineIndex: 0, columnIndex: 64)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
yield return new object[] {
|
yield return new object[] {
|
||||||
"<div><p>Hello <strong>World</strong></div>",
|
"<div><p>Hello <strong>World</strong></div>",
|
||||||
|
|
@ -150,8 +581,12 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
new MarkupTagHelperBlock("strong",
|
new MarkupTagHelperBlock("strong",
|
||||||
factory.Markup("World")),
|
factory.Markup("World")),
|
||||||
blockFactory.MarkupTagBlock("</div>"))),
|
blockFactory.MarkupTagBlock("</div>"))),
|
||||||
new RazorError(string.Format(CultureInfo.InvariantCulture, errorFormat, "p"),
|
new RazorError[]
|
||||||
absoluteIndex: 5, lineIndex: 0, columnIndex: 5)
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, malformedErrorFormat, "p"),
|
||||||
|
absoluteIndex: 5, lineIndex: 0, columnIndex: 5)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
yield return new object[] {
|
yield return new object[] {
|
||||||
"<div><p>Hello <strong>World</div>",
|
"<div><p>Hello <strong>World</div>",
|
||||||
|
|
@ -162,8 +597,15 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
new MarkupTagHelperBlock("strong",
|
new MarkupTagHelperBlock("strong",
|
||||||
factory.Markup("World"),
|
factory.Markup("World"),
|
||||||
blockFactory.MarkupTagBlock("</div>")))),
|
blockFactory.MarkupTagBlock("</div>")))),
|
||||||
new RazorError(string.Format(CultureInfo.InvariantCulture, errorFormat, "strong"),
|
new RazorError[]
|
||||||
absoluteIndex: 14, lineIndex: 0, columnIndex: 14)
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, malformedErrorFormat, "p"),
|
||||||
|
absoluteIndex: 5, lineIndex: 0, columnIndex: 5),
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, malformedErrorFormat, "strong"),
|
||||||
|
absoluteIndex: 14, lineIndex: 0, columnIndex: 14)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
yield return new object[] {
|
yield return new object[] {
|
||||||
"<p class=\"foo\">Hello <p style=\"color:red;\">World</p>",
|
"<p class=\"foo\">Hello <p style=\"color:red;\">World</p>",
|
||||||
|
|
@ -180,8 +622,12 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
{ "style", factory.Markup("color:red;") }
|
{ "style", factory.Markup("color:red;") }
|
||||||
},
|
},
|
||||||
factory.Markup("World")))),
|
factory.Markup("World")))),
|
||||||
new RazorError(string.Format(CultureInfo.InvariantCulture, errorFormat, "p"),
|
new RazorError[]
|
||||||
SourceLocation.Zero)
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(CultureInfo.InvariantCulture, malformedErrorFormat, "p"),
|
||||||
|
SourceLocation.Zero)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -191,9 +637,9 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
public void TagHelperParseTreeRewriter_CreatesErrorForIncompleteTagHelper(
|
public void TagHelperParseTreeRewriter_CreatesErrorForIncompleteTagHelper(
|
||||||
string documentContent,
|
string documentContent,
|
||||||
MarkupBlock expectedOutput,
|
MarkupBlock expectedOutput,
|
||||||
RazorError expectedError)
|
RazorError[] expectedErrors)
|
||||||
{
|
{
|
||||||
RunParseTreeRewriterTest(documentContent, expectedOutput, new[] { expectedError }, "strong", "p");
|
RunParseTreeRewriterTest(documentContent, expectedOutput, expectedErrors, "strong", "p");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TheoryData<string, MarkupBlock> InvalidHtmlBlockData
|
public static TheoryData<string, MarkupBlock> InvalidHtmlBlockData
|
||||||
|
|
@ -1268,7 +1714,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
foreach (var tagName in tagNames)
|
foreach (var tagName in tagNames)
|
||||||
{
|
{
|
||||||
descriptors.Add(
|
descriptors.Add(
|
||||||
new TagHelperDescriptor(tagName, tagName + "taghelper", "SomeAssembly", ContentBehavior.None));
|
new TagHelperDescriptor(tagName, tagName + "taghelper", "SomeAssembly"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TagHelperDescriptorProvider(descriptors);
|
return new TagHelperDescriptorProvider(descriptors);
|
||||||
|
|
@ -1292,8 +1738,10 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||||
var rewritingContext = new RewritingContext(results.Document, errorSink);
|
var rewritingContext = new RewritingContext(results.Document, errorSink);
|
||||||
new TagHelperParseTreeRewriter(provider).Rewrite(rewritingContext);
|
new TagHelperParseTreeRewriter(provider).Rewrite(rewritingContext);
|
||||||
var rewritten = rewritingContext.SyntaxTree;
|
var rewritten = rewritingContext.SyntaxTree;
|
||||||
|
var actualErrors = errorSink.Errors.OrderBy(error => error.Location.AbsoluteIndex)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
EvaluateRazorErrors(errorSink.Errors.ToList(), expectedErrors.ToList());
|
EvaluateRazorErrors(actualErrors, expectedErrors.ToList());
|
||||||
EvaluateParseTree(rewritten, expectedOutput);
|
EvaluateParseTree(rewritten, expectedOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@ namespace TestOutput
|
||||||
public class BasicTagHelpers
|
public class BasicTagHelpers
|
||||||
{
|
{
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#pragma warning disable 0414
|
||||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||||
|
#pragma warning restore 0414
|
||||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||||
|
|
@ -25,57 +27,117 @@ namespace TestOutput
|
||||||
Instrumentation.BeginContext(27, 49, true);
|
Instrumentation.BeginContext(27, 49, true);
|
||||||
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
|
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper.Type = **From custom attribute code renderer**: "text";
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper.Type = **From custom attribute code renderer**: "checkbox";
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
|
#line 7 "BasicTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = **From custom attribute code renderer**: true;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
|
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
Instrumentation.BeginContext(99, 10, true);
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
WriteLiteral("\r\n ");
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
Instrumentation.EndContext();
|
{
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
}
|
||||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
{
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
}
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
else
|
||||||
Instrumentation.BeginContext(116, 10, true);
|
{
|
||||||
WriteLiteral("\r\n ");
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
Instrumentation.EndContext();
|
}
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
|
||||||
__InputTagHelper.Type = **From custom attribute code renderer**: "text";
|
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
|
||||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
|
||||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
|
||||||
Instrumentation.BeginContext(147, 10, true);
|
|
||||||
WriteLiteral("\r\n ");
|
|
||||||
Instrumentation.EndContext();
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
|
||||||
__InputTagHelper.Type = **From custom attribute code renderer**: "checkbox";
|
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
|
||||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
|
||||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
|
||||||
__InputTagHelper2.Checked = **From custom attribute code renderer**: true;
|
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
|
||||||
Instrumentation.BeginContext(196, 6, true);
|
|
||||||
WriteLiteral("\r\n ");
|
|
||||||
Instrumentation.EndContext();
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
Instrumentation.BeginContext(206, 8, true);
|
Instrumentation.BeginContext(206, 8, true);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ namespace TestOutput
|
||||||
#pragma warning disable 1998
|
#pragma warning disable 1998
|
||||||
public override async Task ExecuteAsync()
|
public override async Task ExecuteAsync()
|
||||||
{
|
{
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
__InputTagHelper.Type = "text";
|
__InputTagHelper.Type = "text";
|
||||||
|
|
@ -42,7 +41,12 @@ namespace TestOutput
|
||||||
__InputTagHelper.Type = "checkbox";
|
__InputTagHelper.Type = "checkbox";
|
||||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
|
#line 7 "BasicTagHelpers.cshtml"
|
||||||
__InputTagHelper2.Checked = true;
|
__InputTagHelper2.Checked = true;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
}
|
}
|
||||||
#pragma warning restore 1998
|
#pragma warning restore 1998
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,9 @@ namespace TestOutput
|
||||||
public class BasicTagHelpers
|
public class BasicTagHelpers
|
||||||
{
|
{
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#pragma warning disable 0414
|
||||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||||
|
#pragma warning restore 0414
|
||||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||||
|
|
@ -26,57 +28,117 @@ namespace TestOutput
|
||||||
Instrumentation.BeginContext(27, 49, true);
|
Instrumentation.BeginContext(27, 49, true);
|
||||||
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
|
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper.Type = "text";
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper.Type = "checkbox";
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
|
#line 7 "BasicTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = true;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
|
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
Instrumentation.BeginContext(99, 10, true);
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
WriteLiteral("\r\n ");
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
Instrumentation.EndContext();
|
{
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
}
|
||||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
{
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
}
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
else
|
||||||
Instrumentation.BeginContext(116, 10, true);
|
{
|
||||||
WriteLiteral("\r\n ");
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
Instrumentation.EndContext();
|
}
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
|
||||||
__InputTagHelper.Type = "text";
|
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
|
||||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
|
||||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
|
||||||
Instrumentation.BeginContext(147, 10, true);
|
|
||||||
WriteLiteral("\r\n ");
|
|
||||||
Instrumentation.EndContext();
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
|
||||||
__InputTagHelper.Type = "checkbox";
|
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
|
||||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
|
||||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
|
||||||
__InputTagHelper2.Checked = true;
|
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
|
||||||
Instrumentation.BeginContext(196, 6, true);
|
|
||||||
WriteLiteral("\r\n ");
|
|
||||||
Instrumentation.EndContext();
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
Instrumentation.BeginContext(206, 8, true);
|
Instrumentation.BeginContext(206, 8, true);
|
||||||
|
|
|
||||||
|
|
@ -41,12 +41,6 @@ if (true)
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
|
||||||
#line 8 "ComplexTagHelpers.cshtml"
|
|
||||||
__o = DateTime.Now;
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
#line 10 "ComplexTagHelpers.cshtml"
|
#line 10 "ComplexTagHelpers.cshtml"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -60,11 +54,11 @@ __o = DateTime.Now;
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
__InputTagHelper.Type = "text";
|
__InputTagHelper.Type = "text";
|
||||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
#line 13 "ComplexTagHelpers.cshtml"
|
#line 13 "ComplexTagHelpers.cshtml"
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -73,7 +67,6 @@ __o = DateTime.Now;
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
#line 16 "ComplexTagHelpers.cshtml"
|
#line 16 "ComplexTagHelpers.cshtml"
|
||||||
__o = checkbox;
|
__o = checkbox;
|
||||||
|
|
@ -83,7 +76,12 @@ __o = checkbox;
|
||||||
__InputTagHelper.Type = string.Empty;
|
__InputTagHelper.Type = string.Empty;
|
||||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
__InputTagHelper2.Checked = true;
|
#line 16 "ComplexTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = true;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
#line 17 "ComplexTagHelpers.cshtml"
|
#line 17 "ComplexTagHelpers.cshtml"
|
||||||
__o = true ? "checkbox" : "anything";
|
__o = true ? "checkbox" : "anything";
|
||||||
|
|
@ -121,7 +119,77 @@ if(true) {
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
#line 8 "ComplexTagHelpers.cshtml"
|
||||||
|
__o = DateTime.Now;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
#line 22 "ComplexTagHelpers.cshtml"
|
#line 22 "ComplexTagHelpers.cshtml"
|
||||||
|
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
|
||||||
|
#line 22 "ComplexTagHelpers.cshtml"
|
||||||
|
var @object = false;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
#line 23 "ComplexTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = @object;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
#line 21 "ComplexTagHelpers.cshtml"
|
||||||
|
__PTagHelper.Age = DateTimeOffset.Now.Year - 1970;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
#line 26 "ComplexTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = DateTimeOffset.Now.Year > 2014;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
#line 25 "ComplexTagHelpers.cshtml"
|
||||||
|
__PTagHelper.Age = -1970 + DateTimeOffset.Now.Year;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
#line 29 "ComplexTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = DateTimeOffset.Now.Year > 2014;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
#line 28 "ComplexTagHelpers.cshtml"
|
||||||
|
__PTagHelper.Age = DateTimeOffset.Now.Year - 1970;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
#line 32 "ComplexTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = DateTimeOffset.Now.Year > 2014 ;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
#line 31 "ComplexTagHelpers.cshtml"
|
||||||
|
__PTagHelper.Age = "My age is this long.".Length;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#line 35 "ComplexTagHelpers.cshtml"
|
||||||
}
|
}
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#pragma checksum "ComplexTagHelpers.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "cce31144cd1c3c35d241b49e41c4fc04ff044565"
|
#pragma checksum "ComplexTagHelpers.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "7158abc69d261099393d49d82670ec64a94d9770"
|
||||||
namespace TestOutput
|
namespace TestOutput
|
||||||
{
|
{
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
|
@ -8,7 +8,9 @@ namespace TestOutput
|
||||||
public class ComplexTagHelpers
|
public class ComplexTagHelpers
|
||||||
{
|
{
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#pragma warning disable 0414
|
||||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||||
|
#pragma warning restore 0414
|
||||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||||
|
|
@ -38,23 +40,8 @@ namespace TestOutput
|
||||||
Instrumentation.BeginContext(78, 55, true);
|
Instrumentation.BeginContext(78, 55, true);
|
||||||
WriteLiteral(" <div class=\"randomNonTagHelperAttribute\">\r\n ");
|
WriteLiteral(" <div class=\"randomNonTagHelperAttribute\">\r\n ");
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
WriteLiteral("\r\n <h1>Set Time:</h1>\r\n");
|
||||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
|
||||||
StartWritingScope();
|
|
||||||
WriteLiteral("Current Time: ");
|
|
||||||
#line 8 "ComplexTagHelpers.cshtml"
|
|
||||||
Write(DateTime.Now);
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
__tagHelperStringValueBuffer = EndWritingScope();
|
|
||||||
__tagHelperExecutionContext.AddHtmlAttribute("time", __tagHelperStringValueBuffer.ToString());
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
|
||||||
Instrumentation.BeginContext(171, 34, true);
|
|
||||||
WriteLiteral("\r\n <h1>Set Time:</h1>\r\n");
|
|
||||||
Instrumentation.EndContext();
|
|
||||||
#line 10 "ComplexTagHelpers.cshtml"
|
#line 10 "ComplexTagHelpers.cshtml"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -68,36 +55,62 @@ Write(DateTime.Now);
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
Instrumentation.BeginContext(245, 16, true);
|
WriteLiteral(" ");
|
||||||
WriteLiteral(" ");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
Instrumentation.EndContext();
|
WriteLiteral("New Time: ");
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
}
|
||||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
, StartWritingScope, EndWritingScope);
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
Instrumentation.BeginContext(264, 10, true);
|
__InputTagHelper.Type = "text";
|
||||||
WriteLiteral("New Time: ");
|
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
||||||
Instrumentation.EndContext();
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
__tagHelperExecutionContext.AddHtmlAttribute("value", "");
|
||||||
__InputTagHelper.Type = "text";
|
__tagHelperExecutionContext.AddHtmlAttribute("placeholder", "Enter in a new time...");
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
__tagHelperExecutionContext.AddHtmlAttribute("value", "");
|
{
|
||||||
__tagHelperExecutionContext.AddHtmlAttribute("placeholder", "Enter in a new time...");
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
}
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
{
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
}
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
else
|
||||||
Instrumentation.BeginContext(344, 2, true);
|
{
|
||||||
WriteLiteral("\r\n");
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
Instrumentation.EndContext();
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n");
|
||||||
#line 13 "ComplexTagHelpers.cshtml"
|
#line 13 "ComplexTagHelpers.cshtml"
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -106,117 +119,475 @@ Write(DateTime.Now);
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
Instrumentation.BeginContext(394, 16, true);
|
WriteLiteral(" ");
|
||||||
WriteLiteral(" ");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
Instrumentation.EndContext();
|
WriteLiteral("Current Time: ");
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
}
|
||||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
, StartWritingScope, EndWritingScope);
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
Instrumentation.BeginContext(413, 14, true);
|
StartWritingScope();
|
||||||
WriteLiteral("Current Time: ");
|
|
||||||
Instrumentation.EndContext();
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
|
||||||
StartWritingScope();
|
|
||||||
#line 16 "ComplexTagHelpers.cshtml"
|
#line 16 "ComplexTagHelpers.cshtml"
|
||||||
Write(checkbox);
|
Write(checkbox);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
__tagHelperStringValueBuffer = EndWritingScope();
|
__tagHelperStringValueBuffer = EndWritingScope();
|
||||||
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
||||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
__InputTagHelper2.Checked = true;
|
#line 16 "ComplexTagHelpers.cshtml"
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
__InputTagHelper2.Checked = true;
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
#line default
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
#line hidden
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
Instrumentation.BeginContext(468, 18, true);
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
WriteLiteral("\r\n ");
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
Instrumentation.EndContext();
|
{
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
}
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
StartWritingScope();
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
StartWritingScope();
|
||||||
#line 17 "ComplexTagHelpers.cshtml"
|
#line 17 "ComplexTagHelpers.cshtml"
|
||||||
Write(true ? "checkbox" : "anything");
|
Write(true ? "checkbox" : "anything");
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
__tagHelperStringValueBuffer = EndWritingScope();
|
__tagHelperStringValueBuffer = EndWritingScope();
|
||||||
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
||||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
Instrumentation.BeginContext(536, 18, true);
|
{
|
||||||
WriteLiteral("\r\n ");
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
Instrumentation.EndContext();
|
}
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
{
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
StartWritingScope();
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
StartWritingScope();
|
||||||
#line 18 "ComplexTagHelpers.cshtml"
|
#line 18 "ComplexTagHelpers.cshtml"
|
||||||
if(true) {
|
if(true) {
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
WriteLiteral(" checkbox ");
|
WriteLiteral(" checkbox ");
|
||||||
#line 18 "ComplexTagHelpers.cshtml"
|
#line 18 "ComplexTagHelpers.cshtml"
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
WriteLiteral(" anything ");
|
WriteLiteral(" anything ");
|
||||||
#line 18 "ComplexTagHelpers.cshtml"
|
#line 18 "ComplexTagHelpers.cshtml"
|
||||||
}
|
}
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
__tagHelperStringValueBuffer = EndWritingScope();
|
__tagHelperStringValueBuffer = EndWritingScope();
|
||||||
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
||||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
Instrumentation.BeginContext(637, 2, true);
|
{
|
||||||
WriteLiteral("\r\n");
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
Instrumentation.EndContext();
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n");
|
||||||
#line 19 "ComplexTagHelpers.cshtml"
|
#line 19 "ComplexTagHelpers.cshtml"
|
||||||
}
|
}
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
Instrumentation.BeginContext(654, 8, true);
|
WriteLiteral(" ");
|
||||||
WriteLiteral(" ");
|
}
|
||||||
Instrumentation.EndContext();
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
|
StartWritingScope();
|
||||||
|
WriteLiteral("Current Time: ");
|
||||||
|
#line 8 "ComplexTagHelpers.cshtml"
|
||||||
|
Write(DateTime.Now);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperStringValueBuffer = EndWritingScope();
|
||||||
|
__tagHelperExecutionContext.AddHtmlAttribute("time", __tagHelperStringValueBuffer.ToString());
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
Instrumentation.BeginContext(666, 14, true);
|
Instrumentation.BeginContext(666, 10, true);
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
Instrumentation.EndContext();
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
|
WriteLiteral("\r\n");
|
||||||
|
#line 22 "ComplexTagHelpers.cshtml"
|
||||||
|
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
|
||||||
|
#line 22 "ComplexTagHelpers.cshtml"
|
||||||
|
var @object = false;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
|
#line 23 "ComplexTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = @object;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
|
#line 21 "ComplexTagHelpers.cshtml"
|
||||||
|
__PTagHelper.Age = DateTimeOffset.Now.Year - 1970;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
Instrumentation.BeginContext(813, 10, true);
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
Instrumentation.EndContext();
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
|
#line 26 "ComplexTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = DateTimeOffset.Now.Year > 2014;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
|
#line 25 "ComplexTagHelpers.cshtml"
|
||||||
|
__PTagHelper.Age = -1970 + DateTimeOffset.Now.Year;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
Instrumentation.BeginContext(946, 10, true);
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
Instrumentation.EndContext();
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
|
#line 29 "ComplexTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = DateTimeOffset.Now.Year > 2014;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
|
#line 28 "ComplexTagHelpers.cshtml"
|
||||||
|
__PTagHelper.Age = DateTimeOffset.Now.Year - 1970;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
Instrumentation.BeginContext(1074, 10, true);
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
Instrumentation.EndContext();
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||||
|
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||||
|
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||||
|
#line 32 "ComplexTagHelpers.cshtml"
|
||||||
|
__InputTagHelper2.Checked = DateTimeOffset.Now.Year > 2014 ;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
|
#line 31 "ComplexTagHelpers.cshtml"
|
||||||
|
__PTagHelper.Age = "My age is this long.".Length;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
Instrumentation.BeginContext(1217, 14, true);
|
||||||
WriteLiteral("\r\n </div>\r\n");
|
WriteLiteral("\r\n </div>\r\n");
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
#line 22 "ComplexTagHelpers.cshtml"
|
#line 35 "ComplexTagHelpers.cshtml"
|
||||||
}
|
}
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
|
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
namespace TestOutput
|
|
||||||
{
|
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
public class ContentBehaviorTagHelpers
|
|
||||||
{
|
|
||||||
private static object @__o;
|
|
||||||
private void @__RazorDesignTimeHelpers__()
|
|
||||||
{
|
|
||||||
#pragma warning disable 219
|
|
||||||
string __tagHelperDirectiveSyntaxHelper = null;
|
|
||||||
__tagHelperDirectiveSyntaxHelper =
|
|
||||||
#line 1 "ContentBehaviorTagHelpers.cshtml"
|
|
||||||
"something"
|
|
||||||
|
|
||||||
#line default
|
|
||||||
#line hidden
|
|
||||||
;
|
|
||||||
#pragma warning restore 219
|
|
||||||
}
|
|
||||||
#line hidden
|
|
||||||
private ModifyTagHelper __ModifyTagHelper = null;
|
|
||||||
private NoneTagHelper __NoneTagHelper = null;
|
|
||||||
private AppendTagHelper __AppendTagHelper = null;
|
|
||||||
private PrependTagHelper __PrependTagHelper = null;
|
|
||||||
private ReplaceTagHelper __ReplaceTagHelper = null;
|
|
||||||
#line hidden
|
|
||||||
public ContentBehaviorTagHelpers()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning disable 1998
|
|
||||||
public override async Task ExecuteAsync()
|
|
||||||
{
|
|
||||||
__ModifyTagHelper = CreateTagHelper<ModifyTagHelper>();
|
|
||||||
__NoneTagHelper = CreateTagHelper<NoneTagHelper>();
|
|
||||||
__AppendTagHelper = CreateTagHelper<AppendTagHelper>();
|
|
||||||
__PrependTagHelper = CreateTagHelper<PrependTagHelper>();
|
|
||||||
__ReplaceTagHelper = CreateTagHelper<ReplaceTagHelper>();
|
|
||||||
}
|
|
||||||
#pragma warning restore 1998
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
#pragma checksum "ContentBehaviorTagHelpers.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "5aeeb0a2b5283b353efaff2cd2fb0c739020b899"
|
|
||||||
namespace TestOutput
|
|
||||||
{
|
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
public class ContentBehaviorTagHelpers
|
|
||||||
{
|
|
||||||
#line hidden
|
|
||||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
|
||||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
|
||||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
|
||||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
|
||||||
private ModifyTagHelper __ModifyTagHelper = null;
|
|
||||||
private NoneTagHelper __NoneTagHelper = null;
|
|
||||||
private AppendTagHelper __AppendTagHelper = null;
|
|
||||||
private PrependTagHelper __PrependTagHelper = null;
|
|
||||||
private ReplaceTagHelper __ReplaceTagHelper = null;
|
|
||||||
#line hidden
|
|
||||||
public ContentBehaviorTagHelpers()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning disable 1998
|
|
||||||
public override async Task ExecuteAsync()
|
|
||||||
{
|
|
||||||
Instrumentation.BeginContext(27, 2, true);
|
|
||||||
WriteLiteral("\r\n");
|
|
||||||
Instrumentation.EndContext();
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("modify");
|
|
||||||
__ModifyTagHelper = CreateTagHelper<ModifyTagHelper>();
|
|
||||||
__tagHelperExecutionContext.Add(__ModifyTagHelper);
|
|
||||||
StartWritingScope();
|
|
||||||
WriteLiteral("\r\n ");
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("none");
|
|
||||||
__NoneTagHelper = CreateTagHelper<NoneTagHelper>();
|
|
||||||
__tagHelperExecutionContext.Add(__NoneTagHelper);
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
|
||||||
WriteLiteral("\r\n ");
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("append");
|
|
||||||
__AppendTagHelper = CreateTagHelper<AppendTagHelper>();
|
|
||||||
__tagHelperExecutionContext.Add(__AppendTagHelper);
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
|
||||||
WriteLiteral("\r\n ");
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("prepend");
|
|
||||||
__PrependTagHelper = CreateTagHelper<PrependTagHelper>();
|
|
||||||
__tagHelperExecutionContext.Add(__PrependTagHelper);
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
|
||||||
WriteLiteral("\r\n ");
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("replace");
|
|
||||||
__ReplaceTagHelper = CreateTagHelper<ReplaceTagHelper>();
|
|
||||||
__tagHelperExecutionContext.Add(__ReplaceTagHelper);
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
|
||||||
WriteLiteral("\r\n ");
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
|
||||||
WriteLiteral("\r\n ");
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
|
||||||
WriteLiteral("\r\n ");
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
|
||||||
WriteLiteral("\r\n");
|
|
||||||
__tagHelperStringValueBuffer = EndWritingScope();
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext, __tagHelperStringValueBuffer).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
|
||||||
}
|
|
||||||
#pragma warning restore 1998
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -31,7 +31,11 @@ namespace TestOutput
|
||||||
public override async Task ExecuteAsync()
|
public override async Task ExecuteAsync()
|
||||||
{
|
{
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
__PTagHelper.Age = 1337;
|
#line 3 "SingleTagHelper.cshtml"
|
||||||
|
__PTagHelper.Age = 1337;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
}
|
}
|
||||||
#pragma warning restore 1998
|
#pragma warning restore 1998
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,9 @@ namespace TestOutput
|
||||||
public class SingleTagHelper
|
public class SingleTagHelper
|
||||||
{
|
{
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#pragma warning disable 0414
|
||||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||||
|
#pragma warning restore 0414
|
||||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||||
|
|
@ -24,17 +26,35 @@ namespace TestOutput
|
||||||
Instrumentation.BeginContext(27, 2, true);
|
Instrumentation.BeginContext(27, 2, true);
|
||||||
WriteLiteral("\r\n");
|
WriteLiteral("\r\n");
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||||
|
WriteLiteral("Body of Tag");
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||||
__PTagHelper.Age = 1337;
|
#line 3 "SingleTagHelper.cshtml"
|
||||||
|
__PTagHelper.Age = 1337;
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
|
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
|
||||||
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
|
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
Instrumentation.BeginContext(63, 11, true);
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
WriteLiteral("Body of Tag");
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
Instrumentation.EndContext();
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,40 @@ MyHelper(string val)
|
||||||
Instrumentation.BeginContext(62, 19, true);
|
Instrumentation.BeginContext(62, 19, true);
|
||||||
WriteLiteralTo(__razor_helper_writer, " <div>\r\n ");
|
WriteLiteralTo(__razor_helper_writer, " <div>\r\n ");
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("mytaghelper");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("mytaghelper", "test", async() => {
|
||||||
|
WriteLiteral("\r\n In None ContentBehavior.\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("nestedtaghelper", "test", async() => {
|
||||||
|
WriteLiteral("Some buffered values with a value of ");
|
||||||
|
#line 8 "TagHelpersInHelper.cshtml"
|
||||||
|
Write(val);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__NestedTagHelper = CreateTagHelper<NestedTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__NestedTagHelper);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
__MyTagHelper = CreateTagHelper<MyTagHelper>();
|
__MyTagHelper = CreateTagHelper<MyTagHelper>();
|
||||||
__tagHelperExecutionContext.Add(__MyTagHelper);
|
__tagHelperExecutionContext.Add(__MyTagHelper);
|
||||||
StartWritingScope();
|
StartWritingScope();
|
||||||
|
|
@ -48,28 +81,22 @@ Write(DateTime.Now);
|
||||||
__tagHelperExecutionContext.AddHtmlAttribute("unboundproperty", __tagHelperStringValueBuffer.ToString());
|
__tagHelperExecutionContext.AddHtmlAttribute("unboundproperty", __tagHelperStringValueBuffer.ToString());
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
Instrumentation.BeginContext(184, 52, true);
|
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
WriteLiteralTo(__razor_helper_writer, "\r\n In None ContentBehavior.\r\n ");
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
Instrumentation.EndContext();
|
{
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("nestedtaghelper");
|
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateContent());
|
||||||
__NestedTagHelper = CreateTagHelper<NestedTagHelper>();
|
}
|
||||||
__tagHelperExecutionContext.Add(__NestedTagHelper);
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
StartWritingScope();
|
{
|
||||||
WriteLiteral("Some buffered values with a value of ");
|
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
#line 8 "TagHelpersInHelper.cshtml"
|
}
|
||||||
Write(val);
|
else
|
||||||
|
{
|
||||||
#line default
|
StartWritingScope(__razor_helper_writer);
|
||||||
#line hidden
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
__tagHelperStringValueBuffer = EndWritingScope();
|
EndWritingScope();
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext, __tagHelperStringValueBuffer).Result;
|
}
|
||||||
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateContent());
|
|
||||||
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateEndTag());
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
|
||||||
Instrumentation.BeginContext(312, 10, true);
|
|
||||||
WriteLiteralTo(__razor_helper_writer, "\r\n ");
|
|
||||||
Instrumentation.EndContext();
|
|
||||||
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateEndTag());
|
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
Instrumentation.BeginContext(336, 14, true);
|
Instrumentation.BeginContext(336, 14, true);
|
||||||
|
|
@ -89,7 +116,9 @@ Write(DateTime.Now);
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#pragma warning disable 0414
|
||||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||||
|
#pragma warning restore 0414
|
||||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||||
|
|
@ -106,23 +135,33 @@ Write(DateTime.Now);
|
||||||
Instrumentation.BeginContext(27, 2, true);
|
Instrumentation.BeginContext(27, 2, true);
|
||||||
WriteLiteral("\r\n");
|
WriteLiteral("\r\n");
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("mytaghelper");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("mytaghelper", "test", async() => {
|
||||||
__MyTagHelper = CreateTagHelper<MyTagHelper>();
|
|
||||||
__tagHelperExecutionContext.Add(__MyTagHelper);
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
|
||||||
Instrumentation.BeginContext(367, 9, false);
|
|
||||||
#line 12 "TagHelpersInHelper.cshtml"
|
#line 12 "TagHelpersInHelper.cshtml"
|
||||||
Write(MyHelper(item => new Template((__razor_template_writer) => {
|
Write(MyHelper(item => new Template((__razor_template_writer) => {
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("nestedtaghelper");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("nestedtaghelper", "test", async() => {
|
||||||
|
WriteLiteral("Custom Value");
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
__NestedTagHelper = CreateTagHelper<NestedTagHelper>();
|
__NestedTagHelper = CreateTagHelper<NestedTagHelper>();
|
||||||
__tagHelperExecutionContext.Add(__NestedTagHelper);
|
__tagHelperExecutionContext.Add(__NestedTagHelper);
|
||||||
StartWritingScope();
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
WriteLiteral("Custom Value");
|
|
||||||
__tagHelperStringValueBuffer = EndWritingScope();
|
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext, __tagHelperStringValueBuffer).Result;
|
|
||||||
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateContent());
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartWritingScope(__razor_template_writer);
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
EndWritingScope();
|
||||||
|
}
|
||||||
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateEndTag());
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
}
|
}
|
||||||
|
|
@ -131,7 +170,26 @@ Write(MyHelper(item => new Template((__razor_template_writer) => {
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
Instrumentation.EndContext();
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__MyTagHelper = CreateTagHelper<MyTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__MyTagHelper);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
Instrumentation.BeginContext(439, 2, true);
|
Instrumentation.BeginContext(439, 2, true);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@ namespace TestOutput
|
||||||
public class TagHelpersInSection
|
public class TagHelpersInSection
|
||||||
{
|
{
|
||||||
#line hidden
|
#line hidden
|
||||||
|
#pragma warning disable 0414
|
||||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||||
|
#pragma warning restore 0414
|
||||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||||
|
|
@ -38,7 +40,40 @@ namespace TestOutput
|
||||||
Instrumentation.BeginContext(87, 21, true);
|
Instrumentation.BeginContext(87, 21, true);
|
||||||
WriteLiteralTo(__razor_template_writer, "\r\n <div>\r\n ");
|
WriteLiteralTo(__razor_template_writer, "\r\n <div>\r\n ");
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("mytaghelper");
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("mytaghelper", "test", async() => {
|
||||||
|
WriteLiteral("\r\n In None ContentBehavior.\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("nestedtaghelper", "test", async() => {
|
||||||
|
WriteLiteral("Some buffered values with ");
|
||||||
|
#line 11 "TagHelpersInSection.cshtml"
|
||||||
|
Write(code);
|
||||||
|
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
|
__NestedTagHelper = CreateTagHelper<NestedTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__NestedTagHelper);
|
||||||
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
|
||||||
|
}
|
||||||
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
|
{
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
|
}
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
|
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
}
|
||||||
|
, StartWritingScope, EndWritingScope);
|
||||||
__MyTagHelper = CreateTagHelper<MyTagHelper>();
|
__MyTagHelper = CreateTagHelper<MyTagHelper>();
|
||||||
__tagHelperExecutionContext.Add(__MyTagHelper);
|
__tagHelperExecutionContext.Add(__MyTagHelper);
|
||||||
StartWritingScope();
|
StartWritingScope();
|
||||||
|
|
@ -62,28 +97,22 @@ Write(DateTime.Now);
|
||||||
__tagHelperExecutionContext.AddHtmlAttribute("unboundproperty", __tagHelperStringValueBuffer.ToString());
|
__tagHelperExecutionContext.AddHtmlAttribute("unboundproperty", __tagHelperStringValueBuffer.ToString());
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||||
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
||||||
Instrumentation.BeginContext(211, 52, true);
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GeneratePreContent());
|
||||||
WriteLiteralTo(__razor_template_writer, "\r\n In None ContentBehavior.\r\n ");
|
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||||
Instrumentation.EndContext();
|
{
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("nestedtaghelper");
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateContent());
|
||||||
__NestedTagHelper = CreateTagHelper<NestedTagHelper>();
|
}
|
||||||
__tagHelperExecutionContext.Add(__NestedTagHelper);
|
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||||
StartWritingScope();
|
{
|
||||||
WriteLiteral("Some buffered values with ");
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||||
#line 11 "TagHelpersInSection.cshtml"
|
}
|
||||||
Write(code);
|
else
|
||||||
|
{
|
||||||
#line default
|
StartWritingScope(__razor_template_writer);
|
||||||
#line hidden
|
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||||
__tagHelperStringValueBuffer = EndWritingScope();
|
EndWritingScope();
|
||||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext, __tagHelperStringValueBuffer).Result;
|
}
|
||||||
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GeneratePostContent());
|
||||||
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateContent());
|
|
||||||
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateEndTag());
|
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
|
||||||
Instrumentation.BeginContext(329, 10, true);
|
|
||||||
WriteLiteralTo(__razor_template_writer, "\r\n ");
|
|
||||||
Instrumentation.EndContext();
|
|
||||||
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateEndTag());
|
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateEndTag());
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
Instrumentation.BeginContext(353, 14, true);
|
Instrumentation.BeginContext(353, 14, true);
|
||||||
|
|
|
||||||
|
|
@ -18,5 +18,18 @@
|
||||||
<input type='@if(true) { <text>checkbox</text> } else { <text>anything</text> }' />
|
<input type='@if(true) { <text>checkbox</text> } else { <text>anything</text> }' />
|
||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
|
<p age="@DateTimeOffset.Now.Year - 1970">
|
||||||
|
@{ var @object = false;}
|
||||||
|
<input checked="@(@object)" />
|
||||||
|
</p>
|
||||||
|
<p age="-1970 + @DateTimeOffset.Now.Year">
|
||||||
|
<input checked="@(DateTimeOffset.Now.Year > 2014)" />
|
||||||
|
</p>
|
||||||
|
<p age="DateTimeOffset.Now.Year - 1970">
|
||||||
|
<input checked="DateTimeOffset.Now.Year > 2014" />
|
||||||
|
</p>
|
||||||
|
<p age="@("My age is this long.".Length)">
|
||||||
|
<input checked=" @( DateTimeOffset.Now.Year ) > 2014 " />
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
@addtaghelper "something"
|
|
||||||
|
|
||||||
<modify>
|
|
||||||
<none>
|
|
||||||
<append>
|
|
||||||
<prepend>
|
|
||||||
<replace>This should not be in the output</replace>
|
|
||||||
</prepend>
|
|
||||||
</append>
|
|
||||||
</none>
|
|
||||||
</modify>
|
|
||||||
|
|
@ -5,17 +5,21 @@
|
||||||
"Moq": "4.2.1312.1622",
|
"Moq": "4.2.1312.1622",
|
||||||
"Microsoft.AspNet.Razor": "4.0.0-*",
|
"Microsoft.AspNet.Razor": "4.0.0-*",
|
||||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||||
"Xunit.KRunner": "1.0.0-*"
|
"xunit.runner.kre": "1.0.0-*"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
"test": "Xunit.KRunner"
|
"test": "xunit.runner.kre"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"aspnet50": { },
|
"aspnet50": { },
|
||||||
"aspnetcore50": {
|
"aspnetcore50": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"System.Diagnostics.TraceSource": "4.0.0-beta-*"
|
"System.Diagnostics.TraceSource": "4.0.0-beta-*",
|
||||||
|
"System.Reflection.TypeExtensions": "4.0.0-beta-*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"compilationOptions": {
|
||||||
|
"define": [ "__RemoveThisBitTo__GENERATE_BASELINES" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue